📄 terminal.c
字号:
/*check no clocks are still running*/ if (!Term_CheckClocks(term->root_scene->root_od->net_service, term->root_scene)) return 0; if (term->root_scene->is_dynamic_scene) return 1; /*ask renderer if there are sensors*/ return gf_sr_get_option(term->renderer, GF_OPT_IS_FINISHED);}/*get rendering option*/GF_EXPORTu32 gf_term_get_option(GF_Terminal * term, u32 type){ if (!term) return 0; switch (type) { case GF_OPT_HAS_JAVASCRIPT: return gf_sg_has_scripting(); case GF_OPT_IS_FINISHED: return Term_CheckIsOver(term); case GF_OPT_PLAY_STATE: if (term->renderer->step_mode) return GF_STATE_STEP_PAUSE; if (term->play_state) return GF_STATE_PAUSED; return GF_STATE_PLAYING; case GF_OPT_MEDIA_CACHE: if (!term->enable_cache) return GF_MEDIA_CACHE_DISABLED; else if (term->root_scene && term->root_scene->root_od->net_service->cache) return GF_MEDIA_CACHE_RUNNING; else return GF_MEDIA_CACHE_ENABLED; case GF_OPT_CAN_SELECT_STREAMS: return (term->root_scene && term->root_scene->is_dynamic_scene) ? 1 : 0; default: return gf_sr_get_option(term->renderer, type); }}GF_EXPORTGF_Err gf_term_set_size(GF_Terminal * term, u32 NewWidth, u32 NewHeight){ if (!term) return GF_BAD_PARAM; return gf_sr_set_size(term->renderer, NewWidth, NewHeight);}void gf_term_handle_services(GF_Terminal *term){ GF_ClientService *ns; /*play ODs that need it*/ gf_mx_p(term->net_mx); while (gf_list_count(term->media_queue)) { GF_ObjectManager *odm = (GF_ObjectManager *)gf_list_get(term->media_queue, 0); gf_list_rem(term->media_queue, 0); /*unlock net before sending play/pause*/ gf_mx_v(term->net_mx); /*this is a stop*/ if (odm->media_start_time == (u64)-1) { odm->media_start_time = 0; gf_odm_stop(odm, 0); } /*this is a play*/ else { gf_odm_play(odm); } /*relock net before sending play/pause*/ gf_mx_p(term->net_mx); } gf_mx_v(term->net_mx); /*lock to avoid any start attemps from renderer*/ gf_sr_lock(term->renderer, 1); while (gf_list_count(term->net_services_to_remove)) { gf_mx_p(term->net_mx); ns = (GF_ClientService*)gf_list_get(term->net_services_to_remove, 0); if (ns) gf_list_rem(term->net_services_to_remove, 0); gf_mx_v(term->net_mx); if (!ns) break; gf_term_service_del(ns); } if (term->nodes_pending) { u32 i, count, n_count; i=0; count = gf_list_count(term->nodes_pending); while (i<count) { GF_Node *n = (GF_Node *)gf_list_get(term->nodes_pending, i); gf_node_render(n, NULL); if (!term->nodes_pending) break; n_count = gf_list_count(term->nodes_pending); if (n_count==count) i++; else count=n_count; } } gf_sr_lock(term->renderer, 0); /*need to reload*/ if (term->reload_state == 1) { term->reload_state = 0; gf_term_disconnect(term); term->reload_state = 2; } if (term->reload_state == 2) { if (gf_list_count(term->net_services)) return; term->reload_state = 0; gf_term_connect(term, term->reload_url); free(term->reload_url); term->reload_url = NULL; }}void gf_term_add_render_node(GF_Terminal *term, GF_Node *node){ gf_sr_lock(term->renderer, 1); if (!term->nodes_pending) term->nodes_pending = gf_list_new(); gf_list_add(term->nodes_pending, node); gf_sr_lock(term->renderer, 0);}void gf_term_rem_render_node(GF_Terminal *term, GF_Node *node){ gf_sr_lock(term->renderer, 1); if (term->nodes_pending) { gf_list_del_item(term->nodes_pending, node); if (!gf_list_count(term->nodes_pending)) { gf_list_del(term->nodes_pending); term->nodes_pending = NULL; } } gf_sr_lock(term->renderer, 0);}void gf_term_close_services(GF_Terminal *term, GF_ClientService *ns){ GF_Err e = ns->ifce->CloseService(ns->ifce); ns->owner = NULL; /*if error don't wait for ACK to remove from main list*/ if (e) { gf_list_del_item(term->net_services, ns); gf_list_add(term->net_services_to_remove, ns); }}void gf_term_lock_renderer(GF_Terminal *term, Bool LockIt){ gf_sr_lock(term->renderer, LockIt);}void gf_term_lock_net(GF_Terminal *term, Bool LockIt){ if (LockIt) { gf_mx_p(term->net_mx); } else { gf_mx_v(term->net_mx); }}/*connects given OD manager to its URL*/void gf_term_connect_object(GF_Terminal *term, GF_ObjectManager *odm, char *serviceURL, GF_ClientService *ParentService){ GF_ClientService *ns; u32 i; GF_Err e; gf_term_lock_net(term, 1); if (!strnicmp(serviceURL, "file:///", 8)) serviceURL += 8; else if (!strnicmp(serviceURL, "file://", 7)) serviceURL += 7; /*for remoteODs/dynamic ODs, check if one of the running service cannot be used*/ i=0; while ( (ns = (GF_ClientService*)gf_list_enum(term->net_services, &i)) ) { if (gf_term_service_can_handle_url(ns, serviceURL)) { gf_term_lock_net(term, 0); /*wait for service to setup - service may become destroyed if not available*/ while (1) { gf_term_lock_net(term, 1); if (!ns->owner) { gf_term_lock_net(term, 0); return; } gf_term_lock_net(term, 0); if (ns->owner->OD) break; gf_sleep(5); } odm->net_service = ns; gf_odm_setup_entry_point(odm, serviceURL); return; } } odm->net_service = gf_term_service_new(term, odm, serviceURL, ParentService, &e); if (!odm->net_service) { gf_term_lock_net(term, 0); gf_term_message(term, serviceURL, "Cannot open service", e); gf_odm_disconnect(odm, 1); return; } gf_term_lock_net(term, 0); /*OK connect*/ odm->net_service->ifce->ConnectService(odm->net_service->ifce, odm->net_service, odm->net_service->url);}/*connects given channel to its URL if needed*/GF_Err gf_term_connect_remote_channel(GF_Terminal *term, GF_Channel *ch, char *URL){ GF_Err e; u32 i; GF_ClientService *ns; gf_term_lock_net(term, 1); /*if service is handled by current service don't create new one*/ if (gf_term_service_can_handle_url(ch->service, URL)) { gf_term_lock_net(term, 0); return GF_OK; } i=0; while ( (ns = (GF_ClientService*)gf_list_enum(term->net_services, &i)) ) { if (gf_term_service_can_handle_url(ns, URL)) { ch->service = ns; gf_term_lock_net(term, 0); return GF_OK; } } /*use parent OD for parent service*/ ns = gf_term_service_new(term, NULL, URL, ch->odm->net_service, &e); if (!ns) return e; ch->service = ns; ns->ifce->ConnectService(ns->ifce, ns, ns->url); gf_term_lock_net(term, 0); return GF_OK;}GF_EXPORTu32 gf_term_play_from_time(GF_Terminal *term, u64 from_time, Bool pause_at_first_frame){ if (!term || !term->root_scene || !term->root_scene->root_od) return 0; if (term->root_scene->root_od->flags & GF_ODM_NO_TIME_CTRL) return 1; /*for dynamic scene OD ressources are static and all object use the same clock, so don't restart the root OD, just act as a mediaControl on all playing streams*/ if (term->root_scene->is_dynamic_scene) { /*exit pause mode*/ gf_term_set_play_state(term, GF_STATE_PLAYING, 1, 1); if (pause_at_first_frame) gf_term_set_play_state(term, GF_STATE_STEP_PAUSE, 0, 0); gf_sr_lock(term->renderer, 1); gf_is_restart_dynamic(term->root_scene, from_time); gf_sr_lock(term->renderer, 0); return 2; } /*pause everything*/ gf_term_set_play_state(term, GF_STATE_PAUSED, 0, 1); /*stop root*/ gf_odm_stop(term->root_scene->root_od, 1); gf_is_disconnect(term->root_scene, 0); /*make sure we don't have OD queued*/ while (gf_list_count(term->media_queue)) gf_list_rem(term->media_queue, 0); term->root_scene->root_od->media_start_time = from_time; gf_odm_start(term->root_scene->root_od); gf_term_set_play_state(term, pause_at_first_frame ? GF_STATE_STEP_PAUSE : GF_STATE_PLAYING, 0, 1); return 2;}GF_EXPORTBool gf_term_user_event(GF_Terminal * term, GF_Event *evt){ if (term) return gf_sr_user_event(term->renderer, evt); return 0;}GF_EXPORTDouble gf_term_get_framerate(GF_Terminal *term, Bool absoluteFPS){ if (!term || !term->renderer) return 0; return gf_sr_get_fps(term->renderer, absoluteFPS);}/*get main scene current time in sec*/GF_EXPORTu32 gf_term_get_time_in_ms(GF_Terminal *term){ if (!term || !term->root_scene) return 0; if (term->root_scene->scene_codec) return gf_clock_time(term->root_scene->scene_codec->ck); else if (term->root_scene->dyn_ck) return gf_clock_time(term->root_scene->dyn_ck); return 0;}GF_Node *gf_term_pick_node(GF_Terminal *term, s32 X, s32 Y){ if (!term || !term->renderer) return NULL; return gf_sr_pick_node(term->renderer, X, Y);}GF_EXPORTvoid gf_term_navigate_to(GF_Terminal *term, const char *toURL){ if (!toURL && !term->root_scene) return; if (term->reload_url) free(term->reload_url); term->reload_url = NULL; if (term->root_scene) term->reload_url = gf_url_concatenate(term->root_scene->root_od->net_service->url, toURL); if (!term->reload_url) term->reload_url = strdup(toURL); term->reload_state = 1;}GF_EXPORTGF_Err gf_term_get_viewpoint(GF_Terminal *term, u32 viewpoint_idx, const char **outName, Bool *is_bound){ return gf_sr_get_viewpoint(term->renderer, viewpoint_idx, outName, is_bound);}GF_EXPORTGF_Err gf_term_set_viewpoint(GF_Terminal *term, u32 viewpoint_idx, const char *viewpoint_name){ return gf_sr_set_viewpoint(term->renderer, viewpoint_idx, viewpoint_name);}GF_EXPORTGF_Err gf_term_add_object(GF_Terminal *term, const char *url, Bool auto_play){ GF_MediaObject *mo; SFURL sfurl; MFURL mfurl; if (!url || !term || !term->root_scene || !term->root_scene->is_dynamic_scene) return GF_BAD_PARAM; sfurl.OD_ID = GF_ESM_DYNAMIC_OD_ID; sfurl.url = (char *) url; mfurl.count = 1; mfurl.vals = &sfurl; /*only text tracks are supported for now...*/ mo = gf_is_get_media_object(term->root_scene, &mfurl, GF_MEDIA_OBJECT_TEXT, 1); if (mo) { /*check if we must deactivate it*/ if (mo->odm) { if (mo->num_open && !auto_play) { gf_is_select_object(term->root_scene, mo->odm); } else { mo->odm->OD_PL = auto_play ? 1 : 0; } } else { gf_list_del_item(term->root_scene->media_objects, mo); gf_sg_vrml_mf_reset(&mo->URLs, GF_SG_VRML_MFURL); free(mo); mo = NULL; } } return mo ? GF_OK : GF_NOT_SUPPORTED;}void gf_term_attach_service(GF_Terminal *term, GF_InputService *service_hdl){ Bool net_check_interface(GF_InputService *ifce); GF_InlineScene *is; GF_ObjectManager *odm; if (!net_check_interface(service_hdl)) return; if (term->root_scene) gf_term_disconnect(term); gf_term_lock_net(term, 1); /*create a new scene*/ is = gf_is_new(NULL); odm = gf_odm_new(); gf_sg_set_script_action(is->graph, term_script_action, term); is->root_od = odm; term->root_scene = is; odm->parentscene = NULL; odm->subscene = is; odm->term = term; GF_SAFEALLOC(odm->net_service , GF_ClientService); odm->net_service->term = term; odm->net_service->owner = odm; odm->net_service->ifce = service_hdl; odm->net_service->url = strdup("Internal Service Handler"); odm->net_service->Clocks = gf_list_new(); gf_list_add(term->net_services, odm->net_service); gf_term_lock_net(term, 0); /*OK connect*/ odm->net_service->ifce->ConnectService(odm->net_service->ifce, odm->net_service, odm->net_service->url);}GF_EXPORTGF_Err gf_term_scene_update(GF_Terminal *term, char *type, char *com){ GF_Err e; GF_StreamContext *sc; GF_ESD *esd; Bool is_xml = 0; Double time = 0; u32 i, tag; GF_SceneLoader load; if (!term) return GF_BAD_PARAM; memset(&load, 0, sizeof(GF_SceneLoader)); load.localPath = gf_cfg_get_key(term->user->config, "General", "CacheDirectory"); load.flags = GF_SM_LOAD_FOR_PLAYBACK | GF_SM_LOAD_CONTEXT_READY; load.type = GF_SM_LOAD_BT; if (!term->root_scene) { gf_term_lock_net(term, 1); /*create a new scene*/ term->root_scene = gf_is_new(NULL); gf_sg_set_script_action(term->root_scene->graph, term_script_action, term); term->root_scene->root_od = gf_odm_new(); term->root_scene->root_od->parentscene = NULL; term->root_scene->root_od->subscene = term->root_scene; term->root_scene->root_od->term = term; gf_term_lock_net(term, 0); load.ctx = gf_sm_new(term->root_scene->graph); } else if (term->root_scene->root_od->OD) { load.ctx = gf_sm_new(term->root_scene->graph); /*restore streams*/ i=0; while ((esd = (GF_ESD*)gf_list_enum(term->root_scene->root_od->OD->ESDescriptors, &i)) ) { switch (esd->decoderConfig->streamType) { case GF_STREAM_OD: case GF_STREAM_SCENE: case GF_STREAM_PRIVATE_SCENE: sc = gf_sm_stream_new(load.ctx, esd->ESID, esd->decoderConfig->streamType, esd->decoderConfig->objectTypeIndication); if (esd->decoderConfig->streamType==GF_STREAM_PRIVATE_SCENE) sc->streamType = GF_STREAM_SCENE; sc->timeScale = esd->slConfig->timestampResolution; break; } } } else { return GF_BAD_PARAM; } load.ctx->max_node_id = gf_sg_get_max_node_id(term->root_scene->graph); i=0; while ((com[i] == ' ') || (com[i] == '\r') || (com[i] == '\n') || (com[i] == '\t')) i++; if (com[i]=='<') is_xml = 1; load.type = is_xml ? GF_SM_LOAD_XMTA : GF_SM_LOAD_BT; time = gf_is_get_time(term->root_scene); if (type && (!stricmp(type, "application/x-laser+xml") || !stricmp(type, "laser"))) { load.type = GF_SM_LOAD_XSR; time = gf_is_get_time(term->root_scene); } else if (type && (!stricmp(type, "image/svg+xml") || !stricmp(type, "svg")) ) { load.type = GF_SM_LOAD_XSR; time = gf_is_get_time(term->root_scene); } else if (type && (!stricmp(type, "model/x3d+xml") || !stricmp(type, "x3d")) ) load.type = GF_SM_LOAD_X3D; else if (type && (!stricmp(type, "model/x3d+vrml") || !stricmp(type, "x3dv")) ) load.type = GF_SM_LOAD_X3DV; else if (type && (!stricmp(type, "model/vrml") || !stricmp(type, "vrml")) ) load.type = GF_SM_LOAD_VRML; else if (type && (!stricmp(type, "application/x-xmt") || !stricmp(type, "xmt")) ) load.type = GF_SM_LOAD_XMTA; else if (type && (!stricmp(type, "application/x-bt") || !stricmp(type, "bt")) ) load.type = GF_SM_LOAD_BT; else if (gf_sg_get_root_node(term->root_scene->graph)) { tag = gf_node_get_tag(gf_sg_get_root_node(term->root_scene->graph)); if (tag >= GF_NODE_RANGE_FIRST_SVG) { load.type = GF_SM_LOAD_XSR; time = gf_is_get_time(term->root_scene); } else if (tag>=GF_NODE_RANGE_FIRST_X3D) { load.type = is_xml ? GF_SM_LOAD_X3D : GF_SM_LOAD_X3DV; } else { load.type = is_xml ? GF_SM_LOAD_XMTA : GF_SM_LOAD_BT; time = gf_is_get_time(term->root_scene); } } e = gf_sm_load_string(&load, com, 1); if (!e) { u32 j, au_count, st_count; st_count = gf_list_count(load.ctx->streams); for (i=0; i<st_count; i++) { sc = (GF_StreamContext*)gf_list_get(load.ctx->streams, i); au_count = gf_list_count(sc->AUs); for (j=0; j<au_count; j++) { GF_AUContext *au = (GF_AUContext *)gf_list_get(sc->AUs, j); e = gf_sg_command_apply_list(term->root_scene->graph, au->commands, time); if (e) break; } } } if (!term->root_scene->graph_attached) { if (!load.ctx->scene_width || !load.ctx->scene_height) {// load.ctx->scene_width = term->renderer->width;// load.ctx->scene_height = term->renderer->height; } gf_sg_set_scene_size_info(term->root_scene->graph, load.ctx->scene_width, load.ctx->scene_height, load.ctx->is_pixel_metrics); gf_is_attach_to_renderer(term->root_scene); } gf_sm_del(load.ctx); return e;}GF_Err gf_term_get_screen_buffer(GF_Terminal *term, GF_VideoSurface *framebuffer){ if (!term) return GF_BAD_PARAM; return gf_sr_get_screen_buffer(term->renderer, framebuffer);}GF_Err gf_term_release_screen_buffer(GF_Terminal *term, GF_VideoSurface *framebuffer){ if (!term) return GF_BAD_PARAM; return gf_sr_release_screen_buffer(term->renderer, framebuffer);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -