Index: configure.ac =================================================================== RCS file: /cvsroot/gxmame/gxmame/configure.ac,v retrieving revision 1.14 diff -p -u -r1.14 configure.ac --- configure.ac 16 Feb 2005 16:52:35 -0000 1.14 +++ configure.ac 21 Feb 2005 17:18:23 -0000 @@ -73,6 +73,25 @@ if test "$enable_joystick" = yes ; then AC_CHECK_HEADERS([linux/joystick.h]) fi +AC_PATH_X + +if test x"$x_includes" != x"NONE" && test -n "$x_includes" ; then + X_INCLUDES=-I`echo $x_includes | sed -e "s/:/ -I/g"` +fi +if test x"$x_libraries" != x"NONE" && test -n "$x_libraries" ; then + X_LIBRARIES=-L`echo $x_libraries | sed -e "s/:/ -L/g"` +fi +CFLAGS="$X_INCLUDES $CFLAGS" +LIBS="$X_LIBRARIES $LIBS" + +XTEST_LIBS="" +AC_CHECK_LIB(Xtst, XTestFakeKeyEvent, + XTEST_LIBS="-lX11 -lXtst $X_LIBRARIES" + AC_DEFINE(HAVE_XTEST, 1, [defined if you have XTest library]), + , + $X_LIBRARIES) +AC_SUBST(XTEST_LIBS) + AC_CONFIG_FILES([ intl/Makefile Makefile gxmame.spec Index: src/Makefile.am =================================================================== RCS file: /cvsroot/gxmame/gxmame/src/Makefile.am,v retrieving revision 1.17 diff -p -u -r1.17 Makefile.am --- src/Makefile.am 17 Feb 2005 19:01:33 -0000 1.17 +++ src/Makefile.am 21 Feb 2005 17:18:23 -0000 @@ -3,33 +3,34 @@ bin_PROGRAMS = gxmame gxmame_SOURCES = \ - common.c common.h \ - gxmame.c gxmame.h \ - interface.c interface.h \ - callbacks.c callbacks.h \ + common.c common.h \ + gxmame.c gxmame.h \ + interface.c interface.h \ + callbacks.c callbacks.h \ io.c io.h \ - game_list.h game_list.c \ - game_options.h game_options.c \ - mameio.c \ - gui.c gui.h \ + game_list.h game_list.c \ + game_options.h game_options.c \ + mameio.c \ + gui.c gui.h \ progression_window.c progression_window.h \ - directories.c directories.h \ - about.c about.h \ - audit.c audit.h \ - properties.c properties.h \ - options.c options.h \ - options_string.c options_string.h \ - gtkjoy.c gtkjoy.h \ - gui_prefs.c gui_prefs.h \ - column_layout.c column_layout.h \ - unzip.c unzip.h \ - keyboard.c keyboard.h \ - network_game.h network_game.c \ - xmame_options.h xmame_options.c \ - xmame_executable.h xmame_executable.c + directories.c directories.h \ + about.c about.h \ + audit.c audit.h \ + properties.c properties.h \ + options.c options.h \ + options_string.c options_string.h \ + gtkjoy.c gtkjoy.h \ + gui_prefs.c gui_prefs.h \ + column_layout.c column_layout.h \ + unzip.c unzip.h \ + keyboard.c keyboard.h \ + network_game.h network_game.c \ + xmame_options.h xmame_options.c \ + xmame_executable.h xmame_executable.c \ + scrsaver.c scrsaver.h -gxmame_LDADD = @GTK_LIBS@ $(INTLLIBS) +gxmame_LDADD = @GTK_LIBS@ $(INTLLIBS) $(XTEST_LIBS) -AM_CPPFLAGS = $(GTK_CFLAGS) \ - -DDATADIR=\""$(datadir)"\" \ +AM_CPPFLAGS = $(GTK_CFLAGS) \ + -DDATADIR=\""$(datadir)"\" \ -DPACKAGE_LOCALE_DIR=\""$(datadir)/locale"\" Index: src/gxmame.c =================================================================== RCS file: /cvsroot/gxmame/gxmame/src/gxmame.c,v retrieving revision 1.78 diff -p -u -r1.78 gxmame.c --- src/gxmame.c 17 Feb 2005 17:59:05 -0000 1.78 +++ src/gxmame.c 21 Feb 2005 17:18:25 -0000 @@ -42,6 +42,7 @@ #include "options_string.h" #include "progression_window.h" #include "gtkjoy.h" +#include "scrsaver.h" #define BUFFER_SIZE 1000 @@ -281,154 +282,187 @@ game_filtered (RomEntry * rom) return FALSE; } +typedef struct { + RomEntry *rom; + GString *line; + TotemScrsaver *scrsaver; + ProgressWindow *progress_window; +} LaunchWatchData; -/* launch following the commandline prepared by play_game, playback_game and record_game - then test if the game is launched, detect error and update game status */ -void -launch_emulation (RomEntry *rom, - const gchar *options) +static void +launch_process_output_line (char *long_line, + LaunchWatchData *data) { - FILE *xmame_pipe; - gchar line [BUFFER_SIZE]; + gdouble done; + gchar *line; + gchar **lines; gchar *p, *p2; - gfloat done = 0; - gint nb_loaded = 0; - GList *extra_output = NULL, *extra_output2 = NULL; - gboolean error_during_load,other_error; - ProgressWindow *progress_window; + int i; + int nb_loaded = 0; -#ifdef ENABLE_JOYSTICK - joystick_close (joydata); - joydata = NULL; -#endif - - progress_window = progress_window_new (TRUE); + lines = g_strsplit (long_line, "\n", -1); - progress_window_set_title (progress_window, _("Loading %s:"), rom_entry_get_list_name (rom)); - progress_window_show (progress_window); + for (i = 0; lines[i]; i++) { + line = lines[i]; - gtk_window_get_position (GTK_WINDOW (MainWindow), &gui_prefs.GUIPosX, &gui_prefs.GUIPosY); - gtk_widget_hide (MainWindow); + if ((p = g_strrstr (line, "loading rom"))) { - /* need to use printf otherwise, with GXMAME_DEBUG, we dont see the complete command line */ - GXMAME_DEBUG ("Message: running command %s\n", options); - xmame_pipe = popen (options, "r"); - GXMAME_DEBUG (_("Loading %s:"), rom->gamename); + sscanf (p, "loading rom %d:", &nb_loaded); + if (!data->progress_window) { - /* Loading */ - error_during_load = other_error = FALSE; - while (fgets (line, BUFFER_SIZE, xmame_pipe)) { - /* remove the last \n */ - for (p = line; (*p && (*p != '\n')); p++); - *p = '\0'; - - GXMAME_DEBUG ("xmame: %s", line); - - if (!strncmp (line,"loading", 7)) { - nb_loaded++; - /*search for the : */ - for (p = line; (*p && (*p != ':')); p++); +#ifdef ENABLE_JOYSTICK + joystick_close (joydata); + joydata = NULL; +#endif + totem_scrsaver_disable (data->scrsaver); + data->progress_window = progress_window_new (TRUE); + } + + progress_window_set_title (data->progress_window, _("Loading %s:"), rom_entry_get_list_name (data->rom)); + progress_window_show (data->progress_window); + + /* search for the : */ + for (; (*p && (*p != ':')); p++); p = p + 2; for (p2 = p; (*p2 && (*p2 != '\n')); p2++); p2 = '\0'; + done = (gfloat) ( (gfloat) (nb_loaded) / - (gfloat) (rom->nb_roms)); + (gfloat) (data->rom->nb_roms)); - progress_window_set_value (progress_window, done); - progress_window_set_text (progress_window, p); + progress_window_set_value (data->progress_window, done); + progress_window_set_text (data->progress_window, p); - } else if (!strncmp (line, "Master Mode: Waiting", 20)) { - for (p = line; *p != ':'; p++); + } else if ((p = g_strrstr (line, "Master Mode: Waiting"))) { + for (; *p != ':'; p++); p++; - - progress_window_set_text (progress_window, p); + + if (data->progress_window) + progress_window_set_text (data->progress_window, p); } else if (!g_ascii_strncasecmp (line, "error", 5) || !g_ascii_strncasecmp (line, "Can't bind socket", 17)) { - /* the game didn't even began to load*/ - other_error = TRUE; - extra_output = g_list_append (extra_output, g_strdup (line)); + /* the game didn't even began to load */ + } else if (!strncmp (line, "GLERROR", 7)) { /* OpenGL initialization errors */ + } else if (!strncmp (line, "X Error", 7) || /* X11 mode not found*/ + !strncmp (line, "SDL: Unsupported", 16) || + !strncmp (line, "Unable to start", 15) || + !strncmp (line, "Unspected X Error", 17)) { } - if (!strncmp (line, "done", 4)) - break; + if (!strncmp (line, "done", 4)) { + progress_window_destroy (data->progress_window); + data->progress_window = NULL; + } - while (gtk_events_pending ()) gtk_main_iteration (); } - progress_window_destroy (progress_window); - while (gtk_events_pending ()) gtk_main_iteration (); + g_strfreev (lines); +} - /*check if errors */ - while (fgets (line, BUFFER_SIZE, xmame_pipe)) { - for (p = line; (*p && (*p != '\n')); p++); - *p = '\0'; +static gboolean +launch_watch_stderr (GIOChannel *source, + GIOCondition condition, + gpointer user_data) +{ + LaunchWatchData *data = (LaunchWatchData *)user_data; + RomEntry *rom = data->rom; - GXMAME_DEBUG ("xmame: %s", line); + if (condition & G_IO_IN) { + GIOStatus status; + char *line; - if (!strncmp (line, "GLmame", 6) || !strncmp (line, "based", 5)) - continue; - else if (!g_ascii_strncasecmp (line, "error", 5)) { /* bad rom or no rom found */ - error_during_load = TRUE; - break; - } else if (!strncmp (line, "GLERROR", 7)) { /* OpenGL initialization errors */ - other_error = TRUE; - } /* another error occurred after game loaded */ - else if (!strncmp (line, "X Error", 7) || /* X11 mode not found*/ - !strncmp (line, "SDL: Unsupported", 16) || - !strncmp (line, "Unable to start", 15) || - !strncmp (line, "Unspected X Error", 17)) { - other_error = TRUE; - } - extra_output = g_list_append (extra_output, g_strdup (line)); - } - - pclose (xmame_pipe); - if (error_during_load || other_error) { - int size; - char **message = NULL; - GXMAME_DEBUG ("error during load"); - size = g_list_length (extra_output) + 1; - message = g_new (gchar *, size); - size = 0; - - for (extra_output2 = g_list_first (extra_output); extra_output2;) { - message [size++] = extra_output2->data; - extra_output2 = g_list_next (extra_output2); - } - message[size] = NULL; + status = g_io_channel_read_line (source, &line, NULL, NULL, NULL); - gxmame_message (ERROR, NULL, g_strjoinv ("\n", message)); - g_strfreev (message); - - g_list_free (extra_output); - - /* update game informations if it was an rom problem */ - if (error_during_load) - rom->has_roms = 0; - - } else { + if (status == G_IO_STATUS_NORMAL) { + + if (data->line) { + g_string_append (data->line, line); + g_free (line); + line = g_string_free (data->line, FALSE); + data->line = NULL; + } + + launch_process_output_line (line, data); + + } else if (status == G_IO_STATUS_AGAIN) { + char buf[1]; + /* A non-terminated line was read, read the data into the buffer. */ + status = g_io_channel_read_chars (source, buf, 1, NULL, NULL); + if (status == G_IO_STATUS_NORMAL) { + if (data->line == NULL) { + data->line = g_string_new (NULL); + } + g_string_append_c (data->line, buf[0]); + } + } + g_free (line); + } else if (condition & G_IO_HUP) { GXMAME_DEBUG ("game over"); - g_list_foreach (extra_output, (GFunc)g_free, NULL); - g_list_free (extra_output); + + if (data->progress_window) { + progress_window_destroy (data->progress_window); + data->progress_window = NULL; + } /* update game informations */ rom->timesplayed++; rom->has_roms = 1; - } - gtk_window_move (GTK_WINDOW (MainWindow), - gui_prefs.GUIPosX, - gui_prefs.GUIPosY); - - gtk_widget_show (MainWindow); - /* update the gui for the times played and romstatus if there was any error */ - update_game_in_list (rom); - select_game (rom); + /* update the gui for the times played and romstatus if there was any error */ + update_game_in_list (rom); + select_game (rom); #ifdef ENABLE_JOYSTICK - if (gui_prefs.gui_joy) - joydata = joystick_new (gui_prefs.Joystick_in_GUI); -#endif + if (gui_prefs.gui_joy) + joydata = joystick_new (gui_prefs.Joystick_in_GUI); +#endif + totem_scrsaver_enable (data->scrsaver); + g_object_unref (data->scrsaver); + g_free (data); + return FALSE; + } + + return TRUE; +} + +/* launch following the commandline prepared by play_game, playback_game and record_game + then test if the game is launched, detect error and update game status */ +void +launch_emulation (RomEntry *rom, + const gchar *options) +{ + int res, standard_output, standard_error; + GError *error; + GIOChannel *ioc; + char **argv; + + g_shell_parse_argv (options, NULL, &argv, NULL); + GXMAME_DEBUG ("Message: running command %s\n", options); + res = g_spawn_async_with_pipes (NULL, + argv, + NULL, + G_SPAWN_SEARCH_PATH, + NULL, + NULL, + NULL, + NULL, /* stdin */ + &standard_output, + &standard_error, + &error); + g_strfreev (argv); + + if (res) { + LaunchWatchData *data = g_new0 (LaunchWatchData, 1); + data->rom = rom; + data->scrsaver = totem_scrsaver_new (); + ioc = g_io_channel_unix_new (standard_error); + g_io_channel_set_flags (ioc, G_IO_FLAG_NONBLOCK, NULL); + g_io_add_watch (ioc, G_IO_IN | G_IO_HUP, launch_watch_stderr, data); + } else { + g_warning ("Could not start command: %s: %s", options, error->message); + } + + GXMAME_DEBUG (_("Loading %s:"), rom->gamename); } /* Prepare the commandline to use to play a game */ @@ -449,7 +483,7 @@ play_game (RomEntry *rom) } if (gui_prefs.use_xmame_options) { - opt = g_strdup_printf ("%s %s 2>&1", current_exec->path, rom->romname); + opt = g_strdup_printf ("%s %s", current_exec->path, rom->romname); launch_emulation (rom, opt); g_free (opt); return; @@ -467,7 +501,7 @@ play_game (RomEntry *rom) else Vector_Related_options = g_strdup (""); /* create the command */ - opt = g_strdup_printf ("%s %s %s -%s %s 2>&1", + opt = g_strdup_printf ("%s %s %s -%s %s", current_exec->path, general_options, Vector_Related_options, @@ -532,7 +566,7 @@ playback_game (RomEntry *rom, } /* create the command */ - opt = g_strdup_printf ("%s %s %s -input_directory %s -playback %s -%s %s 2>&1", + opt = g_strdup_printf ("%s %s %s -input_directory %s -playback %s -%s %s", current_exec->path, general_options, Vector_Related_options, @@ -600,7 +634,7 @@ record_game (RomEntry *rom, } /* create the command */ - opt = g_strdup_printf ("%s %s %s -input_directory %s -record %s -%s %s 2>&1", + opt = g_strdup_printf ("%s %s %s -input_directory %s -record %s -%s %s", current_exec->path, general_options, vector_options, --- /dev/null 2005-02-21 06:43:36.317476504 -0500 +++ src/scrsaver.h 2005-02-14 16:02:57.000000000 -0500 @@ -0,0 +1,49 @@ +/* + Copyright (C) 2004, Bastien Nocera + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Bastien Nocera + */ + +#include +#include + +#define TOTEM_TYPE_SCRSAVER (totem_scrsaver_get_type ()) +#define TOTEM_SCRSAVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TOTEM_TYPE_SCRSAVER, TotemScrsaver)) +#define TOTEM_SCRSAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TOTEM_TYPE_SCRSAVER, TotemScrsaverClass)) +#define TOTEM_IS_SCRSAVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TOTEM_TYPE_SCRSAVER)) +#define TOTEM_IS_SCRSAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TOTEM_TYPE_SCRSAVER)) + + +typedef struct TotemScrsaver TotemScrsaver; +typedef struct TotemScrsaverClass TotemScrsaverClass; +typedef struct TotemScrsaverPrivate TotemScrsaverPrivate; + +struct TotemScrsaver { + GObject parent; + TotemScrsaverPrivate *priv; +}; + +struct TotemScrsaverClass { + GObjectClass parent_class; +}; + +GType totem_scrsaver_get_type (void); +TotemScrsaver *totem_scrsaver_new (void); +void totem_scrsaver_enable (TotemScrsaver *scr); +void totem_scrsaver_disable (TotemScrsaver *scr); + --- /dev/null 2005-02-21 06:43:36.317476504 -0500 +++ src/scrsaver.c 2005-02-21 12:18:06.653139567 -0500 @@ -0,0 +1,197 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + Copyright (C) 2004,2005 Bastien Nocera + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Bastien Nocera + */ + + +#include "config.h" +#include "scrsaver.h" + +#include + +#ifdef HAVE_XTEST +#include +#endif /* HAVE_XTEST */ +#include + +#define XSCREENSAVER_MIN_TIMEOUT 60 + +static GObjectClass *parent_class = NULL; +static void totem_scrsaver_class_init (TotemScrsaverClass *class); +static void totem_scrsaver_init (TotemScrsaver *parser); +static void totem_scrsaver_finalize (GObject *object); + + +struct TotemScrsaverPrivate { + /* Whether the screensaver is disabled */ + gboolean disabled; + + /* To save the screensaver info */ + int timeout; + int interval; + int prefer_blanking; + int allow_exposures; + + /* For use with XTest */ + int keycode1, keycode2; + int *keycode; + Bool have_xtest; +}; + +G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT) + +static void +totem_scrsaver_class_init (TotemScrsaverClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = totem_scrsaver_finalize; +} + +TotemScrsaver * +totem_scrsaver_new (void) +{ + return TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL)); +} + +#ifdef HAVE_XTEST +static gboolean +fake_event (TotemScrsaver *scr) +{ + if (scr->priv->disabled) + { + XLockDisplay (GDK_DISPLAY ()); + XTestFakeKeyEvent (GDK_DISPLAY (), *scr->priv->keycode, + True, CurrentTime); + XTestFakeKeyEvent (GDK_DISPLAY (), *scr->priv->keycode, + False, CurrentTime); + XUnlockDisplay (GDK_DISPLAY ()); + /* Swap the keycode */ + if (scr->priv->keycode == &scr->priv->keycode1) + scr->priv->keycode = &scr->priv->keycode2; + else + scr->priv->keycode = &scr->priv->keycode1; + } + + return TRUE; +} +#endif /* HAVE_XTEST */ + +static void +totem_scrsaver_init (TotemScrsaver *scr) +{ + int a, b, c, d; + + scr->priv = g_new0 (TotemScrsaverPrivate, 1); + +#ifdef HAVE_XTEST + XLockDisplay (GDK_DISPLAY ()); + scr->priv->have_xtest = XTestQueryExtension (GDK_DISPLAY (), &a, &b, &c, &d); + if(scr->priv->have_xtest == True) + { + scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY (), XK_Shift_L); + scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY (), XK_Control_L); + scr->priv->keycode = &scr->priv->keycode1; + } + XUnlockDisplay (GDK_DISPLAY ()); +#endif /* HAVE_XTEST */ +} + +void +totem_scrsaver_disable (TotemScrsaver *scr) +{ + if (scr->priv->disabled != FALSE) + return; + + scr->priv->disabled = TRUE; + +#ifdef HAVE_XTEST + if (scr->priv->have_xtest == True) + { + XLockDisplay (GDK_DISPLAY ()); + XGetScreenSaver (GDK_DISPLAY (), &scr->priv->timeout, + &scr->priv->interval, + &scr->priv->prefer_blanking, + &scr->priv->allow_exposures); + XUnlockDisplay (GDK_DISPLAY ()); + + if (scr->priv->timeout != 0) + { + g_timeout_add ((scr->priv->timeout - 1) / 2 * 1000, + (GSourceFunc) fake_event, scr); + } else { + g_timeout_add ((XSCREENSAVER_MIN_TIMEOUT - 1) / 2 * 1000, + (GSourceFunc) fake_event, scr); + } + + return; + } +#endif /* HAVE_XTEST */ + + XLockDisplay (GDK_DISPLAY ()); + XGetScreenSaver (GDK_DISPLAY (), &scr->priv->timeout, + &scr->priv->interval, + &scr->priv->prefer_blanking, + &scr->priv->allow_exposures); + XSetScreenSaver (GDK_DISPLAY (), 0, 0, + DontPreferBlanking, DontAllowExposures); + XUnlockDisplay (GDK_DISPLAY ()); +} + +void +totem_scrsaver_enable (TotemScrsaver *scr) +{ + if (scr->priv->disabled == FALSE) + return; + + scr->priv->disabled = FALSE; + +#ifdef HAVE_XTEST + if (scr->priv->have_xtest == True) + { + g_source_remove_by_user_data (scr); + return; + } + +#endif /* HAVE_XTEST */ + XLockDisplay (GDK_DISPLAY ()); + XSetScreenSaver (GDK_DISPLAY (), + scr->priv->timeout, + scr->priv->interval, + scr->priv->prefer_blanking, + scr->priv->allow_exposures); + XUnlockDisplay (GDK_DISPLAY ()); +} + +static void +totem_scrsaver_finalize (GObject *object) +{ + TotemScrsaver *scr = TOTEM_SCRSAVER (object); + + g_source_remove_by_user_data (scr); + g_free (scr->priv); + + if (G_OBJECT_CLASS (parent_class)->finalize != NULL) { + (* G_OBJECT_CLASS (parent_class)->finalize) (object); + } +} +