From 05328431c2d4c20e3b918cffa5c7f7e39d7b6af2 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Mon, 4 Dec 2006 20:48:49 +0100 Subject: [PATCH] implement breakpoints and handling of them --- libswfdec/swfdec_debugger.c | 7 ++++ player/swfdebug.c | 11 ++++-- player/swfdec_player_manager.c | 80 +++++++++++++++++++++++++++++++++++++----- player/swfdec_player_manager.h | 3 ++ 4 files changed, 89 insertions(+), 12 deletions(-) diff --git a/libswfdec/swfdec_debugger.c b/libswfdec/swfdec_debugger.c index 722afa47..36a3bc89 100644 --- a/libswfdec/swfdec_debugger.c +++ b/libswfdec/swfdec_debugger.c @@ -58,6 +58,7 @@ swfdec_debugger_script_free (SwfdecDebuggerScript *script) enum { SCRIPT_ADDED, SCRIPT_REMOVED, + BREAKPOINT, BREAKPOINT_ADDED, BREAKPOINT_REMOVED, LAST_SIGNAL @@ -92,6 +93,9 @@ swfdec_debugger_class_init (SwfdecDebuggerClass *klass) signals[SCRIPT_REMOVED] = g_signal_new ("script-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); + signals[BREAKPOINT] = g_signal_new ("breakpoint", + G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, + g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals[BREAKPOINT_ADDED] = g_signal_new ("breakpoint-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); @@ -175,6 +179,9 @@ static JSTrapStatus swfdec_debugger_handle_breakpoint (JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, void *closure) { + SwfdecDebugger *debugger = JS_GetContextPrivate (cx); + + g_signal_emit (debugger, signals[BREAKPOINT], 0, GPOINTER_TO_UINT (closure)); return JSTRAP_CONTINUE; } diff --git a/player/swfdebug.c b/player/swfdebug.c index 94ba138e..5ccb5591 100644 --- a/player/swfdebug.c +++ b/player/swfdebug.c @@ -110,6 +110,13 @@ message_display_cb (SwfdecPlayerManager *manager, guint type, const char *messag } static void +destroyed_cb (GtkWindow *window, SwfdecPlayerManager *manager) +{ + g_object_unref (manager); + gtk_main_quit (); +} + +static void view_swf (SwfdecPlayer *player, double scale, gboolean use_image) { SwfdecPlayerManager *manager; @@ -185,12 +192,10 @@ view_swf (SwfdecPlayer *player, double scale, gboolean use_image) gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, TRUE, 0); gtk_widget_grab_focus (widget); - g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); + g_signal_connect (window, "destroy", G_CALLBACK (destroyed_cb), manager); gtk_widget_show_all (window); gtk_main (); - - g_object_unref (manager); } int diff --git a/player/swfdec_player_manager.c b/player/swfdec_player_manager.c index bc48507b..fb5f3268 100644 --- a/player/swfdec_player_manager.c +++ b/player/swfdec_player_manager.c @@ -31,7 +31,8 @@ enum { PROP_0, PROP_PLAYING, - PROP_SPEED + PROP_SPEED, + PROP_INTERRUPTED }; enum { @@ -55,6 +56,9 @@ swfdec_player_manager_get_property (GObject *object, guint param_id, GValue *val case PROP_SPEED: g_value_set_double (value, swfdec_player_manager_get_speed (manager)); break; + case PROP_INTERRUPTED: + g_value_set_boolean (value, swfdec_player_manager_get_interrupted (manager)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; @@ -103,9 +107,12 @@ swfdec_player_manager_class_init (SwfdecPlayerManagerClass * g_class) g_object_class_install_property (object_class, PROP_SPEED, g_param_spec_double ("speed", "speed", "playback speed of movie", G_MINDOUBLE, 16.0, 1.0, G_PARAM_READWRITE)); - g_object_class_install_property (object_class, PROP_SPEED, + g_object_class_install_property (object_class, PROP_PLAYING, g_param_spec_boolean ("playing", "playing", "if the movie is played back", FALSE, G_PARAM_READWRITE)); + g_object_class_install_property (object_class, PROP_INTERRUPTED, + g_param_spec_boolean ("interrupted", "interrupted", "TRUE if we're handling a breakpoint", + FALSE, G_PARAM_READABLE)); signals[MESSAGE] = g_signal_new ("message", G_TYPE_FROM_CLASS (g_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT_POINTER, /* FIXME */ @@ -118,6 +125,8 @@ swfdec_player_manager_init (SwfdecPlayerManager *manager) manager->speed = 1.0; } +static void breakpoint_hit_cb (SwfdecDebugger *debugger, guint id, SwfdecPlayerManager *manager); + static void swfdec_player_manager_set_player (SwfdecPlayerManager *manager, SwfdecPlayer *player) { @@ -125,11 +134,13 @@ swfdec_player_manager_set_player (SwfdecPlayerManager *manager, SwfdecPlayer *pl return; if (manager->player) { + g_signal_handlers_disconnect_by_func (manager->player, breakpoint_hit_cb, manager); g_object_unref (manager->player); } manager->player = player; if (player) { g_object_ref (player); + g_signal_connect (player, "breakpoint", G_CALLBACK (breakpoint_hit_cb), manager); } } @@ -172,11 +183,24 @@ swfdec_player_manager_get_speed (SwfdecPlayerManager *manager) return manager->speed; } +gboolean +swfdec_player_manager_get_interrupted (SwfdecPlayerManager *manager) +{ + g_return_val_if_fail (SWFDEC_IS_PLAYER_MANAGER (manager), FALSE); + + return manager->interrupt_loop != NULL; +} + void swfdec_player_manager_set_playing (SwfdecPlayerManager *manager, gboolean playing) { g_return_if_fail (SWFDEC_IS_PLAYER_MANAGER (manager)); + if (swfdec_player_manager_get_interrupted (manager)) { + if (playing) + swfdec_player_manager_continue (manager); + return; + } if ((manager->source != NULL) == playing) return; if (playing) { @@ -203,10 +227,22 @@ swfdec_player_manager_get_playing (SwfdecPlayerManager *manager) void swfdec_player_manager_iterate (SwfdecPlayerManager *manager) { + g_return_if_fail (SWFDEC_IS_PLAYER_MANAGER (manager)); + g_return_if_fail (!swfdec_player_manager_get_interrupted (manager)); + swfdec_player_manager_set_playing (manager, FALSE); swfdec_player_iterate (manager->player); } +void +swfdec_player_manager_continue (SwfdecPlayerManager *manager) +{ + g_return_if_fail (SWFDEC_IS_PLAYER_MANAGER (manager)); + g_return_if_fail (swfdec_player_manager_get_interrupted (manager)); + + g_main_loop_quit (manager->interrupt_loop); +} + /*** command handling ***/ typedef enum { @@ -237,6 +273,22 @@ swfdec_player_manager_send_message (SwfdecPlayerManager *manager, swfdec_player_manager_send_message (manager, SWFDEC_MESSAGE_ERROR, __VA_ARGS__) static void +breakpoint_hit_cb (SwfdecDebugger *debugger, guint id, SwfdecPlayerManager *manager) +{ + gboolean was_playing = swfdec_player_manager_get_playing (manager); + + swfdec_player_manager_set_playing (manager, FALSE); + manager->interrupt_loop = g_main_loop_new (NULL, FALSE); + g_object_notify (G_OBJECT (manager), "interrupted"); + swfdec_player_manager_output (manager, "Breakpoint %u", id); + g_main_loop_run (manager->interrupt_loop); + g_main_loop_unref (manager->interrupt_loop); + manager->interrupt_loop = NULL; + g_object_notify (G_OBJECT (manager), "interrupted"); + swfdec_player_manager_set_playing (manager, was_playing); +} + +static void command_print (SwfdecPlayerManager *manager, const char *arg) { jsval rval; @@ -272,6 +324,15 @@ command_iterate (SwfdecPlayerManager *manager, const char *arg) } static void +command_continue (SwfdecPlayerManager *manager, const char *arg) +{ + if (swfdec_player_manager_get_interrupted (manager)) + swfdec_player_manager_continue (manager); + else + swfdec_player_manager_error (manager, "Not interrupted, cannot continue"); +} + +static void command_breakpoints (SwfdecPlayerManager *manager, const char *arg) { guint i, n, line; @@ -309,13 +370,14 @@ struct { void (* func) (SwfdecPlayerManager *manager, const char *arg); const char * description; } commands[] = { - { "help", command_help, "print all available commands and a quick description" }, - { "print", command_print, "evaluate the argument as a JavaScript script" }, - { "play", command_play, "play the movie" }, - { "stop", command_stop, "stop the movie" }, - { "iterate", command_iterate,"iterate the movie once" }, - { "breakpoints", command_breakpoints, "show all breakpoints" }, - { "delete", command_delete, "delete a breakpoint" }, + { "help", command_help, "print all available commands and a quick description" }, + { "print", command_print, "evaluate the argument as a JavaScript script" }, + { "play", command_play, "play the movie" }, + { "stop", command_stop, "stop the movie" }, + { "iterate", command_iterate, "iterate the movie once" }, + { "breakpoints", command_breakpoints, "show all breakpoints" }, + { "delete", command_delete, "delete a breakpoint" }, + { "continue", command_continue, "continue when stopped inside a breakpoint" }, }; static void diff --git a/player/swfdec_player_manager.h b/player/swfdec_player_manager.h index 228b565b..04495dfd 100644 --- a/player/swfdec_player_manager.h +++ b/player/swfdec_player_manager.h @@ -41,6 +41,7 @@ struct _SwfdecPlayerManager SwfdecPlayer * player; /* the video we play */ GSource * source; /* the source that is ticking */ double speed; /* speed of playback */ + GMainLoop * interrupt_loop; /* loop we run during an interruption */ }; struct _SwfdecPlayerManagerClass @@ -59,7 +60,9 @@ double swfdec_player_manager_get_speed (SwfdecPlayerManager * manager); void swfdec_player_manager_set_playing (SwfdecPlayerManager * manager, gboolean playing); gboolean swfdec_player_manager_get_playing (SwfdecPlayerManager * manager); +void swfdec_player_manager_continue (SwfdecPlayerManager * manager); void swfdec_player_manager_iterate (SwfdecPlayerManager * manager); +gboolean swfdec_player_manager_get_interrupted (SwfdecPlayerManager * manager); void swfdec_player_manager_execute (SwfdecPlayerManager * manager, const char * command); -- 2.11.4.GIT