]> git.mxchange.org Git - simgear.git/commitdiff
CanvasImage: support for http protocol.
authorThomas Geymayer <tomgey@gmail.com>
Tue, 18 Mar 2014 17:33:44 +0000 (18:33 +0100)
committerThomas Geymayer <tomgey@gmail.com>
Tue, 18 Mar 2014 17:33:44 +0000 (18:33 +0100)
 - Download and display images.

simgear/canvas/CanvasSystemAdapter.hxx
simgear/canvas/elements/CanvasImage.cxx
simgear/canvas/elements/CanvasImage.hxx
simgear/io/HTTPRequest.hxx

index 91fc27400e370c0d121bafe953a70ebedf3a55d4..a5c184872a867d2be9edcb081ff8d9fbb9fd770b 100644 (file)
@@ -23,6 +23,7 @@
 
 namespace simgear
 {
+namespace HTTP { class Client; }
 namespace canvas
 {
 
@@ -35,6 +36,7 @@ namespace canvas
       virtual void addCamera(osg::Camera* camera) const = 0;
       virtual void removeCamera(osg::Camera* camera) const = 0;
       virtual osg::Image* getImage(const std::string& path) const = 0;
+      virtual HTTP::Client* getHTTPClient() const = 0;
   };
 
 } // namespace canvas
index 2852638984c2e4d80d5d6e47e2f15f47f489cb03..a8eb410982f2b649bfb03a3ea98f9f1ad734ed03 100644 (file)
 #include <simgear/scene/util/OsgMath.hxx>
 #include <simgear/scene/util/parse_color.hxx>
 #include <simgear/misc/sg_path.hxx>
+#include <simgear/io/HTTPClient.hxx>
 
 #include <osg/Array>
 #include <osg/Geometry>
 #include <osg/PrimitiveSet>
-
-#include <boost/algorithm/string/predicate.hpp>
+#include <osgDB/Registry>
 
 namespace simgear
 {
@@ -522,18 +522,29 @@ namespace canvas
     }
     else if( name == "file" )
     {
-      static const std::string CANVAS_PROTOCOL = "canvas://";
-      const std::string& path = child->getStringValue();
+      static const std::string PROTOCOL_SEP = "://";
+
+      std::string url = child->getStringValue(),
+                  protocol, path;
 
-      CanvasPtr canvas = _canvas.lock();
-      if( !canvas )
+      size_t sep_pos = url.find(PROTOCOL_SEP);
+      if( sep_pos != std::string::npos )
       {
-        SG_LOG(SG_GL, SG_ALERT, "canvas::Image: No canvas available");
-        return;
+        protocol = url.substr(0, sep_pos);
+        path = url.substr(sep_pos + PROTOCOL_SEP.length());
       }
+      else
+        path = url;
 
-      if( boost::starts_with(path, CANVAS_PROTOCOL) )
+      if( protocol == "canvas" )
       {
+        CanvasPtr canvas = _canvas.lock();
+        if( !canvas )
+        {
+          SG_LOG(SG_GL, SG_ALERT, "canvas::Image: No canvas available");
+          return;
+        }
+
         CanvasMgr* canvas_mgr = canvas->getCanvasMgr();
         if( !canvas_mgr )
         {
@@ -544,7 +555,7 @@ namespace canvas
         const SGPropertyNode* canvas_node =
           canvas_mgr->getPropertyRoot()
                     ->getParent()
-                    ->getNode( path.substr(CANVAS_PROTOCOL.size()) );
+                    ->getNode( path );
         if( !canvas_node )
         {
           SG_LOG(SG_GL, SG_ALERT, "canvas::Image: No such canvas: " << path);
@@ -562,6 +573,14 @@ namespace canvas
 
         setSrcCanvas(src_canvas);
       }
+      else if( protocol == "http" || protocol == "https" )
+      // TODO check https
+      {
+        Canvas::getSystemAdapter()
+          ->getHTTPClient()
+          ->load(url)
+          ->done(this, &Image::handleImageLoadDone);
+      }
       else
       {
         setImage( Canvas::getSystemAdapter()->getImage(path) );
@@ -637,5 +656,37 @@ namespace canvas
     (*_texCoords)[i + 3].set(tl.x(), br.y());
   }
 
+  //----------------------------------------------------------------------------
+  void Image::handleImageLoadDone(HTTP::Request* req)
+  {
+    if( req->responseCode() != 200 )
+    {
+      SG_LOG( SG_GL,
+              SG_WARN,
+              "canvas::Image: failed to download '" << req->url() << "': "
+                                                    << req->responseReason() );
+      return;
+    }
+
+    std::string ext = SGPath(req->path()).extension();
+    SG_LOG(SG_GL, SG_INFO, "canvas::Image: received " << req->url());
+
+    osgDB::ReaderWriter* rw =
+      osgDB::Registry::instance()->getReaderWriterForExtension(ext);
+
+    std::istringstream img_data(
+      static_cast<HTTP::MemoryRequest*>(req)->responseBody()
+    );
+
+    osgDB::ReaderWriter::ReadResult result = rw->readImage(img_data);
+    if( result.success() )
+      setImage( result.takeImage() );
+    else
+      SG_LOG( SG_GL,
+              SG_WARN,
+              "canvas::Image: failed to read image '" << req->url() << "': "
+                                                      << result.message() );
+  }
+
 } // namespace canvas
 } // namespace simgear
index 02a21536214bc9f79b5a1937b8d5737276abe078..6d16e8b3d3ff38ecc9455facdec87124f921896b 100644 (file)
@@ -27,6 +27,7 @@
 
 namespace simgear
 {
+namespace HTTP { class Request; }
 namespace canvas
 {
 
@@ -103,6 +104,8 @@ namespace canvas
       void setQuad(size_t index, const SGVec2f& tl, const SGVec2f& br);
       void setQuadUV(size_t index, const SGVec2f& tl, const SGVec2f& br);
 
+      void handleImageLoadDone(HTTP::Request*);
+
       osg::ref_ptr<osg::Texture2D> _texture;
       // TODO optionally forward events to canvas
       CanvasWeakPtr _src_canvas;
index c9b9de66a78d3d339af47d832098dda16c9dbea5..e12e6d8d9c2d16b13caa35b332b7c1cc118dbb7e 100644 (file)
@@ -8,6 +8,7 @@
 #include <simgear/structure/SGSharedPtr.hxx>
 #include <simgear/math/sg_types.hxx>
 
+#include <boost/bind.hpp>
 #include <boost/function.hpp>
 
 class SGPropertyNode;
@@ -53,6 +54,12 @@ public:
      */
     Request* done(const Callback& cb);
 
+    template<class C>
+    Request* done(C* instance, void (C::*mem_func)(Request*))
+    {
+      return done(boost::bind(mem_func, instance, _1));
+    }
+
     /**
      * Set the handler to be called when the request completes or aborts with an
      * error.
@@ -62,6 +69,12 @@ public:
      */
     Request* fail(const Callback& cb);
 
+    template<class C>
+    Request* fail(C* instance, void (C::*mem_func)(Request*))
+    {
+      return fail(boost::bind(mem_func, instance, _1));
+    }
+
     /**
      * Set the handler to be called when the request either successfully
      * completes or fails.
@@ -71,6 +84,12 @@ public:
      */
     Request* always(const Callback& cb);
 
+    template<class C>
+    Request* always(C* instance, void (C::*mem_func)(Request*))
+    {
+      return always(boost::bind(mem_func, instance, _1));
+    }
+
     /**
      * Set the data for the body of the request. The request is automatically
      * send using the POST method.