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

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.c 585 2006-01-16 09:48:55Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "common.h"
  24. #define MODULE_PATH FOURCC('M','P','A','T')
  25. #define PLUGIN_KEEPALIVE 3*60
  26. typedef struct nodeclass
  27. {
  28. nodedef Def;
  29. bool_t Registered;
  30. int ModuleNo;
  31. struct nodeclass* Parent;
  32. } nodeclass;
  33. typedef struct nodemodule
  34. {
  35. int Id;
  36. int ObjectCount;
  37. bool_t Tmp;
  38. int64_t Date;
  39. int KeepAlive;
  40. void* Module;
  41. void* Db;
  42. void* Func;
  43. uint8_t* Min;
  44. uint8_t* Max;
  45. } nodemodule;
  46. static NOINLINE void FreeModule(nodemodule* p)
  47. {
  48. NodeFreeModule(p->Module,p->Db);
  49. p->Module = NULL;
  50. p->Db = NULL;
  51. p->Func = NULL;
  52. p->Min = NULL;
  53. }
  54. void NodeAddModule(const tchar_t* Path,int Id,int64_t Date,bool_t Load,bool_t Tmp)
  55. {
  56. context* p = Context();
  57. LockEnter(p->NodeLock);
  58. if (ArrayAppend(&p->NodeModule,NULL,sizeof(nodemodule),256))
  59. {
  60. int No = ARRAYCOUNT(p->NodeModule,nodemodule)-1;
  61. nodemodule* Module = ARRAYBEGIN(p->NodeModule,nodemodule)+No;
  62. memset(Module,0,sizeof(nodemodule));
  63. Module->Id = Id;
  64. Module->Date = Date;
  65. Module->Tmp = Tmp;
  66. StringAdd(1,MODULE_PATH,No,Path);
  67. if (Load)
  68. {
  69. p->LoadModuleNo = No;
  70. Module->Module = NodeLoadModule(Path,&Module->Id,&Module->Func,&Module->Db);
  71. p->LoadModuleNo = 0;
  72. #ifdef PLUGINCLEANUP
  73. FreeModule(Module);
  74. #endif
  75. }
  76. }
  77. LockLeave(p->NodeLock);
  78. }
  79. static NOINLINE bool_t TmpModule(context* p,int No)
  80. {
  81. return ARRAYBEGIN(p->NodeModule,nodemodule)[No].Tmp;
  82. }
  83. static NOINLINE int FindModule(context* p,const tchar_t* Path,int Id)
  84. {
  85. // important to find from the begining for Palm OS 
  86. // so the exising plugins are found first
  87. int No,Count;
  88. int Result = -1;
  89. LockEnter(p->NodeLock);
  90. Count = ARRAYCOUNT(p->NodeModule,nodemodule);
  91. if (!Path) Path = T("");
  92. for (No=0;No<Count;++No)
  93. {
  94. bool_t SameId = ARRAYBEGIN(p->NodeModule,nodemodule)[No].Id == Id;
  95. bool_t SameName = tcsicmp(Path,LangStrDef(MODULE_PATH,No))==0;
  96. if (SameId && Id!=0) // same Id means same module
  97. SameName = 1;
  98. if (SameName && !Id)
  99. SameId = 1;
  100. if (SameId && SameName)
  101. {
  102. Result = No;
  103. break;
  104. }
  105. }
  106. LockLeave(p->NodeLock);
  107. return Result;
  108. }
  109. int NodeGetClassCount()
  110. {
  111. return ARRAYCOUNT(Context()->NodeClass,nodeclass*);
  112. }
  113. const nodedef* NodeGetClass(int No,int* Module)
  114. {
  115. nodeclass* i = ARRAYBEGIN(Context()->NodeClass,nodeclass*)[No];
  116. if (Module)
  117. *Module = i->ModuleNo;
  118. return &i->Def;
  119. }
  120. int NodeGetModuleCount()
  121. {
  122. return ARRAYCOUNT(Context()->NodeModule,nodemodule);
  123. }
  124. const tchar_t* NodeGetModule(int No,int* Id,int64_t* Date)
  125. {
  126. *Id = ARRAYBEGIN(Context()->NodeModule,nodemodule)[No].Id;
  127. *Date = ARRAYBEGIN(Context()->NodeModule,nodemodule)[No].Date;
  128. return LangStrDef(MODULE_PATH,No);
  129. }
  130. bool_t NodeFindModule(const tchar_t* Path,int Id)
  131. {
  132. return FindModule(Context(),Path,Id)>0;
  133. }
  134. static int CmpClass(const nodeclass* const* a, const nodeclass* const* b)
  135. {
  136. int AClass = (*a)->Def.Class;
  137. int BClass = (*b)->Def.Class;
  138. if (AClass > BClass) return 1;
  139. if (AClass < BClass) return -1;
  140. return 0;
  141. }
  142. static int CmpClassPri(const nodeclass* const* a, const nodeclass* const* b)
  143. {
  144. int APriority = (*a)->Def.Priority;
  145. int BPriority = (*b)->Def.Priority;
  146. if (APriority > BPriority) return -1;
  147. if (APriority < BPriority) return 1;
  148. return CmpClass(a,b);
  149. }
  150. static NOINLINE nodeclass* FindClass(context* p,int Class)
  151. {
  152. int Pos;
  153. bool_t Found;
  154. nodeclass Item;
  155. nodeclass* Ptr = &Item;
  156. LockEnter(p->NodeLock);
  157. Item.Def.Class = Class;
  158. Pos = ArrayFind(&p->NodeClass,ARRAYCOUNT(p->NodeClass,nodeclass*),
  159.                 sizeof(nodeclass*),&Ptr,(arraycmp)CmpClass,&Found);
  160. if (Found)
  161. Ptr = ARRAYBEGIN(p->NodeClass,nodeclass*)[Pos];
  162. else
  163. Ptr = NULL;
  164. LockLeave(p->NodeLock);
  165. return Ptr;
  166. }
  167. static int CmpNodePri(const node* const* a,const node* const* b)
  168. {
  169. context* p = Context();
  170. const nodeclass* ca = FindClass(p,(*a)->Class);
  171. const nodeclass* cb = FindClass(p,(*b)->Class);
  172. return CmpClassPri(&ca,&cb);
  173. }
  174. static NOINLINE int ReleaseModules(context* p,bool_t Force)
  175. {
  176. int n=0;
  177. int Time = Force ? MAX_INT:GetTimeTick();
  178. nodemodule* j;
  179. LockEnter(p->NodeLock);
  180. for (j=ARRAYBEGIN(p->NodeModule,nodemodule);j!=ARRAYEND(p->NodeModule,nodemodule);++j)
  181. if (j->ObjectCount==0 && j->Module && j->KeepAlive < Time)
  182. {
  183. //DEBUG_MSG1(-1,T("FreeModule %s"),LangStrDef(MODULE_PATH,j-ARRAYBEGIN(p->NodeModule,nodemodule)));
  184. FreeModule(j);
  185. ++n;
  186. }
  187. LockLeave(p->NodeLock);
  188. return n;
  189. }
  190. static NOINLINE void UnlockModule(context* p,int No)
  191. {
  192. nodemodule* Module = ARRAYBEGIN(p->NodeModule,nodemodule)+No;
  193. if (--Module->ObjectCount==0 && Module->Module)
  194. {
  195. #ifdef PLUGINCLEANUP
  196. Module->KeepAlive = GetTimeTick() + GetTimeFreq()*PLUGIN_KEEPALIVE;
  197. ReleaseModules(p,0);
  198. #endif
  199. }
  200. }
  201. static NOINLINE void CallDelete(context* p,node* Node,nodeclass* Class0,bool_t Global)
  202. {
  203. nodeclass* Class;
  204. for (Class=Class0;Class;Class=Class->Parent)
  205. if (Class->Def.Delete)
  206. Class->Def.Delete(Node);
  207. if (!Global)
  208. for (Class=Class0;Class;Class=Class->Parent)
  209. UnlockModule(p,Class->ModuleNo);
  210. }
  211. static NOINLINE nodemodule* LoadModule(context* p,int No)
  212. {
  213. nodemodule* Module = ARRAYBEGIN(p->NodeModule,nodemodule)+No;
  214. if (!Module->Module && No>0 && p->LoadModuleNo!=No)
  215. {
  216. //DEBUG_MSG1(-1,T("LoadModule %s"),LangStrDef(MODULE_PATH,No));
  217. p->LoadModuleNo = No;
  218. Module->Module = NodeLoadModule(LangStrDef(MODULE_PATH,No),&Module->Id,&Module->Func,&Module->Db);
  219. p->LoadModuleNo = 0;
  220. if (!Module->Module)
  221. return NULL;
  222. }
  223. return Module;
  224. }
  225. static int CallCreate(context* p,node* Node,nodeclass* Class,bool_t Global)
  226. {
  227. if (Class)
  228. {
  229. nodemodule* Module = LoadModule(p,Class->ModuleNo);
  230. if (!Module)
  231. return ERR_NOT_SUPPORTED;
  232. if (Class->Def.ParentClass && !Class->Parent)
  233. return ERR_NOT_SUPPORTED;
  234. if (CallCreate(p,Node,Class->Parent,Global)!=ERR_NONE)
  235. return ERR_NOT_SUPPORTED;
  236. if (!Class->Registered || (Class->Def.Create && Class->Def.Create(Node) != ERR_NONE))
  237. {
  238. CallDelete(p,Node,Class->Parent,Global);
  239. return ERR_NOT_SUPPORTED;
  240. }
  241. if (!Global)
  242. Module->ObjectCount++;
  243. }
  244. return ERR_NONE;
  245. }
  246. static void Delete(context* p,node** i)
  247. {
  248. node* Node = *i;
  249. nodeclass* Item = FindClass(p,Node->Class);
  250. *i = NULL;
  251. if (Item)
  252. CallDelete(p,Node,Item,(Item->Def.Flags & CF_GLOBAL)!=0);
  253. free(Node);
  254. }
  255. static void Register(context* p,const nodedef* Def,bool_t Registered,int ModuleNo)
  256. {
  257. nodeclass* Class;
  258. LockEnter(p->NodeLock);
  259. Class = FindClass(p,Def->Class);
  260. if (!Class)
  261. {
  262. nodeclass **c;
  263. Class = (nodeclass*) malloc(sizeof(nodeclass));
  264. if (!Class)
  265. {
  266. LockLeave(p->NodeLock);
  267. return;
  268. }
  269. Class->Def.Class = Def->Class;
  270. Class->Def.ParentClass = 0;
  271. Class->Registered = 0;
  272. Class->ModuleNo = 0;
  273. Class->Def.Flags = 0;
  274. Class->Def.Priority = -1;
  275. if (!ArrayAdd(&p->NodeClass,ARRAYCOUNT(p->NodeClass,nodeclass*),
  276.               sizeof(nodeclass*),&Class,(arraycmp)CmpClass,128))
  277. {
  278. free(Class);
  279. LockLeave(p->NodeLock);
  280. return;
  281. }
  282. // fix possible child classes
  283. for (c=ARRAYBEGIN(p->NodeClass,nodeclass*);c!=ARRAYEND(p->NodeClass,nodeclass*);++c)
  284. if ((*c)->Def.ParentClass == Def->Class)
  285. (*c)->Parent = Class;
  286. }
  287. else
  288. if (!Registered)
  289. {
  290. LockLeave(p->NodeLock);
  291. return;
  292. }
  293. if (Registered)
  294. {
  295. if (Class->Def.Priority > Def->Priority && Class->ModuleNo != ModuleNo)
  296. {
  297. LockLeave(p->NodeLock);
  298. return; // already exits with higher priority in another module
  299. }
  300. #ifndef REGISTRY_GLOBAL
  301. if (ModuleNo>0 && (Class->ModuleNo != ModuleNo || Class->Def.ParentClass != Def->ParentClass || Class->Def.Flags != Def->Flags))
  302. {
  303. // save settings to registry for new classes 
  304. NodeRegSaveString(Def->Class,NODE_NAME);
  305. NodeRegSaveString(Def->Class,NODE_CONTENTTYPE);
  306. NodeRegSaveString(Def->Class,NODE_EXTS);
  307. NodeRegSaveString(Def->Class,NODE_PROBE);
  308. NodeRegSaveValue(Def->Class,NODE_MODULE_PATH,LangStrDef(MODULE_PATH,ModuleNo),MAXPATH,TYPE_STRING);
  309. NodeRegSaveValue(Def->Class,NODE_PARENT,&Def->ParentClass,sizeof(int),TYPE_INT);
  310. NodeRegSaveValue(Def->Class,NODE_FLAGS,&Def->Flags,sizeof(int),TYPE_INT);
  311. }
  312. #endif
  313. }
  314. if (Class->Def.Priority != Def->Priority)
  315. {
  316. ArrayRemove(&p->NodeClassPri,ARRAYCOUNT(p->NodeClassPri,nodeclass*),
  317.             sizeof(nodeclass*),&Class,(arraycmp)CmpClassPri);
  318. Class->Def.Priority = Def->Priority;
  319. ArrayAdd(&p->NodeClassPri,ARRAYCOUNT(p->NodeClassPri,nodeclass*),
  320.          sizeof(nodeclass*),&Class,(arraycmp)CmpClassPri,128);
  321. #ifndef REGISTRY_GLOBAL
  322. if (ModuleNo>0 && Registered)
  323. NodeRegSaveValue(Def->Class,NODE_PRIORITY,Def->Priority!=PRI_DEFAULT?&Def->Priority:NULL,sizeof(int),TYPE_INT);
  324. #endif
  325. }
  326. Class->Def = *Def;
  327. Class->ModuleNo = ModuleNo;
  328. Class->Parent = FindClass(p,Def->ParentClass);
  329. Class->Registered = Registered;
  330. LockLeave(p->NodeLock);
  331. }
  332. void NodeLoadClass(const nodedef* Def,const tchar_t* Module,int ModuleId)
  333. {
  334. context* p = Context();
  335. int ModuleNo = FindModule(p,Module,ModuleId);
  336. if (ModuleNo>=0)
  337. Register(p,Def,0,ModuleNo);
  338. }
  339. void NodeUnRegisterClass(int ClassId)
  340. {
  341. context* p = Context();
  342. nodeclass* Class = FindClass(p,ClassId);
  343. if (Class && Class->Registered)
  344. {
  345. node **i;
  346. LockEnter(p->NodeLock);
  347. Class->Registered = 0;
  348. // delete all objects
  349. for (i=ARRAYBEGIN(p->Node,node*);i!=ARRAYEND(p->Node,node*);++i)
  350. if (*i && NodeIsClass((*i)->Class,ClassId))
  351. Delete(p,i);
  352. Class->Def.Create = NULL;
  353. Class->Def.Delete = NULL;
  354. LockLeave(p->NodeLock);
  355. }
  356. }
  357. static node* NodeCreateFromClass(context* p, nodeclass* Class)
  358. {
  359. node **Empty = NULL;
  360. node **i;
  361. nodemodule* Module;
  362. node* Node;
  363. int Size;
  364. nodeclass *j;
  365. if (!Class || (Class->Def.Flags & CF_ABSTRACT))
  366. return NULL;
  367. Size = 0;
  368. for (j=Class;j;j=j->Parent)
  369. if (Size < (j->Def.Flags & CF_SIZE))
  370. Size = (j->Def.Flags & CF_SIZE);
  371. if (!Size)
  372. return NULL;
  373. LockEnter(p->NodeLock);
  374. if ((Class->Def.Flags & CF_GLOBAL) && 
  375. (Module = LoadModule(p,Class->ModuleNo))!=NULL &&
  376. (Node = NodeEnumObject(NULL,Class->Def.Class))!=NULL)
  377. {
  378. ++Module->ObjectCount;
  379. LockLeave(p->NodeLock);
  380. return Node;
  381. }
  382. for (i=ARRAYBEGIN(p->Node,node*);i!=ARRAYEND(p->Node,node*);++i)
  383. if (!*i)
  384. {
  385. Empty = i;
  386. break;
  387. }
  388. if (!Empty)
  389. {
  390. if (!ArrayAppend(&p->Node,NULL,sizeof(node**),256))
  391. {
  392. LockLeave(p->NodeLock);
  393. return NULL;
  394. }
  395. Empty = ARRAYEND(p->Node,node*)-1;
  396. }
  397. *Empty = Node = (node*) malloc(Size);
  398. if (Node)
  399. {
  400. memset(Node,0,Size);
  401. Node->Class = Class->Def.Class;
  402. if (CallCreate(p,Node,Class,(Class->Def.Flags & CF_GLOBAL)!=0) != ERR_NONE)
  403. {
  404. for (i=ARRAYBEGIN(p->Node,node*);i!=ARRAYEND(p->Node,node*);++i)
  405. if (*i == Node)
  406. *i = NULL;
  407. free(Node);
  408. Node = NULL;
  409. }
  410. else
  411. {
  412. #ifndef REGISTRY_GLOBAL
  413. if (Class->Def.Flags & CF_GLOBAL)
  414. NodeRegLoad(Node);
  415. #endif
  416. Node->Set(Node,NODE_SETTINGSCHANGED,NULL,0); // should be after NodeRegLoad
  417. }
  418. }
  419. LockLeave(p->NodeLock);
  420. return Node;
  421. }
  422. void NodeRegisterClass(const nodedef* Def)
  423. {
  424. context* p = Context();
  425. if (Def->Flags & CF_GLOBAL)
  426. {
  427. //create global object with fake class and don't register if fails
  428. nodeclass Class;
  429. memset(&Class,0,sizeof(Class));
  430. Class.Def = *Def;
  431. Class.ModuleNo = p->LoadModuleNo; 
  432. Class.Parent = FindClass(p,Def->ParentClass);
  433. Class.Registered = 1;
  434. if (!Class.Parent || !NodeCreateFromClass(p,&Class))
  435. return;
  436. }
  437. Register(p,Def,1,p->LoadModuleNo);
  438. }
  439. node* NodeCreate(int ClassId)
  440. {
  441. context* p = Context();
  442. return NodeCreateFromClass(p,FindClass(p,ClassId));
  443. }
  444. void NodeDelete(node* Node)
  445. {
  446. if (Node)
  447. {
  448. nodeclass* Class;
  449. context* p = Context();
  450. LockEnter(p->NodeLock); 
  451. Class = FindClass(p,Node->Class);
  452. if (Class && (Class->Def.Flags & CF_GLOBAL))
  453. UnlockModule(p,Class->ModuleNo);
  454. else
  455. {
  456. node **i;
  457. for (i=ARRAYBEGIN(p->Node,node*);i!=ARRAYEND(p->Node,node*);++i)
  458. if (*i == Node)
  459. {
  460. Delete(p,i);
  461. break;
  462. }
  463. }
  464. LockLeave(p->NodeLock);
  465. }
  466. }
  467. const nodedef* NodeClassDef(int Class)
  468. {
  469. nodeclass* i = FindClass(Context(),Class);
  470. return i?&i->Def:NULL;
  471. }
  472. static NOINLINE bool_t GetNode(context* p,int n,node** Node)
  473. {
  474. node** i;
  475. bool_t Result = 0;
  476. LockEnter(p->NodeLock);
  477. i = ARRAYBEGIN(p->Node,node*)+n;
  478. if (i<ARRAYEND(p->Node,node*))
  479. {
  480. *Node = *i;
  481. Result = 1;
  482. }
  483. LockLeave(p->NodeLock);
  484. return Result;
  485. }
  486. bool_t NodeHibernate()
  487. {
  488. int Mode;
  489. int No;
  490. node* Node;
  491. context* p = Context();
  492. bool_t Changed = 0;
  493. if (p && !p->InHibernate)
  494. {
  495. p->InHibernate = 1;
  496. #ifdef PLUGINCLEANUP
  497. if (ReleaseModules(p,1))
  498. Changed = 1;
  499. #endif
  500. for (Mode=0;!Changed && Mode<HIBERNATEMODES;++Mode)
  501. for (No=0;GetNode(p,No,&Node);++No)
  502. if (Node && Node->Set && Node->Set(Node,NODE_HIBERNATE,&Mode,sizeof(int))==ERR_NONE)
  503. Changed = 1;
  504. if (!Changed && ReleaseModules(p,1))
  505. Changed = 1;
  506. p->InHibernate = 0;
  507. }
  508. return Changed;
  509. }
  510. int NodeBroadcast(int Msg,const void* Data,int Size)
  511. {
  512. int No;
  513. context* p = Context();
  514. node* Node;
  515. for (No=0;GetNode(p,No,&Node);++No)
  516. if (Node && Node->Set)
  517. Node->Set(Node,Msg,Data,Size);
  518. return ERR_NONE;
  519. }
  520. int NodeSettingsChanged()
  521. {
  522. return NodeBroadcast(NODE_SETTINGSCHANGED,NULL,0);
  523. }
  524. node* NodeEnumObject(array* List, int Class)
  525. {
  526. context* p = Context();
  527. node **i;
  528. if (List)
  529. memset(List,0,sizeof(array));
  530. LockEnter(p->NodeLock);
  531. for (i=ARRAYBEGIN(p->Node,node*);i!=ARRAYEND(p->Node,node*);++i)
  532. if (*i && NodeIsClass((*i)->Class,Class))
  533. {
  534. if (!List)
  535. {
  536. node* Node = *i;
  537. LockLeave(p->NodeLock);
  538. return Node;
  539. }
  540. ArrayAppend(List,i,sizeof(node**),64);
  541. }
  542. LockLeave(p->NodeLock);
  543. if (List)
  544. ArraySort(List,ARRAYCOUNT(*List,node*),sizeof(node*),(arraycmp)CmpNodePri);
  545. return NULL;
  546. }
  547. bool_t NodeIsClass(int ClassId, int PartOfClass)
  548. {
  549. nodeclass* Item;
  550. for (Item = FindClass(Context(),ClassId);Item;Item=Item->Parent)
  551. if (Item->Def.Class == PartOfClass)
  552. return 1;
  553. return 0;
  554. }
  555. static void DumpPtr(stream* File, tchar_t* s, node* Ptr, int No)
  556. {
  557. if (Ptr)
  558. {
  559. tchar_t v[32];
  560. if (No)
  561. stprintf_s(v,TSIZEOF(v),T(":%d"),No);
  562. else
  563. v[0] = 0;
  564. StreamPrintf(File,T("%s%s%s (0x%08x)n"),s,LangStrDef(Ptr->Class,0),v,(int)Ptr);
  565. }
  566. else
  567. StreamPrintf(File,T("%sNULLn"),s);
  568. }
  569. static void DumpFormat(stream* File, tchar_t* s,const packetformat* Format)
  570. {
  571. tchar_t v[8];
  572. switch (Format->Type)
  573. {
  574. case PACKET_VIDEO:
  575. StreamPrintf(File,T("%svideo"),s);
  576. if (Format->Format.Video.Pixel.Flags & PF_FOURCC) 
  577. {
  578. FourCCToString(v,TSIZEOF(v),Format->Format.Video.Pixel.FourCC);
  579. StreamPrintf(File,T(" fourcc=%s"),v);
  580. }
  581. else
  582. StreamPrintf(File,T(" bitcount=%d rmask=%04x gmask=%04x bmask=%04x"),Format->Format.Video.Pixel.BitCount,
  583. Format->Format.Video.Pixel.BitMask[0],Format->Format.Video.Pixel.BitMask[1],Format->Format.Video.Pixel.BitMask[2]);
  584. if (Format->Format.Video.Width) StreamPrintf(File,T(" width=%d"),Format->Format.Video.Width);
  585. if (Format->Format.Video.Height) StreamPrintf(File,T(" height=%d"),Format->Format.Video.Height);
  586. if (Format->Format.Video.Pitch) StreamPrintf(File,T(" pitch=%d"),Format->Format.Video.Pitch);
  587. if (Format->Format.Video.Direction) StreamPrintf(File,T(" dir=%d"),Format->Format.Video.Direction);
  588. if (Format->ByteRate) StreamPrintf(File,T(" bitrate=%d"),Format->ByteRate*8);
  589. StreamPrintf(File,T("n"));
  590. break;
  591. case PACKET_AUDIO:
  592. StreamPrintf(File,T("%saudio"),s);
  593. if (Format->Format.Audio.Format) StreamPrintf(File,T(" fmt=%04x"),Format->Format.Audio.Format);
  594. if (Format->Format.Audio.SampleRate) StreamPrintf(File,T(" rate=%d"),Format->Format.Audio.SampleRate);
  595. if (Format->Format.Audio.Channels) StreamPrintf(File,T(" ch=%d"),Format->Format.Audio.Channels);
  596. if (Format->Format.Audio.Bits) StreamPrintf(File,T(" bits=%d"),Format->Format.Audio.Bits);
  597. if (Format->ByteRate) StreamPrintf(File,T(" bitrate=%d"),Format->ByteRate*8);
  598. StreamPrintf(File,T("n"));
  599. break;
  600. case PACKET_SUBTITLE:
  601. FourCCToString(v,TSIZEOF(v),Format->Format.Subtitle.FourCC);
  602. StreamPrintf(File,T("%ssubtitle fourcc=%sn"),s,v);
  603. break;
  604. case PACKET_NONE:
  605. StreamPrintf(File,T("%sempty packet formatn"),s);
  606. break;
  607. default:
  608. StreamPrintf(File,T("%sunknown packet format (%d)n"),s,Format->Type);
  609. break;
  610. }
  611. }
  612. void NodeDump(struct stream* File)
  613. {
  614. context* p = Context();
  615. node **i;
  616. nodemodule* j;
  617. nodeclass** k;
  618. int No;
  619. for (No=0,j=ARRAYBEGIN(p->NodeModule,nodemodule);j!=ARRAYEND(p->NodeModule,nodemodule);++j,++No)
  620. TRY_BEGIN 
  621. {
  622. int ClassCount = 0;
  623. for (k=ARRAYBEGIN(p->NodeClass,nodeclass*);k!=ARRAYEND(p->NodeClass,nodeclass*);++k)
  624. if ((*k)->ModuleNo == No)
  625. ++ClassCount;
  626. if (j->Func && !j->Min)
  627. CodeFindPages(j->Func,&j->Min,&j->Max,NULL);
  628. StreamPrintf(File,T("%s %08x-%08x obj:%d class:%dn"),LangStrDef(MODULE_PATH,No),j->Min,j->Max,j->ObjectCount,ClassCount);
  629. }
  630. TRY_END
  631. StreamPrintf(File,T("nn"));
  632. //no NodeLock, becase may be stayed locked when dumping after crash 
  633. for (i=ARRAYBEGIN(p->Node,node*);i!=ARRAYEND(p->Node,node*);++i)
  634. if (*i)
  635. TRY_BEGIN 
  636. {
  637. tchar_t Flags[64];
  638. tchar_t s[256];
  639. tchar_t Buffer[512];
  640. const tchar_t* Name;
  641. rect Rect;
  642. packetformat Format;
  643. pin Pin;
  644. rgb RGB;
  645. point Point;
  646. bool_t Bool;
  647. tick_t Tick;
  648. fraction Fraction;
  649. node* Ptr;
  650. int Int,No;
  651. node* p = *i;
  652. datadef DataDef;
  653. StreamPrintf(File,T("%s (0x%08x)n"),LangStrDef(p->Class,0),(int)p);
  654. for (No=0;NodeEnum(p,No,&DataDef)==ERR_NONE;++No)
  655. {
  656. TRY_BEGIN 
  657. {
  658. Name = LangStrDef(DataDef.Class,DataDef.No);
  659. if (!Name[0]) Name = DataDef.Name ? DataDef.Name : T("");
  660. Flags[0] = 0;
  661. if (DataDef.Flags & DF_INPUT)
  662. tcscat_s(Flags,TSIZEOF(Flags),T(":IN"));
  663. if (DataDef.Flags & DF_OUTPUT)
  664. tcscat_s(Flags,TSIZEOF(Flags),T(":OUT"));
  665. stprintf_s(s,TSIZEOF(s),T("  %s(%d)%s="),Name,DataDef.No,Flags);
  666. switch (DataDef.Type)
  667. {
  668. case TYPE_BOOL:
  669. if (p->Get(p,DataDef.No,&Bool,sizeof(bool_t))==ERR_NONE)
  670. {
  671. BoolToString(Buffer,TSIZEOF(Buffer),Bool);
  672. StreamPrintf(File,T("%s%sn"),s,Buffer);
  673. }
  674. break;
  675. case TYPE_TICK:
  676. if (p->Get(p,DataDef.No,&Tick,sizeof(tick_t))==ERR_NONE)
  677. {
  678. TickToString(Buffer,TSIZEOF(Buffer),Tick,Tick<TICKSPERSEC,1,0);
  679. StreamPrintf(File,T("%s%sn"),s,Buffer);
  680. }
  681. break;
  682. case TYPE_INT:
  683. if (p->Get(p,DataDef.No,&Int,sizeof(int))==ERR_NONE)
  684. {
  685. IntToString(Buffer,TSIZEOF(Buffer),Int,(DataDef.Flags & DF_HEX)!=0);
  686. StreamPrintf(File,T("%s%sn"),s,Buffer);
  687. }
  688. break;
  689. case TYPE_HOTKEY:
  690. if (p->Get(p,DataDef.No,&Int,sizeof(int))==ERR_NONE)
  691. {
  692. HotKeyToString(Buffer,TSIZEOF(Buffer),Int);
  693. StreamPrintf(File,T("%s%sn"),s,Buffer);
  694. }
  695. break;
  696. case TYPE_FRACTION:
  697. if (p->Get(p,DataDef.No,&Fraction,sizeof(fraction))==ERR_NONE)
  698. {
  699. FractionToString(Buffer,TSIZEOF(Buffer),&Fraction,1,2);
  700. StreamPrintf(File,T("%s%sn"),s,Buffer);
  701. }
  702. break;
  703. case TYPE_STRING:
  704. if (p->Get(p,DataDef.No,Buffer,sizeof(Buffer))==ERR_NONE)
  705. StreamPrintf(File,T("%s%sn"),s,Buffer);
  706. break;
  707. case TYPE_RECT:
  708. if (p->Get(p,DataDef.No,&Rect,sizeof(rect))==ERR_NONE)
  709. StreamPrintf(File,T("%s%d:%d:%d:%dn"),s,Rect.x,Rect.y,Rect.Width,Rect.Height);
  710. break;
  711. case TYPE_POINT:
  712. if (p->Get(p,DataDef.No,&Point,sizeof(point))==ERR_NONE)
  713. StreamPrintf(File,T("%s%d:%dn"),s,Point.x,Point.y);
  714. break;
  715. case TYPE_RGB:
  716. if (p->Get(p,DataDef.No,&RGB.v,sizeof(RGB.v))==ERR_NONE)
  717. StreamPrintf(File,T("%s0x%082%082%082n"),s,RGB.c.r,RGB.c.b,RGB.c.b);
  718. break;
  719. case TYPE_COMMENT:
  720. if (p->Get(p,DataDef.No,&Pin,sizeof(Pin))==ERR_NONE)
  721. DumpPtr(File,s,Pin.Node,Pin.No);
  722. break;
  723. case TYPE_PACKET:
  724. if (p->Get(p,DataDef.No|PIN_FORMAT,&Format,sizeof(Format))==ERR_NONE)
  725. DumpFormat(File,s,&Format);
  726. if (p->Get(p,DataDef.No,&Pin,sizeof(Pin))==ERR_NONE)
  727. DumpPtr(File,s,Pin.Node,Pin.No);
  728. break;
  729. case TYPE_NODE:
  730. if (p->Get(p,DataDef.No,&Ptr,sizeof(Ptr)) == ERR_NONE)
  731. DumpPtr(File,s,Ptr,0);
  732. break;
  733. }
  734. }
  735. TRY_END
  736. }
  737. }
  738. TRY_END
  739. StreamPrintf(File,T("nn"));
  740. for (k=ARRAYBEGIN(p->NodeClass,nodeclass*);k!=ARRAYEND(p->NodeClass,nodeclass*);++k)
  741. TRY_BEGIN 
  742. {
  743. tchar_t s[16],s2[16];
  744. int Class = (*k)->Def.Class;
  745. FourCCToString(s,TSIZEOF(s),Class);
  746. FourCCToString(s2,TSIZEOF(s2),(*k)->Def.ParentClass);
  747. StreamPrintf(File,T("%s %s p:%d r:%d "),s,s2,(*k)->Parent!=NULL,(*k)->Registered);
  748. StreamPrintf(File,T("c:%s e:%s p:%s m:%sn"),
  749. LangStrDef(Class,NODE_CONTENTTYPE),
  750. LangStrDef(Class,NODE_EXTS),
  751. LangStrDef(Class,NODE_PROBE),
  752. LangStrDef(MODULE_PATH,(*k)->ModuleNo));
  753. }
  754. TRY_END
  755. }
  756. int NodeEnumTable(int* No, datadef* Out, const datatable* p)
  757. {
  758. int Count;
  759. for (Count=0;p[Count].Type>=0;++Count);
  760. if (*No < Count)
  761. {
  762. Out->Class = p[Count].No;
  763. p += *No;
  764. Out->No = p->No;
  765. Out->Type = p->Type;
  766. Out->Flags = p->Flags;
  767. Out->Format1 = p->Format1;
  768. Out->Format2 = p->Format2;
  769. switch (Out->Type)
  770. {
  771. case TYPE_BOOL: Out->Size = sizeof(bool_t); break;
  772. case TYPE_INT: Out->Size = sizeof(int); break;
  773. case TYPE_HOTKEY: Out->Size = sizeof(int); break;
  774. case TYPE_FRACTION: Out->Size = sizeof(fraction); break;
  775. case TYPE_STRING: Out->Size = MAXDATA; break;
  776. case TYPE_RECT: Out->Size = sizeof(rect); break;
  777. case TYPE_POINT: Out->Size = sizeof(point); break;
  778. case TYPE_RGB: Out->Size = sizeof(rgbval_t); break;
  779. case TYPE_BINARY: Out->Size = Out->Format1; break;
  780. case TYPE_NODE: Out->Size = sizeof(node*); break;
  781. case TYPE_NOTIFY: Out->Size = sizeof(notify); break;
  782. case TYPE_COMMENT:
  783. case TYPE_PACKET: Out->Size = sizeof(pin); break;
  784. case TYPE_TICK: Out->Size = sizeof(tick_t); break;
  785. case TYPE_BLITFX: Out->Size = sizeof(blitfx); break;
  786. default:
  787. Out->Size = 0;
  788. break;
  789. }
  790. Out->Name = LangStr(Out->Class,Out->No);
  791. return ERR_NONE;
  792. }
  793. *No -= Count;
  794. return ERR_INVALID_PARAM;
  795. }
  796. bool_t NodeDataDef(node* p, int No, datadef* Out)
  797. {
  798. int i;
  799. for (i=0;NodeEnum(p,i,Out)==ERR_NONE;++i)
  800. if (Out->No == No)
  801. return 1;
  802. return 0;
  803. }
  804. int NodeEnum(node* p,int No,datadef* Param)
  805. {
  806. if (!p) return ERR_INVALID_PARAM;
  807. return p->Enum(p,&No,Param);
  808. }
  809. int NodeEnumClass(array* List, int Class)
  810. {
  811. return NodeEnumClassEx(List,Class,NULL,NULL,NULL,0);
  812. }
  813. int NodeEnumClassEx(array* List, int Class, const tchar_t* ContentType, const tchar_t* URL, const void* Data, int Length)
  814. {
  815. context* p = Context();
  816. nodeclass* v;
  817. nodeclass **i;
  818. if (ContentType && !ContentType[0])
  819. ContentType = NULL;
  820. if (URL && !URL[0])
  821. URL = NULL;
  822. if (List)
  823. memset(List,0,sizeof(array));
  824. LockEnter(p->NodeLock);
  825. for (i=ARRAYBEGIN(p->NodeClassPri,nodeclass*);i!=ARRAYEND(p->NodeClassPri,nodeclass*);++i)
  826. if (!((*i)->Def.Flags & CF_ABSTRACT) && !TmpModule(p,(*i)->ModuleNo)) // skip abstract
  827. for (v=*i;v;v=v->Parent)
  828. if (v->Def.Class == Class)
  829. {
  830. int Id = (*i)->Def.Class;
  831. if ((ContentType || URL || Data) &&
  832. (!ContentType || !CheckContentType(ContentType,LangStrDef(Id,NODE_CONTENTTYPE))) &&
  833. (!URL || !CheckExts(URL,LangStrDef(Id,NODE_EXTS))) &&
  834. (!Data || !DataProbe(Data,Length,LangStrDef(Id,NODE_PROBE))))
  835. continue;
  836. if (!List)
  837. {
  838. LockLeave(p->NodeLock);
  839. return Id;
  840. }
  841. ArrayAppend(List,&Id,sizeof(int),64);
  842. break;
  843. }
  844. LockLeave(p->NodeLock);
  845. return 0;
  846. }
  847. static int Enum(void* This,int* EnumNo,datadef* Out) { return ERR_INVALID_PARAM; }
  848. static int Get(void* This,int No,void* Data,int Size) { return ERR_INVALID_PARAM; }
  849. static int Set(void* This,int No,const void* Data,int Size) { return ERR_INVALID_PARAM; }
  850. static int Create(node* p)
  851. {
  852. p->Enum = Enum;
  853. p->Get = Get;
  854. p->Set = Set;
  855. return ERR_NONE;
  856. }
  857. static const nodedef Node =
  858. {
  859. CF_ABSTRACT,
  860. NODE_CLASS,
  861. 0,
  862. PRI_DEFAULT,
  863. (nodecreate)Create
  864. };
  865. void Node_Init()
  866. {
  867. context* p = Context();
  868. ArrayAlloc(&p->NodeClass,sizeof(nodeclass*)*100,128);
  869. ArrayAlloc(&p->NodeClassPri,sizeof(nodeclass*)*100,128);
  870. p->NodeLock = LockCreate();
  871. NodeAddModule(T("common"),0,0,0,0);
  872. if (!ARRAYEMPTY(p->NodeModule))
  873. *(void(**)())&ARRAYBEGIN(p->NodeModule,nodemodule)->Func = Node_Init;
  874. NodeRegisterClass(&Node);
  875. }
  876. void Node_Done()
  877. {
  878. context* p = Context();
  879. nodeclass **i;
  880. NodeUnRegisterClass(NODE_CLASS);
  881. #ifndef NDEBUG
  882. {
  883. nodemodule* j;
  884. for (j=ARRAYBEGIN(p->NodeModule,nodemodule);j!=ARRAYEND(p->NodeModule,nodemodule);++j)
  885. {
  886. if (j->ObjectCount!=0)
  887. DebugMessage(T("module problem %s"),LangStr(MODULE_PATH,j-ARRAYBEGIN(p->NodeModule,nodemodule)));
  888. assert(j->ObjectCount==0);
  889. }
  890. }
  891. #endif
  892. ReleaseModules(p,1);
  893. for (i=ARRAYBEGIN(p->NodeClass,nodeclass*);i!=ARRAYEND(p->NodeClass,nodeclass*);++i)
  894. free(*i);
  895. ArrayClear(&p->Node);
  896. ArrayClear(&p->NodeClass);
  897. ArrayClear(&p->NodeClassPri);
  898. ArrayClear(&p->NodeModule);
  899. LockDelete(p->NodeLock);
  900. p->NodeLock = NULL;
  901. }
  902. bool_t NodeLocatePtr(void* Ptr, tchar_t* OutName, int OutLen, int* OutBase)
  903. {
  904. if (Ptr)
  905. {
  906. context* p = Context();
  907. if (p) 
  908. {
  909. int No;
  910. uint8_t* v = (uint8_t*)Ptr;
  911. nodemodule *i;
  912. // no locking (dump after crash)
  913. for (No=0,i=ARRAYBEGIN(p->NodeModule,nodemodule);i!=ARRAYEND(p->NodeModule,nodemodule);++i,++No)
  914. {
  915. if (i->Func)
  916. {
  917. if (!i->Min)
  918. CodeFindPages(i->Func,&i->Min,&i->Max,NULL);
  919. if (i->Min <= v && i->Max > v)
  920. {
  921. tcscpy_s(OutName,OutLen,LangStrDef(MODULE_PATH,No));
  922. *OutBase = v - i->Min;
  923. return 1;
  924. }
  925. }
  926. }
  927. }
  928. }
  929. return 0;
  930. }
  931. #ifndef REGISTRY_GLOBAL
  932. bool_t NodeRegLoadString(int Class, int Id)
  933. {
  934. uint8_t Buffer[MAXDATA];
  935. if (NodeRegLoadValue(Class,Id,Buffer,sizeof(Buffer),TYPE_STRING))
  936. {
  937. StringAdd(1,Class,Id,(tchar_t*)Buffer);
  938. return 1;
  939. }
  940. return 0;
  941. }
  942. void NodeRegSaveString(int Class, int Id)
  943. {
  944. const tchar_t* s = LangStrDef(Class,Id);
  945. int Len = tcslen(s);
  946. if (Len)
  947. ++Len;
  948. else 
  949. s = NULL;
  950. NodeRegSaveValue(Class,Id,s,Len*sizeof(tchar_t),TYPE_STRING);
  951. }
  952. #endif