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

📄 mdriver.c

📁 这是著名的TCPMP播放器在WINDWOWS,和WINCE下编译通过的源程序.笔者对其中的LIBMAD库做了针对ARM MPU的优化. 并增加了词幕功能.
💻 C
📖 第 1 页 / 共 2 页
字号:
}

MIKMODAPI ULONG Voice_RealVolume(SBYTE voice)
{
	ULONG result=0;

	MUTEX_LOCK(vars);
	if((voice>=0)&&(voice<md_numchn)&& md_driver->VoiceRealVolume)
		result=(md_driver->VoiceRealVolume(voice));
	MUTEX_UNLOCK(vars);

	return result;
}

static BOOL _mm_init(CHAR *cmdline)
{
	UWORD t;

	_mm_critical = 1;

	/* if md_device==0, try to find a device number */
	if(!md_device) {
		cmdline=NULL;

		for(t=1,md_driver=firstdriver;md_driver;md_driver=md_driver->next,t++)
			if(md_driver->IsPresent()) break;

		if(!md_driver) {
			_mm_errno = MMERR_DETECTING_DEVICE;
			if(_mm_errorhandler) _mm_errorhandler();
			md_driver = &drv_nos;
			return 1;
		}

		md_device = t;
	} else {
		/* if n>0, use that driver */
		for(t=1,md_driver=firstdriver;(md_driver)&&(t!=md_device);md_driver=md_driver->next)
			t++;

		if(!md_driver) {
			_mm_errno = MMERR_INVALID_DEVICE;
			if(_mm_errorhandler) _mm_errorhandler();
			md_driver = &drv_nos;
			return 1;
		}

		/* arguments here might be necessary for the presence check to succeed */
		if(cmdline&&(md_driver->CommandLine))
			md_driver->CommandLine(cmdline);

		if(!md_driver->IsPresent()) {
			_mm_errno = MMERR_DETECTING_DEVICE;
			if(_mm_errorhandler) _mm_errorhandler();
			md_driver = &drv_nos;
			return 1;
		}
	}

	olddevice = md_device;
	if(md_driver->Init()) {
		MikMod_Exit_internal();
		if(_mm_errorhandler) _mm_errorhandler();
		return 1;
	}

	initialized=1;
	_mm_critical=0;

	return 0;
}

MIKMODAPI BOOL MikMod_Init(CHAR *cmdline)
{
	BOOL result;

	MUTEX_LOCK(vars);
	MUTEX_LOCK(lists);
	result=_mm_init(cmdline);
	MUTEX_UNLOCK(lists);
	MUTEX_UNLOCK(vars);

	return result;
}

void MikMod_Exit_internal(void)
{
	MikMod_DisableOutput_internal();
	md_driver->Exit();
	md_numchn = md_sfxchn = md_sngchn = 0;
	md_driver = &drv_nos;

	if(sfxinfo) free(sfxinfo);
	if(md_sample) free(md_sample);
	md_sample  = NULL;
	sfxinfo    = NULL;

	initialized = 0;
}

MIKMODAPI void MikMod_Exit(void)
{
	MUTEX_LOCK(vars);
	MUTEX_LOCK(lists);
	MikMod_Exit_internal();
	MUTEX_UNLOCK(lists);
	MUTEX_UNLOCK(vars);
}

/* Reset the driver using the new global variable settings. 
   If the driver has not been initialized, it will be now. */
static BOOL _mm_reset(CHAR *cmdline)
{
	BOOL wasplaying = 0;

	if(!initialized) return _mm_init(cmdline);
	
	if (isplaying) {
		wasplaying = 1;
		md_driver->PlayStop();
	}

	if((!md_driver->Reset)||(md_device != olddevice)) {
		/* md_driver->Reset was NULL, or md_device was changed, so do a full
		   reset of the driver. */
		md_driver->Exit();
		if(_mm_init(cmdline)) {
			MikMod_Exit_internal();
			if(_mm_errno)
				if(_mm_errorhandler) _mm_errorhandler();
			return 1;
		}
	} else {
		if(md_driver->Reset()) {
			MikMod_Exit_internal();
			if(_mm_errno)
				if(_mm_errorhandler) _mm_errorhandler();
			return 1;
		}
	}
	
	if (wasplaying) md_driver->PlayStart();
	return 0;
}

MIKMODAPI BOOL MikMod_Reset(CHAR *cmdline)
{
	BOOL result;

	MUTEX_LOCK(vars);
	MUTEX_LOCK(lists);
	result=_mm_reset(cmdline);
	MUTEX_UNLOCK(lists);
	MUTEX_UNLOCK(vars);

	return result;
}

/* If either parameter is -1, the current set value will be retained. */
BOOL MikMod_SetNumVoices_internal(int music, int sfx)
{
	BOOL resume = 0;
	int t, oldchn = 0;

	if((!music)&&(!sfx)) return 1;
	_mm_critical = 1;
	if(isplaying) {
		MikMod_DisableOutput_internal();
		oldchn = md_numchn;
		resume = 1;
	}

	if(sfxinfo) free(sfxinfo);
	if(md_sample) free(md_sample);
	md_sample  = NULL;
	sfxinfo    = NULL;

	if(music!=-1) md_sngchn = music;
	if(sfx!=-1)   md_sfxchn = sfx;
	md_numchn = md_sngchn + md_sfxchn;

	LimitHardVoices(md_driver->HardVoiceLimit);
	LimitSoftVoices(md_driver->SoftVoiceLimit);

	if(md_driver->SetNumVoices()) {
		MikMod_Exit_internal();
		if(_mm_errno)
			if(_mm_errorhandler!=NULL) _mm_errorhandler();
		md_numchn = md_softchn = md_hardchn = md_sfxchn = md_sngchn = 0;
		return 1;
	}

	if(md_sngchn+md_sfxchn)
		md_sample=(SAMPLE**)_mm_calloc(md_sngchn+md_sfxchn,sizeof(SAMPLE*));
	if(md_sfxchn)
		sfxinfo = (UBYTE *)_mm_calloc(md_sfxchn,sizeof(UBYTE));

	/* make sure the player doesn't start with garbage */
	for(t=oldchn;t<md_numchn;t++)  Voice_Stop_internal(t);

	sfxpool = 0;
	if(resume) MikMod_EnableOutput_internal();
	_mm_critical = 0;

	return 0;
}

MIKMODAPI BOOL MikMod_SetNumVoices(int music, int sfx)
{
	BOOL result;

	MUTEX_LOCK(vars);
	result=MikMod_SetNumVoices_internal(music,sfx);
	MUTEX_UNLOCK(vars);

	return result;
}

BOOL MikMod_EnableOutput_internal(void)
{
	_mm_critical = 1;
	if(!isplaying) {
		if(md_driver->PlayStart()) return 1;
		isplaying = 1;
	}
	_mm_critical = 0;
	return 0;
}

MIKMODAPI BOOL MikMod_EnableOutput(void)
{
	BOOL result;

	MUTEX_LOCK(vars);
	result=MikMod_EnableOutput_internal();
	MUTEX_UNLOCK(vars);

	return result;
}

void MikMod_DisableOutput_internal(void)
{
	if(isplaying && md_driver) {
		isplaying = 0;
		md_driver->PlayStop();
	}
}

MIKMODAPI void MikMod_DisableOutput(void)
{
	MUTEX_LOCK(vars);
	MikMod_DisableOutput_internal();
	MUTEX_UNLOCK(vars);
}

BOOL MikMod_Active_internal(void)
{
	return isplaying;
}

MIKMODAPI BOOL MikMod_Active(void)
{
	BOOL result;

	MUTEX_LOCK(vars);
	result=MikMod_Active_internal();
	MUTEX_UNLOCK(vars);

	return result;
}

/* Plays a sound effects sample.  Picks a voice from the number of voices
   allocated for use as sound effects (loops through voices, skipping all active
   criticals).

   Returns the voice that the sound is being played on.                       */
SBYTE Sample_Play_internal(SAMPLE *s,ULONG start,UBYTE flags)
{
	int orig=sfxpool;/* for cases where all channels are critical */
	int c;

	if(!md_sfxchn) return -1;
	if(s->volume>64) s->volume = 64;

	/* check the first location after sfxpool */
	do {
		if(sfxinfo[sfxpool]&SFX_CRITICAL) {
			if(md_driver->VoiceStopped(c=sfxpool+md_sngchn)) {
				sfxinfo[sfxpool]=flags;
				Voice_Play_internal(c,s,start);
				md_driver->VoiceSetVolume(c,s->volume<<2);
				Voice_SetPanning_internal(c,s->panning);
				md_driver->VoiceSetFrequency(c,s->speed);
				sfxpool++;
				if(sfxpool>=md_sfxchn) sfxpool=0;
				return c;
			}
		} else {
			sfxinfo[sfxpool]=flags;
			Voice_Play_internal(c=sfxpool+md_sngchn,s,start);
			md_driver->VoiceSetVolume(c,s->volume<<2);
			Voice_SetPanning_internal(c,s->panning);
			md_driver->VoiceSetFrequency(c,s->speed);
			sfxpool++;
			if(sfxpool>=md_sfxchn) sfxpool=0;
			return c;
		}

		sfxpool++;
		if(sfxpool>=md_sfxchn) sfxpool = 0;
	} while(sfxpool!=orig);

	return -1;
}

MIKMODAPI SBYTE Sample_Play(SAMPLE *s,ULONG start,UBYTE flags)
{
	SBYTE result;

	MUTEX_LOCK(vars);
	result=Sample_Play_internal(s,start,flags);
	MUTEX_UNLOCK(vars);

	return result;
}

MIKMODAPI long MikMod_GetVersion(void)
{
	return LIBMIKMOD_VERSION;
}

/*========== MT-safe stuff */

#ifdef HAVE_PTHREAD
#define INIT_MUTEX(name) \
	pthread_mutex_t _mm_mutex_##name=PTHREAD_MUTEX_INITIALIZER
#elif defined(__OS2__)||defined(__EMX__)
#define INIT_MUTEX(name) \
	HMTX _mm_mutex_##name
#elif defined(WIN32)
#define INIT_MUTEX(name) \
	HANDLE _mm_mutex_##name
#else
#define INIT_MUTEX(name) \
	void *_mm_mutex_##name = NULL
#endif

INIT_MUTEX(vars);
INIT_MUTEX(lists);

MIKMODAPI BOOL MikMod_InitThreads(void)
{
	static int firstcall=1;
	static int result=0;
	
	if (firstcall) {
		firstcall=0;
#ifdef HAVE_PTHREAD
		result=1;
#elif defined(__OS2__)||defined(__EMX__)
		if(DosCreateMutexSem((PSZ)NULL,&_mm_mutex_lists,0,0) ||
		   DosCreateMutexSem((PSZ)NULL,&_mm_mutex_vars,0,0)) {
			_mm_mutex_lists=_mm_mutex_vars=(HMTX)NULL;
			result=0;
		} else
			result=1;
#elif defined(WIN32)
		if((!(_mm_mutex_lists=CreateMutex(NULL,FALSE,"libmikmod(lists)")))||
		   (!(_mm_mutex_vars=CreateMutex(NULL,FALSE,"libmikmod(vars)"))))
			result=0;
		else
			result=1;
#endif
	}
	return result;
}

MIKMODAPI void MikMod_Unlock(void)
{
	MUTEX_UNLOCK(lists);
	MUTEX_UNLOCK(vars);
}

MIKMODAPI void MikMod_Lock(void)
{
	MUTEX_LOCK(vars);
	MUTEX_LOCK(lists);
}

/*========== Parameter extraction helper */

CHAR *MD_GetAtom(CHAR *atomname,CHAR *cmdline,BOOL implicit)
{
	CHAR *ret=NULL;

	if(cmdline) {
		CHAR *buf=strstr(cmdline,atomname);

		if((buf)&&((buf==cmdline)||(*(buf-1)==','))) {
			CHAR *ptr=buf+strlen(atomname);

			if(*ptr=='=') {
				for(buf=++ptr;(*ptr)&&((*ptr)!=',');ptr++);
				ret=_mm_malloc((1+ptr-buf)*sizeof(CHAR));
				if(ret)
					strncpy(ret,buf,ptr-buf);
			} else if((*ptr==',')||(!*ptr)) {
				if(implicit) {
					ret=_mm_malloc((1+ptr-buf)*sizeof(CHAR));
					if(ret)
						strncpy(ret,buf,ptr-buf);
				}
			}
		}
	}
	return ret;
}

#if defined unix || (defined __APPLE__ && defined __MACH__)

/*========== Posix helper functions */

/* Check if the file is a regular or nonexistant file (or a link to a such a
   file), and that, should the calling program be setuid, the access rights are
   reasonable. Returns 1 if it is safe to rewrite the file, 0 otherwise.
   The goal is to prevent a setuid root libmikmod application from overriding
   files like /etc/passwd with digital sound... */
BOOL MD_Access(CHAR *filename)
{
	struct stat buf;

	if(!stat(filename,&buf)) {
		/* not a regular file ? */
		if(!S_ISREG(buf.st_mode)) return 0;
		/* more than one hard link to the file ? */
		if(buf.st_nlink>1) return 0;
		/* check access rights with the real user and group id */
		if(getuid()==buf.st_uid) {
			if(!(buf.st_mode&S_IWUSR)) return 0;
		} else if(getgid()==buf.st_gid) {
			if(!(buf.st_mode&S_IWGRP)) return 0;
		} else
			if(!(buf.st_mode&S_IWOTH)) return 0;
	}
	
	return 1;
}

/* Drop all root privileges we might have */
BOOL MD_DropPrivileges(void)
{
	if(!geteuid()) {
		if(getuid()) {
			/* we are setuid root -> drop setuid to become the real user */
			if(setuid(getuid())) return 1;
		} else {
			/* we are run as root -> drop all and become user 'nobody' */
			struct passwd *nobody;
			int uid;

			if(!(nobody=getpwnam("nobody"))) return 1; /* no such user ? */
			uid=nobody->pw_uid;
			if (!uid) /* user 'nobody' has root privileges ? weird... */
				return 1;
			if (setuid(uid)) return 1;
		}
	}
	return 0;
}

#endif

/* ex:set ts=4: */

⌨️ 快捷键说明

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