⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 node_palmos.c

📁 大名鼎鼎的CE下播放软件,TCPPMP的源代码!!!2410下可以流畅的解QVGA的H264,MPEG4等格式.
💻 C
字号:
/*****************************************************************************
 *
 * 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);p<ARRAYEND(Buffer,int32_t);p+=3+(p[2]+3)/4)
				for (i=ARRAYBEGIN(List,node*);i!=ARRAYEND(List,node*);++i)
					if ((*i)->Class == 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;++No)
		{
			if ((!Type || Modules[0] == Type) &&
				tcscmp((const tchar_t*)(Modules+3),Path)==0)
			{
				Type = Modules[0];
				if (Modules[1] == Date)
				{
					Modules[1] = -1;
					break;
				}
				Modules[1] = -2;
			}
			Modules += 1+1+1+Modules[2]/4;
		}
	}

	NodeAddModule(Path,Type,Date,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;No<Count;++No)
		{
			if (p[1] != -1 && p[1] != -2)
				NodeAddModule((const tchar_t*)(p+3),p[0],p[1],0,1);
			p += 1+1+1+p[2]/4;
		}

		// load classes (only if not exists already. don't want to override changed loaded plugins)
		while (*p)
		{
			nodedef Def;
			int Module;
			const tchar_t* Name;
			const tchar_t* ContentType;
			const tchar_t* Exts;
			const tchar_t* Probe;

			memset(&Def,0,sizeof(Def));

			Module = *p-1; ++p;
			Def.Class = *p; ++p;
			Def.ParentClass = *p; ++p;
			Def.Flags = *p; ++p;
			Def.Priority = *p; ++p;
			p = GetString(p,&Name);
			p = GetString(p,&ContentType);
			p = GetString(p,&Exts);
			p = GetString(p,&Probe);

			if (Module<Modules[-1] && !NodeEnumClass(NULL,Def.Class))
			{
				int32_t* p = Modules;
				for (i=0;i<Module;++i)
					p += 1+1+1+p[2]/4;

				if (Name) StringAdd(1,Def.Class,NODE_NAME,Name);
				if (ContentType) StringAdd(1,Def.Class,NODE_CONTENTTYPE,ContentType);
				if (Exts) StringAdd(1,Def.Class,NODE_EXTS,Exts);
				if (Probe) StringAdd(1,Def.Class,NODE_PROBE,Probe);

				NodeLoadClass(&Def,(const tchar_t*)(p+3),p[0]);
			}
		}
	}
	else
		FindPlugins(NULL);

	ArrayClear(&Buffer);
}

bool_t NOINLINE AppendInt(array* Buffer,int Data)
{
	return ArrayAppend(Buffer,&Data,sizeof(Data),4096);
}

bool_t NOINLINE AppendStr(array* Buffer,const tchar_t* Data)
{
	int Len = (tcslen((tchar_t*)Data)+1)*sizeof(tchar_t);
	int Total = ALIGN4(Len);
	if (!AppendInt(Buffer,Total) || !ArrayAppend(Buffer,NULL,Total,4096))
		return 0;
	memcpy(ARRAYEND(*Buffer,uint8_t)-Total,Data,Len);
	memset(ARRAYEND(*Buffer,uint8_t)-Total+Len,0,Total-Len);
	return 1;
}

bool_t NOINLINE AppendString(array* Buffer,int Class,int Id)
{
	if (StringIsBinary(Class,Id))
		return AppendInt(Buffer,0);
	return AppendStr(Buffer,LangStrDef(Class,Id));
}

void Plugins_Done()
{
	array Buffer = {NULL};
	uint32_t ProgramId = Context()->ProgramId;
	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;No<Count;++No)
	{
		const tchar_t* Path = NodeGetModule(No,&Id,&Date);
		AppendInt(&Buffer,Id);
		AppendInt(&Buffer,(int)Date);
		AppendStr(&Buffer,Path);
	}

	Count = NodeGetClassCount();
	for (No=0;No<Count;++No)
	{
		const nodedef* Def = NodeGetClass(No,&Id);
		if (Id)
		{
			AppendInt(&Buffer,Id);
			AppendInt(&Buffer,Def->Class);
			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<FTRID_COUNT;++i)
			if (Modules[i] == Module)
			{
				Modules[i] = NULL;
				break;
			}

		PealFreeModule(Module);
		if (Db)
			DmCloseDatabase(Db);
	}
}

static void* LoadPlugin(UInt16 Card,LocalID CurrentDB,bool_t TmpDb,void** Db,int* Id)
{
	void* Module = NULL;
	char Name[48];
	UInt32 Type;
	UInt16 Attr;
	Boolean MemDup = 0;
	Boolean MemSema = 0;
	int No;

	DmDatabaseInfo(Card,CurrentDB,Name,&Attr,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&Type,NULL);
	if ((Type >> 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;No<FTRID_COUNT;++No)
			if (!Modules[No])
				break;

		if (No<FTRID_COUNT)
		{
			Module = PealLoadModule((UInt16)(FTRID_START+No*FTRID_STEP),
			                        MemDup,(Boolean)Context()->LowMemory,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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -