mdriver.c
资源名称:tcpmp.rar [点击查看]
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:21k
源码类别:
Windows CE
开发平台:
C/C++
- /* MikMod sound library
- (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
- for complete list.
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Library 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 Library General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
- */
- /*==============================================================================
- $Id: mdriver.c,v 1.3 2004/02/18 13:29:19 raph Exp $
- These routines are used to access the available soundcard drivers.
- ==============================================================================*/
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #if defined unix || (defined __APPLE__ && defined __MACH__)
- #include <pwd.h>
- #include <sys/stat.h>
- #endif
- #include <string.h>
- #ifdef HAVE_STRINGS_H
- #include <strings.h>
- #endif
- #include "mikmod_internals.h"
- #ifdef SUNOS
- extern int fprintf(FILE *, const char *, ...);
- #endif
- static MDRIVER *firstdriver=NULL;
- MIKMODAPI MDRIVER *md_driver=NULL;
- extern MODULE *pf; /* modfile being played */
- /* Initial global settings */
- MIKMODAPI UWORD md_device = 0; /* autodetect */
- MIKMODAPI UWORD md_mixfreq = 44100;
- MIKMODAPI UWORD md_mode = DMODE_STEREO | DMODE_16BITS |
- DMODE_SURROUND |DMODE_SOFT_MUSIC |
- DMODE_SOFT_SNDFX;
- MIKMODAPI UBYTE md_pansep = 128; /* 128 == 100% (full left/right) */
- MIKMODAPI UBYTE md_reverb = 0; /* no reverb */
- MIKMODAPI UBYTE md_volume = 128; /* global sound volume (0-128) */
- MIKMODAPI UBYTE md_musicvolume = 128; /* volume of song */
- MIKMODAPI UBYTE md_sndfxvolume = 128; /* volume of sound effects */
- UWORD md_bpm = 125; /* tempo */
- /* Do not modify the numchn variables yourself! use MD_SetVoices() */
- UBYTE md_numchn=0,md_sngchn=0,md_sfxchn=0;
- UBYTE md_hardchn=0,md_softchn=0;
- void (*md_player)(void) = Player_HandleTick;
- static BOOL isplaying=0, initialized = 0;
- static UBYTE *sfxinfo;
- static int sfxpool;
- static SAMPLE **md_sample = NULL;
- /* Previous driver in use */
- static SWORD olddevice = -1;
- /* Limits the number of hardware voices to the specified amount.
- This function should only be used by the low-level drivers. */
- static void LimitHardVoices(int limit)
- {
- int t=0;
- if (!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>limit)) md_sfxchn=limit;
- if (!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>limit)) md_sngchn=limit;
- if (!(md_mode & DMODE_SOFT_SNDFX))
- md_hardchn=md_sfxchn;
- else
- md_hardchn=0;
- if (!(md_mode & DMODE_SOFT_MUSIC)) md_hardchn += md_sngchn;
- while (md_hardchn>limit) {
- if (++t & 1) {
- if (!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>4)) md_sfxchn--;
- } else {
- if (!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>8)) md_sngchn--;
- }
- if (!(md_mode & DMODE_SOFT_SNDFX))
- md_hardchn=md_sfxchn;
- else
- md_hardchn=0;
- if (!(md_mode & DMODE_SOFT_MUSIC))
- md_hardchn+=md_sngchn;
- }
- md_numchn=md_hardchn+md_softchn;
- }
- /* Limits the number of hardware voices to the specified amount.
- This function should only be used by the low-level drivers. */
- static void LimitSoftVoices(int limit)
- {
- int t=0;
- if ((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>limit)) md_sfxchn=limit;
- if ((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>limit)) md_sngchn=limit;
- if (md_mode & DMODE_SOFT_SNDFX)
- md_softchn=md_sfxchn;
- else
- md_softchn=0;
- if (md_mode & DMODE_SOFT_MUSIC) md_softchn+=md_sngchn;
- while (md_softchn>limit) {
- if (++t & 1) {
- if ((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>4)) md_sfxchn--;
- } else {
- if ((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>8)) md_sngchn--;
- }
- if (!(md_mode & DMODE_SOFT_SNDFX))
- md_softchn=md_sfxchn;
- else
- md_softchn=0;
- if (!(md_mode & DMODE_SOFT_MUSIC))
- md_softchn+=md_sngchn;
- }
- md_numchn=md_hardchn+md_softchn;
- }
- /* Note: 'type' indicates whether the returned value should be for music or for
- sound effects. */
- ULONG MD_SampleSpace(int type)
- {
- if(type==MD_MUSIC)
- type=(md_mode & DMODE_SOFT_MUSIC)?MD_SOFTWARE:MD_HARDWARE;
- else if(type==MD_SNDFX)
- type=(md_mode & DMODE_SOFT_SNDFX)?MD_SOFTWARE:MD_HARDWARE;
- return md_driver->FreeSampleSpace(type);
- }
- ULONG MD_SampleLength(int type,SAMPLE* s)
- {
- if(type==MD_MUSIC)
- type=(md_mode & DMODE_SOFT_MUSIC)?MD_SOFTWARE:MD_HARDWARE;
- else
- if(type==MD_SNDFX)
- type=(md_mode & DMODE_SOFT_SNDFX)?MD_SOFTWARE:MD_HARDWARE;
- return md_driver->RealSampleLength(type,s);
- }
- MIKMODAPI CHAR* MikMod_InfoDriver(void)
- {
- int t,len=0;
- MDRIVER *l;
- CHAR *list=NULL;
- MUTEX_LOCK(lists);
- /* compute size of buffer */
- for(l=firstdriver;l;l=l->next)
- len+=4+(l->next?1:0)+strlen(l->Version);
- if(len)
- if((list=_mm_malloc(len*sizeof(CHAR)))) {
- list[0]=0;
- /* list all registered device drivers : */
- for(t=1,l=firstdriver;l;l=l->next,t++)
- sprintf(list,(l->next)?"%s%2d %sn":"%s%2d %s",
- list,t,l->Version);
- }
- MUTEX_UNLOCK(lists);
- return list;
- }
- void _mm_registerdriver(struct MDRIVER* drv)
- {
- MDRIVER *cruise = firstdriver;
- /* don't register a MISSING() driver */
- if ((drv->Name) && (drv->Version)) {
- if (cruise) {
- while (cruise->next) cruise = cruise->next;
- cruise->next = drv;
- } else
- firstdriver = drv;
- }
- }
- MIKMODAPI void MikMod_RegisterDriver(struct MDRIVER* drv)
- {
- /* if we try to register an invalid driver, or an already registered driver,
- ignore this attempt */
- if ((!drv)||(drv->next)||(!drv->Name))
- return;
- MUTEX_LOCK(lists);
- _mm_registerdriver(drv);
- MUTEX_UNLOCK(lists);
- }
- MIKMODAPI int MikMod_DriverFromAlias(CHAR *alias)
- {
- int rank=1;
- MDRIVER *cruise;
- MUTEX_LOCK(lists);
- cruise=firstdriver;
- while(cruise) {
- if (cruise->Alias) {
- if (!(strcasecmp(alias,cruise->Alias))) break;
- rank++;
- }
- cruise=cruise->next;
- }
- if(!cruise) rank=0;
- MUTEX_UNLOCK(lists);
- return rank;
- }
- MIKMODAPI MDRIVER *MikMod_DriverByOrdinal(int ordinal)
- {
- MDRIVER *cruise;
- /* Allow only driver ordinals > 0 */
- if (!ordinal)
- return 0;
- MUTEX_LOCK(lists);
- cruise = firstdriver;
- while (cruise && --ordinal)
- cruise = cruise->next;
- MUTEX_UNLOCK(lists);
- return cruise;
- }
- SWORD MD_SampleLoad(SAMPLOAD* s, int type)
- {
- SWORD result;
- if(type==MD_MUSIC)
- type=(md_mode & DMODE_SOFT_MUSIC)?MD_SOFTWARE:MD_HARDWARE;
- else if(type==MD_SNDFX)
- type=(md_mode & DMODE_SOFT_SNDFX)?MD_SOFTWARE:MD_HARDWARE;
- SL_Init(s);
- result=md_driver->SampleLoad(s,type);
- SL_Exit(s);
- return result;
- }
- void MD_SampleUnload(SWORD handle)
- {
- md_driver->SampleUnload(handle);
- }
- MIKMODAPI MikMod_player_t MikMod_RegisterPlayer(MikMod_player_t player)
- {
- MikMod_player_t result;
- MUTEX_LOCK(vars);
- result=md_player;
- md_player=player;
- MUTEX_UNLOCK(vars);
- return result;
- }
- MIKMODAPI void MikMod_Update(void)
- {
- MUTEX_LOCK(vars);
- if(isplaying) {
- if((!pf)||(!pf->forbid))
- md_driver->Update();
- else {
- if (md_driver->Pause)
- md_driver->Pause();
- }
- }
- MUTEX_UNLOCK(vars);
- }
- void Voice_SetVolume_internal(SBYTE voice,UWORD vol)
- {
- ULONG tmp;
- if((voice<0)||(voice>=md_numchn)) return;
- /* range checks */
- if(md_musicvolume>128) md_musicvolume=128;
- if(md_sndfxvolume>128) md_sndfxvolume=128;
- if(md_volume>128) md_volume=128;
- tmp=(ULONG)vol*(ULONG)md_volume*
- ((voice<md_sngchn)?(ULONG)md_musicvolume:(ULONG)md_sndfxvolume);
- md_driver->VoiceSetVolume(voice,tmp/16384UL);
- }
- MIKMODAPI void Voice_SetVolume(SBYTE voice,UWORD vol)
- {
- MUTEX_LOCK(vars);
- Voice_SetVolume_internal(voice,vol);
- MUTEX_UNLOCK(vars);
- }
- MIKMODAPI UWORD Voice_GetVolume(SBYTE voice)
- {
- UWORD result=0;
- MUTEX_LOCK(vars);
- if((voice>=0)&&(voice<md_numchn))
- result=md_driver->VoiceGetVolume(voice);
- MUTEX_UNLOCK(vars);
- return result;
- }
- void Voice_SetFrequency_internal(SBYTE voice,ULONG frq)
- {
- if((voice<0)||(voice>=md_numchn)) return;
- if((md_sample[voice])&&(md_sample[voice]->divfactor))
- frq/=md_sample[voice]->divfactor;
- md_driver->VoiceSetFrequency(voice,frq);
- }
- MIKMODAPI void Voice_SetFrequency(SBYTE voice,ULONG frq)
- {
- MUTEX_LOCK(vars);
- Voice_SetFrequency_internal(voice,frq);
- MUTEX_UNLOCK(vars);
- }
- MIKMODAPI ULONG Voice_GetFrequency(SBYTE voice)
- {
- ULONG result=0;
- MUTEX_LOCK(vars);
- if((voice>=0)&&(voice<md_numchn))
- result=md_driver->VoiceGetFrequency(voice);
- MUTEX_UNLOCK(vars);
- return result;
- }
- void Voice_SetPanning_internal(SBYTE voice,ULONG pan)
- {
- if((voice<0)||(voice>=md_numchn)) return;
- if(pan!=PAN_SURROUND) {
- if(md_pansep>128) md_pansep=128;
- if(md_mode & DMODE_REVERSE) pan=255-pan;
- pan = (((SWORD)(pan-128)*md_pansep)/128)+128;
- }
- md_driver->VoiceSetPanning(voice, pan);
- }
- MIKMODAPI void Voice_SetPanning(SBYTE voice,ULONG pan)
- {
- #ifdef MIKMOD_DEBUG
- if((pan!=PAN_SURROUND)&&((pan<0)||(pan>255)))
- fprintf(stderr,"rVoice_SetPanning called with pan=%ldn",(long)pan);
- #endif
- MUTEX_LOCK(vars);
- Voice_SetPanning_internal(voice,pan);
- MUTEX_UNLOCK(vars);
- }
- MIKMODAPI ULONG Voice_GetPanning(SBYTE voice)
- {
- ULONG result=PAN_CENTER;
- MUTEX_LOCK(vars);
- if((voice>=0)&&(voice<md_numchn))
- result=md_driver->VoiceGetPanning(voice);
- MUTEX_UNLOCK(vars);
- return result;
- }
- void Voice_Play_internal(SBYTE voice,SAMPLE* s,ULONG start)
- {
- ULONG repend;
- if((voice<0)||(voice>=md_numchn)) return;
- md_sample[voice]=s;
- repend=s->loopend;
- if(s->flags&SF_LOOP)
- /* repend can't be bigger than size */
- if(repend>s->length) repend=s->length;
- md_driver->VoicePlay(voice,s->handle,start,s->length,s->loopstart,repend,s->flags);
- }
- MIKMODAPI void Voice_Play(SBYTE voice,SAMPLE* s,ULONG start)
- {
- if(start>s->length) return;
- MUTEX_LOCK(vars);
- Voice_Play_internal(voice,s,start);
- MUTEX_UNLOCK(vars);
- }
- void Voice_Stop_internal(SBYTE voice)
- {
- if((voice<0)||(voice>=md_numchn)) return;
- if(voice>=md_sngchn)
- /* It is a sound effects channel, so flag the voice as non-critical! */
- sfxinfo[voice-md_sngchn]=0;
- md_driver->VoiceStop(voice);
- }
- MIKMODAPI void Voice_Stop(SBYTE voice)
- {
- MUTEX_LOCK(vars);
- Voice_Stop_internal(voice);
- MUTEX_UNLOCK(vars);
- }
- BOOL Voice_Stopped_internal(SBYTE voice)
- {
- if((voice<0)||(voice>=md_numchn)) return 0;
- return(md_driver->VoiceStopped(voice));
- }
- MIKMODAPI BOOL Voice_Stopped(SBYTE voice)
- {
- BOOL result;
- MUTEX_LOCK(vars);
- result=Voice_Stopped_internal(voice);
- MUTEX_UNLOCK(vars);
- return result;
- }
- MIKMODAPI SLONG Voice_GetPosition(SBYTE voice)
- {
- SLONG result=0;
- MUTEX_LOCK(vars);
- if((voice>=0)&&(voice<md_numchn)) {
- if (md_driver->VoiceGetPosition)
- result=(md_driver->VoiceGetPosition(voice));
- else
- result=-1;
- }
- MUTEX_UNLOCK(vars);
- return result;
- }
- 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: */