rewrite SwfdecAudioFormat handling
[swfdec.git] / libswfdec / swfdec_sprite.c
blobf0b49bd54cc59435dcd5269796fd0ff0e7cc297a
1 /* Swfdec
2 * Copyright (C) 2003-2006 David Schleef <ds@schleef.org>
3 * 2005-2006 Eric Anholt <eric@anholt.net>
4 * 2006-2007 Benjamin Otte <otte@gnome.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include <string.h>
27 #include "swfdec_sprite.h"
28 #include "swfdec_debug.h"
29 #include "swfdec_movie.h"
30 #include "swfdec_player_internal.h"
31 #include "swfdec_script.h"
32 #include "swfdec_sound.h"
33 #include "swfdec_sprite_movie.h"
34 #include "swfdec_swf_decoder.h"
35 #include "swfdec_tag.h"
37 G_DEFINE_TYPE (SwfdecSprite, swfdec_sprite, SWFDEC_TYPE_GRAPHIC)
39 void
40 swfdec_content_free (SwfdecContent *content)
42 g_free (content->name);
43 if (content->events)
44 swfdec_event_list_free (content->events);
45 g_free (content);
48 static void
49 swfdec_sprite_dispose (GObject *object)
51 SwfdecSprite * sprite = SWFDEC_SPRITE (object);
52 guint i;
54 if (sprite->frames) {
55 for (i = 0; i < sprite->n_frames; i++) {
56 g_free (sprite->frames[i].label);
57 if (sprite->frames[i].sound_head)
58 g_object_unref (sprite->frames[i].sound_head);
59 if (sprite->frames[i].sound_block) {
60 swfdec_buffer_unref (sprite->frames[i].sound_block);
62 g_slist_foreach (sprite->frames[i].sound, (GFunc) swfdec_sound_chunk_free, NULL);
63 g_slist_free (sprite->frames[i].sound);
65 g_free(sprite->frames);
67 for (i = 0; i < sprite->actions->len; i++) {
68 SwfdecSpriteAction *cur = &g_array_index (sprite->actions, SwfdecSpriteAction, i);
69 if (cur->buffer)
70 swfdec_buffer_unref (cur->buffer);
72 g_array_free (sprite->actions, TRUE);
73 sprite->actions = NULL;
74 if (sprite->init_action) {
75 swfdec_script_unref (sprite->init_action);
76 sprite->init_action = NULL;
79 G_OBJECT_CLASS (swfdec_sprite_parent_class)->dispose (object);
82 void
83 swfdec_sprite_add_sound_chunk (SwfdecSprite * sprite, guint frame,
84 SwfdecBuffer * chunk, int skip, guint n_samples)
86 g_assert (sprite->frames != NULL);
87 g_assert (chunk != NULL || n_samples == 0);
89 if (sprite->frames[frame].sound_head == NULL) {
90 SWFDEC_ERROR ("attempting to add a sound block without previous sound head");
91 swfdec_buffer_unref (chunk);
92 return;
94 if (sprite->frames[frame].sound_block) {
95 SWFDEC_ERROR ("attempting to add 2 sound blocks to one frame");
96 swfdec_buffer_unref (chunk);
97 return;
99 SWFDEC_LOG ("adding %u samples in %u bytes to frame %u", n_samples,
100 chunk ? chunk->length : 0, frame);
101 sprite->frames[frame].sound_skip = skip;
102 sprite->frames[frame].sound_block = chunk;
103 sprite->frames[frame].sound_samples = n_samples *
104 swfdec_audio_format_get_granularity (sprite->frames[frame].sound_head->original_format);
107 void
108 swfdec_sprite_add_action (SwfdecSprite *sprite, guint tag, SwfdecBuffer *buffer)
110 SwfdecSpriteAction action;
112 action.tag = tag;
113 action.buffer = buffer;
114 g_array_append_val (sprite->actions, action);
117 gboolean
118 swfdec_sprite_get_action (SwfdecSprite *sprite, guint n, guint *tag, SwfdecBuffer **buffer)
120 SwfdecSpriteAction *action;
122 g_return_val_if_fail (SWFDEC_IS_SPRITE (sprite), FALSE);
123 g_return_val_if_fail (tag != NULL, FALSE);
124 g_return_val_if_fail (buffer != NULL, FALSE);
126 if (n >= sprite->actions->len)
127 return FALSE;
128 action = &g_array_index (sprite->actions, SwfdecSpriteAction, n);
129 *tag = action->tag;
130 *buffer = action->buffer;
131 return TRUE;
135 tag_func_set_background_color (SwfdecSwfDecoder * s, guint tag)
137 SwfdecPlayer *player = SWFDEC_DECODER (s)->player;
138 SwfdecColor color = swfdec_bits_get_color (&s->b);
140 if (player->bgcolor_set) {
141 /* only an INFO because it can be set by user, should be error if we check duplication of tag */
142 SWFDEC_INFO ("background color has been set to %X already, setting to %X ignored",
143 player->bgcolor, color);
144 } else {
145 SWFDEC_LOG ("setting background color to %X", color);
146 /* can't use swfdec_player_set_background_color() here, because the player is locked and doesn't emit signals */
147 player->bgcolor = color;
148 player->bgcolor_set = TRUE;
149 player->invalid_extents = player->stage;
150 g_array_set_size (player->invalidations, 1);
151 g_array_index (player->invalidations, SwfdecRectangle, 0) = player->stage;
152 g_object_notify (G_OBJECT (player), "background-color");
155 return SWFDEC_STATUS_OK;
158 SwfdecContent *
159 swfdec_content_new (int depth)
161 SwfdecContent *content = g_new0 (SwfdecContent, 1);
163 cairo_matrix_init_identity (&content->transform);
164 swfdec_color_transform_init_identity (&content->color_transform);
165 content->depth = depth;
166 return content;
169 static SwfdecMovie *
170 swfdec_sprite_create_movie (SwfdecGraphic *graphic, gsize *size)
172 SwfdecSpriteMovie *ret = g_object_new (SWFDEC_TYPE_SPRITE_MOVIE, NULL);
174 ret->sprite = SWFDEC_SPRITE (graphic);
175 *size = sizeof (SwfdecSpriteMovie);
177 return SWFDEC_MOVIE (ret);
180 static void
181 swfdec_sprite_class_init (SwfdecSpriteClass * g_class)
183 GObjectClass *object_class = G_OBJECT_CLASS (g_class);
184 SwfdecGraphicClass *graphic_class = SWFDEC_GRAPHIC_CLASS (g_class);
186 object_class->dispose = swfdec_sprite_dispose;
188 graphic_class->create_movie = swfdec_sprite_create_movie;
191 static void
192 swfdec_sprite_init (SwfdecSprite * sprite)
194 sprite->actions = g_array_new (FALSE, FALSE, sizeof (SwfdecSpriteAction));
197 void
198 swfdec_sprite_set_n_frames (SwfdecSprite *sprite, guint n_frames,
199 guint rate)
201 guint i;
203 g_return_if_fail (SWFDEC_IS_SPRITE (sprite));
204 if (n_frames == 0)
205 n_frames = 1;
207 sprite->frames = g_new0 (SwfdecSpriteFrame, n_frames);
208 sprite->n_frames = n_frames;
210 if (rate > 0) {
211 for (i = 0; i < n_frames; i++) {
212 sprite->frames[i].sound_samples = 44100 * 256 / rate;
216 SWFDEC_LOG ("n_frames = %d", sprite->n_frames);
220 swfdec_sprite_get_frame (SwfdecSprite *sprite, const char *label)
222 guint i;
224 g_return_val_if_fail (SWFDEC_IS_SPRITE (sprite), -1);
225 g_return_val_if_fail (label != NULL, -1);
227 for (i = 0; i < SWFDEC_SPRITE (sprite)->n_frames; i++) {
228 SwfdecSpriteFrame *frame = &sprite->frames[i];
229 if (frame->label == NULL)
230 continue;
231 if (g_str_equal (frame->label, label))
232 return i;
234 return -1;