node_palmos.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:14k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*****************************************************************************
  2.  *
  3.  * This program is free software ; you can redistribute it and/or modify
  4.  * it under the terms of the GNU General Public License as published by
  5.  * the Free Software Foundation; either version 2 of the License, or
  6.  * (at your option) any later version.
  7.  *
  8.  * This program is distributed in the hope that it will be useful,
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11.  * GNU General Public License for more details.
  12.  *
  13.  * You should have received a copy of the GNU General Public License
  14.  * along with this program; if not, write to the Free Software
  15.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  16.  *
  17.  * $Id: node_palmos.c 345 2005-11-19 15:57:54Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "../common.h"
  24. #if defined(TARGET_PALMOS)
  25. #define PREFID_NODE 2
  26. #define PREFID_PLUGINS 100
  27. #define FTRID_START 64
  28. #define FTRID_STEP 64
  29. #define FTRID_COUNT 60
  30. #include "pace.h"
  31. #ifdef HAVE_PALMONE_SDK
  32. #include <68K/System/PmPalmOSNVFS.h>
  33. #endif
  34. void NodeRegSaveGlobal()
  35. {
  36. uint8_t Data[MAXDATA];
  37. array Buffer = {NULL};
  38. array List;
  39. node **i;
  40. UInt16 PrefId=PREFID_NODE;
  41. uint32_t ProgramId = Context()->ProgramId;
  42. NodeEnumObject(&List,NODE_CLASS);
  43. for (i=ARRAYBEGIN(List,node*);i!=ARRAYEND(List,node*);++i)
  44. {
  45. int No,Total;
  46. datadef Type;
  47. for (No=0;NodeEnum(*i,No,&Type)==ERR_NONE;++No)
  48. {
  49. node* Node = *i;
  50. if ((Type.Flags & DF_SETUP) && !(Type.Flags & (DF_NOSAVE|DF_RDONLY)))
  51. {
  52. int Result = Node->Get(Node,Type.No,Data,Type.Size);
  53. if (Result == ERR_NONE || Result == ERR_NOT_SUPPORTED) // not supported settings should be still saved
  54. {
  55. if (Type.Type == TYPE_STRING)
  56. Type.Size = (tcslen((tchar_t*)Data)+1)*sizeof(tchar_t);
  57. Total = sizeof(int32_t)*3+ALIGN4(Type.Size);
  58. if (ARRAYCOUNT(Buffer,uint8_t)+Total > 0xF000)
  59. {
  60. PrefSetAppPreferences(ProgramId,PrefId++,CONTEXT_VERSION,ARRAYBEGIN(Buffer,uint8_t),(UInt16)ARRAYCOUNT(Buffer,uint8_t),0);
  61. ArrayDrop(&Buffer);
  62. }
  63. if (ArrayAppend(&Buffer,NULL,Total,4096))
  64. {
  65. int32_t* p = (int32_t*)(ARRAYEND(Buffer,uint8_t) - Total);
  66. memset(p,0,Total);
  67. p[0] = Node->Class;
  68. p[1] = Type.No;
  69. p[2] = Type.Size;
  70. memcpy(p+3,Data,Type.Size);
  71. }
  72. }
  73. }
  74. }
  75. }
  76. if (!ARRAYEMPTY(Buffer))
  77. PrefSetAppPreferences(ProgramId,PrefId++,CONTEXT_VERSION,ARRAYBEGIN(Buffer,uint8_t),(UInt16)ARRAYCOUNT(Buffer,uint8_t),0);
  78. ArrayClear(&List);
  79. ArrayClear(&Buffer);
  80. for (;;)
  81. {
  82. UInt16 PrefSize = 0;
  83. if (PrefGetAppPreferences(ProgramId, PrefId, NULL, &PrefSize, 0) == noPreferenceFound)
  84. break;
  85. PrefSetAppPreferences(ProgramId,PrefId++,CONTEXT_VERSION,NULL,0,0);
  86. }
  87. }
  88. void NodeRegLoadGlobal()
  89. {
  90. array Buffer = {NULL};
  91. array List;
  92. node **i;
  93. int32_t* p;
  94. UInt16 PrefId;
  95. UInt16 PrefSize;
  96. uint32_t ProgramId = Context()->ProgramId;
  97. NodeEnumObject(&List,NODE_CLASS);
  98. for (PrefId=PREFID_NODE;;++PrefId)
  99. {
  100. PrefSize = 0;
  101. if (PrefGetAppPreferences(ProgramId, PrefId, NULL, &PrefSize, 0) == noPreferenceFound)
  102. break;
  103. ArrayDrop(&Buffer);
  104. if (ArrayAppend(&Buffer,NULL,PrefSize,16) && 
  105. PrefGetAppPreferences(ProgramId, PrefId, ARRAYBEGIN(Buffer,int32_t), &PrefSize, 0) != noPreferenceFound)
  106. {
  107. for (p=ARRAYBEGIN(Buffer,int32_t);p<ARRAYEND(Buffer,int32_t);p+=3+(p[2]+3)/4)
  108. for (i=ARRAYBEGIN(List,node*);i!=ARRAYEND(List,node*);++i)
  109. if ((*i)->Class == p[0])
  110. {
  111. (*i)->Set(*i,p[1],p+3,p[2]);
  112. break;
  113. }
  114. }
  115. }
  116. ArrayClear(&List);
  117. ArrayClear(&Buffer);
  118. }
  119. static NOINLINE void AddModule(const tchar_t* Path,int Type,int Date,int32_t* Modules)
  120. {
  121. int No=0;
  122. int Count=0;
  123. if (Modules)
  124. {
  125. //don't load if already registered with same date
  126. Count = Modules[-1];
  127. for (No=0;No<Count;++No)
  128. {
  129. if ((!Type || Modules[0] == Type) &&
  130. tcscmp((const tchar_t*)(Modules+3),Path)==0)
  131. {
  132. Type = Modules[0];
  133. if (Modules[1] == Date)
  134. {
  135. Modules[1] = -1;
  136. break;
  137. }
  138. Modules[1] = -2;
  139. }
  140. Modules += 1+1+1+Modules[2]/4;
  141. }
  142. }
  143. NodeAddModule(Path,Type,Date,No>=Count,0);
  144. }
  145. static void VFSFindPlugins(uint16_t Ref,tchar_t* Path,int PathLen,int32_t* Modules,const tchar_t* Skip)
  146. {
  147. FileRef File;
  148. int PathPos = tcslen(Path);
  149. if (PathPos>0 && Path[PathPos-1]=='/')
  150. Path[PathPos-1] = 0;
  151. if (Skip && tcscmp(Path,Skip)==0)
  152. return;
  153. if (VFSFileOpen(Ref,Path,vfsModeRead,&File)==errNone)
  154. {
  155. FileInfoType Info;
  156. UInt32 Iter = vfsIteratorStart;
  157. tcscat_s(Path,PathLen,"/");
  158. PathPos = tcslen(Path);
  159. Info.nameP = Path + PathPos;
  160. Info.nameBufLen = (UInt16)((PathLen-PathPos)*sizeof(tchar_t));
  161. while (Iter != vfsIteratorStop && VFSDirEntryEnumerate(File,&Iter,&Info)==errNone)
  162. {
  163. if (tcsnicmp(Path+PathPos,T("tcpmp"),5)==0 &&
  164. (Path[PathPos+5]=='_' || Path[PathPos+5]==' '))
  165. {
  166. FileRef File = 0;
  167. VFSFileOpen(Ref,Path,vfsModeRead,&File);
  168. if (File)
  169. {
  170. UInt32 Date;
  171. if (VFSFileGetDate(File,vfsFileDateModified,&Date)==errNone)
  172. {
  173. tchar_t URL[MAXPATH]; 
  174. if (VFSFromVol(Ref,Path,URL,TSIZEOF(URL)))
  175. AddModule(URL,0,Date,Modules);
  176. }
  177. VFSFileClose(File);
  178. }
  179. }
  180. }
  181. VFSFileClose(File);
  182. }
  183. }
  184. static void FindPlugins(int32_t* Modules)
  185. {
  186. bool_t CheckVFS = 1;
  187. Boolean New = 1;
  188. LocalID CurrentDB; 
  189. UInt16 Card; 
  190. DmSearchStateType SearchState;
  191. tchar_t Name[48];
  192. tchar_t URL[MAXPATH]; 
  193. UInt32 Type;
  194. UInt32 Date;
  195. CurrentDB = 0;
  196. while (DmGetNextDatabaseByTypeCreator(New, &SearchState, 0, Context()->ProgramId, 1, &Card, &CurrentDB)==errNone)
  197. {
  198. DmDatabaseInfo(Card,CurrentDB,Name,NULL,NULL,NULL,&Date,NULL,NULL,NULL,NULL,&Type,NULL);
  199. if ((Type >> 24) == 'X')
  200. {
  201. stprintf_s(URL,TSIZEOF(URL),T("mem://%s.prc"),Name);
  202. AddModule(URL,Type,Date,Modules);
  203. CheckVFS = 0;
  204. }
  205. New = 0;
  206. }
  207. if (NodeEnumClass(NULL,VFS_ID))
  208. {
  209. UInt16 Ref;
  210. uint32_t LaunchPath = 0;
  211. URL[0] = 0;
  212. if (FtrGet(Context()->ProgramId,20,&LaunchPath)==errNone)
  213. {
  214. Ref = ((vfspath*)LaunchPath)->volRefNum;
  215. SplitURL(((vfspath*)LaunchPath)->path,URL,TSIZEOF(URL),URL,TSIZEOF(URL),NULL,0,NULL,0);
  216. VFSFindPlugins(Ref,URL,TSIZEOF(URL),Modules,NULL);
  217. }
  218. if (CheckVFS || QueryAdvanced(ADVANCED_CARDPLUGINS))
  219. {
  220. UInt32 Iter = vfsIteratorStart;
  221. while (Iter != vfsIteratorStop && VFSVolumeEnumerate(&Ref,&Iter)==errNone)
  222. {
  223. tchar_t Path[MAXPATH];
  224. UInt16 Size = sizeof(Path);
  225. if (VFSGetDefaultDirectory(Ref,T(".prc"),Path,&Size)==errNone)
  226. VFSFindPlugins(Ref,Path,TSIZEOF(Path),Modules,URL);
  227. }
  228. }
  229. }
  230. }
  231. static NOINLINE int32_t* GetString(int32_t* p,const tchar_t** s)
  232. {
  233. if (p[0])
  234. {
  235. *s = (const tchar_t*)(p+1); 
  236. p+=1+p[0]/4;
  237. }
  238. else
  239. {
  240. *s = NULL;
  241. ++p;
  242. }
  243. return p;
  244. }
  245. void Plugins_Init()
  246. {
  247. array Buffer = {NULL};
  248. int32_t* p;
  249. int32_t* Modules;
  250. int i,No,Count;
  251. bool_t b;
  252. UInt16 PrefSize;
  253. uint32_t ProgramId = Context()->ProgramId;
  254. node* Advanced = Context()->Advanced;
  255. PrefSize = 0;
  256. if (PrefGetAppPreferences(ProgramId, PREFID_PLUGINS, NULL, &PrefSize, 0) != noPreferenceFound &&
  257. ArrayAppend(&Buffer,NULL,PrefSize,16) &&
  258. PrefGetAppPreferences(ProgramId, PREFID_PLUGINS, ARRAYBEGIN(Buffer,int32_t), &PrefSize, 0) != noPreferenceFound)
  259. {
  260. // add all plugins and load changed/new ones
  261. p = ARRAYBEGIN(Buffer,int32_t);
  262. if (*p<0)
  263. {
  264. // params
  265. if (Advanced)
  266. {
  267. b = p[1] != 0;
  268. Advanced->Set(Advanced,ADVANCED_CARDPLUGINS,&b,sizeof(b));
  269. }
  270. p += 1-*p;
  271. }
  272. Count = *(p++);
  273. Modules = p;
  274. FindPlugins(Modules);
  275. // also add non existing modules (maybe SD card removed temporarily)
  276. for (No=0;No<Count;++No)
  277. {
  278. if (p[1] != -1 && p[1] != -2)
  279. NodeAddModule((const tchar_t*)(p+3),p[0],p[1],0,1);
  280. p += 1+1+1+p[2]/4;
  281. }
  282. // load classes (only if not exists already. don't want to override changed loaded plugins)
  283. while (*p)
  284. {
  285. nodedef Def;
  286. int Module;
  287. const tchar_t* Name;
  288. const tchar_t* ContentType;
  289. const tchar_t* Exts;
  290. const tchar_t* Probe;
  291. memset(&Def,0,sizeof(Def));
  292. Module = *p-1; ++p;
  293. Def.Class = *p; ++p;
  294. Def.ParentClass = *p; ++p;
  295. Def.Flags = *p; ++p;
  296. Def.Priority = *p; ++p;
  297. p = GetString(p,&Name);
  298. p = GetString(p,&ContentType);
  299. p = GetString(p,&Exts);
  300. p = GetString(p,&Probe);
  301. if (Module<Modules[-1] && !NodeEnumClass(NULL,Def.Class))
  302. {
  303. int32_t* p = Modules;
  304. for (i=0;i<Module;++i)
  305. p += 1+1+1+p[2]/4;
  306. if (Name) StringAdd(1,Def.Class,NODE_NAME,Name);
  307. if (ContentType) StringAdd(1,Def.Class,NODE_CONTENTTYPE,ContentType);
  308. if (Exts) StringAdd(1,Def.Class,NODE_EXTS,Exts);
  309. if (Probe) StringAdd(1,Def.Class,NODE_PROBE,Probe);
  310. NodeLoadClass(&Def,(const tchar_t*)(p+3),p[0]);
  311. }
  312. }
  313. }
  314. else
  315. FindPlugins(NULL);
  316. ArrayClear(&Buffer);
  317. }
  318. bool_t NOINLINE AppendInt(array* Buffer,int Data)
  319. {
  320. return ArrayAppend(Buffer,&Data,sizeof(Data),4096);
  321. }
  322. bool_t NOINLINE AppendStr(array* Buffer,const tchar_t* Data)
  323. {
  324. int Len = (tcslen((tchar_t*)Data)+1)*sizeof(tchar_t);
  325. int Total = ALIGN4(Len);
  326. if (!AppendInt(Buffer,Total) || !ArrayAppend(Buffer,NULL,Total,4096))
  327. return 0;
  328. memcpy(ARRAYEND(*Buffer,uint8_t)-Total,Data,Len);
  329. memset(ARRAYEND(*Buffer,uint8_t)-Total+Len,0,Total-Len);
  330. return 1;
  331. }
  332. bool_t NOINLINE AppendString(array* Buffer,int Class,int Id)
  333. {
  334. if (StringIsBinary(Class,Id))
  335. return AppendInt(Buffer,0);
  336. return AppendStr(Buffer,LangStrDef(Class,Id));
  337. }
  338. void Plugins_Done()
  339. {
  340. array Buffer = {NULL};
  341. uint32_t ProgramId = Context()->ProgramId;
  342. int64_t Date;
  343. int No,Count;
  344. int Id;
  345. AppendInt(&Buffer,-1);
  346. AppendInt(&Buffer,QueryAdvanced(ADVANCED_CARDPLUGINS));
  347. Count = NodeGetModuleCount();
  348. AppendInt(&Buffer,Count-1);
  349. for (No=1;No<Count;++No)
  350. {
  351. const tchar_t* Path = NodeGetModule(No,&Id,&Date);
  352. AppendInt(&Buffer,Id);
  353. AppendInt(&Buffer,(int)Date);
  354. AppendStr(&Buffer,Path);
  355. }
  356. Count = NodeGetClassCount();
  357. for (No=0;No<Count;++No)
  358. {
  359. const nodedef* Def = NodeGetClass(No,&Id);
  360. if (Id)
  361. {
  362. AppendInt(&Buffer,Id);
  363. AppendInt(&Buffer,Def->Class);
  364. AppendInt(&Buffer,Def->ParentClass);
  365. AppendInt(&Buffer,Def->Flags);
  366. AppendInt(&Buffer,Def->Priority);
  367. AppendString(&Buffer,Def->Class,NODE_NAME);
  368. AppendString(&Buffer,Def->Class,NODE_CONTENTTYPE);
  369. AppendString(&Buffer,Def->Class,NODE_EXTS);
  370. AppendString(&Buffer,Def->Class,NODE_PROBE);
  371. }
  372. }
  373. AppendInt(&Buffer,0);
  374. if (ARRAYCOUNT(Buffer,uint8_t)<0x8000)
  375. PrefSetAppPreferences(ProgramId,PREFID_PLUGINS,CONTEXT_VERSION,ARRAYBEGIN(Buffer,uint8_t),(UInt16)ARRAYCOUNT(Buffer,uint8_t),0);
  376. ArrayClear(&Buffer);
  377. }
  378. static void* Modules[FTRID_COUNT] = {NULL};
  379. void NodeFreeModule(void* Module,void* Db)
  380. {
  381. if (Module)
  382. {
  383. int i;
  384. void* UnRegister = PealGetSymbol(Module,T("DLLUnRegister"));
  385. if (UnRegister)
  386. ((void(*)())UnRegister)();
  387. for (i=0;i<FTRID_COUNT;++i)
  388. if (Modules[i] == Module)
  389. {
  390. Modules[i] = NULL;
  391. break;
  392. }
  393. PealFreeModule(Module);
  394. if (Db)
  395. DmCloseDatabase(Db);
  396. }
  397. }
  398. static void* LoadPlugin(UInt16 Card,LocalID CurrentDB,bool_t TmpDb,void** Db,int* Id)
  399. {
  400. void* Module = NULL;
  401. char Name[48];
  402. UInt32 Type;
  403. UInt16 Attr;
  404. Boolean MemDup = 0;
  405. Boolean MemSema = 0;
  406. int No;
  407. DmDatabaseInfo(Card,CurrentDB,Name,&Attr,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&Type,NULL);
  408. if ((Type >> 24) != 'X')
  409. {
  410. if (TmpDb)
  411. DmDeleteDatabase(Card,CurrentDB);
  412. return NULL;
  413. }
  414. *Id = Type;
  415. #ifdef ARM
  416. {
  417. UInt32 Version;
  418. FtrGet(sysFtrCreator, sysFtrNumROMVersion, &Version);
  419. MemSema = (Boolean)(Version < sysMakeROMVersion(6,0,0,sysROMStageDevelopment,0));
  420. }
  421. #endif
  422. #ifdef HAVE_PALMONE_SDK
  423. // duplicate plugins to memory with NVFS, because writing back reallocation 
  424. // causes the plugins to disappear sometimes from storage flash memory.
  425. if (!MemSema) // but don't care if can use memory semaphore
  426. {
  427. UInt32 Version;
  428. if (FtrGet(sysFtrCreator,sysFtrNumDmAutoBackup,&Version)==errNone && Version==1)
  429. MemDup = 1;
  430. }
  431. #endif
  432. if (TmpDb)
  433. {
  434. Attr |= dmHdrAttrRecyclable;
  435. DmSetDatabaseInfo(Card,CurrentDB,NULL,&Attr,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  436. }
  437. *Db = DmOpenDatabaseByTypeCreator(Type,Context()->ProgramId,dmModeReadOnly);
  438. if (*Db)
  439. {
  440. for (No=0;No<FTRID_COUNT;++No)
  441. if (!Modules[No])
  442. break;
  443. if (No<FTRID_COUNT)
  444. {
  445. Module = PealLoadModule((UInt16)(FTRID_START+No*FTRID_STEP),
  446.                         MemDup,(Boolean)Context()->LowMemory,MemSema);
  447. if (Module)
  448. {
  449. void* Register = PealGetSymbol(Module,T("DLLRegister"));
  450. if (Register)
  451. {
  452. int Result = ((int(*)(int))Register)(CONTEXT_VERSION);
  453. if (Result != ERR_NONE)
  454. {
  455. Register = NULL;
  456. if (Result == ERR_NOT_COMPATIBLE)
  457. {
  458. int n = tcslen(Name);
  459. if (n>7 && tcsnicmp(Name+n-7,T(" plugin"),7)==0)
  460. Name[n-7] = 0;
  461. ShowError(0,ERR_ID,ERR_NOT_COMPATIBLE,Name);
  462. }
  463. }
  464. }
  465. if (!Register)
  466. {
  467. PealFreeModule(Module);
  468. Module = NULL;
  469. }
  470. else
  471. Modules[No] = Module;
  472. }
  473. }
  474. if (!Module || MemDup)
  475. {
  476. DmCloseDatabase(*Db);
  477. *Db = NULL;
  478. }
  479. }
  480. return Module;
  481. }
  482. void* NodeLoadModule(const tchar_t* URL,int* Id,void** AnyFunc,void** Db)
  483. {
  484. void* Module = NULL;
  485. UInt16 Card;
  486. LocalID CurrentDB;
  487. if (tcsncmp(URL,"mem",3)!=0)
  488. {
  489. uint16_t Vol;
  490. const tchar_t* Path = VFSToVol(URL,&Vol);
  491. if (Path && VFSImportDatabaseFromFile(Vol,Path,&Card,&CurrentDB)==errNone)
  492. Module = LoadPlugin(Card,CurrentDB,1,Db,Id);
  493. }
  494. else
  495. {
  496. DmSearchStateType SearchState;
  497. CurrentDB = 0;
  498. if (DmGetNextDatabaseByTypeCreator(1, &SearchState, *Id, Context()->ProgramId, 1, &Card, &CurrentDB)==errNone)
  499. Module = LoadPlugin(Card,CurrentDB,0,Db,Id);
  500. }
  501. return Module;
  502. }
  503. #endif