1 /*
2  *			GPAC - Multimedia Framework C SDK
3  *
4  *			Authors: Jean Le Feuvre
5  *			Copyright (c) Telecom ParisTech 2005-2012
6  *					All rights reserved
7  *
8  *  This file is part of GPAC / common tools sub-project
9  *
10  *  GPAC is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU Lesser General Public License as published by
12  *  the Free Software Foundation; either version 2, or (at your option)
13  *  any later version.
14  *
15  *  GPAC 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 Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; see the file COPYING.  If not, write to
22  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25 
26 #include <gpac/tools.h>
27 #include <gpac/network.h>
28 
29 #ifdef __SYMBIAN32__
30 
31 #include <time.h>
32 #include <sys/stat.h>
33 #include <sys/time.h>
34 #include <dirent.h>
35 #include <unistd.h>
36 #include <sys/times.h>
37 #include <sys/resource.h>
38 /*symbian stdlib*/
39 #include <e32std.h>
40 /*symbian core (for scheduler & trap cleanup)*/
41 #include <e32base.h>
42 /*hardware abstraction layer*/
43 #include <hal.h>
44 
45 /*gpac module internals*/
46 #include "module_wrap.h"
47 #include <gpac/thread.h>
48 
49 
50 //  Exported Functions (DLL entry point)
51 #ifndef EKA2 // for EKA1 only
E32Dll(TDllReason)52 GLDEF_C TInt E32Dll(TDllReason /*aReason*/)
53 // Called when the DLL is loaded and unloaded. Note: have to define
54 // epoccalldllentrypoints in MMP file to get this called in THUMB.
55 {
56 	return KErrNone;
57 }
58 
59 #endif
60 
61 
62 
63 #define SLEEP_ABS_SELECT		1
64 
65 static u32 sys_start_time = 0;
66 
67 GF_EXPORT
gf_sys_clock()68 u32 gf_sys_clock()
69 {
70 	struct timeval now;
71 	gettimeofday(&now, NULL);
72 	return ( (now.tv_sec)*1000 + (now.tv_usec) / 1000) - sys_start_time;
73 }
74 
75 
76 GF_EXPORT
gf_sleep(u32 ms)77 void gf_sleep(u32 ms)
78 {
79 	TTimeIntervalMicroSeconds32 inter;
80 	inter = (TInt) (1000*ms);
81 #ifdef __SERIES60_3X__
82 	User::AfterHighRes(inter);
83 #else
84 	User::After(inter);
85 #endif
86 
87 #if 0
88 	TInt error;
89 	CActiveScheduler::RunIfReady(error, CActive::EPriorityIdle);
90 
91 	RTimer timer;
92 	TRequestStatus timerStatus;
93 	timer.CreateLocal();
94 
95 	timer.After(timerStatus,ms*1000);
96 	User::WaitForRequest(timerStatus);
97 #endif
98 }
99 
100 GF_EXPORT
gf_delete_file(char * fileName)101 void gf_delete_file(char *fileName)
102 {
103 	remove(fileName);
104 }
105 
106 
107 GF_EXPORT
gf_rand_init(Bool Reset)108 void gf_rand_init(Bool Reset)
109 {
110 	if (Reset) {
111 		srand(1);
112 	} else {
113 		srand( (u32) time(NULL) );
114 	}
115 }
116 
117 GF_EXPORT
gf_rand()118 u32 gf_rand()
119 {
120 	return rand();
121 }
122 
123 
124 #ifndef GPAC_READ_ONLY
125 GF_EXPORT
gf_temp_file_new()126 FILE *gf_temp_file_new()
127 {
128 	return tmpfile();
129 }
130 #endif
131 
132 
133 GF_EXPORT
gf_utc_time_since_1970(u32 * sec,u32 * msec)134 void gf_utc_time_since_1970(u32 *sec, u32 *msec)
135 {
136 	struct timeval tv;
137 	gettimeofday(&tv, NULL);
138 	*sec = tv.tv_sec;
139 	*msec = tv.tv_usec/1000;
140 }
141 
142 GF_EXPORT
gf_get_user_name(char * buf,u32 buf_size)143 void gf_get_user_name(char *buf, u32 buf_size)
144 {
145 	strcpy(buf, "mpeg4-user");
146 
147 #if 0
148 	s32 len;
149 	char *t;
150 	strcpy(buf, "");
151 	len = 1024;
152 	GetUserName(buf, &len);
153 	if (!len) {
154 		t = getenv("USER");
155 		if (t) strcpy(buf, t);
156 	}
157 #endif
158 #if 0
159 	struct passwd *pw;
160 	pw = getpwuid(getuid());
161 	strcpy(buf, "");
162 	if (pw && pw->pw_name) strcpy(name, pw->pw_name);
163 #endif
164 }
165 
166 GF_EXPORT
my_str_upr(char * str)167 char * my_str_upr(char *str)
168 {
169 	u32 i;
170 	for (i=0; i<strlen(str); i++) {
171 		str[i] = toupper(str[i]);
172 	}
173 	return str;
174 }
175 GF_EXPORT
my_str_lwr(char * str)176 char * my_str_lwr(char *str)
177 {
178 	u32 i;
179 	for (i=0; i<strlen(str); i++) {
180 		str[i] = tolower(str[i]);
181 	}
182 	return str;
183 }
184 
185 /*enumerate directories*/
186 GF_EXPORT
gf_enum_directory(const char * dir,Bool enum_directory,gf_enum_dir_item enum_dir_fct,void * cbck,const char * filter)187 GF_Err gf_enum_directory(const char *dir, Bool enum_directory, gf_enum_dir_item enum_dir_fct, void *cbck, const char *filter)
188 {
189 	unsigned char item_path[GF_MAX_PATH];
190 	unsigned char path[GF_MAX_PATH], *file;
191 
192 	DIR *the_dir;
193 	struct dirent* the_file;
194 	struct stat st;
195 
196 	if (!dir || !enum_dir_fct) return GF_BAD_PARAM;
197 
198 	strcpy((char*)path, dir);
199 	if (path[strlen((const char*)path)-1] != '\\') strcat((char*)path, "\\");
200 
201 
202 	the_dir = opendir((char*)path);
203 	if (the_dir == NULL) return GF_IO_ERR;
204 
205 	the_file = readdir(the_dir);
206 	while (the_file) {
207 		if (!strcmp(the_file->d_name, "..")) goto next;
208 		if (the_file->d_name[0] == '.') goto next;
209 
210 		if (filter) {
211 			char ext[30];
212 			char *sep = strrchr(the_file->d_name, '.');
213 			if (!sep) goto next;
214 			strcpy(ext, sep+1);
215 			strlwr(ext);
216 			if (!strstr(filter, sep+1)) goto next;
217 		}
218 
219 		strcpy((char*)item_path, (const char*)path);
220 		strcat((char*)item_path, the_file->d_name);
221 		if (stat( (const char*)item_path, &st ) != 0) goto next;
222 		if (enum_directory && ( (st.st_mode & S_IFMT) != S_IFDIR)) goto next;
223 		if (!enum_directory && ((st.st_mode & S_IFMT) == S_IFDIR)) goto next;
224 		file = (unsigned char*)the_file->d_name;
225 
226 		if (enum_dir_fct(cbck, (char *)file, (char *)item_path)) {
227 			break;
228 		}
229 
230 next:
231 		the_file = readdir(the_dir);
232 	}
233 	return GF_OK;
234 }
235 
236 
237 GF_EXPORT
gf_ftell(FILE * fp)238 u64 gf_ftell(FILE *fp)
239 {
240 	return (u64) ftell(fp);
241 }
242 
243 GF_EXPORT
gf_fseek(FILE * fp,s64 offset,s32 whence)244 u64 gf_fseek(FILE *fp, s64 offset, s32 whence)
245 {
246 	return fseek(fp, (s32) offset, whence);
247 }
248 
249 GF_EXPORT
gf_fopen(const char * file_name,const char * mode)250 FILE *gf_fopen(const char *file_name, const char *mode)
251 {
252 	return fopen(file_name, mode);
253 }
254 
255 
256 /*symbian thread*/
257 typedef RThread* TH_HANDLE;
258 
259 /*********************************************************************
260 						OS-Specific Thread Object
261 **********************************************************************/
262 struct __tag_thread
263 {
264 
265 	u32 status;
266 	TH_HANDLE threadH;
267 	u32 stackSize;
268 	/* the thread procedure */
269 	u32 (*Run)(void *param);
270 	void *args;
271 #ifndef GPAC_DISABLE_LOG
272 	char *log_name;
273 #endif
274 	/* lock for signal */
275 	GF_Semaphore *_signal;
276 };
277 
278 GF_EXPORT
gf_th_new(const char * name)279 GF_Thread *gf_th_new(const char *name)
280 {
281 	GF_Thread *tmp = (GF_Thread *) gf_malloc(sizeof(GF_Thread));
282 	memset((void *)tmp, 0, sizeof(GF_Thread));
283 	tmp->status = GF_THREAD_STATUS_STOP;
284 #ifndef GPAC_DISABLE_LOG
285 	if (name) {
286 		tmp->log_name = gf_strdup(name);
287 	} else {
288 		char szN[20];
289 		sprintf(szN, "0x%08x", (u32) tmp);
290 		tmp->log_name = gf_strdup(szN);
291 	}
292 #endif
293 
294 	return tmp;
295 }
296 
RunThread(void * ptr)297 static void *RunThread(void *ptr)
298 {
299 	TInt err;
300 	u32 ret = 0;
301 	CTrapCleanup * cleanup = NULL;
302 	GF_Thread *t = (GF_Thread *)ptr;
303 
304 
305 	CActiveScheduler * scheduler = new CActiveScheduler();
306 	if (scheduler == NULL) {
307 		t->status = GF_THREAD_STATUS_DEAD;
308 		gf_sema_notify(t->_signal, 1);
309 		goto exit;
310 	}
311 #ifndef GPAC_DISABLE_LOG
312 	GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Thread %s] Installing ActiveScheduler\n", t->log_name));
313 #endif
314 	CActiveScheduler::Install(scheduler);
315 
316 #ifndef GPAC_DISABLE_LOG
317 	GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Thread %s] Creating cleanup trap\n", t->log_name));
318 #endif
319 	cleanup = CTrapCleanup::New();
320 	if( cleanup == NULL ) {
321 		t->status = GF_THREAD_STATUS_DEAD;
322 		gf_sema_notify(t->_signal, 1);
323 		delete CActiveScheduler::Current();
324 		goto exit;
325 	}
326 #if 0
327 	CActiveScheduler::Start();
328 #endif
329 	/* OK , signal the caller */
330 	t->status = GF_THREAD_STATUS_RUN;
331 	gf_sema_notify(t->_signal, 1);
332 	/* Run our thread */
333 #ifndef GPAC_DISABLE_LOG
334 	GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Thread %s] Entering thread proc\n", t->log_name));
335 #endif
336 	TRAP(err, ret=t->Run(t->args) );
337 	//ret = t->Run(t->args);
338 
339 	delete CActiveScheduler::Current();
340 	delete cleanup;
341 
342 exit:
343 #ifndef GPAC_DISABLE_LOG
344 	GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Thread %s] Exit\n", t->log_name ));
345 #endif
346 	t->status = GF_THREAD_STATUS_DEAD;
347 	t->Run = NULL;
348 	t->threadH->Close();
349 	t->threadH = NULL;
350 	return (void *)ret;
351 }
352 
353 GF_EXPORT
gf_th_run(GF_Thread * t,u32 (* Run)(void * param),void * param)354 GF_Err gf_th_run(GF_Thread *t, u32 (*Run)(void *param), void *param)
355 {
356 	TBuf<32>	threadName;
357 
358 	const TUint KThreadMinHeapSize = 0x1000;
359 	const TUint KThreadMaxHeapSize = 0x10000;
360 
361 	if (!t || t->Run || t->_signal) return GF_BAD_PARAM;
362 	t->Run = Run;
363 	t->args = param;
364 	t->_signal = gf_sema_new(1, 0);
365 	if (! t->_signal) {
366 		GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Unable to create thread start-up semaphore\n"));
367 		t->status = GF_THREAD_STATUS_DEAD;
368 		return GF_IO_ERR;
369 	}
370 
371 	threadName.Format(_L("GTH%d"), (u32) t);
372 	t->threadH = new RThread();
373 	if ( t->threadH->Create(threadName, (TThreadFunction)RunThread, KDefaultStackSize, KThreadMinHeapSize, KThreadMaxHeapSize, (void *)t, EOwnerProcess) != KErrNone) {
374 		GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Unable to create thread\n"));
375 		t->status = GF_THREAD_STATUS_DEAD;
376 		return GF_IO_ERR;
377 	}
378 	t->threadH->Resume();
379 
380 	/*wait for the child function to call us - do NOT return before, otherwise the thread status would
381 	be unknown*/
382 	//GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Core] Waiting for thread to start\n"));
383 	gf_sema_wait(t->_signal);
384 	gf_sema_del(t->_signal);
385 	t->_signal = NULL;
386 	return GF_OK;
387 }
388 
389 
390 /* Stops a thread. If Destroy is not 0, thread is destroyed DANGEROUS as no cleanup */
Thread_Stop(GF_Thread * t,Bool Destroy)391 static void Thread_Stop(GF_Thread *t, Bool Destroy)
392 {
393 	if (gf_th_status(t) == GF_THREAD_STATUS_RUN) {
394 		if (Destroy) {
395 			t->threadH->Terminate(0);
396 			t->threadH = NULL;
397 		}
398 		else {
399 			t->threadH->Suspend();
400 		}
401 	}
402 	t->status = GF_THREAD_STATUS_DEAD;
403 }
404 
405 GF_EXPORT
gf_th_stop(GF_Thread * t)406 void gf_th_stop(GF_Thread *t)
407 {
408 	Thread_Stop(t, 0);
409 }
410 
411 GF_EXPORT
gf_th_del(GF_Thread * t)412 void gf_th_del(GF_Thread *t)
413 {
414 	Thread_Stop(t, 0);
415 #ifndef GPAC_DISABLE_LOG
416 	gf_free(t->log_name);
417 #endif
418 	gf_free(t);
419 }
420 
421 
422 GF_EXPORT
gf_th_set_priority(GF_Thread * t,s32 priority)423 void gf_th_set_priority(GF_Thread *t, s32 priority)
424 {
425 	/*FIXEME: tune priorities on symbian*/
426 #if 0
427 	if (priority > 200)
428 		t->threadH->SetPriority(EPriorityRealTime);
429 	else
430 		t->threadH->SetPriority(EPriorityNormal);
431 #endif
432 }
433 
434 GF_EXPORT
gf_th_status(GF_Thread * t)435 u32 gf_th_status(GF_Thread *t)
436 {
437 	if (!t) return 0;
438 	return t->status;
439 }
440 
441 
442 GF_EXPORT
gf_th_id()443 u32 gf_th_id()
444 {
445 	return RThread().Id();
446 }
447 
448 
449 
450 /*********************************************************************
451 						OS-Specific Mutex Object
452 **********************************************************************/
453 struct __tag_mutex
454 {
455 	RMutex *hMutex;
456 	/* We filter recursive calls (1 thread calling Lock several times in a row only locks
457 	ONCE the mutex. Holder is the current ThreadID of the mutex holder*/
458 	u32 Holder, HolderCount;
459 #ifndef GPAC_DISABLE_LOG
460 	char *log_name;
461 #endif
462 };
463 
464 
465 GF_EXPORT
gf_mx_new(const char * name)466 GF_Mutex *gf_mx_new(const char *name)
467 {
468 	GF_Mutex *tmp = (GF_Mutex *)gf_malloc(sizeof(GF_Mutex));
469 	if (!tmp) return NULL;
470 	memset(tmp, 0, sizeof(GF_Mutex));
471 
472 	tmp->hMutex = new RMutex();
473 	if( tmp->hMutex->CreateLocal() != KErrNone) {
474 		gf_free(tmp);
475 		return NULL;
476 	}
477 #ifndef GPAC_DISABLE_LOG
478 	if (name) {
479 		tmp->log_name = gf_strdup(name);
480 	} else {
481 		char szN[20];
482 		sprintf(szN, "0x%08x", (u32) tmp);
483 		tmp->log_name = gf_strdup(szN);
484 	}
485 #endif
486 	return tmp;
487 }
488 
489 GF_EXPORT
gf_mx_del(GF_Mutex * mx)490 void gf_mx_del(GF_Mutex *mx)
491 {
492 	mx->hMutex->Close();
493 	gf_free(mx);
494 }
495 
496 GF_EXPORT
gf_mx_v(GF_Mutex * mx)497 void gf_mx_v(GF_Mutex *mx)
498 {
499 	u32 caller;
500 	if (!mx) return;
501 	caller = gf_th_id();
502 
503 	/*only if we own*/
504 	if (caller != mx->Holder) {
505 		GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Core] Invalid mutex release - owner PID %d - caller PID %d\n", mx->Holder, caller));
506 		return;
507 	}
508 	if (!mx->HolderCount) {
509 		GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Core] Invalid mutex release - mutex not locked\n"));
510 		return;
511 	}
512 	mx->HolderCount -= 1;
513 
514 	if (mx->HolderCount == 0) {
515 		mx->Holder = 0;
516 		mx->hMutex->Signal();
517 	}
518 }
519 
520 GF_EXPORT
gf_mx_p(GF_Mutex * mx)521 u32 gf_mx_p(GF_Mutex *mx)
522 {
523 	u32 caller;
524 	if (!mx) return 0;
525 	caller = gf_th_id();
526 	if (caller == mx->Holder) {
527 		mx->HolderCount += 1;
528 		return 1;
529 	}
530 	mx->hMutex->Wait();
531 	mx->Holder = caller;
532 	mx->HolderCount = 1;
533 	return 1;
534 }
535 
536 GF_EXPORT
gf_mx_try_lock(GF_Mutex * mx)537 Bool gf_mx_try_lock(GF_Mutex *mx)
538 {
539 	u32 caller;
540 	if (!mx) return 0;
541 	caller = gf_th_id();
542 	if (caller == mx->Holder) {
543 		mx->HolderCount += 1;
544 		return 1;
545 	}
546 	/*FIXME !! WE MUST HAVE tryLock*/
547 	gf_mx_p(mx);
548 	return 1;
549 }
550 
551 
552 
553 
554 /*********************************************************************
555 						OS-Specific Semaphore Object
556 **********************************************************************/
557 struct __tag_semaphore
558 {
559 	RSemaphore *hSemaphore;
560 };
561 
562 
563 GF_EXPORT
gf_sema_new(u32 MaxCount,u32 InitCount)564 GF_Semaphore *gf_sema_new(u32 MaxCount, u32 InitCount)
565 {
566 	GF_Semaphore *tmp = (GF_Semaphore *) gf_malloc(sizeof(GF_Semaphore));
567 
568 	if (!tmp) return NULL;
569 	tmp->hSemaphore = new RSemaphore();
570 	if (!tmp->hSemaphore) {
571 		gf_free(tmp);
572 		return NULL;
573 	}
574 	TBuf<32>	semaName;
575 	semaName.Format(_L("GPAC_SEM%d"), (u32) tmp);
576 	tmp->hSemaphore->CreateGlobal(semaName, InitCount);
577 
578 	return tmp;
579 }
580 
581 GF_EXPORT
gf_sema_del(GF_Semaphore * sm)582 void gf_sema_del(GF_Semaphore *sm)
583 {
584 	sm->hSemaphore->Close();
585 	gf_free(sm);
586 }
587 
588 GF_EXPORT
gf_sema_notify(GF_Semaphore * sm,u32 NbRelease)589 Bool gf_sema_notify(GF_Semaphore *sm, u32 NbRelease)
590 {
591     if (!sm) return GF_FALSE;
592 	sm->hSemaphore->Signal(NbRelease);
593 	return GF_TRUE;
594 }
595 
596 GF_EXPORT
gf_sema_wait(GF_Semaphore * sm)597 void gf_sema_wait(GF_Semaphore *sm)
598 {
599 	sm->hSemaphore->Wait();
600 }
601 
602 GF_EXPORT
gf_sema_wait_for(GF_Semaphore * sm,u32 TimeOut)603 Bool gf_sema_wait_for(GF_Semaphore *sm, u32 TimeOut)
604 {
605 	return 0;
606 }
607 
608 
609 
610 
611 
612 static u32 sys_init = 0;
613 GF_SystemRTInfo the_rti;
614 
615 GF_EXPORT
gf_sys_init()616 void gf_sys_init()
617 {
618 	if (!sys_init) {
619 		memset(&the_rti, 0, sizeof(GF_SystemRTInfo));
620 		the_rti.pid = getpid();
621 		sys_start_time = gf_sys_clock();
622 	}
623 	sys_init += 1;
624 }
625 
626 GF_EXPORT
gf_sys_close()627 void gf_sys_close()
628 {
629 	if (sys_init > 0) {
630 		sys_init --;
631 		if (sys_init) return;
632 	}
633 }
634 
635 #ifdef GPAC_MEMORY_TRACKING
636 extern size_t gpac_allocated_memory;
637 #endif
638 
639 /*CPU and Memory Usage*/
640 GF_EXPORT
gf_sys_get_rti(u32 refresh_time_ms,GF_SystemRTInfo * rti,u32 flags)641 Bool gf_sys_get_rti(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
642 {
643 	TInt ram, ram_free;
644 	u32 now, time;
645 #ifdef __SERIES60_3X__
646 	TModuleMemoryInfo mi;
647 #endif
648 	TTimeIntervalMicroSeconds tims;
649 	RProcess cur_process;
650 	RThread cur_th;
651 
652 	now = gf_sys_clock();
653 	if (!rti->sampling_instant) {
654 		rti->sampling_instant = now;
655 		if (cur_th.GetCpuTime(tims) != KErrNone) {
656 			return 0;
657 		}
658 #ifdef __SERIES60_3X__
659 		rti->process_cpu_time = (u32) (tims.Int64() / 1000);
660 #else
661 		rti->process_cpu_time = (u32) ( TInt64(tims.Int64() / 1000).GetTInt() );
662 #endif
663 		return 0;
664 	}
665 	if (rti->sampling_instant + refresh_time_ms > now) return 0;
666 	rti->sampling_period_duration = now - rti->sampling_instant;
667 	rti->sampling_instant = now;
668 
669 	if (cur_th.Process(cur_process) != KErrNone) {
670 		return 0;
671 	}
672 #ifdef __SERIES60_3X__
673 	if (cur_process.GetMemoryInfo(mi) != KErrNone) {
674 		return 0;
675 	}
676 	rti->process_memory = mi.iCodeSize + mi.iConstDataSize + mi.iInitialisedDataSize + mi.iUninitialisedDataSize;
677 #endif
678 	if (cur_th.GetCpuTime(tims) != KErrNone) {
679 		return 0;
680 	}
681 #ifdef __SERIES60_3X__
682 	time = (u32) (tims.Int64() / 1000);
683 #else
684 	time = (u32) ( TInt64(tims.Int64() / 1000).GetTInt() );
685 #endif
686 	rti->process_cpu_time_diff = time - rti->process_cpu_time;
687 	rti->process_cpu_time = time;
688 	rti->process_cpu_usage = 100*rti->process_cpu_time_diff / rti->sampling_period_duration;
689 	if (rti->process_cpu_usage > 100) rti->process_cpu_usage = 100;
690 
691 	HAL::Get(HALData::EMemoryRAM, ram);
692 	HAL::Get(HALData::EMemoryRAMFree, ram_free);
693 	rti->physical_memory = ram;
694 	rti->physical_memory_avail = ram_free;
695 #ifdef GPAC_MEMORY_TRACKING
696 	rti->gpac_memory = gpac_allocated_memory;
697 #endif
698 	return 1;
699 }
700 
701 GF_EXPORT
gf_sys_get_battery_state(Bool * onBattery,u32 * state,u32 * level)702 Bool gf_sys_get_battery_state(Bool *onBattery, u32 *state, u32*level)
703 {
704 	return 1;
705 }
706 
707 
708 /*delete all interfaces loaded on object*/
gf_modules_free_module(ModuleInstance * inst)709 void gf_modules_free_module(ModuleInstance *inst)
710 {
711 	while (gf_list_count(inst->interfaces)) {
712 		void *objinterface = gf_list_get(inst->interfaces, 0);
713 		gf_list_rem(inst->interfaces, 0);
714 		inst->destroy_func(objinterface);
715 	}
716 	if (inst->lib_handle) {
717 		RLibrary* pLibrary = (RLibrary *) inst->lib_handle;
718 		pLibrary->Close();
719 	}
720 	gf_list_del(inst->interfaces);
721 	gf_free(inst);
722 }
723 
gf_modules_load_library(ModuleInstance * inst)724 Bool gf_modules_load_library(ModuleInstance *inst)
725 {
726 	const TUid KGPACModuleUid= {0x10000080};
727 	char s_path[GF_MAX_PATH];
728 	HBufC *path;
729 	TInt e;
730 
731 	if (inst->lib_handle) return 1;
732 
733 	sprintf(s_path, "%s%c%s", inst->plugman->dir, GF_PATH_SEPARATOR, inst->szName);
734 
735 	path = HBufC::NewL( User::StringLength( ( TUint8* ) s_path) + 1 );
736 	path->Des().Copy( TPtrC8(( TText8* ) s_path) );
737 
738 	RLibrary* pLibrary = new RLibrary();
739 	e = pLibrary->Load(*path);
740 	delete path;
741 
742 	if (e != KErrNone) {
743 		GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[core] Cannot load library %s: %d", s_path, e));
744 		delete pLibrary;
745 		goto err_exit;
746 	}
747 	/*check UID 2 is GPAC's identifier*/
748 	if (pLibrary->Type()[1] != KGPACModuleUid) {
749 		GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[core] Invalid library UID %x", (u32) pLibrary->Type()[1].iUid));
750 		pLibrary->Close();
751 		delete pLibrary;
752 		goto err_exit;
753 	}
754 	inst->query_func = (QueryInterfaces) pLibrary->Lookup(1);
755 	inst->load_func = (LoadInterface) pLibrary->Lookup(2);
756 	inst->destroy_func = (ShutdownInterface) pLibrary->Lookup(3);
757 
758 	if ((inst->query_func==NULL) || (inst->load_func==NULL) || (inst->destroy_func==NULL) ) {
759 		GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[core] Library %s has invalid interfaces", inst->szName));
760 		pLibrary->Close();
761 		delete pLibrary;
762 		goto err_exit;
763 	}
764 
765 	//store library handle
766 	inst->lib_handle = (void*) pLibrary;
767 	//GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Core] Module %s loaded\n", inst->szName));
768 	return 1;
769 
770 err_exit:
771 	gf_cfg_set_key(inst->plugman->cfg, "SymbianDLLs", inst->szName, "no");
772 	return 0;
773 }
774 
gf_modules_unload_library(ModuleInstance * inst)775 void gf_modules_unload_library(ModuleInstance *inst)
776 {
777 	if (!inst->lib_handle || gf_list_count(inst->interfaces)) return;
778 
779 	RLibrary* pLibrary = (RLibrary *) inst->lib_handle;
780 	pLibrary->Close();
781 	delete pLibrary;
782 
783 	inst->lib_handle = NULL;
784 	inst->load_func = NULL;
785 	inst->destroy_func = NULL;
786 	inst->query_func = NULL;
787 	//GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Core] Module %s unloaded\n", inst->szName));
788 }
789 
790 
enum_modules(void * cbck,char * item_name,char * item_path,GF_FileEnumInfo * file_info)791 static Bool enum_modules(void *cbck, char *item_name, char *item_path, GF_FileEnumInfo *file_info)
792 {
793 	ModuleInstance *inst;
794 
795 	GF_ModuleManager *pm = (GF_ModuleManager *) cbck;
796 
797 	if (strstr(item_name, "nposmozilla")) return 0;
798 	if (strncmp(item_name, "gm_", 3)) return 0;
799 	if (gf_module_is_loaded(pm, item_name) ) return 0;
800 
801 	/*TODO FIXME: add module check for symbian */
802 
803 	GF_SAFEALLOC(inst, ModuleInstance);
804 	inst->interfaces = gf_list_new();
805 	inst->plugman = pm;
806 	strcpy((char*)inst->szName, item_name);
807 	gf_list_add(pm->plug_list, inst);
808 	return 0;
809 }
810 
811 /*refresh modules - note we don't check for deleted modules but since we've open them the OS should forbid delete*/
812 GF_EXPORT
gf_modules_refresh(GF_ModuleManager * pm)813 u32 gf_modules_refresh(GF_ModuleManager *pm)
814 {
815 	if (!pm) return 0;
816 	//!! symbian 9.1 doesn't allow for DLL browsing in /sys/bin, and can only load DLLs in /sys/bin !!
817 #if 0
818 	gf_enum_directory((char*)pm->dir, 0, enum_modules, pm, ".dll");
819 #else
820 	u32 i, mod_count;
821 
822 	mod_count = gf_cfg_get_key_count(pm->cfg, "SymbianDLLs");
823 	for (i=0; i<mod_count; i++) {
824 		const char *mod = gf_cfg_get_key_name(pm->cfg, "SymbianDLLs", i);
825 		if (stricmp(gf_cfg_get_key(pm->cfg, "SymbianDLLs", mod), "yes")) continue;
826 		enum_modules(pm, (char*)mod, NULL);
827 	}
828 #endif
829 	return gf_list_count(pm->plug_list);
830 }
831 
832 #endif
833 
834