From: <br...@us...> - 2008-09-06 04:06:43
|
Revision: 3582 http://openvrml.svn.sourceforge.net/openvrml/?rev=3582&view=rev Author: braden Date: 2008-09-06 04:06:52 +0000 (Sat, 06 Sep 2008) Log Message: ----------- Use D-Bus for communication between openvrml-xembed and its hosts, openvrml-player and the Mozilla plug-in. Modified Paths: -------------- trunk/ChangeLog trunk/README trunk/configure.ac trunk/lib/gtkglext/gdk/x11/gdkglcontext-x11.c trunk/mozilla-plugin/configure.ac trunk/mozilla-plugin/src/Makefile.am trunk/mozilla-plugin/src/openvrml.cpp trunk/src/Makefile.am trunk/src/openvrml-player/filechooserdialog.cpp trunk/src/openvrml-player/openvrml-player.ui trunk/src/openvrml-player/player.cpp trunk/src/openvrml-xembed/main.cpp trunk/src/openvrml-xembed/plugin_streambuf.cpp trunk/src/openvrml-xembed/plugin_streambuf.h Added Paths: ----------- trunk/src/openvrml-player/curlbrowserhost.cpp trunk/src/openvrml-player/curlbrowserhost.h trunk/src/openvrml-xembed/browser-factory.xml trunk/src/openvrml-xembed/browser-host.xml trunk/src/openvrml-xembed/browser.cpp trunk/src/openvrml-xembed/browser.h trunk/src/openvrml-xembed/browser.xml trunk/src/openvrml-xembed/browserfactory.cpp trunk/src/openvrml-xembed/browserfactory.h trunk/src/openvrml-xembed/org.openvrml.BrowserControl.service.in trunk/src/openvrml-xembed/streamclient.cpp trunk/src/openvrml-xembed/streamclient.h Removed Paths: ------------- trunk/src/openvrml-xembed/command_istream.cpp trunk/src/openvrml-xembed/command_istream.h trunk/src/openvrml-xembed/gtkvrmlbrowser.cpp trunk/src/openvrml-xembed/gtkvrmlbrowser.h trunk/src/openvrml-xembed/request_channel.h Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2008-09-06 03:01:00 UTC (rev 3581) +++ trunk/ChangeLog 2008-09-06 04:06:52 UTC (rev 3582) @@ -1,3 +1,253 @@ +2008-09-06 Braden McDaniel <br...@en...> + + Use D-Bus for communication between openvrml-xembed and its hosts, + openvrml-player and the Mozilla plug-in. + + * README: Note changed openvrml-xembed usage. + * configure.ac: Check for D-Bus; emit the BrowserControl service + descriptor. + * lib/gtkglext/gdk/x11/gdkglcontext-x11.c + (_gdk_gl_context_destroy): Fixed usage of + g_object_remove_weak_pointer. + (_gdk_gl_context_set_gl_drawable): Fixed usage of + g_object_{add,remove}_weak_pointer. + * mozilla-plugin/configure.ac: Check for D-Bus; remove check for + GTK+. + * mozilla-plugin/src/Makefile.am + (AM_CXXFLAGS): Added DBUS_G_CFLAGS. + (BUILT_SOURCES): Build browser-host-server-glue.h. + (openvrml_la_LDFLAGS): Added DBUS_G_LIBS. + * mozilla-plugin/src/openvrml.cpp + (OpenvrmlNpBrowserHost): GObject implementing the + org.openvrml.BrowserHost D-Bus interface. + (OpenvrmlNpBrowserHostClass): Class object for + OpenvrmlNpBrowserHost. + (openvrml_np_browser_host_get_type()): GType object for + OpenvrmlNpBrowserHost. + (plugin_instance): Use void* for window rather than + GdkNativeWindow; no reason for this type to be the plug-in code's + only GTK+ dependency. Removed members command_channel, + request_channel, request_channel_watch_id, and request_line. + Added browser_host--the org.openvrml.BrowserHost--and browser--the + proxy for the org.openvrml.Browser object. Removed write_command + member funtion; added member functions new_stream, destroy_stream, + and write. The latter are delegated to by NPP_NewStream, + NPP_DestroyStream, and NPP_Write, respectively. + (openvrml_np_browser_host_init(OpenvrmlNpBrowserHost *)): Instance + init function for the OpenvrmlNpBrowserHost GObject. + (openvrml_np_browser_host_class_init(OpenvrmlNpBrowserHostClass *)): + Class init function for the OpenvrmlNpBrowserHost GObject. + (openvrml_np_browser_host_get_url(OpenvrmlNpBrowserHost *, const + char *, GError **)): Implementation of + org.openvrml.BrowserHost.GetUrl. We can delegate directly to + NPN_GetURL. + (openvrml_np_browser_host_set_world_url(OpenvrmlNpBrowserHost *, + const char * url, GError **)): Implementation of + org.openvrml.BrowserHost.SetWorldUrl. For now, at least, we don't + need this to do anything. + (NPP_GetMIMDescription()): Use an explicit const_cast to quell the + gcc warning about using a string literal as a (nonconst) char*. + (NPP_NewStream(NPP, NPMIMEType, NPStream *, NPBool, uint16 *)): + Delegate to plugin_instance::new_stream. + (NPP_DestroyStream(NPP, NPStream *, NPError)): Delegate to + plugin_instance::destroy_stream. + (NPP_Write(NPP, NPStream *, int32, int32, void *)): Delegate to + plugin_instance::write. + (plugin_instance::plugin_instance(NPP)): Initialize the + browser_host; set its npp member. + (plugin_instance::~plugin_instance()): Emit the Shutdown signal. + (get_browser(DBusGConnection *, const char *, const char *, + guint64, GError **)): Get the org.openvrml.Browser proxy. + (plugin_instance::set_window(NPWindow &)): Get the plug via D-Bus; + we don't need (explicitly) to start up the openvrml-xembed process + here anymore. + (plugin_instance::new_stream(NPMIMEType, NPStream *)): Make a + blocking call to org.openvrml.Browser.NewStream. + (plugin_instance::destroy_stream(NPStream *)): Make a nonblocking + call to org.openvrml.Browser.DestroyStream. + (plugin_instance::write(NPStream *, int32, void *)): Make a + nonblocking call to org.openvrml.Browser.Write. + (plugin_instance::write_command(const std::string &)): Removed. + (request_data_available(GIOChannel *, GIOCondition, gpointer)): + Removed. + * src/Makefile.am + (session_bus_services_DATA): Install the + org.openvrml.BrowserControl service descriptor. + (noinst_HEADERS): Removed obsolete + openvrml-xembed/command_istream.h, + openvrml-xembed/request_channel.h, and + openvrml-xembed/gtkvrmlbrowser.h. + (openvrml_xembed_openvrml_xembed_CPPFLAGS): Look in the + openvrml-xembed builddir for headers (specifically, the ones + generated by dbus-binding-tool). + (openvrml_xembed_datadir): (Sub)package-specific data directory. + (openvrml_xembed_dbusdir): We'll install the D-Bus interface XML + here for lack of a better idea. + (dist_openvrml_xembed_dbus_DATA): D-Bus interface XML. + (BUILT_SOURCES): Build the introspection data headers with + dbus-binding-tool. + * src/openvrml-xembed/org.openvrml.BrowserControl.service.in + (openvrml_player_openvrml_player_CPPFLAGS): Look in the + openvrml-player builddir for headers (specifically, the ones + generated by dbus-binding-tool). + (openvrml_player_openvrml_player_CXXFLAGS): Added DBUS_G_CFLAGS. + (openvrml_player_openvrml_player_LDFLAGS): Added DBUS_G_LIBS. + (openvrml_player_openvrml_player_SOURCES): Added + openvrml-player/curlbrowserhost.{cpp,h}. + (EXTRA_DIST): Added + openvrml-xembed/org.openvrml.BrowserControl.service.in (configure + input). + (CLEANFILES): Added BUILT_SOURCES. + (DISTCLEANFILES): Clean up configure-generated files. + * src/openvrml-xembed/browser.cpp: Added file. + OpenvrmlXembedBrowser implementation (evolved from the now-defunct + GtkVrmlBrowser). + * src/openvrml-xembed/browser.h: Added file. + OpenvrmlXembedBrowser implements the org.openvrml.Browser D-Bus + interface. + * src/openvrml-xembed/browser.xml: Added + file. org.openvrml.Browser D-Bus interface definition. + * src/openvrml-xembed/browserfactory.cpp: Added file. + OpenvrmlXembedBrowserFactory implementation. + * src/openvrml-xembed/browserfactory.h: Added file. + OpenvrmlXembedBrowserFactory implements the + org.openvrml.BrowserFactory D-Bus interface. + * src/openvrml-xembed/browser-factory.xml: Added file. + org.openvrml.BrowserFactory D-Bus interface definition. + * src/openvrml-xembed/browser-host.xml: Added file. + org.openvrml.BrowserHost D-Bus interface definition. + * src/openvrml-xembed/command_istream.cpp: Removed. + * src/openvrml-xembed/command_istream.h: Removed. + * src/openvrml-xembed/gtkvrmlbrowser.cpp: Removed. + * src/openvrml-xembed/gtkvrmlbrowser.h: Removed. + * src/openvrml-xembed/plugin_streambuf.cpp + (openvrml_xembed::plugin_streambuf::plugin_streambuf(const + std::string &, uninitialized_plugin_streambuf_map &, + plugin_streambuf_map &)): Maintain references to the + uninitialized_plugin_streambuf_map and the plugin_streambuf_map. + Now that these maps are per-OpenvrmlXembedBrowser instance, we + cannot access them as globals. + (openvrml_xembed::plugin_streambuf::state() const): Get the + current state of the streambuf (i.e., requested, uninitialized, or + initialized). + (openvrml_xembed::plugin_streambuf::set_get_url_result(int)): + Since we no longer have the requested_plugin_streambuf_map, set + the state to uninitialized on success; or simply remove the stream + from the uninitialized_map_ on failure. + (openvrml_xembed::plugin_streambuf::fail()): Use the member + uninitialized_map_. + (openvrml_xembed::requested_plugin_streambuf_map::find(const + std::string &) const): Removed. + (openvrml_xembed::requested_plugin_streambuf_map::insert(const + std::string &, const boost::shared_ptr<plugin_streambuf> &)): + Removed. + (openvrml_xembed::requested_plugin_streambuf_map::map_entry_matches_streambuf): + Removed. + (openvrml_xembed::requested_plugin_streambuf_map::erase(const + plugin_streambuf &)): Removed. + (openvrml_xembed::requested_plugin_streambuf_map_): Removed. + (openvrml_xembed::uninitialized_plugin_streambuf_map_): Removed. + (openvrml_xembed::plugin_streambuf_map_): Removed. + * src/openvrml-xembed/plugin_streambuf.h + (openvrml_xembed::plugin_streambuf): Added state_id enum along + with state_ member and the corresponding state() accessor. Added + reference members for the uninitialized_plugin_streambuf_map and + the plugin_streambuf_map. + (openvrml_xembed::requested_plugin_streambuf_map): Removed. + * src/openvrml-xembed/main.cpp + (initial_stream_uri): Moved to browser.cpp. + (openvrml_xembed::request_channel): Removed. + (openvrml_xembed::request_channel_mutex): Removed. + (openvrml_xembed::event_listener_id_map): Removed. + (openvrml_xembed::command_istream_reader): Removed. + (openvrml_xembed::initial_stream_reader): Moved to browser.cpp. + (openvrml_xembed::command_channel_loop): Removed. + (main(int, char *[])): Removed --initial-stream option and the XID + argument. Rather than setting up GIOChannels, create the + BrowserFactory. + (openvrml_xembed_browser_event_func(GtkVrmlBrowser *, + GtkVrmlBrowserEvent, gpointer)): Removed. + (command_channel_shutdown(GIOChannel *)): Removed. + (request_channel_shutdown(GIOChannel *)): Removed. + * src/openvrml-xembed/request_channel.h: Removed. + * src/openvrml-xembed/streamclient.cpp: Added; + OpenvrmlXembedStreamClient interface definition. + * src/openvrml-xembed/streamclient.h: Added; a gobject interface + that a host can stream to. + * src/openvrml-player/openvrml-player.ui: Don't specify an object + target for the openvrml_player_on_file_open_activated signal + handler. Create a child OpenvrmlPlayerCurlBrowserHost instead of + a GtkSocket. + * src/openvrml-player/curlbrowserhost.cpp: Added. + OpenvrmlPlayerCurlBrowserHost implementation. + * src/openvrml-player/curlbrowserhost.h: Added. + OpenvrmlPlayerCurlBrowserHost inherits GtkSocket and implements + the org.openvrml.BrowserHost D-Bus interface. + * src/openvrml-player/player.cpp + (command_channel): Removed. + (request_channel): Removed. + (request_channel_watch_id): Removed. + (signal_data): Added. Data for GUI (GtkBuilder) signal handlers. + (curl_stream_data): Moved to curlbrowserhost.cpp. + (curl_source_callback_data): Removed. + (request_data): Removed. + (location_entry): Removed. + (OPENVRML_PLAYER_CURL_EASY_RETURN_VAL_IF_ERROR): Moved to + curlbrowserhost.cpp. + (OPENVRML_PLAYER_CURL_MULTI_RETURN_IF_ERROR): Moved to + curlbrowserhost.cpp. + (OPENVRML_PLAYER_CURL_MULTI_RETURN_VAL_IF_ERROR): Moved to + curlbrowserhost.cpp. + (main(int, char *[])): Got rid of all the command/request channel + setup stuff. The browser control is now created by the + OpenvrmlPlayerCurlControlHost. All we have to do in main is set + up the GUI. Note that since the control isn't created until + realize, we defer calling _load_url until then. + (get_openvrml_xembed_cmd(gint &, char **&)): Removed. + (spawn_openvrml_xembed(GtkNativeWindow, gint &, gint &)): Removed. + (set_locationentry_text(const gchar *)): Removed. + (load_url(const gchar *)): Removed. + (CURLSource): Moved to curlbrowserhost.cpp. + (curl_source_new(CURLM *)): Moved to curlbrowserhost.cpp. + (reset_fds(CURLSource &)): Moved to curlbrowserhost.cpp. + (openvrml_player_curl_prepare(GSource *, gint *)): Moved to + curlbrowserhost.cpp as + openvrml_player_curl_browser_host_curl_prepare. + (openvrml_player_curl_check(GSource *)): Moved to + curlbrowserhost.cpp as + openvrml_player_curl_browser_host_curl_check. + (openvrml_player_curl_dispatch(GSource *, GSourceFunc, gpointer)): + Moved to curlbrowserhost.cpp as + openvrml_player_curl_browser_host_curl_dispatch. + (openvrml_player_curl_finalize(GSource *)): Moved to + curlbrowserhost.cpp as + openvrml_player_curl_browser_host_curl_finalize. + (openvrml_player_curl_source_callback(gpointer)): Moved to + curlbrowserhost.cpp as + openvrml_player_curl_browser_host_curl_source_callback. + (openvrml_player_request_data_available(GIOChannel *, + GIOCondition, gpointer)): Removed. + (openvrml_player_curl_write(void *, size_t, size_t, void *)): + Moved to curlbrowserhost.cpp as + openvrml_player_curl_browser_host_curl_write. + (openvrml_player_on_file_open_activated(GtkAction *, gpointer)): + Use signal_data passed in the user_data argument. + (openvrml_player_on_locationentry_activated(GtkEntry *, + gpointer)): Use signal_data passed in the user_data argument. + (openvrml_player_quit): No more quit dance; just call + gtk_main_quit. + (openvrml_player_watch_child(GPid, gint, gpointer)): Removed. + (openvrml_player_on_browserhost_realize(GtkWidget *, gpointer)): + Load the URL passed in user_data; see main. + (write_command(const std::string &)): Removed. + (curl_stream_data(CURL *, const char *)): Moved to + curlbrowserhost.cpp. + (curl_stream_data::handle() const): Moved to curlbrowserhost.cpp. + (curl_stream_data::url() const): Moved to curlbrowserhost.cpp. + (curl_stream_data::initialize()): Moved to curlbrowserhost.cpp. + (curl_stream_data::initialized() const): Moved to + curlbrowserhost.cpp. + 2008-09-01 Braden McDaniel <br...@en...> * src/libopenvrml/openvrml/script.h: Don't need to include Modified: trunk/README =================================================================== --- trunk/README 2008-09-06 03:01:00 UTC (rev 3581) +++ trunk/README 2008-09-06 04:06:52 UTC (rev 3582) @@ -273,11 +273,12 @@ Mozilla-based browser will show a listing of successfully installed plug-ins. - It is possible, for testing or other convenience, to run the -plug-in from the build directories. A symbolic link to the plug-in -module "openvrml.so" must be made in the Mozilla plug-in directory and -the environment variable "OPENVRML_XEMBED" must be set to the full -path name of the "openvrml-xembed" executable. + To run openvrml-player or the Mozilla plug-in from the build +directories, you must first start an openvrml-xembed process. Once +openvrml-xembed has been installed, D-Bus will start it automatically +as needed. Additionally, to run the plug-in from the build +directories, a symbolic link to the plug-in module "openvrml.so" must +be made in the Mozilla plug-in directory. Conformance Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2008-09-06 03:01:00 UTC (rev 3581) +++ trunk/configure.ac 2008-09-06 04:06:52 UTC (rev 3582) @@ -10,6 +10,7 @@ [models/textures/Makefile] [lib/Makefile] [src/Makefile] + [src/openvrml-xembed/org.openvrml.BrowserControl.service] [src/libopenvrml/openvrml-config.h] [src/libopenvrml-gl/openvrml-gl-config.h] [src/script/Makefile] @@ -161,6 +162,13 @@ # openvrml-xembed and openvrml-player both use GOption, which was # introduced in GLib 2.6. # +PKG_CHECK_MODULES([DBUS_G], [dbus-glib-1 glib-2.0 >= 2.6], , + [have_dbus_glib=no]) +AC_PATH_PROG([DBUS_BINDING_TOOL], [dbus-binding-tool]) +session_bus_servicesdir=`$PKG_CONFIG --variable=session_bus_services_dir dbus-1` +AC_SUBST([session_bus_servicesdir]) + +# # openvrml-player uses GtkBuilder, which was introduced in GTK+ 2.12. # PKG_CHECK_MODULES([GTK], [gtk+-2.0 >= 2.12 gthread-2.0 glib-2.0 >= 2.6], , Modified: trunk/lib/gtkglext/gdk/x11/gdkglcontext-x11.c =================================================================== --- trunk/lib/gtkglext/gdk/x11/gdkglcontext-x11.c 2008-09-06 03:01:00 UTC (rev 3581) +++ trunk/lib/gtkglext/gdk/x11/gdkglcontext-x11.c 2008-09-06 04:06:52 UTC (rev 3582) @@ -107,9 +107,8 @@ if (impl->gldrawable != NULL) { - gpointer gldrawable_location = impl->gldrawable; g_object_remove_weak_pointer (G_OBJECT (impl->gldrawable), - &gldrawable_location); + (gpointer *) &impl->gldrawable); impl->gldrawable = NULL; } @@ -361,18 +360,16 @@ if (impl->gldrawable != NULL) { - gpointer gldrawable_location = impl->gldrawable; g_object_remove_weak_pointer (G_OBJECT (impl->gldrawable), - &gldrawable_location); + (gpointer *) &impl->gldrawable); impl->gldrawable = NULL; } if (gldrawable != NULL && GDK_IS_GL_DRAWABLE (gldrawable)) { impl->gldrawable = gldrawable; - gpointer gldrawable_location = impl->gldrawable; - g_object_add_weak_pointer (G_OBJECT (impl->gldrawable), - &gldrawable_location); + g_object_add_weak_pointer (G_OBJECT (gldrawable), + (gpointer *) &impl->gldrawable); } } Modified: trunk/mozilla-plugin/configure.ac =================================================================== --- trunk/mozilla-plugin/configure.ac 2008-09-06 03:01:00 UTC (rev 3581) +++ trunk/mozilla-plugin/configure.ac 2008-09-06 04:06:52 UTC (rev 3582) @@ -29,17 +29,15 @@ [PKG_CHECK_MODULES([MOZILLA_PLUGIN], [mozilla-plugin >= 1.6], [mozilla_plugin_pkg=mozilla-plugin], [have_mozilla_plugin=no])])])]) -PKG_CHECK_MODULES([GTK], [gtk+-2.0], , [have_gtk=no]) +PKG_CHECK_MODULES([DBUS_G], [dbus-glib-1], , [have_dbus_glib=no]) +AC_PATH_PROG([DBUS_BINDING_TOOL], [dbus-binding-tool]) -if test "X$enable_mozilla_plugin" != "Xno"; then - if test "X$have_mozilla_plugin" = "Xno"; then - AC_MSG_FAILURE([Mozilla plug-in development headers are required to build the Mozilla plug-in.]) - fi - if test "X$have_gtk" = "Xno"; then - AC_MSG_FAILURE([GTK+ is required to build the Mozilla plug-in]) - fi -fi +AS_IF([test "X$enable_mozilla_plugin" != "Xno"], + [AS_IF([test "X$have_mozilla_plugin" = "Xno"], + [AC_MSG_FAILURE([Mozilla plug-in development headers are required to build the Mozilla plug-in.])]) + AS_IF([test "X$have_dbus_glib" = "Xno"], + [AC_MSG_FAILURE([The D-Bus GLib binding is required to build the Mozilla plug-in])])]) AM_CONDITIONAL([ENABLE_MOZILLA_PLUGIN], - [test "X$enable_mozilla_plugin" != "Xno" -a "X$have_gtk" != "Xno"]) + [test "X$enable_mozilla_plugin" != "Xno" -a "X$have_dbus_glib" != "Xno"]) AC_OUTPUT Modified: trunk/mozilla-plugin/src/Makefile.am =================================================================== --- trunk/mozilla-plugin/src/Makefile.am 2008-09-06 03:01:00 UTC (rev 3581) +++ trunk/mozilla-plugin/src/Makefile.am 2008-09-06 04:06:52 UTC (rev 3582) @@ -1,17 +1,28 @@ AM_CPPFLAGS = \ -DGTK_DISABLE_DEPRECATED \ -DOPENVRML_LIBEXECDIR_=\"$(libexecdir)\" -AM_CXXFLAGS = $(MOZILLA_PLUGIN_CFLAGS) $(GTK_CFLAGS) +AM_CXXFLAGS = $(MOZILLA_PLUGIN_CFLAGS) $(DBUS_G_CFLAGS) mozpluginsdir = $(libdir)/mozilla/plugins if ENABLE_MOZILLA_PLUGIN mozplugins_LTLIBRARIES = openvrml.la +BUILT_SOURCES = browser-host-server-glue.h endif openvrml_la_SOURCES = openvrml.cpp openvrml_la_LDFLAGS = \ -module -avoid-version \ - $(MOZILLA_PLUGIN_LIBS) + $(MOZILLA_PLUGIN_LIBS) \ + $(DBUS_G_LIBS) +browser-host-server-glue.h: $(top_srcdir)/../src/openvrml-xembed/browser-host.xml + $(LIBTOOL) --mode=execute $(DBUS_BINDING_TOOL) \ + --prefix=openvrml_np_browser_host \ + --mode=glib-server \ + --output=$@ \ + $? + EXTRA_DIST = $(openvrml_la_SOURCES) + +CLEANFILES = $(BUILT_SOURCES) Modified: trunk/mozilla-plugin/src/openvrml.cpp =================================================================== --- trunk/mozilla-plugin/src/openvrml.cpp 2008-09-06 03:01:00 UTC (rev 3581) +++ trunk/mozilla-plugin/src/openvrml.cpp 2008-09-06 04:06:52 UTC (rev 3582) @@ -2,7 +2,7 @@ // // OpenVRML Mozilla plug-in // -// Copyright 2004, 2005, 2006, 2007 Braden McDaniel +// Copyright 2004, 2005, 2006, 2007, 2008 Braden 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 @@ -33,21 +33,50 @@ # include <boost/scoped_ptr.hpp> # include <npupp.h> # if defined MOZ_X11 -# include <fcntl.h> -# include <gdk/gdkx.h> +# include <dbus/dbus-glib-bindings.h> # else # error Unsupported toolkit. # endif +# define OPENVRML_NP_TYPE_BROWSER_HOST (openvrml_np_browser_host_get_type()) +# define OPENVRML_NP_BROWSER_HOST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), OPENVRML_NP_TYPE_BROWSER_HOST, OpenvrmlNpBrowserHost)) +# define OPENVRML_NP_BROWSER_HOST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), OPENVRML_NP_TYPE_BROWSER_HOST, OpenvrmlNpBrowserHostClass)) + +G_BEGIN_DECLS + +typedef struct OpenvrmlNpBrowserHost_ OpenvrmlNpBrowserHost; +typedef struct OpenvrmlNpBrowserHostClass_ OpenvrmlNpBrowserHostClass; + +struct OpenvrmlNpBrowserHost_ { + GObject parent; + gchar * path; + NPP npp; +}; + +struct OpenvrmlNpBrowserHostClass_ { + GObjectClass parent; + DBusGConnection * connection; + gchar * host_name; +}; + +GType openvrml_np_browser_host_get_type(); + +int +openvrml_np_browser_host_get_url(OpenvrmlNpBrowserHost * host, const char * url, + GError ** error); +void openvrml_np_browser_host_set_world_url(OpenvrmlNpBrowserHost * host, + const char * url, GError ** error); + +G_END_DECLS + +# include "browser-host-server-glue.h" + using namespace boost::multi_index::detail; // for scope_guard namespace { void printerr(const char * str); - extern "C" gboolean request_data_available(GIOChannel * source, - GIOCondition condition, - gpointer data); class plugin_instance; typedef bool (plugin_instance::*script_callback_t)(const NPVariant *, @@ -71,18 +100,12 @@ class plugin_instance : boost::noncopyable { - friend gboolean request_data_available(GIOChannel * source, - GIOCondition condition, - gpointer data); - const NPP npp; - GdkNativeWindow window; + void * window; int x, y; int width, height; - GIOChannel * command_channel; - GIOChannel * request_channel; - guint request_channel_watch_id; - std::stringstream request_line; + OpenvrmlNpBrowserHost * browser_host; + DBusGProxy * browser; public: NPObject * const npobj; @@ -93,8 +116,11 @@ void set_window(NPWindow & window) throw (std::bad_alloc, std::runtime_error); void HandleEvent(void * event) throw (); - ssize_t write_command(const std::string & command); + NPError new_stream(NPMIMEType type, NPStream * stream); + NPError destroy_stream(NPStream * stream); + int32 write(NPStream * stream, int32 len, void * buffer); + // // Scripting API method implementations. // @@ -105,6 +131,87 @@ }; } // namespace +G_DEFINE_TYPE(OpenvrmlNpBrowserHost, openvrml_np_browser_host, G_TYPE_OBJECT) + +void openvrml_np_browser_host_init(OpenvrmlNpBrowserHost * const host) +{ + static size_t count = 0; + host->path = g_strdup_printf("/org/openvrml/BrowserHost/%u/%lu", + getpid(), count++); + dbus_g_connection_register_g_object( + OPENVRML_NP_BROWSER_HOST_GET_CLASS(host)->connection, + host->path, + G_OBJECT(host)); +} + +namespace { + enum np_host_signal_id { + shutdown_id, + last_signal_id + }; + + G_GNUC_INTERNAL guint signals[last_signal_id]; +} + +void openvrml_np_browser_host_class_init(OpenvrmlNpBrowserHostClass * klass) +{ + signals[shutdown_id] = + g_signal_new("shutdown", + G_OBJECT_CLASS_TYPE(klass), + GSignalFlags(G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED), + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + GError * error = 0; + scope_guard error_guard = make_guard(g_error_free, boost::ref(error)); + klass->connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); + if (!klass->connection) { + g_critical("Failed to open connection to bus: %s", error->message); + return; + } + + klass->host_name = g_strdup_printf("org.openvrml.BrowserHost-%u", + getpid()); + + DBusGProxy * driver_proxy = + dbus_g_proxy_new_for_name(klass->connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS); + scope_guard driver_proxy_guard = make_guard(g_object_unref, driver_proxy); + boost::ignore_unused_variable_warning(driver_proxy_guard); + + guint request_ret; + if (!org_freedesktop_DBus_request_name(driver_proxy, + klass->host_name, + 0, &request_ret, + &error)) { + g_critical("Request for name \"%s\" failed: %s", + klass->host_name, error->message); + return; + } + + dbus_g_object_type_install_info( + OPENVRML_NP_TYPE_BROWSER_HOST, + &dbus_glib_openvrml_np_browser_host_object_info); + error_guard.dismiss(); +} + +int openvrml_np_browser_host_get_url(OpenvrmlNpBrowserHost * const host, + const char * const url, + GError ** /* error */) +{ + return NPN_GetURL(host->npp, url, 0); +} + +void openvrml_np_browser_host_set_world_url(OpenvrmlNpBrowserHost * /* host */, + const char * /* url */, + GError ** /* error */) +{ +} + char * NP_GetMIMEDescription() { return NPP_GetMIMEDescription(); @@ -279,9 +386,11 @@ char * NPP_GetMIMEDescription() { - return "model/x3d+vrml:x3dv:X3D world;" - "model/vrml:wrl:VRML world;" - "x-world/x-vrml:wrl:VRML world"; + static const char mimeDescription[] = + "model/x3d+vrml:x3dv:X3D world;" + "model/vrml:wrl:VRML world;" + "x-world/x-vrml:wrl:VRML world"; + return const_cast<char *>(&mimeDescription[0]); } NPError NPP_Initialize() @@ -431,20 +540,14 @@ NPBool /* seekable */, uint16 * const stype) { - if (!instance) { return NPERR_INVALID_INSTANCE_ERROR; } + if (!instance || !instance->pdata) { return NPERR_INVALID_INSTANCE_ERROR; } + *stype = NP_NORMAL; - assert(instance->pdata); plugin_instance & pluginInstance = *static_cast<plugin_instance *>(instance->pdata); - std::ostringstream command; - command << "new-stream " << size_t(stream) << ' ' << type << ' ' - << stream->url << '\n'; - const ssize_t bytes_written = pluginInstance.write_command(command.str()); - return (bytes_written < 0) - ? NPERR_GENERIC_ERROR - : NPERR_NO_ERROR; + return pluginInstance.new_stream(type, stream); } NPError NPP_DestroyStream(const NPP instance, @@ -456,12 +559,7 @@ plugin_instance & pluginInstance = *static_cast<plugin_instance *>(instance->pdata); - std::ostringstream command; - command << "destroy-stream " << size_t(stream) << '\n'; - const ssize_t bytes_written = pluginInstance.write_command(command.str()); - return (bytes_written < 0) - ? NPERR_GENERIC_ERROR - : NPERR_NO_ERROR; + return pluginInstance.destroy_stream(stream); } /* PLUGIN DEVELOPERS: @@ -499,14 +597,7 @@ plugin_instance & pluginInstance = *static_cast<plugin_instance *>(instance->pdata); - std::ostringstream command; - command << "write " << size_t(stream) << ' ' << ' ' << len << '\n'; - for (int32 i = 0; i < len; ++i) { - command.put(static_cast<char *>(buffer)[i]); - } - const ssize_t bytes_written = pluginInstance.write_command(command.str()); - - return bytes_written; // The number of bytes accepted. + return pluginInstance.write(stream, len, buffer); } void NPP_StreamAsFile(const NPP instance, @@ -1043,55 +1134,62 @@ y(0), width(0), height(0), - command_channel(0), - request_channel(0), - request_channel_watch_id(0), + browser_host( + OPENVRML_NP_BROWSER_HOST( + g_object_new(OPENVRML_NP_TYPE_BROWSER_HOST, 0))), + browser(0), npobj(NPN_CreateObject(this->npp, &npclass)) { + if (!this->browser_host) { throw std::bad_alloc(); } if (!this->npobj) { throw std::bad_alloc(); } + + browser_host->npp = npp; } plugin_instance::~plugin_instance() throw () { - if (this->request_channel_watch_id) { - const gboolean succeeded = - g_source_remove(this->request_channel_watch_id); - g_assert(succeeded); - } + NPN_ReleaseObject(this->npobj); + g_signal_emit(this->browser_host, signals[shutdown_id], 0); + } - if (this->request_channel) { - GError * error = 0; - const gboolean flush = false; - GIOStatus status = g_io_channel_shutdown(this->request_channel, - flush, - &error); - if (status != G_IO_STATUS_NORMAL) { - if (error) { - printerr(error->message); - g_error_free(error); - } - } + DBusGProxy * get_browser(DBusGConnection * const connection, + const char * const host_name, + const char * const host_path, + const guint64 host_id, + GError ** const error) + throw () + { + DBusGProxy * browser_factory = + dbus_g_proxy_new_for_name_owner(connection, + "org.openvrml.BrowserControl", + "/BrowserFactory", + "org.openvrml.BrowserFactory", + error); + g_return_val_if_fail(browser_factory, 0); + scope_guard browser_factory_guard = + make_guard(g_object_unref, G_OBJECT(browser_factory)); + boost::ignore_unused_variable_warning(browser_factory_guard); - g_io_channel_unref(this->request_channel); + char * browser_path = 0; + if (!dbus_g_proxy_call(browser_factory, + "CreateControl", + error, + G_TYPE_STRING, host_name, + DBUS_TYPE_G_OBJECT_PATH, host_path, + G_TYPE_UINT64, host_id, + G_TYPE_BOOLEAN, true, + G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &browser_path, + G_TYPE_INVALID)) { + return 0; } - if (this->command_channel) { - GError * error = 0; - const gboolean flush = false; - GIOStatus status = g_io_channel_shutdown(this->command_channel, - flush, - &error); - if (status != G_IO_STATUS_NORMAL) { - if (error) { - printerr(error->message); - g_error_free(error); - } - } - - g_io_channel_unref(this->command_channel); - } - - NPN_ReleaseObject(this->npobj); + DBusGProxy * browser = + dbus_g_proxy_new_for_name(connection, + "org.openvrml.BrowserControl", + browser_path, + "org.openvrml.Browser"); + return browser; } void plugin_instance::set_window(NPWindow & window) @@ -1100,7 +1198,7 @@ assert(window.window); if (this->window) { // - // The plug-in window is unchanged. Resize the window and exit. + // The plug-in window is unchanged. Resize the window and exit. // return; } @@ -1110,171 +1208,91 @@ using boost::lexical_cast; using boost::ref; - this->window = GdkNativeWindow(ptrdiff_t(window.window)); + this->window = window.window; - // - // The OPENVRML_XEMBED environment variable overrides the default path - // to the child process executable. To allow OPENVRML_XEMBED to - // include arguments (rather than just be a path to an executable), it - // is parsed with g_shell_parse_argv. This is particularly useful in - // case we want to run the child process in a harness like valgrind. - // - gint openvrml_xembed_cmd_argc = 0; - gchar ** openvrml_xembed_cmd_argv = 0; - scope_guard openvrml_xembed_cmd_argv_guard = - make_guard(g_strfreev, ref(openvrml_xembed_cmd_argv)); - boost::ignore_unused_variable_warning(openvrml_xembed_cmd_argv_guard); - const gchar * const openvrml_xembed_cmd = - g_getenv("OPENVRML_XEMBED"); - if (!openvrml_xembed_cmd) { - openvrml_xembed_cmd_argc = 1; - openvrml_xembed_cmd_argv = - static_cast<gchar **>(g_malloc0(sizeof (gchar *) * 2)); - if (!openvrml_xembed_cmd_argv) { throw std::bad_alloc(); } - openvrml_xembed_cmd_argv[0] = - g_strdup(OPENVRML_LIBEXECDIR_ "/openvrml-xembed"); - if (!openvrml_xembed_cmd_argv[0]) { throw std::bad_alloc(); } - } else { - GError * error = 0; - scope_guard error_guard = make_guard(g_error_free, ref(error)); - gboolean succeeded = - g_shell_parse_argv(openvrml_xembed_cmd, - &openvrml_xembed_cmd_argc, - &openvrml_xembed_cmd_argv, - &error); - if (!succeeded) { - throw std::runtime_error(error - ? error->message - : "g_shell_parse_argv failure"); - } - error_guard.dismiss(); - } + OpenvrmlNpBrowserHostClass * const browser_host_class = + OPENVRML_NP_BROWSER_HOST_GET_CLASS(this->browser_host); - static const char initial_stream_arg_c_str[] = "--initial-stream"; - static const size_t initial_stream_arg_c_str_size = - sizeof initial_stream_arg_c_str / sizeof (gchar); - vector<gchar> initial_stream_arg_vec( - initial_stream_arg_c_str, - initial_stream_arg_c_str + initial_stream_arg_c_str_size); + GError * error = 0; + scope_guard error_guard = make_guard(g_error_free, boost::ref(error)); - const string socket_id_arg = lexical_cast<string>(this->window); - const char * const socket_id_arg_c_str = socket_id_arg.c_str(); - vector<gchar> socket_id_arg_vec( - socket_id_arg_c_str, - socket_id_arg_c_str + socket_id_arg.length() + 1); - - const gint argv_size = openvrml_xembed_cmd_argc + 3; - gchar ** const argv = - static_cast<gchar **>(g_malloc(sizeof (gchar *) * argv_size)); - if (!argv) { throw std::bad_alloc(); } - scope_guard argv_guard = make_guard(g_free, argv); - boost::ignore_unused_variable_warning(argv_guard); - gint i; - for (i = 0; i < openvrml_xembed_cmd_argc; ++i) { - argv[i] = openvrml_xembed_cmd_argv[i]; + this->browser = get_browser(browser_host_class->connection, + browser_host_class->host_name, + this->browser_host->path, + guint64(this->window), + &error); + if (!this->browser) { + g_critical("Browser creation failed: %s", error->message); + return; } - argv[i++] = &initial_stream_arg_vec.front(); - argv[i++] = &socket_id_arg_vec.front(); - argv[i] = 0; - gchar * const working_dir = g_get_current_dir(); - if (!working_dir) { throw std::bad_alloc(); }; - scope_guard working_dir_guard = make_guard(g_free, working_dir); - boost::ignore_unused_variable_warning(working_dir_guard); + error_guard.dismiss(); + } - gchar ** envp = 0; - GPid * const child_pid = 0; - gint standard_input, standard_output; - gint * const standard_error = 0; + NPError plugin_instance::new_stream(const NPMIMEType type, + NPStream * const stream) + { + if (!this->browser) { return NPERR_INVALID_INSTANCE_ERROR; } + GError * error = 0; - scope_guard error_guard = make_guard(g_error_free, ref(error)); - gboolean succeeded = g_spawn_async_with_pipes(working_dir, - argv, - envp, - GSpawnFlags(0), - 0, - 0, - child_pid, - &standard_input, - &standard_output, - standard_error, - &error); - if (!succeeded) { - throw std::runtime_error(error - ? error->message - : "g_spawn_async_with_pipes failure"); + scope_guard error_guard = make_guard(g_error_free, boost::ref(error)); + gboolean result = dbus_g_proxy_call(this->browser, + "NewStream", + &error, + G_TYPE_UINT64, stream, + G_TYPE_STRING, type, + G_TYPE_STRING, stream->url, + G_TYPE_INVALID, + G_TYPE_INVALID); + if (!result) { + g_critical("Call to org.openvrml.Browser.NewStream failed: %s", + error->message); + return NPERR_GENERIC_ERROR; } - - // - // Don't dismiss "error_guard" yet; we reuse "error" below. - // - - this->command_channel = g_io_channel_unix_new(standard_input); - if (!this->command_channel) { throw std::bad_alloc(); } - const GIOStatus status = - g_io_channel_set_encoding(this->command_channel, - 0, // binary (no encoding) - &error); - if (status != G_IO_STATUS_NORMAL) { - throw std::runtime_error(error - ? error->message - : "g_io_channel_set_encoding failure"); - } error_guard.dismiss(); - - this->request_channel = g_io_channel_unix_new(standard_output); - if (!this->request_channel) { throw std::bad_alloc(); } - this->request_channel_watch_id = - g_io_add_watch(this->request_channel, - G_IO_IN, - request_data_available, - this); + return NPERR_NO_ERROR; } - void plugin_instance::HandleEvent(void *) throw () - {} - - ssize_t plugin_instance::write_command(const std::string & command) + NPError plugin_instance::destroy_stream(NPStream * const stream) { - if (!this->command_channel) { return 0; } + if (!this->browser) { return NPERR_INVALID_INSTANCE_ERROR; } - gsize bytes_written; - GError * error = 0; - GIOStatus status = g_io_channel_write_chars(this->command_channel, - command.data(), - command.length(), - &bytes_written, - &error); - if (status != G_IO_STATUS_NORMAL) { - if (error) { - printerr(error->message); - g_error_free(error); - } - return -1; - } + dbus_g_proxy_call_no_reply(this->browser, + "DestroyStream", + G_TYPE_UINT64, stream, + G_TYPE_INVALID); + return NPERR_NO_ERROR; + } - do { - status = g_io_channel_flush(this->command_channel, &error); - } while (status == G_IO_STATUS_AGAIN); + int32 plugin_instance::write(NPStream * const stream, + const int32 len, + void * const buffer) + { + if (!this->browser) { return 0; } - if (status != G_IO_STATUS_NORMAL) { - if (error) { - printerr(error->message); - g_error_free(error); - } - return -1; - } + GArray array = {}; + array.data = static_cast<char *>(buffer); + array.len = len; - return bytes_written; + dbus_g_proxy_call_no_reply(this->browser, + "Write", + G_TYPE_UINT64, stream, + DBUS_TYPE_G_UCHAR_ARRAY, &array, + G_TYPE_INVALID); + return len; } + void plugin_instance::HandleEvent(void *) throw () + {} + bool plugin_instance::get_name(const NPVariant * const /* args */, const uint32_t /* argCount */, NPVariant * const result) { static const std::string name = PACKAGE_NAME; NPUTF8 * const name_str = - static_cast<NPUTF8 *>(NPN_MemAlloc(sizeof (NPUTF8) * name.length())); + static_cast<NPUTF8 *>( + NPN_MemAlloc(sizeof (NPUTF8) * name.length())); std::copy(name.begin(), name.end(), name_str); STRINGN_TO_NPVARIANT(name_str, name.length(), *result); return true; @@ -1291,64 +1309,4 @@ STRINGN_TO_NPVARIANT(ver_str, ver.length(), *result); return true; } - - gboolean request_data_available(GIOChannel * const source, - GIOCondition, - const gpointer data) - { - using std::string; - - plugin_instance & pluginInstance = - *static_cast<plugin_instance *>(data); - - gchar c; - do { - gsize bytes_read; - GError * error = 0; - const GIOStatus status = - g_io_channel_read_chars(source, &c, 1, &bytes_read, &error); - if (status == G_IO_STATUS_ERROR) { - if (error) { - g_warning(error->message); - g_error_free(error); - } - return false; - } - if (status == G_IO_STATUS_EOF) { return false; } - if (status == G_IO_STATUS_AGAIN) { continue; } - g_return_val_if_fail(status == G_IO_STATUS_NORMAL, false); - - g_assert(bytes_read == 1); - - if (c != '\n') { pluginInstance.request_line.put(c); } - - } while (g_io_channel_get_buffer_condition(source) & G_IO_IN - && c != '\n'); - - if (c == '\n') { - string request_type; - pluginInstance.request_line >> request_type; - if (request_type == "get-url") { - string url, target; - pluginInstance.request_line >> url >> target; - const NPError result = - NPN_GetURL(pluginInstance.npp, - url.c_str(), - target.empty() ? 0 : target.c_str()); - std::ostringstream command; - command << "get-url-result " << url << ' ' << result << '\n'; - const ssize_t bytes_written = - pluginInstance.write_command(command.str()); - if (bytes_written != ssize_t(command.str().length())) { - // XXX - // XXX Do what here? Console message? - // XXX - } - } - pluginInstance.request_line.str(string()); - pluginInstance.request_line.clear(); - } - - return true; - } } // namespace Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2008-09-06 03:01:00 UTC (rev 3581) +++ trunk/src/Makefile.am 2008-09-06 04:06:52 UTC (rev 3582) @@ -7,6 +7,7 @@ if ENABLE_XEMBED libexec_PROGRAMS = openvrml-xembed/openvrml-xembed +session_bus_services_DATA = openvrml-xembed/org.openvrml.BrowserControl.service endif if ENABLE_PLAYER @@ -67,10 +68,7 @@ noinst_HEADERS = \ libopenvrml/private.h \ openvrml-xembed/bounded_buffer.h \ - openvrml-xembed/command_istream.h \ openvrml-xembed/plugin_streambuf.h \ - openvrml-xembed/request_channel.h \ - openvrml-xembed/gtkvrmlbrowser.h \ openvrml-player/filechooserdialog.h LIBOPENVRML_LIBRARY_VERSION = 8:6:0 @@ -323,6 +321,7 @@ libopenvrml_gl_libopenvrml_gl_la_LIBADD = libopenvrml/libopenvrml.la openvrml_xembed_openvrml_xembed_CPPFLAGS = \ + -I$(top_builddir)/src/openvrml-xembed \ -I$(top_srcdir)/lib/gtkglext \ -I$(top_builddir)/lib/gtkglext \ -I$(top_builddir)/lib/gtkglext/gdk \ @@ -334,14 +333,20 @@ -DGTK_DISABLE_DEPRECATED openvrml_xembed_openvrml_xembed_CXXFLAGS = \ $(PTHREAD_CFLAGS) \ + $(DBUS_G_CFLAGS) \ $(GTK_CFLAGS) \ $(GL_CFLAGS) openvrml_xembed_openvrml_xembed_SOURCES = \ openvrml-xembed/main.cpp \ - openvrml-xembed/command_istream.cpp \ + openvrml-xembed/browserfactory.cpp \ + openvrml-xembed/browserfactory.h \ openvrml-xembed/plugin_streambuf.cpp \ - openvrml-xembed/gtkvrmlbrowser.cpp + openvrml-xembed/browser.cpp \ + openvrml-xembed/browser.h \ + openvrml-xembed/streamclient.cpp \ + openvrml-xembed/streamclient.h openvrml_xembed_openvrml_xembed_LDFLAGS = \ + $(DBUS_G_LIBS) \ $(GTK_LIBS) \ $(GL_LIBS) openvrml_xembed_openvrml_xembed_LDADD = \ @@ -349,21 +354,49 @@ $(top_builddir)/lib/gtkglext/gtk/libgtkglext-x11-1.0.la \ $(top_builddir)/lib/gtkglext/gdk/libgdkglext-x11-1.0.la +openvrml_xembed_datadir = $(datadir)/openvrml-xembed +openvrml_xembed_dbusdir = $(openvrml_xembed_datadir)/dbus-1 +dist_openvrml_xembed_dbus_DATA = \ + openvrml-xembed/browser.xml \ + openvrml-xembed/browser-factory.xml \ + openvrml-xembed/browser-host.xml +BUILT_SOURCES = \ + openvrml-xembed/browser-server-glue.h \ + openvrml-xembed/browser-factory-server-glue.h \ + openvrml-player/browser-host-server-glue.h + +openvrml-xembed/browser-server-glue.h: $(srcdir)/openvrml-xembed/browser.xml + $(LIBTOOL) --mode=execute $(DBUS_BINDING_TOOL) \ + --prefix=openvrml_xembed_browser \ + --mode=glib-server \ + --output=$@ \ + $? + +openvrml-xembed/browser-factory-server-glue.h: $(srcdir)/openvrml-xembed/browser-factory.xml + $(LIBTOOL) --mode=execute $(DBUS_BINDING_TOOL) \ + --prefix=openvrml_xembed_browser_factory \ + --mode=glib-server \ + --output=$@ \ + $? + openvrml_player_openvrml_player_CPPFLAGS = \ -DG_DISABLE_DEPRECATED \ -DGTK_DISABLE_DEPRECATED \ -DGNOME_DISABLE_DEPRECATED \ -DOPENVRML_PLAYER_PKGDATADIR_=\"$(datadir)/openvrml-player\" \ -DOPENVRML_LIBEXECDIR_=\"$(libexecdir)\" \ + -I$(builddir)/openvrml-player \ -I$(builddir)/libopenvrml \ -I$(srcdir)/libopenvrml openvrml_player_openvrml_player_CXXFLAGS = \ + $(DBUS_G_CFLAGS) \ $(GNOMEUI_CFLAGS) \ $(CURL_CFLAGS) openvrml_player_openvrml_player_LDFLAGS = \ -export-dynamic \ $(GNOMEUI_LIBS) \ + $(DBUS_G_LIBS) \ $(CURL_LIBS) openvrml_player_uidir = $(datadir)/openvrml-player/ui @@ -371,15 +404,30 @@ openvrml_player_openvrml_player_SOURCES = \ openvrml-player/filechooserdialog.cpp \ - openvrml-player/player.cpp + openvrml-player/player.cpp \ + openvrml-player/curlbrowserhost.cpp \ + openvrml-player/curlbrowserhost.h +openvrml-player/browser-host-server-glue.h: $(srcdir)/openvrml-xembed/browser-host.xml + $(LIBTOOL) --mode=execute $(DBUS_BINDING_TOOL) \ + --prefix=openvrml_player_curl_browser_host \ + --mode=glib-server \ + --output=$@ \ + $? EXTRA_DIST = \ libopenvrml/openvrml-config.h.in \ - libopenvrml-gl/openvrml-gl-config.h.in + libopenvrml-gl/openvrml-gl-config.h.in \ + openvrml-xembed/org.openvrml.BrowserControl.service.in # # Automake 1.10 seems to need this for distcheck to work. # CLEANFILES = \ + $(BUILT_SOURCES) \ openvrml-xembed/.libs/openvrml-xembed + +DISTCLEANFILES = \ + libopenvrml/openvrml-config.h \ + libopenvrml-gl/openvrml-gl-config.h \ + $(session_bus_services_DATA) Copied: trunk/src/openvrml-player/curlbrowserhost.cpp (from rev 3577, branches/dbus/src/openvrml-player/curlbrowserhost.cpp) =================================================================== --- trunk/src/openvrml-player/curlbrowserhost.cpp (rev 0) +++ trunk/src/openvrml-player/curlbrowserhost.cpp 2008-09-06 04:06:52 UTC (rev 3582) @@ -0,0 +1,925 @@ +// -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 78 -*- +// +// OpenVRML Player +// Copyright 2008 Braden 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 "curlbrowserhost.h" +# include <curl/curl.h> +# include <libgnomevfs/gnome-vfs.h> +# include <browser-host-server-glue.h> +# include <dbus/dbus-glib-bindings.h> +# include <dbus/dbus-protocol.h> +# include <boost/concept_check.hpp> +# include <boost/multi_index/detail/scope_guard.hpp> +# include <boost/ref.hpp> +# include <list> +# include <vector> +# include <string.h> + +using namespace boost::multi_index::detail; // for scope_guard + +G_DEFINE_TYPE(OpenvrmlPlayerCurlBrowserHost, + openvrml_player_curl_browser_host, + GTK_TYPE_SOCKET) + +namespace { + G_GNUC_INTERNAL + DBusGProxy * get_browser(DBusGConnection * connection, + const char * host_name, + const char * host_path, + guint64 host_id, + GError ** error) + throw (); + + G_GNUC_INTERNAL GSource * curl_source_new(CURLM * multi_handle) + throw (std::bad_alloc); +} + +extern "C" { + G_GNUC_INTERNAL + void + openvrml_player_curl_browser_host_get_property(GObject * obj, + guint property_id, + GValue * value, + GParamSpec * pspec); + G_GNUC_INTERNAL + void openvrml_player_curl_browser_host_realize(GtkWidget * widget); + G_GNUC_INTERNAL + void openvrml_player_curl_browser_host_unrealize(GtkWidget * widget); + G_GNUC_INTERNAL + void openvrml_player_curl_browser_host_finalize(GObject * obj); + + + G_GNUC_INTERNAL + void + openvrml_player_curl_browser_host_delete_curl_stream_data( + void * stream_data); + G_GNUC_INTERNAL + gboolean + openvrml_player_curl_browser_host_curl_source_callback(gpointer data); +} + +struct OpenvrmlPlayerCurlBrowserHostPrivate_ { + gchar * path; + DBusGProxy * browser; + CURLM * multi_handle; + GSource * curl_source; + GHashTable * stream_data; +}; + +# define OPENVRML_PLAYER_CURL_BROWSER_HOST_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), OPENVRML_PLAYER_TYPE_CURL_BROWSER_HOST, OpenvrmlPlayerCurlBrowserHostPrivate)) + +void +openvrml_player_curl_browser_host_init( + OpenvrmlPlayerCurlBrowserHost * const browser_host) +{ + browser_host->priv = + OPENVRML_PLAYER_CURL_BROWSER_HOST_GET_PRIVATE(browser_host); + + static size_t count = 0; + browser_host->priv->path = + g_strdup_printf("/org/openvrml/BrowserHost/%u/%lu", + getpid(), count++); + dbus_g_connection_register_g_object( + OPENVRML_PLAYER_CURL_BROWSER_HOST_GET_CLASS(browser_host)->connection, + browser_host->priv->path, + G_OBJECT(browser_host)); +} + +namespace { + enum curl_browser_host_property_id { + object_path_id = 1 + }; + + enum curl_browser_host_signal_id { + shutdown_id, + last_signal_id + }; + + G_GNUC_INTERNAL guint signals[last_signal_id]; +} + +void +openvrml_player_curl_browser_host_class_init( + OpenvrmlPlayerCurlBrowserHostClass * klass) +{ + G_OBJECT_CLASS(klass)->get_property = + openvrml_player_curl_browser_host_get_property; + G_OBJECT_CLASS(klass)->finalize = + openvrml_player_curl_browser_host_finalize; + GTK_WIDGET_CLASS(klass)->realize = + openvrml_player_curl_browser_host_realize; + GTK_WIDGET_CLASS(klass)->unrealize = + openvrml_player_curl_browser_host_unrealize; + + signals[shutdown_id] = + g_signal_new("shutdown", + G_OBJECT_CLASS_TYPE(klass), + GSignalFlags(G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED), + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + GError * error = 0; + scope_guard error_guard = make_guard(g_error_free, boost::ref(error)); + klass->connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); + if (!klass->connection) { + g_critical("Failed to open connection to bus: %s", error->message); + return; + } + + klass->host_name = g_strdup_printf("org.openvrml.BrowserHost-%u", + getpid()); + + DBusGProxy * driver_proxy = + dbus_g_proxy_new_for_name(klass->connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS); + scope_guard driver_proxy_guard = make_guard(g_object_unref, driver_proxy); + boost::ignore_unused_variable_warning(driver_proxy_guard); + + guint request_ret; + if (!org_freedesktop_DBus_request_name(driver_proxy, + klass->host_name, + 0, &request_ret, + &error)) { + g_critical("Request for name \"%s\" failed: %s", + klass->host_name, error->message); + return; + } + + GParamSpec * pspec = + g_param_spec_pointer("object-path", + "object path", + "D-Bus object path", + G_PARAM_READABLE); + g_object_class_install_property(G_OBJECT_CLASS(klass), + object_path_id, + pspec); + + g_type_class_add_private(G_OBJECT_CLASS(klass), + sizeof (OpenvrmlPlayerCurlBrowserHostPrivate)); + + dbus_g_object_type_install_info( + OPENVRML_PLAYER_TYPE_CURL_BROWSER_HOST, + &dbus_glib_openvrml_player_curl_browser_host_object_info); + error_guard.dismiss(); +} + +void openvrml_player_curl_browser_host_get_property(GObject * const obj, + const guint property_id, + GValue * const value, + GParamSpec * const pspec) +{ + OpenvrmlPlayerCurlBrowserHost * host = + OPENVRML_PLAYER_CURL_BROWSER_HOST(obj); + switch (property_id) { + case object_path_id: + g_value_set_string(value, host->priv->path); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec); + } +} + +namespace { + + class G_GNUC_INTERNAL curl_stream_data { + CURL * const handle_; + std::vector<char> url_; + DBusGProxy * browser_; + bool initialized_; + + public: + curl_stream_data(CURL * handle, const char * url, DBusGProxy * browser); + + CURL * handle() const; + const char * url() const; + DBusGProxy * browser() const; + void initialize(); + bool initialized() const; + }; +} + +void +openvrml_player_curl_browser_host_delete_curl_stream_data(void * stream_data) +{ + delete static_cast<curl_stream_data *>(stream_data); +} + +void openvrml_player_curl_browser_host_realize(GtkWidget * const widget) +{ + g_return_if_fail(widget); + g_return_if_fail(OPENVRML_PLAYER_IS_CURL_BROWSER_HOST(widget)); + + GtkWidgetClass * klass = + GTK_WIDGET_CLASS( + g_type_... [truncated message content] |