⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swfdec_player.c

📁 Swfdec still is development software, but has also followed a rigid no-crashes-allowed policy. I b
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Swfdec * Copyright (C) 2006-2007 Benjamin Otte <otte@gnome.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. *  * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. *  * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor,  * Boston, MA  02110-1301  USA */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <math.h>#include <stdlib.h>#include <liboil/liboil.h>#include "swfdec_player_internal.h"#include "swfdec_audio_internal.h"#include "swfdec_button_movie.h" /* for mouse cursor */#include "swfdec_cache.h"#include "swfdec_debug.h"#include "swfdec_enums.h"#include "swfdec_event.h"#include "swfdec_js.h"#include "swfdec_listener.h"#include "swfdec_loader_internal.h"#include "swfdec_marshal.h"#include "swfdec_movie.h"#include "swfdec_root_movie.h"#include "swfdec_sprite_movie.h"/*** gtk-doc ***//** * SECTION:SwfdecPlayer * @title: SwfdecPlayer * @short_description: main playback object * * A #SwfdecPlayer is the main object used for playing back Flash files through * Swfdec. * * A player interacts with the outside world in a multitude of ways. The most  * important ones are described below. * * Input is handled via the  * <link linkend="swfdec-SwfdecLoader">SwfdecLoader</link> class. A  * #SwfdecLoader is set on a new player using swfdec_player_set_loader(). * * When the loader has provided enough data, you can start playing the file. * This is done in steps by calling swfdec_player_advance() - preferrably as  * often as swfdec_player_get_next_event() indicates. Or you can provide user input * to the player by calling for example swfdec_player_handle_mouse(). * * You can use swfdec_player_render() to draw the current state of the player. * After that, connect to the SwfdecPlayer::invalidate signal to be notified of * changes. * * Audio output is handled via the  * <link linkend="swfdec-SwfdecAudio">SwfdecAudio</link> class. One  * #SwfdecAudio object is created for every output using the  * SwfdecPlayer::audio-added signal. *//** * SwfdecPlayer: * * This is the base object used for playing Flash files. *//** * SECTION:Enumerations * @title: Enumerations * @short_description: enumerations used in Swfdec * * This file lists all of the enumerations used in various parts of Swfdec. *//** * SwfdecMouseCursor: * @SWFDEC_MOUSE_CURSOR_NORMAL: a normal mouse cursor * @SWFDEC_MOUSE_CURSOR_NONE: no mouse image * @SWFDEC_MOUSE_CURSOR_TEXT: a mouse cursor suitable for text editing * @SWFDEC_MOUSE_CURSOR_CLICK: a mouse cursor for clicking a hyperlink or a  *                             button * * This enumeration describes the possible types for the SwfdecPlayer::mouse-cursor * property. *//*** Timeouts ***/static SwfdecTickswfdec_player_get_next_event_time (SwfdecPlayer *player){  if (player->timeouts) {    return ((SwfdecTimeout *) player->timeouts->data)->timestamp - player->time;  } else {    return 0;  }}/** * swfdec_player_add_timeout: * @player: a #SwfdecPlayer * @timeout: timeout to add * * Adds a timeout to @player. The timeout will be removed automatically when  * triggered, so you need to use swfdec_player_add_timeout() to add it again.  * The #SwfdecTimeout struct and callback does not use a data callback pointer.  * It's suggested that you use the struct as part of your own bigger struct  * and get it back like this: * <programlisting> * typedef struct { *   // ... *   SwfdecTimeout timeout; * } MyStruct; * * static void * my_struct_timeout_callback (SwfdecTimeout *timeout) * { *   MyStruct *mystruct = (MyStruct *) ((void *) timeout - G_STRUCT_OFFSET (MyStruct, timeout)); * *   // do stuff * } * </programlisting> **/voidswfdec_player_add_timeout (SwfdecPlayer *player, SwfdecTimeout *timeout){  GList *walk;  SwfdecTick next_tick;  g_return_if_fail (SWFDEC_IS_PLAYER (player));  g_return_if_fail (timeout != NULL);  g_return_if_fail (timeout->timestamp > player->time);  g_return_if_fail (timeout->callback != NULL);  SWFDEC_LOG ("adding timeout %p", timeout);  next_tick = swfdec_player_get_next_event_time (player);  /* the order is important, on events with the same time, we make sure the new one is last */  for (walk = player->timeouts; walk; walk = walk->next) {    SwfdecTimeout *cur = walk->data;    if (cur->timestamp > timeout->timestamp)      break;  }  player->timeouts = g_list_insert_before (player->timeouts, walk, timeout);  if (next_tick != swfdec_player_get_next_event_time (player))    g_object_notify (G_OBJECT (player), "next-event");}/** * swfdec_player_remove_timeout: * @player: a #SwfdecPlayer * @timeout: a timeout that should be removed * * Removes the @timeout from the list of scheduled timeouts. THe tiemout must  * have been added with swfdec_player_add_timeout() before. **/voidswfdec_player_remove_timeout (SwfdecPlayer *player, SwfdecTimeout *timeout){  SwfdecTick next_tick;  g_return_if_fail (SWFDEC_IS_PLAYER (player));  g_return_if_fail (timeout != NULL);  g_return_if_fail (timeout->timestamp > player->time);  g_return_if_fail (timeout->callback != NULL);  SWFDEC_LOG ("removing timeout %p", timeout);  next_tick = swfdec_player_get_next_event_time (player);  player->timeouts = g_list_remove (player->timeouts, timeout);  if (next_tick != swfdec_player_get_next_event_time (player))    g_object_notify (G_OBJECT (player), "next-event");}/*** Actions ***/typedef struct {  gpointer		object;  SwfdecActionFunc	func;  gpointer		data;} SwfdecPlayerAction;/** * swfdec_player_add_action: * @player: a #SwfdecPlayer * @object: object identifying the action * @action_func: function to execute * @action_data: additional data to pass to @func * * Adds an action to the @player. Actions are used by Flash player to solve * reentrancy issues. Instead of calling back into the Actionscript engine, * an action is queued for later execution. So if you're writing code that * is calling Actionscript code, you want to do this by using actions. **/voidswfdec_player_add_action (SwfdecPlayer *player, gpointer object,    SwfdecActionFunc action_func, gpointer action_data){  SwfdecPlayerAction *action;  g_return_if_fail (SWFDEC_IS_PLAYER (player));  g_return_if_fail (object != NULL);  g_return_if_fail (action_func != NULL);  SWFDEC_LOG ("adding action %p %p %p", object, action_func, action_data);  action = swfdec_ring_buffer_push (player->actions);  if (action == NULL) {    /* FIXME: limit number of actions to not get inf loops due to scripts? */    swfdec_ring_buffer_set_size (player->actions,	swfdec_ring_buffer_get_size (player->actions) + 16);    action = swfdec_ring_buffer_push (player->actions);    g_assert (action);  }  action->object = object;  action->func = action_func;  action->data = action_data;}/** * swfdec_player_remove_all_actions: * @player: a #SwfdecPlayer * @object: object pointer identifying the actions to be removed * * Removes all actions associated with @object. See swfdec_player_add_action() * for details about actions. **/voidswfdec_player_remove_all_actions (SwfdecPlayer *player, gpointer object){  SwfdecPlayerAction *action;  guint i;  g_return_if_fail (SWFDEC_IS_PLAYER (player));  g_return_if_fail (object != NULL);  for (i = 0; i < swfdec_ring_buffer_get_n_elements (player->actions); i++) {    action = swfdec_ring_buffer_peek_nth (player->actions, i);    if (action->object == object) {      SWFDEC_LOG ("removing action %p %p %p", 	  action->object, action->func, action->data);      action->object = NULL;    }  }}static gbooleanswfdec_player_do_action (SwfdecPlayer *player){  SwfdecPlayerAction *action;  SwfdecMovie *movie;  movie = g_queue_peek_head (player->init_queue);  if (movie) {    swfdec_movie_run_init (movie);    return TRUE;  }  movie = g_queue_peek_head (player->construct_queue);  if (movie) {    swfdec_movie_run_construct (movie);    return TRUE;  }  do {    action = swfdec_ring_buffer_pop (player->actions);    if (action == NULL)      return FALSE;  } while (action->object == NULL); /* skip removed actions */  action->func (action->object, action->data);  SWFDEC_LOG ("executing action %p %p %p",       action->object, action->func, action->data);  return TRUE;}/*** SwfdecPlayer ***/enum {  TRACE,  INVALIDATE,  ADVANCE,  HANDLE_MOUSE,  AUDIO_ADDED,  AUDIO_REMOVED,  LAUNCH,  LAST_SIGNAL};static guint signals[LAST_SIGNAL];enum {  PROP_0,  PROP_CACHE_SIZE,  PROP_INITIALIZED,  PROP_MOUSE_CURSOR,  PROP_NEXT_EVENT,  PROP_BACKGROUND_COLOR};G_DEFINE_TYPE (SwfdecPlayer, swfdec_player, G_TYPE_OBJECT)voidswfdec_player_remove_movie (SwfdecPlayer *player, SwfdecMovie *movie){  swfdec_movie_remove (movie);  player->movies = g_list_remove (player->movies, movie);}static voidswfdec_player_get_property (GObject *object, guint param_id, GValue *value,     GParamSpec * pspec){  SwfdecPlayer *player = SWFDEC_PLAYER (object);    switch (param_id) {    case PROP_BACKGROUND_COLOR:      g_value_set_uint (value, swfdec_player_get_background_color (player));      break;    case PROP_CACHE_SIZE:      g_value_set_uint (value, player->cache->max_size);      break;    case PROP_INITIALIZED:      g_value_set_boolean (value, swfdec_player_is_initialized (player));      break;    case PROP_MOUSE_CURSOR:      g_value_set_enum (value, player->mouse_cursor);      break;    case PROP_NEXT_EVENT:      g_value_set_uint (value, swfdec_player_get_next_event (player));      break;    default:      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);      break;  }}static voidswfdec_player_set_property (GObject *object, guint param_id, const GValue *value,    GParamSpec *pspec){  SwfdecPlayer *player = SWFDEC_PLAYER (object);  switch (param_id) {    case PROP_BACKGROUND_COLOR:      swfdec_player_set_background_color (player, g_value_get_uint (value));      break;    case PROP_CACHE_SIZE:      player->cache->max_size = g_value_get_uint (value);      break;    default:      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);      break;  }}static gbooleanfree_registered_class (gpointer key, gpointer value, gpointer playerp){  SwfdecPlayer *player = playerp;  g_free (key);  JS_RemoveRoot (player->jscx, value);  g_free (value);  return TRUE;}static voidswfdec_player_dispose (GObject *object){  SwfdecPlayer *player = SWFDEC_PLAYER (object);  swfdec_player_stop_all_sounds (player);  /* this must happen before we finish the JS player, we have roots in there */  g_hash_table_foreach_steal (player->registered_classes, free_registered_class, player);  g_hash_table_destroy (player->registered_classes);  while (player->roots)    swfdec_movie_destroy (player->roots->data);  swfdec_js_finish_player (player);  swfdec_player_remove_all_actions (player, player); /* HACK to allow non-removable actions */  g_assert (swfdec_ring_buffer_pop (player->actions) == NULL);  swfdec_ring_buffer_free (player->actions);  g_assert (player->movies == NULL);  g_assert (player->audio == NULL);  if (player->rate) {    swfdec_player_remove_timeout (player, &player->iterate_timeout);  }  g_assert (player->timeouts == NULL);  g_assert (g_queue_is_empty (player->init_queue));  g_assert (g_queue_is_empty (player->construct_queue));  g_queue_free (player->init_queue);  g_queue_free (player->construct_queue);  swfdec_cache_unref (player->cache);  if (player->loader) {    g_object_unref (player->loader);    player->loader = NULL;  }  G_OBJECT_CLASS (swfdec_player_parent_class)->dispose (object);}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 mouse_x, mouse_y;  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);  mouse_x = player->mouse_x;  mouse_y = player->mouse_y;  swfdec_movie_global_to_local (movie->parent, &mouse_x, &mouse_y);  mouse_x = CLAMP (mouse_x, player->mouse_drag_rect.x0, player->mouse_drag_rect.x1);  mouse_y = CLAMP (mouse_y, player->mouse_drag_rect.y0, player->mouse_drag_rect.y1);  SWFDEC_LOG ("mouse is at %g %g, orighinally (%g %g)", mouse_x, mouse_y, player->mouse_x, player->mouse_y);  if (player->mouse_drag_center) {    x = (movie->extents.x1 + movie->extents.x0) / 2;    y = (movie->extents.y1 + movie->extents.y0) / 2;  } else {    x = 0;    y = 0;  }  SWFDEC_LOG ("center is at %g %g, mouse is at %g %g", x, y, mouse_x, mouse_y);  if (mouse_x - x != movie->matrix.x0 || mouse_y -y != movie->matrix.y0) {    movie->matrix.x0 += mouse_x - x;    movie->matrix.y0 += mouse_y - 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));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -