diff --git a/projects/VC90/fgadmin/fgadmin.vcproj b/projects/VC90/fgadmin/fgadmin.vcproj index cf34dc845..a7d8f4e09 100644 --- a/projects/VC90/fgadmin/fgadmin.vcproj +++ b/projects/VC90/fgadmin/fgadmin.vcproj @@ -65,7 +65,7 @@ /> +#include + #include #include #include +#include +#include +#include + #include -#if defined(ENABLE_THREADS) -#include -#include -#endif using simgear::PropertyList; @@ -110,6 +112,7 @@ protected: simgear::TiedPropertyList _tiedProperties; typedef std::vector MetarPropertiesList; MetarPropertiesList _metarProperties; + }; /* -------------------------------------------------------------------------------- */ @@ -195,86 +198,95 @@ public: virtual void update (bool first, double delta_time_sec); virtual void shutdown (); - class MetarLoadRequest { - public: - MetarLoadRequest( const string & stationId ) : - _stationId(stationId), - _proxyHost(fgGetNode("/sim/presets/proxy/host", true)->getStringValue()), - _proxyPort(fgGetNode("/sim/presets/proxy/port", true)->getStringValue()), - _proxyAuth(fgGetNode("/sim/presets/proxy/authentication", true)->getStringValue()) - {} - MetarLoadRequest( const MetarLoadRequest & other ) : - _stationId(other._stationId), - _proxyHost(other._proxyAuth), - _proxyPort(other._proxyPort), - _proxyAuth(other._proxyAuth) - {} - string _stationId; - string _proxyHost; - string _proxyPort; - string _proxyAuth; - private: - }; - - class MetarLoadResponse { - public: - MetarLoadResponse( const string & stationId, const string metar ) { - _stationId = stationId; - _metar = metar; - } - MetarLoadResponse( const MetarLoadResponse & other ) { - _stationId = other._stationId; - _metar = other._metar; - } - string _stationId; - string _metar; - }; + /** + * callback from MetarGetRequest when a download succeeds + */ + void gotMetar(const string& stationId, const string& metar); private: double _positionTimeToLive; double _requestTimer; -#if defined(ENABLE_THREADS) - class MetarLoadThread : public OpenThreads::Thread { - public: - MetarLoadThread( long maxAge ); - virtual ~MetarLoadThread( ) { stop(); } - void requestMetar( const MetarLoadRequest & metarRequest, bool background = true ); - bool hasMetar() { return _responseQueue.size() > 0; } - MetarLoadResponse getMetar() { return _responseQueue.pop(); } - virtual void run(); - void stop(); - private: - void fetch( const MetarLoadRequest & ); - long _maxAge; - long _minRequestInterval; - volatile bool _stop; - SGBlockingQueue _requestQueue; - SGBlockingQueue _responseQueue; - }; - - MetarLoadThread * _metarLoadThread; -#endif + simgear::HTTP::Client _http; }; +class MetarGetRequest : public simgear::HTTP::Request +{ +public: + MetarGetRequest(NoaaMetarRealWxController* con, const string& s) : + Request(""), + stationId(s), + fromProxy(false), + wxController(con) + { + setUrl("http://weather.noaa.gov/pub/data/observations/metar/stations/" + stationId + ".TXT"); + } + + virtual string_list requestHeaders() const + { + string_list r; + r.push_back("X-Time"); + return r; + } + + virtual string header(const string& name) const + { + if (name == "X-Time") { + char buf[16]; + snprintf(buf, 16, "%ld", globals->get_time_params()->get_cur_time()); + return buf; + } + + return Request::header(name); + } + + virtual void responseHeader(const string& key, const string& value) + { + if (key == "x-metarproxy") { + fromProxy = true; + } + } + + virtual void gotBodyData(const char* s, int n) + { + metar += string(s, n); + } + + virtual void responseComplete() + { + if (responseCode() == 200) { + wxController->gotMetar(stationId, metar); + } else { + SG_LOG(SG_IO, SG_WARN, "metar download failed:" << url() << ": reason:" << responseReason()); + } + } + + bool fromMetarProxy() const + { return fromProxy; } +private: + string stationId; + string metar; + bool fromProxy; + NoaaMetarRealWxController* wxController; +}; + + + NoaaMetarRealWxController::NoaaMetarRealWxController( SGPropertyNode_ptr rootNode ) : BasicRealWxController(rootNode), _positionTimeToLive(0.0), _requestTimer(0.0) { -#if defined(ENABLE_THREADS) - _metarLoadThread = new MetarLoadThread(getMetarMaxAgeMin()); - _metarLoadThread->start(); -#endif + string proxyHost(fgGetString("/sim/presets/proxy/host")); + int proxyPort(fgGetInt("/sim/presets/proxy/port")); + string proxyAuth(fgGetString("/sim/presets/proxy/auth")); + + if (!proxyHost.empty()) { + _http.setProxy(proxyHost, proxyPort, proxyAuth); + } } void NoaaMetarRealWxController::shutdown() { -#if defined(ENABLE_THREADS) - if( _metarLoadThread ) { - delete _metarLoadThread; - _metarLoadThread = NULL; - } -#endif // ENABLE_THREADS } NoaaMetarRealWxController::~NoaaMetarRealWxController() @@ -283,6 +295,8 @@ NoaaMetarRealWxController::~NoaaMetarRealWxController() void NoaaMetarRealWxController::update( bool first, double dt ) { + _http.update(); + _positionTimeToLive -= dt; _requestTimer -= dt; @@ -315,143 +329,32 @@ void NoaaMetarRealWxController::update( bool first, double dt ) if( _requestTimer <= 0.0 ) { _requestTimer = 10.0; + + BOOST_FOREACH(LiveMetarProperties* p, _metarProperties) { + if( p->getTimeToLive() > 0.0 ) continue; + const std::string & stationId = p->getStationId(); + if( stationId.empty() ) continue; - for( MetarPropertiesList::iterator it = _metarProperties.begin(); - it != _metarProperties.end(); it++ ) { - - if( (*it)->getTimeToLive() > 0.0 ) continue; - const std::string & stationId = (*it)->getStationId(); - if( stationId.empty() ) continue; - - SG_LOG(SG_ALL, SG_INFO, - "NoaaMetarRealWxController::update(): spawning load request for station-id '" << stationId << "'" ); + SG_LOG(SG_ALL, SG_INFO, + "NoaaMetarRealWxController::update(): spawning load request for station-id '" << stationId << "'" ); - MetarLoadRequest request( stationId ); - // load the metar for the nearest airport in the foreground if the fdm is uninitialized - // to make sure a metar is received - // before the automatic runway selection code runs. All subsequent calls - // run in the background - bool background = fgGetBool("/sim/fdm-initialized", false ) || it != _metarProperties.begin(); - _metarLoadThread->requestMetar( request, background ); - } - } - - // pick all the received responses from the result queue and update the associated - // property tree - while( _metarLoadThread->hasMetar() ) { - MetarLoadResponse metar = _metarLoadThread->getMetar(); - SG_LOG( SG_ALL, SG_INFO, "NoaaMetarRwalWxController::update() received METAR for " << metar._stationId << ": " << metar._metar ); - for( MetarPropertiesList::iterator it = _metarProperties.begin(); - it != _metarProperties.end(); it++ ) { - if( (*it)->getStationId() != metar._stationId ) - continue; - (*it)->setTimeToLive(900); - (*it)->setMetar( metar._metar ); - } + _http.makeRequest(new MetarGetRequest(this, stationId)); + } // of MetarProperties iteration } } -/* -------------------------------------------------------------------------------- */ - -#if defined(ENABLE_THREADS) -NoaaMetarRealWxController::MetarLoadThread::MetarLoadThread( long maxAge ) : - _maxAge(maxAge), - _minRequestInterval(2000), - _stop(false) +void NoaaMetarRealWxController::gotMetar(const string& stationId, const string& metar) { -} - -void NoaaMetarRealWxController::MetarLoadThread::requestMetar( const MetarLoadRequest & metarRequest, bool background ) -{ - if( background ) { - if( _requestQueue.size() > 10 ) { - SG_LOG(SG_ALL,SG_ALERT, - "NoaaMetarRealWxController::MetarLoadThread::requestMetar() more than 10 outstanding METAR requests, dropping " - << metarRequest._stationId ); - return; - } - - _requestQueue.push( metarRequest ); - } else { - fetch( metarRequest ); + SG_LOG( SG_ALL, SG_INFO, "NoaaMetarRwalWxController::update() received METAR for " << stationId << ": " << metar ); + BOOST_FOREACH(LiveMetarProperties* p, _metarProperties) { + if (p->getStationId() != stationId) + continue; + + p->setTimeToLive(900); + p->setMetar( metar ); } } -void NoaaMetarRealWxController::MetarLoadThread::stop() -{ - // set stop flag and wake up the thread with an empty request - _stop = true; - MetarLoadRequest request(""); - requestMetar(request); - join(); -} - -void NoaaMetarRealWxController::MetarLoadThread::run() -{ - SGTimeStamp lastRun = SGTimeStamp::fromSec(0); - for( ;; ) { - SGTimeStamp dt = SGTimeStamp::now() - lastRun; - - long delayMs = _minRequestInterval - dt.getSeconds() * 1000; - while (( delayMs > 0 ) && !_stop) - { - // sleep no more than 3 seconds at a time, otherwise shutdown response is too slow - long sleepMs = (delayMs>3000) ? 3000 : delayMs; - microSleep( sleepMs * 1000 ); - delayMs -= sleepMs; - } - - if (_stop) - break; - - lastRun = SGTimeStamp::now(); - - const MetarLoadRequest request = _requestQueue.pop(); - - if (( request._stationId.size() == 0 ) || _stop) - break; - - fetch( request ); - } -} - -void NoaaMetarRealWxController::MetarLoadThread::fetch( const MetarLoadRequest & request ) -{ - SGSharedPtr result = NULL; - - try { - result = new FGMetar( request._stationId, request._proxyHost, request._proxyPort, request._proxyAuth ); - _minRequestInterval = 2000; - } catch (const sg_io_exception& e) { - SG_LOG( SG_GENERAL, SG_WARN, "NoaaMetarRealWxController::fetchMetar(): can't get METAR for " - << request._stationId << ":" << e.getFormattedMessage().c_str() ); - _minRequestInterval += _minRequestInterval/2; - if( _minRequestInterval > 30000 ) - _minRequestInterval = 30000; - return; - } - - string reply = result->getData(); - std::replace(reply.begin(), reply.end(), '\n', ' '); - string metar = simgear::strutils::strip( reply ); - - if( metar.empty() ) { - SG_LOG( SG_GENERAL, SG_WARN, "NoaaMetarRealWxController::fetchMetar(): dropping empty METAR for " - << request._stationId ); - return; - } - - if( _maxAge && result->getAge_min() > _maxAge ) { - SG_LOG( SG_GENERAL, SG_ALERT, "NoaaMetarRealWxController::fetchMetar(): dropping outdated METAR " - << metar ); - return; - } - - MetarLoadResponse response( request._stationId, metar ); - _responseQueue.push( response ); -} -#endif - /* -------------------------------------------------------------------------------- */ RealWxController * RealWxController::createInstance( SGPropertyNode_ptr rootNode ) diff --git a/src/Main/FGEventHandler.cxx b/src/Main/FGEventHandler.cxx index d6be62054..5599723fa 100644 --- a/src/Main/FGEventHandler.cxx +++ b/src/Main/FGEventHandler.cxx @@ -60,6 +60,20 @@ FGEventHandler::FGEventHandler() : numlockKeyMap[GUIEventAdapter::KEY_KP_Home] = '7'; numlockKeyMap[GUIEventAdapter::KEY_KP_Up] = '8'; numlockKeyMap[GUIEventAdapter::KEY_KP_Page_Up] = '9'; + numlockKeyMap[GUIEventAdapter::KEY_KP_Delete] = '.'; + + // mapping when NumLock is off + noNumlockKeyMap[GUIEventAdapter::KEY_KP_Insert] = PU_KEY_INSERT; + noNumlockKeyMap[GUIEventAdapter::KEY_KP_End] = PU_KEY_END; + noNumlockKeyMap[GUIEventAdapter::KEY_KP_Down] = PU_KEY_DOWN; + noNumlockKeyMap[GUIEventAdapter::KEY_KP_Page_Down] = PU_KEY_PAGE_DOWN; + noNumlockKeyMap[GUIEventAdapter::KEY_KP_Left] = PU_KEY_LEFT; + noNumlockKeyMap[GUIEventAdapter::KEY_KP_Begin] = '5'; + noNumlockKeyMap[GUIEventAdapter::KEY_KP_Right] = PU_KEY_RIGHT; + noNumlockKeyMap[GUIEventAdapter::KEY_KP_Home] = PU_KEY_HOME; + noNumlockKeyMap[GUIEventAdapter::KEY_KP_Up] = PU_KEY_UP; + noNumlockKeyMap[GUIEventAdapter::KEY_KP_Page_Up] = PU_KEY_PAGE_UP; + noNumlockKeyMap[GUIEventAdapter::KEY_KP_Delete] = 127; for (int i = 0; i < 128; i++) release_keys[i] = i; @@ -259,7 +273,6 @@ void FGEventHandler::handleKey(const osgGA::GUIEventAdapter& ea, int& key, case GUIEventAdapter::KEY_F10: key = PU_KEY_F10; break; case GUIEventAdapter::KEY_F11: key = PU_KEY_F11; break; case GUIEventAdapter::KEY_F12: key = PU_KEY_F12; break; - case GUIEventAdapter::KEY_KP_Delete: key = '.'; break; case GUIEventAdapter::KEY_KP_Enter: key = '\r'; break; case GUIEventAdapter::KEY_KP_Add: key = '+'; break; case GUIEventAdapter::KEY_KP_Divide: key = '/'; break; @@ -268,18 +281,30 @@ void FGEventHandler::handleKey(const osgGA::GUIEventAdapter& ea, int& key, } osgGA::GUIEventAdapter::EventType eventType = ea.getEventType(); - std::map::iterator numPadIter = numlockKeyMap.find(key); - - if (numPadIter != numlockKeyMap.end()) { #ifdef __APPLE__ - // Num Lock is always true on Mac + // Num Lock is always true on Mac + std::map::iterator numPadIter = numlockKeyMap.find(key); + if (numPadIter != numlockKeyMap.end()) { key = numPadIter->second; + } #else - if (ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_NUM_LOCK) { + if (ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_NUM_LOCK) + { + // NumLock on: map to numeric keys + std::map::iterator numPadIter = numlockKeyMap.find(key); + if (numPadIter != numlockKeyMap.end()) { key = numPadIter->second; } -#endif } + else + { + // NumLock off: map to PU arrow keys + std::map::iterator numPadIter = noNumlockKeyMap.find(key); + if (numPadIter != noNumlockKeyMap.end()) { + key = numPadIter->second; + } + } +#endif modifiers = osgToFGModifiers(ea.getModKeyMask()); currentModifiers = modifiers; diff --git a/src/Main/FGEventHandler.hxx b/src/Main/FGEventHandler.hxx index 080d5afa1..652b2b74d 100644 --- a/src/Main/FGEventHandler.hxx +++ b/src/Main/FGEventHandler.hxx @@ -113,6 +113,7 @@ protected: int statsType; int currentModifiers; std::map numlockKeyMap; + std::map noNumlockKeyMap; void handleKey(const osgGA::GUIEventAdapter& ea, int& key, int& modifiers); bool resizable; bool mouseWarped; diff --git a/src/Scenery/scenery.cxx b/src/Scenery/scenery.cxx index 58bd4db56..12c3ebb69 100644 --- a/src/Scenery/scenery.cxx +++ b/src/Scenery/scenery.cxx @@ -28,8 +28,12 @@ #include #include +#include +#include +#include +#include +#include #include -#include #include #include @@ -38,6 +42,8 @@ #include #include #include +#include +#include #include
#include
@@ -70,6 +76,138 @@ public: } }; +class FGSceneryIntersect : public osg::NodeVisitor { +public: + FGSceneryIntersect(const SGLineSegmentd& lineSegment, + const osg::Node* skipNode) : + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN), + _lineSegment(lineSegment), + _skipNode(skipNode), + _material(0), + _haveHit(false) + { } + + bool getHaveHit() const + { return _haveHit; } + const SGLineSegmentd& getLineSegment() const + { return _lineSegment; } + const SGMaterial* getMaterial() const + { return _material; } + + virtual void apply(osg::Node& node) + { + if (&node == _skipNode) + return; + if (!testBoundingSphere(node.getBound())) + return; + + addBoundingVolume(node); + } + + virtual void apply(osg::Group& group) + { + if (&group == _skipNode) + return; + if (!testBoundingSphere(group.getBound())) + return; + + traverse(group); + addBoundingVolume(group); + } + + virtual void apply(osg::Transform& transform) + { handleTransform(transform); } + virtual void apply(osg::Camera& camera) + { + if (camera.getRenderOrder() != osg::Camera::NESTED_RENDER) + return; + handleTransform(camera); + } + virtual void apply(osg::CameraView& transform) + { handleTransform(transform); } + virtual void apply(osg::MatrixTransform& transform) + { handleTransform(transform); } + virtual void apply(osg::PositionAttitudeTransform& transform) + { handleTransform(transform); } + +private: + void handleTransform(osg::Transform& transform) + { + if (&transform == _skipNode) + return; + // Hmm, may be this needs to be refined somehow ... + if (transform.getReferenceFrame() != osg::Transform::RELATIVE_RF) + return; + + if (!testBoundingSphere(transform.getBound())) + return; + + osg::Matrix inverseMatrix; + if (!transform.computeWorldToLocalMatrix(inverseMatrix, this)) + return; + osg::Matrix matrix; + if (!transform.computeLocalToWorldMatrix(matrix, this)) + return; + + SGLineSegmentd lineSegment = _lineSegment; + bool haveHit = _haveHit; + const SGMaterial* material = _material; + + _haveHit = false; + _lineSegment = lineSegment.transform(SGMatrixd(inverseMatrix.ptr())); + + addBoundingVolume(transform); + traverse(transform); + + if (_haveHit) { + _lineSegment = _lineSegment.transform(SGMatrixd(matrix.ptr())); + } else { + _lineSegment = lineSegment; + _material = material; + _haveHit = haveHit; + } + } + + simgear::BVHNode* getNodeBoundingVolume(osg::Node& node) + { + SGSceneUserData* userData = SGSceneUserData::getSceneUserData(&node); + if (!userData) + return 0; + return userData->getBVHNode(); + } + void addBoundingVolume(osg::Node& node) + { + simgear::BVHNode* bvNode = getNodeBoundingVolume(node); + if (!bvNode) + return; + + // Find ground intersection on the bvh nodes + simgear::BVHLineSegmentVisitor lineSegmentVisitor(_lineSegment, + 0/*startTime*/); + bvNode->accept(lineSegmentVisitor); + if (!lineSegmentVisitor.empty()) { + _lineSegment = lineSegmentVisitor.getLineSegment(); + _material = lineSegmentVisitor.getMaterial(); + _haveHit = true; + } + } + + bool testBoundingSphere(const osg::BoundingSphere& bound) const + { + if (!bound.valid()) + return false; + + SGSphered sphere(toVec3d(toSG(bound._center)), bound._radius); + return intersects(_lineSegment, sphere); + } + + SGLineSegmentd _lineSegment; + const osg::Node* _skipNode; + + const SGMaterial* _material; + bool _haveHit; +}; + // Scenery Management system FGScenery::FGScenery() { @@ -138,43 +276,20 @@ FGScenery::get_elevation_m(const SGGeod& geod, double& alt, SGGeod geodEnd = geod; geodEnd.setElevationM(SGMiscd::min(geod.getElevationM() - 10, -10000)); SGVec3d end = SGVec3d::fromGeod(geodEnd); - - osgUtil::IntersectVisitor intersectVisitor; + + FGSceneryIntersect intersectVisitor(SGLineSegmentd(start, end), butNotFrom); intersectVisitor.setTraversalMask(SG_NODEMASK_TERRAIN_BIT); - osg::ref_ptr lineSegment; - lineSegment = new osg::LineSegment(toOsg(start), toOsg(end)); - intersectVisitor.addLineSegment(lineSegment.get()); get_scene_graph()->accept(intersectVisitor); - bool hits = false; - if (intersectVisitor.hits()) { - int nHits = intersectVisitor.getNumHits(lineSegment.get()); - alt = -SGLimitsd::max(); - for (int i = 0; i < nHits; ++i) { - const osgUtil::Hit& hit - = intersectVisitor.getHitList(lineSegment.get())[i]; - if (butNotFrom && - std::find(hit.getNodePath().begin(), hit.getNodePath().end(), - butNotFrom) != hit.getNodePath().end()) - continue; - // We might need the double variant of the intersection point. - // Thus we cannot use the float variant delivered by - // hit.getWorldIntersectPoint() but we have to redo that with osg::Vec3d. - osg::Vec3d point = hit.getLocalIntersectPoint(); - if (hit.getMatrix()) - point = point*(*hit.getMatrix()); - SGGeod geod = SGGeod::fromCart(toSG(point)); - double elevation = geod.getElevationM(); - if (alt < elevation) { - alt = elevation; - hits = true; - if (material) - *material = SGMaterialLib::findMaterial(hit.getGeode()); - } - } - } + if (!intersectVisitor.getHaveHit()) + return false; - return hits; + geodEnd = SGGeod::fromCart(intersectVisitor.getLineSegment().getEnd()); + alt = geodEnd.getElevationM(); + if (material) + *material = intersectVisitor.getMaterial(); + + return true; } bool @@ -190,40 +305,16 @@ FGScenery::get_cart_ground_intersection(const SGVec3d& pos, const SGVec3d& dir, // computation of ground intersection. SGVec3d start = pos; SGVec3d end = start + 1e5*normalize(dir); // FIXME visibility ??? - - osgUtil::IntersectVisitor intersectVisitor; - intersectVisitor.setTraversalMask(SG_NODEMASK_TERRAIN_BIT); - osg::ref_ptr lineSegment; - lineSegment = new osg::LineSegment(toOsg(start), toOsg(end)); - intersectVisitor.addLineSegment(lineSegment.get()); - get_scene_graph()->accept(intersectVisitor); - bool hits = false; - if (intersectVisitor.hits()) { - int nHits = intersectVisitor.getNumHits(lineSegment.get()); - double dist = SGLimitsd::max(); - for (int i = 0; i < nHits; ++i) { - const osgUtil::Hit& hit - = intersectVisitor.getHitList(lineSegment.get())[i]; - if (butNotFrom && - std::find(hit.getNodePath().begin(), hit.getNodePath().end(), - butNotFrom) != hit.getNodePath().end()) - continue; - // We might need the double variant of the intersection point. - // Thus we cannot use the float variant delivered by - // hit.getWorldIntersectPoint() but we have to redo that with osg::Vec3d. - osg::Vec3d point = hit.getLocalIntersectPoint(); - if (hit.getMatrix()) - point = point*(*hit.getMatrix()); - double newdist = length(start - toSG(point)); - if (newdist < dist) { - dist = newdist; - nearestHit = toSG(point); - hits = true; - } - } - } - return hits; + FGSceneryIntersect intersectVisitor(SGLineSegmentd(start, end), butNotFrom); + intersectVisitor.setTraversalMask(SG_NODEMASK_TERRAIN_BIT); + get_scene_graph()->accept(intersectVisitor); + + if (!intersectVisitor.getHaveHit()) + return false; + + nearestHit = intersectVisitor.getLineSegment().getEnd(); + return true; } bool FGScenery::scenery_available(const SGGeod& position, double range_m) diff --git a/utils/fgadmin/src/fgadmin_funcs.cxx b/utils/fgadmin/src/fgadmin_funcs.cxx index e8d2c9a0c..c05b9e929 100644 --- a/utils/fgadmin/src/fgadmin_funcs.cxx +++ b/utils/fgadmin/src/fgadmin_funcs.cxx @@ -24,14 +24,12 @@ #include #include #include -#include #ifdef _WIN32 # include #endif #include -#include #include @@ -142,11 +140,12 @@ void FGAdminUI::update_install_box() { install_box->clear(); if ( source.length() ) { - ulDir *dir = ulOpenDir( source.c_str() ) ; - ulDirEnt *ent; - while ( dir != 0 && ( ent = ulReadDir( dir ) ) ) { + struct dirent **list; + int nb = fl_filename_list( source.c_str(), &list ); + for ( int i = 0; i < nb; ++i ) { // find base name of archive file char base[FL_PATH_MAX]; + dirent *ent = list[i]; strncpy( base, ent->d_name, FL_PATH_MAX ); const char *p = fl_filename_ext( base ); int offset, expected_length = 0; @@ -186,9 +185,10 @@ void FGAdminUI::update_install_box() { // cout << install.str() << " exists." << endl; } } + free( ent ); } + free( list ); - ulCloseDir( dir ); for ( set::iterator it = file_list.begin(); it != file_list.end(); ++it ) { install_box->add( it->c_str() ); } @@ -217,16 +217,18 @@ void FGAdminUI::update_remove_box() { set dir_list; for ( int i = 0; i < 2; i++ ) { if ( !path[i].empty() ) { - ulDir *dir = ulOpenDir( path[i].c_str() ) ; - ulDirEnt *ent; - while ( dir != 0 && ( ent = ulReadDir( dir ) ) ) { + dirent **list; + int nb = fl_filename_list( path[i].c_str(), &list ); + for ( int i = 0; i < nb; ++i ) { + dirent *ent = list[i]; if ( strlen(ent->d_name) == 7 && ( ent->d_name[0] == 'e' || ent->d_name[0] == 'w' ) && ( ent->d_name[4] == 'n' || ent->d_name[4] == 's' ) ) { dir_list.insert( ent->d_name ); } + free( ent ); } - ulCloseDir( dir ); + free( list ); } } @@ -254,7 +256,7 @@ void FGAdminUI::install_selected() { SGPath file( source ); file.append( f ); struct stat info; - stat( file.str().c_str(), &info ); + fl_stat( file.str().c_str(), &info ); float old_max = progress->maximum(); progress->maximum( info.st_size ); progress_label = "Installing "; @@ -279,23 +281,25 @@ void FGAdminUI::install_selected() { static unsigned long count_dir( const char *dir_name, bool top = true ) { unsigned long cnt = 0L; - ulDir *dir = ulOpenDir( dir_name ) ; - if ( dir ) { - ulDirEnt *ent; - while ( ent = ulReadDir( dir ) ) { + dirent **list; + int nb = fl_filename_list( dir_name, &list ); + if ( nb != 0 ) { + for ( int i = 0; i < nb; ++i ) { + dirent *ent = list[i]; if ( strcmp( ent->d_name, "." ) == 0 ) { // ignore "." } else if ( strcmp( ent->d_name, ".." ) == 0 ) { // ignore ".." - } else if ( ent->d_isdir ) { + } else if ( fl_filename_isdir( ent->d_name ) ) { SGPath child( dir_name ); child.append( ent->d_name ); cnt += count_dir( child.c_str(), false ); } else { cnt += 1; } + free( ent ); } - ulCloseDir( dir ); + free( list ); } else if ( top ) { string base = dir_name; size_t pos = base.rfind('/'); @@ -310,15 +314,16 @@ static unsigned long count_dir( const char *dir_name, bool top = true ) { } static void remove_dir( const char *dir_name, void (*step)(void*,int), void *data, bool top = true ) { - ulDir *dir = ulOpenDir( dir_name ) ; - if ( dir ) { - ulDirEnt *ent; - while ( ent = ulReadDir( dir ) ) { + dirent **list; + int nb = fl_filename_list( dir_name, &list ); + if ( nb != 0 ) { + for ( int i = 0; i < nb; ++i ) { + dirent *ent = list[i]; if ( strcmp( ent->d_name, "." ) == 0 ) { // ignore "." } else if ( strcmp( ent->d_name, ".." ) == 0 ) { // ignore ".." - } else if ( ent->d_isdir ) { + } else if ( fl_filename_isdir( ent->d_name ) ) { SGPath child( dir_name ); child.append( ent->d_name ); remove_dir( child.c_str(), step, data, false ); @@ -328,8 +333,9 @@ static void remove_dir( const char *dir_name, void (*step)(void*,int), void *dat unlink( child.c_str() ); if (step) step( data, 1 ); } + free( ent ); } - ulCloseDir( dir ); + free( list ); rmdir( dir_name ); } else if ( top ) { string base = dir_name; diff --git a/utils/metarproxy/metarproxy b/utils/metarproxy/metarproxy index ba03eb377..88320881f 100755 --- a/utils/metarproxy/metarproxy +++ b/utils/metarproxy/metarproxy @@ -441,6 +441,8 @@ sub serve() $metar .= sprintf "$icao %02d%02d%02dZ ", $day, $hour, $min; $metar .= $last_metar{$addr} || $METAR_DEFAULT; } + + print $client "HTTP/1.0 200 OK\015\012"; print $client "Content-Type: text/plain\015\012" . "X-MetarProxy: nasse Maus\015\012" . "\015\012"