add "interrupted" and "quit" property
[swfdec.git] / vivified / core / vivi_application.c
blob624c9111b7eba7161ca7888caabfedf589da2827
1 /* Vivified
2 * Copyright (C) 2007 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include <libswfdec-gtk/swfdec-gtk.h>
25 #include "vivi_application.h"
26 #include "vivi_debugger.h"
27 #include "vivi_function.h"
28 #include "vivi_ming.h"
30 enum {
31 MESSAGE,
32 LAST_SIGNAL
35 enum {
36 PROP_0,
37 PROP_FILENAME,
38 PROP_PLAYER,
39 PROP_INTERRUPTED,
40 PROP_QUIT
43 G_DEFINE_TYPE (ViviApplication, vivi_application, SWFDEC_TYPE_AS_CONTEXT)
44 static guint signals[LAST_SIGNAL] = { 0, };
46 static void
47 vivi_application_get_property (GObject *object, guint param_id, GValue *value,
48 GParamSpec * pspec)
50 ViviApplication *app = VIVI_APPLICATION (object);
52 switch (param_id) {
53 case PROP_FILENAME:
54 g_value_set_string (value, app->filename);
55 break;
56 case PROP_PLAYER:
57 g_value_set_object (value, app->player);
58 break;
59 case PROP_INTERRUPTED:
60 g_value_set_boolean (value, app->loop != NULL);
61 break;
62 case PROP_QUIT:
63 g_value_set_boolean (value, app->playback_state == VIVI_APPLICATION_EXITING);
64 break;
65 default:
66 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
67 break;
71 static void
72 vivi_application_set_property (GObject *object, guint param_id, const GValue *value,
73 GParamSpec *pspec)
75 ViviApplication *app = VIVI_APPLICATION (object);
77 switch (param_id) {
78 case PROP_FILENAME:
79 vivi_application_set_filename (app, g_value_get_string (value));
80 break;
81 default:
82 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
83 break;
87 static void
88 vivi_application_dispose (GObject *object)
90 ViviApplication *app = VIVI_APPLICATION (object);
92 if (app->playback_state != VIVI_APPLICATION_EXITING)
93 vivi_application_quit (app);
95 g_object_unref (app->player);
96 g_hash_table_destroy (app->wraps);
98 G_OBJECT_CLASS (vivi_application_parent_class)->dispose (object);
101 static void
102 vivi_application_class_init (ViviApplicationClass *klass)
104 GObjectClass *object_class = G_OBJECT_CLASS (klass);
106 object_class->dispose = vivi_application_dispose;
107 object_class->get_property = vivi_application_get_property;
108 object_class->set_property = vivi_application_set_property;
110 g_object_class_install_property (object_class, PROP_FILENAME,
111 g_param_spec_string ("filename", "filename", "name of file to play",
112 NULL, G_PARAM_READWRITE));
113 g_object_class_install_property (object_class, PROP_PLAYER,
114 g_param_spec_object ("player", "player", "Flash player in use",
115 SWFDEC_TYPE_PLAYER, G_PARAM_READABLE));
116 g_object_class_install_property (object_class, PROP_INTERRUPTED,
117 g_param_spec_boolean ("interrupted", "interrupted", "TRUE if handling a breakpoint",
118 FALSE, G_PARAM_READABLE));
119 g_object_class_install_property (object_class, PROP_QUIT,
120 g_param_spec_boolean ("quit", "quit", "TRUE if application has been quit (no breakpoints will happen)",
121 FALSE, G_PARAM_READABLE));
123 signals[MESSAGE] = g_signal_new ("message", G_TYPE_FROM_CLASS (klass),
124 G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT_POINTER, /* FIXME */
125 G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_POINTER);
128 static void
129 vivi_application_init (ViviApplication *app)
131 app->debugger = g_object_new (VIVI_TYPE_DEBUGGER, NULL);
132 app->debugger->app = app;
133 app->player = swfdec_gtk_player_new (SWFDEC_AS_DEBUGGER (app->debugger));
135 app->wraps = g_hash_table_new (g_direct_hash, g_direct_equal);
138 ViviApplication *
139 vivi_application_new (void)
141 ViviApplication *app;
143 app = g_object_new (VIVI_TYPE_APPLICATION, NULL);
144 swfdec_as_context_startup (SWFDEC_AS_CONTEXT (app), 8);
145 vivi_function_init_context (app);
146 return app;
149 void
150 vivi_application_init_player (ViviApplication *app)
152 SwfdecLoader *loader;
154 g_return_if_fail (VIVI_IS_APPLICATION (app));
156 if (app->player_inited)
157 return;
159 if (app->filename == NULL) {
160 vivi_application_error (app, "no file set to play.");
161 return;
164 loader = swfdec_file_loader_new (app->filename);
165 swfdec_player_set_loader (app->player, loader);
166 app->player_inited = TRUE;
169 void
170 vivi_application_reset (ViviApplication *app)
172 g_return_if_fail (VIVI_IS_APPLICATION (app));
174 g_assert (app->loop == NULL); /* FIXME: what do we do if we're inside a breakpoint? */
175 g_object_unref (app->player);
176 app->player = swfdec_gtk_player_new (SWFDEC_AS_DEBUGGER (app->debugger));
177 app->player_inited = FALSE;
178 g_object_notify (G_OBJECT (app), "player");
181 void
182 vivi_application_set_filename (ViviApplication *app, const char *filename)
184 g_return_if_fail (VIVI_IS_APPLICATION (app));
185 g_return_if_fail (filename != NULL);
187 g_free (app->filename);
188 app->filename = g_strdup (filename);
189 vivi_application_reset (app);
190 g_object_notify (G_OBJECT (app), "filename");
193 const char *
194 vivi_application_get_filename (ViviApplication *app)
196 g_return_val_if_fail (VIVI_IS_APPLICATION (app), NULL);
198 return app->filename;
201 SwfdecPlayer *
202 vivi_application_get_player (ViviApplication *app)
204 g_return_val_if_fail (VIVI_IS_APPLICATION (app), NULL);
206 return app->player;
209 gboolean
210 vivi_application_get_interrupted (ViviApplication *app)
212 g_return_val_if_fail (VIVI_IS_APPLICATION (app), FALSE);
214 return app->loop != NULL;
217 gboolean
218 vivi_application_is_quit (ViviApplication *app)
220 g_return_val_if_fail (VIVI_IS_APPLICATION (app), FALSE);
222 return app->playback_state == VIVI_APPLICATION_EXITING;
225 static gboolean
226 vivi_application_step_forward (gpointer appp)
228 ViviApplication *app = appp;
229 guint next_event;
231 next_event = swfdec_player_get_next_event (app->player);
232 swfdec_player_advance (app->player, next_event);
234 return FALSE;
237 static void
238 vivi_application_check (ViviApplication *app)
240 gboolean is_playing, is_breakpoint;
242 /* if we're inside some script code, don't do anything */
243 if (swfdec_as_context_get_frame (SWFDEC_AS_CONTEXT (app)))
244 return;
246 is_playing = swfdec_gtk_player_get_playing (SWFDEC_GTK_PLAYER (app->player));
247 is_breakpoint = app->loop != NULL;
248 swfdec_as_context_maybe_gc (SWFDEC_AS_CONTEXT (app));
250 switch (app->playback_state) {
251 case VIVI_APPLICATION_EXITING:
252 if (is_playing)
253 swfdec_gtk_player_set_playing (SWFDEC_GTK_PLAYER (app->player), FALSE);
254 if (is_breakpoint)
255 g_main_loop_quit (app->loop);
256 break;
257 case VIVI_APPLICATION_STOPPED:
258 if (is_playing)
259 swfdec_gtk_player_set_playing (SWFDEC_GTK_PLAYER (app->player), FALSE);
260 break;
261 case VIVI_APPLICATION_PLAYING:
262 if (!is_playing)
263 swfdec_gtk_player_set_playing (SWFDEC_GTK_PLAYER (app->player), TRUE);
264 if (is_breakpoint)
265 g_main_loop_quit (app->loop);
266 break;
267 case VIVI_APPLICATION_STEPPING:
268 if (is_playing)
269 swfdec_gtk_player_set_playing (SWFDEC_GTK_PLAYER (app->player), FALSE);
270 if (is_breakpoint) {
271 g_main_loop_quit (app->loop);
272 } else {
273 /* FIXME: sanely handle this */
274 g_idle_add_full (-100, vivi_application_step_forward, app, NULL);
276 break;
277 default:
278 g_assert_not_reached ();
279 break;
283 void
284 vivi_application_execute (ViviApplication *app, const char *command)
286 SwfdecAsValue val;
287 SwfdecAsObject *object;
288 SwfdecScript *script;
289 char *error = NULL;
291 g_return_if_fail (VIVI_IS_APPLICATION (app));
292 g_return_if_fail (command != NULL);
294 vivi_application_input (app, command);
295 script = vivi_ming_compile (command, &error);
296 if (script == NULL) {
297 vivi_application_error (app, error);
298 g_free (error);
299 return;
301 object = SWFDEC_AS_CONTEXT (app)->global;
302 swfdec_as_object_get_variable (object,
303 swfdec_as_context_get_string (SWFDEC_AS_CONTEXT (app), "Commands"),
304 &val);
305 if (SWFDEC_AS_VALUE_IS_OBJECT (&val))
306 object = SWFDEC_AS_VALUE_GET_OBJECT (&val);
307 swfdec_as_object_run (object, script);
308 swfdec_script_unref (script);
309 vivi_application_check (app);
312 void
313 vivi_application_send_message (ViviApplication *app,
314 ViviMessageType type, const char *format, ...)
316 va_list args;
317 char *msg;
319 g_return_if_fail (VIVI_IS_APPLICATION (app));
320 g_return_if_fail (format != NULL);
322 va_start (args, format);
323 msg = g_strdup_vprintf (format, args);
324 va_end (args);
325 g_signal_emit (app, signals[MESSAGE], 0, (guint) type, msg);
326 g_free (msg);
329 void
330 vivi_application_play (ViviApplication *app)
332 g_return_if_fail (VIVI_IS_APPLICATION (app));
334 if (app->playback_state == VIVI_APPLICATION_EXITING)
335 return;
336 app->playback_state = VIVI_APPLICATION_PLAYING;
337 app->playback_count = 1;
338 vivi_application_check (app);
341 void
342 vivi_application_stop (ViviApplication *app)
344 g_return_if_fail (VIVI_IS_APPLICATION (app));
346 if (app->playback_state == VIVI_APPLICATION_EXITING)
347 return;
348 app->playback_state = VIVI_APPLICATION_STOPPED;
349 app->playback_count = 0;
350 vivi_application_check (app);
353 void
354 vivi_application_step (ViviApplication *app, guint n_times)
356 g_return_if_fail (VIVI_IS_APPLICATION (app));
358 if (app->playback_state == VIVI_APPLICATION_EXITING)
359 return;
360 app->playback_state = VIVI_APPLICATION_STEPPING;
361 app->playback_count = n_times;
362 vivi_application_check (app);
365 void
366 vivi_application_quit (ViviApplication *app)
368 g_return_if_fail (VIVI_IS_APPLICATION (app));
370 if (app->playback_state == VIVI_APPLICATION_EXITING)
371 return;
372 app->playback_state = VIVI_APPLICATION_EXITING;
373 app->playback_count = 1;
374 g_object_notify (G_OBJECT (app), "quit");
375 vivi_application_check (app);