From d3a17278e7a88b7c6e9e2ed0f10821291d852480 Mon Sep 17 00:00:00 2001 From: Alwin Esch Date: Mon, 18 May 2020 16:59:08 +0200 Subject: [PATCH] Merge pull request #17813 from AlwinEsch/rework-filesystem [addons][filesystem][base] add some new functions, improvement, cleanups and doc rework --- xbmc/addons/binary-addons/AddonDll.cpp | 17 +- xbmc/addons/binary-addons/DllAddon.h | 10 +- xbmc/addons/interfaces/AddonBase.cpp | 35 +- xbmc/addons/interfaces/AddonBase.h | 1 + xbmc/addons/interfaces/Filesystem.cpp | 587 ++- xbmc/addons/interfaces/Filesystem.h | 54 +- xbmc/addons/interfaces/General.cpp | 30 +- xbmc/addons/interfaces/General.h | 1 + .../include/kodi/AddonBase.h | 616 ++- .../include/kodi/Filesystem.h | 3499 ++++++++++------- .../kodi-addon-dev-kit/include/kodi/General.h | 43 + .../kodi-addon-dev-kit/include/kodi/Network.h | 1 + .../kodi/addon-instance/AudioDecoder.h | 9 +- .../kodi/addon-instance/AudioEncoder.h | 10 +- .../include/kodi/addon-instance/Game.h | 13 +- .../kodi/addon-instance/ImageDecoder.h | 10 +- .../include/kodi/addon-instance/Inputstream.h | 8 +- .../include/kodi/addon-instance/Peripheral.h | 8 +- .../include/kodi/addon-instance/Screensaver.h | 13 +- .../include/kodi/addon-instance/VFS.h | 44 +- .../include/kodi/addon-instance/VideoCodec.h | 6 +- .../kodi/addon-instance/Visualization.h | 12 +- .../include/kodi/c-api/CMakeLists.txt | 4 +- .../include/kodi/c-api/addon_base.h | 249 ++ .../include/kodi/c-api/filesystem.h | 295 ++ .../include/kodi/c-api/network.h | 14 +- .../include/kodi/gui/renderHelper.h | 7 +- .../include/kodi/versions.h | 67 +- .../include/kodi/xbmc_addon_dll.h | 4 +- 29 files changed, 3667 insertions(+), 2000 deletions(-) create mode 100644 xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/addon_base.h create mode 100644 xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/filesystem.h diff --git a/xbmc/addons/binary-addons/AddonDll.cpp b/xbmc/addons/binary-addons/AddonDll.cpp index 4814f54858e98..45ad42e758659 100644 --- a/xbmc/addons/binary-addons/AddonDll.cpp +++ b/xbmc/addons/binary-addons/AddonDll.cpp @@ -185,9 +185,8 @@ 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->CreateEx_available() - ? m_pDll->CreateEx(m_pHelpers->GetCallbacks(), kodi::addon::GetTypeVersion(ADDON_GLOBAL_MAIN), info) - : m_pDll->Create(m_pHelpers->GetCallbacks(), info); + ADDON_STATUS status = m_pDll->Create(m_pHelpers->GetCallbacks(), + kodi::addon::GetTypeVersion(ADDON_GLOBAL_MAIN), info); if (status == ADDON_STATUS_OK) { @@ -236,9 +235,8 @@ 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->CreateEx_available() - ? m_pDll->CreateEx(&m_interface, kodi::addon::GetTypeVersion(ADDON_GLOBAL_MAIN), nullptr) - : m_pDll->Create(&m_interface, nullptr); + ADDON_STATUS status = + m_pDll->Create(&m_interface, kodi::addon::GetTypeVersion(ADDON_GLOBAL_MAIN), nullptr); if (status == ADDON_STATUS_OK) { @@ -303,10 +301,9 @@ ADDON_STATUS CAddonDll::CreateInstance(ADDON_TYPE instanceType, return ADDON_STATUS_PERMANENT_FAILURE; KODI_HANDLE addonInstance = nullptr; - 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)); + status = m_interface.toAddon->create_instance(instanceType, instanceID.c_str(), instance, + kodi::addon::GetTypeVersion(instanceType), + &addonInstance, parentInstance); if (status == ADDON_STATUS_OK) { diff --git a/xbmc/addons/binary-addons/DllAddon.h b/xbmc/addons/binary-addons/DllAddon.h index 806c0f49a8768..6692e1cfd0d91 100644 --- a/xbmc/addons/binary-addons/DllAddon.h +++ b/xbmc/addons/binary-addons/DllAddon.h @@ -16,8 +16,7 @@ class DllAddonInterface public: 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 ADDON_STATUS Create(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; @@ -29,9 +28,7 @@ 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_METHOD3(ADDON_STATUS, Create, (void* p1, const char* p2, void* p3)) DEFINE_METHOD0(void, Destroy) DEFINE_METHOD0(ADDON_STATUS, GetStatus) DEFINE_METHOD2(ADDON_STATUS, SetSetting, (const char *p1, const void *p2)) @@ -40,9 +37,8 @@ class DllAddon : public DllDynamic, public DllAddonInterface 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_OPTIONAL(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) diff --git a/xbmc/addons/interfaces/AddonBase.cpp b/xbmc/addons/interfaces/AddonBase.cpp index b3616b567355f..1d45c57f69733 100644 --- a/xbmc/addons/interfaces/AddonBase.cpp +++ b/xbmc/addons/interfaces/AddonBase.cpp @@ -37,6 +37,7 @@ bool Interface_Base::InitInterface(CAddonDll* addon, addonInterface.libBasePath = strdup(CSpecialProtocol::TranslatePath("special://xbmcbinaddons").c_str()); + addonInterface.kodi_base_api_version = strdup(kodi::addon::GetTypeVersion(ADDON_GLOBAL_MAIN)); addonInterface.addonBase = nullptr; addonInterface.globalSingleInstance = nullptr; addonInterface.firstKodiInstance = firstKodiInstance; @@ -45,6 +46,7 @@ bool Interface_Base::InitInterface(CAddonDll* addon, // compatible with other versions addonInterface.toKodi = new AddonToKodiFuncTable_Addon(); addonInterface.toKodi->kodiBase = addon; + addonInterface.toKodi->get_type_version = get_type_version; addonInterface.toKodi->get_addon_path = get_addon_path; addonInterface.toKodi->get_base_user_path = get_base_user_path; addonInterface.toKodi->addon_log_msg = addon_log_msg; @@ -58,6 +60,7 @@ bool Interface_Base::InitInterface(CAddonDll* addon, addonInterface.toKodi->set_setting_string = set_setting_string; addonInterface.toKodi->free_string = free_string; addonInterface.toKodi->free_string_array = free_string_array; + addonInterface.toKodi->get_interface = get_interface; // Related parts becomes set from addon headers, make here to nullptr to allow // checks for right set of them @@ -70,8 +73,6 @@ bool Interface_Base::InitInterface(CAddonDll* addon, Interface_Network::Init(&addonInterface); Interface_GUIGeneral::Init(&addonInterface); - addonInterface.toKodi->get_interface = get_interface; - return true; } @@ -85,6 +86,8 @@ void Interface_Base::DeInitInterface(AddonGlobalInterface& addonInterface) if (addonInterface.libBasePath) free(const_cast(addonInterface.libBasePath)); + if (addonInterface.kodi_base_api_version) + free(const_cast(addonInterface.kodi_base_api_version)); delete addonInterface.toKodi; delete addonInterface.toAddon; @@ -131,6 +134,11 @@ bool Interface_Base::UpdateSettingInActiveDialog(CAddonDll* addon, */ //@{ +char* Interface_Base::get_type_version(void* kodiBase, int type) +{ + return strdup(kodi::addon::GetTypeVersion(type)); +} + char* Interface_Base::get_addon_path(void* kodiBase) { CAddonDll* addon = static_cast(kodiBase); @@ -167,28 +175,23 @@ void Interface_Base::addon_log_msg(void* kodiBase, const int addonLogLevel, cons int logLevel = LOGNONE; switch (addonLogLevel) { - case ADDON_LOG_FATAL: - logLevel = LOGFATAL; - break; - case ADDON_LOG_SEVERE: - logLevel = LOGSEVERE; + case ADDON_LOG_DEBUG: + logLevel = LOGDEBUG; break; - case ADDON_LOG_ERROR: - logLevel = LOGERROR; + case ADDON_LOG_INFO: + logLevel = LOGINFO; break; case ADDON_LOG_WARNING: logLevel = LOGWARNING; break; - case ADDON_LOG_NOTICE: - logLevel = LOGNOTICE; - break; - case ADDON_LOG_INFO: - logLevel = LOGINFO; + case ADDON_LOG_ERROR: + logLevel = LOGERROR; break; - case ADDON_LOG_DEBUG: - logLevel = LOGDEBUG; + case ADDON_LOG_FATAL: + logLevel = LOGFATAL; break; default: + logLevel = LOGDEBUG; break; } diff --git a/xbmc/addons/interfaces/AddonBase.h b/xbmc/addons/interfaces/AddonBase.h index 97a9cbab5a7be..67ec035274769 100644 --- a/xbmc/addons/interfaces/AddonBase.h +++ b/xbmc/addons/interfaces/AddonBase.h @@ -51,6 +51,7 @@ struct Interface_Base * class. */ //@{ + static char* get_type_version(void* kodiBase, int type); static char* get_addon_path(void* kodiBase); static char* get_base_user_path(void* kodiBase); static void addon_log_msg(void* kodiBase, const int addonLogLevel, const char* strMessage); diff --git a/xbmc/addons/interfaces/Filesystem.cpp b/xbmc/addons/interfaces/Filesystem.cpp index a4c72f0d6d98c..d85561c56b4cb 100644 --- a/xbmc/addons/interfaces/Filesystem.cpp +++ b/xbmc/addons/interfaces/Filesystem.cpp @@ -11,15 +11,25 @@ #include "Util.h" #include "addons/binary-addons/AddonDll.h" #include "addons/kodi-addon-dev-kit/include/kodi/Filesystem.h" +#include "filesystem/CurlFile.h" #include "filesystem/Directory.h" #include "filesystem/File.h" #include "filesystem/SpecialProtocol.h" #include "utils/Crc32.h" +#include "utils/HttpHeader.h" #include "utils/StringUtils.h" +#include "utils/URIUtils.h" #include "utils/log.h" #include +#ifndef S_ISDIR +#define S_ISDIR(mode) ((((mode)) & 0170000) == (0040000)) +#endif +#ifndef S_ISLNK +#define S_ISLNK(mode) ((((mode)) & 0170000) == (0120000)) +#endif + using namespace kodi; // addon-dev-kit namespace using namespace XFILE; @@ -30,7 +40,7 @@ namespace ADDON void Interface_Filesystem::Init(AddonGlobalInterface* addonInterface) { - addonInterface->toKodi->kodi_filesystem = static_cast(malloc(sizeof(AddonToKodiFuncTable_kodi_filesystem))); + addonInterface->toKodi->kodi_filesystem = new AddonToKodiFuncTable_kodi_filesystem(); addonInterface->toKodi->kodi_filesystem->can_open_directory = can_open_directory; addonInterface->toKodi->kodi_filesystem->create_directory = create_directory; @@ -49,6 +59,18 @@ 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->is_internet_stream = is_internet_stream; + addonInterface->toKodi->kodi_filesystem->is_on_lan = is_on_lan; + addonInterface->toKodi->kodi_filesystem->is_remote = is_remote; + addonInterface->toKodi->kodi_filesystem->is_local = is_local; + addonInterface->toKodi->kodi_filesystem->is_url = is_url; + addonInterface->toKodi->kodi_filesystem->get_http_header = get_http_header; + addonInterface->toKodi->kodi_filesystem->get_mime_type = get_mime_type; + addonInterface->toKodi->kodi_filesystem->get_content_type = get_content_type; + addonInterface->toKodi->kodi_filesystem->get_cookies = get_cookies; + + addonInterface->toKodi->kodi_filesystem->http_header_create = http_header_create; + addonInterface->toKodi->kodi_filesystem->http_header_free = http_header_free; addonInterface->toKodi->kodi_filesystem->open_file = open_file; addonInterface->toKodi->kodi_filesystem->open_file_for_write = open_file_for_write; @@ -63,6 +85,12 @@ void Interface_Filesystem::Init(AddonGlobalInterface* addonInterface) addonInterface->toKodi->kodi_filesystem->get_file_download_speed = get_file_download_speed; addonInterface->toKodi->kodi_filesystem->close_file = close_file; addonInterface->toKodi->kodi_filesystem->get_file_chunk_size = get_file_chunk_size; + addonInterface->toKodi->kodi_filesystem->io_control_get_seek_possible = + io_control_get_seek_possible; + addonInterface->toKodi->kodi_filesystem->io_control_get_cache_status = + io_control_get_cache_status; + addonInterface->toKodi->kodi_filesystem->io_control_set_cache_rate = io_control_set_cache_rate; + addonInterface->toKodi->kodi_filesystem->io_control_set_retry = io_control_set_retry; addonInterface->toKodi->kodi_filesystem->get_property_values = get_property_values; addonInterface->toKodi->kodi_filesystem->curl_create = curl_create; @@ -72,14 +100,39 @@ void Interface_Filesystem::Init(AddonGlobalInterface* addonInterface) void Interface_Filesystem::DeInit(AddonGlobalInterface* addonInterface) { - if (addonInterface->toKodi && /* <-- needed as long as the old addon way is used */ - addonInterface->toKodi->kodi_filesystem) + if (addonInterface->toKodi) /* <-- Safe check, needed so long old addon way is present */ { - free(addonInterface->toKodi->kodi_filesystem); + delete addonInterface->toKodi->kodi_filesystem; addonInterface->toKodi->kodi_filesystem = nullptr; } } +unsigned int Interface_Filesystem::TranslateFileReadBitsToKodi(unsigned int addonFlags) +{ + unsigned int kodiFlags = 0; + + if (addonFlags & ADDON_READ_TRUNCATED) + kodiFlags |= READ_TRUNCATED; + if (addonFlags & ADDON_READ_CHUNKED) + kodiFlags |= READ_CHUNKED; + if (addonFlags & ADDON_READ_CACHED) + kodiFlags |= READ_CACHED; + if (addonFlags & ADDON_READ_NO_CACHE) + kodiFlags |= READ_NO_CACHE; + if (addonFlags & ADDON_READ_BITRATE) + kodiFlags |= READ_BITRATE; + if (addonFlags & ADDON_READ_MULTI_STREAM) + kodiFlags |= READ_MULTI_STREAM; + if (addonFlags & ADDON_READ_AUDIO_VIDEO) + kodiFlags |= READ_AUDIO_VIDEO; + if (addonFlags & ADDON_READ_AFTER_WRITE) + kodiFlags |= READ_AFTER_WRITE; + if (addonFlags & READ_REOPEN) + kodiFlags |= READ_REOPEN; + + return kodiFlags; +} + bool Interface_Filesystem::can_open_directory(void* kodiBase, const char* url) { CAddonDll* addon = static_cast(kodiBase); @@ -94,7 +147,7 @@ bool Interface_Filesystem::can_open_directory(void* kodiBase, const char* url) return CDirectory::GetDirectory(url, items, "", DIR_FLAG_DEFAULTS); } -bool Interface_Filesystem::create_directory(void* kodiBase, const char *path) +bool Interface_Filesystem::create_directory(void* kodiBase, const char* path) { CAddonDll* addon = static_cast(kodiBase); if (addon == nullptr || path == nullptr) @@ -107,7 +160,7 @@ bool Interface_Filesystem::create_directory(void* kodiBase, const char *path) return CDirectory::Create(path); } -bool Interface_Filesystem::directory_exists(void* kodiBase, const char *path) +bool Interface_Filesystem::directory_exists(void* kodiBase, const char* path) { CAddonDll* addon = static_cast(kodiBase); if (addon == nullptr || path == nullptr) @@ -120,7 +173,7 @@ bool Interface_Filesystem::directory_exists(void* kodiBase, const char *path) return CDirectory::Exists(path); } -bool Interface_Filesystem::remove_directory(void* kodiBase, const char *path) +bool Interface_Filesystem::remove_directory(void* kodiBase, const char* path) { CAddonDll* addon = static_cast(kodiBase); if (addon == nullptr || path == nullptr) @@ -139,8 +192,7 @@ bool Interface_Filesystem::remove_directory(void* kodiBase, const char *path) return CDirectory::Remove(path); } -static void CFileItemListToVFSDirEntries(VFSDirEntry* entries, - const CFileItemList& items) +static void CFileItemListToVFSDirEntries(VFSDirEntry* entries, const CFileItemList& items) { for (unsigned int i = 0; i < static_cast(items.Size()); ++i) { @@ -152,10 +204,15 @@ static void CFileItemListToVFSDirEntries(VFSDirEntry* entries, } } -bool Interface_Filesystem::get_directory(void* kodiBase, const char *path, const char* mask, VFSDirEntry** items, unsigned int* num_items) +bool Interface_Filesystem::get_directory(void* kodiBase, + const char* path, + const char* mask, + struct VFSDirEntry** items, + unsigned int* num_items) { CAddonDll* addon = static_cast(kodiBase); - if (addon == nullptr || path == nullptr || mask == nullptr|| items == nullptr || num_items == nullptr) + if (addon == nullptr || path == nullptr || mask == nullptr || items == nullptr || + num_items == nullptr) { CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', path='{}', mask='{}', " @@ -185,7 +242,9 @@ bool Interface_Filesystem::get_directory(void* kodiBase, const char *path, const return true; } -void Interface_Filesystem::free_directory(void* kodiBase, VFSDirEntry* items, unsigned int num_items) +void Interface_Filesystem::free_directory(void* kodiBase, + struct VFSDirEntry* items, + unsigned int num_items) { CAddonDll* addon = static_cast(kodiBase); if (addon == nullptr || items == nullptr) @@ -205,7 +264,7 @@ void Interface_Filesystem::free_directory(void* kodiBase, VFSDirEntry* items, un //------------------------------------------------------------------------------ -bool Interface_Filesystem::file_exists(void* kodiBase, const char *filename, bool useCache) +bool Interface_Filesystem::file_exists(void* kodiBase, const char* filename, bool useCache) { CAddonDll* addon = static_cast(kodiBase); if (addon == nullptr || filename == nullptr) @@ -218,7 +277,9 @@ bool Interface_Filesystem::file_exists(void* kodiBase, const char *filename, boo return CFile::Exists(filename, useCache); } -int Interface_Filesystem::stat_file(void* kodiBase, const char *filename, struct __stat64* buffer) +bool Interface_Filesystem::stat_file(void* kodiBase, + const char* filename, + struct STAT_STRUCTURE* buffer) { CAddonDll* addon = static_cast(kodiBase); if (addon == nullptr || filename == nullptr || buffer == nullptr) @@ -230,10 +291,22 @@ int Interface_Filesystem::stat_file(void* kodiBase, const char *filename, struct return false; } - return CFile::Stat(filename, buffer); + struct __stat64 statBuffer; + if (CFile::Stat(filename, &statBuffer) != 0) + return false; + + buffer->deviceId = statBuffer.st_dev; + buffer->size = statBuffer.st_size; + buffer->accessTime = statBuffer.st_atime; + buffer->modificationTime = statBuffer.st_mtime; + buffer->statusTime = statBuffer.st_ctime; + buffer->isDirectory = S_ISDIR(statBuffer.st_mode); + buffer->isSymLink = S_ISLNK(statBuffer.st_mode); + + return true; } -bool Interface_Filesystem::delete_file(void* kodiBase, const char *filename) +bool Interface_Filesystem::delete_file(void* kodiBase, const char* filename) { CAddonDll* addon = static_cast(kodiBase); if (addon == nullptr || filename == nullptr) @@ -246,7 +319,9 @@ bool Interface_Filesystem::delete_file(void* kodiBase, const char *filename) return CFile::Delete(filename); } -bool Interface_Filesystem::rename_file(void* kodiBase, const char *filename, const char *newFileName) +bool Interface_Filesystem::rename_file(void* kodiBase, + const char* filename, + const char* newFileName) { CAddonDll* addon = static_cast(kodiBase); if (addon == nullptr || filename == nullptr || newFileName == nullptr) @@ -262,7 +337,7 @@ bool Interface_Filesystem::rename_file(void* kodiBase, const char *filename, con return CFile::Rename(filename, newFileName); } -bool Interface_Filesystem::copy_file(void* kodiBase, const char *filename, const char *dest) +bool Interface_Filesystem::copy_file(void* kodiBase, const char* filename, const char* dest) { CAddonDll* addon = static_cast(kodiBase); if (addon == nullptr || filename == nullptr || dest == nullptr) @@ -338,7 +413,7 @@ char* Interface_Filesystem::make_legal_path(void* kodiBase, const char* path) return buffer; } -char* Interface_Filesystem::translate_special_protocol(void* kodiBase, const char *strSource) +char* Interface_Filesystem::translate_special_protocol(void* kodiBase, const char* strSource) { CAddonDll* addon = static_cast(kodiBase); if (addon == nullptr || strSource == nullptr) @@ -351,6 +426,315 @@ char* Interface_Filesystem::translate_special_protocol(void* kodiBase, const cha return strdup(CSpecialProtocol::TranslatePath(strSource).c_str()); } +bool Interface_Filesystem::is_internet_stream(void* kodiBase, const char* path, bool strictCheck) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || path == nullptr) + { + CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', path='{})", + __FUNCTION__, kodiBase, static_cast(path)); + return false; + } + + return URIUtils::IsInternetStream(path, strictCheck); +} + +bool Interface_Filesystem::is_on_lan(void* kodiBase, const char* path) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || path == nullptr) + { + CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', path='{})", + __FUNCTION__, kodiBase, static_cast(path)); + return false; + } + + return URIUtils::IsOnLAN(path); +} + +bool Interface_Filesystem::is_remote(void* kodiBase, const char* path) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || path == nullptr) + { + CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', path='{})", + __FUNCTION__, kodiBase, static_cast(path)); + return false; + } + + return URIUtils::IsRemote(path); +} + +bool Interface_Filesystem::is_local(void* kodiBase, const char* path) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || path == nullptr) + { + CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', path='{})", + __FUNCTION__, kodiBase, static_cast(path)); + return false; + } + + return CURL(path).IsLocal(); +} + +bool Interface_Filesystem::is_url(void* kodiBase, const char* path) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || path == nullptr) + { + CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', path='{})", + __FUNCTION__, kodiBase, static_cast(path)); + return false; + } + + return URIUtils::IsURL(path); +} + +bool Interface_Filesystem::get_mime_type(void* kodiBase, + const char* url, + char** content, + const char* useragent) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || url == nullptr || content == nullptr || useragent == nullptr) + { + CLog::Log(LOGERROR, + "Interface_Filesystem::{} - invalid data (addon='{}', url='{}', content='{}', " + "useragent='{}')", + __FUNCTION__, kodiBase, static_cast(url), + static_cast(content), static_cast(useragent)); + return false; + } + + std::string kodiContent; + bool ret = XFILE::CCurlFile::GetMimeType(CURL(url), kodiContent, useragent); + if (ret && !kodiContent.empty()) + { + *content = strdup(kodiContent.c_str()); + } + return ret; +} + +bool Interface_Filesystem::get_content_type(void* kodiBase, + const char* url, + char** content, + const char* useragent) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || url == nullptr || content == nullptr || useragent == nullptr) + { + CLog::Log(LOGERROR, + "Interface_Filesystem::{} - invalid data (addon='{}', url='{}', content='{}', " + "useragent='{}')", + __FUNCTION__, kodiBase, static_cast(url), + static_cast(content), static_cast(useragent)); + return false; + } + + std::string kodiContent; + bool ret = XFILE::CCurlFile::GetContentType(CURL(url), kodiContent, useragent); + if (ret && !kodiContent.empty()) + { + *content = strdup(kodiContent.c_str()); + } + return ret; +} + +bool Interface_Filesystem::get_cookies(void* kodiBase, const char* url, char** cookies) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || url == nullptr || cookies == nullptr) + { + CLog::Log( + LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', url='{}', cookies='{}')", + __FUNCTION__, kodiBase, static_cast(url), static_cast(cookies)); + return false; + } + + std::string kodiCookies; + bool ret = XFILE::CCurlFile::GetCookies(CURL(url), kodiCookies); + if (ret && !kodiCookies.empty()) + { + *cookies = strdup(kodiCookies.c_str()); + } + return ret; +} + +bool Interface_Filesystem::get_http_header(void* kodiBase, + const char* url, + struct KODI_HTTP_HEADER* headers) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || url == nullptr || headers == nullptr || headers->handle == nullptr) + { + CLog::Log(LOGERROR, + "Interface_Filesystem::{} - invalid data (addon='{}', url='{}', headers='{}', " + "headers->handle='{}')", + __FUNCTION__, kodiBase, static_cast(url), + static_cast(headers), headers->handle); + return false; + } + + CHttpHeader* httpHeader = static_cast(headers->handle); + return XFILE::CCurlFile::GetHttpHeader(CURL(url), *httpHeader); +} + +//------------------------------------------------------------------------------ + +bool Interface_Filesystem::http_header_create(void* kodiBase, struct KODI_HTTP_HEADER* headers) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || headers == nullptr) + { + CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', headers='{}')", + __FUNCTION__, kodiBase, static_cast(headers)); + return false; + } + + headers->handle = new CHttpHeader; + headers->get_value = http_header_get_value; + headers->get_values = http_header_get_values; + headers->get_header = http_header_get_header; + headers->get_mime_type = http_header_get_mime_type; + headers->get_charset = http_header_get_charset; + headers->get_proto_line = http_header_get_proto_line; + + return true; +} + +void Interface_Filesystem::http_header_free(void* kodiBase, struct KODI_HTTP_HEADER* headers) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || headers == nullptr) + { + CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', headers='{}')", + __FUNCTION__, kodiBase, static_cast(headers)); + return; + } + + delete static_cast(headers->handle); + headers->handle = nullptr; +} + +char* Interface_Filesystem::http_header_get_value(void* kodiBase, void* handle, const char* param) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || handle == nullptr || param == nullptr) + { + CLog::Log(LOGERROR, + "Interface_Filesystem::{} - invalid data (addon='{}', handle='{}', param='{}')", + __FUNCTION__, kodiBase, handle, static_cast(param)); + return nullptr; + } + + std::string string = static_cast(handle)->GetValue(param); + + char* buffer = nullptr; + if (!string.empty()) + buffer = strdup(string.c_str()); + return buffer; +} + +char** Interface_Filesystem::http_header_get_values(void* kodiBase, + void* handle, + const char* param, + int* length) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || handle == nullptr || param == nullptr || length == nullptr) + { + CLog::Log(LOGERROR, + "Interface_Filesystem::{} - invalid data (addon='{}', handle='{}', param='{}', " + "length='{}')", + __FUNCTION__, kodiBase, handle, static_cast(param), + static_cast(length)); + return nullptr; + } + + + std::vector values = static_cast(handle)->GetValues(param); + *length = values.size(); + char** ret = static_cast(malloc(sizeof(char*) * values.size())); + for (int i = 0; i < *length; ++i) + { + ret[i] = strdup(values[i].c_str()); + } + return ret; +} + +char* Interface_Filesystem::http_header_get_header(void* kodiBase, void* handle) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || handle == nullptr) + { + CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', handle='{}')", + __FUNCTION__, kodiBase, handle); + return nullptr; + } + + std::string string = static_cast(handle)->GetHeader(); + + char* buffer = nullptr; + if (!string.empty()) + buffer = strdup(string.c_str()); + return buffer; +} + +char* Interface_Filesystem::http_header_get_mime_type(void* kodiBase, void* handle) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || handle == nullptr) + { + CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', handle='{}')", + __FUNCTION__, kodiBase, handle); + return nullptr; + } + + std::string string = static_cast(handle)->GetMimeType(); + + char* buffer = nullptr; + if (!string.empty()) + buffer = strdup(string.c_str()); + return buffer; +} + +char* Interface_Filesystem::http_header_get_charset(void* kodiBase, void* handle) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || handle == nullptr) + { + CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', handle='{}')", + __FUNCTION__, kodiBase, handle); + return nullptr; + } + + std::string string = static_cast(handle)->GetCharset(); + + char* buffer = nullptr; + if (!string.empty()) + buffer = strdup(string.c_str()); + return buffer; +} + +char* Interface_Filesystem::http_header_get_proto_line(void* kodiBase, void* handle) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || handle == nullptr) + { + CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', handle='{}')", + __FUNCTION__, kodiBase, handle); + return nullptr; + } + + std::string string = static_cast(handle)->GetProtoLine(); + + char* buffer = nullptr; + if (!string.empty()) + buffer = strdup(string.c_str()); + return buffer; +} + //------------------------------------------------------------------------------ void* Interface_Filesystem::open_file(void* kodiBase, const char* filename, unsigned int flags) @@ -364,14 +748,16 @@ void* Interface_Filesystem::open_file(void* kodiBase, const char* filename, unsi } CFile* file = new CFile; - if (file->Open(filename, flags)) + if (file->Open(filename, TranslateFileReadBitsToKodi(flags))) return static_cast(file); delete file; return nullptr; } -void* Interface_Filesystem::open_file_for_write(void* kodiBase, const char* filename, bool overwrite) +void* Interface_Filesystem::open_file_for_write(void* kodiBase, + const char* filename, + bool overwrite) { CAddonDll* addon = static_cast(kodiBase); if (addon == nullptr || filename == nullptr) @@ -402,7 +788,10 @@ ssize_t Interface_Filesystem::read_file(void* kodiBase, void* file, void* ptr, s return static_cast(file)->Read(ptr, size); } -bool Interface_Filesystem::read_file_string(void* kodiBase, void* file, char *szLine, int lineLength) +bool Interface_Filesystem::read_file_string(void* kodiBase, + void* file, + char* szLine, + int lineLength) { CAddonDll* addon = static_cast(kodiBase); if (addon == nullptr || file == nullptr || szLine == nullptr) @@ -526,7 +915,7 @@ int Interface_Filesystem::get_file_chunk_size(void* kodiBase, void* file) CAddonDll* addon = static_cast(kodiBase); if (addon == nullptr || file == nullptr) { - CLog::Log(LOGERROR, "Interface_VFS::{} - invalid data (addon='{}', file='{})", __FUNCTION__, + CLog::Log(LOGERROR, "Interface_VFS::{} - invalid data (addon='{}', file='{}')", __FUNCTION__, kodiBase, file); return -1; } @@ -534,6 +923,74 @@ int Interface_Filesystem::get_file_chunk_size(void* kodiBase, void* file) return static_cast(file)->GetChunkSize(); } +bool Interface_Filesystem::io_control_get_seek_possible(void* kodiBase, void* file) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || file == nullptr) + { + CLog::Log(LOGERROR, "Interface_VFS::{} - invalid data (addon='{}', file='{}')", __FUNCTION__, + kodiBase, file); + return -1; + } + + return static_cast(file)->IoControl(EIoControl::IOCTRL_SEEK_POSSIBLE, nullptr) != 0 + ? true + : false; +} + +bool Interface_Filesystem::io_control_get_cache_status(void* kodiBase, + void* file, + struct VFS_CACHE_STATUS_DATA* status) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || file == nullptr || status == nullptr) + { + CLog::Log(LOGERROR, "Interface_VFS::{} - invalid data (addon='{}', file='{}, status='{}')", + __FUNCTION__, kodiBase, file, static_cast(status)); + return -1; + } + + SCacheStatus data = {0}; + int ret = static_cast(file)->IoControl(EIoControl::IOCTRL_CACHE_STATUS, &data); + if (ret >= 0) + { + status->forward = data.forward; + status->maxrate = data.maxrate; + status->currate = data.currate; + status->lowspeed = data.lowspeed; + return true; + } + return false; +} + +bool Interface_Filesystem::io_control_set_cache_rate(void* kodiBase, void* file, unsigned int rate) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || file == nullptr) + { + CLog::Log(LOGERROR, "Interface_VFS::{} - invalid data (addon='{}', file='{}')", __FUNCTION__, + kodiBase, file); + return -1; + } + + return static_cast(file)->IoControl(EIoControl::IOCTRL_CACHE_SETRATE, &rate) >= 0 ? true + : false; +} + +bool Interface_Filesystem::io_control_set_retry(void* kodiBase, void* file, bool retry) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || file == nullptr) + { + CLog::Log(LOGERROR, "Interface_VFS::{} - invalid data (addon='{}', file='{}')", __FUNCTION__, + kodiBase, file); + return -1; + } + + return static_cast(file)->IoControl(EIoControl::IOCTRL_SET_RETRY, &retry) >= 0 ? true + : false; +} + char** Interface_Filesystem::get_property_values( void* kodiBase, void* file, int type, const char* name, int* numValues) { @@ -551,32 +1008,33 @@ char** Interface_Filesystem::get_property_values( XFILE::FileProperty internalType; switch (type) { - case ADDON_FILE_PROPERTY_RESPONSE_PROTOCOL: - internalType = XFILE::FILE_PROPERTY_RESPONSE_PROTOCOL; - break; - case ADDON_FILE_PROPERTY_RESPONSE_HEADER: - internalType = XFILE::FILE_PROPERTY_RESPONSE_HEADER; - break; - case ADDON_FILE_PROPERTY_CONTENT_TYPE: - internalType = XFILE::FILE_PROPERTY_CONTENT_TYPE; - break; - case ADDON_FILE_PROPERTY_CONTENT_CHARSET: - internalType = XFILE::FILE_PROPERTY_CONTENT_CHARSET; - break; - case ADDON_FILE_PROPERTY_MIME_TYPE: - internalType = XFILE::FILE_PROPERTY_MIME_TYPE; - break; - case ADDON_FILE_PROPERTY_EFFECTIVE_URL: - internalType = XFILE::FILE_PROPERTY_EFFECTIVE_URL; - break; - default: - CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', file='{}')", - __FUNCTION__, kodiBase, file); - return nullptr; + case ADDON_FILE_PROPERTY_RESPONSE_PROTOCOL: + internalType = XFILE::FILE_PROPERTY_RESPONSE_PROTOCOL; + break; + case ADDON_FILE_PROPERTY_RESPONSE_HEADER: + internalType = XFILE::FILE_PROPERTY_RESPONSE_HEADER; + break; + case ADDON_FILE_PROPERTY_CONTENT_TYPE: + internalType = XFILE::FILE_PROPERTY_CONTENT_TYPE; + break; + case ADDON_FILE_PROPERTY_CONTENT_CHARSET: + internalType = XFILE::FILE_PROPERTY_CONTENT_CHARSET; + break; + case ADDON_FILE_PROPERTY_MIME_TYPE: + internalType = XFILE::FILE_PROPERTY_MIME_TYPE; + break; + case ADDON_FILE_PROPERTY_EFFECTIVE_URL: + internalType = XFILE::FILE_PROPERTY_EFFECTIVE_URL; + break; + default: + CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', file='{}')", + __FUNCTION__, kodiBase, file); + return nullptr; }; - std::vector values = static_cast(file)->GetPropertyValues(internalType, name); + std::vector values = + static_cast(file)->GetPropertyValues(internalType, name); *numValues = values.size(); - char **ret = static_cast(malloc(sizeof(char*)*values.size())); + char** ret = static_cast(malloc(sizeof(char*) * values.size())); for (int i = 0; i < *numValues; ++i) { ret[i] = strdup(values[i].c_str()); @@ -602,7 +1060,8 @@ void* Interface_Filesystem::curl_create(void* kodiBase, const char* url) return nullptr; } -bool Interface_Filesystem::curl_add_option(void* kodiBase, void* file, int type, const char* name, const char* value) +bool Interface_Filesystem::curl_add_option( + void* kodiBase, void* file, int type, const char* name, const char* value) { CAddonDll* addon = static_cast(kodiBase); if (addon == nullptr || file == nullptr || name == nullptr || value == nullptr) @@ -618,21 +1077,21 @@ bool Interface_Filesystem::curl_add_option(void* kodiBase, void* file, int type, XFILE::CURLOPTIONTYPE internalType; switch (type) { - case ADDON_CURL_OPTION_OPTION: - internalType = XFILE::CURL_OPTION_OPTION; - break; - case ADDON_CURL_OPTION_PROTOCOL: - internalType = XFILE::CURL_OPTION_PROTOCOL; - break; - case ADDON_CURL_OPTION_CREDENTIALS: - internalType = XFILE::CURL_OPTION_CREDENTIALS; - break; - case ADDON_CURL_OPTION_HEADER: - internalType = XFILE::CURL_OPTION_HEADER; - break; - default: - throw std::logic_error("Interface_Filesystem::curl_add_option - invalid curl option type"); - return false; + case ADDON_CURL_OPTION_OPTION: + internalType = XFILE::CURL_OPTION_OPTION; + break; + case ADDON_CURL_OPTION_PROTOCOL: + internalType = XFILE::CURL_OPTION_PROTOCOL; + break; + case ADDON_CURL_OPTION_CREDENTIALS: + internalType = XFILE::CURL_OPTION_CREDENTIALS; + break; + case ADDON_CURL_OPTION_HEADER: + internalType = XFILE::CURL_OPTION_HEADER; + break; + default: + throw std::logic_error("Interface_Filesystem::curl_add_option - invalid curl option type"); + return false; }; return static_cast(file)->CURLAddOption(internalType, name, value); @@ -648,7 +1107,7 @@ bool Interface_Filesystem::curl_open(void* kodiBase, void* file, unsigned int fl return false; } - return static_cast(file)->CURLOpen(flags); + return static_cast(file)->CURLOpen(TranslateFileReadBitsToKodi(flags)); } } /* namespace ADDON */ diff --git a/xbmc/addons/interfaces/Filesystem.h b/xbmc/addons/interfaces/Filesystem.h index 8d5bd6fd32fea..cf26026e6c661 100644 --- a/xbmc/addons/interfaces/Filesystem.h +++ b/xbmc/addons/interfaces/Filesystem.h @@ -24,6 +24,8 @@ struct Interface_Filesystem static void Init(AddonGlobalInterface* addonInterface); static void DeInit(AddonGlobalInterface* addonInterface); + static unsigned int TranslateFileReadBitsToKodi(unsigned int addonFlags); + /*! * @brief callback functions from add-on to kodi * @@ -34,7 +36,7 @@ struct Interface_Filesystem * The parameter `kodiBase` is used to become the pointer for a `CAddonDll` * class. */ - //@{ + ///@{ static bool can_open_directory(void* kodiBase, const char* url); static bool create_directory(void* kodiBase, const char* path); static bool directory_exists(void* kodiBase, const char* path); @@ -42,12 +44,12 @@ struct Interface_Filesystem static bool get_directory(void* kodiBase, const char* path, const char* mask, - VFSDirEntry** items, + struct VFSDirEntry** items, unsigned int* num_items); - static void free_directory(void* kodiBase, VFSDirEntry* items, unsigned int num_items); + static void free_directory(void* kodiBase, struct VFSDirEntry* items, unsigned int num_items); static bool file_exists(void* kodiBase, const char* filename, bool useCache); - static int stat_file(void* kodiBase, const char* filename, struct __stat64* buffer); + static bool stat_file(void* kodiBase, const char* filename, struct STAT_STRUCTURE* buffer); static bool delete_file(void* kodiBase, const char* filename); static bool rename_file(void* kodiBase, const char* filename, const char* newFileName); static bool copy_file(void* kodiBase, const char* filename, const char* dest); @@ -56,7 +58,42 @@ 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 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); + static bool is_local(void* kodiBase, const char* path); + static bool is_url(void* kodiBase, const char* path); + + static bool get_http_header(void* kodiBase, const char* url, struct KODI_HTTP_HEADER* headers); + static bool get_mime_type(void* kodiBase, const char* url, char** content, const char* useragent); + static bool get_content_type(void* kodiBase, + const char* url, + char** content, + const char* useragent); + static bool get_cookies(void* kodiBase, const char* url, char** cookies); + + /*! + * @brief Callback functions addon class kodi::vfs::CFile + */ + ///@{ + static bool http_header_create(void* kodiBase, struct KODI_HTTP_HEADER* headers); + static void http_header_free(void* kodiBase, struct KODI_HTTP_HEADER* headers); + + static char* http_header_get_value(void* kodiBase, void* handle, const char* param); + static char** http_header_get_values(void* kodiBase, + void* handle, + const char* param, + int* length); + static char* http_header_get_header(void* kodiBase, void* handle); + static char* http_header_get_mime_type(void* kodiBase, void* handle); + static char* http_header_get_charset(void* kodiBase, void* handle); + static char* http_header_get_proto_line(void* kodiBase, void* handle); + ///@} + /*! + * @brief Callback functions addon class kodi::vfs::CFile + */ + ///@{ static void* open_file(void* kodiBase, const char* filename, unsigned int flags); static void* open_file_for_write(void* kodiBase, const char* filename, bool overwrite); static ssize_t read_file(void* kodiBase, void* file, void* ptr, size_t size); @@ -70,6 +107,12 @@ struct Interface_Filesystem static double get_file_download_speed(void* kodiBase, void* file); static void close_file(void* kodiBase, void* file); static int get_file_chunk_size(void* kodiBase, void* file); + static bool io_control_get_seek_possible(void* kodiBase, void* file); + static bool io_control_get_cache_status(void* kodiBase, + void* file, + struct VFS_CACHE_STATUS_DATA* status); + static bool io_control_set_cache_rate(void* kodiBase, void* file, unsigned int rate); + static bool io_control_set_retry(void* kodiBase, void* file, bool retry); static char** get_property_values( void* kodiBase, void* file, int type, const char* name, int* numValues); @@ -77,7 +120,8 @@ struct Interface_Filesystem static bool curl_add_option( void* kodiBase, void* file, int type, const char* name, const char* value); static bool curl_open(void* kodiBase, void* file, unsigned int flags); - //@} + ///@} + ///@} }; } /* namespace ADDON */ diff --git a/xbmc/addons/interfaces/General.cpp b/xbmc/addons/interfaces/General.cpp index a2a12fa635b57..6f83093afa7c2 100644 --- a/xbmc/addons/interfaces/General.cpp +++ b/xbmc/addons/interfaces/General.cpp @@ -55,6 +55,7 @@ void Interface_General::Init(AddonGlobalInterface* addonInterface) addonInterface->toKodi->kodi->get_region = get_region; addonInterface->toKodi->kodi->get_free_mem = get_free_mem; addonInterface->toKodi->kodi->get_global_idle_time = get_global_idle_time; + addonInterface->toKodi->kodi->is_addon_avilable = is_addon_avilable; addonInterface->toKodi->kodi->kodi_version = kodi_version; addonInterface->toKodi->kodi->get_current_skin_id = get_current_skin_id; addonInterface->toKodi->kodi->get_keyboard_layout = get_keyboard_layout; @@ -131,7 +132,7 @@ bool Interface_General::open_settings_dialog(void* kodiBase) // show settings dialog AddonPtr addonInfo; - if (CServiceBroker::GetAddonMgr().GetAddon(addon->ID(), addonInfo)) + if (!CServiceBroker::GetAddonMgr().GetAddon(addon->ID(), addonInfo)) { CLog::Log(LOGERROR, "Interface_General::{} - Could not get addon information for '{}'", __FUNCTION__, addon->ID()); @@ -422,6 +423,31 @@ int Interface_General::get_global_idle_time(void* kodiBase) return g_application.GlobalIdleTime(); } +bool Interface_General::is_addon_avilable(void* kodiBase, + const char* id, + char** version, + bool* enabled) +{ + CAddonDll* addon = static_cast(kodiBase); + if (addon == nullptr || id == nullptr || version == nullptr || enabled == nullptr) + { + CLog::Log( + LOGERROR, + "Interface_General::{} - invalid data (addon='{}', id='{}', version='{}', enabled='{}')", + __FUNCTION__, kodiBase, static_cast(id), static_cast(version), + static_cast(enabled)); + return false; + } + + AddonPtr addonInfo; + if (!CServiceBroker::GetAddonMgr().GetAddon(id, addonInfo, ADDON_UNKNOWN, false)) + return false; + + *version = strdup(addonInfo->Version().asString().c_str()); + *enabled = !CServiceBroker::GetAddonMgr().IsAddonDisabled(id); + return true; +} + void Interface_General::kodi_version(void* kodiBase, char** compile_name, int* major, int* minor, char** revision, char** tag, char** tagversion) { CAddonDll* addon = static_cast(kodiBase); @@ -436,7 +462,7 @@ void Interface_General::kodi_version(void* kodiBase, char** compile_name, int* m static_cast(tagversion)); return; } - + *compile_name = strdup(CCompileInfo::GetAppName()); *major = CCompileInfo::GetMajor(); *minor = CCompileInfo::GetMinor(); diff --git a/xbmc/addons/interfaces/General.h b/xbmc/addons/interfaces/General.h index a4ea93fba61d3..1ccc80d2a96e4 100644 --- a/xbmc/addons/interfaces/General.h +++ b/xbmc/addons/interfaces/General.h @@ -59,6 +59,7 @@ struct Interface_General static char* get_region(void* kodiBase, const char* id); static void get_free_mem(void* kodiInstance, long* free, long* total, bool as_bytes); static int get_global_idle_time(void* kodiBase); + static bool is_addon_avilable(void* kodiBase, const char* id, char** version, bool* enabled); static void kodi_version(void* kodiBase, char** compile_name, int* major, 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 aaefb904fd699..fce461c127ac7 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/AddonBase.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/AddonBase.h @@ -8,238 +8,50 @@ #pragma once +#include "c-api/addon_base.h" +#include "versions.h" + #include /* assert */ -#include /* va_list, va_start, va_arg, va_end */ #include #include #include #include +#include /* va_list, va_start, va_arg, va_end */ #include #include #include -#ifndef TARGET_WINDOWS -#ifndef __cdecl -#define __cdecl -#endif -#ifndef __declspec -#define __declspec(X) -#endif -#endif - -#undef ATTRIBUTE_PACKED -#undef PRAGMA_PACK_BEGIN -#undef PRAGMA_PACK_END - -#if defined(__GNUC__) - #define ATTRIBUTE_PACKED __attribute__ ((packed)) - #define PRAGMA_PACK 0 - #define ATTRIBUTE_HIDDEN __attribute__ ((visibility ("hidden"))) -#endif - -#if !defined(ATTRIBUTE_PACKED) - #define ATTRIBUTE_PACKED - #define PRAGMA_PACK 1 -#endif - -#if !defined(ATTRIBUTE_HIDDEN) - #define ATTRIBUTE_HIDDEN -#endif - -#ifdef _MSC_VER - #define ATTRIBUTE_FORCEINLINE __forceinline -#elif defined(__GNUC__) - #define ATTRIBUTE_FORCEINLINE inline __attribute__((__always_inline__)) -#elif defined(__CLANG__) - #if __has_attribute(__always_inline__) - #define ATTRIBUTE_FORCEINLINE inline __attribute__((__always_inline__)) - #else - #define ATTRIBUTE_FORCEINLINE inline - #endif -#else - #define ATTRIBUTE_FORCEINLINE inline -#endif - -#include "versions.h" - -namespace kodi { namespace addon { class CAddonBase; }} -namespace kodi { namespace addon { class IAddonInstance; }} -namespace kodi { namespace gui { struct IRenderHelper; }} - -extern "C" { - -//============================================================================== -/// Standard undefined pointer handle -typedef void* KODI_HANDLE; -//------------------------------------------------------------------------------ - -//============================================================================== -/// -/// @ingroup cpp_kodi_addon_addonbase -/// @brief Return value of functions in \ref kodi::addon::CAddonBase and -/// associated classes -/// -typedef enum ADDON_STATUS +namespace kodi { - /// For everything OK and no error - ADDON_STATUS_OK, - - /// A needed connection was lost - ADDON_STATUS_LOST_CONNECTION, - - /// Addon needs a restart inside Kodi - ADDON_STATUS_NEED_RESTART, - - /// Necessary settings are not yet set - ADDON_STATUS_NEED_SETTINGS, - - /// Unknown and incomprehensible error - ADDON_STATUS_UNKNOWN, - /// Permanent failure, like failing to resolve methods - ADDON_STATUS_PERMANENT_FAILURE, - - /* internal used return error if function becomes not used from child on - * addon */ - ADDON_STATUS_NOT_IMPLEMENTED -} ADDON_STATUS; -//------------------------------------------------------------------------------ +namespace gui +{ +struct IRenderHelper; +} // namespace gui //============================================================================== -/// @todo remove start with ADDON_* after old way on libXBMC_addon.h is removed /// -typedef enum AddonLog +class CSettingValue { - /// - ADDON_LOG_DEBUG = 0, - - /// - ADDON_LOG_INFO = 1, - - /// - ADDON_LOG_NOTICE = 2, - - /// - ADDON_LOG_WARNING = 3, - - /// - ADDON_LOG_ERROR = 4, - - /// - ADDON_LOG_SEVERE = 5, +public: + explicit CSettingValue(const void* settingValue) : m_settingValue(settingValue) {} - /// - ADDON_LOG_FATAL = 6 -} AddonLog; -//------------------------------------------------------------------------------ + bool empty() const { return (m_settingValue == nullptr) ? true : false; } + std::string GetString() const { return (const char*)m_settingValue; } + int GetInt() const { return *(const int*)m_settingValue; } + unsigned int GetUInt() const { return *(const unsigned int*)m_settingValue; } + bool GetBoolean() const { return *(const bool*)m_settingValue; } + float GetFloat() const { return *(const float*)m_settingValue; } -/*! - * @brief Handle used to return data from the PVR add-on to CPVRClient - */ -struct ADDON_HANDLE_STRUCT -{ - void *callerAddress; /*!< address of the caller */ - void *dataAddress; /*!< address to store data in */ - int dataIdentifier; /*!< parameter to pass back when calling the callback */ +private: + const void* m_settingValue; }; -typedef ADDON_HANDLE_STRUCT *ADDON_HANDLE; - -/* - * To have a on add-on and kodi itself handled string always on known size! - */ -#define ADDON_STANDARD_STRING_LENGTH 1024 -#define ADDON_STANDARD_STRING_LENGTH_SMALL 256 - -/* - * Callback function tables from addon to Kodi - * Set complete from Kodi! - */ -struct AddonToKodiFuncTable_kodi; -struct AddonToKodiFuncTable_kodi_audioengine; -struct AddonToKodiFuncTable_kodi_filesystem; -struct AddonToKodiFuncTable_kodi_network; -struct AddonToKodiFuncTable_kodi_gui; -typedef struct AddonToKodiFuncTable_Addon -{ - // Pointer inside Kodi, used on callback functions to give related handle - // class, for this ADDON::CAddonDll inside Kodi. - KODI_HANDLE kodiBase; - - // Function addresses used for callbacks from addon to Kodi - void (*free_string)(void* kodiBase, char* str); - void (*free_string_array)(void* kodiBase, char** arr, int numElements); - char* (*get_addon_path)(void* kodiBase); - char* (*get_base_user_path)(void* kodiBase); - void (*addon_log_msg)(void* kodiBase, const int loglevel, const char *msg); - - bool (*get_setting_bool)(void* kodiBase, const char* id, bool* value); - bool (*get_setting_int)(void* kodiBase, const char* id, int* value); - bool (*get_setting_float)(void* kodiBase, const char* id, float* value); - bool (*get_setting_string)(void* kodiBase, const char* id, char** value); - - bool (*set_setting_bool)(void* kodiBase, const char* id, bool value); - bool (*set_setting_int)(void* kodiBase, const char* id, int value); - bool (*set_setting_float)(void* kodiBase, const char* id, float value); - bool (*set_setting_string)(void* kodiBase, const char* id, const char* value); - - AddonToKodiFuncTable_kodi* kodi; - AddonToKodiFuncTable_kodi_audioengine* kodi_audioengine; - AddonToKodiFuncTable_kodi_filesystem* kodi_filesystem; - AddonToKodiFuncTable_kodi_gui* kodi_gui; - AddonToKodiFuncTable_kodi_network *kodi_network; - - void* (*get_interface)(void* kodiBase, const char *name, const char *version); -} AddonToKodiFuncTable_Addon; - -/* - * Function tables from Kodi to addon - */ -typedef struct KodiToAddonFuncTable_Addon -{ - void (*destroy)(); - ADDON_STATUS (*get_status)(); - 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; +//------------------------------------------------------------------------------ -/* - * Main structure passed from kodi to addon with basic information needed to - * create add-on. - */ -typedef struct AddonGlobalInterface +namespace addon { - // String with full path where add-on is installed (without his name on end) - // Set from Kodi! - const char* libBasePath; - - // Pointer of first created instance, used in case this add-on goes with single way - // Set from Kodi! - KODI_HANDLE firstKodiInstance; - - // Pointer to master base class inside add-on - // Set from addon header! - kodi::addon::CAddonBase* addonBase; - - // Pointer to a instance used on single way (together with this class) - // Set from addon header! - kodi::addon::IAddonInstance* globalSingleInstance; - - // Callback function tables from addon to Kodi - // Set from Kodi! - AddonToKodiFuncTable_Addon* toKodi; - - // Function tables from Kodi to addon - // Set from addon header! - KodiToAddonFuncTable_Addon* toAddon; -} AddonGlobalInterface; - -} /* extern "C" */ //============================================================================== -namespace kodi { -namespace addon { /* * Internal class to control various instance types with general parts defined * here. @@ -252,49 +64,25 @@ namespace addon { class IAddonInstance { public: - explicit IAddonInstance(ADDON_TYPE type) : m_type(type) { } - virtual ~IAddonInstance() = default; - - virtual ADDON_STATUS CreateInstance(int instanceType, std::string instanceID, KODI_HANDLE instance, KODI_HANDLE& addonInstance) + explicit IAddonInstance(ADDON_TYPE type, const std::string& version) + : m_type(type), m_kodiVersion(version) { - return ADDON_STATUS_NOT_IMPLEMENTED; } + virtual ~IAddonInstance() = default; - virtual ADDON_STATUS CreateInstanceEx(int instanceType, std::string instanceID, KODI_HANDLE instance, KODI_HANDLE& addonInstance, const std::string &version) + virtual ADDON_STATUS CreateInstance(int instanceType, + const std::string& instanceID, + KODI_HANDLE instance, + const std::string& version, + KODI_HANDLE& addonInstance) { - return CreateInstance(instanceType, instanceID, instance, addonInstance); + return ADDON_STATUS_NOT_IMPLEMENTED; } const ADDON_TYPE m_type; + const std::string m_kodiVersion; + std::string m_id; }; -} /* namespace addon */ -} /* namespace kodi */ -//------------------------------------------------------------------------------ - -//============================================================================== -namespace kodi { -/// -class CSettingValue -{ -public: - explicit CSettingValue(const void *settingValue) : m_settingValue(settingValue) {} - - bool empty() const { return (m_settingValue == nullptr) ? true : false; } - std::string GetString() const { return (const char*)m_settingValue; } - int GetInt() const { return *(const int*)m_settingValue; } - unsigned int GetUInt() const { return *(const unsigned int*)m_settingValue; } - bool GetBoolean() const { return *(const bool*)m_settingValue; } - float GetFloat() const { return *(const float*)m_settingValue; } - -private: - const void *m_settingValue; -}; -} /* namespace kodi */ -//------------------------------------------------------------------------------ - -//============================================================================== -namespace kodi { -namespace addon { /* * Internally used helper class to manage processing of a "C" structure in "CPP" @@ -340,29 +128,16 @@ template class CStructHdl { public: - CStructHdl() - : m_cStructure(new C_STRUCT()) - , m_owner(true) - { - } + CStructHdl() : m_cStructure(new C_STRUCT()), m_owner(true) {} CStructHdl(const CPP_CLASS& cppClass) - : m_cStructure(new C_STRUCT(*cppClass.m_cStructure)) - , m_owner(true) + : m_cStructure(new C_STRUCT(*cppClass.m_cStructure)), m_owner(true) { } - CStructHdl(const C_STRUCT* cStructure) - : m_cStructure(new C_STRUCT(*cStructure)) - , m_owner(true) - { - } + CStructHdl(const C_STRUCT* cStructure) : m_cStructure(new C_STRUCT(*cStructure)), m_owner(true) {} - CStructHdl(C_STRUCT* cStructure) - : m_cStructure(cStructure) - { - assert(cStructure); - } + CStructHdl(C_STRUCT* cStructure) : m_cStructure(cStructure) { assert(cStructure); } const CStructHdl& operator=(const CStructHdl& right) { @@ -405,6 +180,9 @@ class CStructHdl } operator C_STRUCT*() { return m_cStructure; } + operator const C_STRUCT*() const { return m_cStructure; } + + const C_STRUCT* GetCStructure() const { return m_cStructure; } protected: C_STRUCT* m_cStructure = nullptr; @@ -419,14 +197,11 @@ class ATTRIBUTE_HIDDEN CAddonBase public: CAddonBase() { - CAddonBase::m_interface->toAddon->destroy = ADDONBASE_Destroy; - CAddonBase::m_interface->toAddon->get_status = ADDONBASE_GetStatus; - 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; + m_interface->toAddon->destroy = ADDONBASE_Destroy; + m_interface->toAddon->get_status = ADDONBASE_GetStatus; + m_interface->toAddon->create_instance = ADDONBASE_CreateInstance; + m_interface->toAddon->destroy_instance = ADDONBASE_DestroyInstance; + m_interface->toAddon->set_setting = ADDONBASE_SetSetting; } virtual ~CAddonBase() = default; @@ -435,16 +210,23 @@ class ATTRIBUTE_HIDDEN CAddonBase virtual ADDON_STATUS GetStatus() { return ADDON_STATUS_OK; } - virtual ADDON_STATUS SetSetting(const std::string& settingName, const CSettingValue& settingValue) { return ADDON_STATUS_UNKNOWN; } + virtual ADDON_STATUS SetSetting(const std::string& settingName, const CSettingValue& settingValue) + { + return ADDON_STATUS_UNKNOWN; + } //========================================================================== /// @ingroup cpp_kodi_addon_addonbase /// @brief Instance created /// - /// @param[in] instanceType The requested type of required instance, see \ref ADDON_TYPE. - /// @param[in] instanceID An individual identification key string given by Kodi. - /// @param[in] instance The instance handler used by Kodi must be passed - /// to the classes created here. See in the example. + /// @param[in] instanceType The requested type of required instance, see \ref ADDON_TYPE. + /// @param[in] instanceID An individual identification key string given by Kodi. + /// @param[in] instance The instance handler used by Kodi must be passed to + /// the classes created here. See in the example. + /// @param[in] version The from Kodi used version of instance. This can be + /// used to allow compatibility to older versions of + /// them. Further is this given to the parent instance + /// that it can handle differences. /// @param[out] addonInstance The pointer to instance class created in addon. /// Needed to be able to identify them on calls. /// @return \ref ADDON_STATUS_OK if correct, for possible errors @@ -463,8 +245,9 @@ class ATTRIBUTE_HIDDEN CAddonBase /// /* If you use only one instance in your add-on, can be instanceType and /// * instanceID ignored */ /// ADDON_STATUS CMyAddon::CreateInstance(int instanceType, - /// std::string instanceID, + /// const std::string& instanceID, /// KODI_HANDLE instance, + /// const std::string& version, /// KODI_HANDLE& addonInstance) /// { /// if (instanceType == ADDON_INSTANCE_SCREENSAVER) @@ -490,18 +273,25 @@ class ATTRIBUTE_HIDDEN CAddonBase /// /// ~~~~~~~~~~~~~ /// - virtual ADDON_STATUS CreateInstance(int instanceType, std::string instanceID, KODI_HANDLE instance, KODI_HANDLE& addonInstance) + virtual ADDON_STATUS CreateInstance(int instanceType, + const std::string& instanceID, + KODI_HANDLE instance, + 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 */ - if (CAddonBase::m_interface->firstKodiInstance == instance && // the kodi side instance pointer must be equal to first one - CAddonBase::m_interface->globalSingleInstance && // the addon side instance pointer must be set - CAddonBase::m_interface->globalSingleInstance->m_type == instanceType) // and the requested type must be equal with used add-on 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(m_interface->globalSingleInstance)->m_type == instanceType) { - addonInstance = CAddonBase::m_interface->globalSingleInstance; + addonInstance = m_interface->globalSingleInstance; return ADDON_STATUS_OK; } @@ -509,80 +299,137 @@ class ATTRIBUTE_HIDDEN CAddonBase } //-------------------------------------------------------------------------- - virtual ADDON_STATUS CreateInstanceEx(int instanceType, std::string instanceID, KODI_HANDLE instance, KODI_HANDLE& addonInstance, const std::string &version) + //========================================================================== + /// @ingroup cpp_kodi_addon_addonbase + /// @brief Instance destroy + /// + /// This function is optional and intended to notify addon that the instance + /// is terminating. + /// + /// @param[in] instanceType The requested type of required instance, see \ref ADDON_TYPE. + /// @param[in] instanceID An individual identification key string given by Kodi. + /// @param[in] addonInstance The pointer to instance class created in addon. + /// + /// @warning This call is only used to inform that the associated instance + /// is terminated. The deletion is carried out in the background. + /// + virtual void DestroyInstance(int instanceType, + const std::string& instanceID, + KODI_HANDLE addonInstance) { - return CreateInstance(instanceType, instanceID, instance, addonInstance); } + //-------------------------------------------------------------------------- /* Background helper for GUI render systems, e.g. Screensaver or Visualization */ std::shared_ptr m_renderHelper; /* 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; + static AddonGlobalInterface* + m_interface; // Interface function table to hold addresses on add-on and from kodi -/*private:*/ /* Needed public as long the old call functions becomes used! */ + /*private:*/ /* Needed public as long the old call functions becomes used! */ static inline void ADDONBASE_Destroy() { - delete CAddonBase::m_interface->addonBase; - CAddonBase::m_interface->addonBase = nullptr; + delete static_cast(m_interface->addonBase); + m_interface->addonBase = nullptr; } - static inline ADDON_STATUS ADDONBASE_GetStatus() { return CAddonBase::m_interface->addonBase->GetStatus(); } - - static inline ADDON_STATUS ADDONBASE_SetSetting(const char *settingName, const void *settingValue) + static inline ADDON_STATUS ADDONBASE_GetStatus() { - return CAddonBase::m_interface->addonBase->SetSetting(settingName, CSettingValue(settingValue)); + return static_cast(m_interface->addonBase)->GetStatus(); } - static inline ADDON_STATUS ADDONBASE_CreateInstance(int instanceType, const char* instanceID, KODI_HANDLE instance, KODI_HANDLE* addonInstance, KODI_HANDLE parent) + static inline ADDON_STATUS ADDONBASE_SetSetting(const char* settingName, const void* settingValue) { - return ADDONBASE_CreateInstanceEx(instanceType, instanceID, instance, addonInstance, parent, ""); + return static_cast(m_interface->addonBase) + ->SetSetting(settingName, CSettingValue(settingValue)); } - static inline ADDON_STATUS ADDONBASE_CreateInstanceEx(int instanceType, const char* instanceID, KODI_HANDLE instance, KODI_HANDLE* addonInstance, KODI_HANDLE parent, const char* version) +private: + static inline ADDON_STATUS ADDONBASE_CreateInstance(int instanceType, + const char* instanceID, + KODI_HANDLE instance, + const char* version, + KODI_HANDLE* addonInstance, + KODI_HANDLE parent) { + CAddonBase* base = static_cast(m_interface->addonBase); + ADDON_STATUS status = ADDON_STATUS_NOT_IMPLEMENTED; if (parent != nullptr) - status = static_cast(parent)->CreateInstanceEx(instanceType, instanceID, instance, *addonInstance, version); + status = static_cast(parent)->CreateInstance( + instanceType, instanceID, instance, version, *addonInstance); if (status == ADDON_STATUS_NOT_IMPLEMENTED) - status = CAddonBase::m_interface->addonBase->CreateInstanceEx(instanceType, instanceID, instance, *addonInstance, version); + status = base->CreateInstance(instanceType, instanceID, instance, version, *addonInstance); if (*addonInstance == nullptr) - throw std::logic_error("kodi::addon::CAddonBase CreateInstanceEx returns a empty instance pointer!"); + throw std::logic_error( + "kodi::addon::CAddonBase CreateInstance returns a empty instance pointer!"); + + if (static_cast(*addonInstance)->m_type != instanceType) + throw std::logic_error("kodi::addon::CAddonBase CreateInstance with difference on given " + "and returned instance type!"); - if (static_cast<::kodi::addon::IAddonInstance*>(*addonInstance)->m_type != instanceType) - throw std::logic_error("kodi::addon::CAddonBase CreateInstanceEx with difference on given and returned instance type!"); + // Store the used ID inside instance, to have on destroy calls by addon to identify + static_cast(*addonInstance)->m_id = instanceID; return status; } static inline void ADDONBASE_DestroyInstance(int instanceType, KODI_HANDLE instance) { - if (CAddonBase::m_interface->globalSingleInstance == nullptr && instance != CAddonBase::m_interface->addonBase) + CAddonBase* base = static_cast(m_interface->addonBase); + + if (m_interface->globalSingleInstance == nullptr && instance != base) { - if (static_cast<::kodi::addon::IAddonInstance*>(instance)->m_type == instanceType) - delete static_cast<::kodi::addon::IAddonInstance*>(instance); + if (static_cast(instance)->m_type == instanceType) + { + base->DestroyInstance(instanceType, static_cast(instance)->m_id, instance); + delete static_cast(instance); + } else - throw std::logic_error("kodi::addon::CAddonBase DestroyInstance called with difference on given and present instance type!"); + throw std::logic_error("kodi::addon::CAddonBase DestroyInstance called with difference on " + "given and present instance type!"); } } }; + } /* namespace addon */ -} /* namespace kodi */ + +//============================================================================== +/// @ingroup cpp_kodi_addon_addonbase +/// @brief To get used version inside Kodi itself about asked type. +/// +/// This thought to allow a addon a handling of newer addon versions within +/// older Kodi until the type min version not changed. +/// +/// @param[in] type The wanted type of @ref ADDON_TYPE to ask +/// @return The version string about type in MAJOR.MINOR.PATCH style. +/// +inline std::string GetKodiTypeVersion(int type) +{ + using namespace kodi::addon; + + char* str = CAddonBase::m_interface->toKodi->get_type_version( + CAddonBase::m_interface->toKodi->kodiBase, type); + std::string ret = str; + CAddonBase::m_interface->toKodi->free_string(CAddonBase::m_interface->toKodi->kodiBase, str); + return ret; +} //------------------------------------------------------------------------------ //============================================================================== -namespace kodi { /// inline std::string GetAddonPath(const std::string& append = "") { - char* str = ::kodi::addon::CAddonBase::m_interface->toKodi->get_addon_path(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase); + using namespace kodi::addon; + + char* str = + CAddonBase::m_interface->toKodi->get_addon_path(CAddonBase::m_interface->toKodi->kodiBase); std::string ret = str; - ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, str); + CAddonBase::m_interface->toKodi->free_string(CAddonBase::m_interface->toKodi->kodiBase, str); if (!append.empty()) { - if (append.at(0) != '\\' && - append.at(0) != '/') + if (append.at(0) != '\\' && append.at(0) != '/') #ifdef TARGET_WINDOWS ret.append("\\"); #else @@ -592,21 +439,21 @@ inline std::string GetAddonPath(const std::string& append = "") } return ret; } -} /* namespace kodi */ //------------------------------------------------------------------------------ //============================================================================== -namespace kodi { /// inline std::string GetBaseUserPath(const std::string& append = "") { - char* str = ::kodi::addon::CAddonBase::m_interface->toKodi->get_base_user_path(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase); + using namespace kodi::addon; + + char* str = CAddonBase::m_interface->toKodi->get_base_user_path( + CAddonBase::m_interface->toKodi->kodiBase); std::string ret = str; - ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, str); + CAddonBase::m_interface->toKodi->free_string(CAddonBase::m_interface->toKodi->kodiBase, str); if (!append.empty()) { - if (append.at(0) != '\\' && - append.at(0) != '/') + if (append.at(0) != '\\' && append.at(0) != '/') #ifdef TARGET_WINDOWS ret.append("\\"); #else @@ -616,54 +463,74 @@ inline std::string GetBaseUserPath(const std::string& append = "") } return ret; } -} /* namespace kodi */ //------------------------------------------------------------------------------ //============================================================================== -namespace kodi { /// inline std::string GetLibPath() { - return ::kodi::addon::CAddonBase::m_interface->libBasePath; + using namespace kodi::addon; + + return CAddonBase::m_interface->libBasePath; } -} /* namespace kodi */ //------------------------------------------------------------------------------ //============================================================================== -namespace kodi { +/// @ingroup cpp_kodi +/// @brief Add a message to Kodi's log. +/// +/// @param[in] loglevel The log level of the message. +/// @param[in] format The format of the message to pass to Kodi. +/// @param[in] ... Additional text to insert in format text +/// +/// +/// @note This method uses limited buffer (16k) for the formatted output. +/// So data, which will not fit into it, will be silently discarded. +/// +/// ---------------------------------------------------------------------------- +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// +/// kodi::Log(ADDON_LOG_ERROR, "%s: There is an error occurred!", __func__); +/// +/// ~~~~~~~~~~~~~ /// inline void Log(const AddonLog loglevel, const char* format, ...) { + using namespace kodi::addon; + char buffer[16384]; va_list args; va_start(args, format); - vsprintf(buffer, format, args); + vsnprintf(buffer, sizeof(buffer), format, args); va_end(args); - ::kodi::addon::CAddonBase::m_interface->toKodi->addon_log_msg(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, loglevel, buffer); + CAddonBase::m_interface->toKodi->addon_log_msg(CAddonBase::m_interface->toKodi->kodiBase, + loglevel, buffer); } -} /* namespace kodi */ //------------------------------------------------------------------------------ //============================================================================ -namespace kodi { /// inline bool CheckSettingString(const std::string& settingName, std::string& settingValue) { + using namespace kodi::addon; + char* buffer = nullptr; - bool ret = ::kodi::addon::CAddonBase::m_interface->toKodi->get_setting_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), &buffer); + bool ret = CAddonBase::m_interface->toKodi->get_setting_string( + CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), &buffer); if (buffer) { if (ret) settingValue = buffer; - ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, buffer); + CAddonBase::m_interface->toKodi->free_string(CAddonBase::m_interface->toKodi->kodiBase, buffer); } return ret; } -} /* namespace kodi */ //---------------------------------------------------------------------------- //============================================================================ -namespace kodi { /// inline std::string GetSettingString(const std::string& settingName) { @@ -671,31 +538,31 @@ inline std::string GetSettingString(const std::string& settingName) CheckSettingString(settingName, settingValue); return settingValue; } -} /* namespace kodi */ //---------------------------------------------------------------------------- //============================================================================ -namespace kodi { /// inline void SetSettingString(const std::string& settingName, const std::string& settingValue) { - ::kodi::addon::CAddonBase::m_interface->toKodi->set_setting_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), settingValue.c_str()); + using namespace kodi::addon; + + CAddonBase::m_interface->toKodi->set_setting_string(CAddonBase::m_interface->toKodi->kodiBase, + settingName.c_str(), settingValue.c_str()); } -} /* namespace kodi */ //---------------------------------------------------------------------------- //============================================================================ -namespace kodi { /// inline bool CheckSettingInt(const std::string& settingName, int& settingValue) { - return ::kodi::addon::CAddonBase::m_interface->toKodi->get_setting_int(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), &settingValue); + using namespace kodi::addon; + + return CAddonBase::m_interface->toKodi->get_setting_int(CAddonBase::m_interface->toKodi->kodiBase, + settingName.c_str(), &settingValue); } -} /* namespace kodi */ //---------------------------------------------------------------------------- //============================================================================ -namespace kodi { /// inline int GetSettingInt(const std::string& settingName) { @@ -703,31 +570,31 @@ inline int GetSettingInt(const std::string& settingName) CheckSettingInt(settingName, settingValue); return settingValue; } -} /* namespace kodi */ //---------------------------------------------------------------------------- //============================================================================ -namespace kodi { /// inline void SetSettingInt(const std::string& settingName, int settingValue) { - ::kodi::addon::CAddonBase::m_interface->toKodi->set_setting_int(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), settingValue); + using namespace kodi::addon; + + CAddonBase::m_interface->toKodi->set_setting_int(CAddonBase::m_interface->toKodi->kodiBase, + settingName.c_str(), settingValue); } -} /* namespace kodi */ //---------------------------------------------------------------------------- //============================================================================ -namespace kodi { /// inline bool CheckSettingBoolean(const std::string& settingName, bool& settingValue) { - return ::kodi::addon::CAddonBase::m_interface->toKodi->get_setting_bool(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), &settingValue); + using namespace kodi::addon; + + return CAddonBase::m_interface->toKodi->get_setting_bool( + CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), &settingValue); } -} /* namespace kodi */ //---------------------------------------------------------------------------- //============================================================================ -namespace kodi { /// inline bool GetSettingBoolean(const std::string& settingName) { @@ -735,31 +602,31 @@ inline bool GetSettingBoolean(const std::string& settingName) CheckSettingBoolean(settingName, settingValue); return settingValue; } -} /* namespace kodi */ //---------------------------------------------------------------------------- //============================================================================ -namespace kodi { /// inline void SetSettingBoolean(const std::string& settingName, bool settingValue) { - ::kodi::addon::CAddonBase::m_interface->toKodi->set_setting_bool(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), settingValue); + using namespace kodi::addon; + + CAddonBase::m_interface->toKodi->set_setting_bool(CAddonBase::m_interface->toKodi->kodiBase, + settingName.c_str(), settingValue); } -} /* namespace kodi */ //---------------------------------------------------------------------------- //============================================================================ -namespace kodi { /// inline bool CheckSettingFloat(const std::string& settingName, float& settingValue) { - return ::kodi::addon::CAddonBase::m_interface->toKodi->get_setting_float(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), &settingValue); + using namespace kodi::addon; + + return CAddonBase::m_interface->toKodi->get_setting_float( + CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), &settingValue); } -} /* namespace kodi */ //---------------------------------------------------------------------------- //============================================================================ -namespace kodi { /// inline float GetSettingFloat(const std::string& settingName) { @@ -767,21 +634,20 @@ inline float GetSettingFloat(const std::string& settingName) CheckSettingFloat(settingName, settingValue); return settingValue; } -} /* namespace kodi */ //---------------------------------------------------------------------------- //============================================================================ -namespace kodi { /// inline void SetSettingFloat(const std::string& settingName, float settingValue) { - ::kodi::addon::CAddonBase::m_interface->toKodi->set_setting_float(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), settingValue); + using namespace kodi::addon; + + CAddonBase::m_interface->toKodi->set_setting_float(CAddonBase::m_interface->toKodi->kodiBase, + settingName.c_str(), settingValue); } -} /* namespace kodi */ //---------------------------------------------------------------------------- //============================================================================ -namespace kodi { /// inline std::string TranslateAddonStatus(ADDON_STATUS status) { @@ -806,13 +672,10 @@ inline std::string TranslateAddonStatus(ADDON_STATUS status) } return "Unknown"; } -} /* namespace kodi */ //---------------------------------------------------------------------------- //============================================================================== -namespace kodi { -/// -/// \ingroup cpp_kodi +/// @ingroup cpp_kodi /// @brief Returns a function table to a named interface /// /// @return pointer to struct containing interface functions @@ -829,12 +692,16 @@ namespace kodi { /// ... /// ~~~~~~~~~~~~~ /// -inline void* GetInterface(const std::string &name, const std::string &version) +inline void* GetInterface(const std::string& name, const std::string& version) { - AddonToKodiFuncTable_Addon* toKodi = ::kodi::addon::CAddonBase::m_interface->toKodi; + using namespace kodi::addon; + + AddonToKodiFuncTable_Addon* toKodi = CAddonBase::m_interface->toKodi; return toKodi->get_interface(toKodi->kodiBase, name.c_str(), version.c_str()); } +//---------------------------------------------------------------------------- + } /* namespace kodi */ /*! addon creation macro @@ -846,17 +713,13 @@ inline void* GetInterface(const std::string &name, const std::string &version) * Becomes really cleaned up soon :D */ #define ADDONCREATOR(AddonClass) \ - extern "C" __declspec(dllexport) void get_addon(void* pAddon) {} \ - extern "C" __declspec(dllexport) ADDON_STATUS ADDON_Create(KODI_HANDLE addonInterface, void *unused) \ + extern "C" __declspec(dllexport) ADDON_STATUS ADDON_Create( \ + KODI_HANDLE addonInterface, const char* globalApiVersion, void* unused) \ { \ kodi::addon::CAddonBase::m_interface = static_cast(addonInterface); \ 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); \ + return static_cast(kodi::addon::CAddonBase::m_interface->addonBase) \ + ->Create(); \ } \ extern "C" __declspec(dllexport) void ADDON_Destroy() \ { \ @@ -866,7 +729,8 @@ inline void* GetInterface(const std::string &name, const std::string &version) { \ return kodi::addon::CAddonBase::ADDONBASE_GetStatus(); \ } \ - extern "C" __declspec(dllexport) ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue) \ + extern "C" __declspec(dllexport) ADDON_STATUS ADDON_SetSetting(const char* settingName, \ + const void* settingValue) \ { \ return kodi::addon::CAddonBase::ADDONBASE_SetSetting(settingName, settingValue); \ } \ @@ -878,6 +742,4 @@ inline void* GetInterface(const std::string &name, const std::string &version) { \ return kodi::addon::GetTypeMinVersion(type); \ } \ - AddonGlobalInterface* kodi::addon::CAddonBase::m_interface = nullptr; \ - std::string kodi::addon::CAddonBase::m_strGlobalApiVersion; - + AddonGlobalInterface* kodi::addon::CAddonBase::m_interface = nullptr; 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 8b57f7a419f24..6664e2be196d2 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/Filesystem.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/Filesystem.h @@ -9,1630 +9,2265 @@ #pragma once #include "AddonBase.h" +#include "c-api/filesystem.h" +#ifdef __cplusplus + +#include #include #include -#if !defined(_WIN32) - #include - #if !defined(__stat64) - #if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) - #define __stat64 stat - #else - #define __stat64 stat64 - #endif - #endif -#endif -#ifdef _WIN32 // windows -#ifndef _SSIZE_T_DEFINED - typedef intptr_t ssize_t; - #define _SSIZE_T_DEFINED -#endif // !_SSIZE_T_DEFINED -#endif - -#ifndef S_ISDIR - #define S_ISDIR(mode) ((((mode)) & 0170000) == (0040000)) -#endif - -#ifndef S_ISLNK - #define S_ISLNK(mode) ((((mode)) & 0170000) == (0120000)) -#endif - -/* - * For interface between add-on and kodi. - * - * This structure defines the addresses of functions stored inside Kodi which - * are then available for the add-on to call - * - * All function pointers there are used by the C++ interface functions below. - * You find the set of them on xbmc/addons/interfaces/General.cpp - * - * Note: For add-on development itself this is not needed - */ -extern "C" +namespace kodi +{ +namespace vfs { - struct VFSProperty - { - char* name; - char* val; - }; - - struct VFSDirEntry - { - char* label; //!< item label - char* title; //!< item title - char* path; //!< item path - unsigned int num_props; //!< Number of properties attached to item - VFSProperty* properties; //!< Properties - time_t date_time; //!< file creation date & time - bool folder; //!< Item is a folder - uint64_t size; //!< Size of file represented by item - }; - - typedef struct AddonToKodiFuncTable_kodi_filesystem - { - bool (*can_open_directory)(void* kodiBase, const char* url); - bool (*create_directory)(void* kodiBase, const char* path); - bool (*remove_directory)(void* kodiBase, const char* path); - bool (*directory_exists)(void* kodiBase, const char* path); - bool (*get_directory)(void* kodiBase, const char* path, const char* mask, VFSDirEntry** items, unsigned int* num_items); - void (*free_directory)(void* kodiBase, VFSDirEntry* items, unsigned int num_items); - - bool (*file_exists)(void* kodiBase, const char *filename, bool useCache); - int (*stat_file)(void* kodiBase, const char *filename, struct __stat64* buffer); - bool (*delete_file)(void* kodiBase, const char *filename); - bool (*rename_file)(void* kodiBase, const char *filename, const char *newFileName); - bool (*copy_file)(void* kodiBase, const char *filename, const char *dest); - - char* (*get_file_md5)(void* kodiBase, const char* filename); - char* (*get_cache_thumb_name)(void* kodiBase, const char* filename); - char* (*make_legal_filename)(void* kodiBase, const char* filename); - char* (*make_legal_path)(void* kodiBase, const char* path); - char* (*translate_special_protocol)(void* kodiBase, const char *strSource); - - void* (*open_file)(void* kodiBase, const char* filename, unsigned int flags); - void* (*open_file_for_write)(void* kodiBase, const char* filename, bool overwrite); - ssize_t (*read_file)(void* kodiBase, void* file, void* ptr, size_t size); - bool (*read_file_string)(void* kodiBase, void* file, char *szLine, int iLineLength); - ssize_t (*write_file)(void* kodiBase, void* file, const void* ptr, size_t size); - void (*flush_file)(void* kodiBase, void* file); - int64_t (*seek_file)(void* kodiBase, void* file, int64_t position, int whence); - int (*truncate_file)(void* kodiBase, void* file, int64_t size); - int64_t (*get_file_position)(void* kodiBase, void* file); - int64_t (*get_file_length)(void* kodiBase, void* file); - double (*get_file_download_speed)(void* kodiBase, void* file); - void (*close_file)(void* kodiBase, void* file); - int (*get_file_chunk_size)(void* kodiBase, void* file); - char** (*get_property_values)(void* kodiBase, void* file, int type, const char *name, int *numValues); - - void* (*curl_create)(void* kodiBase, const char* url); - 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); - } AddonToKodiFuncTable_kodi_filesystem; - -} /* extern "C" */ +//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ +// Main page text for filesystem group by Doxygen. +//{{{ //============================================================================== /// -/// \defgroup cpp_kodi_vfs Interface - kodi::vfs -/// \ingroup cpp -/// @brief **Virtual filesystem functions** +/// @defgroup cpp_kodi_vfs Interface - kodi::vfs +/// @ingroup cpp +/// @brief **Virtual filesystem functions**\n +/// Offers classes and functions for access to the Virtual File Server (VFS) +/// which you can use to manipulate files and folders. /// +/// This system allow the use of ["Special Protocol"](https://kodi.wiki/view/Special_protocol) +/// where is Kodi's solution to platform dependent directories. Common directory +/// names are assigned a `special://[name]` path which is passed around +/// inside Kodi and then translated to the platform specific path before the +/// operating system sees it. This helps keep most of the platform mess +/// centralized in the code.\n +/// To become a correct path back can be @ref TranslateSpecialProtocol() used. /// -/// It has the header \ref Filesystem.h "#include " be +/// It has the header @ref Filesystem.h "#include " be /// included to enjoy it. /// //------------------------------------------------------------------------------ //============================================================================== -/// \defgroup cpp_kodi_vfs_Defs Definitions, structures and enumerators -/// \ingroup cpp_kodi_vfs -/// @brief **Virtual file Server definition values** +/// @defgroup cpp_kodi_vfs_Defs Definitions, structures and enumerators +/// @ingroup cpp_kodi_vfs +/// @brief **Virtual file Server definition values**\n +/// All to VFS system functions associated data structures. +/// //------------------------------------------------------------------------------ //============================================================================== +/// @defgroup cpp_kodi_vfs_Directory 1. Directory functions +/// @ingroup cpp_kodi_vfs +/// @brief **Globally available directories related functions**\n +/// Used to perform typical operations with it. /// -/// @ingroup cpp_kodi_vfs_Defs -/// Flags to define way how file becomes opened with kodi::vfs::CFile::OpenFile() +//------------------------------------------------------------------------------ + +//============================================================================== +/// @defgroup cpp_kodi_vfs_File 2. File functions +/// @ingroup cpp_kodi_vfs +/// @brief **Globally available file related functions**\n +/// Used to perform typical operations with it. +/// +//------------------------------------------------------------------------------ + +//============================================================================== +/// @defgroup cpp_kodi_vfs_General 3. General functions +/// @ingroup cpp_kodi_vfs +/// @brief **Other globally available functions**\n +/// Used to perform typical operations with it. /// -/// The values can be used together, e.g. `file.Open("myfile", READ_TRUNCATED | READ_CHUNKED);` +//------------------------------------------------------------------------------ + +//}}} + +//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ +// "C++" related filesystem definitions +//{{{ + +//============================================================================== +/// @defgroup cpp_kodi_vfs_Defs_FileStatus class FileStatus +/// @ingroup cpp_kodi_vfs_Defs +/// @brief **File information status**\n +/// Used on kodi::vfs::StatFile() to get detailed information about a file. /// -typedef enum OpenFileFlags +//@{ +class FileStatus : public kodi::addon::CStructHdl { - /// indicate that caller can handle truncated reads, where function returns - /// before entire buffer has been filled - READ_TRUNCATED = 0x01, +public: + /*! \cond PRIVATE */ + FileStatus() { memset(m_cStructure, 0, sizeof(STAT_STRUCTURE)); } + FileStatus(const FileStatus& channel) : CStructHdl(channel) {} + FileStatus(const STAT_STRUCTURE* channel) : CStructHdl(channel) {} + FileStatus(STAT_STRUCTURE* channel) : CStructHdl(channel) {} + /*! \endcond */ + + /// @defgroup cpp_kodi_vfs_Defs_FileStatus_Help *Value Help* + /// @ingroup cpp_kodi_vfs_Defs_FileStatus + /// ---------------------------------------------------------------------------- + /// + /// The following table contains values that can be set with @ref cpp_kodi_vfs_Defs_FileStatus : + /// | Name | Type | Set call | Get call + /// |------|------|----------|---------- + /// | **ID of device containing file** | `uint32_t` | @ref FileStatus::SetDeviceId "SetDeviceId" | @ref FileStatus::GetDeviceId "GetDeviceId" + /// | **Total size, in bytes** | `uint64_t` | @ref FileStatus::SetSize "SetSize" | @ref FileStatus::GetSize "GetSize" + /// | **Time of last access** | `time_t` | @ref FileStatus::SetAccessTime "SetAccessTime" | @ref FileStatus::GetAccessTime "GetAccessTime" + /// | **Time of last modification** | `time_t` | @ref FileStatus::SetModificationTime "SetModificationTime" | @ref FileStatus::GetModificationTime "GetModificationTime" + /// | **Time of last status change** | `time_t` | @ref FileStatus::SetStatusTime "SetStatusTime" | @ref FileStatus::GetStatusTime "GetStatusTime" + /// | **Stat url is a directory** | `bool` | @ref FileStatus::SetIsDirectory "SetIsDirectory" | @ref FileStatus::GetIsDirectory "GetIsDirectory" + /// | **Stat url as a symbolic link** | `bool` | @ref FileStatus::SetIsSymLink "SetIsSymLink" | @ref FileStatus::GetIsSymLink "GetIsSymLink" + /// + + /// @addtogroup cpp_kodi_vfs_Defs_FileStatus + /// @copydetails cpp_kodi_vfs_Defs_FileStatus_Help + //@{ + + /// @brief Set ID of device containing file. + void SetDeviceId(uint32_t deviceId) { m_cStructure->deviceId = deviceId; } + + /// @brief Get ID of device containing file. + uint32_t GetDeviceId() const { return m_cStructure->deviceId; } - /// indicate that that caller support read in the minimum defined chunk size, - /// this disables internal cache then - READ_CHUNKED = 0x02, + /// @brief Set total size, in bytes. + void SetSize(uint64_t size) { m_cStructure->size = size; } - /// use cache to access this file - READ_CACHED = 0x04, + /// @brief Get total size, in bytes. + uint64_t GetSize() const { return m_cStructure->size; } - /// open without caching. regardless to file type - READ_NO_CACHE = 0x08, + /// @brief Set time of last access. + void SetAccessTime(time_t accessTime) { m_cStructure->accessTime = accessTime; } - /// calcuate bitrate for file while reading - READ_BITRATE = 0x10, + /// @brief Get time of last access. + time_t GetAccessTime() const { return m_cStructure->accessTime; } - /// indicate to the caller we will seek between multiple streams in the file - /// frequently - READ_MULTI_STREAM = 0x20, + /// @brief Set time of last modification. + void SetModificationTime(time_t modificationTime) + { + m_cStructure->modificationTime = modificationTime; + } + + /// @brief Get time of last modification. + time_t GetModificationTime() const { return m_cStructure->modificationTime; } + + /// @brief Set time of last status change. + void SetStatusTime(time_t statusTime) { m_cStructure->statusTime = statusTime; } - /// indicate to the caller file is audio and/or video (and e.g. may grow) - READ_AUDIO_VIDEO = 0x40, + /// @brief Get time of last status change. + time_t GetStatusTime() const { return m_cStructure->statusTime; } - /// indicate that caller will do write operations before reading - READ_AFTER_WRITE = 0x80, + /// @brief Set the stat url is a directory. + void SetIsDirectory(bool isDirectory) { m_cStructure->isDirectory = isDirectory; } - /// indicate that caller want to reopen a file if its already open - READ_REOPEN = 0x100 -} OpenFileFlags; + /// @brief The stat url is a directory if returns true. + bool GetIsDirectory() const { return m_cStructure->isDirectory; } + + /// @brief Set stat url as a symbolic link. + void SetIsSymLink(bool isSymLink) { m_cStructure->isSymLink = isSymLink; } + + /// @brief Get stat url is a symbolic link. + bool GetIsSymLink() const { return m_cStructure->isSymLink; } + + //@} +}; +//@} //------------------------------------------------------------------------------ //============================================================================== -/// \ingroup cpp_kodi_vfs_Defs -/// @brief CURL message types -/// -/// Used on kodi::vfs::CFile::CURLAddOption() +/// @defgroup cpp_kodi_vfs_Defs_CacheStatus class CacheStatus +/// @ingroup cpp_kodi_vfs_Defs +/// @brief **Cache information status**\n +/// Used on kodi::vfs::CFile::IoControlGetCacheStatus() to get running cache +/// status of proccessed stream. /// -typedef enum CURLOptiontype +//@{ +class CacheStatus : public kodi::addon::CStructHdl { - /// Set a general option - ADDON_CURL_OPTION_OPTION, - - /// Set a protocol option - /// - /// The following names for *ADDON_CURL_OPTION_PROTOCOL* are possible: - /// - /// | Option name | Description - /// |---------------------------:|:---------------------------------------------------------- - /// | accept-charset | Set the "accept-charset" header - /// | acceptencoding or encoding | Set the "accept-encoding" header - /// | active-remote | Set the "active-remote" header - /// | auth | Set the authentication method. Possible values: any, anysafe, digest, ntlm - /// | connection-timeout | Set the connection timeout in seconds - /// | cookie | Set the "cookie" header - /// | customrequest | Set a custom HTTP request like DELETE - /// | noshout | Set to true if kodi detects a stream as shoutcast by mistake. - /// | postdata | Set the post body (value needs to be base64 encoded). (Implicitly sets the request to POST) - /// | referer | Set the "referer" header - /// | user-agent | Set the "user-agent" header - /// | seekable | Set the stream seekable. 1: enable, 0: disable - /// | sslcipherlist | Set list of accepted SSL ciphers. - /// - ADDON_CURL_OPTION_PROTOCOL, - - /// Set User and password - ADDON_CURL_OPTION_CREDENTIALS, - - /// Add a Header - ADDON_CURL_OPTION_HEADER -} CURLOptiontype; +public: + /*! \cond PRIVATE */ + CacheStatus() { memset(m_cStructure, 0, sizeof(VFS_CACHE_STATUS_DATA)); } + CacheStatus(const CacheStatus& channel) : CStructHdl(channel) {} + CacheStatus(const VFS_CACHE_STATUS_DATA* channel) : CStructHdl(channel) {} + CacheStatus(VFS_CACHE_STATUS_DATA* channel) : CStructHdl(channel) {} + /*! \endcond */ + + /// @defgroup cpp_kodi_vfs_Defs_CacheStatus_Help *Value Help* + /// @ingroup cpp_kodi_vfs_Defs_CacheStatus + /// ---------------------------------------------------------------------------- + /// + /// The following table contains values that can be set with @ref cpp_kodi_vfs_Defs_CacheStatus : + /// | Name | Type | Set call | Get call + /// |------|------|----------|---------- + /// | **Number of bytes cached** | `uint64_t` | @ref CacheStatus::SetForward "SetForward" | @ref CacheStatus::GetForward "GetForward" + /// | **Maximum number of bytes per second** | `unsigned int` | @ref CacheStatus::SetMaxRate "SetMaxRate" | @ref CacheStatus::GetMaxRate "GetMaxRate" + /// | **Average read rate from source file** | `unsigned int` | @ref CacheStatus::SetCurrentRate "SetCurrentRate" | @ref CacheStatus::GetCurrentRate "GetCurrentRate" + /// | **Cache low speed condition detected** | `bool` | @ref CacheStatus::SetLowspeed "SetLowspeed" | @ref CacheStatus::GetLowspeed "GetLowspeed" + /// + + /// @addtogroup cpp_kodi_vfs_Defs_CacheStatus + /// @copydetails cpp_kodi_vfs_Defs_CacheStatus_Help + //@{ + + /// @brief Set number of bytes cached forward of current position. + void SetForward(uint64_t forward) { m_cStructure->forward = forward; } + + /// @brief Get number of bytes cached forward of current position. + uint64_t GetForward() { return m_cStructure->forward; } + + /// @brief Set maximum number of bytes per second cache is allowed to fill. + void SetMaxRate(unsigned int maxrate) { m_cStructure->maxrate = maxrate; } + + /// @brief Set maximum number of bytes per second cache is allowed to fill. + unsigned int GetMaxRate() { return m_cStructure->maxrate; } + + /// @brief Set average read rate from source file since last position change. + void SetCurrentRate(unsigned int currate) { m_cStructure->currate = currate; } + + /// @brief Get average read rate from source file since last position change. + unsigned int GetCurrentRate() { return m_cStructure->currate; } + + /// @brief Set cache low speed condition detected. + void SetLowspeed(bool lowspeed) { m_cStructure->lowspeed = lowspeed; } + + /// @brief Get cache low speed condition detected. + bool GetLowspeed() { return m_cStructure->lowspeed; } + + //@} +}; +//@} //------------------------------------------------------------------------------ //============================================================================== -/// \ingroup cpp_kodi_vfs_Defs -/// @brief CURL message types -/// -/// Used on kodi::vfs::CFile::GetPropertyValue() and kodi::vfs::CFile::GetPropertyValues() +/// @defgroup cpp_kodi_vfs_Defs_HttpHeader class HttpHeader +/// @ingroup cpp_kodi_vfs_Defs +/// @brief **HTTP header information**\n +/// The class used to access HTTP header information and get his information. /// -typedef enum FilePropertyTypes -{ - /// Get protocol response line - ADDON_FILE_PROPERTY_RESPONSE_PROTOCOL, - /// Get a response header - ADDON_FILE_PROPERTY_RESPONSE_HEADER, - /// Get file content type - ADDON_FILE_PROPERTY_CONTENT_TYPE, - /// Get file content charset - ADDON_FILE_PROPERTY_CONTENT_CHARSET, - /// Get file mime type - ADDON_FILE_PROPERTY_MIME_TYPE, - /// Get file effective URL (last one if redirected) - ADDON_FILE_PROPERTY_EFFECTIVE_URL -} FilePropertyTypes; -//------------------------------------------------------------------------------ - -//============================================================================ +/// Used on @ref kodi::vfs::GetHttpHeader(). /// -/// \ingroup cpp_kodi_vfs_Defs -/// @brief File information status +/// ---------------------------------------------------------------------------- /// -/// Used on kodi::vfs::StatFile(), all of these calls return a this stat -/// structure, which contains the following fields: +/// @copydetails cpp_kodi_vfs_Defs_HttpHeader_Help /// -struct STAT_STRUCTURE -{ - /// ID of device containing file - uint32_t deviceId; - /// Total size, in bytes - uint64_t size; -#ifdef TARGET_WINDOWS - /// Time of last access - __time64_t accessTime; - /// Time of last modification - __time64_t modificationTime; - /// Time of last status change - __time64_t statusTime; -#else - /// Time of last access - timespec accessTime; - /// Time of last modification - timespec modificationTime; - /// Time of last status change - timespec statusTime; -#endif - /// The stat url is a directory - bool isDirectory; - /// The stat url is a symbolic link - bool isSymLink; -}; -//------------------------------------------------------------------------------ - -namespace kodi -{ -namespace vfs +///@{ +class HttpHeader { - - //============================================================================ - /// - /// \defgroup cpp_kodi_vfs_CDirEntry class CDirEntry - /// \ingroup cpp_kodi_vfs - /// - /// @brief **Virtual file server directory entry** - /// - /// This class is used as an entry for files and folders in - /// kodi::vfs::GetDirectory(). - /// - /// - /// ------------------------------------------------------------------------ - /// - /// **Example:** - /// ~~~~~~~~~~~~~{.cpp} - /// #include - /// - /// ... - /// - /// std::vector items; - /// kodi::vfs::GetDirectory("special://temp", "", items); - /// - /// fprintf(stderr, "Directory have %lu entries\n", items.size()); - /// for (unsigned long i = 0; i < items.size(); i++) - /// { - /// char buff[20]; - /// time_t now = items[i].DateTime(); - /// strftime(buff, 20, "%Y-%m-%d %H:%M:%S", gmtime(&now)); - /// fprintf(stderr, " - %04lu -- Folder: %s -- Name: %s -- Path: %s -- Time: %s\n", - /// i+1, - /// items[i].IsFolder() ? "yes" : "no ", - /// items[i].Label().c_str(), - /// items[i].Path().c_str(), - /// buff); - /// } - /// ~~~~~~~~~~~~~ - /// - /// It has the header \ref Filesystem.h "#include " be included - /// to enjoy it. +public: + //========================================================================== + /// @brief Http header parser class constructor. /// - //@{ - class CDirEntry + HttpHeader() { - public: - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs_CDirEntry - /// @brief Constructor for VFS directory entry - /// - /// @param[in] label [opt] Name to use for entry - /// @param[in] path [opt] Used path of the entry - /// @param[in] folder [opt] If set entry used as folder - /// @param[in] size [opt] If used as file, his size defined there - /// @param[in] dateTime [opt] Date time of the entry - /// - CDirEntry(const std::string& label = "", - const std::string& path = "", - bool folder = false, - int64_t size = -1, - time_t dateTime = 0): - m_label(label), - m_path(path), - m_folder(folder), - m_size(size), - m_dateTime(dateTime) - { - } - //---------------------------------------------------------------------------- - - //============================================================================ - // @note Not for addon development itself needed, thats why below is - // disabled for doxygen! - // - // @ingroup cpp_kodi_vfs_CDirEntry - // @brief Constructor to create own copy - // - // @param[in] dirEntry pointer to own class type - // - explicit CDirEntry(const VFSDirEntry& dirEntry) : - m_label(dirEntry.label ? dirEntry.label : ""), - m_path(dirEntry.path ? dirEntry.path : ""), - m_folder(dirEntry.folder), - m_size(dirEntry.size), - m_dateTime(dirEntry.date_time) - { - } - //---------------------------------------------------------------------------- - - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs_CDirEntry - /// @brief Get the directory entry name - /// - /// @return Name of the entry - /// - const std::string& Label(void) const { return m_label; } - //---------------------------------------------------------------------------- - - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs_CDirEntry - /// @brief Get the optional title of entry - /// - /// @return Title of the entry, if exists - /// - const std::string& Title(void) const { return m_title; } - //---------------------------------------------------------------------------- - - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs_CDirEntry - /// @brief Get the path of the entry - /// - /// @return File system path of the entry - /// - const std::string& Path(void) const { return m_path; } - //---------------------------------------------------------------------------- - - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs_CDirEntry - /// @brief Used to check entry is folder - /// - /// @return true if entry is a folder - /// - bool IsFolder(void) const { return m_folder; } - //---------------------------------------------------------------------------- - - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs_CDirEntry - /// @brief If file, the size of the file - /// - /// @return Defined file size - /// - int64_t Size(void) const { return m_size; } - //---------------------------------------------------------------------------- - - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs_CDirEntry - /// @brief Get file time and date for a new entry - /// - /// @return The with time_t defined date and time of file - /// - time_t DateTime() { return m_dateTime; } - //---------------------------------------------------------------------------- - - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs_CDirEntry - /// @brief Set the label name - /// - /// @param[in] label name of entry - /// - void SetLabel(const std::string& label) { m_label = label; } - //---------------------------------------------------------------------------- - - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs_CDirEntry - /// @brief Set the title name - /// - /// @param[in] title title name of entry - /// - void SetTitle(const std::string& title) { m_title = title; } - //---------------------------------------------------------------------------- - - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs_CDirEntry - /// @brief Set the path of the entry - /// - /// @param[in] path path of entry - /// - void SetPath(const std::string& path) { m_path = path; } - //---------------------------------------------------------------------------- - - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs_CDirEntry - /// @brief Set the entry defined as folder - /// - /// @param[in] folder If true becomes entry defined as folder - /// - void SetFolder(bool folder) { m_folder = folder; } - //---------------------------------------------------------------------------- - - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs_CDirEntry - /// @brief Set a file size for a new entry - /// - /// @param[in] size Size to set for dir entry - /// - void SetSize(int64_t size) { m_size = size; } - //---------------------------------------------------------------------------- - - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs_CDirEntry - /// @brief Set file time and date for a new entry - /// - /// @param[in] dateTime The with time_t defined date and time of file - /// - void SetDateTime(time_t dateTime) { m_dateTime = dateTime; } - //---------------------------------------------------------------------------- - - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs_CDirEntry - /// @brief Add a by string defined property entry to directory entry - /// - /// @note A property can be used to add some special information about a file - /// or directory entry, this can be used on other places to do the right work - /// of them. - /// - /// @param[in] id Identification name of property - /// @param[in] value The property value to add by given id - /// - void AddProperty(const std::string& id, const std::string& value) { m_properties[id] = value; } - //---------------------------------------------------------------------------- - - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs_CDirEntry - /// @brief Clear all present properties - /// - void ClearProperties() { m_properties.clear(); } - //---------------------------------------------------------------------------- - - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs_CDirEntry - /// @brief Get the present properties list on directory entry - /// - /// @return map with all present properties - /// - const std::map& GetProperties() const { return m_properties; } - //---------------------------------------------------------------------------- - - private: - std::string m_label; - std::string m_title; - std::string m_path; - std::map m_properties; - bool m_folder; - int64_t m_size; - time_t m_dateTime; - }; - //@} - //---------------------------------------------------------------------------- + using namespace ::kodi::addon; - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs - /// @brief Make a directory - /// - /// The kodi::vfs::CreateDirectory() function shall create a - /// new directory with name path. - /// - /// The newly created directory shall be an empty directory. - /// - /// @param[in] path Path to the directory. - /// @return Upon successful completion, CreateDirectory() shall return true. - /// Otherwise false shall be returned, no directory shall be created. - /// - /// - /// ------------------------------------------------------------------------- - /// - /// **Example:** - /// ~~~~~~~~~~~~~{.cpp} - /// #include - /// ... - /// std::string directory = "C:\\my_dir"; - /// bool ret = kodi::vfs::CreateDirectory(directory); - /// fprintf(stderr, "Directory '%s' successfull created: %s\n", directory.c_str(), ret ? "yes" : "no"); - /// ... - /// ~~~~~~~~~~~~~ - /// - inline bool CreateDirectory(const std::string& path) - { - return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->create_directory(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, path.c_str()); + CAddonBase::m_interface->toKodi->kodi_filesystem->http_header_create( + CAddonBase::m_interface->toKodi->kodiBase, &m_handle); } - //---------------------------------------------------------------------------- + //-------------------------------------------------------------------------- - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs - /// @brief Verifying the Existence of a Directory + //========================================================================== + /// @brief Class destructor. /// - /// The kodi::vfs::DirectoryExists() method determines whether - /// a specified folder exists. - /// - /// @param[in] path Path to the directory. - /// @return True when it exists, false otherwise. - /// - /// - /// ------------------------------------------------------------------------- - /// - /// **Example:** - /// ~~~~~~~~~~~~~{.cpp} - /// #include - /// ... - /// std::string directory = "C:\\my_dir"; - /// bool ret = kodi::vfs::DirectoryExists(directory); - /// fprintf(stderr, "Directory '%s' present: %s\n", directory.c_str(), ret ? "yes" : "no"); - /// ... - /// ~~~~~~~~~~~~~ - /// - inline bool DirectoryExists(const std::string& path) + ~HttpHeader() { - return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->directory_exists(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, path.c_str()); + using namespace ::kodi::addon; + + CAddonBase::m_interface->toKodi->kodi_filesystem->http_header_free( + CAddonBase::m_interface->toKodi->kodiBase, &m_handle); } - //---------------------------------------------------------------------------- + //-------------------------------------------------------------------------- - //============================================================================ + /// @defgroup cpp_kodi_vfs_Defs_HttpHeader_Help *Value Help* + /// @ingroup cpp_kodi_vfs_Defs_HttpHeader /// - /// @ingroup cpp_kodi_vfs - /// @brief Removes a directory. + /// The following table contains values that can be get with @ref cpp_kodi_vfs_Defs_HttpHeader : + /// | Description | Type | Get call + /// |-------------|------|------------ + /// | **Get the value associated with this parameter of these HTTP headers** | `std::string` | @ref HttpHeader::GetValue "GetValue" + /// | **Get the values as list associated with this parameter of these HTTP headers** | `std::vector` | @ref HttpHeader::GetValues "GetValues" + /// | **Get the full header string associated with these HTTP headers** | `std::string` | @ref HttpHeader::GetHeader "GetHeader" + /// | **Get the mime type associated with these HTTP headers** | `std::string` | @ref HttpHeader::GetMimeType "GetMimeType" + /// | **Get the charset associated with these HTTP headers** | `std::string` | @ref HttpHeader::GetCharset "GetCharset" + /// | **The protocol line associated with these HTTP headers** | `std::string` | @ref HttpHeader::GetProtoLine "GetProtoLine" /// - /// The kodi::vfs::RemoveDirectory() function shall remove a - /// directory whose name is given by path. - /// - /// @param[in] path Path to the directory. - /// @return Upon successful completion, the function RemoveDirectory() shall - /// return true. Otherwise, false shall be returned, and errno set - /// to indicate the error. If false is returned, the named directory - /// shall not be changed. - /// - /// - /// ------------------------------------------------------------------------- + + /// @addtogroup cpp_kodi_vfs_Defs_HttpHeader + ///@{ + + //========================================================================== + /// @brief Get the value associated with this parameter of these HTTP + /// headers. /// - /// **Example:** - /// ~~~~~~~~~~~~~{.cpp} - /// #include - /// ... - /// bool ret = kodi::vfs::RemoveDirectory("C:\\my_dir"); - /// ... - /// ~~~~~~~~~~~~~ + /// @param[in] param The name of the parameter a value is required for + /// @return The value found /// - inline bool RemoveDirectory(const std::string& path) + std::string GetValue(const std::string& param) const { - return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->remove_directory(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, path.c_str()); + using namespace ::kodi::addon; + + if (!m_handle.handle) + return ""; + + std::string protoLine; + char* string = m_handle.get_value(CAddonBase::m_interface->toKodi->kodiBase, m_handle.handle, + param.c_str()); + if (string != nullptr) + { + protoLine = string; + CAddonBase::m_interface->toKodi->free_string(CAddonBase::m_interface->toKodi->kodiBase, + string); + } + return protoLine; } - //---------------------------------------------------------------------------- + //-------------------------------------------------------------------------- - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs - /// @brief Lists a directory. - /// - /// Return the list of files and directories which have been found in the - /// specified directory and which respect the given constraint. - /// - /// It can handle the normal OS dependent paths and also the special virtual - /// filesystem from Kodi what starts with \b special://. - /// - /// @param[in] path The path in which the files and directories are located. - /// @param[in] mask Mask to filter out requested files, e.g. "*.avi|*.mpg" to - /// files with this ending. - /// @param[out] items The returned list directory entries. - /// @return True if listing was successful, false otherwise. - /// + //========================================================================== + /// @brief Get the values as list associated with this parameter of these + /// HTTP headers. /// - /// ------------------------------------------------------------------------- + /// @param[in] param The name of the parameter values are required for + /// @return The values found /// - /// **Example:** - /// ~~~~~~~~~~~~~{.cpp} - /// #include - /// - /// std::vector items; - /// kodi::vfs::GetDirectory("special://temp", "", items); - /// - /// fprintf(stderr, "Directory have %lu entries\n", items.size()); - /// for (unsigned long i = 0; i < items.size(); i++) - /// { - /// fprintf(stderr, " - %04lu -- Folder: %s -- Name: %s -- Path: %s\n", - /// i+1, - /// items[i].IsFolder() ? "yes" : "no ", - /// items[i].Label().c_str(), - /// items[i].Path().c_str()); - /// } - /// ~~~~~~~~~~~~~ - inline bool GetDirectory(const std::string& path, const std::string& mask, std::vector& items) + std::vector GetValues(const std::string& param) const { - VFSDirEntry* dir_list = nullptr; - unsigned int num_items = 0; - if (::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_directory(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, path.c_str(), mask.c_str(), &dir_list, &num_items)) + using namespace kodi::addon; + + if (!m_handle.handle) + return std::vector(); + + int numValues; + char** res(m_handle.get_values(CAddonBase::m_interface->toKodi->kodiBase, m_handle.handle, + param.c_str(), &numValues)); + if (res) { - if (dir_list) + std::vector vecReturn; + for (int i = 0; i < numValues; ++i) { - for (unsigned int i = 0; i < num_items; ++i) - items.emplace_back(dir_list[i]); - - ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->free_directory(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, dir_list, num_items); + vecReturn.emplace_back(res[i]); } - - return true; + CAddonBase::m_interface->toKodi->free_string_array(CAddonBase::m_interface->toKodi->kodiBase, + res, numValues); + return vecReturn; } - return false; + return std::vector(); } - //---------------------------------------------------------------------------- + //-------------------------------------------------------------------------- - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs - /// @brief Retrieve MD5sum of a file + //========================================================================== + /// @brief Get the full header string associated with these HTTP headers. /// - /// @param[in] path path to the file to MD5sum - /// @return md5 sum of the file + /// @return The header as a string /// - /// - /// ------------------------------------------------------------------------- - /// - /// **Example:** - /// ~~~~~~~~~~~~~{.cpp} - /// #include - /// #include - /// ... - /// std::string md5; - /// std::string filename; - /// if (kodi::gui::DialogFileBrowser::ShowAndGetFile("local", "*.avi|*.mpg|*.mp4", - /// "Test File selection to get MD5", - /// filename)) - /// { - /// md5 = kodi::vfs::GetFileMD5(filename); - /// fprintf(stderr, "MD5 of file '%s' is %s\n", md5.c_str(), filename.c_str()); - /// } - /// ~~~~~~~~~~~~~ - /// - inline std::string GetFileMD5(const std::string& path) + std::string GetHeader() const { - std::string strReturn; - char* strMd5 = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_md5(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, path.c_str()); - if (strMd5 != nullptr) + using namespace ::kodi::addon; + + if (!m_handle.handle) + return ""; + + std::string header; + char* string = m_handle.get_header(CAddonBase::m_interface->toKodi->kodiBase, m_handle.handle); + if (string != nullptr) { - if (std::strlen(strMd5)) - strReturn = strMd5; - ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, strMd5); + header = string; + CAddonBase::m_interface->toKodi->free_string(CAddonBase::m_interface->toKodi->kodiBase, + string); } - return strReturn; + return header; } - //---------------------------------------------------------------------------- + //-------------------------------------------------------------------------- - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs - /// @brief Returns a thumb cache filename + //========================================================================== + /// @brief Get the mime type associated with these HTTP headers. /// - /// @param[in] filename path to file - /// @return cache filename + /// @return The mime type /// - /// - /// ------------------------------------------------------------------------ - /// - /// **Example:** - /// ~~~~~~~~~~~~~{.cpp} - /// #include - /// #include - /// ... - /// std::string thumb; - /// std::string filename; - /// if (kodi::gui::DialogFileBrowser::ShowAndGetFile("local", "*.avi|*.mpg|*.mp4", - /// "Test File selection to get Thumnail", - /// filename)) - /// { - /// thumb = kodi::vfs::GetCacheThumbName(filename); - /// fprintf(stderr, "Thumb name of file '%s' is %s\n", thumb.c_str(), filename.c_str()); - /// } - /// ~~~~~~~~~~~~~ - /// - inline std::string GetCacheThumbName(const std::string& filename) + std::string GetMimeType() const { - std::string strReturn; - char* strThumbName = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_cache_thumb_name(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str()); - if (strThumbName != nullptr) + using namespace ::kodi::addon; + + if (!m_handle.handle) + return ""; + + std::string protoLine; + char* string = + m_handle.get_mime_type(CAddonBase::m_interface->toKodi->kodiBase, m_handle.handle); + if (string != nullptr) { - if (std::strlen(strThumbName)) - strReturn = strThumbName; - ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, strThumbName); + protoLine = string; + CAddonBase::m_interface->toKodi->free_string(CAddonBase::m_interface->toKodi->kodiBase, + string); } - return strReturn; + return protoLine; } - //---------------------------------------------------------------------------- + //-------------------------------------------------------------------------- - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs - /// @brief Make filename valid - /// - /// Function to replace not valid characters with '_'. It can be also - /// compared with original before in a own loop until it is equal - /// (no invalid characters). - /// - /// @param[in] filename Filename to check and fix - /// @return The legal filename - /// - /// - /// ------------------------------------------------------------------------ + //========================================================================== + /// @brief Get the charset associated with these HTTP headers. /// - /// **Example:** - /// ~~~~~~~~~~~~~{.cpp} - /// #include - /// ... - /// std::string fileName = "///\\jk???lj????.mpg"; - /// std::string legalName = kodi::vfs::MakeLegalFileName(fileName); - /// fprintf(stderr, "Legal name of '%s' is '%s'\n", fileName.c_str(), legalName.c_str()); + /// @return The charset /// - /// /* Returns as legal: 'jk___lj____.mpg' */ - /// ~~~~~~~~~~~~~ - /// - inline std::string MakeLegalFileName(const std::string& filename) + std::string GetCharset() const { - std::string strReturn; - char* strLegalFileName = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->make_legal_filename(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str()); - if (strLegalFileName != nullptr) + using namespace ::kodi::addon; + + if (!m_handle.handle) + return ""; + + std::string protoLine; + char* string = m_handle.get_charset(CAddonBase::m_interface->toKodi->kodiBase, m_handle.handle); + if (string != nullptr) { - if (std::strlen(strLegalFileName)) - strReturn = strLegalFileName; - ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, strLegalFileName); + protoLine = string; + CAddonBase::m_interface->toKodi->free_string(CAddonBase::m_interface->toKodi->kodiBase, + string); } - return strReturn; + return protoLine; } - //---------------------------------------------------------------------------- + //-------------------------------------------------------------------------- - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs - /// @brief Make directory name valid - /// - /// Function to replace not valid characters with '_'. It can be also - /// compared with original before in a own loop until it is equal - /// (no invalid characters). - /// - /// @param[in] path Directory name to check and fix - /// @return The legal directory name + //========================================================================== + /// @brief The protocol line associated with these HTTP headers. /// + /// @return The protocol line /// - /// ------------------------------------------------------------------------ - /// - /// **Example:** - /// ~~~~~~~~~~~~~{.cpp} - /// #include - /// ... - /// std::string path = "///\\jk???lj????\\hgjkg"; - /// std::string legalPath = kodi::vfs::MakeLegalPath(path); - /// fprintf(stderr, "Legal name of '%s' is '%s'\n", path.c_str(), legalPath.c_str()); - /// - /// /* Returns as legal: '/jk___lj____/hgjkg' */ - /// ~~~~~~~~~~~~~ - /// - inline std::string MakeLegalPath(const std::string& path) + std::string GetProtoLine() const { - std::string strReturn; - char* strLegalPath = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->make_legal_path(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, path.c_str()); - if (strLegalPath != nullptr) + using namespace ::kodi::addon; + + if (!m_handle.handle) + return ""; + + std::string protoLine; + char* string = + m_handle.get_proto_line(CAddonBase::m_interface->toKodi->kodiBase, m_handle.handle); + if (string != nullptr) { - if (std::strlen(strLegalPath)) - strReturn = strLegalPath; - ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, strLegalPath); + protoLine = string; + CAddonBase::m_interface->toKodi->free_string(CAddonBase::m_interface->toKodi->kodiBase, + string); } - return strReturn; + return protoLine; } - //---------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + + ///@} + + KODI_HTTP_HEADER m_handle; +}; +///@} +//---------------------------------------------------------------------------- +//============================================================================== +/// @defgroup cpp_kodi_vfs_CDirEntry class CDirEntry +/// @ingroup cpp_kodi_vfs_Defs +/// +/// @brief **Virtual file server directory entry**\n +/// This class is used as an entry for files and folders in +/// kodi::vfs::GetDirectory(). +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// +/// ... +/// +/// std::vector items; +/// kodi::vfs::GetDirectory("special://temp", "", items); +/// +/// fprintf(stderr, "Directory have %lu entries\n", items.size()); +/// for (unsigned long i = 0; i < items.size(); i++) +/// { +/// char buff[20]; +/// time_t now = items[i].DateTime(); +/// strftime(buff, 20, "%Y-%m-%d %H:%M:%S", gmtime(&now)); +/// fprintf(stderr, " - %04lu -- Folder: %s -- Name: %s -- Path: %s -- Time: %s\n", +/// i+1, +/// items[i].IsFolder() ? "yes" : "no ", +/// items[i].Label().c_str(), +/// items[i].Path().c_str(), +/// buff); +/// } +/// ~~~~~~~~~~~~~ +/// +/// It has the header @ref Filesystem.h "#include " be included +/// to enjoy it. +/// +//@{ +class CDirEntry +{ +public: //============================================================================ - /// - /// @ingroup cpp_kodi_vfs - /// @brief Returns the translated path - /// - /// @param[in] source string or unicode - Path to format - /// @return A human-readable string suitable for logging - /// - /// @note Only useful if you are coding for both Linux and Windows. - /// e.g. Converts 'special://masterprofile/script_data' -> '/home/user/.kodi/UserData/script_data' - /// on Linux. - /// - /// - /// ------------------------------------------------------------------------ - /// - /// **Example:** - /// ~~~~~~~~~~~~~{.cpp} - /// #include - /// ... - /// std::string path = kodi::vfs::TranslateSpecialProtocol("special://masterprofile/script_data"); - /// fprintf(stderr, "Translated path is: %s\n", path.c_str()); - /// ... - /// ~~~~~~~~~~~~~ - /// or - /// ~~~~~~~~~~~~~{.cpp} - /// #include - /// ... - /// fprintf(stderr, "Directory 'special://temp' is '%s'\n", kodi::vfs::TranslateSpecialProtocol("special://temp").c_str()); - /// ... - /// ~~~~~~~~~~~~~ - /// - inline std::string TranslateSpecialProtocol(const std::string& source) + /// @ingroup cpp_kodi_vfs_CDirEntry + /// @brief Constructor for VFS directory entry + /// + /// @param[in] label [opt] Name to use for entry + /// @param[in] path [opt] Used path of the entry + /// @param[in] folder [opt] If set entry used as folder + /// @param[in] size [opt] If used as file, his size defined there + /// @param[in] dateTime [opt] Date time of the entry + /// + CDirEntry(const std::string& label = "", + const std::string& path = "", + bool folder = false, + int64_t size = -1, + time_t dateTime = 0) + : m_label(label), m_path(path), m_folder(folder), m_size(size), m_dateTime(dateTime) { - std::string strReturn; - char* protocol = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->translate_special_protocol(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, source.c_str()); - if (protocol != nullptr) - { - if (std::strlen(protocol)) - strReturn = protocol; - ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, protocol); - } - return strReturn; } //---------------------------------------------------------------------------- //============================================================================ - /// - /// @ingroup cpp_kodi_vfs - /// @brief Return the file name from given complate path string - /// - /// @param[in] path The complete path include file and directory - /// @return Filename from path - /// - /// - /// ------------------------------------------------------------------------ - /// - /// **Example:** - /// ~~~~~~~~~~~~~{.cpp} - /// #include - /// ... - /// std::string fileName = kodi::vfs::GetFileName("special://temp/kodi.log"); - /// fprintf(stderr, "File name is '%s'\n", fileName.c_str()); - /// ~~~~~~~~~~~~~ - /// - inline std::string GetFileName(const std::string& path) + // @note Not for addon development itself needed, thats why below is + // disabled for doxygen! + // + // @ingroup cpp_kodi_vfs_CDirEntry + // @brief Constructor to create own copy + // + // @param[in] dirEntry pointer to own class type + // + explicit CDirEntry(const VFSDirEntry& dirEntry) + : m_label(dirEntry.label ? dirEntry.label : ""), + m_path(dirEntry.path ? dirEntry.path : ""), + m_folder(dirEntry.folder), + m_size(dirEntry.size), + m_dateTime(dirEntry.date_time) { - /* find the last slash */ - const size_t slash = path.find_last_of("/\\"); - return path.substr(slash+1); } //---------------------------------------------------------------------------- - //============================================================================ - /// - /// @ingroup cpp_kodi_vfs - /// @brief Return the directory name from given complate path string - /// - /// @param[in] path The complete path include file and directory - /// @return Directory name from path - /// + /// @defgroup cpp_kodi_vfs_CDirEntry_Help *Value Help* + /// @ingroup cpp_kodi_vfs_CDirEntry + /// -------------------------------------------------------------------------- /// - /// ------------------------------------------------------------------------ + /// The following table contains values that can be set with @ref cpp_kodi_vfs_CDirEntry : + /// | Name | Type | Set call | Get call | Clear call | + /// |------|------|----------|----------|------------| + /// | **Directory entry name** | `std::string` | @ref CDirEntry::SetLabel "SetLabel" | @ref CDirEntry::Label "Label" | | + /// | **Title of entry** | `std::string` | @ref CDirEntry::SetTitle "SetTitle" | @ref CDirEntry::Title "Title" | | + /// | **Path of the entry** | `std::string` | @ref CDirEntry::SetPath "SetPath" | @ref CDirEntry::Path "Path" | | + /// | **Entry is folder** | `bool` | @ref CDirEntry::SetFolder "SetFolder" | @ref CDirEntry::IsFolder "IsFolder" | | + /// | **The size of the file** | `int64_t` | @ref CDirEntry::SetSize "SetSize" | @ref CDirEntry::Size "Size" | | + /// | **File time and date** | `time_t` | @ref CDirEntry::SetDateTime "SetDateTime" | @ref CDirEntry::DateTime "DateTime" | | + /// | **Property entries** | `std::string, std::string` | @ref CDirEntry::AddProperty "AddProperty" | @ref CDirEntry::GetProperties "GetProperties" | @ref CDirEntry::ClearProperties "ClearProperties" /// - /// **Example:** - /// ~~~~~~~~~~~~~{.cpp} - /// #include - /// ... - /// std::string dirName = kodi::vfs::GetDirectoryName("special://temp/kodi.log"); - /// fprintf(stderr, "Directory name is '%s'\n", dirName.c_str()); - /// ~~~~~~~~~~~~~ - /// - inline std::string GetDirectoryName(const std::string& path) - { - // Will from a full filename return the directory the file resides in. - // Keeps the final slash at end and possible |option=foo options. - - size_t iPosSlash = path.find_last_of("/\\"); - if (iPosSlash == std::string::npos) - return ""; // No slash, so no path (ignore any options) - - size_t iPosBar = path.rfind('|'); - if (iPosBar == std::string::npos) - return path.substr(0, iPosSlash + 1); // Only path - - return path.substr(0, iPosSlash + 1) + path.substr(iPosBar); // Path + options - } - //---------------------------------------------------------------------------- + /// @addtogroup cpp_kodi_vfs_CDirEntry + /// @copydetails cpp_kodi_vfs_CDirEntry_Help + //@{ //============================================================================ + /// @brief Get the directory entry name. /// - /// @ingroup cpp_kodi_vfs - /// @brief Remove the slash on given path name + /// @return Name of the entry /// - /// @param[in,out] path The complete path + const std::string& Label(void) const { return m_label; } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Get the optional title of entry. /// + /// @return Title of the entry, if exists /// - /// ------------------------------------------------------------------------ + const std::string& Title(void) const { return m_title; } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Get the path of the entry. /// - /// **Example:** - /// ~~~~~~~~~~~~~{.cpp} - /// #include - /// ... - /// std::string dirName = "special://temp/"; - /// kodi::vfs::RemoveSlashAtEnd(dirName); - /// fprintf(stderr, "Directory name is '%s'\n", dirName.c_str()); - /// ~~~~~~~~~~~~~ + /// @return File system path of the entry /// - inline void RemoveSlashAtEnd(std::string& path) - { - if (!path.empty()) - { - char last = path[path.size() - 1]; - if (last == '/' || last == '\\') - path.erase(path.size() - 1); - } - } + const std::string& Path(void) const { return m_path; } //---------------------------------------------------------------------------- //============================================================================ + /// @brief Used to check entry is folder. /// - /// @ingroup cpp_kodi_vfs - /// @brief Return a size aligned to the chunk size at least as large as the chunk size. + /// @return true if entry is a folder /// - /// @param[in] chunk The chunk size - /// @param[in] minimum The minimum size (or maybe the minimum number of chunks?) - /// @return The aligned size - /// - inline unsigned int GetChunkSize(unsigned int chunk, unsigned int minimum) - { - if (chunk) - return chunk * ((minimum + chunk - 1) / chunk); - else - return minimum; - } + bool IsFolder(void) const { return m_folder; } //---------------------------------------------------------------------------- //============================================================================ + /// @brief If file, the size of the file. /// - /// @ingroup cpp_kodi_vfs - /// @brief Check if a file exists. + /// @return Defined file size /// - /// @param[in] filename The filename to check. - /// @param[in] usecache Check in file cache. - /// @return true if the file exists false otherwise. + int64_t Size(void) const { return m_size; } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Get file time and date for a new entry. /// + /// @return The with time_t defined date and time of file /// - /// ------------------------------------------------------------------------- + time_t DateTime() { return m_dateTime; } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Set the label name. /// - /// **Example:** - /// ~~~~~~~~~~~~~{.cpp} - /// #include - /// ... - /// bool exists = kodi::vfs::FileExists("special://temp/kodi.log"); - /// fprintf(stderr, "Log file should be always present, is it present? %s\n", exists ? "yes" : "no"); - /// ~~~~~~~~~~~~~ + /// @param[in] label name of entry /// - inline bool FileExists(const std::string& filename, bool usecache = false) - { - return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->file_exists(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), usecache); - } + void SetLabel(const std::string& label) { m_label = label; } //---------------------------------------------------------------------------- //============================================================================ + /// @brief Set the title name. /// - /// @ingroup cpp_kodi_vfs - /// @brief Get file status. - /// - /// These function return information about a file. Execute (search) - /// permission is required on all of the directories in path that - /// lead to the file. - /// - /// The call return a stat structure, which contains the on \ref STAT_STRUCTURE - /// defined values. - /// - /// @warning Not all of the OS file systems implement all of the time fields. - /// - /// @param[in] filename The filename to read the status from. - /// @param[out] buffer The file status is written into this buffer. - /// @return On success, tru is returned. On error, fale is returned - /// - /// - /// ------------------------------------------------------------------------- - /// - /// **Example:** - /// ~~~~~~~~~~~~~{.cpp} - /// #include - /// ... - /// STAT_STRUCTURE statFile; - /// int ret = kodi::vfs::StatFile("special://temp/kodi.log", statFile); - /// fprintf(stderr, "deviceId (ID of device containing file) = %u\n" - /// "size (total size, in bytes) = %lu\n" - /// "accessTime (time of last access) = %lu\n" - /// "modificationTime (time of last modification) = %lu\n" - /// "statusTime (time of last status change) = %lu\n" - /// "isDirectory (The stat url is a directory) = %s\n" - /// "isSymLink (The stat url is a symbolic link) = %s\n" - /// "Return value = %i\n", - /// statFile.deviceId, - /// statFile.size, - /// statFile.accessTime, - /// statFile.modificationTime, - /// statFile.statusTime, - /// statFile.isDirectory ? "true" : "false", - /// statFile.isSymLink ? "true" : "false", - /// ret); - /// ~~~~~~~~~~~~~ - /// - inline bool StatFile(const std::string& filename, STAT_STRUCTURE& buffer) - { - struct __stat64 frontendBuffer = { }; - if (::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->stat_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), &frontendBuffer)) - { - buffer.deviceId = frontendBuffer.st_dev; - buffer.size = frontendBuffer.st_size; -#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) - buffer.accessTime = frontendBuffer.st_atimespec; - buffer.modificationTime = frontendBuffer.st_mtimespec; - buffer.statusTime = frontendBuffer.st_ctimespec; -#elif defined(TARGET_WINDOWS) - buffer.accessTime = frontendBuffer.st_atime; - buffer.modificationTime = frontendBuffer.st_mtime; - buffer.statusTime = frontendBuffer.st_ctime; -#elif defined(TARGET_ANDROID) - buffer.accessTime.tv_sec = frontendBuffer.st_atime; - buffer.accessTime.tv_nsec = frontendBuffer.st_atime_nsec; - buffer.modificationTime.tv_sec = frontendBuffer.st_mtime; - buffer.modificationTime.tv_nsec = frontendBuffer.st_mtime_nsec; - buffer.statusTime.tv_sec = frontendBuffer.st_ctime; - buffer.statusTime.tv_nsec = frontendBuffer.st_ctime_nsec; -#else - buffer.accessTime = frontendBuffer.st_atim; - buffer.modificationTime = frontendBuffer.st_mtim; - buffer.statusTime = frontendBuffer.st_ctim; -#endif - buffer.isDirectory = S_ISDIR(frontendBuffer.st_mode); - buffer.isSymLink = S_ISLNK(frontendBuffer.st_mode); - return true; - } - return false; - } + /// @param[in] title title name of entry + /// + void SetTitle(const std::string& title) { m_title = title; } //---------------------------------------------------------------------------- //============================================================================ + /// @brief Set the path of the entry. /// - /// @ingroup cpp_kodi_vfs - /// @brief Deletes a file. - /// - /// @param[in] filename The filename to delete. - /// @return The file was successfully deleted. - /// - /// - /// ------------------------------------------------------------------------- - /// - /// **Example:** - /// ~~~~~~~~~~~~~{.cpp} - /// #include - /// #include - /// #include - /// ... - /// std::string filename; - /// if (kodi::gui::DialogFileBrowser::ShowAndGetFile("local", "", - /// "Test File selection and delete of them!", - /// filename)) - /// { - /// bool successed = kodi::vfs::DeleteFile(filename); - /// if (!successed) - /// kodi::gui::DialogOK::ShowAndGetInput("Error", "Delete of File", filename, "failed!"); - /// else - /// kodi::gui::DialogOK::ShowAndGetInput("Information", "Delete of File", filename, "successfull done."); - /// } - /// ~~~~~~~~~~~~~ - /// - inline bool DeleteFile(const std::string& filename) - { - return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->delete_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str()); - } + /// @param[in] path path of entry + /// + void SetPath(const std::string& path) { m_path = path; } //---------------------------------------------------------------------------- //============================================================================ + /// @brief Set the entry defined as folder. /// - /// @ingroup cpp_kodi_vfs - /// @brief Rename a file name + /// @param[in] folder If true becomes entry defined as folder /// - /// @param[in] filename The filename to copy. - /// @param[in] newFileName The new filename - /// @return true if successfully renamed + void SetFolder(bool folder) { m_folder = folder; } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Set a file size for a new entry. /// + /// @param[in] size Size to set for dir entry /// - inline bool RenameFile(const std::string& filename, const std::string& newFileName) - { - return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->rename_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), newFileName.c_str()); - } + void SetSize(int64_t size) { m_size = size; } //---------------------------------------------------------------------------- //============================================================================ + /// @brief Set file time and date for a new entry. /// - /// @ingroup cpp_kodi_vfs - /// @brief Copy a file from source to destination + /// @param[in] dateTime The with time_t defined date and time of file /// - /// @param[in] filename The filename to copy. - /// @param[in] destination The destination to copy file to - /// @return true if successfully copied + void SetDateTime(time_t dateTime) { m_dateTime = dateTime; } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Add a by string defined property entry to directory entry. + /// + /// @note A property can be used to add some special information about a file + /// or directory entry, this can be used on other places to do the right work + /// of them. + /// + /// @param[in] id Identification name of property + /// @param[in] value The property value to add by given id + /// + void AddProperty(const std::string& id, const std::string& value) { m_properties[id] = value; } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Clear all present properties. /// + void ClearProperties() { m_properties.clear(); } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Get the present properties list on directory entry. /// - inline bool CopyFile(const std::string& filename, const std::string& destination) + /// @return map with all present properties + /// + const std::map& GetProperties() const { return m_properties; } + //---------------------------------------------------------------------------- + + //@} + +private: + std::string m_label; + std::string m_title; + std::string m_path; + std::map m_properties; + bool m_folder; + int64_t m_size; + time_t m_dateTime; +}; +//@} +//------------------------------------------------------------------------------ + +//}}} + +//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ +// "C++" Directory related functions +//{{{ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_Directory +/// @brief Make a directory. +/// +/// The kodi::vfs::CreateDirectory() function shall create a +/// new directory with name path. +/// +/// The newly created directory shall be an empty directory. +/// +/// @param[in] path Path to the directory. +/// @return Upon successful completion, CreateDirectory() shall return true. +/// Otherwise false shall be returned, no directory shall be created. +/// +/// +/// ------------------------------------------------------------------------- +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// std::string directory = "C:\\my_dir"; +/// bool ret = kodi::vfs::CreateDirectory(directory); +/// fprintf(stderr, "Directory '%s' successfull created: %s\n", directory.c_str(), ret ? "yes" : "no"); +/// ... +/// ~~~~~~~~~~~~~ +/// +inline bool CreateDirectory(const std::string& path) +{ + using namespace kodi::addon; + + return CAddonBase::m_interface->toKodi->kodi_filesystem->create_directory( + CAddonBase::m_interface->toKodi->kodiBase, path.c_str()); +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_Directory +/// @brief Verifying the Existence of a Directory. +/// +/// The kodi::vfs::DirectoryExists() method determines whether +/// a specified folder exists. +/// +/// @param[in] path Path to the directory. +/// @return True when it exists, false otherwise. +/// +/// +/// ------------------------------------------------------------------------- +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// std::string directory = "C:\\my_dir"; +/// bool ret = kodi::vfs::DirectoryExists(directory); +/// fprintf(stderr, "Directory '%s' present: %s\n", directory.c_str(), ret ? "yes" : "no"); +/// ... +/// ~~~~~~~~~~~~~ +/// +inline bool DirectoryExists(const std::string& path) +{ + using namespace kodi::addon; + + return CAddonBase::m_interface->toKodi->kodi_filesystem->directory_exists( + CAddonBase::m_interface->toKodi->kodiBase, path.c_str()); +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_Directory +/// @brief Removes a directory. +/// +/// The kodi::vfs::RemoveDirectory() function shall remove a +/// directory whose name is given by path. +/// +/// @param[in] path Path to the directory. +/// @return Upon successful completion, the function RemoveDirectory() shall +/// return true. Otherwise, false shall be returned, and errno set +/// to indicate the error. If false is returned, the named directory +/// shall not be changed. +/// +/// +/// ------------------------------------------------------------------------- +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// bool ret = kodi::vfs::RemoveDirectory("C:\\my_dir"); +/// ... +/// ~~~~~~~~~~~~~ +/// +inline bool RemoveDirectory(const std::string& path) +{ + using namespace kodi::addon; + + return CAddonBase::m_interface->toKodi->kodi_filesystem->remove_directory( + CAddonBase::m_interface->toKodi->kodiBase, path.c_str()); +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_Directory +/// @brief Lists a directory. +/// +/// Return the list of files and directories which have been found in the +/// specified directory and which respect the given constraint. +/// +/// It can handle the normal OS dependent paths and also the special virtual +/// filesystem from Kodi what starts with \b special://. +/// +/// @param[in] path The path in which the files and directories are located. +/// @param[in] mask Mask to filter out requested files, e.g. "*.avi|*.mpg" to +/// files with this ending. +/// @param[out] items The returned list directory entries. +/// @return True if listing was successful, false otherwise. +/// +/// +/// ------------------------------------------------------------------------- +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// +/// std::vector items; +/// kodi::vfs::GetDirectory("special://temp", "", items); +/// +/// fprintf(stderr, "Directory have %lu entries\n", items.size()); +/// for (unsigned long i = 0; i < items.size(); i++) +/// { +/// fprintf(stderr, " - %04lu -- Folder: %s -- Name: %s -- Path: %s\n", +/// i+1, +/// items[i].IsFolder() ? "yes" : "no ", +/// items[i].Label().c_str(), +/// items[i].Path().c_str()); +/// } +/// ~~~~~~~~~~~~~ +inline bool GetDirectory(const std::string& path, + const std::string& mask, + std::vector& items) +{ + using namespace kodi::addon; + + VFSDirEntry* dir_list = nullptr; + unsigned int num_items = 0; + if (CAddonBase::m_interface->toKodi->kodi_filesystem->get_directory( + CAddonBase::m_interface->toKodi->kodiBase, path.c_str(), mask.c_str(), &dir_list, + &num_items)) + { + if (dir_list) + { + for (unsigned int i = 0; i < num_items; ++i) + items.emplace_back(dir_list[i]); + + CAddonBase::m_interface->toKodi->kodi_filesystem->free_directory( + CAddonBase::m_interface->toKodi->kodiBase, dir_list, num_items); + } + + return true; + } + return false; +} +//------------------------------------------------------------------------------ + +//}}} + +//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ +// "C++" File related functions +//{{{ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_File +/// @brief Check if a file exists. +/// +/// @param[in] filename The filename to check. +/// @param[in] usecache Check in file cache. +/// @return true if the file exists false otherwise. +/// +/// +/// ------------------------------------------------------------------------- +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// bool exists = kodi::vfs::FileExists("special://temp/kodi.log"); +/// fprintf(stderr, "Log file should be always present, is it present? %s\n", exists ? "yes" : "no"); +/// ~~~~~~~~~~~~~ +/// +inline bool FileExists(const std::string& filename, bool usecache = false) +{ + using namespace kodi::addon; + + return CAddonBase::m_interface->toKodi->kodi_filesystem->file_exists( + CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), usecache); +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_File +/// @brief Get file status. +/// +/// These function return information about a file. Execute (search) +/// permission is required on all of the directories in path that +/// lead to the file. +/// +/// The call return a stat structure, which contains the on +/// @ref cpp_kodi_vfs_Defs_FileStatus defined values. +/// +/// @warning Not all of the OS file systems implement all of the time fields. +/// +/// @param[in] filename The filename to read the status from. +/// @param[out] buffer The file status is written into this buffer. +/// @return On success, trur is returned. On error, false is returned +/// +/// +/// @copydetails cpp_kodi_vfs_Defs_FileStatus_Help +/// +/// ------------------------------------------------------------------------- +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// kodi::vfs::FileStatus statFile; +/// int ret = kodi::vfs::StatFile("special://temp/kodi.log", statFile); +/// fprintf(stderr, "deviceId (ID of device containing file) = %u\n" +/// "size (total size, in bytes) = %lu\n" +/// "accessTime (time of last access) = %lu\n" +/// "modificationTime (time of last modification) = %lu\n" +/// "statusTime (time of last status change) = %lu\n" +/// "isDirectory (The stat url is a directory) = %s\n" +/// "isSymLink (The stat url is a symbolic link) = %s\n" +/// "Return value = %i\n", +/// statFile.GetDeviceId(), +/// statFile.GetSize(), +/// statFile.GetAccessTime(), +/// statFile.GetModificationTime(), +/// statFile.GetStatusTime(), +/// statFile.GetIsDirectory() ? "true" : "false", +/// statFile.GetIsSymLink() ? "true" : "false", +/// ret); +/// ~~~~~~~~~~~~~ +/// +inline bool StatFile(const std::string& filename, kodi::vfs::FileStatus& buffer) +{ + using namespace kodi::addon; + + return CAddonBase::m_interface->toKodi->kodi_filesystem->stat_file( + CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), buffer); +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_File +/// @brief Deletes a file. +/// +/// @param[in] filename The filename to delete. +/// @return The file was successfully deleted. +/// +/// +/// ------------------------------------------------------------------------- +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// #include +/// #include +/// ... +/// std::string filename; +/// if (kodi::gui::DialogFileBrowser::ShowAndGetFile("local", "", +/// "Test File selection and delete of them!", +/// filename)) +/// { +/// bool successed = kodi::vfs::DeleteFile(filename); +/// if (!successed) +/// kodi::gui::DialogOK::ShowAndGetInput("Error", "Delete of File", filename, "failed!"); +/// else +/// kodi::gui::DialogOK::ShowAndGetInput("Information", "Delete of File", filename, "successfull done."); +/// } +/// ~~~~~~~~~~~~~ +/// +inline bool DeleteFile(const std::string& filename) +{ + using namespace kodi::addon; + + return CAddonBase::m_interface->toKodi->kodi_filesystem->delete_file( + CAddonBase::m_interface->toKodi->kodiBase, filename.c_str()); +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_File +/// @brief Rename a file name. +/// +/// @param[in] filename The filename to copy. +/// @param[in] newFileName The new filename +/// @return true if successfully renamed +/// +/// +inline bool RenameFile(const std::string& filename, const std::string& newFileName) +{ + using namespace kodi::addon; + + return CAddonBase::m_interface->toKodi->kodi_filesystem->rename_file( + CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), newFileName.c_str()); +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_File +/// @brief Copy a file from source to destination. +/// +/// @param[in] filename The filename to copy. +/// @param[in] destination The destination to copy file to +/// @return true if successfully copied +/// +/// +inline bool CopyFile(const std::string& filename, const std::string& destination) +{ + using namespace kodi::addon; + + return CAddonBase::m_interface->toKodi->kodi_filesystem->copy_file( + CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), destination.c_str()); +} +//------------------------------------------------------------------------------ + +//}}} + +//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ +// "C++" General filesystem functions +//{{{ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_General +/// @brief Retrieve MD5sum of a file. +/// +/// @param[in] path Path to the file to MD5sum +/// @return MD5 sum of the file +/// +/// +/// ------------------------------------------------------------------------- +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// #include +/// ... +/// std::string md5; +/// std::string filename; +/// if (kodi::gui::DialogFileBrowser::ShowAndGetFile("local", "*.avi|*.mpg|*.mp4", +/// "Test File selection to get MD5", +/// filename)) +/// { +/// md5 = kodi::vfs::GetFileMD5(filename); +/// fprintf(stderr, "MD5 of file '%s' is %s\n", md5.c_str(), filename.c_str()); +/// } +/// ~~~~~~~~~~~~~ +/// +inline std::string GetFileMD5(const std::string& path) +{ + using namespace kodi::addon; + + std::string strReturn; + char* strMd5 = CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_md5( + CAddonBase::m_interface->toKodi->kodiBase, path.c_str()); + if (strMd5 != nullptr) + { + if (std::strlen(strMd5)) + strReturn = strMd5; + CAddonBase::m_interface->toKodi->free_string(CAddonBase::m_interface->toKodi->kodiBase, strMd5); + } + return strReturn; +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_General +/// @brief Returns a thumb cache filename. +/// +/// @param[in] filename Path to file +/// @return Cache filename +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// #include +/// ... +/// std::string thumb; +/// std::string filename; +/// if (kodi::gui::DialogFileBrowser::ShowAndGetFile("local", "*.avi|*.mpg|*.mp4", +/// "Test File selection to get Thumnail", +/// filename)) +/// { +/// thumb = kodi::vfs::GetCacheThumbName(filename); +/// fprintf(stderr, "Thumb name of file '%s' is %s\n", thumb.c_str(), filename.c_str()); +/// } +/// ~~~~~~~~~~~~~ +/// +inline std::string GetCacheThumbName(const std::string& filename) +{ + using namespace kodi::addon; + + std::string strReturn; + char* strThumbName = CAddonBase::m_interface->toKodi->kodi_filesystem->get_cache_thumb_name( + CAddonBase::m_interface->toKodi->kodiBase, filename.c_str()); + if (strThumbName != nullptr) + { + if (std::strlen(strThumbName)) + strReturn = strThumbName; + CAddonBase::m_interface->toKodi->free_string(CAddonBase::m_interface->toKodi->kodiBase, + strThumbName); + } + return strReturn; +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_General +/// @brief Make filename valid. +/// +/// Function to replace not valid characters with '_'. It can be also +/// compared with original before in a own loop until it is equal +/// (no invalid characters). +/// +/// @param[in] filename Filename to check and fix +/// @return The legal filename +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// std::string fileName = "///\\jk???lj????.mpg"; +/// std::string legalName = kodi::vfs::MakeLegalFileName(fileName); +/// fprintf(stderr, "Legal name of '%s' is '%s'\n", fileName.c_str(), legalName.c_str()); +/// +/// /* Returns as legal: 'jk___lj____.mpg' */ +/// ~~~~~~~~~~~~~ +/// +inline std::string MakeLegalFileName(const std::string& filename) +{ + using namespace kodi::addon; + + std::string strReturn; + char* strLegalFileName = CAddonBase::m_interface->toKodi->kodi_filesystem->make_legal_filename( + CAddonBase::m_interface->toKodi->kodiBase, filename.c_str()); + if (strLegalFileName != nullptr) + { + if (std::strlen(strLegalFileName)) + strReturn = strLegalFileName; + CAddonBase::m_interface->toKodi->free_string(CAddonBase::m_interface->toKodi->kodiBase, + strLegalFileName); + } + return strReturn; +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_General +/// @brief Make directory name valid. +/// +/// Function to replace not valid characters with '_'. It can be also +/// compared with original before in a own loop until it is equal +/// (no invalid characters). +/// +/// @param[in] path Directory name to check and fix +/// @return The legal directory name +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// std::string path = "///\\jk???lj????\\hgjkg"; +/// std::string legalPath = kodi::vfs::MakeLegalPath(path); +/// fprintf(stderr, "Legal name of '%s' is '%s'\n", path.c_str(), legalPath.c_str()); +/// +/// /* Returns as legal: '/jk___lj____/hgjkg' */ +/// ~~~~~~~~~~~~~ +/// +inline std::string MakeLegalPath(const std::string& path) +{ + using namespace kodi::addon; + + std::string strReturn; + char* strLegalPath = CAddonBase::m_interface->toKodi->kodi_filesystem->make_legal_path( + CAddonBase::m_interface->toKodi->kodiBase, path.c_str()); + if (strLegalPath != nullptr) + { + if (std::strlen(strLegalPath)) + strReturn = strLegalPath; + CAddonBase::m_interface->toKodi->free_string(CAddonBase::m_interface->toKodi->kodiBase, + strLegalPath); + } + return strReturn; +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_General +/// @brief Returns the translated path. +/// +/// @param[in] source String or unicode - Path to format +/// @return A human-readable string suitable for logging +/// +/// @note Only useful if you are coding for both Linux and Windows. e.g. +/// Converts 'special://masterprofile/script_data' -> +/// '/home/user/.kodi/UserData/script_data' on Linux. +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// std::string path = kodi::vfs::TranslateSpecialProtocol("special://masterprofile/script_data"); +/// fprintf(stderr, "Translated path is: %s\n", path.c_str()); +/// ... +/// ~~~~~~~~~~~~~ +/// or +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// fprintf(stderr, "Directory 'special://temp' is '%s'\n", kodi::vfs::TranslateSpecialProtocol("special://temp").c_str()); +/// ... +/// ~~~~~~~~~~~~~ +/// +inline std::string TranslateSpecialProtocol(const std::string& source) +{ + using namespace kodi::addon; + + std::string strReturn; + char* protocol = CAddonBase::m_interface->toKodi->kodi_filesystem->translate_special_protocol( + CAddonBase::m_interface->toKodi->kodiBase, source.c_str()); + if (protocol != nullptr) + { + if (std::strlen(protocol)) + strReturn = protocol; + CAddonBase::m_interface->toKodi->free_string(CAddonBase::m_interface->toKodi->kodiBase, + protocol); + } + return strReturn; +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @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 +/// @return Filename from path +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// std::string fileName = kodi::vfs::GetFileName("special://temp/kodi.log"); +/// fprintf(stderr, "File name is '%s'\n", fileName.c_str()); +/// ~~~~~~~~~~~~~ +/// +inline std::string GetFileName(const std::string& path) +{ + /* find the last slash */ + const size_t slash = path.find_last_of("/\\"); + return path.substr(slash + 1); +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_General +/// @brief Return the directory name from given complate path string. +/// +/// @param[in] path The complete path include file and directory +/// @return Directory name from path +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// std::string dirName = kodi::vfs::GetDirectoryName("special://temp/kodi.log"); +/// fprintf(stderr, "Directory name is '%s'\n", dirName.c_str()); +/// ~~~~~~~~~~~~~ +/// +inline std::string GetDirectoryName(const std::string& path) +{ + // Will from a full filename return the directory the file resides in. + // Keeps the final slash at end and possible |option=foo options. + + size_t iPosSlash = path.find_last_of("/\\"); + if (iPosSlash == std::string::npos) + return ""; // No slash, so no path (ignore any options) + + size_t iPosBar = path.rfind('|'); + if (iPosBar == std::string::npos) + return path.substr(0, iPosSlash + 1); // Only path + + return path.substr(0, iPosSlash + 1) + path.substr(iPosBar); // Path + options +} +//------------------------------------------------------------------------------ + + +//============================================================================== +/// @ingroup cpp_kodi_vfs_General +/// @brief Remove the slash on given path name. +/// +/// @param[in,out] path The complete path +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// std::string dirName = "special://temp/"; +/// kodi::vfs::RemoveSlashAtEnd(dirName); +/// fprintf(stderr, "Directory name is '%s'\n", dirName.c_str()); +/// ~~~~~~~~~~~~~ +/// +inline void RemoveSlashAtEnd(std::string& path) +{ + if (!path.empty()) + { + char last = path[path.size() - 1]; + if (last == '/' || last == '\\') + path.erase(path.size() - 1); + } +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_General +/// @brief Return a size aligned to the chunk size at least as large as the +/// chunk size. +/// +/// @param[in] chunk The chunk size +/// @param[in] minimum The minimum size (or maybe the minimum number of chunks?) +/// @return The aligned size +/// +inline unsigned int GetChunkSize(unsigned int chunk, unsigned int minimum) +{ + if (chunk) + return chunk * ((minimum + chunk - 1) / chunk); + else + return minimum; +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_General +/// @brief Checks the given path contains a known internet protocol. +/// +/// About following protocols are the path checked: +/// | Protocol | Return true condition | Protocol | Return true condition +/// |----------|-----------------------|----------|----------------------- +/// | **dav** | strictCheck = true | **rtmps** | always +/// | **davs** | strictCheck = true | **rtmpt** | always +/// | **ftp** | strictCheck = true | **rtmpte** | always +/// | **ftps** | strictCheck = true | **rtp** | always +/// | **http** | always | **rtsp** | always +/// | **https**| always | **sdp** | always +/// | **mms** | always | **sftp** | strictCheck = true +/// | **mmsh** | always | **stack** | always +/// | **mmst** | always | **tcp** | always +/// | **rtmp** | always | **udp** | always +/// | **rtmpe**| always | | | +/// +/// @param[in] path To checked path/URL +/// @param[in] strictCheck [opt] If True the set of protocols used will be +/// extended to include ftp, ftps, dav, davs and sftp. +/// @return True if path is to a internet stream, false otherwise +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// // Check should return false +/// fprintf(stderr, "File name 1 is internet stream '%s' (should no)\n", +/// kodi::vfs::IsInternetStream("D:/my-file.mkv") ? "yes" : "no"); +/// +/// // Check should return true +/// fprintf(stderr, "File name 2 is internet stream '%s' (should yes)\n", +/// kodi::vfs::IsInternetStream("http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_30fps_normal.mp4") ? "yes" : "no"); +/// +/// // Check should return false +/// fprintf(stderr, "File name 1 is internet stream '%s' (should no)\n", +/// kodi::vfs::IsInternetStream("ftp://do-somewhere.com/the-file.mkv") ? "yes" : "no", false); +/// +/// // Check should return true +/// fprintf(stderr, "File name 1 is internet stream '%s' (should yes)\n", +/// kodi::vfs::IsInternetStream("ftp://do-somewhere.com/the-file.mkv") ? "yes" : "no", true); +/// ~~~~~~~~~~~~~ +/// +inline bool IsInternetStream(const std::string& path, bool strictCheck = false) +{ + using namespace kodi::addon; + + return CAddonBase::m_interface->toKodi->kodi_filesystem->is_internet_stream( + CAddonBase::m_interface->toKodi->kodiBase, path.c_str(), strictCheck); +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_General +/// @brief Checks whether the specified path refers to a local network. +/// +/// In difference to @ref IsHostOnLAN() include this more deeper checks where +/// also handle Kodi's special protocol and stacks. +/// +/// @param[in] path To checked path +/// @return True if path is on LAN, false otherwise +/// +/// @note Check includes @ref IsHostOnLAN() too. +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// // Check should return true +/// bool lan = kodi::vfs::IsOnLAN("smb://path/to/file"); +/// ~~~~~~~~~~~~~ +/// +inline bool IsOnLAN(const std::string& path) +{ + using namespace kodi::addon; + + return CAddonBase::m_interface->toKodi->kodi_filesystem->is_on_lan( + CAddonBase::m_interface->toKodi->kodiBase, path.c_str()); +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_General +/// @brief Checks specified path for external network. +/// +/// @param[in] path To checked path +/// @return True if path is remote, false otherwise +/// +/// @note This does not apply to the local network. +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// // Check should return true +/// bool remote = kodi::vfs::IsRemote("http://path/to/file"); +/// ~~~~~~~~~~~~~ +/// +inline bool IsRemote(const std::string& path) +{ + using namespace kodi::addon; + + return CAddonBase::m_interface->toKodi->kodi_filesystem->is_remote( + CAddonBase::m_interface->toKodi->kodiBase, path.c_str()); +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_General +/// @brief Checks whether the given path refers to the own system. +/// +/// @param[in] path To checked path +/// @return True if path is local, false otherwise +/// +inline bool IsLocal(const std::string& path) +{ + using namespace kodi::addon; + + return CAddonBase::m_interface->toKodi->kodi_filesystem->is_local( + CAddonBase::m_interface->toKodi->kodiBase, path.c_str()); +} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @ingroup cpp_kodi_vfs_General +/// @brief Checks specified path is a regular URL, e.g. "someprotocol://path/to/file" +/// +/// @return True if file item is URL, false otherwise +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// +/// bool isURL; +/// // Check should return true +/// isURL = kodi::vfs::IsURL("someprotocol://path/to/file"); +/// +/// // Check should return false +/// isURL = kodi::vfs::IsURL("/path/to/file"); +/// ~~~~~~~~~~~~~ +/// +inline bool IsURL(const std::string& path) +{ + using namespace kodi::addon; + + return CAddonBase::m_interface->toKodi->kodi_filesystem->is_url( + CAddonBase::m_interface->toKodi->kodiBase, path.c_str()); +} +//-------------------------------------------------------------------------- + +//============================================================================ +/// @ingroup cpp_kodi_vfs_General +/// @brief To get HTTP header information. +/// +/// @param[in] url URL source of the data +/// @param[out] header The @ref cpp_kodi_vfs_Defs_HttpHeader +/// @return true if successfully done, otherwise false +/// +/// +/// ------------------------------------------------------------------------ +/// +/// @copydetails cpp_kodi_vfs_Defs_HttpHeader_Help +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// kodi::vfs::HttpHeader header; +/// bool ret = kodi::vfs::GetHttpHeader(url, header); +/// ... +/// ~~~~~~~~~~~~~ +/// +inline bool GetHttpHeader(const std::string& url, HttpHeader& header) +{ + using namespace ::kodi::addon; + + return CAddonBase::m_interface->toKodi->kodi_filesystem->get_http_header( + CAddonBase::m_interface->toKodi->kodiBase, url.c_str(), &header.m_handle); +} +//---------------------------------------------------------------------------- + +//============================================================================ +/// @ingroup cpp_kodi_vfs_General +/// @brief Get file mime type. +/// +/// @param[in] url URL source of the data +/// @param[out] mimeType the mime type of the URL +/// @param[in] useragent to be used when retrieving the MimeType [opt] +/// @return true if successfully done, otherwise false +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// std::string mimeType;. +/// if (kodi::vfs::GetMimeType(url, mimeType)) +/// fprintf(stderr, "The mime type is '%s'\n", mimeType.c_str()); +/// ... +/// ~~~~~~~~~~~~~ +/// +inline bool GetMimeType(const std::string& url, + std::string& mimeType, + const std::string& useragent = "") +{ + using namespace ::kodi::addon; + + char* cMimeType; + bool ret = CAddonBase::m_interface->toKodi->kodi_filesystem->get_mime_type( + CAddonBase::m_interface->toKodi->kodiBase, url.c_str(), &cMimeType, useragent.c_str()); + if (cMimeType != nullptr) { - return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->copy_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), destination.c_str()); + mimeType = cMimeType; + CAddonBase::m_interface->toKodi->free_string(CAddonBase::m_interface->toKodi->kodiBase, + cMimeType); } - //---------------------------------------------------------------------------- + return ret; +} +//---------------------------------------------------------------------------- + +//============================================================================ +/// @ingroup cpp_kodi_vfs_General +/// @brief Get file content-type. +/// +/// @param[in] url URL source of the data +/// @param[out] content The returned type +/// @param[in] useragent to be used when retrieving the MimeType [opt] +/// @return true if successfully done, otherwise false +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// std::string content;. +/// if (kodi::vfs::GetContentType(url, content)) +/// fprintf(stderr, "The content type is '%s'\n", content.c_str()); +/// ... +/// ~~~~~~~~~~~~~ +/// +inline bool GetContentType(const std::string& url, + std::string& content, + const std::string& useragent = "") +{ + using namespace ::kodi::addon; + char* cContent; + bool ret = CAddonBase::m_interface->toKodi->kodi_filesystem->get_content_type( + CAddonBase::m_interface->toKodi->kodiBase, url.c_str(), &cContent, useragent.c_str()); + if (cContent != nullptr) + { + content = cContent; + CAddonBase::m_interface->toKodi->free_string(CAddonBase::m_interface->toKodi->kodiBase, + cContent); + } + return ret; +} +//---------------------------------------------------------------------------- + +//============================================================================ +/// @ingroup cpp_kodi_vfs_General +/// @brief Get cookies stored by CURL in RFC 2109 format. +/// +/// @param[in] url URL source of the data +/// @param[out] cookies The text list of available cookies +/// @return true if successfully done, otherwise false +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// ... +/// std::string url = ""; +/// std::string cookies; +/// bool ret = kodi::vfs::GetCookies(url, cookies); +/// fprintf(stderr, "Cookies from URL '%s' are '%s' (return was %s)\n", +/// url.c_str(), cookies.c_str(), ret ? "true" : "false"); +/// ... +/// ~~~~~~~~~~~~~ +/// +inline bool GetCookies(const std::string& url, std::string& cookies) +{ + using namespace ::kodi::addon; + + char* cCookies; + bool ret = CAddonBase::m_interface->toKodi->kodi_filesystem->get_cookies( + CAddonBase::m_interface->toKodi->kodiBase, url.c_str(), &cCookies); + if (cCookies != nullptr) + { + cookies = cCookies; + CAddonBase::m_interface->toKodi->free_string(CAddonBase::m_interface->toKodi->kodiBase, + cCookies); + } + return ret; +} +//---------------------------------------------------------------------------- + +//}}} + +//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ +// "C++" CFile class +//{{{ + +//============================================================================== +/// @defgroup cpp_kodi_vfs_CFile 4. class CFile +/// @ingroup cpp_kodi_vfs +/// +/// @brief **Creatable class for virtual file server control**\n +/// To perform file read/write with Kodi's filesystem parts. +/// +/// CFile is the class used for handling Files in Kodi. This class can be used +/// for creating, reading, writing and modifying files. It directly provides unbuffered, binary disk input/output services +/// +/// It has the header @ref Filesystem.h "#include " be included +/// to enjoy it. +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// +/// ... +/// +/// /* Create the needed file handle class */ +/// kodi::vfs::CFile myFile(); +/// +/// /* In this example we use the user path for the add-on */ +/// std::string file = kodi::GetUserPath() + "/myFile.txt"; +/// +/// /* Now create and open the file or overwrite if present */ +/// myFile.OpenFileForWrite(file, true); +/// +/// const char* str = "I love Kodi!"; +/// +/// /* write string */ +/// myFile.Write(str, sizeof(str)); +/// +/// /* On this way the Close() is not needed to call, becomes done from destructor */ +/// +/// ~~~~~~~~~~~~~ +/// +//@{ +class CFile +{ +public: //============================================================================ + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Construct a new, unopened file. /// - /// \defgroup cpp_kodi_vfs_CFile class CFile - /// \ingroup cpp_kodi_vfs - /// - /// @brief **Virtual file server control** - /// - /// CFile is the class used for handling Files in Kodi. This class can be used - /// for creating, reading, writing and modifying files. It directly provides unbuffered, binary disk input/output services + CFile() = default; + //---------------------------------------------------------------------------- + + //============================================================================ + /// @ingroup cpp_kodi_vfs_CFile + /// @brief `Close()` is called from the destructor, so explicitly + /// closing the file isn't required. /// - /// It has the header \ref Filesystem.h "#include " be included - /// to enjoy it. + virtual ~CFile() { Close(); } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Open the file with filename via Kodi's @ref cpp_kodi_vfs_CFile + /// "CFile". Needs to be closed by calling Close() when done. /// + /// @param[in] filename The filename to open. + /// @param[in] flags [opt] The flags to pass, see @ref OpenFileFlags + /// @return True on success or false on failure /// - /// ------------------------------------------------------------------------ + bool OpenFile(const std::string& filename, unsigned int flags = 0) + { + using namespace kodi::addon; + + Close(); + m_file = CAddonBase::m_interface->toKodi->kodi_filesystem->open_file( + CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), flags); + return m_file != nullptr; + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Open the file with filename via Kodi's @ref cpp_kodi_vfs_CFile + /// "CFile" in write mode. Needs to be closed by calling Close() when + /// done. /// - /// **Example:** - /// ~~~~~~~~~~~~~{.cpp} - /// #include + /// @note Related folders becomes created if not present. /// - /// ... + /// @param[in] filename The filename to open. + /// @param[in] overwrite True to overwrite, false otherwise. + /// @return True on success or false on failure /// - /// /* Create the needed file handle class */ - /// kodi::vfs::CFile myFile(); + bool OpenFileForWrite(const std::string& filename, bool overwrite = false) + { + using namespace kodi::addon; + + Close(); + + // Try to open the file. If it fails, check if we need to create the directory first + // This way we avoid checking if the directory exists every time + m_file = CAddonBase::m_interface->toKodi->kodi_filesystem->open_file_for_write( + CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), overwrite); + if (!m_file) + { + std::string cacheDirectory = kodi::vfs::GetDirectoryName(filename); + if (CAddonBase::m_interface->toKodi->kodi_filesystem->directory_exists( + CAddonBase::m_interface->toKodi->kodiBase, cacheDirectory.c_str()) || + CAddonBase::m_interface->toKodi->kodi_filesystem->create_directory( + CAddonBase::m_interface->toKodi->kodiBase, cacheDirectory.c_str())) + m_file = CAddonBase::m_interface->toKodi->kodi_filesystem->open_file_for_write( + CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), overwrite); + } + return m_file != nullptr; + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Check file is opened. /// - /// /* In this example we use the user path for the add-on */ - /// std::string file = kodi::GetUserPath() + "/myFile.txt"; + /// @return True on open or false on closed or failure /// - /// /* Now create and open the file or overwrite if present */ - /// myFile.OpenFileForWrite(file, true); + bool IsOpen() { return m_file != nullptr; } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Close an open file. /// - /// const char* str = "I love Kodi!"; + void Close() + { + using namespace kodi::addon; + + if (!m_file) + return; + CAddonBase::m_interface->toKodi->kodi_filesystem->close_file( + CAddonBase::m_interface->toKodi->kodiBase, m_file); + m_file = nullptr; + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Create a Curl representation /// - /// /* write string */ - /// myFile.Write(str, sizeof(str)); + /// @param[in] url The URL of the Type. + /// @return True on success or false on failure /// - /// /* On this way the Close() is not needed to call, becomes done from destructor */ + bool CURLCreate(const std::string& url) + { + using namespace kodi::addon; + + m_file = CAddonBase::m_interface->toKodi->kodi_filesystem->curl_create( + CAddonBase::m_interface->toKodi->kodiBase, url.c_str()); + return m_file != nullptr; + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Add options to the curl file created with CURLCreate. /// - /// ~~~~~~~~~~~~~ + /// @param[in] type Option type to set, see @ref CURLOptiontype + /// @param[in] name Name of the option + /// @param[in] value Value of the option + /// @return True on success or false on failure /// - //@{ - class CFile + bool CURLAddOption(CURLOptiontype type, const std::string& name, const std::string& value) { - public: - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Construct a new, unopened file - /// - CFile() = default; - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Close() is called from the destructor, so explicitly closing the - /// file isn't required - /// - virtual ~CFile() { Close(); } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Open the file with filename via Kodi's \ref cpp_kodi_vfs_CFile - /// "CFile". Needs to be closed by calling Close() when done. - /// - /// @param[in] filename The filename to open. - /// @param[in] flags [opt] The flags to pass, see \ref OpenFileFlags - /// @return True on success or false on failure - /// - bool OpenFile(const std::string& filename, unsigned int flags = 0) - { - Close(); - m_file = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->open_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), flags); - return m_file != nullptr; - } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Open the file with filename via Kodi's \ref cpp_kodi_vfs_CFile - /// "CFile" in write mode. Needs to be closed by calling Close() when - /// done. - /// - /// @note Related folders becomes created if not present. - /// - /// @param[in] filename The filename to open. - /// @param[in] overwrite True to overwrite, false otherwise. - /// @return True on success or false on failure - /// - bool OpenFileForWrite(const std::string& filename, bool overwrite = false) - { - Close(); + using namespace kodi::addon; - // Try to open the file. If it fails, check if we need to create the directory first - // This way we avoid checking if the directory exists every time - m_file = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->open_file_for_write(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), overwrite); - if (!m_file) - { - std::string cacheDirectory = kodi::vfs::GetDirectoryName(filename); - if (::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->directory_exists(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, cacheDirectory.c_str()) || - ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->create_directory(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, cacheDirectory.c_str())) - m_file = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->open_file_for_write(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), overwrite); - } - return m_file != nullptr; - } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Create a Curl representation - /// - /// @param[in] url the URL of the Type. - /// @return True on success or false on failure - /// - bool CURLCreate(const std::string& url) - { - m_file = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->curl_create(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, url.c_str()); - return m_file != nullptr; - } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Add options to the curl file created with CURLCreate - /// - /// @param[in] type option type to set, see \ref CURLOptiontype - /// @param[in] name name of the option - /// @param[in] value value of the option - /// @return True on success or false on failure - /// - bool CURLAddOption(CURLOptiontype type, const std::string& name, const std::string& value) - { - if (!m_file) - { - kodi::Log(ADDON_LOG_ERROR, "kodi::vfs::CURLCreate(...) needed to call before!"); - return false; - } - return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->curl_add_option(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file, type, name.c_str(), value.c_str()); - } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Open the curl file created with CURLCreate - /// - /// @param[in] flags [opt] The flags to pass, see \ref OpenFileFlags - /// @return True on success or false on failure - /// - bool CURLOpen(unsigned int flags = 0) + if (!m_file) { - if (!m_file) - { - kodi::Log(ADDON_LOG_ERROR, "kodi::vfs::CURLCreate(...) needed to call before!"); - return false; - } - return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->curl_open(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file, flags); - } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Read from an open file. - /// - /// @param[in] ptr The buffer to store the data in. - /// @param[in] size The size of the buffer. - /// @return number of successfully read bytes if any bytes - /// were read and stored in buffer, zero if no bytes - /// are available to read (end of file was reached) - /// or undetectable error occur, -1 in case of any - /// explicit error - /// - ssize_t Read(void* ptr, size_t size) - { - if (!m_file) - return -1; - return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->read_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file, ptr, size); - } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Read a string from an open file. - /// - /// @param[out] line The buffer to store the data in. - /// @return True when a line was read, false otherwise. - /// - bool ReadLine(std::string &line) - { - line.clear(); - if (!m_file) - return false; - // TODO: Read 1024 chars into buffer. If file position advanced that many - // chars, we didn't hit a newline. Otherwise, if file position is 1 or 2 - // past the number of bytes read, we read (and skipped) a newline sequence. - char buffer[1025]; - if (::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->read_file_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file, buffer, sizeof(buffer))) - { - line = buffer; - return !line.empty(); - } + kodi::Log(ADDON_LOG_ERROR, "kodi::vfs::CURLCreate(...) needed to call before!"); return false; } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Write to a file opened in write mode. - /// - /// @param[in] ptr Pointer to the data to write, converted to a - /// const void*. - /// @param[in] size Size of the data to write. - /// @return number of successfully written bytes if any - /// bytes were written, zero if no bytes were - /// written and no detectable error occur,-1 in case - /// of any explicit error - /// - ssize_t Write(const void* ptr, size_t size) - { - if (!m_file) - return -1; - return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->write_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file, ptr, size); - } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Flush buffered data. - /// - /// If the given stream was open for writing (or if it was open for updating - /// and the last i/o operation was an output operation) any unwritten data - /// in its output buffer is written to the file. - /// - /// The stream remains open after this call. - /// - /// When a file is closed, either because of a call to close or because the - /// class is destructed, all the buffers associated with it are - /// automatically flushed. - /// - void Flush() - { - if (!m_file) - return; - ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->flush_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file); - } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Set the file's current position. - /// - /// The whence argument is optional and defaults to SEEK_SET (0) - /// - /// @param[in] position the position that you want to seek to - /// @param[in] whence [optional] offset relative to - /// You can set the value of whence to one. - /// of three things: - /// | Value | int | Description | - /// |:--------:|:---:|:----------------------------------------------------| - /// | SEEK_SET | 0 | position is relative to the beginning of the file. This is probably what you had in mind anyway, and is the most commonly used value for whence. - /// | SEEK_CUR | 1 | position is relative to the current file pointer position. So, in effect, you can say, "Move to my current position plus 30 bytes," or, "move to my current position minus 20 bytes." - /// | SEEK_END | 2 | position is relative to the end of the file. Just like SEEK_SET except from the other end of the file. Be sure to use negative values for offset if you want to back up from the end of the file, instead of going past the end into oblivion. - /// - /// @return Returns the resulting offset location as - /// measured in bytes from the beginning of - /// the file. On error, the value -1 is - /// returned. - /// - int64_t Seek(int64_t position, int whence = SEEK_SET) - { - if (!m_file) - return -1; - return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->seek_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file, position, whence); - } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Truncate a file to the requested size. - /// - /// @param[in] size The new max size. - /// @return New size? On error, the value -1 is - /// returned. - /// - int Truncate(int64_t size) - { - if (!m_file) - return -1; - return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->truncate_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file, size); - } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief The current offset in an open file. - /// - /// @return The requested offset. On error, the value -1 is - /// returned. - /// - int64_t GetPosition() - { - if (!m_file) - return -1; - return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_position(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file); - } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Get the file size of an open file. - /// - /// @return The requested size. On error, the value -1 is - /// returned. - /// - int64_t GetLength() + return CAddonBase::m_interface->toKodi->kodi_filesystem->curl_add_option( + CAddonBase::m_interface->toKodi->kodiBase, m_file, type, name.c_str(), value.c_str()); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Open the curl file created with CURLCreate. + /// + /// @param[in] flags [opt] The flags to pass, see @ref OpenFileFlags + /// @return True on success or false on failure + /// + bool CURLOpen(unsigned int flags = 0) + { + using namespace kodi::addon; + + if (!m_file) { - if (!m_file) - return -1; - return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_length(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file); + kodi::Log(ADDON_LOG_ERROR, "kodi::vfs::CURLCreate(...) needed to call before!"); + return false; } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Checks the file access is on end position. - /// - /// @return If you've reached the end of the file, AtEnd() returns true. - /// - bool AtEnd() + return CAddonBase::m_interface->toKodi->kodi_filesystem->curl_open( + CAddonBase::m_interface->toKodi->kodiBase, m_file, flags); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Read from an open file. + /// + /// @param[in] ptr The buffer to store the data in. + /// @param[in] size The size of the buffer. + /// @return number of successfully read bytes if any bytes were read and + /// stored in buffer, zero if no bytes are available to read (end of + /// file was reached) or undetectable error occur, -1 in case of any + /// explicit error + /// + ssize_t Read(void* ptr, size_t size) + { + using namespace kodi::addon; + + if (!m_file) + return -1; + return CAddonBase::m_interface->toKodi->kodi_filesystem->read_file( + CAddonBase::m_interface->toKodi->kodiBase, m_file, ptr, size); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Read a string from an open file. + /// + /// @param[out] line The buffer to store the data in. + /// @return True when a line was read, false otherwise. + /// + bool ReadLine(std::string& line) + { + using namespace kodi::addon; + + line.clear(); + if (!m_file) + return false; + // TODO: Read 1024 chars into buffer. If file position advanced that many + // chars, we didn't hit a newline. Otherwise, if file position is 1 or 2 + // past the number of bytes read, we read (and skipped) a newline sequence. + char buffer[1025]; + if (CAddonBase::m_interface->toKodi->kodi_filesystem->read_file_string( + CAddonBase::m_interface->toKodi->kodiBase, m_file, buffer, sizeof(buffer))) { - if (!m_file) - return true; - int64_t length = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_length(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file); - int64_t position = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_position(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file); - return position >= length; + line = buffer; + return !line.empty(); } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Close an open file. - /// - void Close() + return false; + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Write to a file opened in write mode. + /// + /// @param[in] ptr Pointer to the data to write, converted to a `const void*`. + /// @param[in] size Size of the data to write. + /// @return number of successfully written bytes if any bytes were written, + /// zero if no bytes were written and no detectable error occur,-1 + /// in case of any explicit error + /// + ssize_t Write(const void* ptr, size_t size) + { + using namespace kodi::addon; + + if (!m_file) + return -1; + return CAddonBase::m_interface->toKodi->kodi_filesystem->write_file( + CAddonBase::m_interface->toKodi->kodiBase, m_file, ptr, size); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Flush buffered data. + /// + /// If the given stream was open for writing (or if it was open for updating + /// and the last i/o operation was an output operation) any unwritten data + /// in its output buffer is written to the file. + /// + /// The stream remains open after this call. + /// + /// When a file is closed, either because of a call to close or because the + /// class is destructed, all the buffers associated with it are + /// automatically flushed. + /// + void Flush() + { + using namespace kodi::addon; + + if (!m_file) + return; + CAddonBase::m_interface->toKodi->kodi_filesystem->flush_file( + CAddonBase::m_interface->toKodi->kodiBase, m_file); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Set the file's current position. + /// + /// The whence argument is optional and defaults to SEEK_SET (0) + /// + /// @param[in] position the position that you want to seek to + /// @param[in] whence [optional] offset relative to You can set the value of + /// whence to one of three things: + /// | Value | int | Description | + /// |:--------:|:---:|:----------------------------------------------------| + /// | SEEK_SET | 0 | position is relative to the beginning of the file. This is probably what you had in mind anyway, and is the most commonly used value for whence. + /// | SEEK_CUR | 1 | position is relative to the current file pointer position. So, in effect, you can say, "Move to my current position plus 30 bytes," or, "move to my current position minus 20 bytes." + /// | SEEK_END | 2 | position is relative to the end of the file. Just like SEEK_SET except from the other end of the file. Be sure to use negative values for offset if you want to back up from the end of the file, instead of going past the end into oblivion. + /// + /// @return Returns the resulting offset location as measured in bytes from + /// the beginning of the file. On error, the value -1 is returned. + /// + int64_t Seek(int64_t position, int whence = SEEK_SET) + { + using namespace kodi::addon; + + if (!m_file) + return -1; + return CAddonBase::m_interface->toKodi->kodi_filesystem->seek_file( + CAddonBase::m_interface->toKodi->kodiBase, m_file, position, whence); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Truncate a file to the requested size. + /// + /// @param[in] size The new max size. + /// @return New size? On error, the value -1 is returned. + /// + int Truncate(int64_t size) + { + using namespace kodi::addon; + + if (!m_file) + return -1; + return CAddonBase::m_interface->toKodi->kodi_filesystem->truncate_file( + CAddonBase::m_interface->toKodi->kodiBase, m_file, size); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief The current offset in an open file. + /// + /// @return The requested offset. On error, the value -1 is returned. + /// + int64_t GetPosition() + { + using namespace kodi::addon; + + if (!m_file) + return -1; + return CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_position( + CAddonBase::m_interface->toKodi->kodiBase, m_file); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Get the file size of an open file. + /// + /// @return The requested size. On error, the value -1 is returned. + /// + int64_t GetLength() + { + using namespace kodi::addon; + + if (!m_file) + return -1; + return CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_length( + CAddonBase::m_interface->toKodi->kodiBase, m_file); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Checks the file access is on end position. + /// + /// @return If you've reached the end of the file, AtEnd() returns true. + /// + bool AtEnd() + { + using namespace kodi::addon; + + if (!m_file) + return true; + int64_t length = CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_length( + CAddonBase::m_interface->toKodi->kodiBase, m_file); + int64_t position = CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_position( + CAddonBase::m_interface->toKodi->kodiBase, m_file); + return position >= length; + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Get the chunk size for an open file. + /// + /// @return The requested size. On error, the value -1 is returned. + /// + int GetChunkSize() + { + using namespace kodi::addon; + + if (!m_file) + return -1; + return CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_chunk_size( + CAddonBase::m_interface->toKodi->kodiBase, m_file); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief To check seek possible on current stream by file. + /// + /// @return true if seek possible, false if not + /// + bool IoControlGetSeekPossible() + { + using namespace kodi::addon; + + if (!m_file) + return -1; + return CAddonBase::m_interface->toKodi->kodi_filesystem->io_control_get_seek_possible( + CAddonBase::m_interface->toKodi->kodiBase, m_file); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief To check a running stream on file for state of his cache. + /// + /// @param[in] status Information about current cache status + /// @return true if successfull done, false otherwise + /// + /// + /// @copydetails cpp_kodi_vfs_Defs_CacheStatus_Help + /// + bool IoControlGetCacheStatus(CacheStatus& status) + { + using namespace kodi::addon; + + if (!m_file) + return -1; + return CAddonBase::m_interface->toKodi->kodi_filesystem->io_control_get_cache_status( + CAddonBase::m_interface->toKodi->kodiBase, m_file, status); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Unsigned int with speed limit for caching in bytes per second. + /// + /// @param[in] rate Cache rate size to use + /// @return true if successfull done, false otherwise + /// + bool IoControlSetCacheRate(unsigned int rate) + { + using namespace kodi::addon; + + if (!m_file) + return -1; + return CAddonBase::m_interface->toKodi->kodi_filesystem->io_control_set_cache_rate( + CAddonBase::m_interface->toKodi->kodiBase, m_file, rate); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Enable/disable retry within the protocol handler (if supported). + /// + /// @param[in] retry To set the retry, true for use, false for not + /// @return true if successfull done, false otherwise + /// + bool IoControlSetRetry(bool retry) + { + using namespace kodi::addon; + + if (!m_file) + return -1; + return CAddonBase::m_interface->toKodi->kodi_filesystem->io_control_set_retry( + CAddonBase::m_interface->toKodi->kodiBase, m_file, retry); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Retrieve a file property. + /// + /// @param[in] type The type of the file property to retrieve the value for + /// @param[in] name The name of a named property value (e.g. Header) + /// @return value of requested property, empty on failure / non-existance + /// + const std::string GetPropertyValue(FilePropertyTypes type, const std::string& name) const + { + using namespace kodi::addon; + + if (!m_file) { - if (!m_file) - return; - ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->close_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file); - m_file = nullptr; + kodi::Log(ADDON_LOG_ERROR, + "kodi::vfs::CURLCreate(...) needed to call before GetPropertyValue!"); + return ""; } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Get the chunk size for an open file. - /// - /// @return The requested size. On error, the value -1 is - /// returned. - /// - int GetChunkSize() + std::vector values = GetPropertyValues(type, name); + if (values.empty()) { - if (!m_file) - return -1; - return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_chunk_size(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file); + return ""; } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief retrieve a file property - /// - /// @param[in] type The type of the file property to retrieve the value for - /// @param[in] name The name of a named property value (e.g. Header) - /// @return value of requested property, empty on failure / non-existance - /// - const std::string GetPropertyValue(FilePropertyTypes type, const std::string &name) const + return values[0]; + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Retrieve file property values. + /// + /// @param[in] type The type of the file property values to retrieve the value for + /// @param[in] name The name of the named property (e.g. Header) + /// @return values of requested property, empty vector on failure / non-existance + /// + const std::vector GetPropertyValues(FilePropertyTypes type, + const std::string& name) const + { + using namespace kodi::addon; + + if (!m_file) { - if (!m_file) - { - kodi::Log(ADDON_LOG_ERROR, "kodi::vfs::CURLCreate(...) needed to call before GetPropertyValue!"); - return ""; - } - std::vector values = GetPropertyValues(type, name); - if (values.empty()) { - return ""; - } - return values[0]; + kodi::Log(ADDON_LOG_ERROR, + "kodi::vfs::CURLCreate(...) needed to call before GetPropertyValues!"); + return std::vector(); } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief retrieve file property values - /// - /// @param[in] type The type of the file property values to retrieve the value for - /// @param[in] name The name of the named property (e.g. Header) - /// @return values of requested property, empty vector on failure / non-existance - /// - const std::vector GetPropertyValues(FilePropertyTypes type, const std::string &name) const + int numValues; + char** res(CAddonBase::m_interface->toKodi->kodi_filesystem->get_property_values( + CAddonBase::m_interface->toKodi->kodiBase, m_file, type, name.c_str(), &numValues)); + if (res) { - if (!m_file) - { - kodi::Log(ADDON_LOG_ERROR, "kodi::vfs::CURLCreate(...) needed to call before GetPropertyValues!"); - return std::vector(); - } - int numValues; - char **res(::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_property_values( - ::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file, type, name.c_str(), &numValues)); - if (res) + std::vector vecReturn; + for (int i = 0; i < numValues; ++i) { - std::vector vecReturn; - for (int i = 0; i < numValues; ++i) - { - vecReturn.emplace_back(res[i]); - } - ::kodi::addon::CAddonBase::m_interface->toKodi->free_string_array(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, res, numValues); - return vecReturn; + vecReturn.emplace_back(res[i]); } - return std::vector(); - } - //-------------------------------------------------------------------------- - - //========================================================================== - /// - /// @ingroup cpp_kodi_vfs_CFile - /// @brief Get the current download speed of file if loaded from web. - /// - /// @return The current download speed. - /// - double GetFileDownloadSpeed() - { - if (!m_file) - return 0.0; - return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_download_speed(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file); + CAddonBase::m_interface->toKodi->free_string_array(CAddonBase::m_interface->toKodi->kodiBase, + res, numValues); + return vecReturn; } - //-------------------------------------------------------------------------- + return std::vector(); + } + //-------------------------------------------------------------------------- - private: - void* m_file = nullptr; - }; - //@} - //---------------------------------------------------------------------------- + //========================================================================== + /// @ingroup cpp_kodi_vfs_CFile + /// @brief Get the current download speed of file if loaded from web. + /// + /// @return The current download speed. + /// + double GetFileDownloadSpeed() + { + using namespace kodi::addon; + + if (!m_file) + return 0.0; + return CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_download_speed( + CAddonBase::m_interface->toKodi->kodiBase, m_file); + } + //-------------------------------------------------------------------------- + +private: + void* m_file = nullptr; +}; +//@} +//------------------------------------------------------------------------------ + +//}}} } /* namespace vfs */ } /* namespace kodi */ + +#endif /* __cplusplus */ diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/General.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/General.h index 6f7c8bb46b352..a3858fd75541a 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/General.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/General.h @@ -57,6 +57,7 @@ typedef struct AddonToKodiFuncTable_kodi char* (*get_region)(void* kodiBase, const char* id); void (*get_free_mem)(void* kodiBase, long* free, long* total, bool as_bytes); int (*get_global_idle_time)(void* kodiBase); + bool (*is_addon_avilable)(void* kodiBase, const char* id, char** version, bool* enabled); void (*kodi_version)(void* kodiBase, char** compile_name, int* major, int* minor, char** revision, char** tag, char** tagversion); char* (*get_current_skin_id)(void* kodiBase); bool (*get_keyboard_layout)(void* kodiBase, char** layout_name, int modifier_key, AddonKeyboardKeyTable* layout); @@ -675,6 +676,48 @@ inline std::string GetCurrentSkinId() } /* namespace kodi */ //------------------------------------------------------------------------------ +namespace kodi +{ + +//============================================================================== +/// @brief To check another addon is available and usable inside Kodi. +/// +/// @param[in] id The wanted addon identification string to check +/// @param[out] version Version string of addon if **installed** inside Kodi +/// @param[out] enabled Set to true `true* if addon is enabled +/// @return Returns `true* if addon is installed +/// +/// +/// ------------------------------------------------------------------------ +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include +/// +/// bool enabled = false; +/// std::string version; +/// bool ret = kodi::IsAddonAvailable("inputstream.adaptive", version, enabled); +/// fprintf(stderr, "Available inputstream.adaptive version '%s' and enabled '%s'\n", +/// ret ? version.c_str() : "not installed", enabled ? "yes" : "no"); +/// ~~~~~~~~~~~~~ +/// +inline bool IsAddonAvailable(const std::string& id, std::string& version, bool& enabled) +{ + AddonToKodiFuncTable_Addon* toKodi = ::kodi::addon::CAddonBase::m_interface->toKodi; + + char* cVersion = nullptr; + bool ret = toKodi->kodi->is_addon_avilable(toKodi->kodiBase, id.c_str(), &cVersion, &enabled); + if (cVersion) + { + version = cVersion; + toKodi->free_string(toKodi->kodiBase, cVersion); + } + return ret; +} +//------------------------------------------------------------------------------ + +} /* namespace kodi */ + //============================================================================== namespace kodi { /// diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/Network.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/Network.h index a0187de606560..00ef49171addf 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/Network.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/Network.h @@ -8,6 +8,7 @@ #pragma once +#include "AddonBase.h" #include "c-api/network.h" #ifdef __cplusplus diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioDecoder.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioDecoder.h index d10799fe6753b..7a125c8999fe8 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioDecoder.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioDecoder.h @@ -200,9 +200,14 @@ class CInstanceAudioDecoder : public IAddonInstance /// /// @param[in] instance The addon instance class handler given by Kodi /// at \ref kodi::addon::CAddonBase::CreateInstance(...) + /// @param[in] kodiVersion [opt] Version used in Kodi for this instance, to + /// allow compatibility to older Kodi versions. + /// @note Recommended to set. /// - explicit CInstanceAudioDecoder(KODI_HANDLE instance) - : IAddonInstance(ADDON_INSTANCE_AUDIODECODER) + explicit CInstanceAudioDecoder(KODI_HANDLE instance, const std::string& kodiVersion = "") + : IAddonInstance(ADDON_INSTANCE_AUDIODECODER, + !kodiVersion.empty() ? kodiVersion + : GetKodiTypeVersion(ADDON_INSTANCE_AUDIODECODER)) { if (CAddonBase::m_interface->globalSingleInstance != nullptr) throw std::logic_error("kodi::addon::CInstanceAudioDecoder: Creation of multiple together with single instance way is not allowed!"); diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioEncoder.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioEncoder.h index b98884e324a5b..12a4fda01952b 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioEncoder.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioEncoder.h @@ -64,8 +64,14 @@ namespace addon /// @param[in] instance The from Kodi given instance given be /// add-on CreateInstance call with instance /// id ADDON_INSTANCE_AUDIOENCODER. - explicit CInstanceAudioEncoder(KODI_HANDLE instance) - : IAddonInstance(ADDON_INSTANCE_AUDIOENCODER) + /// @param[in] kodiVersion [opt] Version used in Kodi for this instance, to + /// allow compatibility to older Kodi versions. + /// @note Recommended to set. + /// + explicit CInstanceAudioEncoder(KODI_HANDLE instance, const std::string& kodiVersion = "") + : IAddonInstance(ADDON_INSTANCE_AUDIOENCODER, + !kodiVersion.empty() ? kodiVersion + : GetKodiTypeVersion(ADDON_INSTANCE_AUDIOENCODER)) { if (CAddonBase::m_interface->globalSingleInstance != nullptr) throw std::logic_error("kodi::addon::CInstanceAudioEncoder: Creation of multiple together with single instance way is not allowed!"); diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Game.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Game.h index 2c916144332c6..8d7799770d8d8 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Game.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Game.h @@ -1342,8 +1342,7 @@ class CInstanceGame : public IAddonInstance /// ADDONCREATOR(CGameExample) /// ~~~~~~~~~~~~~ /// - CInstanceGame() - : IAddonInstance(ADDON_INSTANCE_GAME) + CInstanceGame() : IAddonInstance(ADDON_INSTANCE_GAME, GetKodiTypeVersion(ADDON_INSTANCE_GAME)) { if (CAddonBase::m_interface->globalSingleInstance != nullptr) throw std::logic_error("kodi::addon::CInstanceGame: Creation of more as one in single " @@ -1666,7 +1665,7 @@ class CInstanceGame : public IAddonInstance } AddonToKodiFuncTable_Game& cb = - dynamic_cast(CAddonBase::m_interface->globalSingleInstance) + static_cast(CAddonBase::m_interface->globalSingleInstance) ->m_instanceData->toKodi; m_handle = cb.OpenStream(cb.kodiInstance, &properties); return m_handle != nullptr; @@ -1686,7 +1685,7 @@ class CInstanceGame : public IAddonInstance return; AddonToKodiFuncTable_Game& cb = - dynamic_cast(CAddonBase::m_interface->globalSingleInstance) + static_cast(CAddonBase::m_interface->globalSingleInstance) ->m_instanceData->toKodi; cb.CloseStream(cb.kodiInstance, m_handle); m_handle = nullptr; @@ -1713,7 +1712,7 @@ class CInstanceGame : public IAddonInstance return false; AddonToKodiFuncTable_Game& cb = - dynamic_cast(CAddonBase::m_interface->globalSingleInstance) + static_cast(CAddonBase::m_interface->globalSingleInstance) ->m_instanceData->toKodi; return cb.GetStreamBuffer(cb.kodiInstance, m_handle, width, height, &buffer); } @@ -1734,7 +1733,7 @@ class CInstanceGame : public IAddonInstance return; AddonToKodiFuncTable_Game& cb = - dynamic_cast(CAddonBase::m_interface->globalSingleInstance) + static_cast(CAddonBase::m_interface->globalSingleInstance) ->m_instanceData->toKodi; cb.AddStreamData(cb.kodiInstance, m_handle, &packet); } @@ -1755,7 +1754,7 @@ class CInstanceGame : public IAddonInstance return; AddonToKodiFuncTable_Game& cb = - dynamic_cast(CAddonBase::m_interface->globalSingleInstance) + static_cast(CAddonBase::m_interface->globalSingleInstance) ->m_instanceData->toKodi; cb.ReleaseStreamBuffer(cb.kodiInstance, m_handle, &buffer); } diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/ImageDecoder.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/ImageDecoder.h index 09ac6c9319167..35ff48cc5b140 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/ImageDecoder.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/ImageDecoder.h @@ -70,8 +70,14 @@ namespace addon /// @param[in] instance The from Kodi given instance given be /// add-on CreateInstance call with instance /// id ADDON_INSTANCE_IMAGEDECODER. - explicit CInstanceImageDecoder(KODI_HANDLE instance) - : IAddonInstance(ADDON_INSTANCE_IMAGEDECODER) + /// @param[in] kodiVersion [opt] Version used in Kodi for this instance, to + /// allow compatibility to older Kodi versions. + /// @note Recommended to set. + /// + explicit CInstanceImageDecoder(KODI_HANDLE instance, const std::string& kodiVersion = "") + : IAddonInstance(ADDON_INSTANCE_IMAGEDECODER, + !kodiVersion.empty() ? kodiVersion + : GetKodiTypeVersion(ADDON_INSTANCE_IMAGEDECODER)) { if (CAddonBase::m_interface->globalSingleInstance != nullptr) throw std::logic_error("kodi::addon::CInstanceImageDecoder: Creation of multiple together with single instance way is not allowed!"); diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h index 478fd27f48267..b65ba18e7ef27 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h @@ -388,14 +388,16 @@ namespace addon class CInstanceInputStream : public IAddonInstance { public: - explicit CInstanceInputStream(KODI_HANDLE instance, const std::string& kodiVersion = "0.0.0") - : IAddonInstance(ADDON_INSTANCE_INPUTSTREAM) + explicit CInstanceInputStream(KODI_HANDLE instance, const std::string& kodiVersion = "") + : IAddonInstance(ADDON_INSTANCE_INPUTSTREAM, + !kodiVersion.empty() ? kodiVersion + : GetKodiTypeVersion(ADDON_INSTANCE_INPUTSTREAM)) { if (CAddonBase::m_interface->globalSingleInstance != nullptr) throw std::logic_error("kodi::addon::CInstanceInputStream: Creation of multiple together " "with single instance way is not allowed!"); - SetAddonStruct(instance, kodiVersion); + SetAddonStruct(instance, m_kodiVersion); } ~CInstanceInputStream() override = default; diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h index 2df8a3678d3af..c80e73f1fa9d6 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h @@ -457,7 +457,7 @@ namespace addon { public: CInstancePeripheral() - : IAddonInstance(ADDON_INSTANCE_PERIPHERAL) + : IAddonInstance(ADDON_INSTANCE_PERIPHERAL, GetKodiTypeVersion(ADDON_INSTANCE_PERIPHERAL)) { if (CAddonBase::m_interface->globalSingleInstance != nullptr) throw std::logic_error("kodi::addon::CInstancePeripheral: Creation of more as one in single instance way is not allowed!"); @@ -466,8 +466,10 @@ namespace addon CAddonBase::m_interface->globalSingleInstance = this; } - explicit CInstancePeripheral(KODI_HANDLE instance) - : IAddonInstance(ADDON_INSTANCE_PERIPHERAL) + explicit CInstancePeripheral(KODI_HANDLE instance, const std::string& kodiVersion = "") + : IAddonInstance(ADDON_INSTANCE_PERIPHERAL, + !kodiVersion.empty() ? kodiVersion + : GetKodiTypeVersion(ADDON_INSTANCE_PERIPHERAL)) { if (CAddonBase::m_interface->globalSingleInstance != nullptr) throw std::logic_error("kodi::addon::CInstancePeripheral: Creation of multiple together with single instance way is not allowed!"); diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Screensaver.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Screensaver.h index cc942ab82b223..eae836f82f6e6 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Screensaver.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Screensaver.h @@ -230,7 +230,7 @@ namespace addon /// Used by an add-on that only supports screensavers. /// CInstanceScreensaver() - : IAddonInstance(ADDON_INSTANCE_SCREENSAVER) + : IAddonInstance(ADDON_INSTANCE_SCREENSAVER, GetKodiTypeVersion(ADDON_INSTANCE_SCREENSAVER)) { if (CAddonBase::m_interface->globalSingleInstance != nullptr) throw std::logic_error("kodi::addon::CInstanceScreensaver: Creation of more as one in single instance way is not allowed!"); @@ -248,11 +248,16 @@ namespace addon /// /// @param[in] instance The instance value given to /// `kodi::addon::CAddonBase::CreateInstance(...)`. + /// @param[in] kodiVersion [opt] Version used in Kodi for this instance, to + /// allow compatibility to older Kodi versions. + /// @note Recommended to set. /// /// @warning Only use `instance` from the CreateInstance call /// - explicit CInstanceScreensaver(KODI_HANDLE instance) - : IAddonInstance(ADDON_INSTANCE_SCREENSAVER) + explicit CInstanceScreensaver(KODI_HANDLE instance, const std::string& kodiVersion = "") + : IAddonInstance(ADDON_INSTANCE_SCREENSAVER, + !kodiVersion.empty() ? kodiVersion + : GetKodiTypeVersion(ADDON_INSTANCE_SCREENSAVER)) { if (CAddonBase::m_interface->globalSingleInstance != nullptr) throw std::logic_error("kodi::addon::CInstanceScreensaver: Creation of multiple together with single instance way is not allowed!"); @@ -440,7 +445,7 @@ namespace addon /* * Background render helper holds here and in addon base. - * In addon base also to have for the others, and stored here for the worst + * In addon base also to have for the others, and stored here for the worst * case where this class is independent from base and base becomes closed * before. * diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VFS.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VFS.h index 7a33d4b794295..53c3569b76bfc 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VFS.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VFS.h @@ -10,6 +10,17 @@ #include "../AddonBase.h" #include "../Filesystem.h" +#if !defined(_WIN32) +#include +#if !defined(__stat64) +#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) +#define __stat64 stat +#else +#define __stat64 stat64 +#endif +#endif +#endif + #ifdef __cplusplus extern "C" { @@ -501,20 +512,20 @@ namespace addon /// { /// public: /// CMyAddon() { } -/// ADDON_STATUS CreateInstanceEx(int instanceType, -/// std::string instanceID, -/// KODI_HANDLE instance, -/// KODI_HANDLE& addonInstance, -/// const std::string& version) override; +/// ADDON_STATUS CreateInstance(int instanceType, +/// const std::string& instanceID, +/// KODI_HANDLE instance, +/// const std::string& version, +/// KODI_HANDLE& addonInstance) override; /// }; /// /// // If you use only one instance in your add-on, can be instanceType and /// // instanceID ignored -/// ADDON_STATUS CMyAddon::CreateInstanceEx(int instanceType, -/// std::string instanceID, -/// KODI_HANDLE instance, -/// KODI_HANDLE& addonInstance, -/// const std::string& version) +/// ADDON_STATUS CMyAddon::CreateInstance(int instanceType, +/// const std::string& instanceID, +/// KODI_HANDLE instance, +/// const std::string& version, +/// KODI_HANDLE& addonInstance) /// { /// if (instanceType == ADDON_INSTANCE_VFS) /// { @@ -547,23 +558,24 @@ class CInstanceVFS : public IAddonInstance /// /// @param[in] instance The instance value given to /// `kodi::addon::CAddonBase::CreateInstance(...)`. - /// @param[in] kodiVersion [opt] given from Kodi by @ref CAddonBase::CreateInstanceEx + /// @param[in] kodiVersion [opt] given from Kodi by @ref CAddonBase::CreateInstance /// to identify his instance API version /// /// @note Instance path as a single is not supported by this type. It must /// ensure that it can be called up several times. /// /// @warning Only use `instance` from the @ref CAddonBase::CreateInstance or - /// @ref CAddonBase::CreateInstanceEx call. + /// @ref CAddonBase::CreateInstance call. /// - explicit CInstanceVFS(KODI_HANDLE instance, const std::string& kodiVersion = "0.0.0") - : IAddonInstance(ADDON_INSTANCE_VFS) + explicit CInstanceVFS(KODI_HANDLE instance, const std::string& kodiVersion = "") + : IAddonInstance(ADDON_INSTANCE_VFS, + !kodiVersion.empty() ? kodiVersion : GetKodiTypeVersion(ADDON_INSTANCE_VFS)) { if (CAddonBase::m_interface->globalSingleInstance != nullptr) throw std::logic_error("kodi::addon::CInstanceVFS: Creation of multiple together with single " "instance way is not allowed!"); - SetAddonStruct(instance, kodiVersion); + SetAddonStruct(instance); } //-------------------------------------------------------------------------- @@ -970,7 +982,7 @@ class CInstanceVFS : public IAddonInstance //@} private: - void SetAddonStruct(KODI_HANDLE instance, const std::string& kodiVersion) + void SetAddonStruct(KODI_HANDLE instance) { if (instance == nullptr) throw std::logic_error("kodi::addon::CInstanceVFS: Creation with empty addon structure not " diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VideoCodec.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VideoCodec.h index 7adba4e042b17..95413b7988d71 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VideoCodec.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VideoCodec.h @@ -146,8 +146,10 @@ namespace kodi class CInstanceVideoCodec : public IAddonInstance { public: - explicit CInstanceVideoCodec(KODI_HANDLE instance) - : IAddonInstance(ADDON_INSTANCE_VIDEOCODEC) + explicit CInstanceVideoCodec(KODI_HANDLE instance, const std::string& kodiVersion = "") + : IAddonInstance(ADDON_INSTANCE_VIDEOCODEC, + !kodiVersion.empty() ? kodiVersion + : GetKodiTypeVersion(ADDON_INSTANCE_VIDEOCODEC)) { if (CAddonBase::m_interface->globalSingleInstance != nullptr) throw std::logic_error("kodi::addon::CInstanceVideoCodec: Creation of multiple together with single instance way is not allowed!"); diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Visualization.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Visualization.h index cda71bc020b21..66992e9077360 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Visualization.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Visualization.h @@ -309,7 +309,8 @@ namespace addon /// Used by an add-on that only supports visualizations. /// CInstanceVisualization() - : IAddonInstance(ADDON_INSTANCE_VISUALIZATION) + : IAddonInstance(ADDON_INSTANCE_VISUALIZATION, + GetKodiTypeVersion(ADDON_INSTANCE_VISUALIZATION)) { if (CAddonBase::m_interface->globalSingleInstance != nullptr) throw std::logic_error("kodi::addon::CInstanceVisualization: Cannot create multiple instances of add-on."); @@ -327,11 +328,16 @@ namespace addon /// /// @param[in] instance The instance value given to /// `kodi::addon::CAddonBase::CreateInstance(...)`. + /// @param[in] kodiVersion [opt] Version used in Kodi for this instance, to + /// allow compatibility to older Kodi versions. + /// @note Recommended to set. /// /// @warning Only use `instance` from the CreateInstance call /// - explicit CInstanceVisualization(KODI_HANDLE instance) - : IAddonInstance(ADDON_INSTANCE_VISUALIZATION) + explicit CInstanceVisualization(KODI_HANDLE instance, const std::string& kodiVersion = "") + : IAddonInstance(ADDON_INSTANCE_VISUALIZATION, + !kodiVersion.empty() ? kodiVersion + : GetKodiTypeVersion(ADDON_INSTANCE_VISUALIZATION)) { if (CAddonBase::m_interface->globalSingleInstance != nullptr) throw std::logic_error("kodi::addon::CInstanceVisualization: Creation of multiple together with single instance way is not allowed!"); diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/CMakeLists.txt b/xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/CMakeLists.txt index 000444977ce0f..1d0bf81cba35a 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/CMakeLists.txt +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/CMakeLists.txt @@ -1,4 +1,6 @@ -set(HEADERS audio_engine.h +set(HEADERS addon_base.h + audio_engine.h + filesystem.h network.h) if(NOT ENABLE_STATIC_LIBS) diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/addon_base.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/addon_base.h new file mode 100644 index 0000000000000..bc392c4740bd6 --- /dev/null +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/addon_base.h @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2005-2019 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "stdbool.h" +#include "stdint.h" + +#ifndef TARGET_WINDOWS +#ifndef __cdecl +#define __cdecl +#endif +#ifndef __declspec +#define __declspec(X) +#endif +#endif + +#undef ATTRIBUTE_PACKED +#undef PRAGMA_PACK_BEGIN +#undef PRAGMA_PACK_END + +#if defined(__GNUC__) +#define ATTRIBUTE_PACKED __attribute__((packed)) +#define PRAGMA_PACK 0 +#define ATTRIBUTE_HIDDEN __attribute__((visibility("hidden"))) +#endif + +#if !defined(ATTRIBUTE_PACKED) +#define ATTRIBUTE_PACKED +#define PRAGMA_PACK 1 +#endif + +#if !defined(ATTRIBUTE_HIDDEN) +#define ATTRIBUTE_HIDDEN +#endif + +#ifdef _MSC_VER +#define ATTRIBUTE_FORCEINLINE __forceinline +#elif defined(__GNUC__) +#define ATTRIBUTE_FORCEINLINE inline __attribute__((__always_inline__)) +#elif defined(__CLANG__) +#if __has_attribute(__always_inline__) +#define ATTRIBUTE_FORCEINLINE inline __attribute__((__always_inline__)) +#else +#define ATTRIBUTE_FORCEINLINE inline +#endif +#else +#define ATTRIBUTE_FORCEINLINE inline +#endif + +/* + * To have a on add-on and kodi itself handled string always on known size! + */ +#define ADDON_STANDARD_STRING_LENGTH 1024 +#define ADDON_STANDARD_STRING_LENGTH_SMALL 256 + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + //============================================================================ + /// @ingroup cpp_kodi_addon_addonbase + /// @brief Return value of functions in @ref cpp_kodi_addon_addonbase "kodi::addon::CAddonBase" + /// and associated classes. + /// + ///@{ + typedef enum ADDON_STATUS + { + /// @brief For everything OK and no error + ADDON_STATUS_OK, + + /// @brief A needed connection was lost + ADDON_STATUS_LOST_CONNECTION, + + /// @brief Addon needs a restart inside Kodi + ADDON_STATUS_NEED_RESTART, + + /// @brief Necessary settings are not yet set + ADDON_STATUS_NEED_SETTINGS, + + /// @brief Unknown and incomprehensible error + ADDON_STATUS_UNKNOWN, + + /// @brief Permanent failure, like failing to resolve methods + ADDON_STATUS_PERMANENT_FAILURE, + + /* internal used return error if function becomes not used from child on + * addon */ + ADDON_STATUS_NOT_IMPLEMENTED + } ADDON_STATUS; + ///@} + //---------------------------------------------------------------------------- + + //============================================================================ + /// @defgroup cpp_kodi_Defs_AddonLog enum AddonLog + /// @ingroup cpp_kodi_Defs + /// @brief **Log file type definitions**\n + /// These define the types of log entries given with @ref kodi::Log() to Kodi. + /// + /// ------------------------------------------------------------------------- + /// + /// **Example:** + /// ~~~~~~~~~~~~~{.cpp} + /// #include + /// + /// kodi::Log(ADDON_LOG_ERROR, "%s: There is an error occurred!", __func__); + /// + /// ~~~~~~~~~~~~~ + /// + ///@{ + typedef enum AddonLog + { + /// @brief **0** : To include debug information in the log file. + ADDON_LOG_DEBUG = 0, + + /// @brief **1** : To include information messages in the log file. + ADDON_LOG_INFO = 1, + + /// @brief **2** : To write warnings in the log file. + ADDON_LOG_WARNING = 2, + + /// @brief **3** : To report error messages in the log file. + ADDON_LOG_ERROR = 3, + + /// @brief **4** : To notify fatal unrecoverable errors, which can may also indicate + /// upcoming crashes. + ADDON_LOG_FATAL = 4 + } AddonLog; + ///@} + //---------------------------------------------------------------------------- + + /*! @brief Standard undefined pointer handle */ + typedef void* KODI_HANDLE; + + /*! + * @brief Handle used to return data from the PVR add-on to CPVRClient + */ + struct ADDON_HANDLE_STRUCT + { + void* callerAddress; /*!< address of the caller */ + void* dataAddress; /*!< address to store data in */ + int dataIdentifier; /*!< parameter to pass back when calling the callback */ + }; + typedef struct ADDON_HANDLE_STRUCT* ADDON_HANDLE; + + /*! + * @brief Callback function tables from addon to Kodi + * Set complete from Kodi! + */ + struct AddonToKodiFuncTable_kodi; + struct AddonToKodiFuncTable_kodi_audioengine; + struct AddonToKodiFuncTable_kodi_filesystem; + struct AddonToKodiFuncTable_kodi_network; + struct AddonToKodiFuncTable_kodi_gui; + typedef struct AddonToKodiFuncTable_Addon + { + // Pointer inside Kodi, used on callback functions to give related handle + // class, for this ADDON::CAddonDll inside Kodi. + KODI_HANDLE kodiBase; + + // Function addresses used for callbacks from addon to Kodi + char* (*get_type_version)(void* kodiBase, int type); + + void (*free_string)(void* kodiBase, char* str); + void (*free_string_array)(void* kodiBase, char** arr, int numElements); + char* (*get_addon_path)(void* kodiBase); + char* (*get_base_user_path)(void* kodiBase); + void (*addon_log_msg)(void* kodiBase, const int loglevel, const char* msg); + + bool (*get_setting_bool)(void* kodiBase, const char* id, bool* value); + bool (*get_setting_int)(void* kodiBase, const char* id, int* value); + bool (*get_setting_float)(void* kodiBase, const char* id, float* value); + bool (*get_setting_string)(void* kodiBase, const char* id, char** value); + + bool (*set_setting_bool)(void* kodiBase, const char* id, bool value); + bool (*set_setting_int)(void* kodiBase, const char* id, int value); + bool (*set_setting_float)(void* kodiBase, const char* id, float value); + bool (*set_setting_string)(void* kodiBase, const char* id, const char* value); + + void* (*get_interface)(void* kodiBase, const char* name, const char* version); + + struct AddonToKodiFuncTable_kodi* kodi; + struct AddonToKodiFuncTable_kodi_audioengine* kodi_audioengine; + struct AddonToKodiFuncTable_kodi_filesystem* kodi_filesystem; + struct AddonToKodiFuncTable_kodi_gui* kodi_gui; + struct AddonToKodiFuncTable_kodi_network* kodi_network; + } AddonToKodiFuncTable_Addon; + + /*! + * @brief Function tables from Kodi to addon + */ + typedef struct KodiToAddonFuncTable_Addon + { + void (*destroy)(); + ADDON_STATUS (*get_status)(); + ADDON_STATUS(*create_instance) + (int instanceType, + const char* instanceID, + KODI_HANDLE instance, + const char* version, + KODI_HANDLE* addonInstance, + KODI_HANDLE parent); + void (*destroy_instance)(int instanceType, KODI_HANDLE instance); + ADDON_STATUS (*set_setting)(const char* settingName, const void* settingValue); + } KodiToAddonFuncTable_Addon; + + /*! + * @brief Main structure passed from kodi to addon with basic information needed to + * create add-on. + */ + typedef struct AddonGlobalInterface + { + // String with full path where add-on is installed (without his name on end) + // Set from Kodi! + const char* libBasePath; + + // Master API version of Kodi itself (ADDON_GLOBAL_VERSION_MAIN) + const char* kodi_base_api_version; + + // Pointer of first created instance, used in case this add-on goes with single way + // Set from Kodi! + KODI_HANDLE firstKodiInstance; + + // Pointer to master base class inside add-on + // Set from addon header (kodi::addon::CAddonBase)! + KODI_HANDLE addonBase; + + // Pointer to a instance used on single way (together with this class) + // Set from addon header (kodi::addon::IAddonInstance)! + KODI_HANDLE globalSingleInstance; + + // Callback function tables from addon to Kodi + // Set from Kodi! + AddonToKodiFuncTable_Addon* toKodi; + + // Function tables from Kodi to addon + // Set from addon header! + KodiToAddonFuncTable_Addon* toAddon; + } AddonGlobalInterface; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ 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 new file mode 100644 index 0000000000000..2067d22fb6176 --- /dev/null +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/filesystem.h @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2005-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include +#include + +#ifdef _WIN32 // windows +#ifndef _SSIZE_T_DEFINED +typedef intptr_t ssize_t; +#define _SSIZE_T_DEFINED +#endif // !_SSIZE_T_DEFINED + +// Prevent conflicts with Windows macros where have this names. +#ifdef CreateDirectory +#undef CreateDirectory +#endif // CreateDirectory +#ifdef DeleteFile +#undef DeleteFile +#endif // DeleteFile +#endif // _WIN32 + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + //¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + // "C" Definitions, structures and enumerators of filesystem + //{{{ + + //============================================================================ + /// @defgroup cpp_kodi_vfs_Defs_OpenFileFlags enum OpenFileFlags + /// @ingroup cpp_kodi_vfs_Defs + /// @brief **Flags to define way how file becomes opened**\n + /// The values can be used together, e.g. `file.Open("myfile", ADDON_READ_TRUNCATED | ADDON_READ_CHUNKED);` + /// + /// Used on @ref kodi::vfs::CFile::OpenFile(). + /// + ///@{ + typedef enum OpenFileFlags + { + /// @brief **0000 0000 0001** :\n + /// Indicate that caller can handle truncated reads, where function + /// returns before entire buffer has been filled. + ADDON_READ_TRUNCATED = 0x01, + + /// @brief **0000 0000 0010** :\n + /// Indicate that that caller support read in the minimum defined + /// chunk size, this disables internal cache then. + ADDON_READ_CHUNKED = 0x02, + + /// @brief **0000 0000 0100** :\n + /// Use cache to access this file. + ADDON_READ_CACHED = 0x04, + + /// @brief **0000 0000 1000** :\n + /// Open without caching. regardless to file type. + ADDON_READ_NO_CACHE = 0x08, + + /// @brief **0000 0001 0000** :\n + /// Calcuate bitrate for file while reading. + ADDON_READ_BITRATE = 0x10, + + /// @brief **0000 0010 0000** :\n + /// Indicate to the caller we will seek between multiple streams in + /// the file frequently. + ADDON_READ_MULTI_STREAM = 0x20, + + /// @brief **0000 0100 0000** :\n + /// indicate to the caller file is audio and/or video (and e.g. may + /// grow). + ADDON_READ_AUDIO_VIDEO = 0x40, + + /// @brief **0000 1000 0000** :\n + /// Indicate that caller will do write operations before reading. + ADDON_READ_AFTER_WRITE = 0x80, + + /// @brief **0001 0000 0000** :\n + /// Indicate that caller want to reopen a file if its already open. + ADDON_READ_REOPEN = 0x100 + } OpenFileFlags; + ///@} + //---------------------------------------------------------------------------- + + //============================================================================ + /// @defgroup cpp_kodi_vfs_Defs_CURLOptiontype enum CURLOptiontype + /// @ingroup cpp_kodi_vfs_Defs + /// @brief **CURL message types**\n + /// Used on kodi::vfs::CFile::CURLAddOption(). + /// + //@{ + typedef enum CURLOptiontype + { + /// @brief Set a general option. + ADDON_CURL_OPTION_OPTION, + + /// @brief Set a protocol option. + /// + /// The following names for *ADDON_CURL_OPTION_PROTOCOL* are possible: + /// + /// | Option name | Description + /// |------------------------------------:|:-------------------------------- + /// | `accept-charset` | Set the "accept-charset" header + /// | `acceptencoding or encoding` | Set the "accept-encoding" header + /// | `active-remote` | Set the "active-remote" header + /// | `auth` | Set the authentication method. Possible values: any, anysafe, digest, ntlm + /// | `connection-timeout` | Set the connection timeout in seconds + /// | `cookie` | Set the "cookie" header + /// | `customrequest` | Set a custom HTTP request like DELETE + /// | `noshout` | Set to true if kodi detects a stream as shoutcast by mistake. + /// | `postdata` | Set the post body (value needs to be base64 encoded). (Implicitly sets the request to POST) + /// | `referer` | Set the "referer" header + /// | `user-agent` | Set the "user-agent" header + /// | `seekable` | Set the stream seekable. 1: enable, 0: disable + /// | `sslcipherlist` | Set list of accepted SSL ciphers. + /// + ADDON_CURL_OPTION_PROTOCOL, + + /// @brief Set User and password + ADDON_CURL_OPTION_CREDENTIALS, + + /// @brief Add a Header + ADDON_CURL_OPTION_HEADER + } CURLOptiontype; + //@} + //---------------------------------------------------------------------------- + + //============================================================================ + /// @defgroup cpp_kodi_vfs_Defs_FilePropertyTypes enum FilePropertyTypes + /// @ingroup cpp_kodi_vfs_Defs + /// @brief **File property types**\n + /// Mostly to read internet sources. + /// + /// Used on kodi::vfs::CFile::GetPropertyValue() and kodi::vfs::CFile::GetPropertyValues(). + /// + //@{ + typedef enum FilePropertyTypes + { + /// @brief Get protocol response line. + ADDON_FILE_PROPERTY_RESPONSE_PROTOCOL, + /// @brief Get a response header. + ADDON_FILE_PROPERTY_RESPONSE_HEADER, + /// @brief Get file content type. + ADDON_FILE_PROPERTY_CONTENT_TYPE, + /// @brief Get file content charset. + ADDON_FILE_PROPERTY_CONTENT_CHARSET, + /// @brief Get file mime type. + ADDON_FILE_PROPERTY_MIME_TYPE, + /// @brief Get file effective URL (last one if redirected). + ADDON_FILE_PROPERTY_EFFECTIVE_URL + } FilePropertyTypes; + //@} + //---------------------------------------------------------------------------- + + //}}} + + //¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + // "C" Internal interface tables for intercommunications between addon and kodi + //{{{ + + struct KODI_HTTP_HEADER + { + void* handle; + + char* (*get_value)(void* kodiBase, void* handle, const char* param); + char** (*get_values)(void* kodiBase, void* handle, const char* param, int* length); + char* (*get_header)(void* kodiBase, void* handle); + char* (*get_mime_type)(void* kodiBase, void* handle); + char* (*get_charset)(void* kodiBase, void* handle); + char* (*get_proto_line)(void* kodiBase, void* handle); + }; + + struct STAT_STRUCTURE + { + /// ID of device containing file + uint32_t deviceId; + /// Total size, in bytes + uint64_t size; + /// Time of last access + time_t accessTime; + /// Time of last modification + time_t modificationTime; + /// Time of last status change + time_t statusTime; + /// The stat url is a directory + bool isDirectory; + /// The stat url is a symbolic link + bool isSymLink; + }; + + struct VFS_CACHE_STATUS_DATA + { + uint64_t forward; + unsigned int maxrate; + unsigned int currate; + bool lowspeed; + }; + + struct VFSProperty + { + char* name; + char* val; + }; + + struct VFSDirEntry + { + char* label; //!< item label + char* title; //!< item title + char* path; //!< item path + unsigned int num_props; //!< Number of properties attached to item + struct VFSProperty* properties; //!< Properties + time_t date_time; //!< file creation date & time + bool folder; //!< Item is a folder + uint64_t size; //!< Size of file represented by item + }; + + typedef struct AddonToKodiFuncTable_kodi_filesystem + { + bool (*can_open_directory)(void* kodiBase, const char* url); + bool (*create_directory)(void* kodiBase, const char* path); + bool (*remove_directory)(void* kodiBase, const char* path); + bool (*directory_exists)(void* kodiBase, const char* path); + bool (*get_directory)(void* kodiBase, + const char* path, + const char* mask, + struct VFSDirEntry** items, + unsigned int* num_items); + void (*free_directory)(void* kodiBase, struct VFSDirEntry* items, unsigned int num_items); + + bool (*file_exists)(void* kodiBase, const char* filename, bool useCache); + bool (*stat_file)(void* kodiBase, const char* filename, struct STAT_STRUCTURE* buffer); + bool (*delete_file)(void* kodiBase, const char* filename); + bool (*rename_file)(void* kodiBase, const char* filename, const char* newFileName); + bool (*copy_file)(void* kodiBase, const char* filename, const char* dest); + + char* (*get_file_md5)(void* kodiBase, const char* filename); + char* (*get_cache_thumb_name)(void* kodiBase, const char* filename); + char* (*make_legal_filename)(void* kodiBase, const char* filename); + char* (*make_legal_path)(void* kodiBase, const char* path); + char* (*translate_special_protocol)(void* kodiBase, const char* strSource); + bool (*is_internet_stream)(void* kodiBase, const char* path, bool strictCheck); + bool (*is_on_lan)(void* kodiBase, const char* path); + bool (*is_remote)(void* kodiBase, const char* path); + bool (*is_local)(void* kodiBase, const char* path); + bool (*is_url)(void* kodiBase, const char* path); + bool (*get_http_header)(void* kodiBase, const char* url, struct KODI_HTTP_HEADER* headers); + bool (*get_mime_type)(void* kodiBase, const char* url, char** content, const char* useragent); + bool (*get_content_type)(void* kodiBase, + const char* url, + char** content, + const char* useragent); + bool (*get_cookies)(void* kodiBase, const char* url, char** cookies); + bool (*http_header_create)(void* kodiBase, struct KODI_HTTP_HEADER* headers); + void (*http_header_free)(void* kodiBase, struct KODI_HTTP_HEADER* headers); + + void* (*open_file)(void* kodiBase, const char* filename, unsigned int flags); + void* (*open_file_for_write)(void* kodiBase, const char* filename, bool overwrite); + ssize_t (*read_file)(void* kodiBase, void* file, void* ptr, size_t size); + bool (*read_file_string)(void* kodiBase, void* file, char* szLine, int iLineLength); + ssize_t (*write_file)(void* kodiBase, void* file, const void* ptr, size_t size); + void (*flush_file)(void* kodiBase, void* file); + int64_t (*seek_file)(void* kodiBase, void* file, int64_t position, int whence); + int (*truncate_file)(void* kodiBase, void* file, int64_t size); + int64_t (*get_file_position)(void* kodiBase, void* file); + int64_t (*get_file_length)(void* kodiBase, void* file); + double (*get_file_download_speed)(void* kodiBase, void* file); + void (*close_file)(void* kodiBase, void* file); + int (*get_file_chunk_size)(void* kodiBase, void* file); + bool (*io_control_get_seek_possible)(void* kodiBase, void* file); + bool (*io_control_get_cache_status)(void* kodiBase, + void* file, + struct VFS_CACHE_STATUS_DATA* status); + bool (*io_control_set_cache_rate)(void* kodiBase, void* file, unsigned int rate); + bool (*io_control_set_retry)(void* kodiBase, void* file, bool retry); + char** (*get_property_values)( + void* kodiBase, void* file, int type, const char* name, int* numValues); + + void* (*curl_create)(void* kodiBase, const char* url); + 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); + } AddonToKodiFuncTable_kodi_filesystem; + + //}}} + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/network.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/network.h index c10bdfaeedc71..97f1a3372d11e 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/network.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/c-api/network.h @@ -8,7 +8,7 @@ #pragma once -#include "../AddonBase.h" +#include #ifdef __cplusplus extern "C" @@ -28,12 +28,12 @@ extern "C" */ typedef struct AddonToKodiFuncTable_kodi_network { - bool (*wake_on_lan)(KODI_HANDLE kodiBase, const char* mac); - char* (*get_ip_address)(KODI_HANDLE kodiBase); - char* (*dns_lookup)(KODI_HANDLE kodiBase, const char* url, bool* ret); - char* (*url_encode)(KODI_HANDLE kodiBase, const char* url); - char* (*get_hostname)(KODI_HANDLE kodiBase); - bool (*is_local_host)(KODI_HANDLE kodiBase, const char* hostname); + bool (*wake_on_lan)(void* kodiBase, const char* mac); + char* (*get_ip_address)(void* kodiBase); + char* (*dns_lookup)(void* kodiBase, const char* url, bool* ret); + char* (*url_encode)(void* kodiBase, const char* url); + char* (*get_hostname)(void* kodiBase); + bool (*is_local_host)(void* kodiBase, const char* hostname); bool (*is_host_on_lan)(void* kodiBase, const char* hostname, bool offLineCheck); } AddonToKodiFuncTable_kodi_network; diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/gui/renderHelper.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/gui/renderHelper.h index 87d7b19ab2c6b..5a1a58be007c9 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/gui/renderHelper.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/gui/renderHelper.h @@ -62,14 +62,15 @@ namespace gui inline std::shared_ptr GetRenderHelper() { using namespace ::kodi::addon; - if (CAddonBase::m_interface->addonBase->m_renderHelper) - return CAddonBase::m_interface->addonBase->m_renderHelper; + if (static_cast(CAddonBase::m_interface->addonBase)->m_renderHelper) + return static_cast(CAddonBase::m_interface->addonBase)->m_renderHelper; const std::shared_ptr renderHelper(new CRenderHelper()); if (!renderHelper->Init()) return nullptr; - CAddonBase::m_interface->addonBase->m_renderHelper = renderHelper; // Hold on base for other types + static_cast(CAddonBase::m_interface->addonBase)->m_renderHelper = + renderHelper; // Hold on base for other types return renderHelper; } 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 38a5f53b1a8b3..7e8b68ac3fe14 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h @@ -30,16 +30,21 @@ * overview. */ -#define ADDON_GLOBAL_VERSION_MAIN "1.1.0" -#define ADDON_GLOBAL_VERSION_MAIN_MIN "1.0.12" +// Ignore clang here, as this must be good in overview and as the main reason, +// because cmake uses this area in this form to perform its addon dependency +// check. +// clang format off +#define ADDON_GLOBAL_VERSION_MAIN "1.2.0" +#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" \ "xbmc_addon_dll.h" \ "libXBMC_addon.h" \ - "addon-instance/" + "addon-instance/" \ + "c-api/addon_base.h" -#define ADDON_GLOBAL_VERSION_GENERAL "1.0.3" -#define ADDON_GLOBAL_VERSION_GENERAL_MIN "1.0.2" +#define ADDON_GLOBAL_VERSION_GENERAL "1.0.4" +#define ADDON_GLOBAL_VERSION_GENERAL_MIN "1.0.4" #define ADDON_GLOBAL_VERSION_GENERAL_XML_ID "kodi.binary.global.general" #define ADDON_GLOBAL_VERSION_GENERAL_DEPENDS "General.h" @@ -55,77 +60,79 @@ #define ADDON_GLOBAL_VERSION_AUDIOENGINE_DEPENDS "AudioEngine.h" \ "c-api/audio_engine.h" -#define ADDON_GLOBAL_VERSION_FILESYSTEM "1.0.3" -#define ADDON_GLOBAL_VERSION_FILESYSTEM_MIN "1.0.3" +#define ADDON_GLOBAL_VERSION_FILESYSTEM "1.1.0" +#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" \ + "c-api/filesystem.h" \ "gui/gl/Shader.h" -#define ADDON_GLOBAL_VERSION_NETWORK "1.0.1" +#define ADDON_GLOBAL_VERSION_NETWORK "1.0.2" #define ADDON_GLOBAL_VERSION_NETWORK_MIN "1.0.0" #define ADDON_GLOBAL_VERSION_NETWORK_XML_ID "kodi.binary.global.network" #define ADDON_GLOBAL_VERSION_NETWORK_DEPENDS "Network.h" \ "c-api/network.h" -#define ADDON_INSTANCE_VERSION_AUDIODECODER "2.0.0" -#define ADDON_INSTANCE_VERSION_AUDIODECODER_MIN "2.0.0" +#define ADDON_INSTANCE_VERSION_AUDIODECODER "2.0.1" +#define ADDON_INSTANCE_VERSION_AUDIODECODER_MIN "2.0.1" #define ADDON_INSTANCE_VERSION_AUDIODECODER_XML_ID "kodi.binary.instance.audiodecoder" #define ADDON_INSTANCE_VERSION_AUDIODECODER_DEPENDS "addon-instance/AudioDecoder.h" -#define ADDON_INSTANCE_VERSION_AUDIOENCODER "2.0.0" -#define ADDON_INSTANCE_VERSION_AUDIOENCODER_MIN "2.0.0" +#define ADDON_INSTANCE_VERSION_AUDIOENCODER "2.0.1" +#define ADDON_INSTANCE_VERSION_AUDIOENCODER_MIN "2.0.1" #define ADDON_INSTANCE_VERSION_AUDIOENCODER_XML_ID "kodi.binary.instance.audioencoder" #define ADDON_INSTANCE_VERSION_AUDIOENCODER_DEPENDS "addon-instance/AudioEncoder.h" -#define ADDON_INSTANCE_VERSION_GAME "2.0.0" -#define ADDON_INSTANCE_VERSION_GAME_MIN "2.0.0" +#define ADDON_INSTANCE_VERSION_GAME "2.0.1" +#define ADDON_INSTANCE_VERSION_GAME_MIN "2.0.1" #define ADDON_INSTANCE_VERSION_GAME_XML_ID "kodi.binary.instance.game" #define ADDON_INSTANCE_VERSION_GAME_DEPENDS "addon-instance/Game.h" -#define ADDON_INSTANCE_VERSION_IMAGEDECODER "2.0.0" -#define ADDON_INSTANCE_VERSION_IMAGEDECODER_MIN "2.0.0" +#define ADDON_INSTANCE_VERSION_IMAGEDECODER "2.0.1" +#define ADDON_INSTANCE_VERSION_IMAGEDECODER_MIN "2.0.1" #define ADDON_INSTANCE_VERSION_IMAGEDECODER_XML_ID "kodi.binary.instance.imagedecoder" #define ADDON_INSTANCE_VERSION_IMAGEDECODER_DEPENDS "addon-instance/ImageDecoder.h" -#define ADDON_INSTANCE_VERSION_INPUTSTREAM "2.3.0" -#define ADDON_INSTANCE_VERSION_INPUTSTREAM_MIN "2.3.0" +#define ADDON_INSTANCE_VERSION_INPUTSTREAM "2.3.1" +#define ADDON_INSTANCE_VERSION_INPUTSTREAM_MIN "2.3.1" #define ADDON_INSTANCE_VERSION_INPUTSTREAM_XML_ID "kodi.binary.instance.inputstream" #define ADDON_INSTANCE_VERSION_INPUTSTREAM_DEPENDS "addon-instance/Inputstream.h" -#define ADDON_INSTANCE_VERSION_PERIPHERAL "1.3.7" -#define ADDON_INSTANCE_VERSION_PERIPHERAL_MIN "1.3.4" +#define ADDON_INSTANCE_VERSION_PERIPHERAL "1.3.8" +#define ADDON_INSTANCE_VERSION_PERIPHERAL_MIN "1.3.8" #define ADDON_INSTANCE_VERSION_PERIPHERAL_XML_ID "kodi.binary.instance.peripheral" #define ADDON_INSTANCE_VERSION_PERIPHERAL_DEPENDS "addon-instance/Peripheral.h" \ "addon-instance/PeripheralUtils.h" -#define ADDON_INSTANCE_VERSION_PVR "6.5.0" -#define ADDON_INSTANCE_VERSION_PVR_MIN "6.5.0" +#define ADDON_INSTANCE_VERSION_PVR "6.5.1" +#define ADDON_INSTANCE_VERSION_PVR_MIN "6.5.1" #define ADDON_INSTANCE_VERSION_PVR_XML_ID "kodi.binary.instance.pvr" #define ADDON_INSTANCE_VERSION_PVR_DEPENDS "xbmc_pvr_dll.h" \ "xbmc_pvr_types.h" \ "libXBMC_pvr.h" -#define ADDON_INSTANCE_VERSION_SCREENSAVER "2.0.0" -#define ADDON_INSTANCE_VERSION_SCREENSAVER_MIN "2.0.0" +#define ADDON_INSTANCE_VERSION_SCREENSAVER "2.0.1" +#define ADDON_INSTANCE_VERSION_SCREENSAVER_MIN "2.0.1" #define ADDON_INSTANCE_VERSION_SCREENSAVER_XML_ID "kodi.binary.instance.screensaver" #define ADDON_INSTANCE_VERSION_SCREENSAVER_DEPENDS "addon-instance/Screensaver.h" -#define ADDON_INSTANCE_VERSION_VFS "2.3.0" -#define ADDON_INSTANCE_VERSION_VFS_MIN "2.3.0" +#define ADDON_INSTANCE_VERSION_VFS "2.3.1" +#define ADDON_INSTANCE_VERSION_VFS_MIN "2.3.1" #define ADDON_INSTANCE_VERSION_VFS_XML_ID "kodi.binary.instance.vfs" #define ADDON_INSTANCE_VERSION_VFS_DEPENDS "addon-instance/VFS.h" -#define ADDON_INSTANCE_VERSION_VISUALIZATION "2.0.2" -#define ADDON_INSTANCE_VERSION_VISUALIZATION_MIN "2.0.2" +#define ADDON_INSTANCE_VERSION_VISUALIZATION "2.0.3" +#define ADDON_INSTANCE_VERSION_VISUALIZATION_MIN "2.0.3" #define ADDON_INSTANCE_VERSION_VISUALIZATION_XML_ID "kodi.binary.instance.visualization" #define ADDON_INSTANCE_VERSION_VISUALIZATION_DEPENDS "addon-instance/Visualization.h" -#define ADDON_INSTANCE_VERSION_VIDEOCODEC "1.0.1" -#define ADDON_INSTANCE_VERSION_VIDEOCODEC_MIN "1.0.1" +#define ADDON_INSTANCE_VERSION_VIDEOCODEC "1.0.2" +#define ADDON_INSTANCE_VERSION_VIDEOCODEC_MIN "1.0.2" #define ADDON_INSTANCE_VERSION_VIDEOCODEC_XML_ID "kodi.binary.instance.videocodec" #define ADDON_INSTANCE_VERSION_VIDEOCODEC_DEPENDS "addon-instance/VideoCodec.h" \ "StreamCodec.h" \ "StreamCrypto.h" +// clang format on //============================================================================== /// 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 ce2bc9801ec0e..97361a555a9ef 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 @@ -14,8 +14,8 @@ 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); + ADDON_STATUS __declspec(dllexport) + ADDON_Create(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);