Movian 中使用了大量的 backend 服务,本文来分析 backend 实现流程
Register
以 Search 为例
static inr
search_canhandle(const char *url)
{
return !strncmp(url, "search:", strlen("search:"));
}
static int
search_open(prop_t *page, const char *url0, int sync)
{
}
static backend_t be_search = {
.be_canhandle = search_canhandle,
.be_open = search_open,
};
BE_REGISTER(search);BE_REGISTER 宏定义
#define BE_REGISTER(name)
INITIALIZER(backend_init_ ## name) { \
backend_register(&be_ ## name); \
}INITIALIZER 宏定义在 src/compiler.h
#elif defined(__GNUC__)
#define INITIALIZER(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#endif其中 __attribute__ constructor 被修饰的函数作为构造函数执行
其中 backend_register 将 be_search 插入到链表 backends 中
void
backend_register(backend_t *be)
{
LIST_INSERT_HEAD(&backends, be, be_global_link);
}因此在执行到 main 之前已经调用 backend_register,完成 backend 注册
Init
src/arch/linux/linux_main.c
main ->main_init ->backend_init
void
backend_init(void)
{
backend_t *be;
hts_lwmutex_init(&dyanamic_backends_mutex);
hts_mutex_init(&imageloader_mutex);
hts_cond_init(&imageloader_cond, &imageloader_mutex);
TAILQ_INIT(&cached_images);
LIST_FOREACH(be, &backends, be_global_link)
if(be->be_init != NULL)
be->be_init();
}
play video
UI ->glw_create ->class->gc_ctor ->glw_video_ctor ->video_playback_create ->video_player_idle ->play_video ->backend_play_video
play audio
与 video 流程不一样
be_playqueue 注册
static backend_t be_playqueue = {
.be_init = playqueue_init,
.be_canhandle = be_playqueue_canhandle,
.be_open = be_playqueue_open,
};
BE_REGISTER(playqueue);playqueue_init ->player_thread ->backend_play_audio
page open
backend_page_open 注册为 backend,除此之外只给 upgrade 调用
static int
upgrade_open_url(prop_t *page, const char *url, int sync)
{
if(!strcmp(url, "showtime:upgrade")) {
usage_page_open(sync, "Upgrade");
backend_page_open(page, "page:upgrade", sync);
upgrade_refresh();
prop_set(page, "directClose", PROP_SET_INT, 1);
} else {
nav_open_error(page, "Invalid URI");
}
return 0;
}
static backend_t be_page = {
.be_canhandle = be_page_canhandle,
.be_open = backend_page_open,
};
BE_REGISTER(page);backend probe
main_init ->service_int ->service_probe_loop ->backend_probe
backend_probe_result_t
backend_probe(const char *url, char *errbuf, size_t errlen, int timeout_ms)
{
if(timeout_ms <= 0)
timeout_ms = 5000;
// 匹配 URL
backend_t *be = backend_canhandle(url);
if(be == NULL) {
snprintf(errbuf, errlen, "No handler for URL");
return BACKEND_PROBE_NO_HANDLER;
}
if(be->be_probe == NULL)
return BACKEND_PROBE_OK;
// Example: .be_probe = fa_check_url
return be->be_probe(url, errbuf, errlen, timeout_ms);
}
backend open
search_open ->backend_open -> backend_search
可以匹配到 .be_search = plugin_search .be_search = ecmascript_search
通用 src/arch/linux/linux_main.c
main ->linux_global_eventsink ->switch_ui
将 ui_current 设置为 ui_glw,然后
main_loop ->ui_glw->start ->glw_x11_start ->nav_spawn ->nav_create ->nav_open0 ->nav_open_backend ->nav_open_thread ->back_open