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