Update of /cvsroot/openvrml/openvrml/mozilla-plugin/src/openvrml-player In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19538/mozilla-plugin/src/openvrml-player Modified Files: Makefile.am player.cpp Added Files: gtkvrmlbrowser.cpp gtkvrmlbrowser.h Removed Files: browser.cpp browser.h gtkglviewer.cpp gtkglviewer.h Log Message: Refactored code into custom Gtk+ widget. --- NEW FILE: gtkvrmlbrowser.cpp --- // -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4; -*- // // OpenVRML Mozilla plug-in // Copyright 2004, 2005, 2006 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 2 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 program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // # include <iostream> # include <sstream> // Must include before X11 headers. # include <boost/numeric/conversion/converter.hpp> # include <X11/keysym.h> # include <gdk/gdkx.h> # include <openvrml/browser.h> # include <openvrml/gl/viewer.h> # include "gtkvrmlbrowser.h" # include "plugin_streambuf.h" extern "C" { void gtk_vrml_browser_class_init(GtkVrmlBrowserClass * klass); void gtk_vrml_browser_init(GtkVrmlBrowser * vrml_browser); G_GNUC_INTERNAL gboolean gtk_vrml_browser_destroy(GtkWidget * widget, GdkEvent * event, gpointer data); G_GNUC_INTERNAL gboolean gtk_vrml_browser_realize(GtkWidget * widget, GdkEvent * event, gpointer data); G_GNUC_INTERNAL gboolean gtk_vrml_browser_expose_event(GtkWidget * widget, GdkEventExpose * event, gpointer data); G_GNUC_INTERNAL gboolean gtk_vrml_browser_configure_event(GtkWidget * widget, GdkEventConfigure * event, gpointer data); G_GNUC_INTERNAL gboolean gtk_vrml_browser_key_press_event(GtkWidget * widget, GdkEventKey * event, gpointer data); G_GNUC_INTERNAL gboolean gtk_vrml_browser_button_press_event(GtkWidget * widget, GdkEventButton * event, gpointer data); G_GNUC_INTERNAL gboolean gtk_vrml_browser_button_release_event(GtkWidget * widget, GdkEventButton * event, gpointer data); G_GNUC_INTERNAL gboolean gtk_vrml_browser_motion_notify_event(GtkWidget * widget, GdkEventMotion * event, gpointer data); G_GNUC_INTERNAL gint gtk_vrml_browser_timeout_callback(gpointer ptr); } GType gtk_vrml_browser_get_type() { static GType type = 0; if (!type) { static const GTypeInfo info = { sizeof (GtkVrmlBrowserClass), 0, // base_init 0, // base_finalize reinterpret_cast<GClassInitFunc>(gtk_vrml_browser_class_init), 0, // class_finalize 0, // class_data sizeof (GtkVrmlBrowser), 0, // n_preallocs reinterpret_cast<GInstanceInitFunc>(gtk_vrml_browser_init), 0 // value_table }; type = g_type_register_static(GTK_TYPE_DRAWING_AREA, "GtkVrmlBrowser", &info, GTypeFlags(0)); } return type; } namespace { G_GNUC_INTERNAL GdkGLConfig * gl_config; class G_GNUC_INTERNAL browser : public openvrml::browser { GIOChannel * request_channel_; public: explicit browser(GIOChannel & request_channel); private: virtual std::auto_ptr<openvrml::resource_istream> do_get_resource(const std::string & uri); }; class G_GNUC_INTERNAL GtkGLViewer : public openvrml::gl::viewer { friend void (::gtk_vrml_browser_load_url)(GtkVrmlBrowser * vrml_browser, const gchar ** url, const gchar ** parameter); friend void (::gtk_vrml_browser_set_world)(GtkVrmlBrowser * vrml_browser, openvrml::resource_istream & in); friend gint (::gtk_vrml_browser_timeout_callback)(gpointer ptr); friend gboolean (::gtk_vrml_browser_expose_event)(GtkWidget *, GdkEventExpose *, gpointer); ::browser browser_; GtkVrmlBrowser & vrml_browser_; guint timer; public: bool redrawNeeded; GtkGLViewer(GIOChannel & request_channel, GtkVrmlBrowser & vrml_browser); virtual ~GtkGLViewer() throw (); void timer_update(); protected: // // Implement pure virtual methods from openvrml::gl::viewer. // virtual void post_redraw(); virtual void set_cursor(openvrml::gl::viewer::cursor_style); virtual void swap_buffers(); virtual void set_timer(double); }; } GtkWidget * gtk_vrml_browser_new(GIOChannel * const request_channel) { GtkVrmlBrowser * const vrml_browser = GTK_VRML_BROWSER(g_object_new(GTK_TYPE_VRML_BROWSER, 0)); try { vrml_browser->viewer = new GtkGLViewer(*request_channel, *vrml_browser); } catch (std::bad_alloc &) { g_return_val_if_reached(0); } static_cast<GtkGLViewer *>(vrml_browser->viewer) ->resize(GTK_WIDGET(vrml_browser)->allocation.width, GTK_WIDGET(vrml_browser)->allocation.height); return GTK_WIDGET(vrml_browser); } void gtk_vrml_browser_load_url(GtkVrmlBrowser * const vrml_browser, const gchar ** url, const gchar ** parameter) { using std::string; using std::vector; GtkGLViewer & viewer = *static_cast<GtkGLViewer *>(vrml_browser->viewer); vector<string> url_vec, param_vec; while (url) { url_vec.push_back(*(url++)); } while (parameter) { param_vec.push_back(*(parameter++)); } viewer.browser_.load_url(url_vec, param_vec); } void gtk_vrml_browser_set_world(GtkVrmlBrowser * vrml_browser, openvrml::resource_istream & in) { GtkGLViewer & viewer = *static_cast<GtkGLViewer *>(vrml_browser->viewer); viewer.browser_.set_world(in); } void gtk_vrml_browser_class_init(GtkVrmlBrowserClass * klass) {} void gtk_vrml_browser_init(GtkVrmlBrowser * const vrml_browser) { vrml_browser->viewer = 0; if (!::gl_config) { static const int attrib_list[] = { // GDK_GL_ALPHA_SIZE, 1, GDK_GL_DOUBLEBUFFER, GDK_GL_DEPTH_SIZE, 1, GDK_GL_RGBA, GDK_GL_RED_SIZE, 1, GDK_GL_ATTRIB_LIST_NONE }; ::gl_config = gdk_gl_config_new(attrib_list); } static GdkGLContext * const share_list = 0; static const gboolean direct = false; static const int render_type = GDK_GL_RGBA_TYPE; gtk_widget_set_gl_capability(GTK_WIDGET(vrml_browser), ::gl_config, share_list, direct, render_type); gtk_widget_add_events(GTK_WIDGET(vrml_browser), GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_POINTER_MOTION_MASK); g_signal_connect(G_OBJECT(vrml_browser), "destroy_event", G_CALLBACK(gtk_vrml_browser_destroy), 0); g_signal_connect(G_OBJECT(vrml_browser), "expose_event", G_CALLBACK(gtk_vrml_browser_expose_event), 0); g_signal_connect(G_OBJECT(vrml_browser), "configure_event", G_CALLBACK(gtk_vrml_browser_configure_event), 0); g_signal_connect(G_OBJECT(vrml_browser), "key_press_event", G_CALLBACK(gtk_vrml_browser_key_press_event), 0); g_signal_connect(G_OBJECT(vrml_browser), "button_press_event", G_CALLBACK(gtk_vrml_browser_button_press_event), 0); g_signal_connect(G_OBJECT(vrml_browser), "button_release_event", G_CALLBACK(gtk_vrml_browser_button_release_event), 0); g_signal_connect(G_OBJECT(vrml_browser), "motion_notify_event", G_CALLBACK(gtk_vrml_browser_motion_notify_event), 0); } gboolean gtk_vrml_browser_destroy(GtkWidget * const widget, GdkEvent *, gpointer) { delete static_cast<GtkGLViewer *>(GTK_VRML_BROWSER(widget)->viewer); return true; } gboolean gtk_vrml_browser_realize(GtkWidget *, GdkEvent *, gpointer) { return true; } gboolean gtk_vrml_browser_expose_event(GtkWidget * const widget, GdkEventExpose * const event, gpointer) { GdkGLDrawable * const gl_drawable = gtk_widget_get_gl_drawable(widget); g_assert(gl_drawable); GdkGLContext * const gl_context = gtk_widget_get_gl_context(widget); g_assert(gl_context); GtkGLViewer & viewer = *static_cast<GtkGLViewer *>(GTK_VRML_BROWSER(widget)->viewer); if (event->count == 0 && gdk_gl_drawable_make_current(gl_drawable, gl_context)) { viewer.redraw(); } viewer.redrawNeeded = false; if (viewer.timer == 0) { viewer.timer_update(); } return true; } gboolean gtk_vrml_browser_configure_event(GtkWidget * const widget, GdkEventConfigure *, gpointer) { GdkGLDrawable * const gl_drawable = gtk_widget_get_gl_drawable(widget); g_assert(gl_drawable); GdkGLContext * const gl_context = gtk_widget_get_gl_context(widget); g_assert(gl_context); if (GTK_VRML_BROWSER(widget)->viewer && gdk_gl_drawable_make_current(gl_drawable, gl_context)) { GtkGLViewer & viewer = *static_cast<GtkGLViewer *>(GTK_VRML_BROWSER(widget)->viewer); viewer.resize(widget->allocation.width, widget->allocation.height); } return true; } gboolean gtk_vrml_browser_key_press_event(GtkWidget * const widget, GdkEventKey * const event, gpointer) { using openvrml::gl::viewer; viewer::event_info info; info.event = viewer::event_key_down; switch (event->keyval) { case XK_Home: info.what = viewer::key_home; break; case XK_Left: info.what = viewer::key_left; break; case XK_Up: info.what = viewer::key_up; break; case XK_Right: info.what = viewer::key_right; break; case XK_Down: info.what = viewer::key_down; break; case XK_Page_Up: info.what = viewer::key_page_up; break; case XK_Page_Down: info.what = viewer::key_page_down; break; default: if (event->length <= 0) { return true; } info.what = event->string[0]; } GdkGLDrawable * const gl_drawable = gtk_widget_get_gl_drawable(widget); g_assert(gl_drawable); GdkGLContext * const gl_context = gtk_widget_get_gl_context(widget); g_assert(gl_context); if (gdk_gl_drawable_make_current(gl_drawable, gl_context)) { GtkGLViewer * const viewer = static_cast<GtkGLViewer *>(GTK_VRML_BROWSER(widget)->viewer); g_assert(viewer); viewer->input(&info); } return true; } gboolean gtk_vrml_browser_button_press_event(GtkWidget * const widget, GdkEventButton * const event, gpointer) { using openvrml::gl::viewer; viewer::event_info info; info.event = viewer::event_mouse_click; switch (event->button) { case Button1: info.what = 0; break; case Button2: info.what = 1; break; case Button3: info.what = 2; break; } info.x = int(event->x); info.y = int(event->y); GdkGLDrawable * const gl_drawable = gtk_widget_get_gl_drawable(widget); g_assert(gl_drawable); GdkGLContext * const gl_context = gtk_widget_get_gl_context(widget); g_assert(gl_context); if (gdk_gl_drawable_make_current(gl_drawable, gl_context)) { GtkGLViewer * const viewer = static_cast<GtkGLViewer *>(GTK_VRML_BROWSER(widget)->viewer); g_assert(viewer); viewer->input(&info); } return true; } gboolean gtk_vrml_browser_button_release_event(GtkWidget * const widget, GdkEventButton * const event, gpointer) { using openvrml::gl::viewer; viewer::event_info info; info.event = viewer::event_mouse_release; switch (event->button) { case Button1: info.what = 0; break; case Button2: info.what = 1; break; case Button3: info.what = 2; break; } info.x = int(event->x); info.y = int(event->y); GdkGLDrawable * const gl_drawable = gtk_widget_get_gl_drawable(widget); g_assert(gl_drawable); GdkGLContext * const gl_context = gtk_widget_get_gl_context(widget); g_assert(gl_context); if (gdk_gl_drawable_make_current(gl_drawable, gl_context)) { GtkGLViewer * const viewer = static_cast<GtkGLViewer *>(GTK_VRML_BROWSER(widget)->viewer); g_assert(viewer); viewer->input(&info); } return true; } gboolean gtk_vrml_browser_motion_notify_event(GtkWidget * const widget, GdkEventMotion * const event, gpointer) { using openvrml::gl::viewer; viewer::event_info info; info.event = viewer::event_mouse_drag; info.what = 0; if (event->state & Button1Mask) { info.what = 0; } else if (event->state & Button2Mask) { info.what = 1; } else if (event->state & Button3Mask) { info.what = 2; } else { info.event = viewer::event_mouse_move; } info.x = int(event->x); info.y = int(event->y); GdkGLDrawable * const gl_drawable = gtk_widget_get_gl_drawable(widget); g_assert(gl_drawable); GdkGLContext * const gl_context = gtk_widget_get_gl_context(widget); g_assert(gl_context); if (gdk_gl_drawable_make_current(gl_drawable, gl_context)) { GtkGLViewer * const viewer = static_cast<GtkGLViewer *>(GTK_VRML_BROWSER(widget)->viewer); g_assert(viewer); viewer->input(&info); } return true; } gint gtk_vrml_browser_timeout_callback(const gpointer ptr) { assert(ptr); GtkGLViewer & viewer = *static_cast<GtkGLViewer *>(ptr); viewer.timer_update(); return false; } namespace { browser::browser(GIOChannel & request_channel): openvrml::browser(std::cout, std::cerr), request_channel_(&request_channel) {} std::auto_ptr<openvrml::resource_istream> browser::do_get_resource(const std::string & uri) { using openvrml_player::plugin_streambuf; class plugin_resource_istream : public openvrml::resource_istream { boost::shared_ptr<plugin_streambuf> streambuf_; GIOChannel * request_channel_; public: plugin_resource_istream(const std::string & uri, GIOChannel * const request_channel): openvrml::resource_istream(0), streambuf_(new plugin_streambuf(uri)), request_channel_(request_channel) { using std::ostringstream; using openvrml_player::uninitialized_plugin_streambuf_map_; this->rdbuf(this->streambuf_.get()); bool succeeded = uninitialized_plugin_streambuf_map_ .insert(uri, this->streambuf_); g_assert(succeeded); ostringstream request; request << "get-url " << uri << '\n'; gsize bytes_written; g_io_channel_write_chars(this->request_channel_, request.str().data(), request.str().length(), &bytes_written, 0); g_io_channel_flush(this->request_channel_, 0); } 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->request_channel_)); } GtkGLViewer::GtkGLViewer(GIOChannel & request_channel, GtkVrmlBrowser & vrml_browser): browser_(request_channel), vrml_browser_(vrml_browser), timer(0), redrawNeeded(false) { this->browser_.viewer(this); } GtkGLViewer::~GtkGLViewer() throw () { if (this->timer) { g_source_remove(timer); } } void GtkGLViewer::post_redraw() { if (!this->redrawNeeded) { this->redrawNeeded = true; gtk_widget_queue_draw(GTK_WIDGET(&this->vrml_browser_)); } } void GtkGLViewer::set_cursor(cursor_style style) { GdkCursor * cursor(0); switch(style) { case cursor_inherit: XDefineCursor(GDK_WINDOW_XDISPLAY( GTK_WIDGET(&this->vrml_browser_)->window), GDK_WINDOW_XWINDOW( GTK_WIDGET(&this->vrml_browser_)->window), None); return; case cursor_info: cursor = gdk_cursor_new(GDK_HAND1); break; case cursor_cycle: cursor = gdk_cursor_new(GDK_EXCHANGE); break; case cursor_up_down: cursor = gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW); break; case cursor_crosshair: cursor = gdk_cursor_new(GDK_CROSSHAIR); break; default: cursor = gdk_cursor_new(GDK_ARROW); } gdk_window_set_cursor(GTK_WIDGET(&this->vrml_browser_)->window, cursor); gdk_cursor_destroy(cursor); } void GtkGLViewer::swap_buffers() { GdkGLDrawable * const gl_drawable = gtk_widget_get_gl_drawable(GTK_WIDGET(&this->vrml_browser_)); gdk_gl_drawable_swap_buffers(gl_drawable); } void GtkGLViewer::set_timer(const double t) { if (!this->timer) { this->timer = g_timeout_add(guint(10.0 * (t + 1)), GtkFunction(gtk_vrml_browser_timeout_callback), this); } } void GtkGLViewer::timer_update() { this->timer = 0; this->viewer::update(); } } --- gtkglviewer.h DELETED --- --- NEW FILE: gtkvrmlbrowser.h --- /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; -*- * * OpenVRML Mozilla plug-in * Copyright 2004, 2005, 2006 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 2 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 program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ # ifndef GTK_VRML_BROWSER_H # define GTK_VRML_BROWSER_H # include <gtk/gtkdrawingarea.h> # include <gtk/gtkgl.h> G_BEGIN_DECLS # define GTK_TYPE_VRML_BROWSER (gtk_vrml_browser_get_type ()) # define GTK_VRML_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_VRML_BROWSER, GtkVrmlBrowser)) # define GTK_VRML_BROWSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_VRML_BROWSER, GtkVrmlBrowserClass)) # define GTK_IS_VRML_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_VRML_BROWSER)) # define GTK_IS_VRML_BROWSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_VRML_BROWSER)) # define GTK_VRML_BROWSER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_VRML_BROWSER, GtkVrmlBrowserClass)) typedef struct GtkVrmlBrowser_ GtkVrmlBrowser; typedef struct GtkVrmlBrowserClass_ GtkVrmlBrowserClass; struct GtkVrmlBrowser_ { GtkDrawingArea drawing_area; void *viewer; }; struct GtkVrmlBrowserClass_ { GtkDrawingAreaClass parent_class; }; GType gtk_vrml_browser_get_type(void) G_GNUC_CONST; GtkWidget *gtk_vrml_browser_new(GIOChannel *request_channel); void gtk_vrml_browser_load_url(GtkVrmlBrowser *vrml_browser, const gchar **url, const char **parameter); G_END_DECLS # ifdef __cplusplus namespace openvrml { class resource_istream; } // // Since OpenVRML has a C++ interface, exposing this to C is Hard. // void gtk_vrml_browser_set_world(GtkVrmlBrowser * vrml_browser, openvrml::resource_istream & in); # endif # endif /* ifndef GTK_VRML_BROWSER_H */ --- gtkglviewer.cpp DELETED --- --- browser.cpp DELETED --- --- browser.h DELETED --- Index: player.cpp =================================================================== RCS file: /cvsroot/openvrml/openvrml/mozilla-plugin/src/openvrml-player/player.cpp,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -d -r1.22 -r1.23 *** player.cpp 5 Feb 2006 06:40:31 -0000 1.22 --- player.cpp 5 Feb 2006 22:15:42 -0000 1.23 *************** *** 24,31 **** // Must include before X11 headers. # include <boost/numeric/conversion/converter.hpp> ! # include <gdk/gdkx.h> ! # include "browser.h" ! # include "gtkglviewer.h" # include "command_istream.h" # include "plugin_streambuf.h" --- 24,31 ---- // Must include before X11 headers. # include <boost/numeric/conversion/converter.hpp> ! # include <gtk/gtk.h> ! # include <openvrml/browser.h> ! # include "gtkvrmlbrowser.h" # include "command_istream.h" # include "plugin_streambuf.h" *************** *** 130,133 **** --- 130,143 ---- // ::quit_flag.value(true); + + // + // We can safely shut down the Gtk main loop from here. + // + // (However, trying to shut down the command_main loop results in + // it deadlocking in g_main_context_check's call to poll. So we + // still use the annoying quit_flag condition variable (see above) + // to end that thread). + // + gtk_main_quit(); } *************** *** 160,166 **** initial_stream_reader( const boost::shared_ptr<plugin_streambuf> & streambuf, ! openvrml::browser & browser): streambuf_(streambuf), ! browser_(&browser) {} --- 170,176 ---- initial_stream_reader( const boost::shared_ptr<plugin_streambuf> & streambuf, ! GtkVrmlBrowser & vrml_browser): streambuf_(streambuf), ! vrml_browser_(&vrml_browser) {} *************** *** 197,273 **** } } in(this->streambuf_); ! this->browser_->set_world(in); } private: boost::shared_ptr<plugin_streambuf> streambuf_; ! openvrml::browser * browser_; }; GIOChannel * request_channel; - struct command_channel_data { - GMainContext * main_context; - GMainLoop * main_loop; - GIOChannel * command_channel; - }; - struct command_channel_loop { ! explicit command_channel_loop(command_istream & command_in): ! command_in_(&command_in) {} void operator()() const throw () { - command_channel_data data; - data.main_context = g_main_context_new(); - data.main_loop = g_main_loop_new(data.main_context, false); - data.command_channel = g_io_channel_unix_new(0); // stdin - GError * error = 0; - GIOStatus status = - g_io_channel_set_encoding(data.command_channel, - 0, // binary (no encoding) - &error); - if (status != G_IO_STATUS_NORMAL) { - if (error) { - g_critical(error->message); - g_error_free(error); - } - exit(EXIT_FAILURE); - } - - GSource * const command_watch = - g_io_create_watch(data.command_channel, - GIOCondition(G_IO_IN | G_IO_HUP)); - const GDestroyNotify notify = 0; - g_source_set_callback( - command_watch, - reinterpret_cast<GSourceFunc>(::command_data_available), - static_cast<command_streambuf *>(this->command_in_->rdbuf()), - notify); - guint source_id = g_source_attach(command_watch, - data.main_context); - g_return_if_fail(source_id != 0); - GSource * const quit = g_idle_source_new(); g_source_set_callback( quit, ::openvrml_player_command_channel_loop_quit_event, ! &data, notify); ! source_id = g_source_attach(quit, data.main_context); g_return_if_fail(source_id != 0); ! g_main_loop_run(data.main_loop); ! ! g_source_unref(command_watch); ! g_io_channel_unref(data.command_channel); ! ! g_main_loop_unref(data.main_loop); ! g_main_context_unref(data.main_context); } private: ! command_istream * command_in_; }; } --- 207,244 ---- } } in(this->streambuf_); ! gtk_vrml_browser_set_world(this->vrml_browser_, in); } private: boost::shared_ptr<plugin_streambuf> streambuf_; ! GtkVrmlBrowser * vrml_browser_; }; GIOChannel * request_channel; struct command_channel_loop { ! explicit command_channel_loop(GMainLoop & main_loop): ! main_loop_(&main_loop) {} void operator()() const throw () { GSource * const quit = g_idle_source_new(); + const GDestroyNotify notify = 0; g_source_set_callback( quit, ::openvrml_player_command_channel_loop_quit_event, ! this->main_loop_, notify); ! guint source_id = ! g_source_attach(quit, ! g_main_loop_get_context(this->main_loop_)); g_return_if_fail(source_id != 0); ! g_main_loop_run(this->main_loop_); } private: ! GMainLoop * main_loop_; }; } *************** *** 313,319 **** : gtk_window_new(GTK_WINDOW_TOPLEVEL); ! GtkGLViewer viewer(*(GTK_CONTAINER(window)), ::quit_flag); ! browser b(::request_channel); ! b.viewer(&viewer); gtk_widget_show_all(window); --- 284,289 ---- : gtk_window_new(GTK_WINDOW_TOPLEVEL); ! GtkWidget * const vrml_browser = gtk_vrml_browser_new(::request_channel); ! gtk_container_add(GTK_CONTAINER(window), vrml_browser); gtk_widget_show_all(window); *************** *** 321,330 **** thread_group threads; if (argc > 1) { ! const vector<string> uri(1, argv[1]), parameter; ! b.load_url(uri, parameter); } else { function0<void> command_channel_loop_func = ! command_channel_loop(command_in); threads.create_thread(command_channel_loop_func); --- 291,334 ---- thread_group threads; + GMainContext * command_main_context = 0; + GMainLoop * command_main = 0; + GIOChannel * command_channel = 0; + GSource * command_watch = 0; + if (argc > 1) { ! const gchar * url[] = { argv[1], 0 }; ! const gchar ** parameter = 0; ! gtk_vrml_browser_load_url(GTK_VRML_BROWSER(vrml_browser), ! url, ! parameter); } else { + command_main_context = g_main_context_new(); + command_main = g_main_loop_new(command_main_context, false); + command_channel = g_io_channel_unix_new(0); // stdin + GError * error = 0; + GIOStatus status = g_io_channel_set_encoding(command_channel, + 0, // binary (no encoding) + &error); + if (status != G_IO_STATUS_NORMAL) { + if (error) { + g_critical(error->message); + g_error_free(error); + } + return EXIT_FAILURE; + } + + command_watch = g_io_create_watch(command_channel, + GIOCondition(G_IO_IN | G_IO_HUP)); + const GDestroyNotify notify = 0; + g_source_set_callback( + command_watch, + reinterpret_cast<GSourceFunc>(::command_data_available), + static_cast<command_streambuf *>(command_in.rdbuf()), notify); + guint source_id = g_source_attach(command_watch, + command_main_context); + g_return_val_if_fail(source_id != 0, EXIT_FAILURE); + function0<void> command_channel_loop_func = ! command_channel_loop(*command_main); threads.create_thread(command_channel_loop_func); *************** *** 336,340 **** g_return_val_if_fail(succeeded, EXIT_FAILURE); function0<void> initial_stream_reader_func = ! initial_stream_reader(initial_stream, b); threads.create_thread(initial_stream_reader_func); } --- 340,345 ---- g_return_val_if_fail(succeeded, EXIT_FAILURE); function0<void> initial_stream_reader_func = ! initial_stream_reader(initial_stream, ! *GTK_VRML_BROWSER(vrml_browser)); threads.create_thread(initial_stream_reader_func); } *************** *** 343,351 **** threads.create_thread(read_commands); - viewer.timer_update(); gtk_main(); threads.join_all(); if (::request_channel) { GError * error = 0; --- 348,369 ---- threads.create_thread(read_commands); gtk_main(); threads.join_all(); + g_source_unref(command_watch); + + GIOStatus status = g_io_channel_shutdown(command_channel, true, &error); + if (status != G_IO_STATUS_NORMAL) { + if (error) { + g_critical(error->message); + g_error_free(error); + } + } + g_io_channel_unref(command_channel); + + g_main_loop_unref(command_main); + g_main_context_unref(command_main_context); + if (::request_channel) { GError * error = 0; *************** *** 366,386 **** gboolean openvrml_player_command_channel_loop_quit_event(const gpointer data) { ! command_channel_data & cc_data = ! *static_cast<command_channel_data *>(data); if (::quit_flag.value()) { ! GError * error = 0; ! GIOStatus status = g_io_channel_shutdown(cc_data.command_channel, ! true, ! &error); ! if (status != G_IO_STATUS_NORMAL) { ! if (error) { ! g_critical(error->message); ! g_error_free(error); ! } ! } ! ! g_main_loop_quit(cc_data.main_loop); ! return false; } --- 384,391 ---- gboolean openvrml_player_command_channel_loop_quit_event(const gpointer data) { ! GMainLoop * const main_loop = static_cast<GMainLoop *>(data); if (::quit_flag.value()) { ! g_main_loop_quit(main_loop); return false; } Index: Makefile.am =================================================================== RCS file: /cvsroot/openvrml/openvrml/mozilla-plugin/src/openvrml-player/Makefile.am,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** Makefile.am 1 Feb 2006 19:15:51 -0000 1.8 --- Makefile.am 5 Feb 2006 22:15:42 -0000 1.9 *************** *** 18,23 **** command_istream.h \ plugin_streambuf.h \ ! browser.h \ ! gtkglviewer.h \ flag.h openvrml_player_SOURCES = \ --- 18,22 ---- command_istream.h \ plugin_streambuf.h \ ! gtkvrmlbrowser.h \ flag.h openvrml_player_SOURCES = \ *************** *** 25,30 **** command_istream.cpp \ plugin_streambuf.cpp \ ! browser.cpp \ ! gtkglviewer.cpp \ flag.cpp openvrml_player_LDADD = \ --- 24,28 ---- command_istream.cpp \ plugin_streambuf.cpp \ ! gtkvrmlbrowser.cpp \ flag.cpp openvrml_player_LDADD = \ |