/apps/desktop/app_info.c

http://ftk.googlecode.com/ · C · 372 lines · 284 code · 59 blank · 29 comment · 71 complexity · 1f37d49755524a6333f31c9973df8728 MD5 · raw file

  1. /*
  2. * File: app_info.c
  3. * Author: Li XianJing <xianjimli@hotmail.com>
  4. * Brief: application infomation.
  5. *
  6. * Copyright (c) 2009 - 2010 Li XianJing <xianjimli@hotmail.com>
  7. *
  8. * Licensed under the Academic Free License version 2.1
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. /*
  25. * History:
  26. * ================================================================
  27. * 2009-11-29 Li XianJing <xianjimli@hotmail.com> created
  28. *
  29. */
  30. #include "ftk_log.h"
  31. #include "ftk_util.h"
  32. #include "ftk_dlfcn.h"
  33. #include "ftk_mmap.h"
  34. #include "app_info.h"
  35. #include "ftk_app_lua.h"
  36. struct _AppInfoManager
  37. {
  38. size_t nr;
  39. size_t alloc_nr;
  40. AppInfo* infos;
  41. };
  42. AppInfoManager* app_info_manager_create(void)
  43. {
  44. AppInfoManager* thiz = FTK_ZALLOC(sizeof(AppInfoManager));
  45. return thiz;
  46. }
  47. typedef struct _BuilderInfo
  48. {
  49. AppInfoManager* app_info_manager;
  50. }BuilderInfo;
  51. static void ftk_app_info_builder_on_start(FtkXmlBuilder* thiz, const char* tag, const char** attrs)
  52. {
  53. int i = 0;
  54. AppInfo app_info;
  55. const char* name = NULL;
  56. const char* value = NULL;
  57. BuilderInfo* info = (BuilderInfo*)thiz->priv;
  58. AppInfoManager* app_info_manager = info->app_info_manager;
  59. if(strcmp(tag, "application") != 0)
  60. {
  61. return;
  62. }
  63. memset(&app_info, 0, sizeof(AppInfo));
  64. for(i = 0; attrs[i] != NULL; i+=2)
  65. {
  66. name = attrs[i];
  67. value = attrs[i+1];
  68. switch(name[0])
  69. {
  70. case 'n':/*name*/
  71. {
  72. strncpy(app_info.name, value, sizeof(app_info.name) - 1);
  73. break;
  74. }
  75. case 'e': /*exec*/
  76. {
  77. strncpy(app_info.exec, value, sizeof(app_info.exec) - 1);
  78. break;
  79. }
  80. case 'i':
  81. {
  82. if(strcmp(name, "init") == 0)
  83. {
  84. strncpy(app_info.init, value, sizeof(app_info.init) - 1);
  85. }
  86. break;
  87. }
  88. default:break;
  89. }
  90. }
  91. if(app_info.init[0] && app_info.exec[0])
  92. {
  93. app_info_manager_add(app_info_manager, &app_info);
  94. }
  95. else
  96. {
  97. ftk_logd("%s: invalid application info.\n", __func__);
  98. }
  99. return;
  100. }
  101. static void ftk_app_info_builder_on_end(FtkXmlBuilder* thiz, const char* tag)
  102. {
  103. return;
  104. }
  105. static void ftk_app_info_builder_on_text(FtkXmlBuilder* thiz, const char* text, size_t length)
  106. {
  107. return;
  108. }
  109. static void ftk_app_info_builder_on_comment(FtkXmlBuilder* thiz, const char* text, size_t length)
  110. {
  111. return;
  112. }
  113. static void ftk_app_info_builder_on_pi(FtkXmlBuilder* thiz, const char* tag, const char** attrs)
  114. {
  115. return;
  116. }
  117. static void ftk_app_info_builder_on_error(FtkXmlBuilder* thiz, int line, int row, const char* message)
  118. {
  119. return;
  120. }
  121. static void ftk_app_info_builder_destroy(FtkXmlBuilder* thiz)
  122. {
  123. if(thiz != NULL)
  124. {
  125. FTK_ZFREE(thiz, sizeof(FtkXmlBuilder) + sizeof(BuilderInfo));
  126. }
  127. return;
  128. }
  129. static FtkXmlBuilder* ftk_app_info_builder_create(void)
  130. {
  131. FtkXmlBuilder* thiz = FTK_ZALLOC(sizeof(FtkXmlBuilder) + sizeof(BuilderInfo));
  132. if(thiz != NULL)
  133. {
  134. thiz->on_start_element = ftk_app_info_builder_on_start;
  135. thiz->on_end_element = ftk_app_info_builder_on_end;
  136. thiz->on_text = ftk_app_info_builder_on_text;
  137. thiz->on_comment = ftk_app_info_builder_on_comment;
  138. thiz->on_pi_element = ftk_app_info_builder_on_pi;
  139. thiz->on_error = ftk_app_info_builder_on_error;
  140. thiz->destroy = ftk_app_info_builder_destroy;
  141. }
  142. return thiz;
  143. }
  144. static Ret app_info_manager_parse(AppInfoManager* thiz, const char* xml, size_t length)
  145. {
  146. FtkXmlParser* parser = NULL;
  147. FtkXmlBuilder* builder = NULL;
  148. return_val_if_fail(xml != NULL, RET_FAIL);
  149. parser = ftk_xml_parser_create();
  150. return_val_if_fail(parser != NULL, RET_FAIL);
  151. builder = ftk_app_info_builder_create();
  152. if(builder != NULL)
  153. {
  154. BuilderInfo* info = (BuilderInfo*)builder->priv;
  155. info->app_info_manager = thiz;
  156. ftk_xml_parser_set_builder(parser, builder);
  157. ftk_xml_parser_parse(parser, xml, length);
  158. }
  159. ftk_xml_builder_destroy(builder);
  160. ftk_xml_parser_destroy(parser);
  161. return RET_OK;
  162. }
  163. Ret app_info_manager_load_file(AppInfoManager* thiz, const char* filename)
  164. {
  165. FtkMmap* m = NULL;
  166. Ret ret = RET_FAIL;
  167. return_val_if_fail(thiz != NULL && filename != NULL, RET_FAIL);
  168. m = ftk_mmap_create(filename, 0, -1);
  169. return_val_if_fail(m != NULL, RET_FAIL);
  170. ret = app_info_manager_parse(thiz, ftk_mmap_data(m), ftk_mmap_length(m));
  171. ftk_mmap_destroy(m);
  172. return ret;
  173. }
  174. Ret app_info_manager_load_dir(AppInfoManager* thiz, const char* path)
  175. {
  176. DIR* dir = NULL;
  177. char filename[260] = {0};
  178. struct dirent* iter = NULL;
  179. return_val_if_fail(thiz != NULL && path != NULL, RET_FAIL);
  180. dir = opendir(path);
  181. return_val_if_fail(dir != NULL, RET_FAIL);
  182. while((iter = readdir(dir)) != NULL)
  183. {
  184. if(iter->d_name[0] == '.') continue;
  185. if(strstr(iter->d_name, ".desktop") == NULL) continue;
  186. ftk_snprintf(filename, sizeof(filename), "%s/%s", path, iter->d_name);
  187. ftk_normalize_path(filename);
  188. app_info_manager_load_file(thiz, filename);
  189. }
  190. closedir(dir);
  191. return RET_OK;
  192. }
  193. int app_info_manager_get_count(AppInfoManager* thiz)
  194. {
  195. return_val_if_fail(thiz != NULL, 0);
  196. return thiz->nr;
  197. }
  198. Ret app_info_manager_init_app(AppInfoManager* thiz, AppInfo* info)
  199. {
  200. FtkLoadApp load = NULL;
  201. char filename[FTK_MAX_PATH+1] = {0};
  202. return_val_if_fail(thiz != NULL && info != NULL, RET_FAIL);
  203. if(info->app != NULL)
  204. {
  205. return RET_OK;
  206. }
  207. #ifdef FTK_HAS_LUA
  208. if(strstr(info->exec, ".lua") != NULL)
  209. {
  210. info->app = ftk_app_lua_create(info->name, info->exec);
  211. }
  212. else
  213. {
  214. #endif
  215. ftk_dl_file_name(info->exec, filename);
  216. if((info->handle = ftk_dlopen(filename)) == NULL)
  217. {
  218. }
  219. return_val_if_fail(info->handle != NULL, RET_FAIL);
  220. load = (FtkLoadApp)ftk_dlsym(info->handle, info->init);
  221. if(load == NULL)
  222. {
  223. }
  224. return_val_if_fail(load != NULL, RET_FAIL);
  225. info->app = load();
  226. return_val_if_fail(info->app != NULL, RET_FAIL);
  227. #ifdef FTK_HAS_LUA
  228. }
  229. #endif
  230. return RET_OK;
  231. }
  232. Ret app_info_manager_get(AppInfoManager* thiz, size_t index, AppInfo** info)
  233. {
  234. return_val_if_fail(thiz != NULL && index < thiz->nr && info != NULL, RET_FAIL);
  235. *info = thiz->infos+index;
  236. return app_info_manager_init_app(thiz, *info);
  237. }
  238. static Ret app_info_manager_extend(AppInfoManager* thiz, size_t delta)
  239. {
  240. size_t alloc_nr = 0;
  241. AppInfo* infos = NULL;
  242. return_val_if_fail(thiz != NULL, RET_FAIL);
  243. if((thiz->nr + delta) < thiz->alloc_nr) return RET_OK;
  244. alloc_nr = thiz->alloc_nr + delta + 10;
  245. infos = FTK_REALLOC(thiz->infos, sizeof(AppInfo) * alloc_nr);
  246. if(infos != NULL)
  247. {
  248. thiz->infos = infos;
  249. thiz->alloc_nr = alloc_nr;
  250. }
  251. return (thiz->nr + delta) < thiz->alloc_nr ? RET_OK : RET_FAIL;
  252. }
  253. Ret app_info_manager_add(AppInfoManager* thiz, AppInfo* info)
  254. {
  255. return_val_if_fail(thiz != NULL && info != NULL, RET_FAIL);
  256. return_val_if_fail(app_info_manager_extend(thiz, 1) == RET_OK, RET_FAIL);
  257. memcpy(thiz->infos+thiz->nr, info, sizeof(AppInfo));
  258. thiz->nr++;
  259. return RET_OK;
  260. }
  261. Ret app_info_manager_remove(AppInfoManager* thiz, size_t index)
  262. {
  263. return_val_if_fail(thiz != NULL, RET_FAIL);
  264. return_val_if_fail(index < thiz->nr, RET_FAIL);
  265. if((index + 1) < thiz->nr)
  266. {
  267. for(; (index + 1) < thiz->nr; index++)
  268. {
  269. thiz->infos[index] = thiz->infos[index+1];
  270. }
  271. }
  272. thiz->nr--;
  273. return RET_OK;
  274. }
  275. void app_info_manager_destroy(AppInfoManager* thiz)
  276. {
  277. if(thiz != NULL)
  278. {
  279. size_t i = 0;
  280. for(i = 0; i < thiz->nr; i++)
  281. {
  282. ftk_dlclose(thiz->infos[i].handle);
  283. thiz->infos[i].handle = NULL;
  284. ftk_app_destroy(thiz->infos[i].app);
  285. }
  286. FTK_FREE(thiz->infos);
  287. FTK_FREE(thiz);
  288. }
  289. return;
  290. }
  291. #ifdef APP_INFO_TEST
  292. const char* xml = "<application name=\"Contacts\" icon=\"icons/contacts.png\" shortcut=\"0\" exec=\"libapp-contacts.so\" main=\"ftk_main\" tr_path=\"ftk_translate_path\" tr_text=\"ftk_translate_text\" /><application name=\"Calculator\" icon=\"icons/calc.png\" shortcut=\"1\" exec=\"libapp-calc.so\" main=\"ftk_main\" tr_path=\"ftk_translate_path\" tr_text=\"ftk_translate_text\" />";
  293. int main(int argc, char* argv[])
  294. {
  295. size_t i = 0;
  296. AppInfo* info = NULL;
  297. AppInfoManager* thiz = app_info_manager_create();
  298. assert(app_info_manager_parse(thiz, xml, strlen(xml)) == RET_OK);
  299. assert(app_info_manager_get_count(thiz) == 2);
  300. app_info_manager_load_dir(thiz, DATA_DIR"/apps");
  301. assert(app_info_manager_get(thiz, 0, &info) == RET_OK);
  302. assert(strcmp(info->name, "Contacts") == 0);
  303. for(i = 0; i < app_info_manager_get_count(thiz); i++)
  304. {
  305. assert(app_info_manager_get(thiz, i, &info) == RET_OK);
  306. assert(info != NULL);
  307. ftk_logd("%s\n%s\n%s\n\n",
  308. info->name, info->exec, info->init);
  309. }
  310. app_info_manager_destroy(thiz);
  311. return 0;
  312. }
  313. #endif/*APP_INFO_TEST*/