From: Braden M. <br...@us...> - 2007-09-02 18:28:03
|
Update of /cvsroot/openvrml/openvrml/src/openvrml-player In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv4802/src/openvrml-player Modified Files: Makefile.am player.cpp Log Message: Changes to facilitate setting openvrml-player's location entry after the world has been loaded. Significantly, access to the GIOChannel used by the GtkVrmlBrowser (i.e., the request channel) needed to be made thread-safe. Accordingly, all access to the request channel now goes through the function openvrml_xembed::write_request_chars. Index: player.cpp =================================================================== RCS file: /cvsroot/openvrml/openvrml/src/openvrml-player/player.cpp,v retrieving revision 1.25 retrieving revision 1.26 diff -C2 -d -r1.25 -r1.26 *** player.cpp 12 Jul 2007 05:32:24 -0000 1.25 --- player.cpp 2 Sep 2007 18:27:55 -0000 1.26 *************** *** 33,36 **** --- 33,37 ---- # include <glade/glade.h> # include <glade/glade-build.h> + # include <openvrml/browser.h> # include "filechooserdialog.h" *************** *** 96,102 **** --- 97,108 ---- G_GNUC_INTERNAL guint request_channel_watch_id; + G_GNUC_INTERNAL void get_openvrml_xembed_cmd(gint & argc, gchar ** & argv); + G_GNUC_INTERNAL GPid spawn_openvrml_xembed(GdkNativeWindow socket_id, + gint & in_fd, + gint & out_fd); G_GNUC_INTERNAL ssize_t write_command(const std::string & command); G_GNUC_INTERNAL GSource * curl_source_new(CURLM * multi_handle); G_GNUC_INTERNAL GladeXML * xml_new(GnomeProgram & program); + G_GNUC_INTERNAL void set_locationentry_text(const gchar * text); G_GNUC_INTERNAL void load_url(const gchar * url); *************** *** 127,130 **** --- 133,138 ---- curl_source_callback_data * source_callback_data; }; + + GtkWidget * location_entry; } *************** *** 221,226 **** GTK_WINDOW(app_window)); ! GtkWidget * const location_entry = ! glade_xml_get_widget(xml, "locationentry"); g_signal_connect(file_chooser_dialog, "response", --- 229,233 ---- GTK_WINDOW(app_window)); ! ::location_entry = glade_xml_get_widget(xml, "locationentry"); g_signal_connect(file_chooser_dialog, "response", *************** *** 228,326 **** location_entry); - // - // 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(); - } - - GtkWidget * const socket = glade_xml_get_widget(xml, "socket"); - string socket_id_arg = - lexical_cast<string>(gtk_socket_get_id(GTK_SOCKET(socket))); - const char * socket_id_arg_c_str = socket_id_arg.c_str(); - vector<char> socket_id_arg_vec( - socket_id_arg_c_str, - socket_id_arg_c_str + socket_id_arg.length() + 1); - - const gint child_argv_size = openvrml_xembed_cmd_argc + 2; - gchar ** const child_argv = - static_cast<gchar **>(g_malloc(sizeof (gchar *) * child_argv_size)); - if (!argv) { throw std::bad_alloc(); } - scope_guard child_argv_guard = make_guard(g_free, child_argv); - boost::ignore_unused_variable_warning(child_argv_guard); - gint i; - for (i = 0; i < openvrml_xembed_cmd_argc; ++i) { - child_argv[i] = openvrml_xembed_cmd_argv[i]; - } - child_argv[i++] = &socket_id_arg_vec.front(); - child_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); - - gchar ** envp = 0; - GPid child_pid; gint standard_input, standard_output; ! gint * const standard_error = 0; ! GError * error = 0; ! scope_guard error_guard = make_guard(g_error_free, ref(error)); ! gboolean succeeded = g_spawn_async_with_pipes(working_dir, ! child_argv, ! envp, ! G_SPAWN_DO_NOT_REAP_CHILD, ! 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"); ! } g_child_watch_add(child_pid, openvrml_player_watch_child, 0); - // - // Don't dismiss "error_guard" yet; we reuse "error" below. - // - ::command_channel = g_io_channel_unix_new(standard_input); if (!::command_channel) { throw std::bad_alloc(); } GIOStatus status = g_io_channel_set_encoding(::command_channel, 0, // binary (no encoding) --- 235,251 ---- location_entry); gint standard_input, standard_output; ! GtkWidget * const socket = glade_xml_get_widget(xml, "socket"); ! const GPid child_pid = ! spawn_openvrml_xembed(gtk_socket_get_id(GTK_SOCKET(socket)), ! standard_input, ! standard_output); g_child_watch_add(child_pid, openvrml_player_watch_child, 0); ::command_channel = g_io_channel_unix_new(standard_input); if (!::command_channel) { throw std::bad_alloc(); } + GError * error = 0; + scope_guard error_guard = make_guard(g_error_free, ref(error)); GIOStatus status = g_io_channel_set_encoding(::command_channel, 0, // binary (no encoding) *************** *** 370,373 **** --- 295,305 ---- &req_data); + ::write_command("add-browser-event-listener " + + lexical_cast<string>(getpid()) + "\n"); + + if (remaining_args && remaining_args[0]) { + ::load_url(remaining_args[0]); + } + gtk_widget_show(app_window); *************** *** 377,380 **** --- 309,416 ---- namespace { + void get_openvrml_xembed_cmd(gint & argc, gchar ** & argv) + { + using boost::ref; + + const gchar * const openvrml_xembed_cmd = g_getenv("OPENVRML_XEMBED"); + + if (!openvrml_xembed_cmd) { + argc = 1; + argv = static_cast<gchar **>(g_malloc0(sizeof (gchar *) * 2)); + if (!argv) { throw std::bad_alloc(); } + argv[0] = g_strdup(OPENVRML_LIBEXECDIR_ "/openvrml-xembed"); + scope_guard argv_guard = make_guard(g_strfreev, ref(argv)); + boost::ignore_unused_variable_warning(argv_guard); + if (!argv[0]) { throw std::bad_alloc(); } + argv_guard.dismiss(); + return; + } + + GError * error = 0; + scope_guard error_guard = make_guard(g_error_free, ref(error)); + const gboolean succeeded = + g_shell_parse_argv(openvrml_xembed_cmd, &argc, &argv, &error); + if (!succeeded) { + throw std::runtime_error(error + ? error->message + : "g_shell_parse_argv failure"); + } + error_guard.dismiss(); + } + + GPid spawn_openvrml_xembed(const GdkNativeWindow socket_id, + gint & in_fd, + gint & out_fd) + { + using std::string; + using std::vector; + using boost::lexical_cast; + using boost::ref; + + // + // 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; + get_openvrml_xembed_cmd(openvrml_xembed_cmd_argc, + openvrml_xembed_cmd_argv); + + const string socket_id_arg = lexical_cast<string>(socket_id); + const char * socket_id_arg_c_str = socket_id_arg.c_str(); + vector<char> socket_id_arg_vec( + socket_id_arg_c_str, + socket_id_arg_c_str + socket_id_arg.length() + 1); + + const gint child_argv_size = openvrml_xembed_cmd_argc + 2; + gchar ** const child_argv = + static_cast<gchar **>(g_malloc(sizeof (gchar *) * child_argv_size)); + if (!child_argv) { throw std::bad_alloc(); } + scope_guard child_argv_guard = make_guard(g_free, child_argv); + boost::ignore_unused_variable_warning(child_argv_guard); + gint i; + for (i = 0; i < openvrml_xembed_cmd_argc; ++i) { + child_argv[i] = openvrml_xembed_cmd_argv[i]; + } + child_argv[i++] = &socket_id_arg_vec.front(); + child_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); + + gchar ** envp = 0; + GPid child_pid; + gint * const standard_error = 0; + GError * error = 0; + scope_guard error_guard = make_guard(g_error_free, ref(error)); + boost::ignore_unused_variable_warning(error_guard); + gboolean succeeded = + g_spawn_async_with_pipes(working_dir, + child_argv, + envp, + G_SPAWN_DO_NOT_REAP_CHILD, + 0, + 0, + &child_pid, + &in_fd, + &out_fd, + standard_error, + &error); + if (!succeeded) { + throw std::runtime_error(error + ? error->message + : "g_spawn_async_with_pipes failure"); + } + + error_guard.dismiss(); + + return child_pid; + } + GladeXML * xml_new(GnomeProgram & program) { *************** *** 404,408 **** } ! G_GNUC_INTERNAL void load_url(const gchar * url) { std::ostringstream command; --- 440,449 ---- } ! void set_locationentry_text(const gchar * const text) ! { ! gtk_entry_set_text(GTK_ENTRY(::location_entry), text); ! } ! ! void load_url(const gchar * url) { std::ostringstream command; *************** *** 761,764 **** --- 802,817 ---- } while (perform_result == CURLM_CALL_MULTI_PERFORM); } + } else if (request_type == "browser-event") { + pid_t listener_id; + long event; + req_data.request_line >> listener_id >> event; + + if (event == openvrml::browser_event::initialized) { + ::write_command("get-world-url\n"); + } + } else if (request_type == "world-url") { + std::string url; + req_data.request_line >> url; + ::set_locationentry_text(url.c_str()); } Index: Makefile.am =================================================================== RCS file: /cvsroot/openvrml/openvrml/src/openvrml-player/Makefile.am,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** Makefile.am 9 Feb 2007 05:20:28 -0000 1.4 --- Makefile.am 2 Sep 2007 18:27:55 -0000 1.5 *************** *** 4,10 **** -DGNOME_DISABLE_DEPRECATED \ -DOPENVRML_PLAYER_PKGDATADIR_=\"$(datadir)/openvrml-player\" \ ! -DOPENVRML_LIBEXECDIR_=\"$(libexecdir)\" ! AM_CXXFLAGS = @GNOMEUI_CFLAGS@ @GLADE_CFLAGS@ @CURL_CFLAGS@ ! AM_LDFLAGS = -export-dynamic @GNOMEUI_LIBS@ @GLADE_LIBS@ @CURL_LIBS@ gladedir = $(datadir)/openvrml-player/glade --- 4,12 ---- -DGNOME_DISABLE_DEPRECATED \ -DOPENVRML_PLAYER_PKGDATADIR_=\"$(datadir)/openvrml-player\" \ ! -DOPENVRML_LIBEXECDIR_=\"$(libexecdir)\" \ ! -I$(top_builddir)/src/libopenvrml \ ! -I$(top_srcdir)/src/libopenvrml ! AM_CXXFLAGS = $(GNOMEUI_CFLAGS) $(GLADE_CFLAGS) $(CURL_CFLAGS) ! AM_LDFLAGS = -export-dynamic $(GNOMEUI_LIBS) $(GLADE_LIBS) $(CURL_LIBS) gladedir = $(datadir)/openvrml-player/glade |