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
28 #ifdef CAIRO_HAS_SVG_SURFACE
29 # include <cairo-svg.h>
31 #ifdef CAIRO_HAS_PDF_SURFACE
32 # include <cairo-pdf.h>
34 #include <swfdec/swfdec.h>
35 #include <swfdec/swfdec_audio_stream.h>
36 #include <swfdec/swfdec_button.h>
37 #include <swfdec/swfdec_graphic.h>
38 #include <swfdec/swfdec_image.h>
39 #include <swfdec/swfdec_player_internal.h>
40 #include <swfdec/swfdec_sound.h>
41 #include <swfdec/swfdec_sprite.h>
42 #include <swfdec/swfdec_sprite_movie.h>
43 #include <swfdec/swfdec_swf_decoder.h>
44 #include <swfdec/swfdec_renderer_internal.h>
45 #include <swfdec/swfdec_resource.h>
48 encode_wav (SwfdecBuffer
*buffer
)
50 SwfdecBuffer
*wav
= swfdec_buffer_new (buffer
->length
+ 44);
55 /* FIXME: too much magic in this memmove */
56 memmove (data
, "RIFF----WAVEfmt \020\0\0\0"
57 "\001\0ccRRRRbbbbAAbbdata", 40);
58 *(guint32
*) (void *) &data
[4] = GUINT32_TO_LE (buffer
->length
+ 36);
60 *(guint16
*) (void *) &data
[22] = GUINT16_TO_LE (44100);
62 *(guint32
*) (void *) &data
[24] = GUINT32_TO_LE (2);
64 *(guint16
*) (void *) &data
[34] = GUINT16_TO_LE (16);
66 *(guint16
*) (void *) &data
[32] = GUINT16_TO_LE (16 * 2);
67 /* bytes per second */
68 *(guint32
*) (void *) &data
[28] = GUINT32_TO_LE (16 * 2 * 44100);
69 *(guint32
*) (void *) &data
[40] = GUINT32_TO_LE (buffer
->length
);
71 for (i
= 0; i
< buffer
->length
; i
+= 2) {
72 *(gint16
*) (void *) (data
+ i
) = GINT16_TO_LE (*(gint16
* ) (void *) (buffer
->data
+ i
));
78 export_sound (SwfdecSound
*sound
, const char *filename
)
81 SwfdecBuffer
*wav
, *buffer
;
83 /* try to render the sound, that should decode it. */
84 buffer
= swfdec_sound_get_decoded (sound
);
86 g_printerr ("Couldn't decode sound. For extraction of streams extract the sprite.\n");
89 wav
= encode_wav (buffer
);
90 if (!g_file_set_contents (filename
, (char *) wav
->data
,
91 wav
->length
, &error
)) {
92 g_printerr ("Couldn't save sound to file \"%s\": %s\n", filename
, error
->message
);
93 swfdec_buffer_unref (wav
);
97 swfdec_buffer_unref (wav
);
102 export_sprite_sound (SwfdecSprite
*sprite
, const char *filename
)
104 g_printerr ("FIXME: Someone implement sound export from sprites plz\n");
107 GError
*error
= NULL
;
110 SwfdecBufferQueue
*queue
;
111 SwfdecBuffer
*buffer
, *wav
;
113 audio
= swfdec_audio_stream_new (NULL
, sprite
, i
);
115 queue
= swfdec_buffer_queue_new ();
117 buffer
= swfdec_buffer_new0 (i
* 4);
119 swfdec_audio_render (audio
, (gint16
*) (void *) buffer
->data
, 0, i
);
121 i
= swfdec_audio_iterate (audio
, i
);
123 swfdec_buffer_queue_push (queue
, buffer
);
125 depth
= swfdec_buffer_queue_get_depth (queue
);
127 swfdec_buffer_queue_unref (queue
);
128 g_printerr ("Sprite contains no sound\n");
131 buffer
= swfdec_buffer_queue_pull (queue
, depth
);
132 swfdec_buffer_queue_unref (queue
);
133 wav
= encode_wav (buffer
);
134 swfdec_buffer_unref (buffer
);
135 if (!g_file_set_contents (filename
, (char *) wav
->data
,
136 wav
->length
, &error
)) {
137 g_printerr ("Couldn't save sound to file \"%s\": %s\n", filename
, error
->message
);
138 swfdec_buffer_unref (wav
);
139 g_error_free (error
);
142 swfdec_buffer_unref (wav
);
147 static cairo_surface_t
*
148 surface_create_for_filename (const char *filename
, int width
, int height
)
150 guint len
= strlen (filename
);
151 cairo_surface_t
*surface
;
153 #ifdef CAIRO_HAS_PDF_SURFACE
154 } else if (len
>= 3 && g_ascii_strcasecmp (filename
+ len
- 3, "pdf") == 0) {
155 surface
= cairo_pdf_surface_create (filename
, width
, height
);
157 #ifdef CAIRO_HAS_SVG_SURFACE
158 } else if (len
>= 3 && g_ascii_strcasecmp (filename
+ len
- 3, "svg") == 0) {
159 surface
= cairo_svg_surface_create (filename
, width
, height
);
162 surface
= cairo_image_surface_create (CAIRO_FORMAT_ARGB32
, width
, height
);
168 surface_destroy_for_type (cairo_surface_t
*surface
, const char *filename
)
170 if (cairo_surface_get_type (surface
) == CAIRO_SURFACE_TYPE_IMAGE
) {
171 cairo_status_t status
= cairo_surface_write_to_png (surface
, filename
);
172 if (status
!= CAIRO_STATUS_SUCCESS
) {
173 g_printerr ("Error saving file: %s\n", cairo_status_to_string (status
));
174 cairo_surface_destroy (surface
);
178 cairo_surface_destroy (surface
);
183 export_graphic (SwfdecGraphic
*graphic
, const char *filename
)
185 SwfdecRenderer
*renderer
;
186 cairo_surface_t
*surface
;
189 const SwfdecColorTransform trans
= { FALSE
, 256, 0, 256, 0, 256, 0, 256, 0 };
191 if (SWFDEC_IS_SPRITE (graphic
)) {
192 g_printerr ("Sprites can not be exported\n");
195 if (SWFDEC_IS_BUTTON (graphic
)) {
196 g_printerr ("Buttons can not be exported\n");
199 width
= ceil (graphic
->extents
.x1
/ SWFDEC_TWIPS_SCALE_FACTOR
)
200 - floor (graphic
->extents
.x0
/ SWFDEC_TWIPS_SCALE_FACTOR
);
201 height
= ceil (graphic
->extents
.y1
/ SWFDEC_TWIPS_SCALE_FACTOR
)
202 - floor (graphic
->extents
.y0
/ SWFDEC_TWIPS_SCALE_FACTOR
);
203 surface
= surface_create_for_filename (filename
, width
, height
);
204 cr
= cairo_create (surface
);
205 cairo_translate (cr
, - floor (graphic
->extents
.x0
/ SWFDEC_TWIPS_SCALE_FACTOR
),
206 - floor (graphic
->extents
.y0
/ SWFDEC_TWIPS_SCALE_FACTOR
));
207 cairo_scale (cr
, 1.0 / SWFDEC_TWIPS_SCALE_FACTOR
, 1.0 / SWFDEC_TWIPS_SCALE_FACTOR
);
208 renderer
= swfdec_renderer_new (surface
);
209 swfdec_renderer_attach (renderer
, cr
);
210 swfdec_graphic_render (graphic
, cr
, &trans
);
211 cairo_show_page (cr
);
213 g_object_unref (renderer
);
214 return surface_destroy_for_type (surface
, filename
);
218 export_image (SwfdecImage
*image
, const char *filename
)
220 cairo_surface_t
*surface
= swfdec_image_create_surface (image
, NULL
);
224 return surface_destroy_for_type (surface
, filename
);
228 usage (const char *app
)
230 g_print ("usage: %s SWFFILE ID OUTFILE\n\n", app
);
234 main (int argc
, char *argv
[])
236 SwfdecCharacter
*character
;
238 SwfdecPlayer
*player
;
249 player
= swfdec_player_new (NULL
);
250 url
= swfdec_url_new_from_input (argv
[1]);
251 swfdec_player_set_url (player
, url
);
252 swfdec_url_free (url
);
254 swfdec_player_advance (player
, 0);
255 if (!SWFDEC_IS_SPRITE_MOVIE (player
->priv
->roots
->data
)) {
256 g_printerr ("Error parsing file \"%s\"\n", argv
[1]);
257 g_object_unref (player
);
261 id
= strtol (argv
[2], NULL
, 0);
263 character
= swfdec_swf_decoder_get_character (
264 SWFDEC_SWF_DECODER (SWFDEC_MOVIE (player
->priv
->roots
->data
)->resource
->decoder
),
267 character
= SWFDEC_CHARACTER (SWFDEC_SWF_DECODER (
268 SWFDEC_MOVIE (player
->priv
->roots
->data
)->resource
->decoder
)->main_sprite
);
270 if (SWFDEC_IS_SPRITE (character
)) {
271 if (!export_sprite_sound (SWFDEC_SPRITE (character
), argv
[3]))
273 } else if (SWFDEC_IS_SOUND (character
)) {
274 if (!export_sound (SWFDEC_SOUND (character
), argv
[3]))
276 } else if (SWFDEC_IS_GRAPHIC (character
)) {
277 if (!export_graphic (SWFDEC_GRAPHIC (character
), argv
[3]))
279 } else if (SWFDEC_IS_IMAGE (character
)) {
280 if (!export_image (SWFDEC_IMAGE (character
), argv
[3]))
283 g_printerr ("id %ld does not specify an exportable object\n", id
);
287 g_object_unref (player
);