/***************************************************************************** * * This program is free software ; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: node_palmos.c 345 2005-11-19 15:57:54Z picard $ * * The Core Pocket Media Player * Copyright (c) 2004-2005 Gabor Kovacs * ****************************************************************************/ #include "../common.h" #if defined(TARGET_PALMOS) #define PREFID_NODE 2 #define PREFID_PLUGINS 100 #define FTRID_START 64 #define FTRID_STEP 64 #define FTRID_COUNT 60 #include "pace.h" #ifdef HAVE_PALMONE_SDK #include <68K/System/PmPalmOSNVFS.h> #endif void NodeRegSaveGlobal() { uint8_t Data[MAXDATA]; array Buffer = {NULL}; array List; node **i; UInt16 PrefId=PREFID_NODE; uint32_t ProgramId = Context()->ProgramId; NodeEnumObject(&List,NODE_CLASS); for (i=ARRAYBEGIN(List,node*);i!=ARRAYEND(List,node*);++i) { int No,Total; datadef Type; for (No=0;NodeEnum(*i,No,&Type)==ERR_NONE;++No) { node* Node = *i; if ((Type.Flags & DF_SETUP) && !(Type.Flags & (DF_NOSAVE|DF_RDONLY))) { int Result = Node->Get(Node,Type.No,Data,Type.Size); if (Result == ERR_NONE || Result == ERR_NOT_SUPPORTED) // not supported settings should be still saved { if (Type.Type == TYPE_STRING) Type.Size = (tcslen((tchar_t*)Data)+1)*sizeof(tchar_t); Total = sizeof(int32_t)*3+ALIGN4(Type.Size); if (ARRAYCOUNT(Buffer,uint8_t)+Total > 0xF000) { PrefSetAppPreferences(ProgramId,PrefId++,CONTEXT_VERSION,ARRAYBEGIN(Buffer,uint8_t),(UInt16)ARRAYCOUNT(Buffer,uint8_t),0); ArrayDrop(&Buffer); } if (ArrayAppend(&Buffer,NULL,Total,4096)) { int32_t* p = (int32_t*)(ARRAYEND(Buffer,uint8_t) - Total); memset(p,0,Total); p[0] = Node->Class; p[1] = Type.No; p[2] = Type.Size; memcpy(p+3,Data,Type.Size); } } } } } if (!ARRAYEMPTY(Buffer)) PrefSetAppPreferences(ProgramId,PrefId++,CONTEXT_VERSION,ARRAYBEGIN(Buffer,uint8_t),(UInt16)ARRAYCOUNT(Buffer,uint8_t),0); ArrayClear(&List); ArrayClear(&Buffer); for (;;) { UInt16 PrefSize = 0; if (PrefGetAppPreferences(ProgramId, PrefId, NULL, &PrefSize, 0) == noPreferenceFound) break; PrefSetAppPreferences(ProgramId,PrefId++,CONTEXT_VERSION,NULL,0,0); } } void NodeRegLoadGlobal() { array Buffer = {NULL}; array List; node **i; int32_t* p; UInt16 PrefId; UInt16 PrefSize; uint32_t ProgramId = Context()->ProgramId; NodeEnumObject(&List,NODE_CLASS); for (PrefId=PREFID_NODE;;++PrefId) { PrefSize = 0; if (PrefGetAppPreferences(ProgramId, PrefId, NULL, &PrefSize, 0) == noPreferenceFound) break; ArrayDrop(&Buffer); if (ArrayAppend(&Buffer,NULL,PrefSize,16) && PrefGetAppPreferences(ProgramId, PrefId, ARRAYBEGIN(Buffer,int32_t), &PrefSize, 0) != noPreferenceFound) { for (p=ARRAYBEGIN(Buffer,int32_t);pClass == p[0]) { (*i)->Set(*i,p[1],p+3,p[2]); break; } } } ArrayClear(&List); ArrayClear(&Buffer); } static NOINLINE void AddModule(const tchar_t* Path,int Type,int Date,int32_t* Modules) { int No=0; int Count=0; if (Modules) { //don't load if already registered with same date Count = Modules[-1]; for (No=0;No=Count,0); } static void VFSFindPlugins(uint16_t Ref,tchar_t* Path,int PathLen,int32_t* Modules,const tchar_t* Skip) { FileRef File; int PathPos = tcslen(Path); if (PathPos>0 && Path[PathPos-1]=='/') Path[PathPos-1] = 0; if (Skip && tcscmp(Path,Skip)==0) return; if (VFSFileOpen(Ref,Path,vfsModeRead,&File)==errNone) { FileInfoType Info; UInt32 Iter = vfsIteratorStart; tcscat_s(Path,PathLen,"/"); PathPos = tcslen(Path); Info.nameP = Path + PathPos; Info.nameBufLen = (UInt16)((PathLen-PathPos)*sizeof(tchar_t)); while (Iter != vfsIteratorStop && VFSDirEntryEnumerate(File,&Iter,&Info)==errNone) { if (tcsnicmp(Path+PathPos,T("tcpmp"),5)==0 && (Path[PathPos+5]=='_' || Path[PathPos+5]==' ')) { FileRef File = 0; VFSFileOpen(Ref,Path,vfsModeRead,&File); if (File) { UInt32 Date; if (VFSFileGetDate(File,vfsFileDateModified,&Date)==errNone) { tchar_t URL[MAXPATH]; if (VFSFromVol(Ref,Path,URL,TSIZEOF(URL))) AddModule(URL,0,Date,Modules); } VFSFileClose(File); } } } VFSFileClose(File); } } static void FindPlugins(int32_t* Modules) { bool_t CheckVFS = 1; Boolean New = 1; LocalID CurrentDB; UInt16 Card; DmSearchStateType SearchState; tchar_t Name[48]; tchar_t URL[MAXPATH]; UInt32 Type; UInt32 Date; CurrentDB = 0; while (DmGetNextDatabaseByTypeCreator(New, &SearchState, 0, Context()->ProgramId, 1, &Card, &CurrentDB)==errNone) { DmDatabaseInfo(Card,CurrentDB,Name,NULL,NULL,NULL,&Date,NULL,NULL,NULL,NULL,&Type,NULL); if ((Type >> 24) == 'X') { stprintf_s(URL,TSIZEOF(URL),T("mem://%s.prc"),Name); AddModule(URL,Type,Date,Modules); CheckVFS = 0; } New = 0; } if (NodeEnumClass(NULL,VFS_ID)) { UInt16 Ref; uint32_t LaunchPath = 0; URL[0] = 0; if (FtrGet(Context()->ProgramId,20,&LaunchPath)==errNone) { Ref = ((vfspath*)LaunchPath)->volRefNum; SplitURL(((vfspath*)LaunchPath)->path,URL,TSIZEOF(URL),URL,TSIZEOF(URL),NULL,0,NULL,0); VFSFindPlugins(Ref,URL,TSIZEOF(URL),Modules,NULL); } if (CheckVFS || QueryAdvanced(ADVANCED_CARDPLUGINS)) { UInt32 Iter = vfsIteratorStart; while (Iter != vfsIteratorStop && VFSVolumeEnumerate(&Ref,&Iter)==errNone) { tchar_t Path[MAXPATH]; UInt16 Size = sizeof(Path); if (VFSGetDefaultDirectory(Ref,T(".prc"),Path,&Size)==errNone) VFSFindPlugins(Ref,Path,TSIZEOF(Path),Modules,URL); } } } } static NOINLINE int32_t* GetString(int32_t* p,const tchar_t** s) { if (p[0]) { *s = (const tchar_t*)(p+1); p+=1+p[0]/4; } else { *s = NULL; ++p; } return p; } void Plugins_Init() { array Buffer = {NULL}; int32_t* p; int32_t* Modules; int i,No,Count; bool_t b; UInt16 PrefSize; uint32_t ProgramId = Context()->ProgramId; node* Advanced = Context()->Advanced; PrefSize = 0; if (PrefGetAppPreferences(ProgramId, PREFID_PLUGINS, NULL, &PrefSize, 0) != noPreferenceFound && ArrayAppend(&Buffer,NULL,PrefSize,16) && PrefGetAppPreferences(ProgramId, PREFID_PLUGINS, ARRAYBEGIN(Buffer,int32_t), &PrefSize, 0) != noPreferenceFound) { // add all plugins and load changed/new ones p = ARRAYBEGIN(Buffer,int32_t); if (*p<0) { // params if (Advanced) { b = p[1] != 0; Advanced->Set(Advanced,ADVANCED_CARDPLUGINS,&b,sizeof(b)); } p += 1-*p; } Count = *(p++); Modules = p; FindPlugins(Modules); // also add non existing modules (maybe SD card removed temporarily) for (No=0;NoProgramId; int64_t Date; int No,Count; int Id; AppendInt(&Buffer,-1); AppendInt(&Buffer,QueryAdvanced(ADVANCED_CARDPLUGINS)); Count = NodeGetModuleCount(); AppendInt(&Buffer,Count-1); for (No=1;NoClass); AppendInt(&Buffer,Def->ParentClass); AppendInt(&Buffer,Def->Flags); AppendInt(&Buffer,Def->Priority); AppendString(&Buffer,Def->Class,NODE_NAME); AppendString(&Buffer,Def->Class,NODE_CONTENTTYPE); AppendString(&Buffer,Def->Class,NODE_EXTS); AppendString(&Buffer,Def->Class,NODE_PROBE); } } AppendInt(&Buffer,0); if (ARRAYCOUNT(Buffer,uint8_t)<0x8000) PrefSetAppPreferences(ProgramId,PREFID_PLUGINS,CONTEXT_VERSION,ARRAYBEGIN(Buffer,uint8_t),(UInt16)ARRAYCOUNT(Buffer,uint8_t),0); ArrayClear(&Buffer); } static void* Modules[FTRID_COUNT] = {NULL}; void NodeFreeModule(void* Module,void* Db) { if (Module) { int i; void* UnRegister = PealGetSymbol(Module,T("DLLUnRegister")); if (UnRegister) ((void(*)())UnRegister)(); for (i=0;i> 24) != 'X') { if (TmpDb) DmDeleteDatabase(Card,CurrentDB); return NULL; } *Id = Type; #ifdef ARM { UInt32 Version; FtrGet(sysFtrCreator, sysFtrNumROMVersion, &Version); MemSema = (Boolean)(Version < sysMakeROMVersion(6,0,0,sysROMStageDevelopment,0)); } #endif #ifdef HAVE_PALMONE_SDK // duplicate plugins to memory with NVFS, because writing back reallocation // causes the plugins to disappear sometimes from storage flash memory. if (!MemSema) // but don't care if can use memory semaphore { UInt32 Version; if (FtrGet(sysFtrCreator,sysFtrNumDmAutoBackup,&Version)==errNone && Version==1) MemDup = 1; } #endif if (TmpDb) { Attr |= dmHdrAttrRecyclable; DmSetDatabaseInfo(Card,CurrentDB,NULL,&Attr,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); } *Db = DmOpenDatabaseByTypeCreator(Type,Context()->ProgramId,dmModeReadOnly); if (*Db) { for (No=0;NoLowMemory,MemSema); if (Module) { void* Register = PealGetSymbol(Module,T("DLLRegister")); if (Register) { int Result = ((int(*)(int))Register)(CONTEXT_VERSION); if (Result != ERR_NONE) { Register = NULL; if (Result == ERR_NOT_COMPATIBLE) { int n = tcslen(Name); if (n>7 && tcsnicmp(Name+n-7,T(" plugin"),7)==0) Name[n-7] = 0; ShowError(0,ERR_ID,ERR_NOT_COMPATIBLE,Name); } } } if (!Register) { PealFreeModule(Module); Module = NULL; } else Modules[No] = Module; } } if (!Module || MemDup) { DmCloseDatabase(*Db); *Db = NULL; } } return Module; } void* NodeLoadModule(const tchar_t* URL,int* Id,void** AnyFunc,void** Db) { void* Module = NULL; UInt16 Card; LocalID CurrentDB; if (tcsncmp(URL,"mem",3)!=0) { uint16_t Vol; const tchar_t* Path = VFSToVol(URL,&Vol); if (Path && VFSImportDatabaseFromFile(Vol,Path,&Card,&CurrentDB)==errNone) Module = LoadPlugin(Card,CurrentDB,1,Db,Id); } else { DmSearchStateType SearchState; CurrentDB = 0; if (DmGetNextDatabaseByTypeCreator(1, &SearchState, *Id, Context()->ProgramId, 1, &Card, &CurrentDB)==errNone) Module = LoadPlugin(Card,CurrentDB,0,Db,Id); } return Module; } #endif