分析源文件 src/plugins.c
install
plugin_install
-> plugin_load
-> ecmascript_plugin_load
plugin_load
解析 plugin.json
文件
//plugin.json 路径
snprintf(ctrlfile, sizeof(ctrlfile), "%s/plugin.json", url);
// 读取文件内容
if((b = fa_load(ctrlfile,
FA_LOAD_ERRBUF(errbuf2, sizeof(errbuf2)),
NULL)) == NULL) {
snprintf(errbuf, errlen, "Unable to load %s -- %s", ctrlfile, errbuf2);
return -1;
}
// 解析 json 文件
ctrl = htsmsg_json_deserialize2(buf_cstr(b), errbuf, errlen);
// 获取数据
const char *type = htsmsg_get_str(ctrl, "type");
const char *id = htsmsg_get_str(ctrl, "id");
const char *version = htsmsg_get_str(ctrl, "version");
const char *file = htsmsg_get_str(ctrl, "file");
//js 文件路径
snprintf(fullpath, sizeof(fullpath), "%s/%s", url, file);
int version = htsmsg_get_u32_or_default(ctrl, "apiversion", 1);
// 打开 js 文件
hts_mutex_unlock(&plugin_mutex);
r = ecmascript_plugin_load(id, fullpath, errbuf, errlen, version,
buf_cstr(b), pflags);
hts_mutex_lock(&plugin_mutex);
scmascript_plugin_load
int
ecmascript_plugin_load(const char *id, const char *url,
char *errbuf, size_t errlen,
int version, const char *manifest,
int flags)
{
char storage[PATH_MAX];
snprintf(storage, sizeof(storage),
"%s/plugins/%s", gconf.persistent_path, id);
es_context_t *ec = es_context_create(id, flags | ECMASCRIPT_PLUGIN,
url, storage);
duk_context *ctx = es_context_begin(ec);
duk_push_global_object(ctx);
int plugin_obj_idx = duk_push_object(ctx);
duk_push_string(ctx, id);
duk_put_prop_string(ctx, plugin_obj_idx, "id");
duk_push_string(ctx, url);
duk_put_prop_string(ctx, plugin_obj_idx, "url");
duk_push_string(ctx, manifest);
duk_put_prop_string(ctx, plugin_obj_idx, "manifest");
duk_push_int(ctx, version);
duk_put_prop_string(ctx, plugin_obj_idx, "apiversion");
if(ec->ec_path) {
duk_push_string(ctx, ec->ec_path);
duk_put_prop_string(ctx, plugin_obj_idx, "path");
}
//Plugin object {"id": , "url": , "manifest": , "apiversion": , "path": }
duk_put_prop_string(ctx, -2, "Plugin");
duk_pop(ctx);
if(version == 1) {
int64_t ts0 = arch_get_ts();
// 根据文件及路径编译为函数
if(es_load_and_compile(ec, "dataroot://res/ecmascript/legacy/api-v1.js",
ctx))
goto bad;
int64_t ts1 = arch_get_ts();
// 执行函数
if(duk_pcall(ctx, 0)) {
es_dump_err(ctx);
goto bad;
}
int64_t ts2 = arch_get_ts();
//xx.js 编译
if(es_load_and_compile(ec, url, ctx)) {
duk_pop(ctx);
goto bad;
}
int64_t ts3 = arch_get_ts();
duk_swap_top(ctx, 0);
// 执行
if(duk_pcall_method(ctx, 0))
es_dump_err(ctx);
int64_t ts4 = arch_get_ts();
es_debug(ec, "API v1 emulation: Compile:%dms Exec:%dms",
((int)(ts1 - ts0)) / 1000,
((int)(ts2 - ts1)) / 1000);
es_debug(ec, "Plugin main: Compile:%dms Exec:%dms",
((int)(ts3 - ts2)) / 1000,
((int)(ts4 - ts3)) / 1000);
} else {
es_exec(ec, url, ctx);
}
bad:
es_context_end(ec, 1, ctx);
es_context_release(ec);
return 0;
}