2 * Copyright (C) 2006-2008 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
29 #include "swfdec_player_internal.h"
30 #include "swfdec_as_frame_internal.h"
31 #include "swfdec_as_internal.h"
32 #include "swfdec_as_strings.h"
33 #include "swfdec_audio_internal.h"
34 #include "swfdec_button_movie.h" /* for mouse cursor */
35 #include "swfdec_cache.h"
36 #include "swfdec_debug.h"
37 #include "swfdec_enums.h"
38 #include "swfdec_event.h"
39 #include "swfdec_filter.h"
40 #include "swfdec_internal.h"
41 #include "swfdec_loader_internal.h"
42 #include "swfdec_marshal.h"
43 #include "swfdec_movie.h"
44 #include "swfdec_renderer_internal.h"
45 #include "swfdec_resource.h"
46 #include "swfdec_sandbox.h"
47 #include "swfdec_script_internal.h"
48 #include "swfdec_sprite_movie.h"
49 #include "swfdec_text_field_movie.h"
50 #include "swfdec_utils.h"
55 * SECTION:SwfdecPlayer
56 * @title: SwfdecPlayer
57 * @short_description: main playback object
59 * A #SwfdecPlayer is the main object used for playing back Flash files through
62 * A player interacts with the outside world in a multitude of ways. The most
63 * important ones are described below.
65 * Input is handled via the
66 * <link linkend="swfdec-SwfdecLoader">SwfdecLoader</link> class. A
67 * #SwfdecLoader is set on a new player using swfdec_player_set_loader().
69 * When the loader has provided enough data, you can start playing the file.
70 * This is done in steps by calling swfdec_player_advance() - preferrably as
71 * often as swfdec_player_get_next_event() indicates. Or you can provide user input
72 * to the player by calling for example swfdec_player_handle_mouse().
74 * You can use swfdec_player_render() to draw the current state of the player.
75 * After that, connect to the SwfdecPlayer:invalidate signal to be notified of
78 * Audio output is handled via the
79 * <link linkend="swfdec-SwfdecAudio">SwfdecAudio</link> class. One
80 * #SwfdecAudio object is created for every output using the
81 * SwfdecPlayer::audio-added signal.
87 * This is the base object used for playing Flash files.
91 * SECTION:Enumerations
92 * @title: Enumerations
93 * @short_description: enumerations used in Swfdec
95 * This file lists all of the enumerations used in various parts of Swfdec.
100 * @SWFDEC_MOUSE_CURSOR_NORMAL: a normal mouse cursor
101 * @SWFDEC_MOUSE_CURSOR_NONE: no mouse image
102 * @SWFDEC_MOUSE_CURSOR_TEXT: a mouse cursor suitable for text editing
103 * @SWFDEC_MOUSE_CURSOR_CLICK: a mouse cursor for clicking a hyperlink or a
106 * This enumeration describes the possible types for the SwfdecPlayer::mouse-cursor
112 * @SWFDEC_ALIGNMENT_TOP_LEFT: top left
113 * @SWFDEC_ALIGNMENT_TOP: top
114 * @SWFDEC_ALIGNMENT_TOP_RIGHT: top right
115 * @SWFDEC_ALIGNMENT_LEFT: left
116 * @SWFDEC_ALIGNMENT_CENTER: center
117 * @SWFDEC_ALIGNMENT_RIGHT: right
118 * @SWFDEC_ALIGNMENT_BOTTOM_LEFT: left
119 * @SWFDEC_ALIGNMENT_BOTTOM: bottom
120 * @SWFDEC_ALIGNMENT_BOTTOM_RIGHT: bottom right
122 * These are the possible values for the alignment of an unscaled movie.
127 * @SWFDEC_SCALE_SHOW_ALL: Show the whole content as large as possible
128 * @SWFDEC_SCALE_NO_BORDER: Fill the whole area, possibly cropping parts
129 * @SWFDEC_SCALE_EXACT_FIT: Fill the whole area, don't keep aspect ratio
130 * @SWFDEC_SCALE_NONE: Do not scale the movie at all
132 * Describes how the movie should be scaled if the given size doesn't equal the
138 * @SWFDEC_KEY_LEFT_MOUSE: the left mouse button
139 * @SWFDEC_KEY_RIGHT_MOUSE: the left mouse button
140 * @SWFDEC_KEY_MIDDLE_MOUSE: the middle mouse button
141 * @SWFDEC_KEY_BACKSPACE: the backspace key
142 * @SWFDEC_KEY_TAB: the tab key
143 * @SWFDEC_KEY_CLEAR: the clear key
144 * @SWFDEC_KEY_ENTER: the enter key
145 * @SWFDEC_KEY_SHIFT: the shift key
146 * @SWFDEC_KEY_CONTROL: the control key
147 * @SWFDEC_KEY_ALT: the alt key
148 * @SWFDEC_KEY_CAPS_LOCK: the caps lock key
149 * @SWFDEC_KEY_ESCAPE: the escape key
150 * @SWFDEC_KEY_SPACE: the space key
151 * @SWFDEC_KEY_PAGE_UP: the page up key
152 * @SWFDEC_KEY_PAGE_DOWN: the page down key
153 * @SWFDEC_KEY_END: the end key
154 * @SWFDEC_KEY_HOME: the home key
155 * @SWFDEC_KEY_LEFT: the left key
156 * @SWFDEC_KEY_UP: the up key
157 * @SWFDEC_KEY_RIGHT: the right key
158 * @SWFDEC_KEY_DOWN: the down key
159 * @SWFDEC_KEY_INSERT: the insert key
160 * @SWFDEC_KEY_DELETE: the delete key
161 * @SWFDEC_KEY_HELP: the help key
162 * @SWFDEC_KEY_0: the 0 key
163 * @SWFDEC_KEY_1: the 1 key
164 * @SWFDEC_KEY_2: the 2 key
165 * @SWFDEC_KEY_3: the 3 key
166 * @SWFDEC_KEY_4: the 4 key
167 * @SWFDEC_KEY_5: the 5 key
168 * @SWFDEC_KEY_6: the 6 key
169 * @SWFDEC_KEY_7: the 7 key
170 * @SWFDEC_KEY_8: the 8 key
171 * @SWFDEC_KEY_9: the 9 key
172 * @SWFDEC_KEY_A: the ! key
173 * @SWFDEC_KEY_B: the B key
174 * @SWFDEC_KEY_C: the C key
175 * @SWFDEC_KEY_D: the D key
176 * @SWFDEC_KEY_E: the E key
177 * @SWFDEC_KEY_F: the F key
178 * @SWFDEC_KEY_G: the G key
179 * @SWFDEC_KEY_H: the H key
180 * @SWFDEC_KEY_I: the I key
181 * @SWFDEC_KEY_J: the J key
182 * @SWFDEC_KEY_K: the K key
183 * @SWFDEC_KEY_L: the L key
184 * @SWFDEC_KEY_M: the M key
185 * @SWFDEC_KEY_N: the N key
186 * @SWFDEC_KEY_O: the O key
187 * @SWFDEC_KEY_P: the P key
188 * @SWFDEC_KEY_Q: the Q key
189 * @SWFDEC_KEY_R: the R key
190 * @SWFDEC_KEY_S: the S key
191 * @SWFDEC_KEY_T: the T key
192 * @SWFDEC_KEY_U: the U key
193 * @SWFDEC_KEY_V: the V key
194 * @SWFDEC_KEY_W: the W key
195 * @SWFDEC_KEY_X: the X key
196 * @SWFDEC_KEY_Y: the Y key
197 * @SWFDEC_KEY_Z: the Z key
198 * @SWFDEC_KEY_NUMPAD_0: the 0 key on the numeric keypad
199 * @SWFDEC_KEY_NUMPAD_1: the 1 key on the numeric keypad
200 * @SWFDEC_KEY_NUMPAD_2: the 2 key on the numeric keypad
201 * @SWFDEC_KEY_NUMPAD_3: the 3 key on the numeric keypad
202 * @SWFDEC_KEY_NUMPAD_4: the 4 key on the numeric keypad
203 * @SWFDEC_KEY_NUMPAD_5: the 5 key on the numeric keypad
204 * @SWFDEC_KEY_NUMPAD_6: the 6 key on the numeric keypad
205 * @SWFDEC_KEY_NUMPAD_7: the 7 key on the numeric keypad
206 * @SWFDEC_KEY_NUMPAD_8: the 8 key on the numeric keypad
207 * @SWFDEC_KEY_NUMPAD_9: the 9 key on the numeric keypad
208 * @SWFDEC_KEY_NUMPAD_MULTIPLY: the multiply key on the numeric keypad
209 * @SWFDEC_KEY_NUMPAD_ADD: the add key on the numeric keypad
210 * @SWFDEC_KEY_NUMPAD_SUBTRACT: the subtract key on the numeric keypad
211 * @SWFDEC_KEY_NUMPAD_DECIMAL: the decimal key on the numeric keypad
212 * @SWFDEC_KEY_NUMPAD_DIVIDE: the divide key on the numeric keypad
213 * @SWFDEC_KEY_F1: the F1 key
214 * @SWFDEC_KEY_F2: the F2 key
215 * @SWFDEC_KEY_F3: the F3 key
216 * @SWFDEC_KEY_F4: the F4 key
217 * @SWFDEC_KEY_F5: the F5 key
218 * @SWFDEC_KEY_F6: the F6 key
219 * @SWFDEC_KEY_F7: the F7 key
220 * @SWFDEC_KEY_F8: the F8 key
221 * @SWFDEC_KEY_F9: the F9 key
222 * @SWFDEC_KEY_F10: the F10 key
223 * @SWFDEC_KEY_F11: the F11 key
224 * @SWFDEC_KEY_F12: the F12 key
225 * @SWFDEC_KEY_F13: the F13 key
226 * @SWFDEC_KEY_F14: the F14 key
227 * @SWFDEC_KEY_F15: the F15 key
228 * @SWFDEC_KEY_NUM_LOCK: the num lock key
229 * @SWFDEC_KEY_SCROLL_LOCK: the scroll lock key
230 * @SWFDEC_KEY_SEMICOLON: the semicolon key (on English keyboards)
231 * @SWFDEC_KEY_EQUAL: the equal key (on English keyboards)
232 * @SWFDEC_KEY_COMMA: the comma key (on English keyboards)
233 * @SWFDEC_KEY_MINUS: the minus key (on English keyboards)
234 * @SWFDEC_KEY_DOT: the dot key (on English keyboards)
235 * @SWFDEC_KEY_SLASH: the slash key (on English keyboards)
236 * @SWFDEC_KEY_GRAVE: the grave key (on English keyboards)
237 * @SWFDEC_KEY_LEFT_BRACKET: the left bracket key (on English keyboards)
238 * @SWFDEC_KEY_BACKSLASH: the backslash key (on English keyboards)
239 * @SWFDEC_KEY_RIGHT_BRACKET: the right bracket key (on English keyboards)
240 * @SWFDEC_KEY_APOSTROPHE: the apostrophe key (on English keyboards)
242 * Lists all known key codes in Swfdec and their meanings on an English
243 * keyboard. Note that key codes in Flash represent virtual key codes as used
244 * in Microsoft Windows.
247 /*** timeval type mapping ***/
250 * SWFDEC_TYPE_TIME_VAL:
252 * This type wraps a @GTimeVal object as a boxed type and makes it available
253 * for use in object properties.
256 swfdec_time_val_copy (gpointer boxed
)
258 return g_memdup (boxed
, sizeof (GTimeVal
));
262 swfdec_time_val_get_type (void)
264 static GType type
= 0;
267 type
= g_boxed_type_register_static ("SwfdecTimeVal",
268 swfdec_time_val_copy
, g_free
);
277 swfdec_player_get_next_event_time (SwfdecPlayer
*player
)
279 SwfdecPlayerPrivate
*priv
= player
->priv
;
281 if (priv
->timeouts
) {
282 SwfdecTick next
= ((SwfdecTimeout
*) priv
->timeouts
->data
)->timestamp
;
283 /* This can happen because advancing only uses millisecond granularity */
284 if (next
< priv
->time
)
287 return next
- priv
->time
;
294 * swfdec_player_add_timeout:
295 * @player: a #SwfdecPlayer
296 * @timeout: timeout to add
298 * Adds a timeout to @player. The timeout will be removed automatically when
299 * triggered, so you need to use swfdec_player_add_timeout() to add it again.
300 * The #SwfdecTimeout struct and callback does not use a data callback pointer.
301 * It's suggested that you use the struct as part of your own bigger struct
302 * and get it back like this:
306 * SwfdecTimeout timeout;
310 * my_struct_timeout_callback (SwfdecTimeout *timeout)
312 * MyStruct *mystruct = (MyStruct *) ((void *) timeout - G_STRUCT_OFFSET (MyStruct, timeout));
319 swfdec_player_add_timeout (SwfdecPlayer
*player
, SwfdecTimeout
*timeout
)
321 SwfdecPlayerPrivate
*priv
;
323 SwfdecTick next_tick
;
325 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
326 g_return_if_fail (timeout
!= NULL
);
327 g_return_if_fail (timeout
->timestamp
>= player
->priv
->time
);
328 g_return_if_fail (timeout
->callback
!= NULL
);
331 SWFDEC_LOG ("adding timeout %p in %"G_GUINT64_FORMAT
" msecs", timeout
,
332 SWFDEC_TICKS_TO_MSECS (timeout
->timestamp
- priv
->time
));
333 next_tick
= swfdec_player_get_next_event_time (player
);
334 /* the order is important, on events with the same time, we make sure the new one is last */
335 for (walk
= priv
->timeouts
; walk
; walk
= walk
->next
) {
336 SwfdecTimeout
*cur
= walk
->data
;
337 if (cur
->timestamp
> timeout
->timestamp
)
340 priv
->timeouts
= g_list_insert_before (priv
->timeouts
, walk
, timeout
);
341 if (next_tick
!= swfdec_player_get_next_event_time (player
))
342 g_object_notify (G_OBJECT (player
), "next-event");
346 * swfdec_player_remove_timeout:
347 * @player: a #SwfdecPlayer
348 * @timeout: a timeout that should be removed
350 * Removes the @timeout from the list of scheduled timeouts. The timeout must
351 * have been added with swfdec_player_add_timeout() before.
354 swfdec_player_remove_timeout (SwfdecPlayer
*player
, SwfdecTimeout
*timeout
)
356 SwfdecPlayerPrivate
*priv
;
357 SwfdecTick next_tick
;
359 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
360 g_return_if_fail (timeout
!= NULL
);
361 /* FIXME: can't use that due to rounding issues */
362 //g_return_if_fail (timeout->timestamp >= player->priv->time);
363 g_return_if_fail (timeout
->callback
!= NULL
);
365 SWFDEC_LOG ("removing timeout %p", timeout
);
367 next_tick
= swfdec_player_get_next_event_time (player
);
368 priv
->timeouts
= g_list_remove (priv
->timeouts
, timeout
);
369 if (next_tick
!= swfdec_player_get_next_event_time (player
))
370 g_object_notify (G_OBJECT (player
), "next-event");
376 SwfdecActor
* actor
; /* the actor to trigger the action on */
377 SwfdecScript
* script
; /* script to execute or NULL to trigger action */
378 SwfdecEventType event
; /* the action to trigger */
380 } SwfdecPlayerAction
;
384 SwfdecActionFunc func
;
386 } SwfdecPlayerExternalAction
;
389 swfdec_player_compress_actions (SwfdecRingBuffer
*buffer
)
391 SwfdecPlayerAction
*action
, tmp
;
394 for (i
= swfdec_ring_buffer_get_n_elements (buffer
); i
> 0; i
--) {
395 action
= swfdec_ring_buffer_pop (buffer
);
397 if (action
->actor
== NULL
)
400 action
= swfdec_ring_buffer_push (buffer
);
403 SWFDEC_INFO ("compresed action queue to %u elements",
404 swfdec_ring_buffer_get_n_elements (buffer
));
405 for (i
= 0; i
< swfdec_ring_buffer_get_n_elements (buffer
); i
++) {
406 action
= swfdec_ring_buffer_peek_nth (buffer
, i
);
407 g_assert (action
->actor
!= NULL
);
412 swfdec_player_do_add_action (SwfdecPlayer
*player
, guint importance
, SwfdecPlayerAction
*act
)
414 SwfdecPlayerPrivate
*priv
= player
->priv
;
415 SwfdecPlayerAction
*action
= swfdec_ring_buffer_push (priv
->actions
[importance
]);
416 if (action
== NULL
) {
417 /* try to get rid of freed actions */
418 swfdec_player_compress_actions (priv
->actions
[importance
]);
419 action
= swfdec_ring_buffer_push (priv
->actions
[importance
]);
420 if (action
== NULL
) {
421 if (swfdec_ring_buffer_get_size (priv
->actions
[importance
]) == 256) {
422 SWFDEC_WARNING ("256 levels of recursion were exceeded in one action list.");
424 swfdec_ring_buffer_set_size (priv
->actions
[importance
],
425 swfdec_ring_buffer_get_size (priv
->actions
[importance
]) + 16);
426 action
= swfdec_ring_buffer_push (priv
->actions
[importance
]);
434 * swfdec_player_add_event:
435 * @player: a #SwfdecPlayer
436 * @movie: the movie on which to trigger the event
437 * @type: type of the event
438 * @type: key of the event
439 * @importance: importance of the event
441 * Adds an action to the @player. Actions are used by Flash player to solve
442 * reentrancy issues. Instead of calling back into the Actionscript engine,
443 * an action is queued for later execution. So if you're writing code that
444 * is calling Actionscript code, you want to do this by using actions.
447 swfdec_player_add_action (SwfdecPlayer
*player
, SwfdecActor
*actor
,
448 SwfdecEventType type
, guint8 key
, guint importance
)
450 SwfdecPlayerAction action
= { actor
, NULL
, type
, key
};
452 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
453 g_return_if_fail (SWFDEC_IS_ACTOR (actor
));
454 g_return_if_fail (importance
< SWFDEC_PLAYER_N_ACTION_QUEUES
);
456 SWFDEC_LOG ("adding action %s %u", SWFDEC_MOVIE (actor
)->name
, type
);
457 swfdec_player_do_add_action (player
, importance
, &action
);
461 swfdec_player_add_action_script (SwfdecPlayer
*player
, SwfdecActor
*actor
,
462 SwfdecScript
*script
, guint importance
)
464 SwfdecPlayerAction action
= { actor
, script
, 0 };
466 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
467 g_return_if_fail (SWFDEC_IS_ACTOR (actor
));
468 g_return_if_fail (script
!= NULL
);
469 g_return_if_fail (importance
< SWFDEC_PLAYER_N_ACTION_QUEUES
);
471 SWFDEC_LOG ("adding action script %s %s", SWFDEC_MOVIE (actor
)->name
, script
->name
);
472 swfdec_player_do_add_action (player
, importance
, &action
);
476 * swfdec_player_remove_all_actions:
477 * @player: a #SwfdecPlayer
478 * @movie: movie pointer identifying the actions to be removed
480 * Removes all actions associated with @movie that have not yet been executed.
481 * See swfdec_player_add_action() for details about actions.
484 swfdec_player_remove_all_actions (SwfdecPlayer
*player
, SwfdecActor
*actor
)
486 SwfdecPlayerAction
*action
;
487 SwfdecPlayerPrivate
*priv
;
490 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
491 g_return_if_fail (SWFDEC_IS_ACTOR (actor
));
494 for (i
= 0; i
< SWFDEC_PLAYER_N_ACTION_QUEUES
; i
++) {
495 for (j
= 0; j
< swfdec_ring_buffer_get_n_elements (priv
->actions
[i
]); j
++) {
496 action
= swfdec_ring_buffer_peek_nth (priv
->actions
[i
], j
);
498 if (action
->actor
== actor
) {
499 SWFDEC_LOG ("removing action %p %u",
500 action
->actor
, action
->event
);
501 action
->actor
= NULL
;
508 swfdec_player_do_action (SwfdecPlayer
*player
)
510 SwfdecPlayerAction
*action
;
511 SwfdecPlayerPrivate
*priv
;
515 for (i
= 0; i
< SWFDEC_PLAYER_N_ACTION_QUEUES
; i
++) {
517 action
= swfdec_ring_buffer_pop (priv
->actions
[i
]);
520 } while (action
->actor
== NULL
); /* skip removed actions */
522 if (action
->script
) {
523 SwfdecSandbox
*sandbox
= SWFDEC_MOVIE (action
->actor
)->resource
->sandbox
;
524 SwfdecAsObject
*object
= swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (action
->actor
));
525 swfdec_sandbox_use (sandbox
);
526 swfdec_as_object_run (object
, action
->script
);
527 swfdec_sandbox_unuse (sandbox
);
529 swfdec_actor_execute (action
->actor
, action
->event
, action
->key
);
539 swfdec_player_perform_external_actions (SwfdecPlayer
*player
)
541 SwfdecPlayerExternalAction
*action
;
542 SwfdecPlayerPrivate
*priv
= player
->priv
;
545 /* remove timeout if it exists - do this before executing stuff below */
546 if (priv
->external_timeout
.callback
) {
547 swfdec_player_remove_timeout (player
, &priv
->external_timeout
);
548 priv
->external_timeout
.callback
= NULL
;
551 /* we need to query the number of current actions so newly added ones aren't
552 * executed in here */
553 for (i
= swfdec_ring_buffer_get_n_elements (priv
->external_actions
); i
> 0; i
--) {
554 action
= swfdec_ring_buffer_pop (priv
->external_actions
);
555 g_assert (action
!= NULL
);
556 /* skip removed actions */
557 if (action
->object
== NULL
)
559 action
->func (action
->object
, action
->data
);
560 swfdec_player_perform_actions (player
);
565 swfdec_player_trigger_external_actions (SwfdecTimeout
*advance
)
567 SwfdecPlayerPrivate
*priv
= (SwfdecPlayerPrivate
*) ((void *) ((guint8
*) advance
- G_STRUCT_OFFSET (SwfdecPlayerPrivate
, external_timeout
)));
569 priv
->external_timeout
.callback
= NULL
;
570 swfdec_player_perform_external_actions (priv
->player
);
574 swfdec_player_add_external_action (SwfdecPlayer
*player
, gpointer object
,
575 SwfdecActionFunc action_func
, gpointer action_data
)
577 SwfdecPlayerExternalAction
*action
;
578 SwfdecPlayerPrivate
*priv
;
580 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
581 g_return_if_fail (object
!= NULL
);
582 g_return_if_fail (action_func
!= NULL
);
584 SWFDEC_LOG ("adding external action %p %p %p", object
, action_func
, action_data
);
586 action
= swfdec_ring_buffer_push (priv
->external_actions
);
587 if (action
== NULL
) {
588 /* FIXME: limit number of actions to not get inf loops due to scripts? */
589 swfdec_ring_buffer_set_size (priv
->external_actions
,
590 swfdec_ring_buffer_get_size (priv
->external_actions
) + 16);
591 action
= swfdec_ring_buffer_push (priv
->external_actions
);
594 action
->object
= object
;
595 action
->func
= action_func
;
596 action
->data
= action_data
;
597 if (!priv
->external_timeout
.callback
) {
598 /* trigger execution immediately.
599 * But if initialized, keep at least 100ms from when the last external
600 * timeout triggered. This is a crude method to get around infinite loops
601 * when script actions executed by external actions trigger another external
602 * action that would execute instantly.
604 if (priv
->initialized
) {
605 priv
->external_timeout
.timestamp
= MAX (priv
->time
,
606 priv
->external_timeout
.timestamp
+ SWFDEC_MSECS_TO_TICKS (100));
608 priv
->external_timeout
.timestamp
= priv
->time
;
610 priv
->external_timeout
.callback
= swfdec_player_trigger_external_actions
;
611 swfdec_player_add_timeout (player
, &priv
->external_timeout
);
616 swfdec_player_remove_all_external_actions (SwfdecPlayer
*player
, gpointer object
)
618 SwfdecPlayerExternalAction
*action
;
619 SwfdecPlayerPrivate
*priv
;
622 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
623 g_return_if_fail (object
!= NULL
);
626 for (i
= 0; i
< swfdec_ring_buffer_get_n_elements (priv
->external_actions
); i
++) {
627 action
= swfdec_ring_buffer_peek_nth (priv
->external_actions
, i
);
629 if (action
->object
== object
) {
630 SWFDEC_LOG ("removing external action %p %p %p",
631 action
->object
, action
->func
, action
->data
);
632 action
->object
= NULL
;
637 /*** SwfdecPlayer ***/
653 static guint signals
[LAST_SIGNAL
] = { 0, };
664 PROP_BACKGROUND_COLOR
,
681 PROP_ALLOW_FULLSCREEN
,
685 G_DEFINE_TYPE (SwfdecPlayer
, swfdec_player
, SWFDEC_TYPE_AS_CONTEXT
)
688 swfdec_player_alignment_to_flags (SwfdecAlignment alignment
)
690 static const guint align_flags
[9] = {
691 SWFDEC_ALIGN_FLAG_TOP
| SWFDEC_ALIGN_FLAG_LEFT
,
692 SWFDEC_ALIGN_FLAG_TOP
,
693 SWFDEC_ALIGN_FLAG_TOP
| SWFDEC_ALIGN_FLAG_RIGHT
,
694 SWFDEC_ALIGN_FLAG_LEFT
,
696 SWFDEC_ALIGN_FLAG_RIGHT
,
697 SWFDEC_ALIGN_FLAG_BOTTOM
| SWFDEC_ALIGN_FLAG_LEFT
,
698 SWFDEC_ALIGN_FLAG_BOTTOM
,
699 SWFDEC_ALIGN_FLAG_BOTTOM
| SWFDEC_ALIGN_FLAG_RIGHT
701 return align_flags
[alignment
];
704 static SwfdecAlignment
705 swfdec_player_alignment_from_flags (guint flags
)
707 if (flags
& SWFDEC_ALIGN_FLAG_TOP
) {
708 if (flags
& SWFDEC_ALIGN_FLAG_LEFT
) {
709 return SWFDEC_ALIGNMENT_TOP_LEFT
;
710 } else if (flags
& SWFDEC_ALIGN_FLAG_RIGHT
) {
711 return SWFDEC_ALIGNMENT_TOP_RIGHT
;
713 return SWFDEC_ALIGNMENT_TOP
;
715 } else if (flags
& SWFDEC_ALIGN_FLAG_BOTTOM
) {
716 if (flags
& SWFDEC_ALIGN_FLAG_LEFT
) {
717 return SWFDEC_ALIGNMENT_BOTTOM_LEFT
;
718 } else if (flags
& SWFDEC_ALIGN_FLAG_RIGHT
) {
719 return SWFDEC_ALIGNMENT_BOTTOM_RIGHT
;
721 return SWFDEC_ALIGNMENT_BOTTOM
;
724 if (flags
& SWFDEC_ALIGN_FLAG_LEFT
) {
725 return SWFDEC_ALIGNMENT_LEFT
;
726 } else if (flags
& SWFDEC_ALIGN_FLAG_RIGHT
) {
727 return SWFDEC_ALIGNMENT_RIGHT
;
729 return SWFDEC_ALIGNMENT_CENTER
;
735 swfdec_player_get_property (GObject
*object
, guint param_id
, GValue
*value
,
738 SwfdecPlayer
*player
= SWFDEC_PLAYER (object
);
739 SwfdecPlayerPrivate
*priv
= player
->priv
;
742 case PROP_CACHE_SIZE
:
743 g_value_set_ulong (value
, swfdec_cache_get_max_cache_size (priv
->cache
));
745 case PROP_INITIALIZED
:
746 g_value_set_boolean (value
, swfdec_player_is_initialized (player
));
748 case PROP_DEFAULT_WIDTH
:
749 g_value_set_uint (value
, priv
->width
);
751 case PROP_DEFAULT_HEIGHT
:
752 g_value_set_uint (value
, priv
->height
);
755 g_value_set_double (value
, priv
->rate
/ 256.0);
757 case PROP_MOUSE_CURSOR
:
758 g_value_set_enum (value
, priv
->mouse_cursor
);
760 case PROP_NEXT_EVENT
:
761 g_value_set_uint (value
, swfdec_player_get_next_event (player
));
763 case PROP_BACKGROUND_COLOR
:
764 g_value_set_uint (value
, priv
->bgcolor
? priv
->bgcolor
: SWFDEC_COLOR_WHITE
);
767 g_value_set_int (value
, priv
->stage_width
);
770 g_value_set_int (value
, priv
->stage_height
);
773 g_value_set_enum (value
, swfdec_player_alignment_from_flags (priv
->align_flags
));
776 g_value_set_enum (value
, priv
->scale_mode
);
779 g_value_set_object (value
, priv
->scripting
);
782 g_value_set_object (value
, priv
->system
);
784 case PROP_MAX_RUNTIME
:
785 g_value_set_ulong (value
, priv
->max_runtime
);
787 case PROP_LOADER_TYPE
:
788 g_value_set_gtype (value
, priv
->loader_type
);
790 case PROP_SOCKET_TYPE
:
791 g_value_set_gtype (value
, priv
->socket_type
);
794 g_value_set_boxed (value
, priv
->url
);
797 g_value_set_boxed (value
, priv
->base_url
);
800 g_value_set_string (value
, priv
->variables
);
803 g_value_set_boolean (value
, priv
->has_focus
);
806 g_value_set_object (value
, priv
->renderer
);
808 case PROP_FULLSCREEN
:
809 g_value_set_boolean (value
, priv
->fullscreen
);
811 case PROP_ALLOW_FULLSCREEN
:
812 g_value_set_boolean (value
, priv
->allow_fullscreen
);
815 g_value_set_string (value
, priv
->selection
);
818 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
824 swfdec_player_emit_signals (SwfdecPlayer
*player
)
826 SwfdecPlayerPrivate
*priv
= player
->priv
;
829 /* emit invalidate signal */
830 if (priv
->invalidations
->len
!= 0) {
831 g_signal_emit (player
, signals
[INVALIDATE
], 0,
832 priv
->invalidations
->data
, priv
->invalidations
->len
);
833 g_array_set_size (priv
->invalidations
, 0);
836 /* emit audio-added for all added audio streams */
837 for (walk
= priv
->audio
; walk
; walk
= walk
->next
) {
838 SwfdecAudio
*audio
= walk
->data
;
840 swfdec_audio_update_matrix (audio
);
842 g_signal_emit (player
, signals
[AUDIO_ADDED
], 0, audio
);
847 /* emit missing-plugin signal for newly discovered plugins */
848 if (priv
->missing_plugins
) {
850 guint i
= 0, n_plugins
= g_slist_length (priv
->missing_plugins
);
851 char **details
= g_new (char *, n_plugins
+ 1);
853 for (swalk
= priv
->missing_plugins
; swalk
; swalk
= swalk
->next
) {
854 details
[i
++] = swalk
->data
;
857 g_slist_free (priv
->missing_plugins
);
858 priv
->missing_plugins
= NULL
;
859 SWFDEC_INFO ("emitting missing plugins signal for %u plugins", n_plugins
);
860 g_signal_emit (player
, signals
[MISSING_PLUGINS
], 0, details
);
861 g_strfreev (details
);
866 swfdec_player_update_scale (SwfdecPlayer
*player
)
868 SwfdecPlayerPrivate
*priv
= player
->priv
;
870 double scale_x
, scale_y
;
873 priv
->stage
.width
= priv
->stage_width
>= 0 ? priv
->stage_width
: (int) priv
->width
;
874 priv
->stage
.height
= priv
->stage_height
>= 0 ? priv
->stage_height
: (int) priv
->height
;
876 if (priv
->stage
.height
== 0 || priv
->stage
.width
== 0) {
877 cairo_matrix_init_scale (&priv
->stage_to_global
,
878 SWFDEC_TWIPS_SCALE_FACTOR
, SWFDEC_TWIPS_SCALE_FACTOR
);
879 priv
->global_to_stage
= priv
->stage_to_global
;
880 cairo_matrix_invert (&priv
->global_to_stage
);
883 if (priv
->width
== 0 || priv
->height
== 0) {
887 scale_x
= (double) priv
->stage
.width
/ priv
->width
;
888 scale_y
= (double) priv
->stage
.height
/ priv
->height
;
890 switch (priv
->scale_mode
) {
891 case SWFDEC_SCALE_SHOW_ALL
:
892 scale_x
= MIN (scale_x
, scale_y
);
895 case SWFDEC_SCALE_NO_BORDER
:
896 scale_x
= MAX (scale_x
, scale_y
);
899 case SWFDEC_SCALE_EXACT_FIT
:
901 case SWFDEC_SCALE_NONE
:
906 g_assert_not_reached ();
908 width
= priv
->stage
.width
- ceil (priv
->width
* scale_x
);
909 height
= priv
->stage
.height
- ceil (priv
->height
* scale_y
);
910 if (priv
->align_flags
& SWFDEC_ALIGN_FLAG_LEFT
) {
912 } else if (priv
->align_flags
& SWFDEC_ALIGN_FLAG_RIGHT
) {
917 if (priv
->align_flags
& SWFDEC_ALIGN_FLAG_TOP
) {
919 } else if (priv
->align_flags
& SWFDEC_ALIGN_FLAG_BOTTOM
) {
924 SWFDEC_LOG ("coordinate translation is %g * x + %d - %g * y + %d",
925 scale_x
, width
, scale_y
, height
);
926 cairo_matrix_init_translate (&priv
->global_to_stage
, width
, height
);
927 cairo_matrix_scale (&priv
->global_to_stage
, SWFDEC_TWIPS_TO_DOUBLE (scale_x
),
928 SWFDEC_TWIPS_TO_DOUBLE (scale_y
));
929 priv
->stage_to_global
= priv
->global_to_stage
;
930 if (cairo_matrix_invert (&priv
->stage_to_global
)) {
931 g_assert_not_reached ();
933 /* FIXME: notify textfields more gentle about the update */
934 /* FIXME: these events can cause invalidations in TextFields */
935 for (walk
= priv
->roots
; walk
; walk
= walk
->next
) {
936 g_signal_emit_by_name (walk
->data
, "matrix-changed");
938 swfdec_player_invalidate (player
, NULL
, NULL
);
939 if (!swfdec_player_is_locked (player
))
940 swfdec_player_emit_signals (player
);
944 swfdec_player_set_property (GObject
*object
, guint param_id
, const GValue
*value
,
947 SwfdecPlayer
*player
= SWFDEC_PLAYER (object
);
948 SwfdecPlayerPrivate
*priv
= player
->priv
;
951 case PROP_CACHE_SIZE
:
952 swfdec_cache_set_max_cache_size (priv
->cache
, g_value_get_ulong (value
));
955 swfdec_player_set_size (player
, g_value_get_int (value
), priv
->stage_height
);
958 swfdec_player_set_size (player
, priv
->stage_width
, g_value_get_int (value
));
961 priv
->align_flags
= swfdec_player_alignment_to_flags (g_value_get_enum (value
));
962 swfdec_player_update_scale (player
);
965 swfdec_player_set_scale_mode (player
, g_value_get_enum (value
));
968 swfdec_player_set_scripting (player
, g_value_get_object (value
));
971 g_object_unref (priv
->system
);
972 if (g_value_get_object (value
)) {
973 priv
->system
= SWFDEC_SYSTEM (g_value_dup_object (value
));
975 priv
->system
= swfdec_system_new ();
978 case PROP_MAX_RUNTIME
:
979 swfdec_player_set_maximum_runtime (player
, g_value_get_ulong (value
));
981 case PROP_LOADER_TYPE
:
982 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (g_value_get_gtype (value
)));
983 priv
->loader_type
= g_value_get_gtype (value
);
985 case PROP_SOCKET_TYPE
:
986 priv
->socket_type
= g_value_get_gtype (value
);
989 swfdec_player_set_url (player
, g_value_get_boxed (value
));
992 swfdec_player_set_base_url (player
, g_value_get_boxed (value
));
995 swfdec_player_set_variables (player
, g_value_get_boxed (value
));
997 case PROP_START_TIME
:
999 const GTimeVal
*set
= g_value_get_boxed (value
);
1001 SWFDEC_AS_CONTEXT (player
)->start_time
= *set
;
1002 /* else use default time from context */
1006 swfdec_player_set_focus (player
, g_value_get_boolean (value
));
1009 swfdec_player_set_renderer (player
, g_value_get_object (value
));
1011 case PROP_ALLOW_FULLSCREEN
:
1012 swfdec_player_set_allow_fullscreen (player
, g_value_get_boolean (value
));
1015 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
1021 swfdec_player_stop_ticking (SwfdecPlayer
*player
)
1023 SwfdecPlayerPrivate
*priv
;
1025 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
1027 priv
= player
->priv
;
1028 if (priv
->iterate_timeout
.callback
== NULL
)
1030 swfdec_player_remove_timeout (player
, &priv
->iterate_timeout
);
1031 priv
->iterate_timeout
.callback
= NULL
;
1035 swfdec_player_dispose (GObject
*object
)
1037 SwfdecPlayer
*player
= SWFDEC_PLAYER (object
);
1038 SwfdecPlayerPrivate
*priv
= player
->priv
;
1041 swfdec_player_stop_all_sounds (player
);
1042 swfdec_function_list_clear (&priv
->resource_requests
);
1043 g_hash_table_destroy (priv
->registered_classes
);
1044 g_hash_table_destroy (priv
->scripting_callbacks
);
1046 g_list_foreach (priv
->loading_policy_files
, (GFunc
) g_object_unref
, NULL
);
1047 g_list_free (priv
->loading_policy_files
);
1048 priv
->loading_policy_files
= NULL
;
1049 g_slist_foreach (priv
->policy_files
, (GFunc
) g_object_unref
, NULL
);
1050 g_slist_free (priv
->policy_files
);
1051 priv
->policy_files
= NULL
;
1052 g_slist_free (priv
->invalid_pending
);
1053 priv
->invalid_pending
= NULL
;
1056 swfdec_movie_destroy (priv
->roots
->data
);
1058 /* we do this here so references to GC'd objects get freed */
1059 G_OBJECT_CLASS (swfdec_player_parent_class
)->dispose (object
);
1060 /* must happen after disposing context, some objects unroot themselves */
1061 swfdec_function_list_clear (&priv
->rooted
);
1063 swfdec_player_remove_all_external_actions (player
, player
);
1064 #ifndef G_DISABLE_ASSERT
1066 SwfdecPlayerExternalAction
*action
;
1067 while ((action
= swfdec_ring_buffer_pop (priv
->external_actions
)) != NULL
) {
1068 g_assert (action
->object
== NULL
); /* skip removed actions */
1072 SwfdecPlayerAction
*action
;
1073 for (i
= 0; i
< SWFDEC_PLAYER_N_ACTION_QUEUES
; i
++) {
1074 while ((action
= swfdec_ring_buffer_pop (priv
->actions
[i
])) != NULL
) {
1075 g_assert (action
->actor
== NULL
); /* skip removed actions */
1080 swfdec_ring_buffer_free (priv
->external_actions
);
1081 for (i
= 0; i
< SWFDEC_PLAYER_N_ACTION_QUEUES
; i
++) {
1082 swfdec_ring_buffer_free (priv
->actions
[i
]);
1084 g_assert (priv
->actors
== NULL
);
1085 g_assert (priv
->audio
== NULL
);
1086 g_slist_free (priv
->sandboxes
);
1087 if (priv
->external_timeout
.callback
)
1088 swfdec_player_remove_timeout (player
, &priv
->external_timeout
);
1089 swfdec_player_stop_ticking (player
);
1090 g_assert (priv
->timeouts
== NULL
);
1091 g_list_free (priv
->intervals
);
1092 priv
->intervals
= NULL
;
1093 g_object_unref (priv
->cache
);
1095 g_object_unref (priv
->system
);
1096 priv
->system
= NULL
;
1098 g_array_free (priv
->invalidations
, TRUE
);
1099 priv
->invalidations
= NULL
;
1100 if (priv
->renderer
) {
1101 g_object_unref (priv
->renderer
);
1102 priv
->renderer
= NULL
;
1104 if (priv
->runtime
) {
1105 g_timer_destroy (priv
->runtime
);
1106 priv
->runtime
= NULL
;
1108 if (priv
->base_url
) {
1109 swfdec_url_free (priv
->base_url
);
1110 priv
->base_url
= NULL
;
1113 swfdec_url_free (priv
->url
);
1116 g_free (priv
->variables
);
1117 priv
->variables
= NULL
;
1121 swfdec_player_broadcast (SwfdecPlayer
*player
, const char *object_name
,
1122 const char *signal_name
, guint argc
, SwfdecAsValue
*argv
)
1125 SwfdecAsValue vals
[3];
1126 SwfdecAsObject
*obj
;
1128 /* FIXME: extend when needed, by increasing the array size above */
1129 g_return_if_fail (argc
<= 2);
1132 memcpy (&vals
[1], argv
, argc
* sizeof (SwfdecAsValue
));
1135 SWFDEC_DEBUG ("broadcasting message %s.%s", object_name
, signal_name
);
1136 /* FIXME: sandbox ordering? */
1137 for (walk
= player
->priv
->sandboxes
; walk
; walk
= walk
->next
) {
1138 SwfdecSandbox
*sandbox
= walk
->data
;
1139 swfdec_sandbox_use (sandbox
);
1140 swfdec_as_object_get_variable (SWFDEC_AS_CONTEXT (player
)->global
, object_name
, &vals
[0]);
1141 if (!SWFDEC_AS_VALUE_IS_COMPOSITE (&vals
[0]))
1143 obj
= SWFDEC_AS_VALUE_GET_COMPOSITE (&vals
[0]);
1146 SWFDEC_AS_VALUE_SET_STRING (&vals
[0], signal_name
);
1147 swfdec_as_object_call (obj
, SWFDEC_AS_STR_broadcastMessage
, argc
+ 1, vals
, NULL
);
1148 swfdec_sandbox_unuse (sandbox
);
1153 swfdec_player_invalidate_focusrect (SwfdecPlayer
*player
)
1155 SwfdecPlayerPrivate
*priv
;
1157 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
1159 priv
= player
->priv
;
1161 if (swfdec_rect_is_empty (&priv
->focusrect
))
1164 swfdec_player_invalidate (player
, NULL
, &priv
->focusrect
);
1165 swfdec_rect_init_empty (&priv
->focusrect
);
1169 * swfdec_player_grab_focus:
1170 * @player: the player
1171 * @actor: the actor to give focus or %NULL to unset focus
1173 * This function handles passing the focus around. It is supposed to be called
1174 * by all functions that wish to change keyboard focus. Note that only the
1175 * currently focused movie receives keyboard events - i.e. key_pressed and
1176 * key_released vfuncs.
1179 swfdec_player_grab_focus (SwfdecPlayer
*player
, SwfdecActor
*actor
)
1181 SwfdecAsValue vals
[2];
1182 SwfdecPlayerPrivate
*priv
;
1183 SwfdecActorClass
*klass
;
1186 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
1187 g_return_if_fail (actor
== NULL
|| SWFDEC_IS_ACTOR (actor
));
1190 priv
= player
->priv
;
1191 if (actor
== priv
->focus
) {
1192 SWFDEC_DEBUG ("nothing to do, focus change request from movie %s to itself",
1193 actor
? SWFDEC_MOVIE (actor
)->name
: "---");
1198 SWFDEC_AS_VALUE_SET_MOVIE (&vals
[0], SWFDEC_MOVIE (prev
));
1200 SWFDEC_AS_VALUE_SET_NULL (&vals
[0]);
1203 SWFDEC_AS_VALUE_SET_MOVIE (&vals
[1], SWFDEC_MOVIE (actor
));
1205 SWFDEC_AS_VALUE_SET_NULL (&vals
[1]);
1208 swfdec_sandbox_use (SWFDEC_MOVIE (prev
)->resource
->sandbox
);
1209 swfdec_as_relay_call (SWFDEC_AS_RELAY (prev
), SWFDEC_AS_STR_onKillFocus
,
1211 swfdec_sandbox_unuse (SWFDEC_MOVIE (prev
)->resource
->sandbox
);
1212 klass
= SWFDEC_ACTOR_GET_CLASS (prev
);
1213 if (klass
->focus_out
)
1214 klass
->focus_out (prev
);
1216 priv
->focus_previous
= prev
;
1217 priv
->focus
= actor
;
1218 swfdec_player_invalidate_focusrect (player
);
1220 swfdec_sandbox_use (SWFDEC_MOVIE (actor
)->resource
->sandbox
);
1221 swfdec_as_relay_call (SWFDEC_AS_RELAY (actor
), SWFDEC_AS_STR_onSetFocus
,
1223 swfdec_sandbox_unuse (SWFDEC_MOVIE (actor
)->resource
->sandbox
);
1224 klass
= SWFDEC_ACTOR_GET_CLASS (actor
);
1225 if (klass
->focus_in
)
1226 klass
->focus_in (actor
);
1228 swfdec_player_broadcast (player
, SWFDEC_AS_STR_Selection
, SWFDEC_AS_STR_onSetFocus
, 2, vals
);
1232 swfdec_player_update_mouse_cursor (SwfdecPlayer
*player
)
1234 SwfdecPlayerPrivate
*priv
= player
->priv
;
1235 SwfdecMouseCursor
new = SWFDEC_MOUSE_CURSOR_NORMAL
;
1237 if (!priv
->mouse_visible
) {
1238 new = SWFDEC_MOUSE_CURSOR_NONE
;
1239 } else if (priv
->mouse_grab
!= NULL
) {
1240 SwfdecActorClass
*klass
= SWFDEC_ACTOR_GET_CLASS (priv
->mouse_grab
);
1242 if (klass
->mouse_cursor
)
1243 new = klass
->mouse_cursor (priv
->mouse_grab
);
1245 new = SWFDEC_MOUSE_CURSOR_CLICK
;
1248 if (new != priv
->mouse_cursor
) {
1249 priv
->mouse_cursor
= new;
1250 g_object_notify (G_OBJECT (player
), "mouse-cursor");
1255 * swfdec_player_set_drag_movie:
1256 * @player: a #SwfdecPlayer
1257 * @drag: the movie to be dragged by the mouse or NULL to unset
1258 * @center: TRUE if the center of @drag should be at the mouse pointer, FALSE if (0,0)
1259 * of @drag should be at the mouse pointer.
1260 * @rect: NULL or the rectangle that clips the mouse position. The coordinates
1261 * are in the coordinate system of the parent of @drag.
1263 * Sets or unsets the movie that is dragged by the mouse.
1266 swfdec_player_set_drag_movie (SwfdecPlayer
*player
, SwfdecActor
*drag
, gboolean center
,
1269 SwfdecPlayerPrivate
*priv
;
1271 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
1272 g_return_if_fail (drag
== NULL
|| SWFDEC_IS_ACTOR (drag
));
1274 /* FIXME: need to do anything with old drag? */
1275 priv
= player
->priv
;
1276 priv
->mouse_drag
= drag
;
1277 priv
->mouse_drag_center
= center
;
1278 if (drag
&& !center
) {
1279 priv
->mouse_drag_x
= priv
->mouse_x
;
1280 priv
->mouse_drag_y
= priv
->mouse_y
;
1281 swfdec_player_stage_to_global (player
, &priv
->mouse_drag_x
, &priv
->mouse_drag_y
);
1282 if (SWFDEC_MOVIE (drag
)->parent
)
1283 swfdec_movie_global_to_local (SWFDEC_MOVIE (drag
)->parent
, &priv
->mouse_drag_x
, &priv
->mouse_drag_y
);
1284 priv
->mouse_drag_x
-= SWFDEC_MOVIE (drag
)->matrix
.x0
;
1285 priv
->mouse_drag_y
-= SWFDEC_MOVIE (drag
)->matrix
.y0
;
1288 priv
->mouse_drag_rect
= *rect
;
1290 priv
->mouse_drag_rect
.x0
= -G_MAXDOUBLE
;
1291 priv
->mouse_drag_rect
.y0
= -G_MAXDOUBLE
;
1292 priv
->mouse_drag_rect
.x1
= G_MAXDOUBLE
;
1293 priv
->mouse_drag_rect
.y1
= G_MAXDOUBLE
;
1295 SWFDEC_DEBUG ("starting drag in %g %g %g %g",
1296 priv
->mouse_drag_rect
.x0
, priv
->mouse_drag_rect
.y0
,
1297 priv
->mouse_drag_rect
.x1
, priv
->mouse_drag_rect
.y1
);
1298 if (SWFDEC_MOVIE (drag
))
1299 SWFDEC_MOVIE (drag
)->modified
= TRUE
;
1303 swfdec_player_grab_mouse_movie (SwfdecPlayer
*player
)
1305 SwfdecPlayerPrivate
*priv
= player
->priv
;
1308 SwfdecActor
*below_mouse
= NULL
;
1312 swfdec_player_stage_to_global (player
, &x
, &y
);
1313 for (walk
= g_list_last (priv
->roots
); walk
; walk
= walk
->prev
) {
1314 SwfdecMovie
*movie
= swfdec_movie_get_movie_at (walk
->data
, x
, y
, TRUE
);
1315 if (SWFDEC_IS_ACTOR (movie
) &&
1316 swfdec_actor_get_mouse_events (SWFDEC_ACTOR (movie
))) {
1317 below_mouse
= SWFDEC_ACTOR (movie
);
1321 if (swfdec_player_is_mouse_pressed (player
)) {
1322 /* a mouse grab is active */
1323 if (priv
->mouse_grab
) {
1324 if (below_mouse
== priv
->mouse_grab
&&
1325 priv
->mouse_below
!= priv
->mouse_grab
) {
1326 SwfdecActorClass
*klass
= SWFDEC_ACTOR_GET_CLASS (priv
->mouse_grab
);
1327 if (klass
->mouse_in
)
1328 klass
->mouse_in (priv
->mouse_grab
);
1329 } else if (below_mouse
!= priv
->mouse_grab
&&
1330 priv
->mouse_below
== priv
->mouse_grab
) {
1331 SwfdecActorClass
*klass
= SWFDEC_ACTOR_GET_CLASS (priv
->mouse_grab
);
1332 if (klass
->mouse_out
)
1333 klass
->mouse_out (priv
->mouse_grab
);
1337 /* no mouse grab is active */
1338 if (below_mouse
!= priv
->mouse_grab
) {
1339 if (priv
->mouse_grab
) {
1340 SwfdecActorClass
*klass
= SWFDEC_ACTOR_GET_CLASS (priv
->mouse_grab
);
1341 if (klass
->mouse_out
)
1342 klass
->mouse_out (priv
->mouse_grab
);
1345 SwfdecActorClass
*klass
= SWFDEC_ACTOR_GET_CLASS (below_mouse
);
1346 if (klass
->mouse_in
)
1347 klass
->mouse_in (below_mouse
);
1350 priv
->mouse_grab
= below_mouse
;
1352 priv
->mouse_below
= below_mouse
;
1353 SWFDEC_DEBUG ("%s %p has mouse at %g %g",
1354 priv
->mouse_grab
? G_OBJECT_TYPE_NAME (priv
->mouse_grab
) : "---",
1355 priv
->mouse_grab
, priv
->mouse_x
, priv
->mouse_y
);
1359 swfdec_player_do_mouse_move (SwfdecPlayer
*player
, double x
, double y
)
1361 SwfdecPlayerPrivate
*priv
= player
->priv
;
1364 if (priv
->mouse_x
!= x
|| priv
->mouse_y
!= y
) {
1367 for (walk
= priv
->actors
; walk
; walk
= walk
->next
) {
1368 swfdec_actor_queue_script (walk
->data
, SWFDEC_EVENT_MOUSE_MOVE
);
1370 swfdec_player_broadcast (player
, SWFDEC_AS_STR_Mouse
, SWFDEC_AS_STR_onMouseMove
, 0, NULL
);
1372 swfdec_player_grab_mouse_movie (player
);
1373 if (priv
->mouse_grab
) {
1374 SwfdecActorClass
*klass
= SWFDEC_ACTOR_GET_CLASS (priv
->mouse_grab
);
1375 swfdec_player_stage_to_global (player
, &x
, &y
);
1376 swfdec_movie_global_to_local (SWFDEC_MOVIE (priv
->mouse_grab
), &x
, &y
);
1377 if (klass
->mouse_move
)
1378 klass
->mouse_move (priv
->mouse_grab
, x
, y
);
1381 /* FIXME: allow events to pass through */
1386 swfdec_player_do_mouse_press (SwfdecPlayer
*player
, guint button
)
1388 SwfdecPlayerPrivate
*priv
= player
->priv
;
1391 priv
->mouse_button
|= 1 << button
;
1393 for (walk
= priv
->actors
; walk
; walk
= walk
->next
) {
1394 swfdec_actor_queue_script (walk
->data
, SWFDEC_EVENT_MOUSE_DOWN
);
1396 swfdec_player_broadcast (player
, SWFDEC_AS_STR_Mouse
, SWFDEC_AS_STR_onMouseDown
, 0, NULL
);
1398 if (priv
->mouse_grab
) {
1399 SwfdecActorClass
*klass
= SWFDEC_ACTOR_GET_CLASS (priv
->mouse_grab
);
1400 if (klass
->mouse_press
)
1401 klass
->mouse_press (priv
->mouse_grab
, button
);
1404 /* FIXME: allow events to pass through */
1409 swfdec_player_do_mouse_release (SwfdecPlayer
*player
, guint button
)
1411 SwfdecPlayerPrivate
*priv
= player
->priv
;
1414 priv
->mouse_button
&= ~(1 << button
);
1416 for (walk
= priv
->actors
; walk
; walk
= walk
->next
) {
1417 swfdec_actor_queue_script (walk
->data
, SWFDEC_EVENT_MOUSE_UP
);
1419 swfdec_player_broadcast (player
, SWFDEC_AS_STR_Mouse
, SWFDEC_AS_STR_onMouseUp
, 0, NULL
);
1421 if (priv
->mouse_grab
) {
1422 SwfdecActorClass
*klass
= SWFDEC_ACTOR_GET_CLASS (priv
->mouse_grab
);
1423 if (klass
->mouse_release
)
1424 klass
->mouse_release (priv
->mouse_grab
, button
);
1425 if (button
== 0 && priv
->mouse_grab
!= priv
->mouse_below
) {
1426 priv
->mouse_grab
= priv
->mouse_below
;
1427 if (priv
->mouse_grab
) {
1428 klass
= SWFDEC_ACTOR_GET_CLASS (priv
->mouse_grab
);
1429 if (klass
->mouse_in
)
1430 klass
->mouse_in (priv
->mouse_grab
);
1435 /* FIXME: allow events to pass through */
1440 swfdec_player_focus_sort (gconstpointer ca
, gconstpointer cb
)
1442 SwfdecMovie
*a
= SWFDEC_MOVIE (ca
);
1443 SwfdecMovie
*b
= SWFDEC_MOVIE (cb
);
1444 double xa
, ya
, xb
, yb
;
1448 swfdec_movie_update (a
);
1449 swfdec_movie_update (b
);
1453 swfdec_movie_local_to_global (a
->parent
, &xa
, &ya
);
1456 swfdec_movie_local_to_global (b
->parent
, &xb
, &yb
);
1468 na
= swfdec_movie_get_path (a
, TRUE
);
1469 nb
= swfdec_movie_get_path (b
, TRUE
);
1470 result
= strcmp (na
, nb
);
1478 if (a
->depth
< b
->depth
)
1480 else if (a
->depth
> b
->depth
)
1483 /* provide consistent sorting as long as we are active */
1491 swfdec_player_get_tab_movies (SwfdecPlayer
*player
, const GList
*current
)
1493 SwfdecAsObject
*object
;
1498 for (walk
= current
; walk
; walk
= walk
->next
) {
1499 SwfdecActor
*actor
= walk
->data
;
1501 if (!SWFDEC_IS_ACTOR (actor
))
1504 object
= swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (actor
));
1505 swfdec_sandbox_use (SWFDEC_MOVIE (actor
)->resource
->sandbox
);
1506 if (SWFDEC_IS_TEXT_FIELD_MOVIE (actor
)) {
1507 SwfdecTextFieldMovie
*text
= SWFDEC_TEXT_FIELD_MOVIE (actor
);
1509 ret
= g_list_prepend (ret
, actor
);
1510 } else if (SWFDEC_MOVIE (actor
)->parent
!= NULL
) {
1511 swfdec_as_object_get_variable (object
, SWFDEC_AS_STR_tabEnabled
, &val
);
1512 if (swfdec_as_value_to_boolean (SWFDEC_AS_CONTEXT (player
), &val
)) {
1513 /* Flash queries again - why not? :/ */
1514 swfdec_as_object_get_variable (object
, SWFDEC_AS_STR_tabEnabled
, &val
);
1515 ret
= g_list_prepend (ret
, actor
);
1516 } else if (SWFDEC_AS_VALUE_IS_UNDEFINED (&val
) &&
1517 swfdec_actor_get_mouse_events (actor
)) {
1518 ret
= g_list_prepend (ret
, actor
);
1522 if (SWFDEC_MOVIE (actor
)->parent
== NULL
)
1523 SWFDEC_AS_VALUE_SET_UNDEFINED (&val
);
1525 swfdec_as_object_get_variable (object
, SWFDEC_AS_STR_tabChildren
, &val
);
1527 if (SWFDEC_AS_VALUE_IS_UNDEFINED (&val
) ||
1528 swfdec_as_value_to_boolean (SWFDEC_AS_CONTEXT (player
), &val
)) {
1530 swfdec_sandbox_unuse (SWFDEC_MOVIE (actor
)->resource
->sandbox
);
1531 list
= swfdec_player_get_tab_movies (player
, SWFDEC_MOVIE (actor
)->list
);
1533 ret
= g_list_concat (list
, ret
);
1535 swfdec_sandbox_unuse (SWFDEC_MOVIE (actor
)->resource
->sandbox
);
1542 swfdec_player_handle_tab (SwfdecPlayer
*player
, gboolean forward
)
1544 SwfdecPlayerPrivate
*priv
= player
->priv
;
1546 GList
*free_list
= NULL
;
1549 if (priv
->focus_list
) {
1550 list
= priv
->focus_list
;
1552 free_list
= swfdec_player_get_tab_movies (player
, priv
->roots
);
1553 free_list
= g_list_sort (free_list
, swfdec_player_focus_sort
);
1558 walk
= g_list_find (list
, priv
->focus
);
1563 walk
= forward
? list
: g_list_last (list
);
1564 actor
= walk
? walk
->data
: NULL
;
1566 walk
= forward
? walk
->next
: walk
->prev
;
1568 SWFDEC_FIXME ("try tabbing out of the flash movie here");
1569 walk
= forward
? list
: g_list_last (list
);
1571 actor
= walk
? walk
->data
: NULL
;
1573 swfdec_player_grab_focus (player
, actor
);
1576 g_list_free (free_list
);
1580 swfdec_player_handle_special_keys_before (SwfdecPlayer
*player
, guint key
)
1582 if (key
== SWFDEC_KEY_ESCAPE
) {
1583 swfdec_player_set_fullscreen (player
, FALSE
);
1588 swfdec_player_handle_special_keys_after (SwfdecPlayer
*player
, guint key
)
1590 if (key
== SWFDEC_KEY_TAB
) {
1591 gboolean forward
= swfdec_player_is_key_pressed (player
, SWFDEC_KEY_SHIFT
);
1592 swfdec_player_handle_tab (player
, forward
);
1597 swfdec_player_get_conditional_key (guint keycode
, guint character
)
1599 static guint special_keys
[] = {
1608 SWFDEC_KEY_BACKSPACE
,
1617 SWFDEC_KEY_PAGE_DOWN
,
1624 for (i
= 0; i
< G_N_ELEMENTS (special_keys
); i
++) {
1625 if (special_keys
[i
] == keycode
)
1630 if (character
>= 32 && character
<= 126)
1637 swfdec_player_do_handle_key (SwfdecPlayer
*player
, guint keycode
, guint character
, gboolean down
)
1639 SwfdecPlayerPrivate
*priv
= player
->priv
;
1642 g_assert (keycode
< 256);
1644 if (!swfdec_player_lock (player
))
1646 /* set the correct variables */
1647 priv
->last_keycode
= keycode
;
1648 priv
->last_character
= character
;
1650 priv
->key_pressed
[keycode
/ 8] |= 1 << keycode
% 8;
1652 priv
->key_pressed
[keycode
/ 8] &= ~(1 << keycode
% 8);
1656 swfdec_player_handle_special_keys_before (player
, keycode
);
1659 guint8 cond
= swfdec_player_get_conditional_key (keycode
, character
);
1661 for (walk
= priv
->actors
; walk
; walk
= walk
->next
) {
1662 swfdec_actor_queue_script_with_key (walk
->data
, SWFDEC_EVENT_KEY_PRESS
,
1667 swfdec_player_broadcast (player
, SWFDEC_AS_STR_Key
,
1668 down
? SWFDEC_AS_STR_onKeyDown
: SWFDEC_AS_STR_onKeyUp
, 0, NULL
);
1671 SwfdecActorClass
*klass
= SWFDEC_ACTOR_GET_CLASS (priv
->focus
);
1673 if (klass
->key_press
)
1674 klass
->key_press (priv
->focus
, keycode
, character
);
1676 if (klass
->key_release
)
1677 klass
->key_release (priv
->focus
, keycode
, character
);
1681 swfdec_player_handle_special_keys_after (player
, keycode
);
1682 swfdec_player_perform_actions (player
);
1683 swfdec_player_unlock (player
);
1689 swfdec_player_do_handle_mouse (SwfdecPlayer
*player
,
1690 double x
, double y
, int button
)
1694 if (!swfdec_player_lock (player
))
1697 SWFDEC_LOG ("handling mouse for %g %g %d", x
, y
, button
);
1698 ret
= swfdec_player_do_mouse_move (player
, x
, y
);
1700 ret
|= swfdec_player_do_mouse_press (player
, button
- 1);
1701 } else if (button
< 0) {
1702 ret
|= swfdec_player_do_mouse_release (player
, -button
- 1);
1704 swfdec_player_perform_actions (player
);
1705 swfdec_player_unlock (player
);
1711 swfdec_player_global_to_stage (SwfdecPlayer
*player
, double *x
, double *y
)
1713 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
1714 g_return_if_fail (x
!= NULL
);
1715 g_return_if_fail (y
!= NULL
);
1717 cairo_matrix_transform_point (&player
->priv
->global_to_stage
, x
, y
);
1721 swfdec_player_stage_to_global (SwfdecPlayer
*player
, double *x
, double *y
)
1723 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
1724 g_return_if_fail (x
!= NULL
);
1725 g_return_if_fail (y
!= NULL
);
1727 cairo_matrix_transform_point (&player
->priv
->stage_to_global
, x
, y
);
1731 swfdec_player_execute_on_load_init (SwfdecPlayer
*player
)
1735 /* FIXME: This can be made a LOT faster with correct caching, but I'm lazy */
1737 for (walk
= player
->priv
->actors
; walk
; walk
= walk
->next
) {
1738 SwfdecMovie
*movie
= walk
->data
;
1739 SwfdecResource
*resource
= swfdec_movie_get_own_resource (movie
);
1740 if (resource
== NULL
)
1742 if (swfdec_resource_emit_on_load_init (resource
))
1745 } while (walk
!= NULL
);
1749 swfdec_player_iterate (SwfdecTimeout
*timeout
)
1751 SwfdecPlayerPrivate
*priv
= (SwfdecPlayerPrivate
*) ((void *) ((guint8
*) timeout
- G_STRUCT_OFFSET (SwfdecPlayerPrivate
, iterate_timeout
)));
1752 SwfdecPlayer
*player
= priv
->player
;
1755 /* add timeout again - do this first because later code can change it */
1756 /* FIXME: rounding issues? */
1757 priv
->iterate_timeout
.timestamp
+= SWFDEC_TICKS_PER_SECOND
* 256 / priv
->rate
;
1758 swfdec_player_add_timeout (player
, &priv
->iterate_timeout
);
1759 swfdec_player_perform_external_actions (player
);
1760 SWFDEC_INFO ("=== START ITERATION ===");
1761 /* start the iteration. This performs a goto next frame on all
1762 * movies that are not stopped. It also queues onEnterFrame.
1764 for (walk
= priv
->actors
; walk
; walk
= walk
->next
) {
1765 SwfdecActorClass
*klass
= SWFDEC_ACTOR_GET_CLASS (walk
->data
);
1766 if (klass
->iterate_start
)
1767 klass
->iterate_start (walk
->data
);
1769 swfdec_player_perform_actions (player
);
1770 SWFDEC_INFO ("=== STOP ITERATION ===");
1771 /* this loop allows removal of walk->data */
1772 walk
= priv
->actors
;
1774 SwfdecMovie
*cur
= walk
->data
;
1775 SwfdecActorClass
*klass
= SWFDEC_ACTOR_GET_CLASS (cur
);
1777 g_assert (klass
->iterate_end
);
1778 if (!klass
->iterate_end (SWFDEC_ACTOR (cur
)))
1779 swfdec_movie_destroy (cur
);
1781 swfdec_player_execute_on_load_init (player
);
1782 swfdec_function_list_execute_and_clear (&priv
->resource_requests
, player
);
1783 swfdec_player_perform_actions (player
);
1787 swfdec_player_advance_audio (SwfdecPlayer
*player
, guint samples
)
1795 /* don't use for loop here, because we need to advance walk before
1796 * removing the audio */
1797 walk
= player
->priv
->audio
;
1801 if (swfdec_audio_iterate (audio
, samples
) == 0)
1802 swfdec_audio_remove (audio
);
1807 swfdec_player_do_advance (SwfdecPlayer
*player
, gulong msecs
, guint audio_samples
)
1809 SwfdecPlayerPrivate
*priv
= player
->priv
;
1810 SwfdecTimeout
*timeout
;
1811 SwfdecTick target_time
;
1813 if (!swfdec_player_lock (player
))
1816 g_assert (priv
->timeouts
!= NULL
);
1818 target_time
= priv
->time
+ SWFDEC_MSECS_TO_TICKS (msecs
);
1819 SWFDEC_DEBUG ("advancing %lu msecs (%u audio frames)", msecs
, audio_samples
);
1821 timeout
= priv
->timeouts
->data
;
1822 swfdec_player_advance_audio (player
, audio_samples
);
1823 if (timeout
->timestamp
<= target_time
) {
1824 priv
->timeouts
= g_list_remove (priv
->timeouts
, timeout
);
1825 priv
->time
= timeout
->timestamp
;
1826 SWFDEC_LOG ("activating timeout %p now (timeout is %"G_GUINT64_FORMAT
,
1827 timeout
, timeout
->timestamp
);
1828 timeout
->callback (timeout
);
1829 swfdec_player_perform_actions (player
);
1831 priv
->time
= target_time
;
1833 g_object_notify (G_OBJECT (player
), "next-event");
1834 swfdec_player_unlock (player
);
1838 swfdec_player_perform_actions (SwfdecPlayer
*player
)
1840 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
1842 while (swfdec_player_do_action (player
));
1845 /* used for breakpoints */
1847 swfdec_player_lock_soft (SwfdecPlayer
*player
)
1849 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
1850 g_assert (!swfdec_player_is_locked (player
));
1851 g_assert (player
->priv
->invalidations
->len
== 0);
1853 g_object_freeze_notify (G_OBJECT (player
));
1854 g_timer_start (player
->priv
->runtime
);
1855 player
->priv
->locked
= TRUE
;
1856 SWFDEC_DEBUG ("LOCKED");
1860 swfdec_player_lock (SwfdecPlayer
*player
)
1862 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), FALSE
);
1863 g_assert (!swfdec_player_is_locked (player
));
1864 g_assert (swfdec_ring_buffer_get_n_elements (player
->priv
->actions
[0]) == 0);
1865 g_assert (swfdec_ring_buffer_get_n_elements (player
->priv
->actions
[1]) == 0);
1866 g_assert (swfdec_ring_buffer_get_n_elements (player
->priv
->actions
[2]) == 0);
1867 g_assert (swfdec_ring_buffer_get_n_elements (player
->priv
->actions
[3]) == 0);
1869 if (swfdec_as_context_is_aborted (SWFDEC_AS_CONTEXT (player
)))
1872 g_object_ref (player
);
1873 swfdec_player_lock_soft (player
);
1878 swfdec_player_update_drag_movie (SwfdecPlayer
*player
)
1880 SwfdecPlayerPrivate
*priv
= player
->priv
;
1884 if (priv
->mouse_drag
== NULL
)
1887 movie
= SWFDEC_MOVIE (priv
->mouse_drag
);
1888 swfdec_movie_update (movie
);
1891 swfdec_player_stage_to_global (player
, &x
, &y
);
1893 swfdec_movie_global_to_local (movie
->parent
, &x
, &y
);
1894 if (priv
->mouse_drag_center
) {
1895 x
-= (movie
->extents
.x1
- movie
->extents
.x0
) / 2;
1896 y
-= (movie
->extents
.y1
- movie
->extents
.y0
) / 2;
1898 x
-= priv
->mouse_drag_x
;
1899 y
-= priv
->mouse_drag_y
;
1901 x
= CLAMP (x
, priv
->mouse_drag_rect
.x0
, priv
->mouse_drag_rect
.x1
);
1902 y
= CLAMP (y
, priv
->mouse_drag_rect
.y0
, priv
->mouse_drag_rect
.y1
);
1903 SWFDEC_LOG ("mouse is at %g %g, originally (%g %g)", x
, y
, priv
->mouse_x
, priv
->mouse_y
);
1904 if (x
!= movie
->matrix
.x0
|| y
!= movie
->matrix
.y0
) {
1905 swfdec_movie_begin_update_matrix (movie
);
1906 movie
->matrix
.x0
= x
;
1907 movie
->matrix
.y0
= y
;
1908 swfdec_movie_end_update_matrix (movie
);
1912 /* runs queued invalidations for all movies and resets the movies */
1914 swfdec_player_update_movies (SwfdecPlayer
*player
)
1916 SwfdecPlayerPrivate
*priv
= player
->priv
;
1918 cairo_matrix_t matrix
;
1921 swfdec_player_update_drag_movie (player
);
1922 for (walk
= priv
->invalid_pending
; walk
; walk
= walk
->next
) {
1925 swfdec_movie_update (movie
);
1926 g_assert (movie
->invalidate_last
);
1929 swfdec_movie_local_to_global_matrix (movie
->parent
, &matrix
);
1931 cairo_matrix_init_identity (&matrix
);
1932 swfdec_movie_invalidate (movie
, &matrix
, TRUE
);
1933 /* also clear invalidation flag from first invalidation */
1934 movie
->invalidate_last
= FALSE
;
1936 g_slist_free (priv
->invalid_pending
);
1937 priv
->invalid_pending
= NULL
;
1941 swfdec_player_update_focusrect (SwfdecPlayer
*player
)
1943 SwfdecPlayerPrivate
*priv
= player
->priv
;
1946 if (!swfdec_rect_is_empty (&priv
->focusrect
))
1949 if (priv
->focus
== NULL
||
1950 !swfdec_actor_has_focusrect (priv
->focus
))
1953 movie
= SWFDEC_MOVIE (priv
->focus
);
1954 g_assert (movie
->state
== SWFDEC_MOVIE_UP_TO_DATE
);
1955 priv
->focusrect
= movie
->extents
;
1957 swfdec_movie_rect_local_to_global (movie
->parent
, &priv
->focusrect
);
1958 swfdec_player_invalidate (player
, NULL
, &priv
->focusrect
);
1962 swfdec_player_update_selection (SwfdecPlayer
*player
)
1964 SwfdecPlayerPrivate
*priv
= player
->priv
;
1966 if (SWFDEC_IS_TEXT_FIELD_MOVIE (priv
->focus
)) {
1967 SwfdecTextFieldMovie
*text
= SWFDEC_TEXT_FIELD_MOVIE (priv
->focus
);
1969 swfdec_text_buffer_get_selection (text
->text
, &start
, &end
);
1971 const char *s
= swfdec_text_buffer_get_text (text
->text
);
1972 if (priv
->selection
!= NULL
&&
1973 priv
->selection
[end
- start
] == '\0' &&
1974 strncmp (s
+ start
, priv
->selection
, end
- start
) == 0)
1976 g_free (priv
->selection
);
1977 priv
->selection
= g_strndup (s
+ start
, end
- start
);
1978 g_object_notify (G_OBJECT (player
), "selection");
1982 /* only possible if both are NULL */
1983 if (priv
->selection
== NULL
)
1985 g_free (priv
->selection
);
1986 priv
->selection
= NULL
;
1987 g_object_notify (G_OBJECT (player
), "selection");
1990 /* used for breakpoints */
1992 swfdec_player_unlock_soft (SwfdecPlayer
*player
)
1994 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
1995 g_assert (swfdec_player_is_locked (player
));
1997 SWFDEC_DEBUG ("UNLOCK");
1998 g_timer_stop (player
->priv
->runtime
);
1999 swfdec_player_update_movies (player
);
2000 swfdec_player_update_mouse_cursor (player
);
2001 swfdec_player_update_focusrect (player
);
2002 swfdec_player_update_selection (player
);
2003 g_object_thaw_notify (G_OBJECT (player
));
2004 swfdec_player_emit_signals (player
);
2005 player
->priv
->locked
= FALSE
;
2008 /* This function does all the things that happen during rendering */
2010 swfdec_player_pretend_to_render (SwfdecPlayer
*player
)
2012 SwfdecPlayerPrivate
*priv
= player
->priv
;
2015 for (walk
= priv
->actors
; walk
; walk
= walk
->next
) {
2016 if (SWFDEC_IS_TEXT_FIELD_MOVIE (walk
->data
)) {
2017 SwfdecTextFieldMovie
*text
= walk
->data
;
2018 gboolean onScroller_emitted
= text
->onScroller_emitted
;
2019 text
->onScroller_emitted
= TRUE
;
2020 swfdec_text_field_movie_autosize (text
);
2021 text
->onScroller_emitted
= onScroller_emitted
;
2027 swfdec_player_unlock (SwfdecPlayer
*player
)
2029 SwfdecAsContext
*context
;
2031 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
2032 g_assert (swfdec_ring_buffer_get_n_elements (player
->priv
->actions
[0]) == 0);
2033 g_assert (swfdec_ring_buffer_get_n_elements (player
->priv
->actions
[1]) == 0);
2034 g_assert (swfdec_ring_buffer_get_n_elements (player
->priv
->actions
[2]) == 0);
2035 g_assert (swfdec_ring_buffer_get_n_elements (player
->priv
->actions
[3]) == 0);
2036 context
= SWFDEC_AS_CONTEXT (player
);
2037 g_return_if_fail (context
->state
!= SWFDEC_AS_CONTEXT_INTERRUPTED
);
2039 swfdec_player_pretend_to_render (player
);
2041 if (context
->state
== SWFDEC_AS_CONTEXT_RUNNING
)
2042 swfdec_as_context_maybe_gc (SWFDEC_AS_CONTEXT (player
));
2043 swfdec_player_unlock_soft (player
);
2044 g_object_unref (player
);
2048 swfdec_accumulate_or (GSignalInvocationHint
*ihint
, GValue
*return_accu
,
2049 const GValue
*handler_return
, gpointer data
)
2051 if (g_value_get_boolean (handler_return
))
2052 g_value_set_boolean (return_accu
, TRUE
);
2057 swfdec_accumulate_quit (GSignalInvocationHint
*ihint
, GValue
*return_accu
,
2058 const GValue
*handler_return
, gpointer data
)
2060 if (g_value_get_boolean (handler_return
))
2061 g_value_set_boolean (return_accu
, TRUE
);
2066 swfdec_player_mark_string_object (gpointer key
, gpointer value
, gpointer data
)
2068 swfdec_as_string_mark (key
);
2069 swfdec_gc_object_mark (value
);
2073 swfdec_player_mark (SwfdecAsContext
*context
)
2075 SwfdecPlayer
*player
= SWFDEC_PLAYER (context
);
2076 SwfdecPlayerPrivate
*priv
= player
->priv
;
2078 g_hash_table_foreach (priv
->registered_classes
, swfdec_player_mark_string_object
, NULL
);
2079 g_hash_table_foreach (priv
->scripting_callbacks
, swfdec_player_mark_string_object
, NULL
);
2080 g_list_foreach (priv
->roots
, (GFunc
) swfdec_gc_object_mark
, NULL
);
2081 g_list_foreach (priv
->intervals
, (GFunc
) swfdec_gc_object_mark
, NULL
);
2082 g_slist_foreach (priv
->sandboxes
, (GFunc
) swfdec_gc_object_mark
, NULL
);
2083 swfdec_function_list_execute (&priv
->rooted
, player
);
2084 swfdec_gc_object_mark (priv
->resource
);
2086 SWFDEC_AS_CONTEXT_CLASS (swfdec_player_parent_class
)->mark (context
);
2090 swfdec_player_get_time (SwfdecAsContext
*context
, GTimeVal
*tv
)
2092 *tv
= context
->start_time
;
2094 /* FIXME: what granularity do we want? Currently it's milliseconds */
2095 g_time_val_add (tv
, SWFDEC_TICKS_TO_MSECS (SWFDEC_PLAYER (context
)->priv
->time
) * 1000);
2099 swfdec_player_check_continue (SwfdecAsContext
*context
)
2101 SwfdecPlayer
*player
= SWFDEC_PLAYER (context
);
2102 SwfdecPlayerPrivate
*priv
= player
->priv
;
2104 if (priv
->max_runtime
== 0)
2106 return g_timer_elapsed (priv
->runtime
, NULL
) * 1000 <= priv
->max_runtime
;
2110 swfdec_player_do_query_size (SwfdecPlayer
*player
, gboolean fullscreen
,
2111 int *width
, int *height
)
2114 SwfdecPlayerPrivate
*priv
= player
->priv
;
2115 *width
= priv
->system
->screen_width
;
2116 *height
= priv
->system
->screen_height
;
2125 swfdec_player_class_init (SwfdecPlayerClass
*klass
)
2127 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
2128 SwfdecAsContextClass
*context_class
= SWFDEC_AS_CONTEXT_CLASS (klass
);
2130 g_type_class_add_private (klass
, sizeof (SwfdecPlayerPrivate
));
2132 object_class
->get_property
= swfdec_player_get_property
;
2133 object_class
->set_property
= swfdec_player_set_property
;
2134 object_class
->dispose
= swfdec_player_dispose
;
2136 g_object_class_install_property (object_class
, PROP_INITIALIZED
,
2137 g_param_spec_boolean ("initialized", "initialized", "TRUE when the player has initialized its basic values",
2138 FALSE
, G_PARAM_READABLE
));
2139 g_object_class_install_property (object_class
, PROP_DEFAULT_WIDTH
,
2140 g_param_spec_uint ("default-width", "default width", "default width of the movie",
2141 0, G_MAXUINT
, 0, G_PARAM_READABLE
));
2142 g_object_class_install_property (object_class
, PROP_DEFAULT_HEIGHT
,
2143 g_param_spec_uint ("default-height", "default height", "default height of the movie",
2144 0, G_MAXUINT
, 0, G_PARAM_READABLE
));
2145 g_object_class_install_property (object_class
, PROP_RATE
,
2146 g_param_spec_double ("rate", "rate", "rate in frames per second",
2147 0.0, 256.0, 0.0, G_PARAM_READABLE
));
2148 g_object_class_install_property (object_class
, PROP_MOUSE_CURSOR
,
2149 g_param_spec_enum ("mouse-cursor", "mouse cursor", "how the mouse pointer should be presented",
2150 SWFDEC_TYPE_MOUSE_CURSOR
, SWFDEC_MOUSE_CURSOR_NONE
, G_PARAM_READABLE
));
2151 g_object_class_install_property (object_class
, PROP_NEXT_EVENT
,
2152 g_param_spec_long ("next-event", "next event", "how many milliseconds until the next event or -1 when no event pending",
2153 -1, G_MAXLONG
, -1, G_PARAM_READABLE
));
2154 g_object_class_install_property (object_class
, PROP_CACHE_SIZE
,
2155 g_param_spec_ulong ("cache-size", "cache size", "maximum cache size in bytes",
2156 0, G_MAXULONG
, 32 * 1024 * 1024, G_PARAM_READWRITE
));
2157 g_object_class_install_property (object_class
, PROP_BACKGROUND_COLOR
,
2158 g_param_spec_uint ("background-color", "background color", "ARGB color used to draw the background",
2159 0, G_MAXUINT
, SWFDEC_COLOR_COMBINE (0xFF, 0xFF, 0xFF, 0xFF), G_PARAM_READABLE
));
2160 g_object_class_install_property (object_class
, PROP_WIDTH
,
2161 g_param_spec_int ("width", "width", "current width of the movie",
2162 -1, G_MAXINT
, -1, G_PARAM_READWRITE
));
2163 g_object_class_install_property (object_class
, PROP_HEIGHT
,
2164 g_param_spec_int ("height", "height", "current height of the movie",
2165 -1, G_MAXINT
, -1, G_PARAM_READWRITE
));
2166 g_object_class_install_property (object_class
, PROP_ALIGNMENT
,
2167 g_param_spec_enum ("alignment", "alignment", "point of the screen to align the output to",
2168 SWFDEC_TYPE_ALIGNMENT
, SWFDEC_ALIGNMENT_CENTER
, G_PARAM_READWRITE
));
2169 g_object_class_install_property (object_class
, PROP_SCALE
,
2170 g_param_spec_enum ("scale-mode", "scale mode", "method used to scale the movie",
2171 SWFDEC_TYPE_SCALE_MODE
, SWFDEC_SCALE_SHOW_ALL
, G_PARAM_READWRITE
));
2172 g_object_class_install_property (object_class
, PROP_SCRIPTING
,
2173 g_param_spec_object ("scripting", "scripting", "external scripting implementation",
2174 SWFDEC_TYPE_PLAYER_SCRIPTING
, G_PARAM_READWRITE
));
2175 g_object_class_install_property (object_class
, PROP_SYSTEM
,
2176 g_param_spec_object ("system", "system", "object holding system information",
2177 SWFDEC_TYPE_SYSTEM
, G_PARAM_READWRITE
));
2178 g_object_class_install_property (object_class
, PROP_MAX_RUNTIME
,
2179 g_param_spec_ulong ("max-runtime", "maximum runtime", "maximum time in msecs scripts may run in the player before aborting",
2180 0, G_MAXULONG
, 10 * 1000, G_PARAM_READWRITE
));
2181 g_object_class_install_property (object_class
, PROP_LOADER_TYPE
,
2182 g_param_spec_gtype ("loader-type", "loader type", "type to use for creating loaders",
2183 SWFDEC_TYPE_LOADER
, G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
));
2184 g_object_class_install_property (object_class
, PROP_SOCKET_TYPE
,
2185 g_param_spec_gtype ("socket-type", "socket type", "type to use for creating sockets",
2186 SWFDEC_TYPE_SOCKET
, G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
));
2187 g_object_class_install_property (object_class
, PROP_URL
,
2188 g_param_spec_boxed ("url", "url", "URL of resource currently played back or NULL if not set",
2189 SWFDEC_TYPE_URL
, G_PARAM_READABLE
));
2190 g_object_class_install_property (object_class
, PROP_BASE_URL
,
2191 g_param_spec_boxed ("base-url", "base url", "base URL for creating new resource or NULL if not set yet",
2192 SWFDEC_TYPE_URL
, G_PARAM_READWRITE
));
2193 g_object_class_install_property (object_class
, PROP_VARIABLES
,
2194 g_param_spec_string ("variables", "variables", "variables to use when setting the URL",
2195 NULL
, G_PARAM_READWRITE
));
2196 g_object_class_install_property (object_class
, PROP_START_TIME
,
2197 g_param_spec_boxed ("start-time", "start-time", "time to use as the beginning time for this player",
2198 SWFDEC_TYPE_TIME_VAL
, G_PARAM_WRITABLE
| G_PARAM_CONSTRUCT_ONLY
));
2199 g_object_class_install_property (object_class
, PROP_FOCUS
,
2200 g_param_spec_boolean ("focus", "focus", "TRUE if the player has keyboard focus",
2201 TRUE
, G_PARAM_READWRITE
));
2202 g_object_class_install_property (object_class
, PROP_RENDERER
,
2203 g_param_spec_object ("renderer", "renderer", "the renderer used by this player",
2204 SWFDEC_TYPE_RENDERER
, G_PARAM_READWRITE
| G_PARAM_CONSTRUCT
));
2205 g_object_class_install_property (object_class
, PROP_FULLSCREEN
,
2206 g_param_spec_boolean ("fullscreen", "fullscreen", "if the player is in fullscreen mode",
2207 FALSE
, G_PARAM_READABLE
));
2208 g_object_class_install_property (object_class
, PROP_ALLOW_FULLSCREEN
,
2209 g_param_spec_boolean ("allow-fullscreen", "allow fullscreen",
2210 "if the player is allowed to change into fullscreen mode",
2211 FALSE
, G_PARAM_READWRITE
));
2212 g_object_class_install_property (object_class
, PROP_SELECTION
,
2213 g_param_spec_string ("selection", "selection", "currently selected text",
2214 NULL
, G_PARAM_READABLE
));
2217 * SwfdecPlayer::invalidate:
2218 * @player: the #SwfdecPlayer affected
2219 * @rectangles: a number of smaller rectangles for fine-grained control over
2221 * @n_rectangles: number of rectangles in @rectangles
2223 * This signal is emitted whenever graphical elements inside the player have
2224 * changed. It provides two ways to look at the changes: By looking at the
2225 * @extents parameter, it provides a simple way to get a single rectangle that
2226 * encloses all changes. By looking at the @rectangles array, you can get
2227 * finer control over changes which is very useful if your rendering system
2228 * provides a way to handle regions.
2230 signals
[INVALIDATE
] = g_signal_new ("invalidate", G_TYPE_FROM_CLASS (klass
),
2231 G_SIGNAL_RUN_LAST
, 0, NULL
, NULL
, swfdec_marshal_VOID__POINTER_UINT
,
2232 G_TYPE_NONE
, 2, G_TYPE_POINTER
, G_TYPE_UINT
);
2234 * SwfdecPlayer::advance:
2235 * @player: the #SwfdecPlayer affected
2236 * @msecs: the amount of milliseconds the player will advance
2237 * @audio_samples: number of frames the audio is advanced (in 44100Hz steps)
2239 * Emitted whenever the player advances.
2241 signals
[ADVANCE
] = g_signal_new ("advance", G_TYPE_FROM_CLASS (klass
),
2242 G_SIGNAL_RUN_LAST
, G_STRUCT_OFFSET (SwfdecPlayerClass
, advance
),
2243 NULL
, NULL
, swfdec_marshal_VOID__ULONG_UINT
,
2244 G_TYPE_NONE
, 2, G_TYPE_ULONG
, G_TYPE_UINT
);
2246 * SwfdecPlayer::handle-key:
2247 * @player: the #SwfdecPlayer affected
2248 * @key: #SwfdecKey that was pressed or released
2249 * @pressed: %TRUE if the @key was pressed or %FALSE if it was released
2251 * This signal is emitted whenever @player should respond to a key event. If
2252 * any of the handlers returns TRUE, swfdec_player_key_press() or
2253 * swfdec_player_key_release() will return TRUE. Note that unlike many event
2254 * handlers in gtk, returning TRUE will not stop further event handlers from
2255 * being invoked. Use g_signal_stop_emission() in that case.
2257 * Returns: TRUE if this handler handles the event.
2259 signals
[HANDLE_KEY
] = g_signal_new ("handle-key", G_TYPE_FROM_CLASS (klass
),
2260 G_SIGNAL_RUN_LAST
, G_STRUCT_OFFSET (SwfdecPlayerClass
, handle_key
),
2261 swfdec_accumulate_or
, NULL
, swfdec_marshal_BOOLEAN__UINT_UINT_BOOLEAN
,
2262 G_TYPE_BOOLEAN
, 3, G_TYPE_UINT
, G_TYPE_UINT
, G_TYPE_BOOLEAN
);
2264 * SwfdecPlayer::handle-mouse:
2265 * @player: the #SwfdecPlayer affected
2266 * @x: new x coordinate of the mouse
2267 * @y: new y coordinate of the mouse
2268 * @button: 0 for a mouse move, a positive number if a button was pressed,
2269 * a negative number if a button was released
2271 * This signal is emitted whenever @player should respond to a mouse event. If
2272 * any of the handlers returns TRUE, swfdec_player_handle_mouse() will return
2273 * TRUE. Note that unlike many event handlers in gtk, returning TRUE will not
2274 * stop further event handlers from being invoked. Use g_signal_stop_emission()
2277 * Returns: TRUE if this handler handles the event.
2279 signals
[HANDLE_MOUSE
] = g_signal_new ("handle-mouse", G_TYPE_FROM_CLASS (klass
),
2280 G_SIGNAL_RUN_LAST
, G_STRUCT_OFFSET (SwfdecPlayerClass
, handle_mouse
),
2281 swfdec_accumulate_or
, NULL
, swfdec_marshal_BOOLEAN__DOUBLE_DOUBLE_INT
,
2282 G_TYPE_BOOLEAN
, 3, G_TYPE_DOUBLE
, G_TYPE_DOUBLE
, G_TYPE_INT
);
2284 * SwfdecPlayer::audio-added:
2285 * @player: the #SwfdecPlayer affected
2286 * @audio: the audio stream that was added
2288 * Emitted whenever a new audio stream was added to @player.
2290 signals
[AUDIO_ADDED
] = g_signal_new ("audio-added", G_TYPE_FROM_CLASS (klass
),
2291 G_SIGNAL_RUN_LAST
, 0, NULL
, NULL
, g_cclosure_marshal_VOID__OBJECT
,
2292 G_TYPE_NONE
, 1, SWFDEC_TYPE_AUDIO
);
2294 * SwfdecPlayer::audio-removed:
2295 * @player: the #SwfdecPlayer affected
2296 * @audio: the audio stream that was removed
2298 * Emitted whenever an audio stream was removed from @player. The stream will
2299 * have been added with the SwfdecPlayer::audio-added signal previously.
2301 signals
[AUDIO_REMOVED
] = g_signal_new ("audio-removed", G_TYPE_FROM_CLASS (klass
),
2302 G_SIGNAL_RUN_LAST
, 0, NULL
, NULL
, g_cclosure_marshal_VOID__OBJECT
,
2303 G_TYPE_NONE
, 1, SWFDEC_TYPE_AUDIO
);
2305 * SwfdecPlayer::fscommand:
2306 * @player: the #SwfdecPlayer affected
2307 * @command: the command to execute. This is a lower case string.
2308 * @parameter: parameter to pass to the command. The parameter depends on the
2311 * This signal is emited whenever a Flash script command (also known as
2312 * fscommand) is encountered. This method is ued by the Flash file to
2313 * communicate with the hosting environment. In web browsers it is used to
2314 * call Javascript functions. Standalone Flash players understand a limited
2315 * set of functions. They vary from player to player, but the most common are
2316 * listed here: <itemizedlist>
2317 * <listitem><para>"quit": quits the player.</para></listitem>
2318 * <listitem><para>"fullscreen": A boolean setting (parameter is "true" or
2319 * "false") that sets the player into fullscreen mode.</para></listitem>
2320 * <listitem><para>"allowscale": A boolean setting that tells the player to
2321 * not scale the Flash application.</para></listitem>
2322 * <listitem><para>"showmenu": A boolean setting that tells the Flash player
2323 * to not show its own entries in the right-click menu.</para></listitem>
2324 * <listitem><para>"exec": Run an external executable. The parameter
2325 * specifies the path.</para></listitem>
2326 * <listitem><para>"trapallkeys": A boolean setting that tells the Flash
2327 * player to pass all key events to the Flash application instead of using it
2328 * for keyboard shortcuts or similar.</para></listitem>
2331 /* FIXME: document fscommand:toggle */
2332 signals
[FSCOMMAND
] = g_signal_new ("fscommand", G_TYPE_FROM_CLASS (klass
),
2333 G_SIGNAL_RUN_LAST
, 0, NULL
, NULL
, swfdec_marshal_VOID__STRING_STRING
,
2334 G_TYPE_NONE
, 2, G_TYPE_STRING
, G_TYPE_STRING
);
2336 * SwfdecPlayer::launch:
2337 * @player: the #SwfdecPlayer affected
2339 * @target: target to load the URL into
2340 * @data: optional data to pass on with the request. Can be %NULL indicating
2341 * no data should be passed.
2342 * @header_count: number of custom HTTP headers to be sent
2343 * @header_names: names of the custom HTTP headers. %NULL terminated
2344 * @header_values: values of the custom HTTP headers. %NULL terminated
2346 * Emitted whenever the @player encounters an URL that should be loaded into
2347 * a target the Flash player does not recognize. In most cases this happens
2348 * when the user clicks a link in an embedded Flash movie that should open a
2350 * The effect of calling any swfdec functions on the emitting @player is undefined.
2352 signals
[LAUNCH
] = g_signal_new ("launch", G_TYPE_FROM_CLASS (klass
),
2353 G_SIGNAL_RUN_LAST
, 0, NULL
, NULL
, swfdec_marshal_VOID__STRING_STRING_BOXED_UINT_BOXED_BOXED
,
2354 G_TYPE_NONE
, 6, G_TYPE_STRING
, G_TYPE_STRING
, SWFDEC_TYPE_BUFFER
, G_TYPE_UINT
, G_TYPE_STRV
, G_TYPE_STRV
);
2356 * SwfdecPlayer::missing-plugins:
2357 * @player: the #SwfdecPlayer missing plugins
2358 * @details: the details strings for all missing plugins
2360 * Emitted whenever a plugin is detected that GStreamer cannot currently
2361 * handle because it is missing plugins to do so. You should use
2362 * gst_install_plugins_async() to install those plugins.
2364 signals
[MISSING_PLUGINS
] = g_signal_new ("missing-plugins", G_TYPE_FROM_CLASS (klass
),
2365 G_SIGNAL_RUN_LAST
, G_STRUCT_OFFSET (SwfdecPlayerClass
, missing_plugins
),
2366 NULL
, NULL
, g_cclosure_marshal_VOID__BOXED
,
2367 G_TYPE_NONE
, 1, G_TYPE_STRV
);
2370 * SwfdecPlayer::query-size:
2371 * @player: the #SwfdecPlayer that resizes
2372 * @fullscreen: %TRUE if the player queries the fullscreen size, %FALSE for
2374 * @width: pointer to an integer that takes the width to use
2375 * @height: pointer to an integer that takes the height to use
2377 * This signals is emitted whenever the player is (un)fullscreened. In this
2378 * case it requests the new size the Flash file will be displayed in
2379 * immediately. If you want to provide values, connect to this signal. The
2380 * values don't have to be exact, you can still call swfdec_player_set_size()
2381 * later on. However, it will look visually nicer if your values here are
2382 * correct. By default, the screen resolution values will be used for
2383 * fullscreen and the default size will be used otherwise.
2385 * Returns: TRUE if this handler properly sets @width and @height and no
2386 * other handlers should be invoked.
2388 signals
[QUERY_SIZE
] = g_signal_new ("query-size", G_TYPE_FROM_CLASS (klass
),
2389 G_SIGNAL_RUN_LAST
, G_STRUCT_OFFSET (SwfdecPlayerClass
, query_size
),
2390 swfdec_accumulate_quit
, NULL
, swfdec_marshal_BOOLEAN__BOOLEAN_POINTER_POINTER
,
2391 G_TYPE_BOOLEAN
, 3, G_TYPE_BOOLEAN
, G_TYPE_POINTER
, G_TYPE_POINTER
);
2393 context_class
->mark
= swfdec_player_mark
;
2394 context_class
->get_time
= swfdec_player_get_time
;
2395 context_class
->check_continue
= swfdec_player_check_continue
;
2397 klass
->advance
= swfdec_player_do_advance
;
2398 klass
->handle_key
= swfdec_player_do_handle_key
;
2399 klass
->handle_mouse
= swfdec_player_do_handle_mouse
;
2400 klass
->query_size
= swfdec_player_do_query_size
;
2404 swfdec_player_init (SwfdecPlayer
*player
)
2406 SwfdecPlayerPrivate
*priv
;
2409 player
->priv
= priv
= G_TYPE_INSTANCE_GET_PRIVATE (player
, SWFDEC_TYPE_PLAYER
, SwfdecPlayerPrivate
);
2410 priv
->player
= player
;
2412 priv
->system
= swfdec_system_new ();
2413 priv
->registered_classes
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
2414 priv
->scripting_callbacks
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
2416 for (i
= 0; i
< SWFDEC_PLAYER_N_ACTION_QUEUES
; i
++) {
2417 priv
->actions
[i
] = swfdec_ring_buffer_new_for_type (SwfdecPlayerAction
, 16);
2419 priv
->external_actions
= swfdec_ring_buffer_new_for_type (SwfdecPlayerExternalAction
, 8);
2420 // Big cache is required to allow images in the sizes of 3000x2000
2421 priv
->cache
= swfdec_cache_new (32 * 1024 * 1024);
2422 priv
->socket_type
= SWFDEC_TYPE_SOCKET
;
2424 priv
->runtime
= g_timer_new ();
2425 g_timer_stop (priv
->runtime
);
2426 priv
->max_runtime
= 10 * 1000;
2427 priv
->invalidations
= g_array_new (FALSE
, FALSE
, sizeof (SwfdecRectangle
));
2428 priv
->mouse_visible
= TRUE
;
2429 priv
->mouse_cursor
= SWFDEC_MOUSE_CURSOR_NORMAL
;
2430 priv
->stage_width
= -1;
2431 priv
->stage_height
= -1;
2432 priv
->has_focus
= TRUE
;
2434 cairo_matrix_init_scale (&priv
->stage_to_global
,
2435 SWFDEC_TWIPS_SCALE_FACTOR
, SWFDEC_TWIPS_SCALE_FACTOR
);
2436 priv
->global_to_stage
= priv
->stage_to_global
;
2437 cairo_matrix_invert (&priv
->global_to_stage
);
2438 swfdec_sound_matrix_init_identity (&priv
->sound_matrix
);
2442 swfdec_player_stop_all_sounds (SwfdecPlayer
*player
)
2444 SwfdecPlayerPrivate
*priv
;
2446 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
2448 priv
= player
->priv
;
2449 while (priv
->audio
) {
2450 swfdec_audio_remove (priv
->audio
->data
);
2455 swfdec_player_stop_sounds (SwfdecPlayer
*player
, SwfdecAudioRemoveFunc func
, gpointer data
)
2459 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
2460 g_return_if_fail (func
);
2462 walk
= player
->priv
->audio
;
2464 SwfdecAudio
*audio
= walk
->data
;
2466 if (func (audio
, data
))
2467 swfdec_audio_remove (audio
);
2472 swfdec_player_invalidate_movie (SwfdecMovie
*movie
, double xscale
, double yscale
,
2473 SwfdecRectangle
*rect
)
2476 /* FIXME: We should likely always enlarge by one and not only for filters */
2477 gboolean enlarge
= !SWFDEC_IS_TEXT_FIELD_MOVIE (movie
);
2479 while (movie
!= NULL
) {
2480 for (walk
= movie
->filters
; walk
; walk
= walk
->next
) {
2486 swfdec_filter_get_rectangle (walk
->data
, rect
, xscale
, yscale
, rect
);
2488 movie
= movie
->parent
;
2493 * swfdec_player_invalidate:
2494 * @player: Player to invalidate in
2495 * @movie: the movie that causes the invalidation or %NULL if the invalidation
2496 * is not specific to a movie. The invalid region will be enhanced by
2497 * the area required by filters. Also the "invalidate" signal will be
2498 * emitted on the movie and all its parents.
2499 * @rect: rectangle to invalidate in global coordiantes or %NULL for the
2502 * Invalidates the given area of the player. This causes this area to be
2503 * emitted as part of the SwfdecPlayer::invalidate signal.
2506 swfdec_player_invalidate (SwfdecPlayer
*player
, SwfdecMovie
*movie
, const SwfdecRect
*rect
)
2508 SwfdecPlayerPrivate
*priv
;
2513 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
2515 priv
= player
->priv
;
2519 if (swfdec_rect_is_empty (rect
))
2522 swfdec_rect_transform (&tmp
, rect
, &priv
->global_to_stage
);
2523 swfdec_rectangle_init_rect (&r
, &tmp
);
2524 swfdec_player_invalidate_movie (movie
,
2525 player
->priv
->global_to_stage
.xx
* SWFDEC_TWIPS_SCALE_FACTOR
,
2526 player
->priv
->global_to_stage
.yy
* SWFDEC_TWIPS_SCALE_FACTOR
,
2529 /* FIXME: currently we clamp the rectangle to the visible area, it might
2530 * be useful to allow out-of-bounds drawing. In that case this needs to be
2532 swfdec_rectangle_intersect (&r
, &r
, &priv
->stage
);
2533 if (swfdec_rectangle_is_empty (&r
))
2537 SWFDEC_LOG (" invalidating %d %d %d %d", r
.x
, r
.y
, r
.width
, r
.height
);
2538 /* FIXME: get region code into swfdec? */
2539 for (i
= 0; i
< priv
->invalidations
->len
; i
++) {
2540 SwfdecRectangle
*cur
= &g_array_index (priv
->invalidations
, SwfdecRectangle
, i
);
2541 if (swfdec_rectangle_contains (cur
, &r
))
2543 if (swfdec_rectangle_contains (&r
, cur
)) {
2548 if (i
== priv
->invalidations
->len
) {
2549 g_array_append_val (priv
->invalidations
, r
);
2551 SWFDEC_DEBUG ("toplevel invalidation of %d %d %d %d - now %u subregions",
2552 r
.x
, r
.y
, r
.width
, r
.height
,
2553 priv
->invalidations
->len
);
2557 swfdec_player_set_background_color (SwfdecPlayer
*player
, SwfdecColor bgcolor
)
2559 SwfdecPlayerPrivate
*priv
;
2561 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
2563 priv
= player
->priv
;
2564 if (priv
->bgcolor
) {
2565 SWFDEC_DEBUG ("not setting background color twice");
2569 SWFDEC_INFO ("setting bgcolor to %08X", bgcolor
);
2570 priv
->bgcolor
= bgcolor
;
2571 swfdec_player_invalidate (player
, NULL
, NULL
);
2572 g_object_notify (G_OBJECT (player
), "background-color");
2576 * swfdec_player_get_level:
2577 * @player: a #SwfdecPlayer
2578 * @name: a name that is supposed to refer to a level
2579 * @version: version to use for case sensitivity checks
2581 * Checks if the given @name refers to a level, and if so, returns the level.
2582 * An example for such a name is "_level5". These strings are used to refer to
2583 * root movies inside the Flash player.
2585 * Returns: the level referred to by @name or -1 if none
2588 swfdec_player_get_level (SwfdecPlayer
*player
, const char *name
, guint version
)
2593 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), -1);
2594 g_return_val_if_fail (name
!= NULL
, -1);
2596 /* check name starts with "_level" */
2597 if (swfdec_strncmp (version
, name
, "_level", 6) != 0)
2600 /* extract depth from rest string (or fail if it's not a depth) */
2602 l
= strtoul (name
, &end
, 10);
2603 if (errno
!= 0 || *end
!= 0 || l
> G_MAXINT
)
2609 swfdec_player_create_movie_at_level (SwfdecPlayer
*player
, SwfdecResource
*resource
,
2615 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), NULL
);
2616 g_return_val_if_fail (level
>= 0, NULL
);
2617 g_return_val_if_fail (swfdec_player_get_movie_at_level (player
, level
) == NULL
, NULL
);
2619 /* create new root movie */
2620 s
= swfdec_as_context_give_string (SWFDEC_AS_CONTEXT (player
), g_strdup_printf ("_level%d", level
));
2621 movie
= swfdec_movie_new (player
, level
- 16384, NULL
, resource
, NULL
, s
);
2622 movie
->name
= SWFDEC_AS_STR_EMPTY
;
2623 return SWFDEC_SPRITE_MOVIE (movie
);
2627 * swfdec_player_get_movie_at_level:
2628 * @player: a #SwfdecPlayer
2629 * @level: number of the level
2631 * This function is used to look up root movies in the given @player.
2633 * Returns: the #SwfdecMovie located at the given level or %NULL if there is no
2634 * movie at that level.
2637 swfdec_player_get_movie_at_level (SwfdecPlayer
*player
, int level
)
2642 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), NULL
);
2643 g_return_val_if_fail (level
>= 0, NULL
);
2645 depth
= level
- 16384;
2647 for (walk
= player
->priv
->roots
; walk
; walk
= walk
->next
) {
2648 SwfdecMovie
*cur
= walk
->data
;
2649 if (cur
->depth
< depth
)
2651 if (cur
->depth
== depth
)
2652 return SWFDEC_SPRITE_MOVIE (cur
);
2659 swfdec_player_launch_with_headers (SwfdecPlayer
*player
, const char *url
,
2660 const char *target
, SwfdecBuffer
*data
, guint header_count
,
2661 char **header_names
, char **header_values
)
2663 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
2664 g_return_if_fail (url
!= NULL
);
2665 g_return_if_fail (target
!= NULL
);
2666 g_return_if_fail (header_count
== 0 || header_names
!= NULL
);
2667 g_return_if_fail (header_count
== 0 || header_values
!= NULL
);
2668 g_return_if_fail (header_names
== NULL
||
2669 header_names
[header_count
] == NULL
);
2670 g_return_if_fail (header_values
== NULL
||
2671 header_values
[header_count
] == NULL
);
2673 if (!g_ascii_strncasecmp (url
, "FSCommand:", strlen ("FSCommand:"))) {
2674 const char *command
= url
+ strlen ("FSCommand:");
2675 g_signal_emit (player
, signals
[FSCOMMAND
], 0, command
, target
);
2678 g_signal_emit (player
, signals
[LAUNCH
], 0, url
, target
, data
, header_count
,
2679 header_names
, header_values
);
2683 swfdec_player_start_ticking (SwfdecPlayer
*player
)
2685 SwfdecPlayerPrivate
*priv
;
2687 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
2688 g_return_if_fail (player
->priv
->initialized
);
2689 g_return_if_fail (player
->priv
->iterate_timeout
.callback
== NULL
);
2691 priv
= player
->priv
;
2692 priv
->iterate_timeout
.callback
= swfdec_player_iterate
;
2693 priv
->iterate_timeout
.timestamp
= priv
->time
+ SWFDEC_TICKS_PER_SECOND
* 256 / priv
->rate
/ 10;
2694 swfdec_player_add_timeout (player
, &priv
->iterate_timeout
);
2695 SWFDEC_LOG ("initialized iterate timeout %p to %"G_GUINT64_FORMAT
" (now %"G_GUINT64_FORMAT
")",
2696 &priv
->iterate_timeout
, priv
->iterate_timeout
.timestamp
, priv
->time
);
2700 * swfdec_player_initialize:
2701 * @player: a #SwfdecPlayer
2702 * @version: Flash version to use
2703 * @rate: framerate in 256th or 0 for undefined
2704 * @width: width of movie
2705 * @height: height of movie
2707 * Initializes the player to the given @version, @width, @height and @rate. If
2708 * the player is already initialized, this function does nothing.
2711 swfdec_player_initialize (SwfdecPlayer
*player
, guint rate
, guint width
, guint height
)
2713 SwfdecPlayerPrivate
*priv
;
2715 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
2716 g_return_if_fail (rate
> 0);
2718 priv
= player
->priv
;
2719 if (!priv
->initialized
) {
2720 priv
->initialized
= TRUE
;
2721 g_object_notify (G_OBJECT (player
), "initialized");
2723 /* FIXME: need to kick all other movies out here */
2724 swfdec_player_stop_ticking (player
);
2727 SWFDEC_INFO ("initializing player to size %ux%u and rate %u/256", width
, height
, rate
);
2728 if (rate
!= priv
->rate
) {
2730 g_object_notify (G_OBJECT (player
), "rate");
2732 if (priv
->width
!= width
) {
2733 priv
->width
= width
;
2734 g_object_notify (G_OBJECT (player
), "default-width");
2736 if (priv
->height
!= height
) {
2737 priv
->height
= height
;
2738 g_object_notify (G_OBJECT (player
), "default-height");
2740 priv
->broadcasted_width
= priv
->internal_width
= priv
->stage_width
>= 0 ? (guint
) priv
->stage_width
: priv
->width
;
2741 priv
->broadcasted_height
= priv
->internal_height
= priv
->stage_height
>= 0 ? (guint
) priv
->stage_height
: priv
->height
;
2742 swfdec_player_update_scale (player
);
2746 * swfdec_player_get_export_class:
2747 * @player: a #SwfdecPlayer
2748 * @name: garbage-collected string naming the export
2750 * Looks up the constructor for characters that are exported using @name.
2752 * Returns: a #SwfdecAsObject naming the constructor or %NULL if none
2755 swfdec_player_get_export_class (SwfdecPlayer
*player
, const char *name
)
2757 SwfdecPlayerPrivate
*priv
= player
->priv
;
2758 SwfdecAsObject
*ret
;
2760 ret
= g_hash_table_lookup (priv
->registered_classes
, name
);
2762 SWFDEC_LOG ("found registered class %p for %s", ret
, name
);
2769 * swfdec_player_set_export_class:
2770 * @player: a #SwfdecPlayer
2771 * @name: garbage-collected string naming the export
2772 * @object: object to use as constructor or %NULL for none
2774 * Sets the constructor to be used for instances created using the object
2775 * exported with @name.
2778 swfdec_player_set_export_class (SwfdecPlayer
*player
, const char *name
, SwfdecAsObject
*object
)
2780 SwfdecPlayerPrivate
*priv
;
2782 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
2783 g_return_if_fail (name
!= NULL
);
2784 g_return_if_fail (object
== NULL
|| SWFDEC_IS_AS_OBJECT (object
));
2786 priv
= player
->priv
;
2788 SWFDEC_LOG ("setting class %p for %s", object
, name
);
2789 g_hash_table_insert (priv
->registered_classes
, (gpointer
) name
, object
);
2791 g_hash_table_remove (priv
->registered_classes
, name
);
2796 * swfdec_player_create_socket:
2797 * @player: a #SwfdecPlayer
2798 * @hostname: the host name to connect to.
2799 * @port: the port to connect to
2801 * Creates a new socket connecting to the given hostname and port.
2803 * Returns: a new socket
2806 swfdec_player_create_socket (SwfdecPlayer
*player
, const char *hostname
, guint port
)
2809 SwfdecSocketClass
*klass
;
2811 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), NULL
);
2812 g_return_val_if_fail (hostname
!= NULL
, NULL
);
2813 g_return_val_if_fail (port
> 0, NULL
);
2815 sock
= g_object_new (player
->priv
->socket_type
, NULL
);
2816 klass
= SWFDEC_SOCKET_GET_CLASS (sock
);
2817 klass
->connect (sock
, player
, hostname
, port
);
2823 swfdec_player_create_url (SwfdecPlayer
*player
, const char *string
)
2827 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), NULL
);
2828 g_return_val_if_fail (string
!= NULL
, NULL
);
2830 url
= swfdec_url_new_relative (player
->priv
->base_url
, string
);
2831 /* FIXME: check that we don't go below base for local urls */
2836 swfdec_player_load_with_headers (SwfdecPlayer
*player
, const char *url
,
2837 SwfdecBuffer
*buffer
, guint header_count
, const char **header_names
,
2838 const char **header_values
)
2840 SwfdecLoader
*loader
;
2841 SwfdecLoaderClass
*klass
;
2843 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), NULL
);
2844 g_return_val_if_fail (url
!= NULL
, NULL
);
2845 g_return_val_if_fail (header_count
== 0 || header_names
!= NULL
, NULL
);
2846 g_return_val_if_fail (header_count
== 0 || header_values
!= NULL
, NULL
);
2847 g_return_val_if_fail (header_names
== NULL
||
2848 header_names
[header_count
] == NULL
, NULL
);
2849 g_return_val_if_fail (header_values
== NULL
||
2850 header_values
[header_count
] == NULL
, NULL
);
2852 loader
= g_object_new (player
->priv
->loader_type
, NULL
);
2853 klass
= SWFDEC_LOADER_GET_CLASS (loader
);
2854 g_return_val_if_fail (klass
->load
!= NULL
, NULL
);
2855 klass
->load (loader
, player
, url
, buffer
, header_count
, header_names
,
2862 swfdec_player_add_missing_plugin (SwfdecPlayer
*player
, const char *detail
)
2864 SwfdecPlayerPrivate
*priv
;
2866 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
2867 g_return_if_fail (detail
!= NULL
);
2869 priv
= player
->priv
;
2870 if (g_slist_find_custom (priv
->missing_plugins
, detail
, (GCompareFunc
) strcmp
))
2873 SWFDEC_INFO ("adding missing plugin: %s\n", detail
);
2874 priv
->missing_plugins
= g_slist_prepend (priv
->missing_plugins
, g_strdup (detail
));
2878 swfdec_player_update_size (gpointer playerp
, gpointer unused
)
2880 SwfdecPlayer
*player
= playerp
;
2881 SwfdecPlayerPrivate
*priv
= player
->priv
;
2883 priv
->internal_width
= priv
->stage_width
>=0 ? (guint
) priv
->stage_width
: priv
->width
;
2884 priv
->internal_height
= priv
->stage_height
>=0 ? (guint
) priv
->stage_height
: priv
->height
;
2886 if (priv
->scale_mode
!= SWFDEC_SCALE_NONE
)
2889 /* only broadcast once */
2890 if (priv
->internal_width
== priv
->broadcasted_width
&&
2891 priv
->internal_height
== priv
->broadcasted_height
)
2894 priv
->broadcasted_width
= priv
->internal_width
;
2895 priv
->broadcasted_height
= priv
->internal_height
;
2896 swfdec_player_broadcast (player
, SWFDEC_AS_STR_Stage
, SWFDEC_AS_STR_onResize
, 0, NULL
);
2900 swfdec_player_set_fullscreen (SwfdecPlayer
*player
, gboolean fullscreen
)
2902 SwfdecPlayerPrivate
*priv
;
2906 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
2908 priv
= player
->priv
;
2909 if (priv
->fullscreen
== fullscreen
)
2912 if (fullscreen
&& !priv
->allow_fullscreen
) {
2913 SWFDEC_INFO ("going fullscreen not allowed");
2918 g_signal_emit (player
, signals
[QUERY_SIZE
], 0, fullscreen
,
2919 &priv
->stage_width
, &priv
->stage_height
, &result
);
2921 priv
->fullscreen
= fullscreen
;
2922 g_object_notify (G_OBJECT (player
), "fullscreen");
2923 SWFDEC_AS_VALUE_SET_BOOLEAN (&val
, fullscreen
);
2924 swfdec_player_update_scale (player
);
2925 if (SWFDEC_AS_CONTEXT (player
)->global
) {
2926 SwfdecSandbox
*sandbox
= swfdec_sandbox_get (player
);
2927 swfdec_sandbox_unuse (sandbox
);
2928 swfdec_player_update_size (player
, NULL
);
2929 swfdec_player_broadcast (player
, SWFDEC_AS_STR_Stage
, SWFDEC_AS_STR_onFullScreen
, 1, &val
);
2930 swfdec_sandbox_use (sandbox
);
2932 swfdec_player_update_size (player
, NULL
);
2933 swfdec_player_broadcast (player
, SWFDEC_AS_STR_Stage
, SWFDEC_AS_STR_onFullScreen
, 1, &val
);
2940 * swfdec_player_new:
2941 * @debugger: %NULL or a #SwfdecAsDebugger to use for debugging this player.
2943 * Creates a new player. This function is supposed to be used for testing.
2944 * Because of this, the created player will behave as predictable as possible.
2945 * For example, it will generate the same random number sequence every time.
2946 * The function calls swfdec_init () for you if it wasn't called before.
2948 * Returns: The new player
2951 swfdec_player_new (SwfdecAsDebugger
*debugger
)
2953 SwfdecPlayer
*player
;
2955 g_return_val_if_fail (debugger
== NULL
|| SWFDEC_IS_AS_DEBUGGER (debugger
), NULL
);
2958 player
= g_object_new (SWFDEC_TYPE_PLAYER
, "random-seed", 0,
2959 "loader-type", SWFDEC_TYPE_FILE_LOADER
, "socket-type", SWFDEC_TYPE_SOCKET
,
2961 "debugger", debugger
, NULL
);
2967 * swfdec_player_mouse_move:
2968 * @player: a #SwfdecPlayer
2969 * @x: x coordinate of mouse
2970 * @y: y coordinate of mouse
2972 * Updates the current mouse position. If the mouse has left the area of @player,
2973 * you should pass values outside the movie size for @x and @y. You will
2974 * probably want to call swfdec_player_advance() before to update the player to
2975 * the correct time when calling this function.
2977 * Returns: %TRUE if the mouse event was handled. %FALSE if the event should be
2978 * propagated further. A mouse event may not be handled if the user
2979 * clicked on a translucent area.
2982 swfdec_player_mouse_move (SwfdecPlayer
*player
, double x
, double y
)
2986 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), FALSE
);
2988 g_signal_emit (player
, signals
[HANDLE_MOUSE
], 0, x
, y
, 0, &ret
);
2994 * swfdec_player_mouse_press:
2995 * @player: a #SwfdecPlayer
2996 * @x: x coordinate of mouse
2997 * @y: y coordinate of mouse
2998 * @button: number of the button that was pressed. Swfdec supports up to 32
3001 * Tells the @player that the mouse button @button was pressed at the given
3004 * Returns: %TRUE if the mouse event was handled. %FALSE if the event should be
3005 * propagated further. A mouse event may not be handled if the user
3006 * clicked on a translucent area.
3009 swfdec_player_mouse_press (SwfdecPlayer
*player
, double x
, double y
,
3014 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), FALSE
);
3015 g_return_val_if_fail (button
> 0 && button
<= 32, FALSE
);
3017 g_signal_emit (player
, signals
[HANDLE_MOUSE
], 0, x
, y
, button
, &ret
);
3023 * swfdec_player_mouse_release:
3024 * @player: a #SwfdecPlayer
3025 * @x: x coordinate of mouse
3026 * @y: y coordinate of mouse
3027 * @button: number of the button that was released. Swfdec supports up to 32
3030 * Tells the @player that the mouse button @button was released at the given
3033 * Returns: %TRUE if the mouse event was handled. %FALSE if the event should be
3034 * propagated further. A mouse event may not be handled if the user
3035 * clicked on a translucent area.
3038 swfdec_player_mouse_release (SwfdecPlayer
*player
, double x
, double y
,
3043 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), FALSE
);
3044 g_return_val_if_fail (button
> 0 && button
<= 32, FALSE
);
3046 g_signal_emit (player
, signals
[HANDLE_MOUSE
], 0, x
, y
, -button
, &ret
);
3052 * swfdec_player_key_press:
3053 * @player: a #SwfdecPlayer
3054 * @keycode: the key that was pressed, must be smaller than 256.
3055 * @character: UCS4 of the character that was inserted or 0 if none
3057 * Call this function to make the @player react to a key press. A list of
3058 * defined key codes is defined by #SwfdecKey. You will likely need to
3059 * translate from your keyboard API to the Flash key codes.
3061 * Returns: %TRUE if the key press was handled by the @player, %FALSE if it
3062 * should be propagated further
3065 swfdec_player_key_press (SwfdecPlayer
*player
, guint keycode
, guint character
)
3069 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), FALSE
);
3070 g_return_val_if_fail (player
->priv
->has_focus
, FALSE
);
3071 g_return_val_if_fail (keycode
< 256, FALSE
);
3073 g_signal_emit (player
, signals
[HANDLE_KEY
], 0, keycode
, character
, TRUE
, &ret
);
3079 * swfdec_player_key_release:
3080 * @player: a #SwfdecPlayer
3081 * @keycode: the key that was released
3082 * @character: UCS4 of the character that was inserted or 0 if none
3084 * Call this function to make the @player react to a key being released. See
3085 * swfdec_player_key_press() for details.
3087 * Returns: %TRUE if the key press was handled by the @player, %FALSE if it
3088 * should be propagated further
3091 swfdec_player_key_release (SwfdecPlayer
*player
, guint keycode
, guint character
)
3095 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), FALSE
);
3096 g_return_val_if_fail (player
->priv
->has_focus
, FALSE
);
3097 g_return_val_if_fail (keycode
< 256, FALSE
);
3099 g_signal_emit (player
, signals
[HANDLE_KEY
], 0, keycode
, character
, FALSE
, &ret
);
3105 swfdec_player_render_focusrect (SwfdecPlayer
*player
, cairo_t
*cr
)
3107 #define LINE_WIDTH (3.0)
3108 SwfdecPlayerPrivate
*priv
;
3112 priv
= player
->priv
;
3113 if (swfdec_rect_is_empty (&priv
->focusrect
))
3116 rect
= priv
->focusrect
;
3118 /* I wonder why this has to be yellow... */
3119 cairo_set_source_rgb (cr
, 1.0, 1.0, 0.0);
3120 cairo_set_line_width (cr
, LINE_WIDTH
);
3121 swfdec_player_global_to_stage (player
, &rect
.x0
, &rect
.y0
);
3122 swfdec_player_global_to_stage (player
, &rect
.x1
, &rect
.y1
);
3123 w
= MAX (rect
.x1
- rect
.x0
- LINE_WIDTH
, 0);
3124 h
= MAX (rect
.y1
- rect
.y0
- LINE_WIDTH
, 0);
3125 cairo_rectangle (cr
, rect
.x0
+ LINE_WIDTH
/ 2, rect
.y0
+ LINE_WIDTH
/ 2, w
, h
);
3132 * swfdec_player_render:
3133 * @player: a #SwfdecPlayer
3134 * @cr: #cairo_t to render to
3136 * Renders the given area of the current frame to @cr. This function just calls
3137 * swfdec_player_render_with_renderer() using the @player's renderer.
3140 swfdec_player_render (SwfdecPlayer
*player
, cairo_t
*cr
)
3142 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
3143 g_return_if_fail (cr
!= NULL
);
3145 swfdec_player_render_with_renderer (player
, cr
, player
->priv
->renderer
);
3149 * swfdec_player_render_with_renderer:
3150 * @player: a #SwfdecPlayer
3151 * @cr: #cairo_t to render to
3152 * @renderer: Renderer to use for rendering
3154 * Renders the given area of the current frame to @cr. If you only want to
3155 * redraw parts of the player, like when responding to a
3156 * SwfdecPlayer:invalidate signal, set a clip on @cr using cairo_clip():
3157 * <informalexample><programlisting>
3158 * cairo_rectangle (cr, x, y, width, height);
3160 * swfdec_player_render_with_renderer (player, cr, renderer);
3161 * </programlisting></informalexample>
3162 * Only redrawing parts of the player improves performance considerably.
3165 swfdec_player_render_with_renderer (SwfdecPlayer
*player
, cairo_t
*cr
,
3166 SwfdecRenderer
*renderer
)
3168 static const SwfdecColorTransform trans
= { FALSE
, 256, 0, 256, 0, 256, 0, 256, 0 };
3169 SwfdecPlayerPrivate
*priv
;
3172 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
3173 g_return_if_fail (cr
!= NULL
);
3174 g_return_if_fail (SWFDEC_IS_RENDERER (renderer
));
3176 /* FIXME: fail when !initialized? */
3177 if (!swfdec_player_is_initialized (player
))
3180 priv
= player
->priv
;
3182 swfdec_renderer_attach (renderer
, cr
);
3185 /* compute the rectangle */
3186 SWFDEC_INFO ("=== %p: START RENDER ===", player
);
3187 /* convert the cairo matrix */
3188 cairo_transform (cr
, &priv
->global_to_stage
);
3190 for (walk
= priv
->roots
; walk
; walk
= walk
->next
) {
3191 SwfdecMovie
*movie
= walk
->data
;
3193 swfdec_movie_render (movie
, cr
, &trans
);
3196 /* NB: we render the focusrect after restoring, so the focusrect doesn't scale */
3197 swfdec_player_render_focusrect (player
, cr
);
3199 SWFDEC_INFO ("=== %p: END RENDER ===", player
);
3203 * swfdec_player_advance:
3204 * @player: the #SwfdecPlayer to advance
3205 * @msecs: number of milliseconds to advance at maximum
3207 * Advances @player by @msecs or at most one event, whatever happens first in
3208 * the player's timeline. You should make sure to call this function as often
3209 * as swfdec_player_get_next_event() indicates or your player will not appear
3212 * Returns: actual number of milliseconds advanced.
3215 swfdec_player_advance (SwfdecPlayer
*player
, gulong msecs
)
3217 SwfdecPlayerPrivate
*priv
;
3221 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), 0);
3223 /* find the max time to advance */
3224 max
= swfdec_player_get_next_event (player
);
3228 msecs
= MIN ((gulong
) max
, msecs
);
3229 priv
= player
->priv
;
3230 frames
= SWFDEC_TICKS_TO_SAMPLES (priv
->time
+ SWFDEC_MSECS_TO_TICKS (msecs
))
3231 - SWFDEC_TICKS_TO_SAMPLES (priv
->time
);
3232 g_signal_emit (player
, signals
[ADVANCE
], 0, msecs
, frames
);
3238 * swfdec_player_is_initialized:
3239 * @player: a #SwfdecPlayer
3241 * Determines if the @player is initalized yet. An initialized player is able
3242 * to provide basic values like width, height or rate. A player may not be
3243 * initialized if the loader it was started with does not reference a Flash
3244 * resources or it did not provide enough data yet. If a player is initialized,
3245 * it will never be uninitialized again.
3247 * Returns: TRUE if the basic values are known.
3250 swfdec_player_is_initialized (SwfdecPlayer
*player
)
3252 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), FALSE
);
3254 return player
->priv
->initialized
;
3258 * swfdec_player_get_next_event:
3259 * @player: ia #SwfdecPlayer
3261 * Queries how long to the next event. This is the next time when you should
3262 * call swfdec_player_advance() to forward to.
3264 * Returns: number of milliseconds until next event or -1 if no outstanding event
3267 swfdec_player_get_next_event (SwfdecPlayer
*player
)
3272 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), 0);
3274 if (swfdec_as_context_is_aborted (SWFDEC_AS_CONTEXT (player
)))
3277 tick
= swfdec_player_get_next_event_time (player
);
3278 if (tick
== G_MAXUINT64
)
3280 /* round up to full msecs */
3281 ret
= SWFDEC_TICKS_TO_MSECS (tick
+ SWFDEC_TICKS_PER_SECOND
/ 1000 - 1);
3287 * swfdec_player_get_rate:
3288 * @player: a #SwfdecPlayer
3290 * Queries the framerate of this movie. This number specifies the number
3291 * of frames that are supposed to pass per second. It is a multiple of 1/256.
3293 * Returns: The framerate of this movie or 0 if it isn't known yet or the
3294 * movie doesn't have a framerate.
3297 swfdec_player_get_rate (SwfdecPlayer
*player
)
3299 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), 0.0);
3301 return player
->priv
->rate
/ 256.0;
3305 * swfdec_player_get_default_size:
3306 * @player: a #SwfdecPlayer
3307 * @width: integer to store the width in or %NULL
3308 * @height: integer to store the height in or %NULL
3310 * If the default size of the movie is initialized, fills in @width and @height
3311 * with the size. Otherwise @width and @height are set to 0.
3314 swfdec_player_get_default_size (SwfdecPlayer
*player
, guint
*width
, guint
*height
)
3316 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
3319 *width
= player
->priv
->width
;
3321 *height
= player
->priv
->height
;
3325 * swfdec_player_get_size:
3326 * @player: a #SwfdecPlayer
3327 * @width: integer to store the width in or %NULL
3328 * @height: integer to store the height in or %NULL
3330 * Gets the currently set image size. If the default width or height should be
3331 * used, the width or height respectively is set to -1.
3334 swfdec_player_get_size (SwfdecPlayer
*player
, int *width
, int *height
)
3336 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
3339 *width
= player
->priv
->stage_width
;
3341 *height
= player
->priv
->stage_height
;
3345 * swfdec_player_set_size:
3346 * @player: a #SwfdecPlayer
3347 * @width: desired width of the movie or -1 for default
3348 * @height: desired height of the movie or -1 for default
3350 * Sets the image size to the given values. The image size is what the area that
3351 * the @player will render and advocate with scripts.
3354 swfdec_player_set_size (SwfdecPlayer
*player
, int width
, int height
)
3356 SwfdecPlayerPrivate
*priv
;
3357 gboolean changed
= FALSE
;
3359 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
3360 g_return_if_fail (width
>= -1);
3361 g_return_if_fail (height
>= -1);
3363 priv
= player
->priv
;
3364 if (priv
->stage_width
!= width
) {
3365 priv
->stage_width
= width
;
3366 g_object_notify (G_OBJECT (player
), "width");
3369 if (priv
->stage_height
!= height
) {
3370 priv
->stage_height
= height
;
3371 g_object_notify (G_OBJECT (player
), "height");
3374 swfdec_player_update_scale (player
);
3376 swfdec_player_add_external_action (player
, player
, swfdec_player_update_size
, NULL
);
3380 * swfdec_player_get_audio:
3381 * @player: a #SwfdecPlayer
3383 * Returns a list of all currently active audio streams in @player.
3385 * Returns: A #GList of #SwfdecAudio. You must not modify or free this list.
3387 /* FIXME: I don't like this function */
3389 swfdec_player_get_audio (SwfdecPlayer
* player
)
3391 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), NULL
);
3393 return player
->priv
->audio
;
3397 * swfdec_player_get_background_color:
3398 * @player: a #SwfdecPlayer
3400 * Gets the current suggested background color. The color will be an ARGB-color,
3401 * with the MSB being the alpha value. Note that Swfdec will not render the
3402 * background color itself, so if you want the background to not be translucent
3403 * it is your job to clear the background using this color.
3405 * Returns: the background color as an ARGB value
3408 swfdec_player_get_background_color (SwfdecPlayer
*player
)
3412 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), SWFDEC_COLOR_COMBINE (0xFF, 0xFF, 0xFF, 0xFF));
3414 bgcolor
= player
->priv
->bgcolor
;
3415 return bgcolor
? bgcolor
: SWFDEC_COLOR_WHITE
;
3419 * swfdec_player_get_scale_mode:
3420 * @player: a #SwfdecPlayer
3422 * Gets the currrent mode used for scaling the movie. See #SwfdecScaleMode for
3423 * the different modes.
3425 * Returns: the current scale mode
3428 swfdec_player_get_scale_mode (SwfdecPlayer
*player
)
3430 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), SWFDEC_SCALE_SHOW_ALL
);
3432 return player
->priv
->scale_mode
;
3436 * swfdec_player_set_scale_mode:
3437 * @player: a #SwfdecPlayer
3438 * @mode: a #SwfdecScaleMode
3440 * Sets the currrent mode used for scaling the movie. See #SwfdecScaleMode for
3441 * the different modes.
3444 swfdec_player_set_scale_mode (SwfdecPlayer
*player
, SwfdecScaleMode mode
)
3446 SwfdecPlayerPrivate
*priv
;
3448 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
3450 priv
= player
->priv
;
3451 if (priv
->scale_mode
!= mode
) {
3452 priv
->scale_mode
= mode
;
3453 swfdec_player_update_scale (player
);
3454 g_object_notify (G_OBJECT (player
), "scale-mode");
3455 swfdec_player_add_external_action (player
, player
, swfdec_player_update_size
, NULL
);
3460 * swfdec_player_get_alignment:
3461 * @player: a #SwfdecPlayer
3463 * Gets the alignment of the player. The alignment describes what point is used
3464 * as the anchor for drawing the contents. See #SwfdecAlignment for possible
3467 * Returns: the current alignment
3470 swfdec_player_get_alignment (SwfdecPlayer
*player
)
3472 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), SWFDEC_ALIGNMENT_CENTER
);
3474 return swfdec_player_alignment_from_flags (player
->priv
->align_flags
);
3478 * swfdec_player_set_alignment:
3479 * @player: a #SwfdecPlayer
3480 * @align: #SwfdecAlignment to set
3482 * Sets the alignment to @align. For details about alignment, see
3483 * swfdec_player_get_alignment() and #SwfdecAlignment.
3486 swfdec_player_set_alignment (SwfdecPlayer
*player
, SwfdecAlignment align
)
3490 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
3492 flags
= swfdec_player_alignment_to_flags (align
);
3493 swfdec_player_set_align_flags (player
, flags
);
3497 swfdec_player_set_align_flags (SwfdecPlayer
*player
, guint flags
)
3499 SwfdecPlayerPrivate
*priv
;
3501 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
3503 priv
= player
->priv
;
3504 if (flags
!= priv
->align_flags
) {
3505 priv
->align_flags
= flags
;
3506 swfdec_player_update_scale (player
);
3507 g_object_notify (G_OBJECT (player
), "alignment");
3512 * swfdec_player_get_maximum_runtime:
3513 * @player: a #SwfdecPlayer
3515 * Queries the given @player for how long scripts may run. see
3516 * swfdec_player_set_maximum_runtime() for a longer discussion of this value.
3518 * Returns: the maximum time in milliseconds that scripts are allowed to run or
3522 swfdec_player_get_maximum_runtime (SwfdecPlayer
*player
)
3524 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), 0);
3526 return player
->priv
->max_runtime
;
3530 * swfdec_player_set_maximum_runtime:
3531 * @player: a #SwfdecPlayer
3532 * @msecs: time in milliseconds that scripts are allowed to run or 0 for
3535 * Sets the time that the player may use to let internal scripts run. If the
3536 * Flash file that is currently played back does not manage to complete its
3537 * scripts in the given time, it is aborted. You cannot continue the scripts at
3538 * a later point in time. However, your application may become unresponsive and
3539 * your users annoyed if they cannot interact with it for too long. To give a
3540 * reference point, the Adobe Flash player usually sets this value to 10
3541 * seconds. Note that this time determines the maximum time calling
3542 * swfdec_player_advance() may take, even if it is called with a large value.
3543 * Also note that this setting is ignored when running inside a debugger.
3546 swfdec_player_set_maximum_runtime (SwfdecPlayer
*player
, gulong msecs
)
3548 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
3550 player
->priv
->max_runtime
= msecs
;
3551 g_object_notify (G_OBJECT (player
), "max-runtime");
3555 * swfdec_player_get_scripting:
3556 * @player: a #SwfdecPlayer
3558 * Gets the current scripting implementation in use. If no implementation is in
3559 * use (the default), %NULL is returned.
3561 * Returns: the current scripting implementation used or %NULL if none
3563 SwfdecPlayerScripting
*
3564 swfdec_player_get_scripting (SwfdecPlayer
*player
)
3566 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), NULL
);
3568 return player
->priv
->scripting
;
3572 * swfdec_player_set_scripting:
3573 * @player: a #SwfdecPlayer
3574 * @scripting: the scripting implementation to use or %NULL to disable scripting
3576 * Sets the implementation to use for external scripting in the given @player.
3577 * Note that this is different from the internal script engine. See the
3578 * #SwfdecPlayerScripting paragraph for details about external scripting.
3581 swfdec_player_set_scripting (SwfdecPlayer
*player
, SwfdecPlayerScripting
*scripting
)
3583 SwfdecPlayerPrivate
*priv
;
3585 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
3586 g_return_if_fail (scripting
== NULL
|| SWFDEC_IS_PLAYER_SCRIPTING (scripting
));
3588 priv
= player
->priv
;
3589 if (priv
->scripting
== scripting
)
3592 if (priv
->scripting
)
3593 g_object_unref (priv
->scripting
);
3594 priv
->scripting
= g_object_ref (scripting
);
3595 g_object_notify (G_OBJECT (player
), "scripting");
3599 swfdec_player_update_focus (gpointer playerp
, gpointer unused
)
3601 SwfdecPlayer
*player
= playerp
;
3602 SwfdecPlayerPrivate
*priv
= player
->priv
;
3604 if (priv
->has_focus
) {
3605 if (priv
->focus
== NULL
)
3606 swfdec_player_grab_focus (player
, priv
->focus_previous
);
3608 swfdec_player_grab_focus (player
, NULL
);
3613 * swfdec_player_get_focus:
3614 * @player: a #SwfdecPlayer
3616 * Checks if the @player has keyboard focus. See swfdec_player_set_focus() for
3619 * Returns: %TRUE if the player has keyboard focus.
3622 swfdec_player_get_focus (SwfdecPlayer
*player
)
3624 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), FALSE
);
3626 return player
->priv
->has_focus
;
3630 * swfdec_player_set_focus:
3631 * @player: the player
3632 * @focus: if the player is focussed
3634 * Tells the @player whether keyboard focus is inside it. The player will use
3635 * this information to draw focus indicators around objects. Note that this
3636 * update will not happen immediately, but only the next time you call
3637 * swfdec_player_advance(). The player is focussed by default. So if you
3638 * integrate it into a widget system such, you likely want to unset this upon
3639 * creation of the player.
3640 * <note><para>The player must be focussed to receive keyboard events.</para>
3644 swfdec_player_set_focus (SwfdecPlayer
*player
, gboolean focus
)
3646 SwfdecPlayerPrivate
*priv
;
3648 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
3650 priv
= player
->priv
;
3651 if (priv
->has_focus
== focus
)
3654 priv
->has_focus
= focus
;
3655 swfdec_player_add_external_action (player
, player
, swfdec_player_update_focus
, NULL
);
3656 g_object_notify (G_OBJECT (player
), "focus");
3660 * swfdec_player_get_renderer:
3663 * Gets the current renderer in use. See swfdec_player_set_renderer() for
3666 * Returns: the current #SwfdecRenderer in use.
3669 swfdec_player_get_renderer (SwfdecPlayer
*player
)
3671 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), NULL
);
3673 return player
->priv
->renderer
;
3677 * swfdec_player_set_renderer:
3679 * @renderer: the renderer to use
3681 * Sets the renderer to be used by the @player. Setting the correct renderer is
3682 * mostly relevant for TextField flash objects with native fonts, as the
3683 * renderer provides those. It can also be very relevant for performance
3684 * reasons. See the #SwfdecRenderer documentation for details.
3687 swfdec_player_set_renderer (SwfdecPlayer
*player
, SwfdecRenderer
*renderer
)
3689 SwfdecPlayerPrivate
*priv
;
3691 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
3693 priv
= player
->priv
;
3695 g_object_ref (renderer
);
3697 renderer
= swfdec_renderer_new_default (player
);
3700 g_object_unref (priv
->renderer
);
3701 priv
->renderer
= renderer
;
3702 g_object_notify (G_OBJECT (player
), "renderer");
3706 * swfdec_player_get_base_url:
3707 * @player: a #SwfdecPlayer
3709 * Gets the base URL that this player uses when resolving a relative URL. It is
3710 * automatically set to the parent directory of the currently played back
3711 * resource, but can be changed using swfdec_player_set_base_url(). When no
3712 * resource has been set on the @player yet, %NULL is returned.
3714 * Returns: the base #SwfdecURL for resolving relative links or %NULL
3717 swfdec_player_get_base_url (SwfdecPlayer
*player
)
3719 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), NULL
);
3721 return player
->priv
->base_url
;
3725 * swfdec_player_set_base_url:
3726 * @player: a #SwfdecPlayer
3727 * @url: a #SwfdecURL or %NULL to reset to defaults
3729 * Sets the URL that will be used for resolving realtive links inside the
3733 swfdec_player_set_base_url (SwfdecPlayer
*player
, const SwfdecURL
*url
)
3735 SwfdecPlayerPrivate
*priv
;
3737 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
3739 priv
= player
->priv
;
3741 swfdec_url_free (priv
->base_url
);
3744 priv
->base_url
= swfdec_url_new_parent (priv
->url
);
3746 priv
->base_url
= NULL
;
3749 priv
->base_url
= swfdec_url_copy (url
);
3751 g_object_notify (G_OBJECT (player
), "base-url");
3755 * swfdec_player_get_url:
3756 * @player: a #SwfdecPlayer
3758 * Gets the URL of the resource that is currently played back. If no URL has
3759 * been set on the @player yet, %NULL is returned.
3761 * Returns: the #SwfdecURL currently played back or %NULL
3764 swfdec_player_get_url (SwfdecPlayer
*player
)
3766 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), NULL
);
3768 if (player
->priv
->resource
== NULL
)
3771 return swfdec_loader_get_url (player
->priv
->resource
->loader
);
3775 * swfdec_player_set_url:
3776 * @player: a #SwfdecPlayer
3777 * @url: the url for the initial reference in this player
3779 * Sets the @url for the main data. This function may only be called once.
3782 swfdec_player_set_url (SwfdecPlayer
*player
, const SwfdecURL
*url
)
3784 SwfdecPlayerPrivate
*priv
;
3785 SwfdecLoader
*loader
;
3788 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
3789 g_return_if_fail (player
->priv
->url
== NULL
);
3790 g_return_if_fail (url
!= NULL
);
3792 g_object_freeze_notify (G_OBJECT (player
));
3793 priv
= player
->priv
;
3794 priv
->url
= swfdec_url_copy (url
);
3795 if (priv
->base_url
== NULL
) {
3796 priv
->base_url
= swfdec_url_new_parent (url
);
3797 g_object_notify (G_OBJECT (player
), "base-url");
3799 /* we initialize url and base_url before requesting the loader, so the loader
3801 loader
= swfdec_player_load (player
, swfdec_url_get_url (url
), NULL
);
3802 priv
->resource
= swfdec_resource_new (player
, loader
, priv
->variables
);
3803 movie
= swfdec_movie_new (player
, -16384, NULL
, priv
->resource
, NULL
, SWFDEC_AS_STR__level0
);
3804 SWFDEC_ACTOR (movie
)->focusrect
= SWFDEC_FLASH_YES
;
3805 movie
->name
= SWFDEC_AS_STR_EMPTY
;
3806 g_object_unref (loader
);
3807 g_object_notify (G_OBJECT (player
), "url");
3808 g_object_thaw_notify (G_OBJECT (player
));
3812 * swfdec_player_get_variables:
3813 * @player: a #SwfdecPlayer
3815 * Gets the initial variables for this player. See swfdec_player_set_variables()
3816 * for details about variables.
3818 * Returns: a string represetation of the current variables or %NULL if none are
3819 * set on the @player.
3822 swfdec_player_get_variables (SwfdecPlayer
*player
)
3824 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), NULL
);
3826 return player
->priv
->variables
;
3830 * swfdec_player_set_variables:
3831 * @player: a #SwfdecPlayer
3832 * @variables: a string that is checked to be in 'application/x-www-form-urlencoded'
3833 * syntax describing the arguments to set on the new player or NULL for
3836 * Sets the loader for the main data. This function may only be called if
3837 * swfdec_player_set_url() has not been called yet.
3838 * If the @variables are set and validate, they will be set as properties on the
3842 swfdec_player_set_variables (SwfdecPlayer
*player
, const char *variables
)
3844 SwfdecPlayerPrivate
*priv
;
3846 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
3847 g_return_if_fail (player
->priv
->url
== NULL
);
3849 priv
= player
->priv
;
3850 g_free (priv
->variables
);
3851 priv
->variables
= g_strdup (variables
);
3852 g_object_notify (G_OBJECT (player
), "variables");
3856 * swfdec_player_get_fullscreen:
3857 * @player: the player
3859 * CHecks if the player is in fullscreen mode currently. If the player is
3860 * in fullscreen mode, it assumes it occupies the whole screen. A player will
3861 * only ever go into fullscreen, if you have allowed it by calling
3862 * swfdec_player_set_allow_fullscreen().
3864 * Returns: %TRUE if the player is in fullscreen mode currently
3867 swfdec_player_get_fullscreen (SwfdecPlayer
*player
)
3869 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), FALSE
);
3871 return player
->priv
->fullscreen
;
3875 * swfdec_player_get_allow_fullscreen:
3876 * @player: the player
3878 * Checks if the player is allowed to go fullscreen. See
3879 * swfdec_player_set_allow_fullscreen() for details.
3881 * Returns: %TRUE if the player is allowed to go fullscreen
3884 swfdec_player_get_allow_fullscreen (SwfdecPlayer
*player
)
3886 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), FALSE
);
3888 return player
->priv
->allow_fullscreen
;
3892 * swfdec_player_set_allow_fullscreen:
3893 * @player: the player
3894 * @allow: if the player should be allowed to go fullscreen
3896 * Sets if the player is allowed to go fullscreen. If a player is allowed to go
3897 * fullscreen, it may set the SwfdecPlayer::fullscreen property to %TRUE.
3898 * Players are not allowed to go fullscreen by default. Usually applications
3899 * only want to allow going fullscreen in response to mouse or keyboard events.
3902 swfdec_player_set_allow_fullscreen (SwfdecPlayer
*player
, gboolean allow
)
3904 g_return_if_fail (SWFDEC_IS_PLAYER (player
));
3906 player
->priv
->allow_fullscreen
= allow
;
3907 g_object_notify (G_OBJECT (player
), "allow-fullscreen");
3911 * swfdec_player_get_selection:
3912 * @player: the player
3914 * Retrieves the currently selected text of the player. If no text is currently
3915 * selected, %NULL is returned.
3917 * Returns: the currently selected text or %NULL
3920 swfdec_player_get_selection (SwfdecPlayer
*player
)
3922 g_return_val_if_fail (SWFDEC_IS_PLAYER (player
), NULL
);
3924 return player
->priv
->selection
;