From d1fd5756f6b8b4fdd121a19391af942582b5d35e Mon Sep 17 00:00:00 2001 From: James Turner Date: Sat, 31 May 2014 18:04:56 +0100 Subject: [PATCH] Initial package-system integration. - disabled by default - incomplete, adding so Thomas can see the API --- src/Main/fg_init.cxx | 16 +++- src/Main/globals.cxx | 11 +++ src/Main/globals.hxx | 11 ++- src/Network/HTTPClient.cxx | 160 +++++++++++++++++++++++++++++++++++++ src/Network/HTTPClient.hxx | 1 + 5 files changed, 196 insertions(+), 3 deletions(-) diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index b94a73cf9..0f90d8e6d 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -69,6 +69,8 @@ #include #include +#include + #include #include #include @@ -123,6 +125,7 @@ #include #include #include +#include #include @@ -149,7 +152,9 @@ using std::string; using std::endl; using std::cerr; using std::cout; + using namespace boost::algorithm; +using namespace simgear::pkg; extern osg::ref_ptr viewer; @@ -480,11 +485,19 @@ int fgInitConfig ( int argc, char **argv, bool reinit ) int fgInitAircraft(bool reinit) { + // FIXME - use Documents/FlightGear/Aircraft + SGPath userAircraftDir = globals->get_fg_home(); + userAircraftDir.append("Aircraft"); + + SGSharedPtr pkgRoot(new Root(userAircraftDir, FLIGHTGEAR_VERSION)); + // set the http client later (too early in startup right now) + globals->setPackageRoot(pkgRoot); + // Scan user config files and command line for a specified aircraft. if (reinit) { SGPropertyNode* sim = fgGetNode("/sim", true); sim->removeChildren("fg-aircraft"); - // after reset, add aircraft dirs to props, neede for Nasal IO rules + // after reset, add aircraft dirs to props, needed for Nasal IO rules string_list::const_iterator it; int index = 0; for (it = globals->get_aircraft_paths().begin(); @@ -493,7 +506,6 @@ int fgInitAircraft(bool reinit) SGPropertyNode* n = sim->getChild("fg-aircraft", index, true); n->setStringValue(*it); n->setAttribute(SGPropertyNode::WRITE, false); - } SGPropertyNode* aircraftProp = fgGetNode("/sim/aircraft", true); diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx index e3b21f790..2efb4ec74 100644 --- a/src/Main/globals.cxx +++ b/src/Main/globals.cxx @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -740,4 +741,14 @@ void FGGlobals::cleanupListeners() _listeners_to_cleanup.clear(); } +simgear::pkg::Root* FGGlobals::packageRoot() +{ + return _packageRoot.get(); +} + +void FGGlobals::setPackageRoot(const SGSharedPtr& p) +{ + _packageRoot = p; +} + // end of globals.cxx diff --git a/src/Main/globals.hxx b/src/Main/globals.hxx index 0569a7129..17708c3f7 100644 --- a/src/Main/globals.hxx +++ b/src/Main/globals.hxx @@ -31,6 +31,7 @@ #include #include +#include typedef std::vector string_list; typedef std::vector PathList; @@ -67,6 +68,10 @@ class FGRenderer; class FGFontCache; class FGSampleQueue; +namespace simgear { namespace pkg { + class Root; +}} + /** * Bucket for subsystem pointers representing the sim's state. */ @@ -163,7 +168,8 @@ private: typedef std::vector SGPropertyChangeListenerVec; SGPropertyChangeListenerVec _listeners_to_cleanup; - + + SGSharedPtr _packageRoot; public: FGGlobals(); @@ -337,6 +343,9 @@ public: void set_chatter_queue(FGSampleQueue* queue); void addListenerToCleanup(SGPropertyChangeListener* l); + + simgear::pkg::Root* packageRoot(); + void setPackageRoot(const SGSharedPtr& p); }; diff --git a/src/Network/HTTPClient.cxx b/src/Network/HTTPClient.cxx index b97c7e41c..3d3a4b28f 100644 --- a/src/Network/HTTPClient.cxx +++ b/src/Network/HTTPClient.cxx @@ -20,9 +20,98 @@ #include "HTTPClient.hxx" +#include + #include
+#include + #include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +using namespace simgear; + +typedef nasal::Ghost NasalPackageRoot; +typedef nasal::Ghost NasalPackage; +typedef nasal::Ghost NasalCatalog; +typedef nasal::Ghost NasalInstall; + +// #define ENABLE_PACKAGE_SYSTEM 1 + +namespace { + + class FGDelegate : public pkg::Delegate +{ +public: + virtual void refreshComplete() + { + SG_LOG(SG_IO, SG_INFO, "all Catalogs refreshed"); + + // auto-update; make this controlled by a property + pkg::Root* r = globals->packageRoot(); + + pkg::PackageList toBeUpdated(r->packagesNeedingUpdate()); + pkg::PackageList::const_iterator it; + for (it = toBeUpdated.begin(); it != toBeUpdated.end(); ++it) { + assert((*it)->isInstalled()); + SG_LOG(SG_IO, SG_INFO, "updating:" << (*it)->id()); + r->scheduleToUpdate((*it)->install()); + } + } + + virtual void failedRefresh(pkg::Catalog* aCat, FailureCode aReason) + { + switch (aReason) { + case pkg::Delegate::FAIL_SUCCESS: + SG_LOG(SG_IO, SG_WARN, "refresh of Catalog done"); + break; + + default: + SG_LOG(SG_IO, SG_WARN, "refresh of Catalog " << aCat->url() << " failed:" << aReason); + } + } + + virtual void startInstall(pkg::Install* aInstall) + { + SG_LOG(SG_IO, SG_INFO, "begining install of:" << aInstall->package()->id() + << " to local path:" << aInstall->path()); + + } + + virtual void installProgress(pkg::Install* aInstall, unsigned int aBytes, unsigned int aTotal) + { + SG_LOG(SG_IO, SG_INFO, "installing:" << aInstall->package()->id() << ":" + << aBytes << " of " << aTotal); + } + + virtual void finishInstall(pkg::Install* aInstall) + { + SG_LOG(SG_IO, SG_INFO, "finished install of:" << aInstall->package()->id() + << " to local path:" << aInstall->path()); + + } + + virtual void failedInstall(pkg::Install* aInstall, FailureCode aReason) + { + SG_LOG(SG_IO, SG_WARN, "install failed of:" << aInstall->package()->id() + << " to local path:" << aInstall->path()); + } + +}; + +} // of anonymous namespace + FGHTTPClient::FGHTTPClient() { } @@ -42,6 +131,77 @@ void FGHTTPClient::init() if (!proxyHost.empty()) { _http->setProxy(proxyHost, proxyPort, proxyAuth); } + +#ifdef ENABLE_PACKAGE_SYSTEM + pkg::Root* packageRoot = globals->packageRoot(); + if (packageRoot) { + // package system needs access to the HTTP engine too + packageRoot->setHTTPClient(_http.get()); + + packageRoot->setDelegate(new FGDelegate); + + // setup default catalog if not present + pkg::Catalog* defaultCatalog = packageRoot->getCatalogById("org.flightgear.default"); + if (!defaultCatalog) { + // always show this message + SG_LOG(SG_GENERAL, SG_ALERT, "default catalog not found, installing..."); + pkg::Catalog::createFromUrl(packageRoot, + "http://fgfs.goneabitbursar.com/pkg/" FLIGHTGEAR_VERSION "/default-catalog.xml"); + } + + // start a refresh now + packageRoot->refresh(); + } +#endif // of ENABLE_PACKAGE_SYSTEM +} + +void FGHTTPClient::postinit() +{ +#ifdef ENABLE_PACKAGE_SYSTEM + NasalPackageRoot::init("PackageRoot") + .member("path", &pkg::Root::path) + .member("version", &pkg::Root::catalogVersion) + .method("refresh", &pkg::Root::refresh) + .method("packageById", &pkg::Root::getPackageById) + .method("catalogById", &pkg::Root::getCatalogById); + + NasalCatalog::init("Catalog") + .member("installRoot", &pkg::Catalog::installRoot) + .member("id", &pkg::Catalog::id) + .member("url", &pkg::Catalog::url) + .member("description", &pkg::Catalog::description) + .method("packageById", &pkg::Catalog::getPackageById) + .method("refresh", &pkg::Catalog::refresh) + .method("needingUpdate", &pkg::Catalog::packagesNeedingUpdate) + .member("installed", &pkg::Catalog::installedPackages); + + NasalPackage::init("Package") + .member("id", &pkg::Package::id) + .member("name", &pkg::Package::name) + .member("description", &pkg::Package::description) + .member("installed", &pkg::Package::isInstalled) + .member("thumbnails", &pkg::Package::thumbnailUrls) + .member("revision", &pkg::Package::revision) + .member("catalog", &pkg::Package::catalog) + .method("install", &pkg::Package::install) + .method("lprop", &pkg::Package::getLocalisedProp); + + NasalInstall::init("Install") + .member("revision", &pkg::Install::revsion) + .member("pkg", &pkg::Install::package) + .member("path", &pkg::Install::path) + .member("hasUpdate", &pkg::Install::hasUpdate) + .method("startUpdate", & pkg::Install::startUpdate) + .method("uninstall", &pkg::Install::uninstall); + + pkg::Root* packageRoot = globals->packageRoot(); + if (packageRoot) { + FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal"); + nasal::Hash nasalGlobals = nasalSys->getGlobals(); + nasal::Hash nasalPkg = nasalGlobals.createHash("pkg"); // module + nasalPkg.set("root", packageRoot); + } +#endif // of ENABLE_PACKAGE_SYSTEM } void FGHTTPClient::shutdown() diff --git a/src/Network/HTTPClient.hxx b/src/Network/HTTPClient.hxx index 341b39dee..c20fe7f9e 100644 --- a/src/Network/HTTPClient.hxx +++ b/src/Network/HTTPClient.hxx @@ -37,6 +37,7 @@ public: simgear::HTTP::Client const* client() const { return _http.get(); } virtual void init(); + virtual void postinit(); virtual void shutdown(); virtual void update(double); -- 2.39.5