📄 swfdec_player.c
字号:
SWFDEC_DEBUG ("broadcasting message %s.%s", object_name, signal); obj = SWFDEC_AS_CONTEXT (player)->global; swfdec_as_object_get_variable (obj, object_name, &val); if (!SWFDEC_AS_VALUE_IS_OBJECT (&val)) return; obj = SWFDEC_AS_VALUE_GET_OBJECT (&val); SWFDEC_AS_VALUE_SET_STRING (&val, signal); swfdec_as_object_call (obj, SWFDEC_AS_STR_broadcastMessage, 1, &val, NULL);}static voidswfdec_player_update_mouse_cursor (SwfdecPlayer *player){ SwfdecMouseCursor new = SWFDEC_MOUSE_CURSOR_NORMAL; if (!player->mouse_visible) { new = SWFDEC_MOUSE_CURSOR_NONE; } else if (player->mouse_grab != NULL) { /* FIXME: this needs to be more sophisticated, since SwfdecEditText may * want to have different mouse cursors depending on location (it supports * links in theory) */ if (SWFDEC_IS_BUTTON_MOVIE (player->mouse_grab)) new = SWFDEC_MOUSE_CURSOR_CLICK; } if (new != player->mouse_cursor) { player->mouse_cursor = new; g_object_notify (G_OBJECT (player), "mouse-cursor"); }}static voidswfdec_player_update_drag_movie (SwfdecPlayer *player){ double x, y; SwfdecMovie *movie; if (player->mouse_drag == NULL) return; movie = player->mouse_drag; g_assert (movie->cache_state == SWFDEC_MOVIE_UP_TO_DATE); x = player->mouse_x; y = player->mouse_y; swfdec_player_stage_to_global (player, &x, &y); if (movie->parent) swfdec_movie_global_to_local (movie->parent, &x, &y); if (player->mouse_drag_center) { x -= (movie->extents.x1 - movie->extents.x0) / 2; y -= (movie->extents.y1 - movie->extents.y0) / 2; } else { x -= player->mouse_drag_x; y -= player->mouse_drag_y; } x = CLAMP (x, player->mouse_drag_rect.x0, player->mouse_drag_rect.x1); y = CLAMP (y, player->mouse_drag_rect.y0, player->mouse_drag_rect.y1); SWFDEC_LOG ("mouse is at %g %g, originally (%g %g)", x, y, player->mouse_x, player->mouse_y); if (x != movie->matrix.x0 || y != movie->matrix.y0) { movie->matrix.x0 = x; movie->matrix.y0 = y; swfdec_movie_queue_update (movie, SWFDEC_MOVIE_INVALID_MATRIX); }}/** * swfdec_player_set_drag_movie: * @player: a #SwfdecPlayer * @drag: the movie to be dragged by the mouse or NULL to unset * @center: TRUE if the center of @drag should be at the mouse pointer, FALSE if (0,0) * of @drag should be at the mouse pointer. * @rect: NULL or the rectangle that clips the mouse position. The coordinates * are in the coordinate system of the parent of @drag. * * Sets or unsets the movie that is dragged by the mouse. **/voidswfdec_player_set_drag_movie (SwfdecPlayer *player, SwfdecMovie *drag, gboolean center, SwfdecRect *rect){ g_return_if_fail (SWFDEC_IS_PLAYER (player)); g_return_if_fail (drag == NULL || SWFDEC_IS_MOVIE (drag)); /* FIXME: need to do anything with old drag? */ player->mouse_drag = drag; player->mouse_drag_center = center; if (drag && !center) { player->mouse_drag_x = player->mouse_x; player->mouse_drag_y = player->mouse_y; swfdec_player_stage_to_global (player, &player->mouse_drag_x, &player->mouse_drag_y); if (drag->parent) swfdec_movie_global_to_local (drag->parent, &player->mouse_drag_x, &player->mouse_drag_y); player->mouse_drag_x -= drag->matrix.x0; player->mouse_drag_y -= drag->matrix.y0; } 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); drag->modified = TRUE; 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 { double x, y; /* if the mouse button is pressed the grab widget stays the same (I think) */ x = player->mouse_x; y = player->mouse_y; swfdec_player_stage_to_global (player, &x, &y); for (walk = g_list_last (player->roots); walk; walk = walk->prev) { mouse_grab = swfdec_movie_get_movie_at (walk->data, x, 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_player_broadcast (player, SWFDEC_AS_STR_Mouse, SWFDEC_AS_STR_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 = SWFDEC_AS_STR_onMouseDown; } else { event = SWFDEC_EVENT_MOUSE_UP; event_name = SWFDEC_AS_STR_onMouseUp; } for (walk = player->movies; walk; walk = walk->next) { swfdec_movie_queue_script (walk->data, event); } swfdec_player_broadcast (player, SWFDEC_AS_STR_Mouse, 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 */ swfdec_player_global_to_stage (player, &player->invalid.x0, &player->invalid.y0); swfdec_player_global_to_stage (player, &player->invalid.x1, &player->invalid.y1); x = MAX (player->invalid.x0, 0.0); y = MAX (player->invalid.y0, 0.0); width = MIN (player->invalid.x1, player->stage_width) - x; height = MIN (player->invalid.y1, player->stage_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_key (SwfdecPlayer *player, guint keycode, guint character, gboolean down){ g_assert (keycode < 256); /* set the correct variables */ player->last_keycode = keycode; player->last_character = character; if (down) { player->key_pressed[keycode / 8] |= 1 << keycode % 8; } else { player->key_pressed[keycode / 8] &= ~(1 << keycode % 8); } swfdec_player_broadcast (player, SWFDEC_AS_STR_Stage, down ? SWFDEC_AS_STR_onKeyDown : SWFDEC_AS_STR_onKeyUp); return TRUE;}static gbooleanswfdec_player_do_handle_mouse (SwfdecPlayer *player, double x, double y, int button){ swfdec_player_lock (player); 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;}voidswfdec_player_global_to_stage (SwfdecPlayer *player, double *x, double *y){ g_return_if_fail (SWFDEC_IS_PLAYER (player)); g_return_if_fail (x != NULL); g_return_if_fail (y != NULL); *x = *x / SWFDEC_TWIPS_SCALE_FACTOR * player->scale_x + player->offset_x; *y = *y / SWFDEC_TWIPS_SCALE_FACTOR * player->scale_y + player->offset_y;}voidswfdec_player_stage_to_global (SwfdecPlayer *player, double *x, double *y){ g_return_if_fail (SWFDEC_IS_PLAYER (player)); g_return_if_fail (x != NULL); g_return_if_fail (y != NULL); *x = (*x - player->offset_x) / player->scale_x * SWFDEC_TWIPS_SCALE_FACTOR; *y = (*y - player->offset_y) / player->scale_y * SWFDEC_TWIPS_SCALE_FACTOR;}static voidswfdec_player_iterate (SwfdecTimeout *timeout){ SwfdecPlayer *player = SWFDEC_PLAYER ((guint8 *) timeout - G_STRUCT_OFFSET (SwfdecPlayer, iterate_timeout)); GList *walk; swfdec_player_perform_external_actions (player); SWFDEC_INFO ("=== START ITERATION ==="); /* 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; double x, y; 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 */ x = player->mouse_x; y = player->mouse_y; swfdec_player_stage_to_global (player, &x, &y); if (swfdec_rect_contains (&player->invalid, x, 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;}/* used for breakpoints */voidswfdec_player_lock_soft (SwfdecPlayer *player){ g_return_if_fail (SWFDEC_IS_PLAYER (player)); g_assert (swfdec_rect_is_empty (&player->invalid)); g_object_freeze_notify (G_OBJECT (player)); SWFDEC_DEBUG ("LOCKED");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -