PageRenderTime 65ms CodeModel.GetById 20ms app.highlight 27ms RepoModel.GetById 13ms app.codeStats 0ms

/apps/desktop/app_info.c

http://ftk.googlecode.com/
C | 372 lines | 284 code | 59 blank | 29 comment | 69 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/*
 26 * History:
 27 * ================================================================
 28 * 2009-11-29 Li XianJing <xianjimli@hotmail.com> created
 29 *
 30 */
 31#include "ftk_log.h"
 32#include "ftk_util.h"
 33#include  "ftk_dlfcn.h"
 34#include "ftk_mmap.h"
 35#include "app_info.h"
 36#include "ftk_app_lua.h"
 37
 38struct _AppInfoManager
 39{
 40	size_t nr;
 41	size_t alloc_nr;
 42	AppInfo* infos;
 43};
 44
 45AppInfoManager* app_info_manager_create(void)
 46{
 47	AppInfoManager* thiz = FTK_ZALLOC(sizeof(AppInfoManager));
 48
 49	return thiz;
 50}
 51
 52typedef struct _BuilderInfo
 53{
 54	AppInfoManager* app_info_manager;
 55}BuilderInfo;
 56
 57static void ftk_app_info_builder_on_start(FtkXmlBuilder* thiz, const char* tag, const char** attrs)
 58{
 59	int i = 0;
 60	AppInfo app_info;
 61	const char* name = NULL;
 62	const char* value = NULL;
 63	BuilderInfo* info = (BuilderInfo*)thiz->priv;
 64	AppInfoManager* app_info_manager = info->app_info_manager;
 65
 66	if(strcmp(tag, "application") != 0)
 67	{
 68		return;
 69	}
 70
 71	memset(&app_info, 0, sizeof(AppInfo));
 72	for(i = 0; attrs[i] != NULL; i+=2)
 73	{
 74		name = attrs[i];
 75		value = attrs[i+1];
 76		switch(name[0])
 77		{
 78			case 'n':/*name*/
 79			{
 80				strncpy(app_info.name, value, sizeof(app_info.name) - 1);
 81				break;
 82			}
 83			case 'e': /*exec*/
 84			{
 85				strncpy(app_info.exec, value, sizeof(app_info.exec) - 1);
 86				break;
 87			}
 88			case 'i':
 89			{
 90				if(strcmp(name, "init") == 0)
 91				{
 92					strncpy(app_info.init, value, sizeof(app_info.init) - 1);
 93				}
 94				break;
 95			}
 96			default:break;
 97		}
 98	}
 99
100	if(app_info.init[0] && app_info.exec[0])
101	{
102		app_info_manager_add(app_info_manager, &app_info);
103	}
104	else
105	{
106		ftk_logd("%s: invalid application info.\n", __func__);
107	}
108
109	return;
110}
111
112static void ftk_app_info_builder_on_end(FtkXmlBuilder* thiz, const char* tag)
113{
114	return;
115}
116
117static void ftk_app_info_builder_on_text(FtkXmlBuilder* thiz, const char* text, size_t length)
118{
119	return;
120}
121
122static void ftk_app_info_builder_on_comment(FtkXmlBuilder* thiz, const char* text, size_t length)
123{
124	return;
125}
126
127static void ftk_app_info_builder_on_pi(FtkXmlBuilder* thiz, const char* tag, const char** attrs)
128{
129	return;
130}
131
132static void ftk_app_info_builder_on_error(FtkXmlBuilder* thiz, int line, int row, const char* message)
133{
134	return;
135}
136
137static void ftk_app_info_builder_destroy(FtkXmlBuilder* thiz)
138{
139	if(thiz != NULL)
140	{
141		FTK_ZFREE(thiz, sizeof(FtkXmlBuilder) + sizeof(BuilderInfo));
142	}
143
144	return;
145}
146
147static FtkXmlBuilder* ftk_app_info_builder_create(void)
148{
149	FtkXmlBuilder* thiz = FTK_ZALLOC(sizeof(FtkXmlBuilder) + sizeof(BuilderInfo));
150
151	if(thiz != NULL)
152	{
153		thiz->on_start_element = ftk_app_info_builder_on_start;
154		thiz->on_end_element   = ftk_app_info_builder_on_end;
155		thiz->on_text          = ftk_app_info_builder_on_text;
156		thiz->on_comment       = ftk_app_info_builder_on_comment;
157		thiz->on_pi_element    = ftk_app_info_builder_on_pi;
158		thiz->on_error         = ftk_app_info_builder_on_error;
159		thiz->destroy          = ftk_app_info_builder_destroy;
160	}
161
162	return thiz;
163}
164
165static Ret  app_info_manager_parse(AppInfoManager* thiz, const char* xml, size_t length)
166{
167	FtkXmlParser* parser = NULL;
168	FtkXmlBuilder* builder = NULL;
169	return_val_if_fail(xml != NULL, RET_FAIL);
170
171	parser  = ftk_xml_parser_create();
172	return_val_if_fail(parser != NULL, RET_FAIL);
173
174	builder = ftk_app_info_builder_create();
175
176	if(builder != NULL)
177	{
178		BuilderInfo* info = (BuilderInfo*)builder->priv;
179		info->app_info_manager = thiz;
180		ftk_xml_parser_set_builder(parser, builder);
181		ftk_xml_parser_parse(parser, xml, length);
182	}
183	ftk_xml_builder_destroy(builder);
184	ftk_xml_parser_destroy(parser);
185
186	return RET_OK;
187}
188
189Ret  app_info_manager_load_file(AppInfoManager* thiz, const char* filename)
190{
191	FtkMmap* m = NULL;
192	Ret ret = RET_FAIL;
193	return_val_if_fail(thiz != NULL && filename != NULL, RET_FAIL);
194
195	m = ftk_mmap_create(filename, 0, -1);
196	return_val_if_fail(m != NULL, RET_FAIL);
197
198	ret = app_info_manager_parse(thiz, ftk_mmap_data(m), ftk_mmap_length(m));
199	ftk_mmap_destroy(m);
200
201	return ret;
202}
203
204Ret  app_info_manager_load_dir(AppInfoManager* thiz, const char* path)
205{
206	DIR* dir = NULL;
207	char filename[260] = {0};
208	struct dirent* iter = NULL;
209	return_val_if_fail(thiz != NULL && path != NULL, RET_FAIL);
210	dir = opendir(path);
211	return_val_if_fail(dir != NULL, RET_FAIL);
212
213	while((iter = readdir(dir)) != NULL)
214	{
215		if(iter->d_name[0] == '.') continue;
216		if(strstr(iter->d_name, ".desktop") == NULL) continue;
217
218		ftk_snprintf(filename, sizeof(filename), "%s/%s", path, iter->d_name);
219		ftk_normalize_path(filename);
220		app_info_manager_load_file(thiz, filename);
221	}
222	closedir(dir);
223
224	return RET_OK;
225}
226
227int  app_info_manager_get_count(AppInfoManager* thiz)
228{
229	return_val_if_fail(thiz != NULL, 0);
230
231	return thiz->nr;
232}
233
234Ret  app_info_manager_init_app(AppInfoManager* thiz, AppInfo* info)
235{
236	FtkLoadApp load = NULL;
237	char filename[FTK_MAX_PATH+1] = {0};
238	return_val_if_fail(thiz != NULL && info != NULL, RET_FAIL);
239
240	if(info->app != NULL)
241	{
242		return RET_OK;
243	}
244#ifdef FTK_HAS_LUA
245	if(strstr(info->exec, ".lua") != NULL)
246	{
247		info->app = ftk_app_lua_create(info->name, info->exec);
248	}
249	else
250	{
251#endif
252		ftk_dl_file_name(info->exec, filename);
253		if((info->handle = ftk_dlopen(filename)) == NULL)
254		{
255		}
256		return_val_if_fail(info->handle != NULL, RET_FAIL);
257		
258		load = (FtkLoadApp)ftk_dlsym(info->handle, info->init);
259		if(load == NULL)
260		{
261
262		}
263		return_val_if_fail(load != NULL, RET_FAIL);
264
265		info->app = load();
266		return_val_if_fail(info->app != NULL, RET_FAIL);
267#ifdef FTK_HAS_LUA
268	}
269#endif
270	return RET_OK;
271}
272
273Ret  app_info_manager_get(AppInfoManager* thiz, size_t index, AppInfo** info)
274{
275	return_val_if_fail(thiz != NULL && index < thiz->nr && info != NULL, RET_FAIL);
276
277	*info = thiz->infos+index;
278
279	return app_info_manager_init_app(thiz, *info);
280}
281
282static Ret  app_info_manager_extend(AppInfoManager* thiz, size_t delta)
283{
284	size_t alloc_nr = 0;
285	AppInfo* infos = NULL;
286	return_val_if_fail(thiz != NULL, RET_FAIL);
287
288	if((thiz->nr + delta) < thiz->alloc_nr) return RET_OK;
289
290	alloc_nr = thiz->alloc_nr + delta + 10;
291	infos = FTK_REALLOC(thiz->infos, sizeof(AppInfo) * alloc_nr);
292	if(infos != NULL)
293	{
294		thiz->infos = infos;
295		thiz->alloc_nr = alloc_nr;
296	}
297
298	return (thiz->nr + delta) < thiz->alloc_nr ? RET_OK : RET_FAIL;
299}
300
301Ret  app_info_manager_add(AppInfoManager* thiz, AppInfo* info)
302{
303	return_val_if_fail(thiz != NULL && info != NULL, RET_FAIL);
304	return_val_if_fail(app_info_manager_extend(thiz, 1) == RET_OK, RET_FAIL);
305
306	memcpy(thiz->infos+thiz->nr, info, sizeof(AppInfo));
307	thiz->nr++;
308
309	return RET_OK;
310}
311
312Ret  app_info_manager_remove(AppInfoManager* thiz, size_t index)
313{
314	return_val_if_fail(thiz != NULL, RET_FAIL);
315	return_val_if_fail(index < thiz->nr, RET_FAIL);
316
317	if((index + 1) < thiz->nr)
318	{
319		for(; (index + 1) < thiz->nr; index++)
320		{
321			thiz->infos[index] = thiz->infos[index+1];
322		}
323	}
324	thiz->nr--;
325
326	return RET_OK;
327}
328
329void app_info_manager_destroy(AppInfoManager* thiz)
330{
331	if(thiz != NULL)
332	{
333		size_t i = 0;
334		for(i = 0; i < thiz->nr; i++)
335		{
336			ftk_dlclose(thiz->infos[i].handle);
337			thiz->infos[i].handle = NULL;
338			ftk_app_destroy(thiz->infos[i].app);
339		}
340		FTK_FREE(thiz->infos);
341		FTK_FREE(thiz);
342	}
343
344	return;
345}
346
347#ifdef APP_INFO_TEST
348const 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\" />";
349
350int main(int argc, char* argv[])
351{
352	size_t i = 0;
353	AppInfo* info = NULL;
354	AppInfoManager* thiz = app_info_manager_create();
355	assert(app_info_manager_parse(thiz, xml, strlen(xml)) == RET_OK);
356	assert(app_info_manager_get_count(thiz) == 2);
357	app_info_manager_load_dir(thiz, DATA_DIR"/apps");
358	assert(app_info_manager_get(thiz, 0, &info) == RET_OK);
359	assert(strcmp(info->name, "Contacts") == 0);	
360
361	for(i = 0; i < app_info_manager_get_count(thiz); i++)
362	{
363		assert(app_info_manager_get(thiz, i, &info) == RET_OK);
364		assert(info != NULL);
365		ftk_logd("%s\n%s\n%s\n\n", 
366			info->name, info->exec, info->init);
367	}
368	app_info_manager_destroy(thiz);
369
370	return 0;
371}
372#endif/*APP_INFO_TEST*/