[videodb] remove unused seasons table from episode_view
[xbmc.git] / xbmc / addons / interfaces / AddonBase.cpp
blob496ca92b680193039bfa3c55e678025a3b835c35
1 /*
2 * Copyright (C) 2005-2020 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "AddonBase.h"
11 #include "GUIUserMessages.h"
12 #include "addons/AddonManager.h"
13 #include "addons/addoninfo/AddonInfo.h"
14 #include "addons/addoninfo/AddonType.h"
15 #include "addons/binary-addons/AddonDll.h"
16 #include "addons/gui/GUIDialogAddonSettings.h"
17 #include "addons/settings/AddonSettings.h"
18 #include "application/Application.h"
19 #include "filesystem/Directory.h"
20 #include "filesystem/SpecialProtocol.h"
21 #include "guilib/GUIComponent.h"
22 #include "guilib/GUIWindowManager.h"
23 #include "guilib/LocalizeStrings.h"
24 #include "settings/lib/Setting.h"
25 #include "utils/StringUtils.h"
26 #include "utils/URIUtils.h"
27 #include "utils/log.h"
29 // "C" interface addon callback handle classes
30 #include "AudioEngine.h"
31 #include "Filesystem.h"
32 #include "General.h"
33 #include "Network.h"
34 #include "gui/General.h"
36 namespace ADDON
39 std::vector<ADDON_GET_INTERFACE_FN> Interface_Base::s_registeredInterfaces;
41 bool Interface_Base::InitInterface(CAddonDll* addon,
42 AddonGlobalInterface& addonInterface,
43 KODI_ADDON_INSTANCE_STRUCT* firstKodiInstance)
45 addonInterface = {};
47 addonInterface.addonBase = nullptr;
48 addonInterface.globalSingleInstance = nullptr;
49 addonInterface.firstKodiInstance = firstKodiInstance;
51 // Create function list from kodi to addon, generated with malloc to have
52 // compatible with other versions
53 addonInterface.toKodi = new AddonToKodiFuncTable_Addon();
54 addonInterface.toKodi->kodiBase = addon;
55 addonInterface.toKodi->addon_log_msg = addon_log_msg;
56 addonInterface.toKodi->free_string = free_string;
57 addonInterface.toKodi->free_string_array = free_string_array;
59 addonInterface.toKodi->kodi_addon = new AddonToKodiFuncTable_kodi_addon();
60 addonInterface.toKodi->kodi_addon->get_addon_path = get_addon_path;
61 addonInterface.toKodi->kodi_addon->get_lib_path = get_lib_path;
62 addonInterface.toKodi->kodi_addon->get_user_path = get_user_path;
63 addonInterface.toKodi->kodi_addon->get_temp_path = get_temp_path;
64 addonInterface.toKodi->kodi_addon->get_localized_string = get_localized_string;
65 addonInterface.toKodi->kodi_addon->open_settings_dialog = open_settings_dialog;
66 addonInterface.toKodi->kodi_addon->is_setting_using_default = is_setting_using_default;
67 addonInterface.toKodi->kodi_addon->get_setting_bool = get_setting_bool;
68 addonInterface.toKodi->kodi_addon->get_setting_int = get_setting_int;
69 addonInterface.toKodi->kodi_addon->get_setting_float = get_setting_float;
70 addonInterface.toKodi->kodi_addon->get_setting_string = get_setting_string;
71 addonInterface.toKodi->kodi_addon->set_setting_bool = set_setting_bool;
72 addonInterface.toKodi->kodi_addon->set_setting_int = set_setting_int;
73 addonInterface.toKodi->kodi_addon->set_setting_float = set_setting_float;
74 addonInterface.toKodi->kodi_addon->set_setting_string = set_setting_string;
75 addonInterface.toKodi->kodi_addon->get_addon_info = get_addon_info;
76 addonInterface.toKodi->kodi_addon->get_type_version = get_type_version;
77 addonInterface.toKodi->kodi_addon->get_interface = get_interface;
79 // Related parts becomes set from addon headers, make here to nullptr to allow
80 // checks for right set of them
81 addonInterface.toAddon = new KodiToAddonFuncTable_Addon();
83 // Init the other interfaces
84 Interface_General::Init(&addonInterface);
85 Interface_AudioEngine::Init(&addonInterface);
86 Interface_Filesystem::Init(&addonInterface);
87 Interface_Network::Init(&addonInterface);
88 Interface_GUIGeneral::Init(&addonInterface);
90 return true;
93 void Interface_Base::DeInitInterface(AddonGlobalInterface& addonInterface)
95 Interface_GUIGeneral::DeInit(&addonInterface);
96 Interface_Network::DeInit(&addonInterface);
97 Interface_Filesystem::DeInit(&addonInterface);
98 Interface_AudioEngine::DeInit(&addonInterface);
99 Interface_General::DeInit(&addonInterface);
101 if (addonInterface.toKodi)
102 delete addonInterface.toKodi->kodi_addon;
103 delete addonInterface.toKodi;
104 delete addonInterface.toAddon;
105 addonInterface = {};
108 void Interface_Base::RegisterInterface(ADDON_GET_INTERFACE_FN fn)
110 s_registeredInterfaces.push_back(fn);
113 bool Interface_Base::UpdateSettingInActiveDialog(CAddonDll* addon,
114 AddonInstanceId instanceId,
115 const char* id,
116 const std::string& value)
118 if (!CServiceBroker::GetGUI()->GetWindowManager().IsWindowActive(WINDOW_DIALOG_ADDON_SETTINGS))
119 return false;
121 CGUIDialogAddonSettings* dialog =
122 CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogAddonSettings>(
123 WINDOW_DIALOG_ADDON_SETTINGS);
124 if (dialog->GetCurrentAddonID() != addon->ID())
125 return false;
127 CGUIMessage message(GUI_MSG_SETTING_UPDATED, 0, 0);
128 std::vector<std::string> params;
129 params.emplace_back(id);
130 params.push_back(value);
131 message.SetStringParams(params);
132 message.SetParam1(instanceId);
133 CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(message,
134 WINDOW_DIALOG_ADDON_SETTINGS);
136 return true;
140 * @brief Addon to Kodi basic callbacks below
142 * The amount of functions here are hold so minimal as possible. Only parts
143 * where needed on nearly every add-on (e.g. addon_log_msg) are to add there.
145 * More specific parts like e.g. to open files should be added to a separate
146 * part.
148 //@{
150 void Interface_Base::addon_log_msg(const KODI_ADDON_BACKEND_HDL hdl,
151 const int addonLogLevel,
152 const char* strMessage)
154 CAddonDll* addon = static_cast<CAddonDll*>(hdl);
155 if (addon == nullptr)
157 CLog::Log(LOGERROR, "addon_log_msg(...) called with empty kodi instance pointer");
158 return;
161 int logLevel = LOGNONE;
162 switch (addonLogLevel)
164 case ADDON_LOG_DEBUG:
165 logLevel = LOGDEBUG;
166 break;
167 case ADDON_LOG_INFO:
168 logLevel = LOGINFO;
169 break;
170 case ADDON_LOG_WARNING:
171 logLevel = LOGWARNING;
172 break;
173 case ADDON_LOG_ERROR:
174 logLevel = LOGERROR;
175 break;
176 case ADDON_LOG_FATAL:
177 logLevel = LOGFATAL;
178 break;
179 default:
180 logLevel = LOGDEBUG;
181 break;
184 CLog::Log(logLevel, "AddOnLog: {}: {}", addon->ID(), strMessage);
187 char* Interface_Base::get_type_version(const KODI_ADDON_BACKEND_HDL hdl, int type)
189 return strdup(kodi::addon::GetTypeVersion(type));
192 char* Interface_Base::get_addon_path(const KODI_ADDON_BACKEND_HDL hdl)
194 CAddonDll* addon = static_cast<CAddonDll*>(hdl);
195 if (addon == nullptr)
197 CLog::Log(LOGERROR, "get_addon_path(...) called with empty kodi instance pointer");
198 return nullptr;
201 return strdup(CSpecialProtocol::TranslatePath(addon->Path()).c_str());
204 char* Interface_Base::get_lib_path(const KODI_ADDON_BACKEND_HDL hdl)
206 CAddonDll* addon = static_cast<CAddonDll*>(hdl);
207 if (addon == nullptr)
209 CLog::Log(LOGERROR, "get_lib_path(...) called with empty kodi instance pointer");
210 return nullptr;
213 return strdup(CSpecialProtocol::TranslatePath("special://xbmcbinaddons/" + addon->ID()).c_str());
216 char* Interface_Base::get_user_path(const KODI_ADDON_BACKEND_HDL hdl)
218 CAddonDll* addon = static_cast<CAddonDll*>(hdl);
219 if (addon == nullptr)
221 CLog::Log(LOGERROR, "get_user_path(...) called with empty kodi instance pointer");
222 return nullptr;
225 return strdup(CSpecialProtocol::TranslatePath(addon->Profile()).c_str());
228 char* Interface_Base::get_temp_path(const KODI_ADDON_BACKEND_HDL hdl)
230 CAddonDll* addon = static_cast<CAddonDll*>(hdl);
231 if (addon == nullptr)
233 CLog::Log(LOGERROR, "get_temp_path(...) called with empty kodi instance pointer");
234 return nullptr;
237 std::string tempPath =
238 URIUtils::AddFileToFolder(CServiceBroker::GetAddonMgr().GetTempAddonBasePath(), addon->ID());
239 tempPath += "-temp";
240 XFILE::CDirectory::Create(tempPath);
242 return strdup(CSpecialProtocol::TranslatePath(tempPath).c_str());
245 char* Interface_Base::get_localized_string(const KODI_ADDON_BACKEND_HDL hdl, long label_id)
247 CAddonDll* addon = static_cast<CAddonDll*>(hdl);
248 if (!addon)
250 CLog::Log(LOGERROR, "get_localized_string(...) called with empty kodi instance pointer");
251 return nullptr;
254 if (g_application.m_bStop)
255 return nullptr;
257 std::string label = g_localizeStrings.GetAddonString(addon->ID(), label_id);
258 if (label.empty())
259 label = g_localizeStrings.Get(label_id);
260 char* buffer = strdup(label.c_str());
261 return buffer;
264 char* Interface_Base::get_addon_info(const KODI_ADDON_BACKEND_HDL hdl, const char* id)
266 CAddonDll* addon = static_cast<CAddonDll*>(hdl);
267 if (addon == nullptr || id == nullptr)
269 CLog::Log(LOGERROR, "get_addon_info(...) called with empty pointer");
270 return nullptr;
273 std::string str;
274 if (StringUtils::CompareNoCase(id, "author") == 0)
275 str = addon->Author();
276 else if (StringUtils::CompareNoCase(id, "changelog") == 0)
277 str = addon->ChangeLog();
278 else if (StringUtils::CompareNoCase(id, "description") == 0)
279 str = addon->Description();
280 else if (StringUtils::CompareNoCase(id, "disclaimer") == 0)
281 str = addon->Disclaimer();
282 else if (StringUtils::CompareNoCase(id, "fanart") == 0)
283 str = addon->FanArt();
284 else if (StringUtils::CompareNoCase(id, "icon") == 0)
285 str = addon->Icon();
286 else if (StringUtils::CompareNoCase(id, "id") == 0)
287 str = addon->ID();
288 else if (StringUtils::CompareNoCase(id, "name") == 0)
289 str = addon->Name();
290 else if (StringUtils::CompareNoCase(id, "path") == 0)
291 str = addon->Path();
292 else if (StringUtils::CompareNoCase(id, "profile") == 0)
293 str = addon->Profile();
294 else if (StringUtils::CompareNoCase(id, "summary") == 0)
295 str = addon->Summary();
296 else if (StringUtils::CompareNoCase(id, "type") == 0)
297 str = ADDON::CAddonInfo::TranslateType(addon->Type());
298 else if (StringUtils::CompareNoCase(id, "version") == 0)
299 str = addon->Version().asString();
300 else
302 CLog::Log(LOGERROR, "Interface_Base::{} - add-on '{}' requests invalid id '{}'", __func__,
303 addon->Name(), id);
304 return nullptr;
307 char* buffer = strdup(str.c_str());
308 return buffer;
311 bool Interface_Base::open_settings_dialog(const KODI_ADDON_BACKEND_HDL hdl)
313 CAddonDll* addon = static_cast<CAddonDll*>(hdl);
314 if (addon == nullptr)
316 CLog::Log(LOGERROR, "open_settings_dialog(...) called with empty kodi instance pointer");
317 return false;
320 // show settings dialog
321 AddonPtr addonInfo;
322 if (!CServiceBroker::GetAddonMgr().GetAddon(addon->ID(), addonInfo, OnlyEnabled::CHOICE_YES))
324 CLog::Log(LOGERROR, "Interface_Base::{} - Could not get addon information for '{}'", __func__,
325 addon->ID());
326 return false;
329 return CGUIDialogAddonSettings::ShowForAddon(addonInfo);
332 bool Interface_Base::is_setting_using_default(const KODI_ADDON_BACKEND_HDL hdl, const char* id)
334 CAddonDll* addon = static_cast<CAddonDll*>(hdl);
335 if (addon == nullptr || id == nullptr)
337 CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}')", __func__, hdl,
338 static_cast<const void*>(id));
340 return false;
343 if (!addon->HasSettings())
345 CLog::Log(LOGERROR, "Interface_Base::{} - couldn't get settings for add-on '{}'", __func__,
346 addon->Name());
347 return false;
350 auto setting = addon->GetSettings()->GetSetting(id);
351 if (setting == nullptr)
353 CLog::Log(LOGERROR, "Interface_Base::{} - can't find setting '{}' in '{}'", __func__, id,
354 addon->Name());
355 return false;
358 return setting->IsDefault();
361 bool Interface_Base::get_setting_bool(const KODI_ADDON_BACKEND_HDL hdl, const char* id, bool* value)
363 CAddonDll* addon = static_cast<CAddonDll*>(hdl);
364 if (addon == nullptr || id == nullptr || value == nullptr)
366 CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}', value='{}')",
367 __func__, hdl, static_cast<const void*>(id), static_cast<void*>(value));
369 return false;
372 if (!addon->HasSettings())
374 CLog::Log(LOGERROR, "Interface_Base::{} - couldn't get settings for add-on '{}'", __func__,
375 addon->Name());
376 return false;
379 auto setting = addon->GetSettings()->GetSetting(id);
380 if (setting == nullptr)
382 CLog::Log(LOGERROR, "Interface_Base::{} - can't find setting '{}' in '{}'", __func__, id,
383 addon->Name());
384 return false;
387 if (setting->GetType() != SettingType::Boolean)
389 CLog::Log(LOGERROR, "Interface_Base::{} - setting '{}' is not a boolean in '{}'", __func__, id,
390 addon->Name());
391 return false;
394 *value = std::static_pointer_cast<CSettingBool>(setting)->GetValue();
395 return true;
398 bool Interface_Base::get_setting_int(const KODI_ADDON_BACKEND_HDL hdl, const char* id, int* value)
400 CAddonDll* addon = static_cast<CAddonDll*>(hdl);
401 if (addon == nullptr || id == nullptr || value == nullptr)
403 CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}', value='{}')",
404 __func__, hdl, static_cast<const void*>(id), static_cast<void*>(value));
406 return false;
409 if (!addon->HasSettings())
411 CLog::Log(LOGERROR, "Interface_Base::{} - couldn't get settings for add-on '{}'", __func__,
412 addon->Name());
413 return false;
416 auto setting = addon->GetSettings()->GetSetting(id);
417 if (setting == nullptr)
419 CLog::Log(LOGERROR, "Interface_Base::{} - can't find setting '{}' in '{}'", __func__, id,
420 addon->Name());
421 return false;
424 if (setting->GetType() != SettingType::Integer && setting->GetType() != SettingType::Number)
426 CLog::Log(LOGERROR, "Interface_Base::{} - setting '{}' is not a integer in '{}'", __func__, id,
427 addon->Name());
428 return false;
431 if (setting->GetType() == SettingType::Integer)
432 *value = std::static_pointer_cast<CSettingInt>(setting)->GetValue();
433 else
434 *value = static_cast<int>(std::static_pointer_cast<CSettingNumber>(setting)->GetValue());
435 return true;
438 bool Interface_Base::get_setting_float(const KODI_ADDON_BACKEND_HDL hdl,
439 const char* id,
440 float* value)
442 CAddonDll* addon = static_cast<CAddonDll*>(hdl);
443 if (addon == nullptr || id == nullptr || value == nullptr)
445 CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}', value='{}')",
446 __func__, hdl, static_cast<const void*>(id), static_cast<void*>(value));
448 return false;
451 if (!addon->HasSettings())
453 CLog::Log(LOGERROR, "Interface_Base::{} - couldn't get settings for add-on '{}'", __func__,
454 addon->Name());
455 return false;
458 auto setting = addon->GetSettings()->GetSetting(id);
459 if (setting == nullptr)
461 CLog::Log(LOGERROR, "Interface_Base::{} - can't find setting '{}' in '{}'", __func__, id,
462 addon->Name());
463 return false;
466 if (setting->GetType() != SettingType::Number)
468 CLog::Log(LOGERROR, "Interface_Base::{} - setting '{}' is not a number in '{}'", __func__, id,
469 addon->Name());
470 return false;
473 *value = static_cast<float>(std::static_pointer_cast<CSettingNumber>(setting)->GetValue());
474 return true;
477 bool Interface_Base::get_setting_string(const KODI_ADDON_BACKEND_HDL hdl,
478 const char* id,
479 char** value)
481 CAddonDll* addon = static_cast<CAddonDll*>(hdl);
482 if (addon == nullptr || id == nullptr || value == nullptr)
484 CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}', value='{}')",
485 __func__, hdl, static_cast<const void*>(id), static_cast<void*>(value));
487 return false;
490 if (!addon->HasSettings())
492 CLog::Log(LOGERROR, "Interface_Base::{} - couldn't get settings for add-on '{}'", __func__,
493 addon->Name());
494 return false;
497 auto setting = addon->GetSettings()->GetSetting(id);
498 if (setting == nullptr)
500 CLog::Log(LOGERROR, "Interface_Base::{} - can't find setting '{}' in '{}'", __func__, id,
501 addon->Name());
502 return false;
505 if (setting->GetType() != SettingType::String)
507 CLog::Log(LOGERROR, "Interface_Base::{} - setting '{}' is not a string in '{}'", __func__, id,
508 addon->Name());
509 return false;
512 *value = strdup(std::static_pointer_cast<CSettingString>(setting)->GetValue().c_str());
513 return true;
516 bool Interface_Base::set_setting_bool(const KODI_ADDON_BACKEND_HDL hdl, const char* id, bool value)
518 CAddonDll* addon = static_cast<CAddonDll*>(hdl);
519 if (addon == nullptr || id == nullptr)
521 CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}')", __func__, hdl,
522 static_cast<const void*>(id));
524 return false;
527 if (Interface_Base::UpdateSettingInActiveDialog(addon, ADDON_SETTINGS_ID, id,
528 value ? "true" : "false"))
529 return true;
531 if (!addon->UpdateSettingBool(id, value))
533 CLog::Log(LOGERROR, "Interface_Base::{} - invalid setting type", __func__);
534 return false;
537 addon->SaveSettings();
539 return true;
542 bool Interface_Base::set_setting_int(const KODI_ADDON_BACKEND_HDL hdl, const char* id, int value)
544 CAddonDll* addon = static_cast<CAddonDll*>(hdl);
545 if (addon == nullptr || id == nullptr)
547 CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}')", __func__, hdl,
548 static_cast<const void*>(id));
550 return false;
553 if (Interface_Base::UpdateSettingInActiveDialog(addon, ADDON_SETTINGS_ID, id,
554 std::to_string(value)))
555 return true;
557 if (!addon->UpdateSettingInt(id, value))
559 CLog::Log(LOGERROR, "Interface_Base::{} - invalid setting type", __func__);
560 return false;
563 addon->SaveSettings();
565 return true;
568 bool Interface_Base::set_setting_float(const KODI_ADDON_BACKEND_HDL hdl,
569 const char* id,
570 float value)
572 CAddonDll* addon = static_cast<CAddonDll*>(hdl);
573 if (addon == nullptr || id == nullptr)
575 CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}')", __func__, hdl,
576 static_cast<const void*>(id));
578 return false;
581 if (Interface_Base::UpdateSettingInActiveDialog(addon, ADDON_SETTINGS_ID, id,
582 StringUtils::Format("{:f}", value)))
583 return true;
585 if (!addon->UpdateSettingNumber(id, static_cast<double>(value)))
587 CLog::Log(LOGERROR, "Interface_Base::{} - invalid setting type", __func__);
588 return false;
591 addon->SaveSettings();
593 return true;
596 bool Interface_Base::set_setting_string(const KODI_ADDON_BACKEND_HDL hdl,
597 const char* id,
598 const char* value)
600 CAddonDll* addon = static_cast<CAddonDll*>(hdl);
601 if (addon == nullptr || id == nullptr || value == nullptr)
603 CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}', value='{}')",
604 __func__, hdl, static_cast<const void*>(id), static_cast<const void*>(value));
606 return false;
609 if (Interface_Base::UpdateSettingInActiveDialog(addon, ADDON_SETTINGS_ID, id, value))
610 return true;
612 if (!addon->UpdateSettingString(id, value))
614 CLog::Log(LOGERROR, "Interface_Base::{} - invalid setting type", __func__);
615 return false;
618 addon->SaveSettings();
620 return true;
623 void Interface_Base::free_string(const KODI_ADDON_BACKEND_HDL hdl, char* str)
625 if (str)
626 free(str);
629 void Interface_Base::free_string_array(const KODI_ADDON_BACKEND_HDL hdl,
630 char** arr,
631 int numElements)
633 if (arr)
635 for (int i = 0; i < numElements; ++i)
637 free(arr[i]);
639 free(arr);
643 void* Interface_Base::get_interface(const KODI_ADDON_BACKEND_HDL hdl,
644 const char* name,
645 const char* version)
647 if (!name || !version)
648 return nullptr;
650 void* retval(nullptr);
652 for (auto fn : s_registeredInterfaces)
653 if ((retval = fn(name, version)))
654 break;
656 return retval;
659 //@}
661 } // namespace ADDON