typedef nasal::Ghost<pkg::CatalogRef> NasalCatalog;
typedef nasal::Ghost<pkg::InstallRef> NasalInstall;
-// #define ENABLE_PACKAGE_SYSTEM 1
-namespace {
-
- class FGDelegate : public pkg::Delegate
+class FGHTTPClient::FGDelegate : public pkg::Delegate
{
public:
virtual void refreshComplete()
r->scheduleToUpdate((*it)->install());
}
}
-
- virtual void failedRefresh(pkg::Catalog* aCat, FailureCode aReason)
+
+ virtual void catalogRefreshed(pkg::CatalogRef aCat, StatusCode aReason)
{
+ if (aCat.ptr() == NULL) {
+ SG_LOG(SG_IO, SG_INFO, "refresh of all catalogs done");
+ return;
+ }
+
switch (aReason) {
- case pkg::Delegate::FAIL_SUCCESS:
- SG_LOG(SG_IO, SG_WARN, "refresh of Catalog done");
+ case pkg::Delegate::STATUS_SUCCESS:
+ case pkg::Delegate::STATUS_REFRESHED:
+ SG_LOG(SG_IO, SG_INFO, "refresh of Catalog done:" << aCat->url());
break;
-
+
+ case pkg::Delegate::STATUS_IN_PROGRESS:
+ SG_LOG(SG_IO, SG_INFO, "refresh of Catalog started:" << aCat->url());
+ break;
+
default:
SG_LOG(SG_IO, SG_WARN, "refresh of Catalog " << aCat->url() << " failed:" << aReason);
}
}
- virtual void startInstall(pkg::Install* aInstall)
+ virtual void startInstall(pkg::InstallRef aInstall)
{
- SG_LOG(SG_IO, SG_INFO, "begining install of:" << aInstall->package()->id()
+ SG_LOG(SG_IO, SG_INFO, "beginning install of:" << aInstall->package()->id()
<< " to local path:" << aInstall->path());
}
- virtual void installProgress(pkg::Install* aInstall, unsigned int aBytes, unsigned int aTotal)
+ virtual void installProgress(pkg::InstallRef 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)
+ virtual void finishInstall(pkg::InstallRef aInstall, StatusCode aReason)
{
+ if (aReason == STATUS_SUCCESS) {
SG_LOG(SG_IO, SG_INFO, "finished install of:" << aInstall->package()->id()
<< " to local path:" << aInstall->path());
+ } else {
+ SG_LOG(SG_IO, SG_WARN, "install failed 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 FGHTTPClient::FGDelegate
-} // of anonymous namespace
-
-FGHTTPClient::FGHTTPClient()
+FGHTTPClient::FGHTTPClient() :
+ _inited(false)
{
}
void FGHTTPClient::init()
{
+ // launcher may need to setup HTTP access abnormally early, so
+ // guard against duplicate inits
+ if (_inited) {
+ return;
+ }
+
_http.reset(new simgear::HTTP::Client);
std::string proxyHost(fgGetString("/sim/presets/proxy/host"));
_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");
- }
+ _packageDelegate.reset(new FGDelegate);
+ packageRoot->addDelegate(_packageDelegate.get());
// start a refresh now
packageRoot->refresh();
}
-#endif // of ENABLE_PACKAGE_SYSTEM
+
+ _inited = true;
+}
+
+namespace {
+
+std::string _getDefaultCatalogId()
+{
+ return fgGetString("/sim/package-system/default-catalog/id", "org.flightgear.official" );
+}
+
+pkg::CatalogRef getDefaultCatalog()
+{
+ if (!globals->packageRoot())
+ return pkg::CatalogRef();
+
+ return globals->packageRoot()->getCatalogById(_getDefaultCatalogId());
+}
+
+} // of anonymous namespace
+
+bool FGHTTPClient::isDefaultCatalogInstalled() const
+{
+ return getDefaultCatalog().valid();
+}
+
+void FGHTTPClient::addDefaultCatalog()
+{
+ pkg::CatalogRef defaultCatalog = getDefaultCatalog();
+ if (!defaultCatalog.valid()) {
+ pkg::Catalog::createFromUrl(globals->packageRoot(), getDefaultCatalogUrl());
+ }
+}
+
+std::string FGHTTPClient::getDefaultCatalogId() const
+{
+ return _getDefaultCatalogId();
+}
+
+std::string FGHTTPClient::getDefaultCatalogUrl() const
+{
+ return fgGetString("/sim/package-system/default-catalog/url",
+ "http://fgfs.goneabitbursar.com/pkg/" FLIGHTGEAR_VERSION "/catalog.xml");;
+}
+
+static naRef f_package_existingInstall( pkg::Package& pkg,
+ const nasal::CallContext& ctx )
+{
+ return ctx.to_nasal(
+ pkg.existingInstall( ctx.getArg<pkg::Package::InstallCallback>(0) )
+ );
}
static naRef f_package_uninstall(pkg::Package& pkg, const nasal::CallContext& ctx)
static SGPropertyNode_ptr queryPropsFromHash(const nasal::Hash& h)
{
SGPropertyNode_ptr props(new SGPropertyNode);
- int tagCount = 0;
for (nasal::Hash::const_iterator it = h.begin(); it != h.end(); ++it) {
std::string const key = it->getKey();
props->setStringValue(key, it->getValue<std::string>());
} else if (strutils::starts_with(key, "rating-")) {
props->setIntValue(key, it->getValue<int>());
- } else if (strutils::starts_with(key, "tag-")) {
- SGPropertyNode_ptr tag = props->getChild("tag", tagCount++, true);
- tag->setStringValue(key.substr(4));
+ } else if (key == "tags") {
+ string_list tags = it->getValue<string_list>();
+ string_list::const_iterator tagIt;
+ int tagCount = 0;
+ for (tagIt = tags.begin(); tagIt != tags.end(); ++tagIt) {
+ SGPropertyNode_ptr tag = props->getChild("tag", tagCount++, true);
+ tag->setStringValue(*tagIt);
+ }
+ } else if (key == "installed") {
+ props->setBoolValue(key, it->getValue<bool>());
} else {
SG_LOG(SG_GENERAL, SG_WARN, "unknown filter term in hash:" << key);
}
return ctx.to_nasal(result);
}
+static naRef f_package_variants(pkg::Package& pack, naContext c)
+{
+ nasal::Hash h(c);
+ string_list vars(pack.variants());
+ for (string_list_iterator it = vars.begin(); it != vars.end(); ++it) {
+ h.set(*it, pack.nameForVariant(*it));
+ }
+
+ return h.get_naRef();
+}
+
void FGHTTPClient::postinit()
{
-#ifdef ENABLE_PACKAGE_SYSTEM
NasalPackageRoot::init("PackageRoot")
.member("path", &pkg::Root::path)
.member("version", &pkg::Root::catalogVersion)
.member("description", &pkg::Package::description)
.member("installed", &pkg::Package::isInstalled)
.member("thumbnails", &pkg::Package::thumbnailUrls)
+ .member("variants", &f_package_variants)
.member("revision", &pkg::Package::revision)
.member("catalog", &pkg::Package::catalog)
.method("install", &pkg::Package::install)
.method("uninstall", &f_package_uninstall)
- .method("lprop", &pkg::Package::getLocalisedProp);
+ .method("existingInstall", &f_package_existingInstall)
+ .method("lprop", &pkg::Package::getLocalisedProp)
+ .member("fileSize", &pkg::Package::fileSizeBytes);
typedef pkg::Install* (pkg::Install::*InstallCallback)
(const pkg::Install::Callback&);
nasal::Hash nasalPkg = nasalGlobals.createHash("pkg"); // module
nasalPkg.set("root", packageRoot);
}
-#endif // of ENABLE_PACKAGE_SYSTEM
}
void FGHTTPClient::shutdown()
{
- _http.reset();
+ pkg::Root* packageRoot = globals->packageRoot();
+ if (packageRoot && _packageDelegate.get()) {
+ packageRoot->removeDelegate(_packageDelegate.get());
+ }
+
+ _packageDelegate.reset();
+ _http.reset();
}
void FGHTTPClient::update(double)