From 6c75e2fe3c4ad87479d354e6ae993c80382c7d7f Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Tue, 18 Mar 2014 18:33:44 +0100 Subject: [PATCH] CanvasImage: support for http protocol. - Download and display images. --- simgear/canvas/CanvasSystemAdapter.hxx | 2 + simgear/canvas/elements/CanvasImage.cxx | 71 +++++++++++++++++++++---- simgear/canvas/elements/CanvasImage.hxx | 3 ++ simgear/io/HTTPRequest.hxx | 19 +++++++ 4 files changed, 85 insertions(+), 10 deletions(-) diff --git a/simgear/canvas/CanvasSystemAdapter.hxx b/simgear/canvas/CanvasSystemAdapter.hxx index 91fc2740..a5c18487 100644 --- a/simgear/canvas/CanvasSystemAdapter.hxx +++ b/simgear/canvas/CanvasSystemAdapter.hxx @@ -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 diff --git a/simgear/canvas/elements/CanvasImage.cxx b/simgear/canvas/elements/CanvasImage.cxx index 28526389..a8eb4109 100644 --- a/simgear/canvas/elements/CanvasImage.cxx +++ b/simgear/canvas/elements/CanvasImage.cxx @@ -25,12 +25,12 @@ #include #include #include +#include #include #include #include - -#include +#include 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(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 diff --git a/simgear/canvas/elements/CanvasImage.hxx b/simgear/canvas/elements/CanvasImage.hxx index 02a21536..6d16e8b3 100644 --- a/simgear/canvas/elements/CanvasImage.hxx +++ b/simgear/canvas/elements/CanvasImage.hxx @@ -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 _texture; // TODO optionally forward events to canvas CanvasWeakPtr _src_canvas; diff --git a/simgear/io/HTTPRequest.hxx b/simgear/io/HTTPRequest.hxx index c9b9de66..e12e6d8d 100644 --- a/simgear/io/HTTPRequest.hxx +++ b/simgear/io/HTTPRequest.hxx @@ -8,6 +8,7 @@ #include #include +#include #include class SGPropertyNode; @@ -53,6 +54,12 @@ public: */ Request* done(const Callback& cb); + template + 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 + 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 + 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. -- 2.39.5