summaryrefslogtreecommitdiffstats
path: root/xbmc/addons/AddonManager.h
blob: 8bc058d0f6af842d2b1b496adc062f5b76103e13 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
#pragma once
/*
 *      Copyright (C) 2005-2013 Team XBMC
 *      http://xbmc.org
 *
 *  This Program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  This Program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with XBMC; see the file COPYING.  If not, see
 *  <http://www.gnu.org/licenses/>.
 *
 */
#include "Addon.h"
#include "threads/CriticalSection.h"
#include "utils/Observer.h"
#include <string>
#include <vector>
#include <map>
#include <deque>
#include "AddonDatabase.h"

class DllLibCPluff;
extern "C"
{
#include "lib/cpluff/libcpluff/cpluff.h"
}

namespace ADDON
{
  typedef std::map<TYPE, VECADDONS> MAPADDONS;
  typedef std::map<TYPE, VECADDONS>::iterator IMAPADDONS;
  typedef std::vector<cp_cfg_element_t*> ELEMENTS;

  const std::string ADDON_METAFILE             = "description.xml";
  const std::string ADDON_VIS_EXT              = "*.vis";
  const std::string ADDON_PYTHON_EXT           = "*.py";
  const std::string ADDON_SCRAPER_EXT          = "*.xml";
  const std::string ADDON_SCREENSAVER_EXT      = "*.xbs";
  const std::string ADDON_PVRDLL_EXT           = "*.pvr";
  const std::string ADDON_DSP_AUDIO_EXT        = "*.adsp";
  const std::string ADDON_VERSION_RE = "(?<Major>\\d*)\\.?(?<Minor>\\d*)?\\.?(?<Build>\\d*)?\\.?(?<Revision>\\d*)?";

  /**
  * Class - IAddonMgrCallback
  * This callback should be inherited by any class which manages
  * specific addon types. Could be mostly used for Dll addon types to handle
  * cleanup before restart/removal
  */
  class IAddonMgrCallback
  {
    public:
      virtual ~IAddonMgrCallback() {};
      virtual bool RequestRestart(AddonPtr addon, bool datachanged)=0;
      virtual bool RequestRemoval(AddonPtr addon)=0;
  };

  /**
  * Class - CAddonMgr
  * Holds references to all addons, enabled or
  * otherwise. Services the generic callbacks available
  * to all addon variants.
  */
  class CAddonMgr : public Observable
  {
  public:
    static CAddonMgr &Get();
    bool ReInit() { DeInit(); return Init(); }
    bool Init();
    void DeInit();

    IAddonMgrCallback* GetCallbackForType(TYPE type);
    bool RegisterAddonMgrCallback(TYPE type, IAddonMgrCallback* cb);
    void UnregisterAddonMgrCallback(TYPE type);

    /* Addon access */
    bool GetDefault(const TYPE &type, AddonPtr &addon);
    bool SetDefault(const TYPE &type, const std::string &addonID);
    /*! \brief Retrieve a specific addon (of a specific type)
     \param id the id of the addon to retrieve.
     \param addon [out] the retrieved addon pointer - only use if the function returns true.
     \param type type of addon to retrieve - defaults to any type.
     \param enabledOnly whether we only want enabled addons - set to false to allow both enabled and disabled addons - defaults to true.
     \return true if an addon matching the id of the given type is available and is enabled (if enabledOnly is true).
     */
    bool GetAddon(const std::string &id, AddonPtr &addon, const TYPE &type = ADDON_UNKNOWN, bool enabledOnly = true);
    bool HasAddons(const TYPE &type, bool enabled = true);
    bool GetAddons(const TYPE &type, VECADDONS &addons, bool enabled = true);
    bool GetAllAddons(VECADDONS &addons, bool enabled = true, bool allowRepos = false);
    void AddToUpdateableAddons(AddonPtr &pAddon);
    void RemoveFromUpdateableAddons(AddonPtr &pAddon);    
    bool ReloadSettings(const std::string &id);
    /*! \brief Get all addons with available updates
     \param addons List to fill with all outdated addons
     \param getLocalVersion Whether to get the local addon version or the addon verion from the repository
     \return True if there are outdated addons otherwise false
     */
    bool GetAllOutdatedAddons(VECADDONS &addons, bool getLocalVersion = false);
    /*! \brief Checks if there is any addon with available updates
     \return True if there are outdated addons otherwise false
     */
    bool HasOutdatedAddons();
    std::string GetString(const std::string &id, const int number);

    std::string GetTranslatedString(const cp_cfg_element_t *root, const char *tag);
    static AddonPtr AddonFromProps(AddonProps& props);
    void FindAddons();
    void RemoveAddon(const std::string& ID);

    /* \brief Disable an addon
     Triggers the database routine and saves the current addon state to cache.
     \param ID id of the addon
     \param disable whether to enable or disable. Defaults to true (disable)
     \sa IsAddonDisabled,
     */
    bool DisableAddon(const std::string& ID, bool disable = true);

    /* \brief Check whether an addon has been disabled via DisableAddon.
     In case the disabled cache does not know about the current state the database routine will be used.
     \param ID id of the addon
     \sa DisableAddon
     */
    bool IsAddonDisabled(const std::string& ID);

    /* \brief Checks whether an addon can be disabled via DisableAddon.
     \param ID id of the addon
     \sa DisableAddon
     */
    bool CanAddonBeDisabled(const std::string& ID);

    /* \brief Checks whether an addon is installed.
     \param ID id of the addon
    */
    bool IsAddonInstalled(const std::string& ID);

    /* \brief Checks whether an addon is installed.
     \param ID id of the addon
     \param addon Installed addon
     */
    bool IsAddonInstalled(const std::string& ID, AddonPtr& addon);

    /* \brief Checks whether an addon can be installed. Broken addons can't be installed.
     \param ID id of the addon
     */
    bool CanAddonBeInstalled(const std::string& ID);

    /* \brief Checks whether an addon can be installed. Broken addons can't be installed.
    \param addon addon to be checked
    */
    bool CanAddonBeInstalled(const AddonPtr& addon);

    /* libcpluff */
    std::string GetExtValue(cp_cfg_element_t *base, const char *path);

    /*! \brief Retrieve a vector of repeated elements from a given configuration element
     \param base the base configuration element.
     \param path the path to the configuration element from the base element.
     \param result [out] returned list of elements.
     \return true if the configuration element is present and the list of elements is non-empty
     */
    bool GetExtElements(cp_cfg_element_t *base, const char *path, ELEMENTS &result);

    /*! \brief Retrieve a list of strings from a given configuration element
     Assumes the configuration element or attribute contains a whitespace separated list of values (eg xs:list schema).
     \param base the base configuration element.
     \param path the path to the configuration element or attribute from the base element.
     \param result [out] returned list of strings.
     \return true if the configuration element is present and the list of strings is non-empty
     */
    bool GetExtList(cp_cfg_element_t *base, const char *path, std::vector<std::string> &result) const;

    const cp_extension_t *GetExtension(const cp_plugin_info_t *props, const char *extension) const;

    /*! \brief Load the addon in the given path
     This loads the addon using c-pluff which parses the addon descriptor file.
     \param path folder that contains the addon.
     \param addon [out] returned addon.
     \return true if addon is set, false otherwise.
     */
    bool LoadAddonDescription(const std::string &path, AddonPtr &addon);

    /*! \brief Load the addon in the given in-memory xml
     This loads the addon using c-pluff which parses the addon descriptor file.
     \param root Root element of an XML document.
     \param addon [out] returned addon.
     \return true if addon is set, false otherwise.
     */
    bool LoadAddonDescriptionFromMemory(const TiXmlElement *root, AddonPtr &addon);

    /*! \brief Parse a repository XML file for addons and load their descriptors
     A repository XML is essentially a concatenated list of addon descriptors.
     \param root Root element of an XML document.
     \param addons [out] returned list of addons.
     \return true if the repository XML file is parsed, false otherwise.
     */
    bool AddonsFromRepoXML(const TiXmlElement *root, VECADDONS &addons);

    /*! \brief Start all services addons.
        \return True is all addons are started, false otherwise
    */
    bool StartServices(const bool beforelogin);
    /*! \brief Stop all services addons.
    */
    void StopServices(const bool onlylogin);

  private:
    void LoadAddons(const std::string &path,
                    std::map<std::string, AddonPtr>& unresolved);

    /* libcpluff */
    const cp_cfg_element_t *GetExtElement(cp_cfg_element_t *base, const char *path);
    cp_context_t *m_cp_context;
    DllLibCPluff *m_cpluff;
    VECADDONS    m_updateableAddons;

    /*! \brief Fetch a (single) addon from a plugin descriptor.
     Assumes that there is a single (non-trivial) extension point per addon.
     \param info the plugin descriptor
     \param type the extension point we want
     \return an AddonPtr based on the descriptor.  May be NULL if no suitable extension point is found.
     */
    AddonPtr GetAddonFromDescriptor(const cp_plugin_info_t *info,
                                    const std::string& type="");

    /*! \brief Check whether this addon is supported on the current platform
     \param info the plugin descriptor
     \return true if the addon is supported, false otherwise.
     */
    bool PlatformSupportsAddon(const cp_plugin_info_t *info) const;

    AddonPtr Factory(const cp_extension_t *props);
    bool CheckUserDirs(const cp_cfg_element_t *element);

    // private construction, and no assignements; use the provided singleton methods
    CAddonMgr();
    CAddonMgr(const CAddonMgr&);
    CAddonMgr const& operator=(CAddonMgr const&);
    virtual ~CAddonMgr();

    std::map<std::string, bool> m_disabled;
    static std::map<TYPE, IAddonMgrCallback*> m_managers;
    CCriticalSection m_critSection;
    CAddonDatabase m_database;
  };

}; /* namespace ADDON */