1
0
Fork 0
flightgear/src/Add-ons/AddonManager.hxx
Florent Rougon 48f52f14c4 Improved infrastructure for add-ons: C++ classes, metadata file, Nasal interface
This commit adds C++ classes for add-on management, most notably
AddonManager, Addon and AddonVersion. The AddonManager is used to
register add-ons. It relies on an std::map<std::string, AddonRef> to
hold the metadata of each registered add-on (keys of the std::map are
add-on identifiers, and AddonRef is currently SGSharedPtr<Addon>).
Accessor methods are available for:

  - retrieving the list of registered or loaded add-ons (terminology
    explained in $FG_ROOT/Docs/README.add-ons);

  - checking if a particular add-on has already been registered or
    loaded;

  - for each add-on, obtaining an Addon instance which can be queried
    for its name, id, version, base path, the minimum and maximum
    FlightGear versions it requires, its base node in the Property Tree,
    its order in the load sequence, short and long description strings,
    home page, etc.

The most important metadata is made accessible in the Property Tree
under /addons/by-id/<addon-id> and the property
/addons/by-id/<addon-id>/loaded can be checked or listened to, in
order to determine when a particular add-on is loaded. There is also a
Nasal interface to access add-on metadata in a convenient way.

In order to provide this metadata, each add-on must from now on have in
its base directory a file called 'addon-metadata.xml'.

All this is documented in much more detail in
$FG_ROOT/Docs/README.add-ons.

Mailing-list discussion:

  https://sourceforge.net/p/flightgear/mailman/message/36146017/
2017-12-08 00:36:41 +01:00

136 lines
4.8 KiB
C++

// -*- coding: utf-8 -*-
//
// AddonManager.hxx --- Manager class for FlightGear add-ons
// Copyright (C) 2017 Florent Rougon
//
// 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 of the License, 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 this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#ifndef FG_ADDONMANAGER_HXX
#define FG_ADDONMANAGER_HXX
#include <string>
#include <map>
#include <memory> // std::unique_ptr, std::shared_ptr
#include <vector>
#include <simgear/misc/sg_path.hxx>
#include <simgear/props/props.hxx>
#include "addon_fwd.hxx"
#include "Addon.hxx"
#include "AddonVersion.hxx"
namespace flightgear
{
namespace addon_errors
{
// Custom exception classes
class error : public sg_exception
{
public:
explicit error(const std::string& message,
const std::string& origin = std::string());
explicit error(const char* message, const char* origin = nullptr);
};
class error_loading_config_file : public error
{ using error::error; /* inherit all constructors */ };
class no_metadata_file_found : public error
{ using error::error; };
class error_loading_metadata_file : public error
{ using error::error; };
class duplicate_registration_attempt : public error
{ using error::error; };
class fg_version_too_old : public error
{ using error::error; };
class fg_version_too_recent : public error
{ using error::error; };
} // of namespace addon_errors
class AddonManager
{
public:
AddonManager(const AddonManager&) = delete;
AddonManager& operator=(const AddonManager&) = delete;
AddonManager(AddonManager&&) = delete;
AddonManager& operator=(AddonManager&&) = delete;
// The instance is created by createInstance() -> private constructor
// but it should be deleted by its owning std::unique_ptr -> public destructor
~AddonManager() = default;
// Static creator
static const std::unique_ptr<AddonManager>& createInstance();
// Singleton accessor
static const std::unique_ptr<AddonManager>& instance();
// Reset the static smart pointer, i.e., shut down the AddonManager.
static void reset();
// Register an add-on and return its id.
// 'addonPath': directory containing the add-on to register
//
// This comprises the following steps, where $path = addonPath.realpath():
// - load add-on metadata from $path/addon-metadata.xml and register it
// inside _idToAddonMap (this step is done via registerAddonMetadata());
// - load $path/config.xml into the Property Tree;
// - append $path to the list of aircraft paths;
// - make part of the add-on metadata available in the Property Tree under
// the /addons node (/addons/by-id/<addonId>/{id,version,path,...});
// - append a ref to the Addon instance to _registeredAddons.
std::string registerAddon(const SGPath& addonPath);
// Return the list of registered add-ons in registration order (which, BTW,
// is the same as load order).
std::vector<AddonRef> registeredAddons() const;
bool isAddonRegistered(const std::string& addonId) const;
// A loaded add-on is one whose main.nas file has been loaded. The returned
// vector is sorted by add-on id (cheap sorting based on UTF-8 code units,
// only guaranteed correct for ASCII chars).
std::vector<AddonRef> loadedAddons() const;
bool isAddonLoaded(const std::string& addonId) const;
AddonRef getAddon(const std::string& addonId) const;
AddonVersionRef addonVersion(const std::string& addonId) const;
SGPath addonBasePath(const std::string& addonId) const;
// Base node pertaining to the add-on in the Global Property Tree
SGPropertyNode_ptr addonNode(const std::string& addonId) const;
private:
// Constructor called from createInstance() only
explicit AddonManager() = default;
static void loadConfigFileIfExists(const SGPath& configFile);
// Register add-on metadata inside _idToAddonMap and return the add-on id
std::string registerAddonMetadata(const SGPath& addonPath);
// Map each add-on id to the corresponding Addon instance.
std::map<std::string, AddonRef> _idToAddonMap;
// The order in _registeredAddons is the registration order.
std::vector<AddonRef> _registeredAddons;
// 0 for the first loaded add-on, 1 for the second, etc.
// Also note that add-ons are loaded in their registration order.
int _loadSequenceNumber = 0;
};
} // of namespace flightgear
#endif // of FG_ADDONMANAGER_HXX