📄 mdriver.c
字号:
}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#endifINIT_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 + -