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.
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
24 #include "swfdec_interaction.h"
26 static const GScannerConfig scanner_config
= {
28 (char *) G_CSET_a_2_z G_CSET_A_2_Z
,
29 (char *) G_CSET_a_2_z G_CSET_A_2_Z
,
32 FALSE
, TRUE
, FALSE
, TRUE
, TRUE
, FALSE
,
33 TRUE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
,
34 TRUE
, TRUE
, TRUE
, FALSE
, FALSE
,
35 FALSE
, TRUE
, FALSE
, FALSE
,
40 swfdec_interaction_free (SwfdecInteraction
*inter
)
42 g_return_if_fail (inter
!= NULL
);
44 g_array_free (inter
->commands
, TRUE
);
49 swfdec_interaction_reset (SwfdecInteraction
*inter
)
51 g_return_if_fail (inter
!= NULL
);
55 inter
->mouse_button
= 0;
57 inter
->time_elapsed
= 0;
61 swfdec_interaction_scanner_message (GScanner
*scanner
, gchar
*message
, gboolean error
)
64 g_printerr ("warning: %s\n", message
);
65 g_set_error (scanner
->user_data
, G_FILE_ERROR
, G_FILE_ERROR_FAILED
, "%s", message
);
69 swfdec_command_append_mouse (SwfdecInteraction
*inter
, SwfdecCommandType type
, int x
, int y
, int button
)
71 SwfdecCommand command
;
73 command
.command
= type
;
74 command
.args
.mouse
.x
= x
;
75 command
.args
.mouse
.y
= y
;
76 command
.args
.mouse
.button
= button
;
79 inter
->mouse_button
= button
;
80 g_array_append_val (inter
->commands
, command
);
84 swfdec_command_append_key (SwfdecInteraction
*inter
, SwfdecKey code
, guint ascii
, SwfdecCommandType type
)
86 SwfdecCommand command
;
88 command
.command
= type
;
89 command
.args
.key
.code
= code
;
90 command
.args
.key
.ascii
= ascii
;
91 g_array_append_val (inter
->commands
, command
);
95 swfdec_command_append_wait (SwfdecInteraction
*inter
, int msecs
)
97 SwfdecCommand command
;
99 command
.command
= SWFDEC_COMMAND_WAIT
;
100 command
.args
.time
= msecs
;
101 g_array_append_val (inter
->commands
, command
);
105 swfdec_interaction_new (const char *data
, guint length
, GError
**error
)
109 SwfdecInteraction
*inter
;
112 g_return_val_if_fail (data
!= NULL
|| length
== 0, NULL
);
115 scanner
= g_scanner_new (&scanner_config
);
116 scanner
->user_data
= error
;
117 scanner
->msg_handler
= swfdec_interaction_scanner_message
;
118 g_scanner_scope_add_symbol (scanner
, 0, "wait", GINT_TO_POINTER (SWFDEC_COMMAND_WAIT
));
119 g_scanner_scope_add_symbol (scanner
, 0, "move", GINT_TO_POINTER (SWFDEC_COMMAND_MOVE
));
120 g_scanner_scope_add_symbol (scanner
, 0, "down", GINT_TO_POINTER (SWFDEC_COMMAND_DOWN
));
121 g_scanner_scope_add_symbol (scanner
, 0, "up", GINT_TO_POINTER (SWFDEC_COMMAND_UP
));
122 g_scanner_scope_add_symbol (scanner
, 0, "press", GINT_TO_POINTER (SWFDEC_COMMAND_PRESS
));
123 g_scanner_scope_add_symbol (scanner
, 0, "release", GINT_TO_POINTER (SWFDEC_COMMAND_RELEASE
));
124 g_scanner_input_text (scanner
, data
, length
);
127 inter
= g_new0 (SwfdecInteraction
, 1);
128 inter
->commands
= g_array_new (FALSE
, FALSE
, sizeof (SwfdecCommand
));
130 while ((token
= g_scanner_get_next_token (scanner
)) != G_TOKEN_EOF
) {
131 switch ((SwfdecCommandType
)token
) {
132 case SWFDEC_COMMAND_WAIT
:
133 token
= g_scanner_get_next_token (scanner
);
134 if (token
!= G_TOKEN_INT
) {
135 g_scanner_unexp_token (scanner
, G_TOKEN_INT
, NULL
, NULL
, NULL
, NULL
, TRUE
);
138 i
= scanner
->value
.v_int
;
139 swfdec_command_append_wait (inter
, i
);
141 case SWFDEC_COMMAND_MOVE
:
142 token
= g_scanner_get_next_token (scanner
);
143 if (token
!= G_TOKEN_INT
) {
144 g_scanner_unexp_token (scanner
, G_TOKEN_INT
, NULL
, NULL
, NULL
, NULL
, TRUE
);
147 i
= scanner
->value
.v_int
;
148 token
= g_scanner_get_next_token (scanner
);
149 if (token
!= G_TOKEN_INT
) {
150 g_scanner_unexp_token (scanner
, G_TOKEN_INT
, NULL
, NULL
, NULL
, NULL
, TRUE
);
153 j
= scanner
->value
.v_int
;
154 swfdec_command_append_mouse (inter
, SWFDEC_COMMAND_MOVE
, i
, j
, inter
->mouse_button
);
156 case SWFDEC_COMMAND_DOWN
:
157 swfdec_command_append_mouse (inter
, SWFDEC_COMMAND_DOWN
, inter
->mouse_x
, inter
->mouse_y
, 1);
159 case SWFDEC_COMMAND_UP
:
160 swfdec_command_append_mouse (inter
, SWFDEC_COMMAND_UP
, inter
->mouse_x
, inter
->mouse_y
, 1);
162 case SWFDEC_COMMAND_PRESS
:
163 case SWFDEC_COMMAND_RELEASE
:
165 token
= g_scanner_get_next_token (scanner
);
166 if (token
!= G_TOKEN_INT
) {
167 g_scanner_unexp_token (scanner
, G_TOKEN_INT
, NULL
, NULL
, NULL
, NULL
, TRUE
);
170 i
= scanner
->value
.v_int
;
172 g_scanner_unexp_token (scanner
, G_TOKEN_INT
, NULL
, NULL
, NULL
, NULL
, TRUE
);
175 /* FIXME: allow string here and convert first char */
176 token
= g_scanner_get_next_token (scanner
);
177 if (token
!= G_TOKEN_INT
) {
178 g_scanner_unexp_token (scanner
, G_TOKEN_INT
, NULL
, NULL
, NULL
, NULL
, TRUE
);
181 swfdec_command_append_key (inter
, i
, scanner
->value
.v_int
, j
);
184 g_scanner_unexp_token (scanner
, SWFDEC_COMMAND_WAIT
, NULL
, NULL
, NULL
, NULL
, TRUE
);
188 swfdec_interaction_reset (inter
);
189 g_scanner_destroy (scanner
);
193 swfdec_interaction_free (inter
);
194 g_scanner_destroy (scanner
);
199 swfdec_interaction_new_from_file (const char *filename
, GError
**error
)
203 SwfdecInteraction
*ret
;
205 g_return_val_if_fail (filename
!= NULL
, NULL
);
207 if (!g_file_get_contents (filename
, &contents
, &length
, error
))
210 ret
= swfdec_interaction_new (contents
, length
, error
);
215 /* returns time until next event in msecs or -1 if none */
217 swfdec_interaction_get_next_event (SwfdecInteraction
*inter
)
219 SwfdecCommand
*command
;
221 g_return_val_if_fail (inter
!= NULL
, -1);
223 if (inter
->cur_idx
>= inter
->commands
->len
)
225 command
= &g_array_index (inter
->commands
, SwfdecCommand
, inter
->cur_idx
);
226 if (command
->command
!= SWFDEC_COMMAND_WAIT
)
228 g_assert (command
->args
.time
> inter
->time_elapsed
);
229 return command
->args
.time
- inter
->time_elapsed
;
233 swfdec_interaction_advance (SwfdecInteraction
*inter
, SwfdecPlayer
*player
, guint msecs
)
235 SwfdecCommand
*command
;
237 g_return_if_fail (inter
!= NULL
);
239 inter
->time_elapsed
+= msecs
;
240 while (inter
->cur_idx
< inter
->commands
->len
) {
241 command
= &g_array_index (inter
->commands
, SwfdecCommand
, inter
->cur_idx
);
242 switch (command
->command
) {
243 case SWFDEC_COMMAND_WAIT
:
244 if (inter
->time_elapsed
< command
->args
.time
)
246 inter
->time_elapsed
-= command
->args
.time
;
248 case SWFDEC_COMMAND_MOVE
:
249 swfdec_player_mouse_move (player
, command
->args
.mouse
.x
,
250 command
->args
.mouse
.y
);
252 case SWFDEC_COMMAND_PRESS
:
253 swfdec_player_key_press (player
, command
->args
.key
.code
, command
->args
.key
.ascii
);
255 case SWFDEC_COMMAND_RELEASE
:
256 swfdec_player_key_release (player
, command
->args
.key
.code
, command
->args
.key
.ascii
);
258 case SWFDEC_COMMAND_DOWN
:
259 swfdec_player_mouse_press (player
, command
->args
.mouse
.x
,
260 command
->args
.mouse
.y
, command
->args
.mouse
.button
);
262 case SWFDEC_COMMAND_UP
:
263 swfdec_player_mouse_release (player
, command
->args
.mouse
.x
,
264 command
->args
.mouse
.y
, command
->args
.mouse
.button
);
267 g_assert_not_reached ();
275 swfdec_interaction_get_duration (SwfdecInteraction
*inter
)
279 g_return_val_if_fail (inter
!= NULL
, 0);
282 for (i
= 0; i
< inter
->commands
->len
; i
++) {
283 SwfdecCommand
*command
= &g_array_index (inter
->commands
, SwfdecCommand
, i
);
284 if (command
->command
== SWFDEC_COMMAND_WAIT
)
285 duration
+= command
->args
.time
;