diff options
-rw-r--r-- | xbmc/addons/binary-addons/AddonDll.cpp | 2 | ||||
-rw-r--r-- | xbmc/addons/interfaces/AddonBase.cpp | 2 | ||||
-rw-r--r-- | xbmc/addons/interfaces/Filesystem.cpp | 31 | ||||
-rw-r--r-- | xbmc/addons/interfaces/Filesystem.h | 2 | ||||
-rw-r--r-- | xbmc/addons/interfaces/gui/Window.cpp | 14 | ||||
-rw-r--r-- | xbmc/addons/kodi-addon-dev-kit/include/kodi/AddonBase.h | 126 | ||||
-rw-r--r-- | xbmc/addons/kodi-addon-dev-kit/include/kodi/Filesystem.h | 65 | ||||
-rw-r--r-- | xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/filesystem.h | 4 | ||||
-rw-r--r-- | xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h | 4 |
9 files changed, 183 insertions, 67 deletions
diff --git a/xbmc/addons/binary-addons/AddonDll.cpp b/xbmc/addons/binary-addons/AddonDll.cpp index 45ad42e758..97c9130f18 100644 --- a/xbmc/addons/binary-addons/AddonDll.cpp +++ b/xbmc/addons/binary-addons/AddonDll.cpp @@ -305,7 +305,7 @@ ADDON_STATUS CAddonDll::CreateInstance(ADDON_TYPE instanceType, kodi::addon::GetTypeVersion(instanceType), &addonInstance, parentInstance); - if (status == ADDON_STATUS_OK) + if (addonInstance) { m_usedInstances[instanceClass] = std::make_pair(instanceType, addonInstance); } diff --git a/xbmc/addons/interfaces/AddonBase.cpp b/xbmc/addons/interfaces/AddonBase.cpp index 1d45c57f69..7ceba7e279 100644 --- a/xbmc/addons/interfaces/AddonBase.cpp +++ b/xbmc/addons/interfaces/AddonBase.cpp @@ -195,7 +195,7 @@ void Interface_Base::addon_log_msg(void* kodiBase, const int addonLogLevel, cons break; } - CLog::Log(logLevel, "AddOnLog: {}: {}", addon->Name(), strMessage); + CLog::Log(logLevel, "AddOnLog: {}: {}", addon->ID(), strMessage); } bool Interface_Base::get_setting_bool(void* kodiBase, const char* id, bool* value) diff --git a/xbmc/addons/interfaces/Filesystem.cpp b/xbmc/addons/interfaces/Filesystem.cpp index d85561c56b..73bd368c3a 100644 --- a/xbmc/addons/interfaces/Filesystem.cpp +++ b/xbmc/addons/interfaces/Filesystem.cpp @@ -15,6 +15,7 @@ #include "filesystem/Directory.h" #include "filesystem/File.h" #include "filesystem/SpecialProtocol.h" +#include "platform/Filesystem.h" #include "utils/Crc32.h" #include "utils/HttpHeader.h" #include "utils/StringUtils.h" @@ -59,6 +60,7 @@ void Interface_Filesystem::Init(AddonGlobalInterface* addonInterface) addonInterface->toKodi->kodi_filesystem->make_legal_filename = make_legal_filename; addonInterface->toKodi->kodi_filesystem->make_legal_path = make_legal_path; addonInterface->toKodi->kodi_filesystem->translate_special_protocol = translate_special_protocol; + addonInterface->toKodi->kodi_filesystem->get_disk_space = get_disk_space; addonInterface->toKodi->kodi_filesystem->is_internet_stream = is_internet_stream; addonInterface->toKodi->kodi_filesystem->is_on_lan = is_on_lan; addonInterface->toKodi->kodi_filesystem->is_remote = is_remote; @@ -426,6 +428,35 @@ char* Interface_Filesystem::translate_special_protocol(void* kodiBase, const cha return strdup(CSpecialProtocol::TranslatePath(strSource).c_str()); } +bool Interface_Filesystem::get_disk_space( + void* kodiBase, const char* path, uint64_t* capacity, uint64_t* free, uint64_t* available) +{ + using namespace KODI::PLATFORM::FILESYSTEM; + + CAddonDll* addon = static_cast<CAddonDll*>(kodiBase); + if (addon == nullptr || path == nullptr || capacity == nullptr || free == nullptr || + available == nullptr) + { + CLog::Log( + LOGERROR, + "Interface_Filesystem::{} - invalid data (addon='{}', path='{}, capacity='{}, free='{}, " + "available='{})", + __FUNCTION__, kodiBase, static_cast<const void*>(path), static_cast<void*>(capacity), + static_cast<void*>(free), static_cast<void*>(available)); + return false; + } + + std::error_code ec; + auto freeSpace = space(CSpecialProtocol::TranslatePath(path), ec); + if (ec.value() != 0) + return false; + + *capacity = freeSpace.capacity; + *free = freeSpace.free; + *available = freeSpace.available; + return true; +} + bool Interface_Filesystem::is_internet_stream(void* kodiBase, const char* path, bool strictCheck) { CAddonDll* addon = static_cast<CAddonDll*>(kodiBase); diff --git a/xbmc/addons/interfaces/Filesystem.h b/xbmc/addons/interfaces/Filesystem.h index cf26026e6c..86f7ad9f37 100644 --- a/xbmc/addons/interfaces/Filesystem.h +++ b/xbmc/addons/interfaces/Filesystem.h @@ -58,6 +58,8 @@ struct Interface_Filesystem static char* make_legal_filename(void* kodiBase, const char* filename); static char* make_legal_path(void* kodiBase, const char* path); static char* translate_special_protocol(void* kodiBase, const char* strSource); + static bool get_disk_space( + void* kodiBase, const char* path, uint64_t* capacity, uint64_t* free, uint64_t* available); static bool is_internet_stream(void* kodiBase, const char* path, bool strictCheck); static bool is_on_lan(void* kodiBase, const char* path); static bool is_remote(void* kodiBase, const char* path); diff --git a/xbmc/addons/interfaces/gui/Window.cpp b/xbmc/addons/interfaces/gui/Window.cpp index 3a2aced51f..b866647192 100644 --- a/xbmc/addons/interfaces/gui/Window.cpp +++ b/xbmc/addons/interfaces/gui/Window.cpp @@ -145,19 +145,21 @@ void* Interface_GUIWindow::create(void* kodiBase, const char* xml_filename, if (XFILE::CFile::Exists(basePath)) { addonInfo->SetPath(basePath); - ADDON::CSkinInfo skinInfo(addonInfo, res); - skinInfo.Start(); - strSkinPath = skinInfo.GetSkinPath(xml_filename, &res); + const std::shared_ptr<ADDON::CSkinInfo> skinInfo = + std::make_shared<ADDON::CSkinInfo>(addonInfo, res); + skinInfo->Start(); + strSkinPath = skinInfo->GetSkinPath(xml_filename, &res); } if (!XFILE::CFile::Exists(strSkinPath)) { // Finally fallback to the DefaultSkin as it didn't exist in either the Kodi Skin folder or the fallback skin folder addonInfo->SetPath(URIUtils::AddFileToFolder(fallbackPath, default_skin)); - ADDON::CSkinInfo skinInfo(addonInfo, res); + const std::shared_ptr<ADDON::CSkinInfo> skinInfo = + std::make_shared<ADDON::CSkinInfo>(addonInfo, res); - skinInfo.Start(); - strSkinPath = skinInfo.GetSkinPath(xml_filename, &res); + skinInfo->Start(); + strSkinPath = skinInfo->GetSkinPath(xml_filename, &res); if (!XFILE::CFile::Exists(strSkinPath)) { CLog::Log(LOGERROR, "Interface_GUIWindow::%s: %s/%s - XML File '%s' for Window is missing, contact Developer '%s' of this addon", 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 7e4263a88e..f8f6d60b1a 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/AddonBase.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/AddonBase.h @@ -418,23 +418,7 @@ public: const std::string& version, KODI_HANDLE& addonInstance) { - /* The handling below is intended for the case of the add-on only one - * instance and this is integrated in the add-on base class. - */ - - /* Check about single instance usage: - * 1. The kodi side instance pointer must be equal to first one - * 2. The addon side instance pointer must be set - * 3. And the requested type must be equal with used add-on class - */ - if (m_interface->firstKodiInstance == instance && m_interface->globalSingleInstance && - static_cast<IAddonInstance*>(m_interface->globalSingleInstance)->m_type == instanceType) - { - addonInstance = m_interface->globalSingleInstance; - return ADDON_STATUS_OK; - } - - return ADDON_STATUS_UNKNOWN; + return ADDON_STATUS_NOT_IMPLEMENTED; } //-------------------------------------------------------------------------- @@ -495,18 +479,63 @@ private: CAddonBase* base = static_cast<CAddonBase*>(m_interface->addonBase); ADDON_STATUS status = ADDON_STATUS_NOT_IMPLEMENTED; - if (parent != nullptr) - status = static_cast<IAddonInstance*>(parent)->CreateInstance( - instanceType, instanceID, instance, version, *addonInstance); - if (status == ADDON_STATUS_NOT_IMPLEMENTED) - status = base->CreateInstance(instanceType, instanceID, instance, version, *addonInstance); + + /* Check about single instance usage: + * 1. The kodi side instance pointer must be equal to first one + * 2. The addon side instance pointer must be set + * 3. And the requested type must be equal with used add-on class + */ + if (m_interface->firstKodiInstance == instance && m_interface->globalSingleInstance && + static_cast<IAddonInstance*>(m_interface->globalSingleInstance)->m_type == instanceType) + { + /* The handling here is intended for the case of the add-on only one + * instance and this is integrated in the add-on base class. + */ + *addonInstance = m_interface->globalSingleInstance; + status = ADDON_STATUS_OK; + } + else + { + /* Here it should use the CreateInstance instance function to allow + * creation of several on one addon. + */ + + /* Check first a parent is defined about (e.g. Codec within inputstream) */ + if (parent != nullptr) + status = static_cast<IAddonInstance*>(parent)->CreateInstance( + instanceType, instanceID, instance, version, *addonInstance); + + /* if no parent call the main instance creation function to get it */ + if (status == ADDON_STATUS_NOT_IMPLEMENTED) + { + status = base->CreateInstance(instanceType, instanceID, instance, version, *addonInstance); + } + } + if (*addonInstance == nullptr) - throw std::logic_error( - "kodi::addon::CAddonBase CreateInstance returns a empty instance pointer!"); + { + if (status == ADDON_STATUS_OK) + { + m_interface->toKodi->addon_log_msg(m_interface->toKodi->kodiBase, ADDON_LOG_FATAL, + "kodi::addon::CAddonBase CreateInstance returned an " + "empty instance pointer, but reported OK!"); + return ADDON_STATUS_PERMANENT_FAILURE; + } + else + { + return status; + } + } if (static_cast<IAddonInstance*>(*addonInstance)->m_type != instanceType) - throw std::logic_error("kodi::addon::CAddonBase CreateInstance with difference on given " - "and returned instance type!"); + { + m_interface->toKodi->addon_log_msg( + m_interface->toKodi->kodiBase, ADDON_LOG_FATAL, + "kodi::addon::CAddonBase CreateInstance difference between given and returned"); + delete static_cast<IAddonInstance*>(*addonInstance); + *addonInstance = nullptr; + return ADDON_STATUS_PERMANENT_FAILURE; + } // Store the used ID inside instance, to have on destroy calls by addon to identify static_cast<IAddonInstance*>(*addonInstance)->m_id = instanceID; @@ -520,14 +549,8 @@ private: if (m_interface->globalSingleInstance == nullptr && instance != base) { - if (static_cast<IAddonInstance*>(instance)->m_type == instanceType) - { - base->DestroyInstance(instanceType, static_cast<IAddonInstance*>(instance)->m_id, instance); - delete static_cast<IAddonInstance*>(instance); - } - else - throw std::logic_error("kodi::addon::CAddonBase DestroyInstance called with difference on " - "given and present instance type!"); + base->DestroyInstance(instanceType, static_cast<IAddonInstance*>(instance)->m_id, instance); + delete static_cast<IAddonInstance*>(instance); } } }; @@ -711,6 +734,7 @@ inline bool CheckSettingString(const std::string& settingName, std::string& sett /// The setting name relate to names used in his <b>settings.xml</b> file. /// /// @param[in] settingName The name of asked setting +/// @param[in] defaultValue [opt] Default value if not found /// @return The value of setting, empty if not found; /// /// @@ -723,9 +747,10 @@ inline bool CheckSettingString(const std::string& settingName, std::string& sett /// std::string value = kodi::GetSettingString("my_string_value"); /// ~~~~~~~~~~~~~ /// -inline std::string GetSettingString(const std::string& settingName) +inline std::string GetSettingString(const std::string& settingName, + const std::string& defaultValue = "") { - std::string settingValue; + std::string settingValue = defaultValue; CheckSettingString(settingName, settingValue); return settingValue; } @@ -797,7 +822,8 @@ inline bool CheckSettingInt(const std::string& settingName, int& settingValue) /// The setting name relate to names used in his <b>settings.xml</b> file. /// /// @param[in] settingName The name of asked setting -/// @return The value of setting, <b>`0`</b> if not found; +/// @param[in] defaultValue [opt] Default value if not found +/// @return The value of setting, <b>`0`</b> or defaultValue if not found /// /// /// ---------------------------------------------------------------------------- @@ -809,9 +835,9 @@ inline bool CheckSettingInt(const std::string& settingName, int& settingValue) /// int value = kodi::GetSettingInt("my_integer_value"); /// ~~~~~~~~~~~~~ /// -inline int GetSettingInt(const std::string& settingName) +inline int GetSettingInt(const std::string& settingName, int defaultValue = 0) { - int settingValue = 0; + int settingValue = defaultValue; CheckSettingInt(settingName, settingValue); return settingValue; } @@ -883,7 +909,8 @@ inline bool CheckSettingBoolean(const std::string& settingName, bool& settingVal /// The setting name relate to names used in his <b>settings.xml</b> file. /// /// @param[in] settingName The name of asked setting -/// @return The value of setting, <b>`false`</b> if not found; +/// @param[in] defaultValue [opt] Default value if not found +/// @return The value of setting, <b>`false`</b> or defaultValue if not found /// /// /// ---------------------------------------------------------------------------- @@ -895,9 +922,9 @@ inline bool CheckSettingBoolean(const std::string& settingName, bool& settingVal /// bool value = kodi::GetSettingBoolean("my_boolean_value"); /// ~~~~~~~~~~~~~ /// -inline bool GetSettingBoolean(const std::string& settingName) +inline bool GetSettingBoolean(const std::string& settingName, bool defaultValue = false) { - bool settingValue = false; + bool settingValue = defaultValue; CheckSettingBoolean(settingName, settingValue); return settingValue; } @@ -969,7 +996,8 @@ inline bool CheckSettingFloat(const std::string& settingName, float& settingValu /// The setting name relate to names used in his <b>settings.xml</b> file. /// /// @param[in] settingName The name of asked setting -/// @return The value of setting, <b>`0.0`</b> if not found; +/// @param[in] defaultValue [opt] Default value if not found +/// @return The value of setting, <b>`0.0`</b> or defaultValue if not found /// /// /// ---------------------------------------------------------------------------- @@ -981,9 +1009,9 @@ inline bool CheckSettingFloat(const std::string& settingName, float& settingValu /// float value = kodi::GetSettingFloat("my_float_value"); /// ~~~~~~~~~~~~~ /// -inline float GetSettingFloat(const std::string& settingName) +inline float GetSettingFloat(const std::string& settingName, float defaultValue = 0.0f) { - float settingValue = 0.0f; + float settingValue = defaultValue; CheckSettingFloat(settingName, settingValue); return settingValue; } @@ -1068,7 +1096,8 @@ inline bool CheckSettingEnum(const std::string& settingName, enumType& settingVa /// The setting name relate to names used in his <b>settings.xml</b> file. /// /// @param[in] settingName The name of asked setting -/// @return The value of setting, forced to <b>`0`</b> if not found; +/// @param[in] defaultValue [opt] Default value if not found +/// @return The value of setting, forced to <b>`0`</b> or defaultValue if not found /// /// @remark The enums are used as integer inside settings.xml. /// @@ -1090,9 +1119,10 @@ inline bool CheckSettingEnum(const std::string& settingName, enumType& settingVa /// ~~~~~~~~~~~~~ /// template<typename enumType> -inline enumType GetSettingEnum(const std::string& settingName) +inline enumType GetSettingEnum(const std::string& settingName, + enumType defaultValue = static_cast<enumType>(0)) { - enumType settingValue = static_cast<enumType>(0); + enumType settingValue = defaultValue; CheckSettingEnum(settingName, settingValue); return settingValue; } diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/Filesystem.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/Filesystem.h index 11a8e7e7a0..15d984e74f 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/Filesystem.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/Filesystem.h @@ -1256,6 +1256,54 @@ inline std::string TranslateSpecialProtocol(const std::string& source) //============================================================================== /// @ingroup cpp_kodi_vfs_General +/// @brief Retrieves information about the amount of space that is available on +/// a disk volume. +/// +/// Path can be also with Kodi's special protocol. +/// +/// @param[in] path Path for where to check +/// @param[out] capacity The total number of bytes in the file system +/// @param[out] free The total number of free bytes in the file system +/// @param[out] available The total number of free bytes available to a +/// non-privileged process +/// @return true if successfully done and set +/// +/// @warning This only works with paths belonging to OS. If <b>"special://"</b> +/// is used, it must point to a place on your own OS. +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include <climits> // for ULLONG_MAX +/// #include <kodi/Filesystem.h> +/// ... +/// std::string path = "special://temp"; +/// uint64_t capacity = ULLONG_MAX; +/// uint64_t free = ULLONG_MAX; +/// uint64_t available = ULLONG_MAX; +/// kodi::vfs::GetDiskSpace(path, capacity, free, available); +/// fprintf(stderr, "Path '%s' sizes:\n", path.c_str()); +/// fprintf(stderr, " - capacity: %lu MByte\n", capacity / 1024 / 1024); +/// fprintf(stderr, " - free: %lu MByte\n", free / 1024 / 1024); +/// fprintf(stderr, " - available: %lu MByte\n", available / 1024 / 1024); +/// ~~~~~~~~~~~~~ +/// +inline bool GetDiskSpace(const std::string& path, + uint64_t& capacity, + uint64_t& free, + uint64_t& available) +{ + using namespace kodi::addon; + + return CAddonBase::m_interface->toKodi->kodi_filesystem->get_disk_space( + CAddonBase::m_interface->toKodi->kodiBase, path.c_str(), &capacity, &free, &available); +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_General /// @brief Return the file name from given complate path string. /// /// @param[in] path The complete path include file and directory @@ -1315,7 +1363,6 @@ inline std::string GetDirectoryName(const std::string& path) } //------------------------------------------------------------------------------ - //============================================================================== /// @ingroup cpp_kodi_vfs_General /// @brief Remove the slash on given path name. @@ -1810,7 +1857,7 @@ public: /// /// @return True on open or false on closed or failure /// - bool IsOpen() { return m_file != nullptr; } + bool IsOpen() const { return m_file != nullptr; } //-------------------------------------------------------------------------- //========================================================================== @@ -2039,7 +2086,7 @@ public: /// /// @return The requested offset. On error, the value -1 is returned. /// - int64_t GetPosition() + int64_t GetPosition() const { using namespace kodi::addon; @@ -2056,7 +2103,7 @@ public: /// /// @return The requested size. On error, the value -1 is returned. /// - int64_t GetLength() + int64_t GetLength() const { using namespace kodi::addon; @@ -2073,7 +2120,7 @@ public: /// /// @return If you've reached the end of the file, AtEnd() returns true. /// - bool AtEnd() + bool AtEnd() const { using namespace kodi::addon; @@ -2093,7 +2140,7 @@ public: /// /// @return The requested size. On error, the value -1 is returned. /// - int GetChunkSize() + int GetChunkSize() const { using namespace kodi::addon; @@ -2110,7 +2157,7 @@ public: /// /// @return true if seek possible, false if not /// - bool IoControlGetSeekPossible() + bool IoControlGetSeekPossible() const { using namespace kodi::addon; @@ -2131,7 +2178,7 @@ public: /// /// @copydetails cpp_kodi_vfs_Defs_CacheStatus_Help /// - bool IoControlGetCacheStatus(CacheStatus& status) + bool IoControlGetCacheStatus(CacheStatus& status) const { using namespace kodi::addon; @@ -2248,7 +2295,7 @@ public: /// /// @return The current download speed. /// - double GetFileDownloadSpeed() + double GetFileDownloadSpeed() const { using namespace kodi::addon; diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/filesystem.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/filesystem.h index 2067d22fb6..b68a24c91c 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/filesystem.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/filesystem.h @@ -8,6 +8,7 @@ #pragma once +#include <stdbool.h> #include <stdint.h> #include <time.h> @@ -286,6 +287,9 @@ extern "C" bool (*curl_add_option)( void* kodiBase, void* file, int type, const char* name, const char* value); bool (*curl_open)(void* kodiBase, void* file, unsigned int flags); + + bool (*get_disk_space)( + void* kodiBase, const char* path, uint64_t* capacity, uint64_t* free, uint64_t* available); } AddonToKodiFuncTable_kodi_filesystem; //}}} diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h index 8a33a1403e..fa79f5a287 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h @@ -34,7 +34,7 @@ // because cmake uses this area in this form to perform its addon dependency // check. // clang-format off -#define ADDON_GLOBAL_VERSION_MAIN "1.2.1" +#define ADDON_GLOBAL_VERSION_MAIN "1.2.2" #define ADDON_GLOBAL_VERSION_MAIN_MIN "1.2.0" #define ADDON_GLOBAL_VERSION_MAIN_XML_ID "kodi.binary.global.main" #define ADDON_GLOBAL_VERSION_MAIN_DEPENDS "AddonBase.h" \ @@ -60,7 +60,7 @@ #define ADDON_GLOBAL_VERSION_AUDIOENGINE_DEPENDS "AudioEngine.h" \ "c-api/audio_engine.h" -#define ADDON_GLOBAL_VERSION_FILESYSTEM "1.1.2" +#define ADDON_GLOBAL_VERSION_FILESYSTEM "1.1.3" #define ADDON_GLOBAL_VERSION_FILESYSTEM_MIN "1.1.0" #define ADDON_GLOBAL_VERSION_FILESYSTEM_XML_ID "kodi.binary.global.filesystem" #define ADDON_GLOBAL_VERSION_FILESYSTEM_DEPENDS "Filesystem.h" \ |