~ubuntu-branches/ubuntu/intrepid/gpac/intrepid-proposed

« back to all changes in this revision

Viewing changes to modules/render2d/svg_media.c

  • Committer: Bazaar Package Importer
  • Author(s): John Dong
  • Date: 2007-01-24 23:34:57 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20070124233457-zzlls8afkt0nyakj
Tags: 0.4.2~rc2-0ubuntu1
* New upstream release
  * Most notably MP4 tagging support via MP4Box -itags
* debian/patches/01_64bits.dpatch: dropped; included upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *                      GPAC - Multimedia Framework C SDK
 
3
 *
 
4
 *                      Authors: Cyril Concolato - Jean le Feuvre
 
5
 *                              Copyright (c) 2005-200X ENST
 
6
 *                                      All rights reserved
 
7
 *
 
8
 *  This file is part of GPAC / SVG Rendering sub-project
 
9
 *
 
10
 *  GPAC is free software; you can redistribute it and/or modify
 
11
 *  it under the terms of the GNU Lesser General Public License as published by
 
12
 *  the Free Software Foundation; either version 2, or (at your option)
 
13
 *  any later version.
 
14
 *   
 
15
 *  GPAC is distributed in the hope that it will be useful,
 
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 *  GNU Lesser General Public License for more details.
 
19
 *   
 
20
 *  You should have received a copy of the GNU Lesser General Public
 
21
 *  License along with this library; see the file COPYING.  If not, write to
 
22
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 
23
 *
 
24
 */
 
25
 
 
26
#include "svg_stacks.h"
 
27
#include "visualsurface2d.h"
 
28
 
 
29
#ifndef GPAC_DISABLE_SVG
 
30
 
 
31
#include <gpac/internal/scenegraph_dev.h>
 
32
 
 
33
#ifdef DANAE
 
34
int processDanaeAudio(void *param, unsigned int scene_time);
 
35
#endif
 
36
 
 
37
/************************/
 
38
/* Generic URI handling */
 
39
/************************/
 
40
 
 
41
Bool SVG_SetMFURLFromURI(GF_Renderer *sr, MFURL *mfurl, SVG_IRI *iri) 
 
42
{
 
43
        Bool ret = 1;
 
44
        SFURL *sfurl = NULL;
 
45
        if (!iri->iri) return 0;
 
46
 
 
47
        gf_sg_vrml_mf_reset(mfurl, GF_SG_VRML_MFURL);
 
48
        mfurl->count = 1;
 
49
        GF_SAFEALLOC(mfurl->vals, sizeof(SFURL))
 
50
        sfurl = mfurl->vals;
 
51
        sfurl->OD_ID = 0;
 
52
#ifndef DANAE
 
53
        if (!strncmp(iri->iri, "data:", 5)) {
 
54
                const char *cache_dir = gf_cfg_get_key(sr->user->config, "General", "CacheDirectory");
 
55
                ret = gf_svg_store_embedded_data(iri, cache_dir, "embedded_");
 
56
        }
 
57
#endif
 
58
        sfurl->url = strdup(iri->iri);
 
59
        return ret;
 
60
}
 
61
 
 
62
static Bool SVG_check_url_change(MFURL *url, SVG_IRI *iri)
 
63
{
 
64
        if (url->count && !iri->iri) return 1;
 
65
        if (!url->count && iri->iri) return 1;
 
66
        if (!url->count) return 0;
 
67
        if (!strcmp(url->vals[0].url, iri->iri)) return 0;
 
68
        return 1;
 
69
}
 
70
 
 
71
#if 0
 
72
static void SVG_ComputeAR(Fixed objw, Fixed objh, Fixed viewportw, Fixed viewporth,
 
73
                                                  SVG_PreserveAspectRatio *par, GF_Matrix2D *par_mat)
 
74
{
 
75
        gf_mx2d_init(*par_mat);
 
76
        if (par->meetOrSlice == SVG_MEETORSLICE_MEET) {
 
77
                switch(par->align) {
 
78
                        case SVG_PRESERVEASPECTRATIO_NONE:
 
79
                                break;
 
80
                        case SVG_PRESERVEASPECTRATIO_XMINYMIN:
 
81
                                break;
 
82
                        case SVG_PRESERVEASPECTRATIO_XMIDYMIN:
 
83
                                break;
 
84
                        case SVG_PRESERVEASPECTRATIO_XMAXYMIN:
 
85
                                break;
 
86
                        case SVG_PRESERVEASPECTRATIO_XMINYMID:
 
87
                                break;
 
88
                        case SVG_PRESERVEASPECTRATIO_XMIDYMID:
 
89
                                break;
 
90
                        case SVG_PRESERVEASPECTRATIO_XMAXYMID:
 
91
                                break;
 
92
                        case SVG_PRESERVEASPECTRATIO_XMINYMAX:
 
93
                                break;
 
94
                        case SVG_PRESERVEASPECTRATIO_XMIDYMAX:
 
95
                                break;
 
96
                        case SVG_PRESERVEASPECTRATIO_XMAXYMAX:
 
97
                                break;
 
98
                }
 
99
        } else {
 
100
        }
 
101
}
 
102
#endif
 
103
static void SVG_Draw_bitmap(DrawableContext *ctx)
 
104
{
 
105
        GF_ColorMatrix *cmat;
 
106
        u8 alpha;
 
107
        Render2D *sr;
 
108
        Bool use_blit;
 
109
        sr = ctx->surface->render;
 
110
 
 
111
        use_blit = 1;
 
112
        alpha = GF_COL_A(ctx->aspect.fill_color);
 
113
 
 
114
        cmat = NULL;
 
115
        if (!ctx->cmat.identity) cmat = &ctx->cmat;
 
116
        //else if (ctx->h_texture->has_cmat) cmat = NULL;
 
117
 
 
118
        /*this is not a native texture, use graphics*/
 
119
        if (!ctx->h_texture->data || ctx->transform.m[1] || ctx->transform.m[3]) {
 
120
                use_blit = 0;
 
121
        } else {
 
122
                if (!ctx->surface->SupportsFormat || !ctx->surface->DrawBitmap ) use_blit = 0;
 
123
                /*format not supported directly, try with brush*/
 
124
                else if (!ctx->surface->SupportsFormat(ctx->surface, ctx->h_texture->pixelformat) ) use_blit = 0;
 
125
        }
 
126
 
 
127
        /*no HW, fall back to the graphics driver*/
 
128
        if (!use_blit) {
 
129
                VS2D_TexturePath(ctx->surface, ctx->node->path, ctx);
 
130
                return;
 
131
        }
 
132
 
 
133
        /*direct rendering, render without clippers */
 
134
        if (ctx->surface->render->top_effect->trav_flags & TF_RENDER_DIRECT) {
 
135
                ctx->surface->DrawBitmap(ctx->surface, ctx->h_texture, &ctx->clip, &ctx->unclip, alpha, NULL, cmat);
 
136
        }
 
137
        /*render bitmap for all dirty rects*/
 
138
        else {
 
139
                u32 i;
 
140
                GF_IRect clip;
 
141
                for (i=0; i<ctx->surface->to_redraw.count; i++) {
 
142
                        /*there's an opaque region above, don't draw*/
 
143
                        if (ctx->surface->draw_node_index<ctx->surface->to_redraw.opaque_node_index[i]) continue;
 
144
                        clip = ctx->clip;
 
145
                        gf_irect_intersect(&clip, &ctx->surface->to_redraw.list[i]);
 
146
                        if (clip.width && clip.height) {
 
147
                                ctx->surface->DrawBitmap(ctx->surface, ctx->h_texture, &clip, &ctx->unclip, alpha, NULL, cmat);
 
148
                        }
 
149
                }
 
150
        }
 
151
}
 
152
 
 
153
static void SVG_BuildGraph_image(SVG_image_stack *st)
 
154
{
 
155
        GF_Rect rc, new_rc;
 
156
        SVGimageElement *img = (SVGimageElement *)st->graph->owner;
 
157
        gf_path_get_bounds(st->graph->path, &rc);
 
158
        drawable_reset_path(st->graph);
 
159
        gf_path_add_rect_center(st->graph->path, img->x.value+img->width.value/2, img->y.value+img->height.value/2, img->width.value, img->height.value);
 
160
        gf_path_get_bounds(st->graph->path, &new_rc);
 
161
        /*change in visual aspect*/
 
162
        if (!gf_rect_equal(rc, new_rc)) st->graph->node_changed = 1;
 
163
        gf_node_dirty_clear(st->graph->owner, GF_SG_SVG_GEOMETRY_DIRTY);
 
164
}
 
165
 
 
166
 
 
167
static void SVG_BuildGraph_video(SVG_video_stack *st)
 
168
{
 
169
        GF_Rect rc, new_rc;
 
170
        SVGvideoElement *video = (SVGvideoElement *)st->graph->owner;
 
171
        gf_path_get_bounds(st->graph->path, &rc);
 
172
        drawable_reset_path(st->graph);
 
173
        gf_path_add_rect_center(st->graph->path, video->x.value+video->width.value/2, video->y.value+video->height.value/2, video->width.value, video->height.value);
 
174
        gf_path_get_bounds(st->graph->path, &new_rc);
 
175
        /*change in visual aspect*/
 
176
        if (!gf_rect_equal(rc, new_rc)) st->graph->node_changed = 1;
 
177
        gf_node_dirty_clear(st->graph->owner, GF_SG_SVG_GEOMETRY_DIRTY);
 
178
}
 
179
 
 
180
static void SVG_Render_bitmap(GF_Node *node, void *rs)
 
181
{
 
182
        /*video stack is just an extension of image stack, type-casting is OK*/
 
183
        SVG_image_stack *st = (SVG_image_stack*)gf_node_get_private(node);
 
184
        RenderEffect2D *eff = (RenderEffect2D *)rs;
 
185
        SVGPropertiesPointers backup_props;
 
186
        GF_Matrix2D backup_matrix;
 
187
        SVG_Matrix *m;
 
188
        DrawableContext *ctx;
 
189
 
 
190
        SVG_Render_base(node, (RenderEffect2D *)rs, &backup_props);
 
191
 
 
192
        if (gf_node_dirty_get(node)) {
 
193
                if (gf_node_get_tag(node)==TAG_SVG_image) {
 
194
                        SVG_BuildGraph_image(gf_node_get_private(node));
 
195
                        m = &((SVGimageElement *)node)->transform;
 
196
                } else {
 
197
                        SVG_BuildGraph_video(gf_node_get_private(node));
 
198
                        m = &((SVGvideoElement *)node)->transform;
 
199
                }
 
200
 
 
201
                /*if open and changed, stop and play*/
 
202
                if (SVG_check_url_change(&st->txurl, & ((SVGElement *)node)->xlink->href)) {
 
203
                        const char *cache_dir = gf_cfg_get_key(st->txh.compositor->user->config, "General", "CacheDirectory");
 
204
                        gf_svg_store_embedded_data(& ((SVGElement *)node)->xlink->href, cache_dir, "embedded_");
 
205
 
 
206
                        if (SVG_check_url_change(&st->txurl, & ((SVGElement *)node)->xlink->href)) {
 
207
                                SVG_SetMFURLFromURI(st->txh.compositor, &(st->txurl), & ((SVGElement*)node)->xlink->href);
 
208
                                if (st->txh.is_open) gf_sr_texture_stop(&st->txh);
 
209
                                fprintf(stdout, "URL changed to %s\n", st->txurl.vals[0].url);
 
210
                                gf_sr_texture_play(&st->txh, &st->txurl);
 
211
                        }
 
212
                } 
 
213
                gf_node_dirty_clear(node, 0);
 
214
        } else {
 
215
                if (gf_node_get_tag(node)==TAG_SVG_image) {
 
216
                        m = &((SVGimageElement *)node)->transform;
 
217
                } else {
 
218
                        m = &((SVGvideoElement *)node)->transform;
 
219
                }
 
220
        }
 
221
 
 
222
        /*FIXME: setup aspect ratio*/
 
223
 
 
224
        if (eff->trav_flags & TF_RENDER_GET_BOUNDS) {
 
225
                gf_mx2d_pre_multiply(&eff->transform, m);
 
226
                if (*(eff->svg_props->display) != SVG_DISPLAY_NONE) {
 
227
                        gf_path_get_bounds(st->graph->path, &eff->bounds);
 
228
                }
 
229
                memcpy(eff->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
 
230
                return;
 
231
        }
 
232
 
 
233
        if (*(eff->svg_props->display) == SVG_DISPLAY_NONE ||
 
234
                *(eff->svg_props->visibility) == SVG_VISIBILITY_HIDDEN) {
 
235
                memcpy(eff->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
 
236
                return;
 
237
        }
 
238
 
 
239
        gf_mx2d_copy(backup_matrix, eff->transform);
 
240
        gf_mx2d_pre_multiply(&eff->transform, m);
 
241
 
 
242
        ctx = SVG_drawable_init_context(st->graph, eff);
 
243
        if (!ctx || !ctx->h_texture ) return;
 
244
        /*store bounds*/
 
245
        gf_path_get_bounds(ctx->node->path, &ctx->original);
 
246
 
 
247
        /*even if set this is not true*/
 
248
        ctx->aspect.has_line = 0;
 
249
        /*this is to make sure we don't fill the path if the texture is transparent*/
 
250
        ctx->aspect.filled = 0;
 
251
        ctx->aspect.pen_props.width = 0;
 
252
        ctx->no_antialias = 1;
 
253
 
 
254
        /*if rotation, transparent*/
 
255
        ctx->transparent = 0;
 
256
        if (ctx->transform.m[1] || ctx->transform.m[3]) {
 
257
                ctx->transparent = 1;
 
258
                ctx->no_antialias = 0;
 
259
        }
 
260
        else if (ctx->h_texture->transparent) 
 
261
                ctx->transparent = 1;
 
262
        else if (eff->svg_props->opacity && (eff->svg_props->opacity->type==SVG_NUMBER_VALUE) && (eff->svg_props->opacity->value!=FIX_ONE)) {
 
263
                ctx->transparent = 1;
 
264
                ctx->aspect.fill_alpha = FIX2INT(0xFF * eff->svg_props->opacity->value);
 
265
                ctx->aspect.fill_color = ctx->aspect.fill_alpha << 24;
 
266
        }
 
267
 
 
268
        /*bounds are stored when building graph*/       
 
269
        drawable_finalize_render(ctx, eff);
 
270
        gf_mx2d_copy(eff->transform, backup_matrix);  
 
271
        memcpy(eff->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
 
272
}
 
273
 
 
274
static Bool SVG_PointOver_bitmap(DrawableContext *ctx, Fixed x, Fixed y, u32 check_type)
 
275
{
 
276
        return 1;
 
277
}
 
278
 
 
279
 
 
280
/*********************/
 
281
/* SVG image element */
 
282
/*********************/
 
283
 
 
284
static void SVG_Update_image(GF_TextureHandler *txh)
 
285
{
 
286
        SVGimageElement *txnode = (SVGimageElement *) txh->owner;
 
287
        MFURL *txurl = &(((SVG_image_stack *)gf_node_get_private((GF_Node *)txnode))->txurl);
 
288
 
 
289
        /*setup texture if needed*/
 
290
        if (!txh->is_open && txurl->count) {
 
291
                gf_sr_texture_play(txh, txurl);
 
292
        }
 
293
        gf_sr_texture_update_frame(txh, 0);
 
294
        /*URL is present but not opened - redraw till fetch*/
 
295
        if (txh->stream && !txh->hwtx) gf_sr_invalidate(txh->compositor, NULL);
 
296
}
 
297
 
 
298
static void SVG_Destroy_image(GF_Node *node)
 
299
{
 
300
        SVG_image_stack *st = (SVG_image_stack *)gf_node_get_private(node);
 
301
 
 
302
        gf_sr_texture_destroy(&st->txh);
 
303
        gf_sg_mfurl_del(st->txurl);
 
304
 
 
305
        drawable_del(st->graph);
 
306
        free(st);
 
307
}
 
308
 
 
309
void SVG_Init_image(Render2D *sr, GF_Node *node)
 
310
{
 
311
        SVG_image_stack *st;
 
312
        GF_SAFEALLOC(st, sizeof(SVG_image_stack))
 
313
        st->graph = drawable_new();
 
314
 
 
315
        gf_sr_traversable_setup(st->graph, node, sr->compositor);
 
316
        st->graph->Draw = SVG_Draw_bitmap;
 
317
        st->graph->IsPointOver = SVG_PointOver_bitmap;
 
318
 
 
319
        gf_sr_texture_setup(&st->txh, sr->compositor, node);
 
320
        st->txh.update_texture_fcnt = SVG_Update_image;
 
321
        st->txh.flags = 0;
 
322
 
 
323
        /* builds the MFURL to be used by the texture */
 
324
        SVG_SetMFURLFromURI(sr->compositor, &(st->txurl), & ((SVGimageElement*)node)->xlink->href);
 
325
 
 
326
        gf_node_set_private(node, st);
 
327
        gf_node_set_render_function(node, SVG_Render_bitmap);
 
328
        gf_node_set_predestroy_function(node, SVG_Destroy_image);
 
329
 
 
330
}
 
331
 
 
332
/*********************/
 
333
/* SVG video element */
 
334
/*********************/
 
335
 
 
336
static void SVG_Activate_video(SVG_video_stack *stack, SVGvideoElement *video)
 
337
{
 
338
        MFURL *txurl = &(((SVG_video_stack *)gf_node_get_private((GF_Node *)video))->txurl);
 
339
        stack->isActive = 1;
 
340
        if (!stack->txh.is_open) {
 
341
                gf_sr_texture_play(&stack->txh, txurl);
 
342
        }
 
343
        gf_mo_set_speed(stack->txh.stream, FIX_ONE);
 
344
}
 
345
 
 
346
/*
 
347
static void SVG_Deactivate_video(SVG_video_stack *stack, SVGvideoElement *video)
 
348
{
 
349
        stack->isActive = 0;
 
350
        stack->time_handle.needs_unregister = 1;
 
351
 
 
352
        if (stack->txh.is_open) {
 
353
                gf_sr_texture_stop(&stack->txh);
 
354
        }
 
355
}
 
356
*/
 
357
 
 
358
static void SVG_Update_video(GF_TextureHandler *txh)
 
359
{
 
360
        //SVGvideoElement *txnode = (SVGvideoElement *) txh->owner;
 
361
        SVG_video_stack *st = (SVG_video_stack *) gf_node_get_private(txh->owner);
 
362
        //MFURL *txurl = &(st->txurl);
 
363
 
 
364
        /*setup texture if needed*/
 
365
        if (!txh->is_open) return;
 
366
        if (!st->isActive && st->first_frame_fetched) return;
 
367
 
 
368
        /*when fetching the first frame disable resync*/
 
369
        gf_sr_texture_update_frame(txh, 0);
 
370
 
 
371
        if (txh->stream_finished) {
 
372
                /*
 
373
                if (MT_GetLoop(st, txnode)) {
 
374
                        gf_sr_texture_restart(txh);
 
375
                }
 
376
                //if active deactivate
 
377
                else if (txnode->isActive && gf_mo_should_deactivate(st->txh.stream) ) {
 
378
                        MT_Deactivate(st, txnode);
 
379
                }
 
380
                */
 
381
        }
 
382
        /* first frame is fetched */
 
383
        if (!st->first_frame_fetched && (txh->needs_refresh) ) {
 
384
                st->first_frame_fetched = 1;
 
385
                /*
 
386
                txnode->duration_changed = gf_mo_get_duration(txh->stream);
 
387
                gf_node_event_out_str(txh->owner, "duration_changed");
 
388
                */
 
389
                /*stop stream if needed
 
390
                if (!txnode->isActive && txh->is_open) {
 
391
                        gf_sr_texture_stop(txh);
 
392
                        //make sure the refresh flag is not cleared
 
393
                        txh->needs_refresh = 1;
 
394
                }
 
395
                */
 
396
        }
 
397
        /*we have no choice but retraversing the graph until we're inactive since the movie framerate and
 
398
        the renderer framerate are likely to be different */
 
399
        if (!txh->stream_finished) 
 
400
                gf_sr_invalidate(txh->compositor, NULL);
 
401
 
 
402
}
 
403
 
 
404
static void SVG_UpdateTime_video(GF_TimeNode *st)
 
405
{
 
406
        Double sceneTime;
 
407
        SVGvideoElement *video = (SVGvideoElement *)st->obj;
 
408
        SVG_video_stack *stack = (SVG_video_stack *)gf_node_get_private(st->obj);
 
409
        MFURL *txurl = &(stack->txurl);
 
410
        
 
411
        /*not active, store start time and speed */
 
412
        if (!stack->isActive) {
 
413
                //stack->start_time = mt->startTime;
 
414
                stack->start_time = 0;
 
415
        }
 
416
 
 
417
        sceneTime = gf_node_get_scene_time(st->obj);
 
418
 
 
419
        if (sceneTime < stack->start_time //||
 
420
                /*special case if we're getting active AFTER stoptime 
 
421
                (!mt->isActive && (mt->stopTime > stack->start_time) && (time>=mt->stopTime)) */
 
422
                ) {
 
423
                /*opens stream only at first access to fetch first frame*/
 
424
                if (stack->fetch_first_frame) {
 
425
                        stack->fetch_first_frame = 0;
 
426
                        if (!stack->txh.is_open)
 
427
                                gf_sr_texture_play(&stack->txh, txurl);
 
428
                }
 
429
                return;
 
430
        }
 
431
 
 
432
        /*
 
433
        if (MT_GetSpeed(stack, mt) && mt->isActive) {
 
434
                // if stoptime is reached (>startTime) deactivate
 
435
                if ((mt->stopTime > stack->start_time) && (time >= mt->stopTime) ) {
 
436
                        MT_Deactivate(stack, mt);
 
437
                        return;
 
438
                }
 
439
        }
 
440
        */
 
441
 
 
442
        if (!stack->isActive) SVG_Activate_video(stack, video);
 
443
}
 
444
 
 
445
static void SVG_Destroy_video(GF_Node *node)
 
446
{
 
447
        SVG_video_stack *st = (SVG_video_stack *)gf_node_get_private(node);
 
448
        gf_sr_texture_destroy(&st->txh);
 
449
        gf_sg_mfurl_del(st->txurl);
 
450
 
 
451
        if (st->time_handle.is_registered) gf_sr_unregister_time_node(st->txh.compositor, &st->time_handle);
 
452
        drawable_del(st->graph);
 
453
        free(st);
 
454
}
 
455
 
 
456
void SVG_Init_video(Render2D *sr, GF_Node *node)
 
457
{
 
458
        SVG_video_stack *st;
 
459
        GF_SAFEALLOC(st, sizeof(SVG_video_stack))
 
460
        st->graph = drawable_new();
 
461
 
 
462
        gf_sr_traversable_setup(st->graph, node, sr->compositor);
 
463
        st->graph->Draw = SVG_Draw_bitmap;
 
464
        st->graph->IsPointOver = SVG_PointOver_bitmap;
 
465
 
 
466
        gf_sr_texture_setup(&st->txh, sr->compositor, node);
 
467
        st->txh.update_texture_fcnt = SVG_Update_video;
 
468
        st->txh.flags = 0;
 
469
        st->time_handle.UpdateTimeNode = SVG_UpdateTime_video;
 
470
        st->time_handle.obj = node;
 
471
        st->fetch_first_frame = 1;
 
472
        
 
473
        /* create an MFURL from the SVG iri */
 
474
        SVG_SetMFURLFromURI(sr->compositor, &(st->txurl), & ((SVGvideoElement *)node)->xlink->href);
 
475
 
 
476
        gf_sr_register_time_node(st->txh.compositor, &st->time_handle); 
 
477
        
 
478
        gf_node_set_private(node, st);
 
479
        gf_node_set_render_function(node, SVG_Render_bitmap);
 
480
        gf_node_set_predestroy_function(node, SVG_Destroy_video);
 
481
}
 
482
 
 
483
/*********************/
 
484
/* SVG audio element */
 
485
/*********************/
 
486
typedef struct
 
487
{
 
488
        GF_AudioInput input;
 
489
        GF_TimeNode time_handle;
 
490
        Bool is_active;
 
491
        Double start_time;
 
492
        MFURL aurl;
 
493
#ifdef DANAE
 
494
        GF_Renderer *comp;
 
495
        void *dmo;
 
496
#endif
 
497
} SVG_audio_stack;
 
498
 
 
499
 
 
500
static void SVG_Activate_audio(SVG_audio_stack *st, SVGaudioElement *audio)
 
501
{
 
502
        MFURL *aurl = &(((SVG_audio_stack *)gf_node_get_private((GF_Node*)audio))->aurl);
 
503
 
 
504
        gf_sr_audio_open(&st->input, aurl);
 
505
        st->is_active = 1;
 
506
        gf_mo_set_speed(st->input.stream, FIX_ONE);
 
507
        /*rerender all graph to get parent audio group*/
 
508
        gf_sr_invalidate(st->input.compositor, NULL);
 
509
}
 
510
 
 
511
static void SVG_Deactivate_audio(SVG_audio_stack *st)
 
512
{
 
513
        gf_sr_audio_stop(&st->input);
 
514
        st->is_active = 0;
 
515
        st->time_handle.needs_unregister = 1;
 
516
}
 
517
 
 
518
static void SVG_Render_audio(GF_Node *node, void *rs)
 
519
{
 
520
        SVGPropertiesPointers backup_props;
 
521
        RenderEffect2D *eff = (RenderEffect2D*)rs;
 
522
        SVG_audio_stack *st = (SVG_audio_stack *)gf_node_get_private(node);
 
523
 
 
524
#ifdef DANAE
 
525
        if (st->is_active) {
 
526
                if (!st->dmo) st->dmo = getDanaeMediaOjbectFromUrl(st->comp->danae_session, st->aurl.vals[0].url, 2);
 
527
                if (st->dmo) {
 
528
                                processDanaeAudio(st->dmo, (u32) (gf_node_get_scene_time(node)*1000));
 
529
                                st->comp->draw_next_frame = 1;
 
530
                }
 
531
        }
 
532
 
 
533
#else
 
534
        /*check end of stream*/
 
535
        if (st->input.stream && st->input.stream_finished) {
 
536
                if (gf_mo_get_loop(st->input.stream, 0)) {
 
537
                        gf_sr_audio_restart(&st->input);
 
538
                } else if (st->is_active /*&& gf_mo_should_deactivate(st->input.stream)*/) {
 
539
                        SVG_Deactivate_audio(st);
 
540
                }
 
541
        }
 
542
        if (st->is_active) {
 
543
                gf_sr_audio_register(&st->input, (GF_BaseEffect*)rs);
 
544
        }
 
545
 
 
546
        /*for heritage and anims*/
 
547
        SVG_Render_base(node, (RenderEffect2D *)rs, &backup_props);
 
548
 
 
549
        /*store mute flag*/
 
550
        st->input.is_muted = 0;
 
551
        if ((eff->trav_flags & GF_SR_TRAV_SWITCHED_OFF)
 
552
                || (*(eff->svg_props->display) == SVG_DISPLAY_NONE) 
 
553
                || (*(eff->svg_props->visibility) == SVG_VISIBILITY_HIDDEN) ) {
 
554
        
 
555
                st->input.is_muted = 1;
 
556
        }
 
557
 
 
558
        memcpy(eff->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
 
559
 
 
560
#endif
 
561
}
 
562
 
 
563
static void SVG_UpdateTime_audio(GF_TimeNode *tn)
 
564
{
 
565
        Double sceneTime;
 
566
        SVGaudioElement *audio = (SVGaudioElement *)tn->obj;
 
567
        SVG_audio_stack *st = (SVG_audio_stack *)gf_node_get_private(tn->obj);
 
568
 
 
569
        if (! st->is_active) {
 
570
                //st->start_time = as->startTime;
 
571
                st->start_time = 0;
 
572
                //st->input.speed = as->speed;
 
573
        }
 
574
        sceneTime = gf_node_get_scene_time(tn->obj);
 
575
        //if ((sceneTime<st->start_time) || (st->start_time<0)) return;
 
576
        
 
577
        /*
 
578
        if (st->input.input_ifce.GetSpeed(st->input.input_ifce.callback) && st->is_active) {
 
579
                if ( (as->stopTime > st->start_time) && (time>=as->stopTime)) {
 
580
                        SVG_Deactivate_audio(st, audio);
 
581
                        return;
 
582
                }
 
583
        }
 
584
        */
 
585
        if (!st->is_active) SVG_Activate_audio(st, audio);
 
586
}
 
587
 
 
588
static void SVG_Destroy_audio(GF_Node *node)
 
589
{
 
590
        SVG_audio_stack *st = (SVG_audio_stack *)gf_node_get_private(node);
 
591
        gf_sr_audio_stop(&st->input);
 
592
        gf_sr_audio_unregister(&st->input);
 
593
        if (st->time_handle.is_registered) {
 
594
                gf_sr_unregister_time_node(st->input.compositor, &st->time_handle);
 
595
        }
 
596
        gf_sg_mfurl_del(st->aurl);
 
597
#ifdef DANAE
 
598
        if (st->dmo) releaseDanaeMediaObject(st->dmo); 
 
599
#endif
 
600
        free(st);
 
601
}
 
602
 
 
603
void SVG_Init_audio(Render2D *sr, GF_Node *node)
 
604
{
 
605
        SVG_audio_stack *st;
 
606
        GF_SAFEALLOC(st, sizeof(SVG_audio_stack))
 
607
 
 
608
        gf_sr_audio_setup(&st->input, sr->compositor, node);
 
609
 
 
610
        st->time_handle.UpdateTimeNode = SVG_UpdateTime_audio;
 
611
        st->time_handle.obj = node;
 
612
 
 
613
        /* creates an MFURL from the URI of the SVG element */
 
614
        SVG_SetMFURLFromURI(sr->compositor, &(st->aurl), & ((SVGaudioElement *)node)->xlink->href);
 
615
 
 
616
        gf_node_set_private(node, st);
 
617
        gf_node_set_render_function(node, SVG_Render_audio);
 
618
        gf_node_set_predestroy_function(node, SVG_Destroy_audio);
 
619
 
 
620
        gf_sr_register_time_node(sr->compositor, &st->time_handle);
 
621
#ifdef DANAE
 
622
        st->comp = sr->compositor;
 
623
#endif
 
624
}
 
625
 
 
626
#endif //GPAC_DISABLE_SVG
 
627