]> git.mxchange.org Git - flightgear.git/commitdiff
Initial package-system integration.
authorJames Turner <zakalawe@mac.com>
Sat, 31 May 2014 17:04:56 +0000 (18:04 +0100)
committerJames Turner <zakalawe@mac.com>
Sat, 31 May 2014 17:04:56 +0000 (18:04 +0100)
- disabled by default
- incomplete, adding so Thomas can see the API

src/Main/fg_init.cxx
src/Main/globals.cxx
src/Main/globals.hxx
src/Network/HTTPClient.cxx
src/Network/HTTPClient.hxx

index b94a73cf9cd2466219b8c2fcd97a5670e95df7c0..0f90d8e6d524584c07b94af036eefd45143be5cb 100644 (file)
@@ -69,6 +69,8 @@
 #include <simgear/scene/model/particles.hxx>
 #include <simgear/scene/tsync/terrasync.hxx>
 
+#include <simgear/package/Root.hxx>
+
 #include <Aircraft/controls.hxx>
 #include <Aircraft/replay.hxx>
 #include <Aircraft/FlightHistory.hxx>
 #include <Network/HTTPClient.hxx>
 #include <Network/fgcom.hxx>
 #include <Network/http/httpd.hxx>
+#include <Include/version.h>
 
 #include <Viewer/CameraGroup.hxx>
 
@@ -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<osgViewer::Viewer> 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<Root> 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);
index e3b21f790e8c5e979dfcab0c2279b2b5075d8d0d..2efb4ec744cf2b3ef6bff6f671dc357de94c623e 100644 (file)
@@ -43,6 +43,7 @@
 #include <simgear/props/propertyObject.hxx>
 #include <simgear/props/props_io.hxx>
 #include <simgear/scene/model/modellib.hxx>
+#include <simgear/package/Root.hxx>
 
 #include <Aircraft/controls.hxx>
 #include <Airports/runways.hxx>
@@ -740,4 +741,14 @@ void FGGlobals::cleanupListeners()
     _listeners_to_cleanup.clear();
 }
 
+simgear::pkg::Root* FGGlobals::packageRoot()
+{
+  return _packageRoot.get();
+}
+
+void FGGlobals::setPackageRoot(const SGSharedPtr<simgear::pkg::Root>& p)
+{
+  _packageRoot = p;
+}
+
 // end of globals.cxx
index 0569a71299463d404a29b8d22b4d970ca34001bc..17708c3f72f759224b0e36edee34712920c8d3a9 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <vector>
 #include <string>
+#include <memory>
 
 typedef std::vector<std::string> string_list;
 typedef std::vector<SGPath> 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<SGPropertyChangeListener*> SGPropertyChangeListenerVec;
     SGPropertyChangeListenerVec _listeners_to_cleanup;
-    
+  
+    SGSharedPtr<simgear::pkg::Root> _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<simgear::pkg::Root>& p);
 };
 
 
index b97c7e41c82ba9cd7cd4c1e4ba22f253b5e64bf0..3d3a4b28f262dc94af63e2ff515a17127b32c23e 100644 (file)
 
 #include "HTTPClient.hxx"
 
+#include <cassert>
+
 #include <Main/fg_props.hxx>
+#include <Include/version.h>
+
 #include <simgear/sg_inlines.h>
 
+#include <simgear/package/Root.hxx>
+#include <simgear/package/Catalog.hxx>
+#include <simgear/package/Delegate.hxx>
+#include <simgear/package/Install.hxx>
+#include <simgear/package/Package.hxx>
+
+#include <simgear/nasal/cppbind/from_nasal.hxx>
+#include <simgear/nasal/cppbind/to_nasal.hxx>
+#include <simgear/nasal/cppbind/NasalHash.hxx>
+#include <simgear/nasal/cppbind/Ghost.hxx>
+
+#include <Scripting/NasalSys.hxx>
+
+using namespace simgear;
+
+typedef nasal::Ghost<pkg::RootRef> NasalPackageRoot;
+typedef nasal::Ghost<pkg::PackageRef> NasalPackage;
+typedef nasal::Ghost<pkg::CatalogRef> NasalCatalog;
+typedef nasal::Ghost<pkg::InstallRef> 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()
index 341b39dee428722437c8fbdc2f295e89beb147d3..c20fe7f9e283e81e645b56a62d5583c72f729ceb 100644 (file)
@@ -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);