1 /* 2 * Copyright (C) 2013-2018 Team Kodi 3 * This file is part of Kodi - https://kodi.tv 4 * 5 * SPDX-License-Identifier: GPL-2.0-or-later 6 * See LICENSES/README.md for more information. 7 */ 8 9 #pragma once 10 11 #include "addons/IAddon.h" 12 #include "interfaces/generic/ILanguageInvoker.h" 13 #include "threads/CriticalSection.h" 14 15 #include <map> 16 #include <memory> 17 #include <set> 18 #include <vector> 19 20 class CLanguageInvokerThread; 21 typedef std::shared_ptr<CLanguageInvokerThread> CLanguageInvokerThreadPtr; 22 23 class CScriptInvocationManager 24 { 25 public: 26 static CScriptInvocationManager& GetInstance(); 27 28 void Process(); 29 void Uninitialize(); 30 31 void RegisterLanguageInvocationHandler(ILanguageInvocationHandler *invocationHandler, const std::string &extension); 32 void RegisterLanguageInvocationHandler(ILanguageInvocationHandler *invocationHandler, const std::set<std::string> &extensions); 33 void UnregisterLanguageInvocationHandler(ILanguageInvocationHandler *invocationHandler); 34 bool HasLanguageInvoker(const std::string &script) const; 35 LanguageInvokerPtr GetLanguageInvoker(const std::string& script); 36 37 /*! 38 * \brief Returns addon_handle if last reusable invoker is ready to use. 39 */ 40 int GetReusablePluginHandle(const std::string& script); 41 42 /*! 43 * \brief Executes the given script asynchronously in a separate thread. 44 * 45 * \param script Path to the script to be executed 46 * \param addon (Optional) Addon to which the script belongs 47 * \param arguments (Optional) List of arguments passed to the script 48 * \return -1 if an error occurred, otherwise the ID of the script 49 */ 50 int ExecuteAsync(const std::string& script, 51 const ADDON::AddonPtr& addon = ADDON::AddonPtr(), 52 const std::vector<std::string>& arguments = std::vector<std::string>(), 53 bool reuseable = false, 54 int pluginHandle = -1); 55 /*! 56 * \brief Executes the given script asynchronously in a separate thread. 57 * 58 * \param script Path to the script to be executed 59 * \param languageInvoker Language invoker to be used to execute the script 60 * \param addon (Optional) Addon to which the script belongs 61 * \param arguments (Optional) List of arguments passed to the script 62 * \return -1 if an error occurred, otherwise the ID of the script 63 */ 64 int ExecuteAsync(const std::string& script, 65 const LanguageInvokerPtr& languageInvoker, 66 const ADDON::AddonPtr& addon = ADDON::AddonPtr(), 67 const std::vector<std::string>& arguments = std::vector<std::string>(), 68 bool reuseable = false, 69 int pluginHandle = -1); 70 71 /*! 72 * \brief Executes the given script synchronously. 73 * 74 * \details The script is actually executed asynchronously but the calling 75 * thread is blocked until either the script has finished or the given timeout 76 * has expired. If the given timeout has expired the script's execution is 77 * stopped and depending on the specified wait behaviour we wait for the 78 * script's execution to finish or not. 79 * 80 * \param script Path to the script to be executed 81 * \param addon (Optional) Addon to which the script belongs 82 * \param arguments (Optional) List of arguments passed to the script 83 * \param timeout (Optional) Timeout (in milliseconds) for the script's execution 84 * \param waitShutdown (Optional) Whether to wait when having to forcefully stop the script's execution or not. 85 * \return -1 if an error occurred, 0 if the script terminated or ETIMEDOUT if the given timeout expired 86 */ 87 int ExecuteSync(const std::string& script, 88 const ADDON::AddonPtr& addon = ADDON::AddonPtr(), 89 const std::vector<std::string>& arguments = std::vector<std::string>(), 90 uint32_t timeoutMs = 0, 91 bool waitShutdown = false); 92 /*! 93 * \brief Executes the given script synchronously. 94 * 95 * \details The script is actually executed asynchronously but the calling 96 * thread is blocked until either the script has finished or the given timeout 97 * has expired. If the given timeout has expired the script's execution is 98 * stopped and depending on the specified wait behaviour we wait for the 99 * script's execution to finish or not. 100 * 101 * \param script Path to the script to be executed 102 * \param languageInvoker Language invoker to be used to execute the script 103 * \param addon (Optional) Addon to which the script belongs 104 * \param arguments (Optional) List of arguments passed to the script 105 * \param timeout (Optional) Timeout (in milliseconds) for the script's execution 106 * \param waitShutdown (Optional) Whether to wait when having to forcefully stop the script's execution or not. 107 * \return -1 if an error occurred, 0 if the script terminated or ETIMEDOUT if the given timeout expired 108 */ 109 int ExecuteSync(const std::string& script, 110 const LanguageInvokerPtr& languageInvoker, 111 const ADDON::AddonPtr& addon = ADDON::AddonPtr(), 112 const std::vector<std::string>& arguments = std::vector<std::string>(), 113 uint32_t timeoutMs = 0, 114 bool waitShutdown = false); 115 bool Stop(int scriptId, bool wait = false); 116 bool Stop(const std::string &scriptPath, bool wait = false); 117 118 /*! 119 *\brief Stop all running scripts 120 *\param wait if kodi should wait for each script to finish (default false) 121 */ 122 void StopRunningScripts(bool wait = false); 123 124 bool IsRunning(int scriptId) const; 125 bool IsRunning(const std::string& scriptPath) const; 126 127 protected: 128 friend class CLanguageInvokerThread; 129 130 void OnExecutionDone(int scriptId); 131 132 private: 133 CScriptInvocationManager() = default; 134 CScriptInvocationManager(const CScriptInvocationManager&) = delete; 135 CScriptInvocationManager const& operator=(CScriptInvocationManager const&) = delete; 136 virtual ~CScriptInvocationManager(); 137 138 typedef struct { 139 CLanguageInvokerThreadPtr thread; 140 std::string script; 141 bool done; 142 } LanguageInvokerThread; 143 typedef std::map<int, LanguageInvokerThread> LanguageInvokerThreadMap; 144 typedef std::map<std::string, ILanguageInvocationHandler*> LanguageInvocationHandlerMap; 145 146 LanguageInvokerThread getInvokerThread(int scriptId) const; 147 148 LanguageInvocationHandlerMap m_invocationHandlers; 149 LanguageInvokerThreadMap m_scripts; 150 CLanguageInvokerThreadPtr m_lastInvokerThread; 151 int m_lastPluginHandle = -1; 152 153 std::map<std::string, int> m_scriptPaths; 154 int m_nextId = 0; 155 mutable CCriticalSection m_critSection; 156 }; 157