📄 network_service.c
字号:
if (!url) { (*ret_code) = GF_URL_ERROR; return NULL; } sURL = NULL; if (parent_url) sURL = gf_url_concatenate(parent_url, url); /*path absolute*/ if (!sURL) { char *tmp = (char *) url; if (!strnicmp(url, "file:///", 8)) tmp += 8; else if (!strnicmp(url, "file://", 7)) tmp += 7; if ((tmp[0]=='/') && (tmp[2]==':')) tmp += 1; sURL = strdup(tmp); } if (no_mime_check) { mime_type = NULL; } else { /*fetch a mime type if any. If error don't even attempt to open the service TRYTOFIXME: it would be nice to reuse the downloader created while fetching the mime type, however we don't know if the plugin will want it threaded or not.... */ mime_type = get_mime_type(term, sURL, &e); if (e) { free(sURL); (*ret_code) = e; return NULL; } } if (mime_type && (!stricmp(mime_type, "text/plain") || !stricmp(mime_type, "video/quicktime")) ) { free(mime_type); mime_type = NULL; } ifce = NULL; /*load from mime type*/ if (mime_type) { const char *sPlug = gf_cfg_get_key(term->user->config, "MimeTypes", mime_type); GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] Mime type found: %s\n", mime_type)); if (sPlug) sPlug = strrchr(sPlug, '"'); if (sPlug) { sPlug += 2; ifce = (GF_InputService *) gf_modules_load_interface_by_name(term->user->modules, sPlug, GF_NET_CLIENT_INTERFACE); if (ifce && !net_check_interface(ifce) ) { gf_modules_close_interface((GF_BaseInterface *) ifce); ifce = NULL; } } } ext = strrchr(sURL, '.'); if (ext && !stricmp(ext, ".gz")) { char *anext; ext[0] = 0; anext = strrchr(sURL, '.'); ext[0] = '.'; ext = anext; } /*no mime type: either local or streaming. If streaming discard extension checking*/ if (!ifce && !mime_type && strstr(sURL, "://") && strnicmp(sURL, "file://", 7)) ext = NULL; if (mime_type) free(mime_type); /*browse extensions for prefered module*/ if (!ifce && ext) { u32 keyCount; strcpy(szExt, &ext[1]); ext = strrchr(szExt, '#'); if (ext) ext[0] = 0; GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] No mime type found - checking by extension %s\n", szExt)); keyCount = gf_cfg_get_key_count(term->user->config, "MimeTypes"); for (i=0; i<keyCount; i++) { char *sMime, *sPlug; const char *sKey; sMime = (char *) gf_cfg_get_key_name(term->user->config, "MimeTypes", i); if (!sMime) continue; sKey = gf_cfg_get_key(term->user->config, "MimeTypes", sMime); if (!sKey) continue; if (!check_extension((char *)sKey, szExt)) continue; sPlug = strrchr(sKey, '"'); if (!sPlug) continue; /*bad format entry*/ sPlug += 2; ifce = (GF_InputService *) gf_modules_load_interface_by_name(term->user->modules, sPlug, GF_NET_CLIENT_INTERFACE); if (!ifce) continue; if (!net_check_interface(ifce)) { gf_modules_close_interface((GF_BaseInterface *) ifce); ifce = NULL; continue; } break; } } /*browse all modules*/ if (!ifce) { for (i=0; i< gf_modules_get_count(term->user->modules); i++) { ifce = (GF_InputService *) gf_modules_load_interface(term->user->modules, i, GF_NET_CLIENT_INTERFACE); if (!ifce) continue; GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] Checking if module %s supports URL %s\n", ifce->module_name, sURL)); if (net_check_interface(ifce) && ifce->CanHandleURL(ifce, sURL)) break; gf_modules_close_interface((GF_BaseInterface *) ifce); ifce = NULL; } } if (!ifce) { free(sURL); (*ret_code) = GF_NOT_SUPPORTED; return NULL; } GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] Found input plugin %s for URL %s\n", ifce->module_name, sURL)); *out_url = sURL; return ifce;}GF_ClientService *gf_term_service_new(GF_Terminal *term, struct _od_manager *owner, const char *url, GF_ClientService *parent_service, GF_Err *ret_code){ char *sURL; GF_ClientService *serv; GF_InputService *ifce = gf_term_can_handle_service(term, url, parent_service ? parent_service->url : NULL, 0, &sURL, ret_code); if (!ifce) return NULL; GF_SAFEALLOC(serv, GF_ClientService); serv->term = term; serv->owner = owner; serv->ifce = ifce; serv->url = sURL; serv->Clocks = gf_list_new(); serv->dnloads = gf_list_new(); gf_list_add(term->net_services, serv); return serv;}Bool gf_term_is_supported_url(GF_Terminal *term, const char *fileName, Bool use_parent_url, Bool no_mime_check){ GF_InputService *ifce; GF_Err e; char *sURL; char *parent_url = NULL; if (use_parent_url && term->root_scene) parent_url = term->root_scene->root_od->net_service->url; ifce = gf_term_can_handle_service(term, fileName, parent_url, no_mime_check, &sURL, &e); if (!ifce) return 0; gf_modules_close_interface((GF_BaseInterface *) ifce); free(sURL); return 1;}Bool gf_term_service_can_handle_url(GF_ClientService *ns, char *url){ /*if no owner attached the service is being deleted, don't query it*/ if (!ns->owner || !ns->ifce->CanHandleURLInService) return 0; return ns->ifce->CanHandleURLInService(ns->ifce, url);}GF_Err gf_term_service_command(GF_ClientService *ns, GF_NetworkCommand *com) { return ns->ifce->ServiceCommand(ns->ifce, com); }GF_Err gf_term_channel_get_sl_packet(GF_ClientService *ns, LPNETCHANNEL channel, char **out_data_ptr, u32 *out_data_size, GF_SLHeader *out_sl_hdr, Bool *sl_compressed, GF_Err *out_reception_status, Bool *is_new_data){ if (!ns->ifce->ChannelGetSLP) return GF_NOT_SUPPORTED; return ns->ifce->ChannelGetSLP(ns->ifce, channel, out_data_ptr, out_data_size, out_sl_hdr, sl_compressed, out_reception_status, is_new_data);}GF_Err gf_term_channel_release_sl_packet(GF_ClientService *ns, LPNETCHANNEL channel){ if (!ns->ifce->ChannelGetSLP) return GF_NOT_SUPPORTED; return ns->ifce->ChannelReleaseSLP(ns->ifce, channel);}GF_EXPORTvoid gf_term_on_message(GF_ClientService *service, GF_Err error, const char *message){ assert(service); term_on_message(service->term, service, error, message);}GF_EXPORTvoid gf_term_on_connect(GF_ClientService *service, LPNETCHANNEL ns, GF_Err response){ assert(service); term_on_connect(service->term, service, ns, response);}GF_EXPORTvoid gf_term_on_disconnect(GF_ClientService *service, LPNETCHANNEL ns, GF_Err response){ assert(service); term_on_disconnect(service->term, service, ns, response);}GF_EXPORTvoid gf_term_on_command(GF_ClientService *service, GF_NetworkCommand *com, GF_Err response){ assert(service); term_on_command(service->term, service, com, response);}GF_EXPORTvoid gf_term_on_sl_packet(GF_ClientService *service, LPNETCHANNEL ns, char *data, u32 data_size, GF_SLHeader *hdr, GF_Err reception_status){ assert(service); term_on_slp_recieved(service->term, service, ns, data, data_size, hdr, reception_status);}GF_EXPORTvoid gf_term_add_media(GF_ClientService *service, GF_Descriptor *media_desc, Bool no_scene_check){ term_on_media_add(service->term, service, media_desc, no_scene_check);}GF_EXPORTconst char *gf_term_get_service_url(GF_ClientService *service){ if (!service) return NULL; return service->url;}void NM_DeleteService(GF_ClientService *ns){ const char *sOpt = gf_cfg_get_key(ns->term->user->config, "StreamingCache", "AutoSave"); if (ns->cache) gf_term_service_cache_close(ns, (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0); gf_modules_close_interface((GF_BaseInterface *)ns->ifce); free(ns->url); assert(!ns->nb_odm_users); assert(!ns->nb_ch_users); /*delete all the clocks*/ while (gf_list_count(ns->Clocks)) { GF_Clock *ck = (GF_Clock *)gf_list_get(ns->Clocks, 0); gf_list_rem(ns->Clocks, 0); gf_clock_del(ck); } gf_list_del(ns->Clocks); assert(!gf_list_count(ns->dnloads)); gf_list_del(ns->dnloads); free(ns);}GF_EXPORTGF_InputService *gf_term_get_service_interface(GF_ClientService *serv){ return serv ? serv->ifce : NULL;}GF_EXPORTGF_DownloadSession *gf_term_download_new(GF_ClientService *service, const char *url, u32 flags, gf_dm_user_io user_io, void *cbk){ GF_Err e; GF_DownloadSession * sess; char *sURL; if (!service || !user_io) return NULL; sURL = gf_url_concatenate(service->url, url); /*path was absolute*/ if (!sURL) sURL = strdup(url); sess = gf_dm_sess_new(service->term->downloader, sURL, flags, user_io, cbk, &e); free(sURL); if (!sess) return NULL; gf_dm_sess_set_private(sess, service); gf_list_add(service->dnloads, sess); return sess;}GF_EXPORTvoid gf_term_download_del(GF_DownloadSession * sess){ GF_ClientService *serv; if (!sess) return; serv = (GF_ClientService *)gf_dm_sess_get_private(sess); /*avoid sending data back to user*/ gf_dm_sess_abort(sess); /*unregister from service*/ gf_list_del_item(serv->dnloads, sess); /*same as service: this may be called in the downloader thread (typically when download fails) so we must queue the downloader and let the term delete it later on*/ gf_list_add(serv->term->net_services_to_remove, sess);}GF_EXPORTvoid gf_term_download_update_stats(GF_DownloadSession * sess){ GF_ClientService *serv; const char *szURI; u32 total_size, bytes_done, net_status, bytes_per_sec; gf_dm_sess_get_stats(sess, NULL, &szURI, &total_size, &bytes_done, &bytes_per_sec, &net_status); serv = (GF_ClientService *)gf_dm_sess_get_private(sess); switch (net_status) { case GF_NETIO_SETUP: gf_term_on_message(serv, GF_OK, "Connecting"); break; case GF_NETIO_CONNECTED: gf_term_on_message(serv, GF_OK, "Connected"); break; case GF_NETIO_WAIT_FOR_REPLY: gf_term_on_message(serv, GF_OK, "Waiting for reply..."); break; case GF_NETIO_DATA_EXCHANGE: /*notify some connection / ...*/ if (total_size) { GF_Event evt; evt.type = GF_EVENT_PROGRESS; evt.progress.progress_type = 1; evt.progress.service = szURI; evt.progress.total = total_size; evt.progress.done = bytes_done; GF_USER_SENDEVENT(serv->term->user, &evt); } break; }}void gf_term_service_del(GF_ClientService *ns){ /*this is a downloader session*/ if (! * (u32 *) ns) { gf_dm_sess_del((GF_DownloadSession * ) ns); } else { NM_DeleteService(ns); }}GF_EXPORTvoid gf_term_register_mime_type(GF_InputService *ifce, const char *mimeType, const char *extList, const char *description){ u32 len; char *buf; if (!ifce || !mimeType || !extList || !description) return; len = strlen(extList) + 3 + strlen(description) + 3 + strlen(ifce->module_name) + 1; buf = (char*)malloc(sizeof(char)*len); sprintf(buf, "\"%s\" ", extList); strlwr(buf); strcat(buf, "\""); strcat(buf, description); strcat(buf, "\" "); strcat(buf, ifce->module_name); gf_modules_set_option((GF_BaseInterface *)(GF_BaseInterface *)ifce, "MimeTypes", mimeType, buf); free(buf);}GF_EXPORTBool gf_term_check_extension(GF_InputService *ifce, const char *mimeType, const char *extList, const char *description, const char *fileExt){ const char *szExtList; char *ext, szExt[100]; if (!ifce || !mimeType || !extList || !description || !fileExt) return 0; /*this is a URL*/ if ( (strlen(fileExt)>20) || strchr(fileExt, '/')) return 0; if (fileExt[0]=='.') fileExt++; strcpy(szExt, fileExt); strlwr(szExt); ext = strchr(szExt, '#'); if (ext) ext[0]=0; szExtList = gf_modules_get_option((GF_BaseInterface *)(GF_BaseInterface *)ifce, "MimeTypes", mimeType); if (!szExtList) { gf_term_register_mime_type(ifce, mimeType, extList, description); szExtList = gf_modules_get_option((GF_BaseInterface *)(GF_BaseInterface *)ifce, "MimeTypes", mimeType); } if (!strstr(szExtList, ifce->module_name)) return 0; return check_extension((char *)szExtList, szExt);}GF_Err gf_term_service_cache_load(GF_ClientService *ns){ GF_Err e; const char *sOpt; char szName[GF_MAX_PATH], szURL[1024]; GF_NetworkCommand com; u32 i; GF_StreamingCache *mcache = NULL; /*is service cachable*/ com.base.on_channel = NULL; com.base.command_type = GF_NET_IS_CACHABLE; if (ns->ifce->ServiceCommand(ns->ifce, &com) != GF_OK) return GF_OK; /*locate a cache*/ for (i=0; i< gf_modules_get_count(ns->term->user->modules); i++) { mcache = (GF_StreamingCache *) gf_modules_load_interface(ns->term->user->modules, i, GF_STREAMING_MEDIA_CACHE); if (mcache && mcache->Open && mcache->Close && mcache->Write && mcache->ChannelGetSLP && mcache->ChannelReleaseSLP && mcache->ServiceCommand) break; if (mcache) gf_modules_close_interface((GF_BaseInterface *)mcache); mcache = NULL; } if (!mcache) return GF_NOT_SUPPORTED; sOpt = gf_cfg_get_key(ns->term->user->config, "StreamingCache", "RecordDirectory"); if (!sOpt) sOpt = gf_cfg_get_key(ns->term->user->config, "General", "CacheDirectory"); if (sOpt) { strcpy(szName, sOpt); if (szName[strlen(szName)-1]!='\\') strcat(szName, "\\"); } else { strcpy(szName, ""); } sOpt = gf_cfg_get_key(ns->term->user->config, "StreamingCache", "BaseFileName"); if (sOpt) { strcat(szName, sOpt); } else { char *sep; strcat(szName, "rec_"); sOpt = strrchr(ns->url, '/'); if (!sOpt) sOpt = strrchr(ns->url, '\\'); if (sOpt) sOpt += 1; else { sOpt = strstr(ns->url, "://"); if (sOpt) sOpt += 3; else sOpt = ns->url; } strcpy(szURL, sOpt); sep = strrchr(szURL, '.'); if (sep) sep[0] = 0; for (i=0; i<strlen(szURL); i++) { switch (szURL[i]) { case '/': case '\\': case '.': case ':': case '?': szURL[i] = '_'; break; } } strcat(szName, szURL); } sOpt = gf_cfg_get_key(ns->term->user->config, "StreamingCache", "KeepExistingFiles"); e = mcache->Open(mcache, ns, szName, (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0); if (e) { gf_modules_close_interface((GF_BaseInterface *)mcache); return e; } ns->cache = mcache; return GF_OK;}GF_Err gf_term_service_cache_close(GF_ClientService *ns, Bool no_save){ GF_Err e; if (!ns->cache) return GF_OK; e = ns->cache->Close(ns->cache, no_save); gf_modules_close_interface((GF_BaseInterface *)ns->cache); ns->cache = NULL; return e;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -