From: <br...@us...> - 2009-03-19 04:19:33
|
Revision: 3846 http://openvrml.svn.sourceforge.net/openvrml/?rev=3846&view=rev Author: braden Date: 2009-03-19 04:19:27 +0000 (Thu, 19 Mar 2009) Log Message: ----------- Created a convenience library libopenvrml-control to hold the platform-independent parts of the OpenVRML control (which is currently called openvrml-xembed). Modified Paths: -------------- trunk/ChangeLog trunk/src/Makefile.am trunk/src/openvrml-xembed/browser.cpp trunk/src/openvrml-xembed/plugin_streambuf.h Added Paths: ----------- trunk/src/libopenvrml-control/ trunk/src/libopenvrml-control/openvrml_control/ trunk/src/libopenvrml-control/openvrml_control/browser.cpp trunk/src/libopenvrml-control/openvrml_control/browser.h Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2009-03-19 04:07:16 UTC (rev 3845) +++ trunk/ChangeLog 2009-03-19 04:19:27 UTC (rev 3846) @@ -1,3 +1,73 @@ +2009-03-19 Braden McDaniel <br...@en...> + + Created a convenience library libopenvrml-control to hold the + platform-independent parts of the OpenVRML control (which is + currently called openvrml-xembed). + + * src/Makefile.am + (noinst_LTLIBRARIES): Added convenience library + libopenvrml-control. + (libopenvrml_control_libopenvrml_control_la_SOURCES): + libopenvrml-control sources. + (libopenvrml_control_libopenvrml_control_la_CPPFLAGS): + libopenvrml-control CPPFLAGS. + (libopenvrml_control_libopenvrml_control_la_LIBADD): Depends on + libopenvrml. + (openvrml_xembed_openvrml_xembed_CPPFLAGS): Added + libopenvrml-control to include path. + (openvrml_xembed_openvrml_xembed_LDADD): Depends on + libopenvrml-control. + * src/libopenvrml-control/openvrml_control/browser.cpp: Added + file. openvrml_control::browser encapsulates a browser "control". + * src/libopenvrml-control/openvrml_control/browser.h: Added + file. openvrml_control::browser encapsulates a browser "control". + * src/openvrml-xembed/browser.cpp + (resource_fetcher): Moved to + src/libopenvrml-control/openvrml_control/browser.cpp. + (browser_host_proxy): Added; implements + openvrml_control::browser_host. + (OpenvrmlXembedBrowserPrivate_): Added browser_control_host_proxy + and browser_control; removed resource_fetcher, browser, + browser_initialized_mutex, uninitialized_streambuf_map, + streambuf_map, initial_stream_reader_thread, got_initial_stream, + and browser_initialized. The removed members have been moved + to (or have equivalents in) openvrml_control::browser. + (initial_stream_reader): Moved to + src/libopenvrml-control/openvrml_control/browser.cpp. + (openvrml_xembed_browser_constructor(GType, guint, + GObjectConstructParam *)): Initialize the browser_control and + browser_control_host_proxy members; removed initialization of + removed members. + (openvrml_xembed_browser_finalize(GObject *)): Removed cleanup of + removed members; delete browser_control and + browser_control_host_proxy. + (openvrml_xembed_browser_new_stream(OpenvrmlXembedStreamClient *, + guint64, const char *, const char *, GError **)): Delegate to + openvrml_control::browser::new_stream. + (openvrml_xembed_browser_destroy_stream(OpenvrmlXembedStreamClient *, + guint64, GError **)): Delegate to + openvrml_control::browser::destroy_stream. + (openvrml_xembed_browser_write(OpenvrmlXembedStreamClient *, + guint64, const GArray *, GError **)): Delegate to + openvrml_control::browser::write. + (load_url): Moved to + src/libopenvrml-control/openvrml_control/browser.cpp. + (openvrml_xembed_browser_load_url(OpenvrmlXembedBrowser *, const + gchar **, const gchar **, GError **)): Delegate to + openvrml_control::browser::load_uri. + (openvrml_xembed_browser_get_world_url(OpenvrmlXembedBrowser *, + GError **)): Delegate to openvrml_control::browser::world_url. + (openvrml_xembed_browser_initialized(OpenvrmlXembedBrowser *)): + Delegate to openvrml_control::browser::initialized. + (browser_listener::do_browser_changed(const + openvrml::browser_event &)): Don't set browser_initialized; this + is now taken care of inside openvrml_control::browser. + (GtkGLViewer::GtkGLViewer(OpenvrmlXembedBrowserPlug &)): Call + openvrml_control::browser::viewer. + * src/openvrml-xembed/plugin_streambuf.h + (openvrml_xembed::plugin_streambuf): Grant friendship to + openvrml_control::browser. + 2009-03-18 Braden McDaniel <br...@en...> Newer jni.h is more const-correct; play along. Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2009-03-19 04:07:16 UTC (rev 3845) +++ trunk/src/Makefile.am 2009-03-19 04:19:27 UTC (rev 3846) @@ -721,6 +721,7 @@ libopenvrml_gl_libopenvrml_gl_la_LIBADD = libopenvrml/libopenvrml.la if ENABLE_XEMBED +noinst_LTLIBRARIES = libopenvrml-control/libopenvrml-control.la libexec_PROGRAMS = openvrml-xembed/openvrml-xembed session_bus_servicesdir = $(datadir)/dbus-1/services session_bus_services_DATA = openvrml-xembed/org.openvrml.BrowserControl.service @@ -729,8 +730,20 @@ openvrml-xembed/browser-factory-server-glue.h \ openvrml-xembed/browser-host-client-glue.h endif +libopenvrml_control_libopenvrml_control_la_SOURCES = \ + libopenvrml-control/openvrml_control/browser.cpp \ + libopenvrml-control/openvrml_control/browser.h +libopenvrml_control_libopenvrml_control_la_CPPFLAGS = \ + -I$(top_srcdir)/src/openvrml-xembed \ + -I$(top_builddir)/src/libopenvrml \ + -I$(top_srcdir)/src/libopenvrml +libopenvrml_control_libopenvrml_control_la_LIBADD = \ + libopenvrml/libopenvrml.la + openvrml_xembed_openvrml_xembed_CPPFLAGS = \ -I$(top_builddir)/src/openvrml-xembed \ + -I$(top_srcdir)/src/openvrml-xembed \ + -I$(top_srcdir)/src/libopenvrml-control \ -I$(top_builddir)/src/libopenvrml \ -I$(top_srcdir)/src/libopenvrml \ -I$(top_builddir)/src/libopenvrml-gl \ @@ -753,6 +766,7 @@ $(DBUS_G_LIBS) \ $(GTKGL_LIBS) openvrml_xembed_openvrml_xembed_LDADD = \ + libopenvrml-control/libopenvrml-control.la \ libopenvrml-gl/libopenvrml-gl.la openvrml_xembed_datadir = $(datadir)/openvrml-xembed Added: trunk/src/libopenvrml-control/openvrml_control/browser.cpp =================================================================== --- trunk/src/libopenvrml-control/openvrml_control/browser.cpp (rev 0) +++ trunk/src/libopenvrml-control/openvrml_control/browser.cpp 2009-03-19 04:19:27 UTC (rev 3846) @@ -0,0 +1,366 @@ +// -*- mode: c++; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 78 -*- +// +// OpenVRML Control +// +// Copyright 2009 Braden N. McDaniel +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; if not, see <http://www.gnu.org/licenses/>. +// + +# include "browser.h" +# include <openvrml/browser.h> +# include <boost/lexical_cast.hpp> +# include <iostream> + +openvrml_control::unknown_stream::unknown_stream(const std::string & uri): + std::logic_error("no stream corresponding to URI: " + uri) +{} + +openvrml_control::unknown_stream::unknown_stream(const uint64_t stream_id): + std::logic_error("no stream corresponding to stream ID: " + + boost::lexical_cast<std::string>(stream_id)) +{} + +openvrml_control::unknown_stream::~unknown_stream() throw () +{} + +openvrml_control::browser::resource_fetcher:: +resource_fetcher(browser_host & control_host, + openvrml_xembed::uninitialized_plugin_streambuf_map & + uninitialized_plugin_streambuf_map, + openvrml_xembed::plugin_streambuf_map & plugin_streambuf_map): + control_host_(control_host), + uninitialized_plugin_streambuf_map_(uninitialized_plugin_streambuf_map), + plugin_streambuf_map_(plugin_streambuf_map) +{} + +openvrml_control::browser::resource_fetcher::~resource_fetcher() + OPENVRML_NOTHROW +{ + this->thread_group_.join_all(); +} + +void +openvrml_control::browser::resource_fetcher:: +create_thread(const boost::function0<void> & threadfunc) +{ + this->thread_group_.create_thread(threadfunc); +} + +std::auto_ptr<openvrml::resource_istream> +openvrml_control::browser::resource_fetcher:: +do_get_resource(const std::string & uri) +{ + using openvrml_xembed::plugin_streambuf; + + class plugin_resource_istream : public openvrml::resource_istream { + const boost::shared_ptr<plugin_streambuf> streambuf_; + resource_fetcher & resource_fetcher_; + + public: + plugin_resource_istream(const std::string & uri, + resource_fetcher & fetcher): + openvrml::resource_istream(0), + streambuf_( + new plugin_streambuf( + uri, + fetcher.uninitialized_plugin_streambuf_map_, + fetcher.plugin_streambuf_map_)), + resource_fetcher_(fetcher) + { + this->rdbuf(this->streambuf_.get()); + fetcher.uninitialized_plugin_streambuf_map_.insert( + uri, this->streambuf_); + + // + // browser_host::get_url could throw; let it. + // + const int get_url_result = fetcher.control_host_.get_url(uri); + + if (get_url_result != 0) { + this->setstate(ios_base::badbit); + } + this->streambuf_->set_get_url_result(get_url_result); + } + + private: + virtual const std::string do_url() const OPENVRML_NOTHROW + { + return this->streambuf_->url(); + } + + virtual const std::string do_type() const OPENVRML_NOTHROW + { + return this->streambuf_->type(); + } + + virtual bool do_data_available() const OPENVRML_NOTHROW + { + return this->streambuf_->data_available(); + } + }; + return std::auto_ptr<openvrml::resource_istream>( + new plugin_resource_istream(uri, *this)); +} + +openvrml_control::browser::browser_listener::browser_listener(browser & b): + browser_(b) +{} + +void +openvrml_control::browser::browser_listener:: +do_browser_changed(const openvrml::browser_event & event) +{ + switch (event.id()) { + case openvrml::browser_event::initialized: + { + boost::mutex::scoped_lock lock(this->browser_.initialized_mutex_); + this->browser_.initialized_ = true; + } + break; + default: + break; + } +} + +namespace { + // + // We don't already know what the URI of the initial stream is until we + // start getting that data from the browser. This is a placeholder that + // is used to identify the plugin_streambuf that will be used to receive + // the initial stream data. + // + const char initial_stream_uri[] = "x-openvrml-initial:"; + + struct OPENVRML_LOCAL initial_stream_reader { + initial_stream_reader( + const boost::shared_ptr<openvrml_xembed::plugin_streambuf> & + streambuf, + openvrml::browser & browser): + streambuf_(streambuf), + browser_(browser) + {} + + void operator()() const throw () + { + using openvrml_xembed::plugin_streambuf; + + class plugin_istream : public openvrml::resource_istream { + boost::shared_ptr<plugin_streambuf> streambuf_; + + public: + explicit plugin_istream( + const boost::shared_ptr<plugin_streambuf> & streambuf): + openvrml::resource_istream(streambuf.get()), + streambuf_(streambuf) + {} + + virtual ~plugin_istream() throw () + {} + + private: + virtual const std::string do_url() const throw (std::bad_alloc) + { + return this->streambuf_->url(); + } + + virtual const std::string do_type() const + throw (std::bad_alloc) + { + return this->streambuf_->type(); + } + + virtual bool do_data_available() const throw () + { + return this->streambuf_->data_available(); + } + } in(this->streambuf_); + + this->browser_.set_world(in); + } + + private: + boost::shared_ptr<openvrml_xembed::plugin_streambuf> streambuf_; + openvrml::browser & browser_; + }; +} + +openvrml_control::browser::browser(browser_host & host, + const bool expect_initial_stream): + fetcher_(host, + this->uninitialized_streambuf_map_, + this->streambuf_map_), + listener_(*this), + browser_(this->fetcher_, std::cout, std::cerr), + host_(host), + expect_initial_stream_(expect_initial_stream), + got_initial_stream_(false) +{ + this->browser_.add_listener(this->listener_); + + // + // If necessary, create the initial stream. + // + if (expect_initial_stream) { + using boost::function0; + using boost::shared_ptr; + using openvrml_xembed::plugin_streambuf; + + const shared_ptr<plugin_streambuf> initial_stream( + new plugin_streambuf(::initial_stream_uri, + this->uninitialized_streambuf_map_, + this->streambuf_map_)); + initial_stream->state_ = plugin_streambuf::uninitialized; + this->uninitialized_streambuf_map_.insert(::initial_stream_uri, + initial_stream); + + const function0<void> initial_stream_reader_func = + initial_stream_reader(initial_stream, this->browser_); + + this->initial_stream_reader_thread_.reset( + new boost::thread(initial_stream_reader_func)); + } +} + +openvrml_control::browser::~browser() OPENVRML_NOTHROW +{ + if (this->expect_initial_stream_) { + this->initial_stream_reader_thread_->join(); + } + this->browser_.remove_listener(this->listener_); +} + +bool openvrml_control::browser::initialized() const +{ + boost::mutex::scoped_lock lock(this->initialized_mutex_); + return this->initialized_; +} + +void openvrml_control::browser::new_stream(const uint64_t stream_id, + const std::string & type, + const std::string & uri) + OPENVRML_THROW1(unknown_stream) +{ + using namespace openvrml_xembed; + using boost::shared_ptr; + + shared_ptr<plugin_streambuf> streambuf = + this->uninitialized_streambuf_map_.find(uri); + + if (!streambuf) { + if (!this->got_initial_stream_) { + assert(this->uninitialized_streambuf_map_.size() == 1); + streambuf = this->uninitialized_streambuf_map_.front(); + this->got_initial_stream_ = true; + } else { + throw unknown_stream(uri); + } + } + assert(streambuf->state() != plugin_streambuf::initialized); + streambuf->init(stream_id, uri, type); +} + +void openvrml_control::browser::destroy_stream(const uint64_t stream_id) + OPENVRML_THROW1(unknown_stream) +{ + using namespace openvrml_xembed; + using boost::shared_ptr; + + const shared_ptr<plugin_streambuf> streambuf = + this->streambuf_map_.find(stream_id); + if (!streambuf) { throw unknown_stream(stream_id); } + streambuf->buf_.set_eof(); + this->streambuf_map_.erase(stream_id); +} + +void openvrml_control::browser::write(const uint64_t stream_id, + const unsigned char * const data, + const size_t size) + OPENVRML_THROW1(unknown_stream) +{ + using namespace openvrml_xembed; + using boost::shared_ptr; + + const shared_ptr<plugin_streambuf> streambuf = + this->streambuf_map_.find(stream_id); + if (!streambuf) { throw unknown_stream(stream_id); } + for (size_t i = 0; i < size; ++i) { streambuf->buf_.put(data[i]); } +} + +struct OPENVRML_LOCAL openvrml_control::browser::load_url { + load_url(browser & b, + const std::vector<std::string> & url, + const std::vector<std::string> & parameter): + browser_(b), + url_(url), + parameter_(parameter) + {} + + void operator()() const OPENVRML_NOTHROW + { + try { + { + boost::mutex::scoped_lock + lock(this->browser_.initialized_mutex_); + this->browser_.initialized_ = false; + } + this->browser_.browser_.load_url(this->url_, this->parameter_); + } catch (std::exception & ex) { + this->browser_.browser_.err(ex.what()); + } + } + + private: + browser & browser_; + const std::vector<std::string> url_, parameter_; +}; + +void +openvrml_control::browser::load_uri(const std::vector<std::string> & uri, + const std::vector<std::string> & parameter) + OPENVRML_THROW2(boost::thread_resource_error, std::bad_alloc) +{ + this->fetcher_.create_thread(load_url(*this, uri, parameter)); +} + +const std::string openvrml_control::browser::world_url() +{ + return this->browser_.world_url(); +} + +bool +openvrml_control::browser::add_listener(openvrml::browser_listener & listener) +{ + return this->browser_.add_listener(listener); +} + +bool +openvrml_control::browser:: +remove_listener(openvrml::browser_listener & listener) +{ + return this->browser_.remove_listener(listener); +} + +void openvrml_control::browser::viewer(openvrml::viewer * v) +{ + this->browser_.viewer(v); +} + +openvrml_control::browser_host::~browser_host() +{} + +int openvrml_control::browser_host::get_url(const std::string & url) +{ + this->do_get_url(url); +} Property changes on: trunk/src/libopenvrml-control/openvrml_control/browser.cpp ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/src/libopenvrml-control/openvrml_control/browser.h =================================================================== --- trunk/src/libopenvrml-control/openvrml_control/browser.h (rev 0) +++ trunk/src/libopenvrml-control/openvrml_control/browser.h 2009-03-19 04:19:27 UTC (rev 3846) @@ -0,0 +1,123 @@ +// -*- mode: c++; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 78 -*- +// +// OpenVRML Control +// +// Copyright 2009 Braden N. McDaniel +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; if not, see <http://www.gnu.org/licenses/>. +// + +# ifndef OPENVRML_CONTROL_BROWSER_H +# define OPENVRML_CONTROL_BROWSER_H + +# include "plugin_streambuf.h" +# include <openvrml/browser.h> + +namespace openvrml_control { + + class unknown_stream : public std::logic_error { + public: + explicit unknown_stream(const std::string & uri); + explicit unknown_stream(uint64_t stream_id); + virtual ~unknown_stream() throw (); + }; + + class browser_host; + + class browser { + struct load_url; + + class resource_fetcher : public openvrml::resource_fetcher { + browser_host & control_host_; + openvrml_xembed::uninitialized_plugin_streambuf_map & + uninitialized_plugin_streambuf_map_; + openvrml_xembed::plugin_streambuf_map & plugin_streambuf_map_; + boost::thread_group thread_group_; + + public: + resource_fetcher( + browser_host & control_host, + openvrml_xembed::uninitialized_plugin_streambuf_map & + uninitialized_plugin_streambuf_map, + openvrml_xembed::plugin_streambuf_map & plugin_streambuf_map); + virtual ~resource_fetcher() OPENVRML_NOTHROW; + + void create_thread(const boost::function0<void> & threadfunc); + + private: + virtual std::auto_ptr<openvrml::resource_istream> + do_get_resource(const std::string & uri); + }; + + class browser_listener : public openvrml::browser_listener { + browser & browser_; + + public: + explicit browser_listener(browser & b); + + private: + virtual void + do_browser_changed(const openvrml::browser_event & event); + }; + + openvrml_xembed::uninitialized_plugin_streambuf_map + uninitialized_streambuf_map_; + openvrml_xembed::plugin_streambuf_map streambuf_map_; + resource_fetcher fetcher_; + browser_listener listener_; + openvrml::browser browser_; + browser_host & host_; + boost::scoped_ptr<boost::thread> initial_stream_reader_thread_; + bool expect_initial_stream_, got_initial_stream_; + mutable boost::mutex initialized_mutex_; + bool initialized_; + + public: + browser(browser_host & host, bool expect_initial_stream); + ~browser() OPENVRML_NOTHROW; + + bool initialized() const; + + void new_stream(uint64_t stream_id, + const std::string & type, const std::string & uri) + OPENVRML_THROW1(unknown_stream); + void destroy_stream(uint64_t stream_id) + OPENVRML_THROW1(unknown_stream); + void write(uint64_t stream_id, const unsigned char * data, size_t size) + OPENVRML_THROW1(unknown_stream); + + void load_uri(const std::vector<std::string> & uri, + const std::vector<std::string> & parameter) + OPENVRML_THROW2(boost::thread_resource_error, std::bad_alloc); + const std::string world_url(); + + bool add_listener(openvrml::browser_listener & listener); + bool remove_listener(openvrml::browser_listener & listener); + + void viewer(openvrml::viewer * v); + }; + + + class browser_host { + public: + virtual ~browser_host() = 0; + + int get_url(const std::string & url); + + private: + virtual int do_get_url(const std::string & url) = 0; + }; +} + +# endif // ifndef OPENVRML_CONTROL_BROWSER_H Property changes on: trunk/src/libopenvrml-control/openvrml_control/browser.h ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/src/openvrml-xembed/browser.cpp =================================================================== --- trunk/src/openvrml-xembed/browser.cpp 2009-03-19 04:07:16 UTC (rev 3845) +++ trunk/src/openvrml-xembed/browser.cpp 2009-03-19 04:19:27 UTC (rev 3846) @@ -18,21 +18,17 @@ // with this library; if not, see <http://www.gnu.org/licenses/>. // -# include <iostream> -# include <sstream> # include <boost/multi_index/detail/scope_guard.hpp> // Must include before X11 headers. # include <boost/numeric/conversion/converter.hpp> -# include <boost/ptr_container/ptr_map.hpp> # include <X11/keysym.h> # include <dbus/dbus-glib.h> # include <gdk/gdkx.h> -# include <openvrml/browser.h> +# include <openvrml_control/browser.h> # include <openvrml/gl/viewer.h> # include "browser.h" # include "browser-server-glue.h" # include "browser-host-client-glue.h" -# include "plugin_streambuf.h" # include <gtk/gtkgl.h> # include <gtk/gtkdrawingarea.h> @@ -73,54 +69,59 @@ openvrml_xembed_browser_stream_client_interface_init)) namespace { - class G_GNUC_INTERNAL resource_fetcher : public openvrml::resource_fetcher { - DBusGProxy & control_host_; - openvrml_xembed::uninitialized_plugin_streambuf_map & - uninitialized_plugin_streambuf_map_; - openvrml_xembed::plugin_streambuf_map & plugin_streambuf_map_; - boost::thread_group thread_group_; + class G_GNUC_INTERNAL browser_listener : public openvrml::browser_listener { + OpenvrmlXembedBrowser & browser_; + public: - resource_fetcher( - DBusGProxy & control_host, - openvrml_xembed::uninitialized_plugin_streambuf_map & - uninitialized_plugin_streambuf_map, - openvrml_xembed::plugin_streambuf_map & plugin_streambuf_map); - virtual ~resource_fetcher() OPENVRML_NOTHROW; + explicit browser_listener(OpenvrmlXembedBrowser & browser); - void create_thread(const boost::function0<void> & threadfunc); - private: - virtual std::auto_ptr<openvrml::resource_istream> - do_get_resource(const std::string & uri); + virtual void do_browser_changed(const openvrml::browser_event & event); }; - class G_GNUC_INTERNAL browser_listener : public openvrml::browser_listener { - OpenvrmlXembedBrowser & browser_; + class G_GNUC_INTERNAL browser_host_proxy : + public openvrml_control::browser_host { + + DBusGProxy & host_; + public: - explicit browser_listener(OpenvrmlXembedBrowser & browser); + explicit browser_host_proxy(DBusGProxy & host): + host_(host) + {} private: - virtual void do_browser_changed(const openvrml::browser_event & event); + virtual int do_get_url(const std::string & url) + { + GError * error = 0; + scope_guard error_guard = make_guard(g_error_free, boost::ref(error)); + gint result = -1; + gboolean succeeded = + org_openvrml_BrowserHost_get_url(&this->host_, + url.c_str(), + &result, + &error); + if (!succeeded) { + throw std::invalid_argument(error->message); + } + + error_guard.dismiss(); + + return result; + } }; } struct OpenvrmlXembedBrowserPrivate_ { DBusGProxy * control_host; - ::resource_fetcher * resource_fetcher; - openvrml::browser * browser; + browser_host_proxy * browser_control_host_proxy; + openvrml_control::browser * browser_control; browser_listener * listener; OpenvrmlXembedBrowserPlug * browser_plug; GMutex * browser_plug_mutex; GCond * browser_plug_set_cond; - GMutex * browser_initialized_mutex; - openvrml_xembed::uninitialized_plugin_streambuf_map * uninitialized_streambuf_map; - openvrml_xembed::plugin_streambuf_map * streambuf_map; - boost::thread * initial_stream_reader_thread; bool expect_initial_stream; - bool got_initial_stream; - bool browser_initialized; }; # define OPENVRML_XEMBED_BROWSER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), OPENVRML_XEMBED_TYPE_BROWSER, OpenvrmlXembedBrowserPrivate)) @@ -207,68 +208,6 @@ &dbus_glib_openvrml_xembed_browser_object_info); } -namespace { - // - // We don't already know what the URI of the initial stream is until we - // start getting that data from the browser. This is a placeholder that - // is used to identify the plugin_streambuf that will be used to receive - // the initial stream data. - // - const char initial_stream_uri[] = "x-openvrml-initial:"; - - struct OPENVRML_LOCAL initial_stream_reader { - initial_stream_reader( - const boost::shared_ptr<openvrml_xembed::plugin_streambuf> & - streambuf, - openvrml::browser & browser): - streambuf_(streambuf), - browser_(browser) - {} - - void operator()() const throw () - { - using openvrml_xembed::plugin_streambuf; - - class plugin_istream : public openvrml::resource_istream { - boost::shared_ptr<plugin_streambuf> streambuf_; - - public: - explicit plugin_istream( - const boost::shared_ptr<plugin_streambuf> & streambuf): - openvrml::resource_istream(streambuf.get()), - streambuf_(streambuf) - {} - - virtual ~plugin_istream() throw () - {} - - private: - virtual const std::string do_url() const throw (std::bad_alloc) - { - return this->streambuf_->url(); - } - - virtual const std::string do_type() const - throw (std::bad_alloc) - { - return this->streambuf_->type(); - } - - virtual bool do_data_available() const throw () - { - return this->streambuf_->data_available(); - } - } in(this->streambuf_); - - this->browser_.set_world(in); - } - - private: - boost::shared_ptr<openvrml_xembed::plugin_streambuf> streambuf_; - openvrml::browser & browser_; - }; -} - GObject * openvrml_xembed_browser_constructor( GType type, @@ -289,54 +228,21 @@ try { OpenvrmlXembedBrowser * const browser = OPENVRML_XEMBED_BROWSER(obj); - browser->priv->uninitialized_streambuf_map = - new openvrml_xembed::uninitialized_plugin_streambuf_map; - browser->priv->streambuf_map = - new openvrml_xembed::plugin_streambuf_map; - browser->priv->resource_fetcher = - new resource_fetcher(*browser->priv->control_host, - *browser->priv->uninitialized_streambuf_map, - *browser->priv->streambuf_map); - browser->priv->browser = - new openvrml::browser(*browser->priv->resource_fetcher, - std::cout, - std::cerr); + browser->priv->browser_control_host_proxy = + new browser_host_proxy(*browser->priv->control_host); + browser->priv->browser_control = + new openvrml_control::browser( + *browser->priv->browser_control_host_proxy, + browser->priv->expect_initial_stream); browser->priv->listener = new browser_listener(*browser); - browser->priv->browser->add_listener(*browser->priv->listener); + browser->priv->browser_control->add_listener(*browser->priv->listener); browser->priv->browser_plug = 0; browser->priv->browser_plug_mutex = g_mutex_new(); browser->priv->browser_plug_set_cond = g_cond_new(); - - browser->priv->browser_initialized = false; - browser->priv->browser_initialized_mutex = g_mutex_new(); - - // - // If necessary, create the initial stream. - // - if (browser->priv->expect_initial_stream) { - using boost::function0; - using boost::shared_ptr; - using openvrml_xembed::plugin_streambuf; - - const shared_ptr<plugin_streambuf> initial_stream( - new plugin_streambuf( - ::initial_stream_uri, - *browser->priv->uninitialized_streambuf_map, - *browser->priv->streambuf_map)); - initial_stream->state_ = plugin_streambuf::uninitialized; - browser->priv->uninitialized_streambuf_map - ->insert(::initial_stream_uri, initial_stream); - - const function0<void> initial_stream_reader_func = - initial_stream_reader(initial_stream, *browser->priv->browser); - - browser->priv->initial_stream_reader_thread = - new boost::thread(initial_stream_reader_func); - } } catch (std::exception & ex) { // - // ex is most likely std::bad_alloc or boost::thread_resource_error. + // ex is most likely std::bad_alloc. // g_critical("%s", ex.what()); return 0; @@ -347,21 +253,12 @@ void openvrml_xembed_browser_finalize(GObject * const obj) { OpenvrmlXembedBrowser * const browser = OPENVRML_XEMBED_BROWSER(obj); - - if (browser->priv->expect_initial_stream) { - browser->priv->initial_stream_reader_thread->join(); - delete browser->priv->initial_stream_reader_thread; - } - - g_mutex_free(browser->priv->browser_initialized_mutex); g_cond_free(browser->priv->browser_plug_set_cond); g_mutex_free(browser->priv->browser_plug_mutex); - browser->priv->browser->remove_listener(*browser->priv->listener); + browser->priv->browser_control->remove_listener(*browser->priv->listener); delete browser->priv->listener; - delete browser->priv->browser; - delete browser->priv->resource_fetcher; - delete browser->priv->streambuf_map; - delete browser->priv->uninitialized_streambuf_map; + delete browser->priv->browser_control; + delete browser->priv->browser_control_host_proxy; } void openvrml_xembed_browser_set_property(GObject * const obj, @@ -458,28 +355,15 @@ OpenvrmlXembedBrowser * const browser = OPENVRML_XEMBED_BROWSER(stream_client); - shared_ptr<plugin_streambuf> streambuf = - browser->priv->uninitialized_streambuf_map->find(url); - - if (!streambuf) { - if (!browser->priv->got_initial_stream) { - g_assert( - browser->priv->uninitialized_streambuf_map->size() == 1); - streambuf = - browser->priv->uninitialized_streambuf_map->front(); - browser->priv->got_initial_stream = true; - } else { - g_set_error( - error, - OPENVRML_XEMBED_ERROR, - OPENVRML_XEMBED_ERROR_UNKNOWN_STREAM, - "Attempt to create a stream that has not been requested: %s", - url); - return false; - } + try { + browser->priv->browser_control->new_stream(stream_id, type, url); + } catch (const openvrml_control::unknown_stream & ex) { + g_set_error(error, + OPENVRML_XEMBED_ERROR, + OPENVRML_XEMBED_ERROR_UNKNOWN_STREAM, + ex.what()); + return false; } - g_assert(streambuf->state() != plugin_streambuf::initialized); - streambuf->init(stream_id, url, type); return true; } @@ -495,19 +379,15 @@ OpenvrmlXembedBrowser * const browser = OPENVRML_XEMBED_BROWSER(stream_client); - const shared_ptr<plugin_streambuf> streambuf = - browser->priv->streambuf_map->find(stream_id); - if (!streambuf) { - g_set_error( - error, - OPENVRML_XEMBED_ERROR, - OPENVRML_XEMBED_ERROR_UNKNOWN_STREAM, - "Attempt to destroy a nonexistent stream: %lu", - stream_id); + try { + browser->priv->browser_control->destroy_stream(stream_id); + } catch (const openvrml_control::unknown_stream & ex) { + g_set_error(error, + OPENVRML_XEMBED_ERROR, + OPENVRML_XEMBED_ERROR_UNKNOWN_STREAM, + ex.what()); return false; } - streambuf->buf_.set_eof(); - browser->priv->streambuf_map->erase(stream_id); return true; } @@ -523,52 +403,20 @@ OpenvrmlXembedBrowser * const browser = OPENVRML_XEMBED_BROWSER(stream_client); - const shared_ptr<plugin_streambuf> streambuf = - browser->priv->streambuf_map->find(stream_id); - if (!streambuf) { - g_set_error( - error, - OPENVRML_XEMBED_ERROR, - OPENVRML_XEMBED_ERROR_UNKNOWN_STREAM, - "Attempt to write to a nonexistent stream: %lu", - stream_id); - return false; + try { + browser->priv->browser_control->write( + stream_id, + reinterpret_cast<unsigned char *>(data->data), + data->len); + } catch (const openvrml_control::unknown_stream & ex) { + g_set_error(error, + OPENVRML_XEMBED_ERROR, + OPENVRML_XEMBED_ERROR_UNKNOWN_STREAM, + ex.what()); } - for (size_t i = 0; i < data->len; ++i) { - streambuf->buf_.put(g_array_index(data, unsigned char, i)); - } return true; } -namespace { - struct G_GNUC_INTERNAL load_url { - load_url(OpenvrmlXembedBrowser & browser, - const std::vector<std::string> & url, - const std::vector<std::string> & parameter): - browser_(browser), - url_(url), - parameter_(parameter) - {} - - void operator()() const OPENVRML_NOTHROW - { - try { - g_mutex_lock(this->browser_.priv->browser_initialized_mutex); - this->browser_.priv->browser_initialized = false; - g_mutex_unlock(this->browser_.priv->browser_initialized_mutex); - this->browser_.priv->browser->load_url(this->url_, - this->parameter_); - } catch (std::exception & ex) { - this->browser_.priv->browser->err(ex.what()); - } - } - - private: - OpenvrmlXembedBrowser & browser_; - const std::vector<std::string> url_, parameter_; - }; -} - gboolean openvrml_xembed_browser_load_url(OpenvrmlXembedBrowser * const vrml_browser, const gchar ** url, @@ -583,8 +431,7 @@ while (url && *url) { url_vec.push_back(*(url++)); } while (parameter && *parameter) { param_vec.push_back(*(parameter++)); } - vrml_browser->priv->resource_fetcher - ->create_thread(load_url(*vrml_browser, url_vec, param_vec)); + vrml_browser->priv->browser_control->load_uri(url_vec, param_vec); } catch (const std::bad_alloc & ex) { *error = g_error_new(OPENVRML_XEMBED_ERROR, OPENVRML_XEMBED_ERROR_NO_MEMORY, @@ -653,19 +500,16 @@ gchar * openvrml_xembed_browser_get_world_url( - OpenvrmlXembedBrowser * const vrml_browser, + OpenvrmlXembedBrowser * const browser, GError ** /* error */) { - return g_strdup(vrml_browser->priv->browser->world_url().c_str()); + return g_strdup(browser->priv->browser_control->world_url().c_str()); } gboolean openvrml_xembed_browser_initialized(OpenvrmlXembedBrowser * const browser) { - g_mutex_lock(browser->priv->browser_initialized_mutex); - const bool browser_initialized = browser->priv->browser_initialized; - g_mutex_unlock(browser->priv->browser_initialized_mutex); - return browser_initialized; + return browser->priv->browser_control->initialized(); } @@ -1249,104 +1093,6 @@ namespace { - resource_fetcher::resource_fetcher( - DBusGProxy & control_host, - openvrml_xembed::uninitialized_plugin_streambuf_map & - uninitialized_plugin_streambuf_map, - openvrml_xembed::plugin_streambuf_map & plugin_streambuf_map): - control_host_(control_host), - uninitialized_plugin_streambuf_map_(uninitialized_plugin_streambuf_map), - plugin_streambuf_map_(plugin_streambuf_map) - {} - - resource_fetcher::~resource_fetcher() OPENVRML_NOTHROW - { - this->thread_group_.join_all(); - } - - void - resource_fetcher::create_thread(const boost::function0<void> & threadfunc) - { - this->thread_group_.create_thread(threadfunc); - } - - std::auto_ptr<openvrml::resource_istream> - resource_fetcher::do_get_resource(const std::string & uri) - { - using openvrml_xembed::plugin_streambuf; - - class plugin_resource_istream : public openvrml::resource_istream { - const boost::shared_ptr<plugin_streambuf> streambuf_; - resource_fetcher & resource_fetcher_; - - public: - plugin_resource_istream(const std::string & uri, - resource_fetcher & fetcher): - openvrml::resource_istream(0), - streambuf_( - new plugin_streambuf( - uri, - fetcher.uninitialized_plugin_streambuf_map_, - fetcher.plugin_streambuf_map_)), - resource_fetcher_(fetcher) - { - using std::ostringstream; - using boost::ref; - - this->rdbuf(this->streambuf_.get()); - fetcher.uninitialized_plugin_streambuf_map_ - .insert(uri, this->streambuf_); - - // - // We're in a thread started by libopenvrml here. By using - // dbus_g_proxy_begin_call here (instead of dbus_g_proxy_call), - // we finish the call in the main thread. That's important - // because we want to make sure this call "finishes" before - // we execute the host's successive NewStream call. - // - GError * error = 0; - scope_guard error_guard = make_guard(g_error_free, - boost::ref(error)); - gint get_url_result = -1; - gboolean succeeded = - org_openvrml_BrowserHost_get_url(&fetcher.control_host_, - uri.c_str(), - &get_url_result, - &error); - if (!succeeded) { - g_critical(error->message); - this->setstate(ios_base::badbit); - return; - } - - if (get_url_result != 0) { - this->setstate(ios_base::badbit); - } - this->streambuf_->set_get_url_result(get_url_result); - - error_guard.dismiss(); - } - - private: - virtual const std::string do_url() const throw () - { - return this->streambuf_->url(); - } - - virtual const std::string do_type() const throw () - { - return this->streambuf_->type(); - } - - virtual bool do_data_available() const throw () - { - return this->streambuf_->data_available(); - } - }; - return std::auto_ptr<openvrml::resource_istream>( - new plugin_resource_istream(uri, *this)); - } - browser_listener::browser_listener(OpenvrmlXembedBrowser & browser): browser_(browser) {} @@ -1357,10 +1103,6 @@ switch (event.id()) { case openvrml::browser_event::initialized: g_signal_emit(&this->browser_, signals[initialized_id], 0); - - g_mutex_lock(this->browser_.priv->browser_initialized_mutex); - this->browser_.priv->browser_initialized = true; - g_mutex_unlock(this->browser_.priv->browser_initialized_mutex); break; case openvrml::browser_event::shutdown: g_signal_emit(&this->browser_, signals[shutdown_id], 0); @@ -1374,7 +1116,7 @@ browser_plug_(browser_plug), timer(0) { - this->browser_plug_.priv->browser->priv->browser->viewer(this); + this->browser_plug_.priv->browser->priv->browser_control->viewer(this); } GtkGLViewer::~GtkGLViewer() throw () Modified: trunk/src/openvrml-xembed/plugin_streambuf.h =================================================================== --- trunk/src/openvrml-xembed/plugin_streambuf.h 2009-03-19 04:07:16 UTC (rev 3845) +++ trunk/src/openvrml-xembed/plugin_streambuf.h 2009-03-19 04:19:27 UTC (rev 3846) @@ -28,8 +28,11 @@ # include <boost/enable_shared_from_this.hpp> # include <openvrml/read_write_mutex.h> # include "bounded_buffer.h" -# include "browser.h" +namespace openvrml_control { + class browser; +} + namespace openvrml_xembed { // @@ -86,20 +89,7 @@ public boost::enable_shared_from_this<plugin_streambuf>, public std::streambuf { - friend - GObject * - (::openvrml_xembed_browser_constructor)( - GType type, - guint n_construct_properties, - GObjectConstructParam * construct_properties); - friend - gboolean - (::openvrml_xembed_browser_destroy_stream)(OpenvrmlXembedStreamClient *, - guint64, GError **); - friend - gboolean - (::openvrml_xembed_browser_write)(OpenvrmlXembedStreamClient *, guint64, - const GArray *, GError **); + friend class openvrml_control::browser; public: enum state_id { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |