📄 swfdec_player.c
字号:
/* FIXME: need to do anything with old drag? */ player->mouse_drag = drag; player->mouse_drag_center = center; if (rect) { player->mouse_drag_rect = *rect; } else { player->mouse_drag_rect.x0 = -G_MAXDOUBLE; player->mouse_drag_rect.y0 = -G_MAXDOUBLE; player->mouse_drag_rect.x1 = G_MAXDOUBLE; player->mouse_drag_rect.y1 = G_MAXDOUBLE; } SWFDEC_DEBUG ("starting drag in %g %g %g %g", player->mouse_drag_rect.x0, player->mouse_drag_rect.y0, player->mouse_drag_rect.x1, player->mouse_drag_rect.y1); /* FIXME: need a way to make sure we get updated */ if (drag) { swfdec_movie_update (drag); swfdec_player_update_drag_movie (player); }}static voidswfdec_player_update_mouse_position (SwfdecPlayer *player){ GList *walk; SwfdecMovie *mouse_grab = NULL; if (player->mouse_button) { mouse_grab = player->mouse_grab; } else { /* if the mouse button is pressed the grab widget stays the same (I think) */ for (walk = g_list_last (player->roots); walk; walk = walk->prev) { mouse_grab = swfdec_movie_get_movie_at (walk->data, player->mouse_x, player->mouse_y); if (mouse_grab) break; } } SWFDEC_DEBUG ("%s %p has mouse at %g %g", mouse_grab ? G_OBJECT_TYPE_NAME (mouse_grab) : "---", mouse_grab, player->mouse_x, player->mouse_y); if (player->mouse_grab && mouse_grab != player->mouse_grab) swfdec_movie_send_mouse_change (player->mouse_grab, TRUE); player->mouse_grab = mouse_grab; if (mouse_grab) swfdec_movie_send_mouse_change (mouse_grab, FALSE);}static voidswfdec_player_do_mouse_move (SwfdecPlayer *player){ GList *walk; swfdec_player_update_drag_movie (player); for (walk = player->movies; walk; walk = walk->next) { swfdec_movie_queue_script (walk->data, SWFDEC_EVENT_MOUSE_MOVE); } swfdec_listener_execute (player->mouse_listener, "onMouseMove"); swfdec_player_update_mouse_position (player);}static voidswfdec_player_do_mouse_button (SwfdecPlayer *player){ GList *walk; guint event; const char *event_name; if (player->mouse_button) { event = SWFDEC_EVENT_MOUSE_DOWN; event_name = "onMouseDown"; } else { event = SWFDEC_EVENT_MOUSE_UP; event_name = "onMouseUp"; } for (walk = player->movies; walk; walk = walk->next) { swfdec_movie_queue_script (walk->data, event); } swfdec_listener_execute (player->mouse_listener, event_name); if (player->mouse_grab) swfdec_movie_send_mouse_change (player->mouse_grab, FALSE);}static voidswfdec_player_emit_signals (SwfdecPlayer *player){ GList *walk; /* emit invalidate signal */ if (!swfdec_rect_is_empty (&player->invalid)) { double x, y, width, height; /* FIXME: currently we clamp the rectangle to the visible area, it might * be useful to allow out-of-bounds drawing. In that case this needs to be * changed */ x = SWFDEC_TWIPS_TO_DOUBLE (player->invalid.x0); x = MAX (x, 0.0); y = SWFDEC_TWIPS_TO_DOUBLE (player->invalid.y0); y = MAX (y, 0.0); width = SWFDEC_TWIPS_TO_DOUBLE (player->invalid.x1 - player->invalid.x0); width = MIN (width, player->width - x); height = SWFDEC_TWIPS_TO_DOUBLE (player->invalid.y1 - player->invalid.y0); height = MIN (height, player->height - y); g_signal_emit (player, signals[INVALIDATE], 0, x, y, width, height); swfdec_rect_init_empty (&player->invalid); } /* emit audio-added for all added audio streams */ for (walk = player->audio; walk; walk = walk->next) { SwfdecAudio *audio = walk->data; if (audio->added) continue; g_signal_emit (player, signals[AUDIO_ADDED], 0, audio); audio->added = TRUE; }}static gbooleanswfdec_player_do_handle_mouse (SwfdecPlayer *player, double x, double y, int button){ swfdec_player_lock (player); x *= SWFDEC_TWIPS_SCALE_FACTOR; y *= SWFDEC_TWIPS_SCALE_FACTOR; SWFDEC_LOG ("handling mouse at %g %g %d", x, y, button); if (player->mouse_x != x || player->mouse_y != y) { player->mouse_x = x; player->mouse_y = y; swfdec_player_do_mouse_move (player); } if (player->mouse_button != button) { player->mouse_button = button; swfdec_player_do_mouse_button (player); } swfdec_player_perform_actions (player); swfdec_player_unlock (player); /* FIXME: allow events to pass through */ return TRUE;}static voidswfdec_player_iterate (SwfdecTimeout *timeout){ SwfdecPlayer *player = SWFDEC_PLAYER ((void *) timeout - G_STRUCT_OFFSET (SwfdecPlayer, iterate_timeout)); GList *walk; SWFDEC_INFO ("=== START ITERATION ==="); /* First, we prepare the iteration. We flag all movies for removal that will * be removed */ for (walk = player->movies; walk; walk = walk->next) { if (SWFDEC_IS_SPRITE_MOVIE (walk->data)) swfdec_sprite_movie_prepare (walk->data); } /* Step 2: start the iteration. This performs a goto next frame on all * movies that are not stopped. It also queues onEnterFrame. */ for (walk = player->movies; walk; walk = walk->next) { SwfdecMovieClass *klass = SWFDEC_MOVIE_GET_CLASS (walk->data); if (klass->iterate_start) klass->iterate_start (walk->data); } swfdec_player_perform_actions (player); SWFDEC_INFO ("=== STOP ITERATION ==="); /* this loop allows removal of walk->data */ walk = player->movies; while (walk) { SwfdecMovie *cur = walk->data; SwfdecMovieClass *klass = SWFDEC_MOVIE_GET_CLASS (cur); walk = walk->next; g_assert (klass->iterate_end); if (!klass->iterate_end (cur)) swfdec_movie_destroy (cur); } /* add timeout again */ /* FIXME: rounding issues? */ player->iterate_timeout.timestamp += SWFDEC_TICKS_PER_SECOND * 256 / player->rate; swfdec_player_add_timeout (player, &player->iterate_timeout);}static voidswfdec_player_do_advance (SwfdecPlayer *player, guint msecs, guint audio_samples){ GList *walk; SwfdecAudio *audio; SwfdecTimeout *timeout; SwfdecTick target_time; guint frames_now; swfdec_player_lock (player); target_time = player->time + SWFDEC_MSECS_TO_TICKS (msecs); SWFDEC_DEBUG ("advancing %u msecs (%u audio frames)", msecs, audio_samples); player->audio_skip = audio_samples; /* iterate all playing sounds */ walk = player->audio; while (walk) { audio = walk->data; walk = walk->next; if (swfdec_audio_iterate (audio, audio_samples) == 0) swfdec_audio_remove (audio); } for (timeout = player->timeouts ? player->timeouts->data : NULL; timeout && timeout->timestamp <= target_time; timeout = player->timeouts ? player->timeouts->data : NULL) { player->timeouts = g_list_remove (player->timeouts, timeout); frames_now = SWFDEC_TICKS_TO_SAMPLES (timeout->timestamp) - SWFDEC_TICKS_TO_SAMPLES (player->time); player->time = timeout->timestamp; player->audio_skip -= frames_now; SWFDEC_LOG ("activating timeout %p now (timeout is %"G_GUINT64_FORMAT", target time is %"G_GUINT64_FORMAT, timeout, timeout->timestamp, target_time); timeout->callback (timeout); swfdec_player_perform_actions (player); } if (target_time > player->time) { frames_now = SWFDEC_TICKS_TO_SAMPLES (target_time) - SWFDEC_TICKS_TO_SAMPLES (player->time); player->time = target_time; player->audio_skip -= frames_now; } g_assert (player->audio_skip == 0); swfdec_player_unlock (player);}voidswfdec_player_perform_actions (SwfdecPlayer *player){ GList *walk; SwfdecRect old_inval; g_return_if_fail (SWFDEC_IS_PLAYER (player)); swfdec_rect_init_empty (&old_inval); do { while (swfdec_player_do_action (player)); for (walk = player->roots; walk; walk = walk->next) { swfdec_movie_update (walk->data); } /* update the state of the mouse when stuff below it moved */ if (swfdec_rect_contains (&player->invalid, player->mouse_x, player->mouse_y)) { SWFDEC_INFO ("=== NEED TO UPDATE mouse post-iteration ==="); swfdec_player_update_mouse_position (player); for (walk = player->roots; walk; walk = walk->next) { swfdec_movie_update (walk->data); } } swfdec_rect_union (&old_inval, &old_inval, &player->invalid); swfdec_rect_init_empty (&player->invalid); } while (swfdec_ring_buffer_get_n_elements (player->actions) > 0); player->invalid = old_inval;}voidswfdec_player_lock (SwfdecPlayer *player){ g_return_if_fail (SWFDEC_IS_PLAYER (player)); g_assert (swfdec_ring_buffer_get_n_elements (player->actions) == 0); g_assert (swfdec_rect_is_empty (&player->invalid)); g_object_freeze_notify (G_OBJECT (player)); SWFDEC_DEBUG ("LOCKED");}voidswfdec_player_unlock (SwfdecPlayer *player){ g_return_if_fail (SWFDEC_IS_PLAYER (player)); g_assert (swfdec_ring_buffer_get_n_elements (player->actions) == 0); SWFDEC_DEBUG ("UNLOCK"); swfdec_player_update_mouse_cursor (player); g_object_thaw_notify (G_OBJECT (player)); swfdec_player_emit_signals (player);}static gbooleanswfdec_accumulate_or (GSignalInvocationHint *ihint, GValue *return_accu, const GValue *handler_return, gpointer data){ if (g_value_get_boolean (handler_return)) g_value_set_boolean (return_accu, TRUE); return TRUE;}static voidswfdec_player_class_init (SwfdecPlayerClass *klass){ GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->get_property = swfdec_player_get_property; object_class->set_property = swfdec_player_set_property; object_class->dispose = swfdec_player_dispose; g_object_class_install_property (object_class, PROP_INITIALIZED, g_param_spec_boolean ("initialized", "initialized", "TRUE when the player has initialized its basic values", FALSE, G_PARAM_READABLE)); g_object_class_install_property (object_class, PROP_MOUSE_CURSOR, g_param_spec_enum ("mouse-cursor", "mouse cursor", "how the mouse pointer should be presented", SWFDEC_TYPE_MOUSE_CURSOR, SWFDEC_MOUSE_CURSOR_NONE, G_PARAM_READABLE)); g_object_class_install_property (object_class, PROP_NEXT_EVENT, g_param_spec_uint ("next-event", "next event", "how many milliseconds until the next event or 0 when no event pending", 0, G_MAXUINT, 0, G_PARAM_READABLE)); g_object_class_install_property (object_class, PROP_CACHE_SIZE, g_param_spec_uint ("cache-size", "cache size", "maximum cache size in bytes", 0, G_MAXUINT, 50 * 1024 * 1024, G_PARAM_READABLE)); g_object_class_install_property (object_class, PROP_BACKGROUND_COLOR, g_param_spec_uint ("background-color", "background color", "ARGB color used to draw the background", 0, G_MAXUINT, SWFDEC_COLOR_COMBINE (0xFF, 0xFF, 0xFF, 0xFF), G_PARAM_READWRITE)); /** * SwfdecPlayer::trace: * @player: the #SwfdecPlayer affected * @text: the debugging string * * Emits a debugging string while running. The effect of calling any swfdec * functions on the emitting @player is undefined. */ signals[TRACE] = g_signal_new ("trace", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); /** * SwfdecPlayer::invalidate: * @player: the #SwfdecPlayer affected * @x: x coordinate of invalid region * @y: y coordinate of invalid region * @width: width of invalid region * @height: height of invalid region * * This signal is emitted whenever graphical elements inside the player have * changed. The coordinates describe the smallest rectangle that includes all * changes. */ signals[INVALIDATE] = g_signal_new ("invalidate", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, swfdec_marshal_VOID__DOUBLE_DOUBLE_DOUBLE_DOUBLE, G_TYPE_NONE, 4, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE); /** * SwfdecPlayer::advance: * @player: the #SwfdecPlayer affected * @msecs: the amount of milliseconds the player will advance * @audio_samples: number of frames the audio is advanced (in 44100Hz steps) * * Emitted whenever the player advances. */ signals[ADVANCE] = g_signal_new ("advance", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (SwfdecPlayerClass, advance), NULL, NULL, swfdec_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); /** * SwfdecPlayer::handle-mouse: * @player: the #SwfdecPlayer affected * @x: new x coordinate of the mouse * @y: new y coordinate of the mouse * @button: 1 if the button is pressed, 0 if not * * this signal is emitted whenever @player should respond to a mouse event. If * any of the handlers returns TRUE, swfdec_player_handle_mouse() will return * TRUE. Note that unlike many event handlers in gtk, returning TRUE will not * stop further event handlers from being invoked. Use g_signal_stop_emission() * in that case. * * Returns: TRUE if this handler handles the event. **/ signals[HANDLE_MOUSE] = g_signal_new ("handle-mouse", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (SwfdecPlayerClass, handle_mouse), swfdec_accumulate_or, NULL, swfdec_marshal_BOOLEAN__DOUBLE_DOUBLE_INT, G_TYPE_BOOLEAN, 3, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_INT); /** * SwfdecPlayer::audio-added: * @player: the #SwfdecPlayer affected * @audio: the audio stream that was added * * Emitted whenever a new audio stream was added to @player. */ signals[AUDIO_ADDED] = g_signal_new ("audio-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, SWFDEC_TYPE_AUDIO); /** * SwfdecPlayer::audio-removed: * @player: the #SwfdecPlayer affected * @audio: the audio stream that was removed * * Emitted whenever an audio stream was removed from @player. The stream will * have been added with the SwfdecPlayer::audio-added signal previously. */ signals[AUDIO_REMOVED] = g_signal_new ("audio-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, SWFDEC_TYPE_AUDIO); /** * SwfdecPlayer::launch: * @player: the #SwfdecPlayer affected * @url: URL to open * @target: target to load the URL into * * Emitted whenever the @player encounters an URL that should be loaded into * a target the Flash player does not recognize. In most cases this happens * when the user clicks a link in an embedded Flash movie that should open a * new web page. * The effect of calling any swfdec functions on the emitting @player is undefined. */ signals[LAUNCH] = g_signal_new ("launch", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, swfdec_marshal_VOID__STRING_STRING, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); klass->advance = swfdec_player_do_advance; klass->handle_mouse = swfdec_player_do_handle_mouse;}static voidswfdec_player_init (SwfdecPlayer *player){ swfdec_js_init_player (player); player->registered_classes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); player->actions = swfdec_ring_buffer_new_for_type (SwfdecPlayerAction, 16); player->cache = swfdec_cache_new (50 * 1024 * 1024); /* 100 MB */ player->bgcolor = SWFDEC_COLOR_COMBINE (0xFF, 0xFF, 0xFF, 0xFF); player->mouse_visible = TRUE; player->mouse_cursor = SWFDEC_MOUSE_CURSOR_NORMAL; player->iterate_timeout.callback = swfdec_player_iterate; player->init_queue = g_queue_new (); player->construct_queue = g_queue_new ();}voidswfdec_player_stop_all_sounds (SwfdecPlayer *player){ g_return_if_fail (SWFDEC_IS_PLAYER (player)); while (player->audio) { swfdec_audio_remove (player->audio->data); }}voidswfdec_player_trace (SwfdecPlayer *player, const char *text){ g_return_if_fail (SWFDEC_IS_PLAYER (player)); g_return_if_fail (text != NULL); /* FIXME: accumulate and emit after JS handling? */ g_signal_emit (player, signals[TRACE], 0, text);}voidswfdec_player_invalidate (SwfdecPlayer *player, const SwfdecRect *rect){ if (swfdec_rect_is_empty (rect)) { g_assert_not_reached (); return; } swfdec_rect_union (&player->invalid, &player->invalid, rect); SWFDEC_DEBUG ("toplevel invalidation of %g %g %g %g - invalid region now %g %g %g %g", rect->x0, rect->y0, rect->x1, rect->y1, player->invalid.x0, player->invalid.y0, player->invalid.x1, player->invalid.y1);}SwfdecRootMovie *swfdec_player_add_level_from_loader (SwfdecPlayer *player, guint depth, SwfdecLoader *loader, const char *variables){ SwfdecMovie *movie; SwfdecRootMovie *root; swfdec_player_remove_level (player, depth); movie = swfdec_movie_new_for_player (player, depth); root = SWFDEC_ROOT_MOVIE (movie); root->player = player; root->loader = loader; if (variables) swfdec_scriptable_set_variables (SWFDEC_SCRIPTABLE (movie), variables); swfdec_loader_set_target (root->loader, SWFDEC_LOADER_TARGET (root)); return root;}voidswfdec_player_remove_level (SwfdecPlayer *player, guint depth){ GList *walk; int real_depth; real_depth = (int) depth - 16384; for (walk = player->roots; walk; walk = walk->next) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -