summaryrefslogtreecommitdiffstats
path: root/xbmc/addons/kodi-addon-dev-kit/include/kodi/AddonBase.h
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2017-06-04 16:57:49 +0200
committermanuel <manuel@mausz.at>2017-06-04 16:57:49 +0200
commitf44ecaa4f27e7538ddcad66d40e543bffa2d2d86 (patch)
treed8de60fc7e17edeb6f0921726c038ee54b281445 /xbmc/addons/kodi-addon-dev-kit/include/kodi/AddonBase.h
parentae08c8b7221bc965ac40d70e53fc8fcddb050c46 (diff)
downloadkodi-pvr-build-f44ecaa4f27e7538ddcad66d40e543bffa2d2d86.tar.gz
kodi-pvr-build-f44ecaa4f27e7538ddcad66d40e543bffa2d2d86.tar.bz2
kodi-pvr-build-f44ecaa4f27e7538ddcad66d40e543bffa2d2d86.zip
sync with upstream
Diffstat (limited to 'xbmc/addons/kodi-addon-dev-kit/include/kodi/AddonBase.h')
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/AddonBase.h634
1 files changed, 634 insertions, 0 deletions
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/AddonBase.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/AddonBase.h
new file mode 100644
index 0000000..fdf030b
--- /dev/null
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/AddonBase.h
@@ -0,0 +1,634 @@
1#pragma once
2/*
3 * Copyright (C) 2005-2017 Team Kodi
4 * http://kodi.tv
5 *
6 * This Program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This Program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Kodi; see the file COPYING. If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#include <stdarg.h> /* va_list, va_start, va_arg, va_end */
23#include <cstdlib>
24#include <cstring>
25#include <stdexcept>
26#include <string>
27#include <vector>
28
29#ifndef TARGET_WINDOWS
30#ifndef __cdecl
31#define __cdecl
32#endif
33#ifndef __declspec
34#define __declspec(X)
35#endif
36#endif
37
38#undef ATTRIBUTE_PACKED
39#undef PRAGMA_PACK_BEGIN
40#undef PRAGMA_PACK_END
41
42#if defined(__GNUC__)
43 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
44 #define ATTRIBUTE_PACKED __attribute__ ((packed))
45 #define PRAGMA_PACK 0
46 #endif
47#endif
48
49#if !defined(ATTRIBUTE_PACKED)
50 #define ATTRIBUTE_PACKED
51 #define PRAGMA_PACK 1
52#endif
53
54#include "versions.h"
55
56namespace kodi { namespace addon { class CAddonBase; }}
57namespace kodi { namespace addon { class IAddonInstance; }}
58
59extern "C" {
60
61//==============================================================================
62/// Standard undefined pointer handle
63typedef void* KODI_HANDLE;
64//------------------------------------------------------------------------------
65
66//==============================================================================
67///
68typedef enum ADDON_STATUS
69{
70 ///
71 ADDON_STATUS_OK,
72
73 ///
74 ADDON_STATUS_LOST_CONNECTION,
75
76 ///
77 ADDON_STATUS_NEED_RESTART,
78
79 ///
80 ADDON_STATUS_NEED_SETTINGS,
81
82 ///
83 ADDON_STATUS_UNKNOWN,
84
85 ///
86 ADDON_STATUS_NEED_SAVEDSETTINGS,
87
88 /// permanent failure, like failing to resolve methods
89 ADDON_STATUS_PERMANENT_FAILURE,
90
91 /* internal used return error if function becomes not used from child on
92 * addon */
93 ADDON_STATUS_NOT_IMPLEMENTED
94} ADDON_STATUS;
95//------------------------------------------------------------------------------
96
97//==============================================================================
98/// @todo remove start with ADDON_* after old way on libXBMC_addon.h is removed
99///
100typedef enum AddonLog
101{
102 ///
103 ADDON_LOG_DEBUG = 0,
104
105 ///
106 ADDON_LOG_INFO = 1,
107
108 ///
109 ADDON_LOG_NOTICE = 2,
110
111 ///
112 ADDON_LOG_WARNING = 3,
113
114 ///
115 ADDON_LOG_ERROR = 4,
116
117 ///
118 ADDON_LOG_SEVERE = 5,
119
120 ///
121 ADDON_LOG_FATAL = 6
122} AddonLog;
123//------------------------------------------------------------------------------
124
125/*!
126 * @brief Handle used to return data from the PVR add-on to CPVRClient
127 */
128struct ADDON_HANDLE_STRUCT
129{
130 void *callerAddress; /*!< address of the caller */
131 void *dataAddress; /*!< address to store data in */
132 int dataIdentifier; /*!< parameter to pass back when calling the callback */
133};
134typedef ADDON_HANDLE_STRUCT *ADDON_HANDLE;
135
136/*
137 * To have a on add-on and kodi itself handled string always on known size!
138 */
139#define ADDON_STANDARD_STRING_LENGTH 1024
140#define ADDON_STANDARD_STRING_LENGTH_SMALL 256
141
142/*
143 * Callback function tables from addon to Kodi
144 * Set complete from Kodi!
145 */
146struct AddonToKodiFuncTable_kodi;
147struct AddonToKodiFuncTable_kodi_audioengine;
148struct AddonToKodiFuncTable_kodi_filesystem;
149struct AddonToKodiFuncTable_kodi_network;
150struct AddonToKodiFuncTable_kodi_gui;
151typedef struct AddonToKodiFuncTable_Addon
152{
153 // Pointer inside Kodi, used on callback functions to give related handle
154 // class, for this ADDON::CAddonDll inside Kodi.
155 KODI_HANDLE kodiBase;
156
157 // Function addresses used for callbacks from addon to Kodi
158 void (*free_string)(void* kodiBase, char* str);
159 char* (*get_addon_path)(void* kodiBase);
160 char* (*get_base_user_path)(void* kodiBase);
161 void (*addon_log_msg)(void* kodiBase, const int loglevel, const char *msg);
162 bool (*get_setting)(void* kodiBase, const char* settingName, void *settingValue);
163 bool (*set_setting)(void* kodiBase, const char* settingName, const char* settingValue);
164
165 AddonToKodiFuncTable_kodi* kodi;
166 AddonToKodiFuncTable_kodi_audioengine* kodi_audioengine;
167 AddonToKodiFuncTable_kodi_filesystem* kodi_filesystem;
168 AddonToKodiFuncTable_kodi_gui* kodi_gui;
169 AddonToKodiFuncTable_kodi_network *kodi_network;
170} AddonToKodiFuncTable_Addon;
171
172/*
173 * Function tables from Kodi to addon
174 */
175typedef struct KodiToAddonFuncTable_Addon
176{
177 void (*destroy)();
178 ADDON_STATUS (*get_status)();
179 ADDON_STATUS (*create_instance)(int instanceType, const char* instanceID, KODI_HANDLE instance, KODI_HANDLE* addonInstance, KODI_HANDLE parent);
180 void (*destroy_instance)(int instanceType, KODI_HANDLE instance);
181 ADDON_STATUS (*set_setting)(const char *settingName, const void *settingValue);
182} KodiToAddonFuncTable_Addon;
183
184/*
185 * Main structure passed from kodi to addon with basic information needed to
186 * create add-on.
187 */
188typedef struct AddonGlobalInterface
189{
190 // String with full path where add-on is installed (without his name on end)
191 // Set from Kodi!
192 const char* libBasePath;
193
194 // Pointer of first created instance, used in case this add-on goes with single way
195 // Set from Kodi!
196 KODI_HANDLE firstKodiInstance;
197
198 // Pointer to master base class inside add-on
199 // Set from addon header!
200 kodi::addon::CAddonBase* addonBase;
201
202 // Pointer to a instance used on single way (together with this class)
203 // Set from addon header!
204 kodi::addon::IAddonInstance* globalSingleInstance;
205
206 // Callback function tables from addon to Kodi
207 // Set from Kodi!
208 AddonToKodiFuncTable_Addon* toKodi;
209
210 // Function tables from Kodi to addon
211 // Set from addon header!
212 KodiToAddonFuncTable_Addon* toAddon;
213} AddonGlobalInterface;
214
215} /* extern "C" */
216
217//==============================================================================
218namespace kodi {
219namespace addon {
220/*
221 * Internal class to control various instance types with general parts defined
222 * here.
223 *
224 * Mainly is this currently used to identify requested instance types.
225 *
226 * @note This class is not need to know during add-on development thats why
227 * commented with "*".
228 */
229class IAddonInstance
230{
231public:
232 IAddonInstance(ADDON_TYPE type) : m_type(type) { }
233 virtual ~IAddonInstance() = default;
234
235 virtual ADDON_STATUS CreateInstance(int instanceType, std::string instanceID, KODI_HANDLE instance, KODI_HANDLE& addonInstance)
236 {
237 return ADDON_STATUS_NOT_IMPLEMENTED;
238 }
239
240 const ADDON_TYPE m_type;
241};
242} /* namespace addon */
243} /* namespace kodi */
244//------------------------------------------------------------------------------
245
246//==============================================================================
247namespace kodi {
248///
249class CSettingValue
250{
251public:
252 CSettingValue(const void *settingValue) : m_settingValue(settingValue) {}
253
254 bool empty() const { return (m_settingValue == nullptr) ? true : false; }
255 std::string GetString() const { return (char*)m_settingValue; }
256 int GetInt() const { return *(int*)m_settingValue; }
257 unsigned int GetUInt() const { return *(unsigned int*)m_settingValue; }
258 bool GetBoolean() const { return *(bool*)m_settingValue; }
259 float GetFloat() const { return *(float*)m_settingValue; }
260
261private:
262 const void *m_settingValue;
263};
264} /* namespace kodi */
265//------------------------------------------------------------------------------
266
267//==============================================================================
268namespace kodi {
269namespace addon {
270/// Add-on main instance class.
271class CAddonBase
272{
273public:
274 CAddonBase()
275 {
276 CAddonBase::m_interface->toAddon->destroy = ADDONBASE_Destroy;
277 CAddonBase::m_interface->toAddon->get_status = ADDONBASE_GetStatus;
278 CAddonBase::m_interface->toAddon->create_instance = ADDONBASE_CreateInstance;
279 CAddonBase::m_interface->toAddon->destroy_instance = ADDONBASE_DestroyInstance;
280 CAddonBase::m_interface->toAddon->set_setting = ADDONBASE_SetSetting;
281 }
282
283 virtual ~CAddonBase() = default;
284
285 virtual ADDON_STATUS Create() { return ADDON_STATUS_OK; }
286
287 virtual ADDON_STATUS GetStatus() { return ADDON_STATUS_OK; }
288
289 virtual ADDON_STATUS SetSetting(const std::string& settingName, const CSettingValue& settingValue) { return ADDON_STATUS_UNKNOWN; }
290
291 virtual ADDON_STATUS CreateInstance(int instanceType, std::string instanceID, KODI_HANDLE instance, KODI_HANDLE& addonInstance)
292 {
293 /* The handling below is intended for the case of the add-on only one
294 * instance and this is integrated in the add-on base class.
295 */
296
297 /* Check about single instance usage */
298 if (CAddonBase::m_interface->firstKodiInstance == instance && // the kodi side instance pointer must be equal to first one
299 CAddonBase::m_interface->globalSingleInstance && // the addon side instance pointer must be set
300 CAddonBase::m_interface->globalSingleInstance->m_type == instanceType) // and the requested type must be equal with used add-on class
301 {
302 addonInstance = CAddonBase::m_interface->globalSingleInstance;
303 return ADDON_STATUS_OK;
304 }
305
306 return ADDON_STATUS_UNKNOWN;
307 }
308
309 /* Global variables of class */
310 static AddonGlobalInterface* m_interface; // Interface function table to hold addresses on add-on and from kodi
311
312/*private:*/ /* Needed public as long the old call functions becomes used! */
313 static inline void ADDONBASE_Destroy()
314 {
315 delete CAddonBase::m_interface->addonBase;
316 CAddonBase::m_interface->addonBase = nullptr;
317 }
318
319 static inline ADDON_STATUS ADDONBASE_GetStatus() { return CAddonBase::m_interface->addonBase->GetStatus(); }
320
321 static inline ADDON_STATUS ADDONBASE_SetSetting(const char *settingName, const void *settingValue)
322 {
323 return CAddonBase::m_interface->addonBase->SetSetting(settingName, CSettingValue(settingValue));
324 }
325
326 static inline ADDON_STATUS ADDONBASE_CreateInstance(int instanceType, const char* instanceID, KODI_HANDLE instance, KODI_HANDLE* addonInstance, KODI_HANDLE parent)
327 {
328 ADDON_STATUS status = ADDON_STATUS_NOT_IMPLEMENTED;
329 if (parent != nullptr)
330 status = static_cast<IAddonInstance*>(parent)->CreateInstance(instanceType, instanceID, instance, *addonInstance);
331 if (status == ADDON_STATUS_NOT_IMPLEMENTED)
332 status = CAddonBase::m_interface->addonBase->CreateInstance(instanceType, instanceID, instance, *addonInstance);
333 if (*addonInstance == nullptr)
334 throw std::logic_error("kodi::addon::CAddonBase CreateInstance returns a empty instance pointer!");
335
336 if (static_cast<::kodi::addon::IAddonInstance*>(*addonInstance)->m_type != instanceType)
337 throw std::logic_error("kodi::addon::CAddonBase CreateInstance with difference on given and returned instance type!");
338
339 return status;
340 }
341
342 static inline void ADDONBASE_DestroyInstance(int instanceType, KODI_HANDLE instance)
343 {
344 if (CAddonBase::m_interface->globalSingleInstance == nullptr && instance != CAddonBase::m_interface->addonBase)
345 {
346 if (static_cast<::kodi::addon::IAddonInstance*>(instance)->m_type == instanceType)
347 delete static_cast<::kodi::addon::IAddonInstance*>(instance);
348 else
349 throw std::logic_error("kodi::addon::CAddonBase DestroyInstance called with difference on given and present instance type!");
350 }
351 }
352};
353} /* namespace addon */
354} /* namespace kodi */
355//------------------------------------------------------------------------------
356
357//==============================================================================
358namespace kodi {
359///
360inline std::string GetAddonPath(const std::string& append = "")
361{
362 char* str = ::kodi::addon::CAddonBase::m_interface->toKodi->get_addon_path(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase);
363 std::string ret = str;
364 ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, str);
365 if (!append.empty())
366 {
367 if (append.at(0) != '\\' &&
368 append.at(0) != '/')
369#ifdef TARGET_WINDOWS
370 ret.append("\\");
371#else
372 ret.append("/");
373#endif
374 ret.append(append);
375 }
376 return ret;
377}
378} /* namespace kodi */
379//------------------------------------------------------------------------------
380
381//==============================================================================
382namespace kodi {
383///
384inline std::string GetBaseUserPath(const std::string& append = "")
385{
386 char* str = ::kodi::addon::CAddonBase::m_interface->toKodi->get_base_user_path(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase);
387 std::string ret = str;
388 ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, str);
389 if (!append.empty())
390 {
391 if (append.at(0) != '\\' &&
392 append.at(0) != '/')
393#ifdef TARGET_WINDOWS
394 ret.append("\\");
395#else
396 ret.append("/");
397#endif
398 ret.append(append);
399 }
400 return ret;
401}
402} /* namespace kodi */
403//------------------------------------------------------------------------------
404
405//==============================================================================
406namespace kodi {
407///
408inline std::string GetLibPath()
409{
410 return ::kodi::addon::CAddonBase::m_interface->libBasePath;
411}
412} /* namespace kodi */
413//------------------------------------------------------------------------------
414
415//==============================================================================
416namespace kodi {
417///
418inline void Log(const AddonLog loglevel, const char* format, ...)
419{
420 char buffer[16384];
421 va_list args;
422 va_start(args, format);
423 vsprintf(buffer, format, args);
424 va_end(args);
425 ::kodi::addon::CAddonBase::m_interface->toKodi->addon_log_msg(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, loglevel, buffer);
426}
427} /* namespace kodi */
428//------------------------------------------------------------------------------
429
430//============================================================================
431namespace kodi {
432///
433inline bool CheckSettingString(const std::string& settingName, std::string& settingValue)
434{
435 char * buffer = nullptr;
436 bool ret = ::kodi::addon::CAddonBase::m_interface->toKodi->get_setting(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), &buffer);
437 if (buffer)
438 {
439 if (ret)
440 settingValue = buffer;
441 ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, buffer);
442 }
443 return ret;
444}
445} /* namespace kodi */
446//----------------------------------------------------------------------------
447
448//============================================================================
449namespace kodi {
450///
451inline std::string GetSettingString(const std::string& settingName)
452{
453 std::string settingValue;
454 CheckSettingString(settingName, settingValue);
455 return settingValue;
456}
457} /* namespace kodi */
458//----------------------------------------------------------------------------
459
460//============================================================================
461namespace kodi {
462///
463inline void SetSettingString(const std::string& settingName, const std::string& settingValue)
464{
465 ::kodi::addon::CAddonBase::m_interface->toKodi->set_setting(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), settingValue.c_str());
466}
467} /* namespace kodi */
468//----------------------------------------------------------------------------
469
470//============================================================================
471namespace kodi {
472///
473inline bool CheckSettingInt(const std::string& settingName, int& settingValue)
474{
475 return ::kodi::addon::CAddonBase::m_interface->toKodi->get_setting(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), &settingValue);
476}
477} /* namespace kodi */
478//----------------------------------------------------------------------------
479
480//============================================================================
481namespace kodi {
482///
483inline int GetSettingInt(const std::string& settingName)
484{
485 int settingValue = 0;
486 CheckSettingInt(settingName, settingValue);
487 return settingValue;
488}
489} /* namespace kodi */
490//----------------------------------------------------------------------------
491
492//============================================================================
493namespace kodi {
494///
495inline void SetSettingInt(const std::string& settingName, int settingValue)
496{
497 char buffer[33];
498 snprintf(buffer, sizeof(buffer), "%i", settingValue);
499 ::kodi::addon::CAddonBase::m_interface->toKodi->set_setting(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), buffer);
500}
501} /* namespace kodi */
502//----------------------------------------------------------------------------
503
504//============================================================================
505namespace kodi {
506///
507inline bool CheckSettingBoolean(const std::string& settingName, bool& settingValue)
508{
509 return ::kodi::addon::CAddonBase::m_interface->toKodi->get_setting(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), &settingValue);
510}
511} /* namespace kodi */
512//----------------------------------------------------------------------------
513
514//============================================================================
515namespace kodi {
516///
517inline bool GetSettingBoolean(const std::string& settingName)
518{
519 bool settingValue = false;
520 CheckSettingBoolean(settingName, settingValue);
521 return settingValue;
522}
523} /* namespace kodi */
524//----------------------------------------------------------------------------
525
526//============================================================================
527namespace kodi {
528///
529inline void SetSettingBoolean(const std::string& settingName, bool settingValue)
530{
531 ::kodi::addon::CAddonBase::m_interface->toKodi->set_setting(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), settingValue ? "true" : "false");
532}
533} /* namespace kodi */
534//----------------------------------------------------------------------------
535
536//============================================================================
537namespace kodi {
538///
539inline bool CheckSettingFloat(const std::string& settingName, float& settingValue)
540{
541 return ::kodi::addon::CAddonBase::m_interface->toKodi->get_setting(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), &settingValue);
542}
543} /* namespace kodi */
544//----------------------------------------------------------------------------
545
546//============================================================================
547namespace kodi {
548///
549inline float GetSettingFloat(const std::string& settingName)
550{
551 float settingValue = 0.0f;
552 CheckSettingFloat(settingName, settingValue);
553 return settingValue;
554}
555} /* namespace kodi */
556//----------------------------------------------------------------------------
557
558//============================================================================
559namespace kodi {
560///
561inline void SetSettingFloat(const std::string& settingName, float settingValue)
562{
563 char buffer[50];
564 snprintf(buffer, sizeof(buffer), "%f", settingValue);
565 ::kodi::addon::CAddonBase::m_interface->toKodi->set_setting(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, settingName.c_str(), buffer);
566}
567} /* namespace kodi */
568//----------------------------------------------------------------------------
569
570//============================================================================
571namespace kodi {
572///
573inline std::string TranslateAddonStatus(ADDON_STATUS status)
574{
575 switch (status)
576 {
577 case ADDON_STATUS_OK:
578 return "OK";
579 case ADDON_STATUS_LOST_CONNECTION:
580 return "Lost Connection";
581 case ADDON_STATUS_NEED_RESTART:
582 return "Need Restart";
583 case ADDON_STATUS_NEED_SETTINGS:
584 return "Need Settings";
585 case ADDON_STATUS_UNKNOWN:
586 return "Unknown error";
587 case ADDON_STATUS_NEED_SAVEDSETTINGS:
588 return "Need saved settings";
589 case ADDON_STATUS_PERMANENT_FAILURE:
590 return "Permanent failure";
591 case ADDON_STATUS_NOT_IMPLEMENTED:
592 return "Not implemented";
593 default:
594 break;
595 }
596 return "Unknown";
597}
598} /* namespace kodi */
599//----------------------------------------------------------------------------
600
601
602/*! addon creation macro
603 * @todo cleanup this stupid big macro
604 * This macro includes now all for add-on's needed functions. This becomes a bigger
605 * rework after everything is done on Kodi itself, currently is this way needed
606 * to have compatibility with not reworked interfaces.
607 *
608 * Becomes really cleaned up soon :D
609 */
610#define ADDONCREATOR(AddonClass) \
611 extern "C" __declspec(dllexport) void get_addon(void* pAddon) {} \
612 extern "C" __declspec(dllexport) ADDON_STATUS ADDON_Create(KODI_HANDLE addonInterface, void *unused) \
613 { \
614 kodi::addon::CAddonBase::m_interface = static_cast<AddonGlobalInterface*>(addonInterface); \
615 kodi::addon::CAddonBase::m_interface->addonBase = new AddonClass; \
616 return kodi::addon::CAddonBase::m_interface->addonBase->Create(); \
617 } \
618 extern "C" __declspec(dllexport) void ADDON_Destroy() \
619 { \
620 kodi::addon::CAddonBase::ADDONBASE_Destroy(); \
621 } \
622 extern "C" __declspec(dllexport) ADDON_STATUS ADDON_GetStatus() \
623 { \
624 return kodi::addon::CAddonBase::ADDONBASE_GetStatus(); \
625 } \
626 extern "C" __declspec(dllexport) ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue) \
627 { \
628 return kodi::addon::CAddonBase::ADDONBASE_SetSetting(settingName, settingValue); \
629 } \
630 extern "C" __declspec(dllexport) const char* ADDON_GetTypeVersion(int type) \
631 { \
632 return kodi::addon::GetTypeVersion(type); \
633 } \
634 AddonGlobalInterface* kodi::addon::CAddonBase::m_interface = nullptr;