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