This source file includes following definitions.
- gf_term_resolve_xlink
- gf_term_get_mfurl_from_xlink
- gf_svg_get_subscene
- gf_mo_load_xlink_resource
- gf_mo_unload_xlink_resource
#include <gpac/constants.h>
#include <gpac/internal/terminal_dev.h>
#include <gpac/mediaobject.h>
#ifndef GPAC_DISABLE_SVG
#include <gpac/internal/scenegraph_dev.h>
#include <gpac/nodes_svg.h>
#include <gpac/compositor.h>
#include <gpac/network.h>
char *gf_term_resolve_xlink(GF_Node *node, char *the_url)
{
char *url;
GF_Scene *scene = gf_sg_get_private(gf_node_get_graph(node));
if (!scene) return NULL;
url = gf_strdup(the_url);
while (node) {
GF_FieldInfo info;
if (gf_node_get_attribute_by_tag(node, TAG_XML_ATT_base, 0, 0, &info)==GF_OK) {
char *new_url = gf_url_concatenate( ((XMLRI*)info.far_ptr)->string, url);
if (new_url) {
gf_free(url);
url = new_url;
}
}
node = gf_node_get_parent(node, 0);
}
if (url[0]=='#') return url;
if (scene) {
char *the_url;
if (scene->redirect_xml_base) {
the_url = gf_url_concatenate(scene->redirect_xml_base, url);
} else {
the_url = gf_strdup(url);
}
gf_free(url);
return the_url;
}
return url;
}
GF_EXPORT
GF_Err gf_term_get_mfurl_from_xlink(GF_Node *node, MFURL *mfurl)
{
u32 stream_id = 0;
GF_Err e = GF_OK;
SFURL *sfurl = NULL;
GF_FieldInfo info;
XMLRI *iri;
GF_Scene *scene = gf_sg_get_private(gf_node_get_graph(node));
if (!scene) return GF_BAD_PARAM;
gf_sg_vrml_mf_reset(mfurl, GF_SG_VRML_MFURL);
e = gf_node_get_attribute_by_tag(node, TAG_XLINK_ATT_href, 0, 0, &info);
if (e) return e;
iri = (XMLRI*)info.far_ptr;
if (iri->type==XMLRI_STREAMID) {
stream_id = iri->lsr_stream_id;
} else if (!iri->string) return GF_OK;
mfurl->count = 1;
GF_SAFEALLOC(mfurl->vals, SFURL)
sfurl = mfurl->vals;
if (!sfurl) return GF_BAD_PARAM;
sfurl->OD_ID = stream_id;
if (stream_id) return GF_OK;
if (!strncmp(iri->string, "data:", 5)) {
const char *cache_dir = gf_cfg_get_key(scene->root_od->term->user->config, "General", "CacheDirectory");
e = gf_node_store_embedded_data(iri, cache_dir, "embedded_");
if (e) return e;
sfurl->url = gf_strdup(iri->string);
return GF_OK;
}
sfurl->url = gf_term_resolve_xlink(node, iri->string);
return e;
}
static GF_Scene *gf_svg_get_subscene(GF_Node *elt, XLinkAttributesPointers *xlinkp, SMILSyncAttributesPointers *syncp, Bool use_sync, Bool primary_resource)
{
MFURL url;
Bool lock_timelines = 0;
GF_MediaObject *mo;
GF_SceneGraph *graph = gf_node_get_graph(elt);
GF_Scene *scene = (GF_Scene *)gf_sg_get_private(graph);
if (!scene) return NULL;
if (use_sync && syncp) {
switch ((syncp->syncBehavior?*syncp->syncBehavior:SMIL_SYNCBEHAVIOR_DEFAULT)) {
case SMIL_SYNCBEHAVIOR_LOCKED:
case SMIL_SYNCBEHAVIOR_CANSLIP:
lock_timelines = 1;
break;
case SMIL_SYNCBEHAVIOR_DEFAULT:
{
#if 0
if (svg && syncp) {
switch ((syncp->syncBehaviorDefault ? *syncp->syncBehaviorDefault : SMIL_SYNCBEHAVIOR_LOCKED)) {
case SMIL_SYNCBEHAVIOR_LOCKED:
case SMIL_SYNCBEHAVIOR_CANSLIP:
lock_timelines = 1;
break;
default:
break;
}
}
#endif
}
default:
break;
}
}
memset(&url, 0, sizeof(MFURL));
if (!xlinkp->href) return NULL;
gf_term_get_mfurl_from_xlink(elt, &url);
while (scene->secondary_resource && scene->root_od->parentscene)
scene = scene->root_od->parentscene;
mo = gf_scene_get_media_object_ex(scene, &url, GF_MEDIA_OBJECT_SCENE, lock_timelines, NULL, primary_resource, elt);
gf_sg_vrml_mf_reset(&url, GF_SG_VRML_MFURL);
if (!mo || !mo->odm) return NULL;
mo->odm->subscene->secondary_resource = primary_resource ? 0 : 1;
return mo->odm->subscene;
}
GF_MediaObject *gf_mo_load_xlink_resource(GF_Node *node, Bool primary_resource, Double clipBegin, Double clipEnd)
{
GF_Scene *new_resource;
SVGAllAttributes all_atts;
XLinkAttributesPointers xlinkp;
SMILSyncAttributesPointers syncp;
GF_Scene *scene = gf_sg_get_private(gf_node_get_graph(node));
if (!scene) return NULL;
gf_svg_flatten_attributes((SVG_Element *)node, &all_atts);
xlinkp.actuate = all_atts.xlink_actuate;
xlinkp.arcrole = all_atts.xlink_arcrole;
xlinkp.href = all_atts.xlink_href;
xlinkp.role = all_atts.xlink_role;
xlinkp.show = all_atts.xlink_show;
xlinkp.title = all_atts.xlink_title;
xlinkp.type = all_atts.xlink_type;
syncp.syncBehavior = all_atts.syncBehavior;
syncp.syncBehaviorDefault = all_atts.syncBehaviorDefault;
syncp.syncMaster = all_atts.syncMaster;
syncp.syncReference = all_atts.syncReference;
syncp.syncTolerance = all_atts.syncTolerance;
syncp.syncToleranceDefault = all_atts.syncToleranceDefault;
if (!xlinkp.href) return NULL;
if (xlinkp.href->type == XMLRI_ELEMENTID) return NULL;
new_resource = gf_svg_get_subscene(node, &xlinkp, &syncp, primary_resource ? 1 : 0, primary_resource);
if (!new_resource) return NULL;
gf_mo_play(new_resource->root_od->mo, 0, -1, 0);
return new_resource->root_od->mo;
}
void gf_mo_unload_xlink_resource(GF_Node *node, GF_MediaObject *mo)
{
if (!mo) return;
if (!gf_odm_lock_mo(mo)) return;
if (!mo->odm->subscene) {
gf_odm_lock(mo->odm, 0);
return;
}
if (mo->num_open) {
mo->num_open--;
if (!mo->num_open) {
gf_odm_disconnect(mo->odm, 2);
return;
}
}
if (mo->odm) gf_odm_lock(mo->odm, 0);
}
#endif