static void midi_dispose_buffer(MidiBuffer * node, const char * caller) { MMRESULT rv; if (node->prepared) { rv = midiOutUnprepareHeader( (HMIDIOUT) midiStream, &node->hdr, sizeof(MIDIHDR) ); if (rv != MMSYSERR_NOERROR) { midi_error(rv, "WinMM %s/midi_dispose_buffer midiOutUnprepareHeader", caller); } node->prepared = FALSE; } if (midiThread) { // remove the node from the activeMidiBuffers list LL_Remove( node, next, prev ); // when playing, we keep the buffers LL_Add( (MidiBuffer*) &spareMidiBuffers, node, next, prev ); //fprintf(stderr, "WinMM %s/midi_dispose_buffer recycling buffer %p\n", caller, node); } else { // when not, we throw them away free(node); //fprintf(stderr, "WinMM %s/midi_dispose_buffer freeing buffer %p\n", caller, node); } }
/** Remove a widget from a screen. * \param s Screen to remove the widget \c w from. * \param w Widget to be removed from \c s. * \retval <0 Error. * \retval 0 Success. */ int screen_remove_widget(Screen *s, Widget *w) { debug(RPT_DEBUG, "%s(s=[%.40s], widget=[%.40s])", __FUNCTION__, s->id, w->id); LL_Remove(s->widgetlist, (void *) w, NEXT); return 0; }
void LL_DeleteList(LINKED_LIST_t* linkedList) { LIST_NODE_t* node; node = linkedList->first; while(node) { LL_Remove(linkedList, node); node = linkedList->first; } }
int screenlist_remove(Screen *s) { debug(RPT_DEBUG, "%s(s=[%.40s])", __FUNCTION__, s->id); if (!screenlist) return -1; /* Are we trying to remove the current screen ? */ if (s == current_screen) { screenlist_goto_next(); if (s == current_screen) { /* Hmm, no other screen had same priority */ void *res = LL_Remove(screenlist, s, NEXT); /* And now once more */ screenlist_goto_next(); return (res == NULL) ? -1 : 0; } } return (LL_Remove(screenlist, s, NEXT) == NULL) ? -1 : 0; }
void LL_DeleteListAndData(LINKED_LIST_t* linkedList) { LIST_NODE_t* node; node = linkedList->first; while(node) { LL_Free(node->data); LL_Remove(linkedList, node); node = linkedList->first; } }
void* LL_PopData(LINKED_LIST_t* linkedList) { LIST_NODE_t* retNode; void* data = NULL; retNode = linkedList->first; if( retNode ) { data = retNode->data; } LL_Remove(linkedList, retNode); return data; }
VoiceNode *MV_AllocVoice(int32_t priority) { VoiceNode *voice, *node; DisableInterrupts(); // Check if we have any free voices if (LL_Empty(&VoicePool, next, prev)) { // check if we have a higher priority than a voice that is playing. for (voice = node = VoiceList.next; node != &VoiceList; node = node->next) { if (node->priority < voice->priority) voice = node; } if (priority >= voice->priority && voice != &VoiceList && voice->handle >= MV_MINVOICEHANDLE) MV_Kill(voice->handle); if (LL_Empty(&VoicePool, next, prev)) { // No free voices RestoreInterrupts(); return NULL; } } voice = VoicePool.next; LL_Remove(voice, next, prev); RestoreInterrupts(); int32_t vhan = MV_MINVOICEHANDLE; // Find a free voice handle do { if (++vhan < MV_MINVOICEHANDLE || vhan > MV_MaxVoices) vhan = MV_MINVOICEHANDLE; } while (MV_VoicePlaying(vhan)); voice->handle = vhan; return voice; }
int remove_access_list (int num, int permit, prefix_t *prefix, prefix_t *wildcard, int exact, int refine) { condition_t *condition; if (num < 0 || num >= MAX_ALIST) return (-1); if (access_list[num] == NULL) { return (-1); } condition = find_access_list (num, permit, prefix, wildcard, exact, refine); if (condition == NULL) return (-1); Deref_Prefix (condition->prefix); Deref_Prefix (condition->wildcard); LL_Remove (access_list[num], condition); return (LL_GetCount (access_list[num])); }
/* ================= FreeEdict Marks the edict as free ================= */ void Level::FreeEdict( gentity_t *ed ) { gclient_t *client; assert( ed != &free_edicts ); // unlink from world gi.unlinkentity ( ed ); assert( ed->next ); assert( ed->prev ); if ( next_edict == ed ) { next_edict = ed->next; } LL_Remove( ed, next, prev ); assert( ed->next == ed ); assert( ed->prev == ed ); assert( free_edicts.next ); assert( free_edicts.prev ); client = ed->client; memset( ed, 0, sizeof( *ed ) ); ed->client = client; ed->freetime = time; ed->inuse = false; ed->s.number = ed - g_entities; assert( free_edicts.next ); assert( free_edicts.prev ); LL_Add( &free_edicts, ed, next, prev ); assert( ed->next ); assert( ed->prev ); }
static void midi_free_buffers(void) { MidiBuffer *node, *next; //fprintf(stderr, "waiting for active buffers to return\n"); while (!LL_ListEmpty(&activeMidiBuffers, next, prev)) { // wait for Windows to finish with all the buffers queued midi_gc_buffers(); //fprintf(stderr, "waiting...\n"); Sleep(10); } //fprintf(stderr, "waiting over\n"); for ( node = spareMidiBuffers.next; node != &spareMidiBuffers; node = next ) { next = node->next; LL_Remove( node, next, prev ); free(node); //fprintf(stderr, "WinMM midi_free_buffers freeing buffer %p\n", node); } assert(currentMidiBuffer == 0); }
static void MV_StopVoice(VoiceNode *voice) { DisableInterrupts(); // move the voice from the play list to the free list LL_Remove(voice, next, prev); LL_Add((VoiceNode*) &VoicePool, voice, next, prev); RestoreInterrupts(); switch (voice->wavetype) { #ifdef HAVE_VORBIS case FMT_VORBIS: MV_ReleaseVorbisVoice(voice); break; #endif #ifdef HAVE_FLAC case FMT_FLAC: MV_ReleaseFLACVoice(voice); break; #endif case FMT_XA: MV_ReleaseXAVoice(voice); break; default: break; } voice->handle = 0; }
static int LOADDS GUSWAVE_DebugCallBack ( int reason, int voice, unsigned char **buf, unsigned long *size ) { VoiceNode *Voice; // this function is called from an interrupt // remember not to make any DOS or BIOS calls from here // also don't call any C library functions unless you are sure that // they are reentrant // restore our DS register if ( VoiceStatus[ voice ].playing == FALSE ) { // DB_printf( "GUS Voice %d not playing.\n", voice ); DB_printf( "GUS Voice " ); DB_PrintNum( voice ); DB_printf( " not playing.\n" ); return( DIG_DONE ); } if ( reason == DIG_MORE_DATA ) { Voice = VoiceStatus[ voice ].Voice; // DB_printf( "Voice %d : More data -- ", Voice ); DB_printf( "Voice " ); DB_PrintNum( voice ); DB_printf( " : More data -- " ); if ( Voice != NULL ) { if ( Voice->Playing ) { GUSWAVE_GetNextVOCBlock( Voice ); if ( Voice->Playing ) { // DB_printf( "More data -- size = %u blocklength = %u\n", // Voice->length, Voice->BlockLength ); DB_printf( "More data -- size = " ); DB_PrintNum( Voice->length ); DB_printf( " blocklength = " ); DB_PrintNum( Voice->BlockLength ); DB_printf( "\n" ); *buf = Voice->sound; *size = Voice->length; return( DIG_MORE_DATA ); } else { DB_printf( "Voice done.\n" ); } } else { DB_printf( "Voice not active.\n" ); } } else { DB_printf( " NULL Voice\n" ); } return( DIG_DONE ); } if ( reason == DIG_DONE ) { VoiceStatus[ voice ].playing = FALSE; Voice = VoiceStatus[ voice ].Voice; // DB_printf( "Voice %d : Done -- ", Voice ); DB_printf( "Voice " ); DB_PrintNum( voice ); DB_printf( " : Done -- " ); if ( Voice != NULL ) { DB_printf( "Ok\n" ); Voice->Active = FALSE; Voice->Playing = FALSE; // I'm commenting this out because a -1 could cause a crash if it // is sent to the GF1 code. This shouldn't be necessary since // Active should be false when GF1voice is -1, but this is just // a precaution. Adjust the pan on the wrong voice is a lot // more pleasant than a crash! // Voice->GF1voice = -1; LL_Remove( VoiceNode, &VoiceList, Voice ); LL_AddToTail( VoiceNode, &VoicePool, Voice ); } else { DB_printf( "Null voice\n" ); } if ( GUSWAVE_CallBackFunc ) { GUSWAVE_CallBackFunc( Voice->callbackval ); } } return( DIG_DONE ); }
static int LOADDS GUSWAVE_CallBack ( int reason, int voice, unsigned char **buf, unsigned long *size ) { VoiceNode *Voice; playbackstatus status; // this function is called from an interrupt // remember not to make any DOS or BIOS calls from here // also don't call any C library functions unless you are sure that // they are reentrant // restore our DS register if ( VoiceStatus[ voice ].playing == FALSE ) { return( DIG_DONE ); } if ( reason == DIG_MORE_DATA ) { // SetBorderColor(16); Voice = VoiceStatus[ voice ].Voice; if ( ( Voice != NULL ) && ( Voice->Playing ) ) /* { *buf = ( unsigned char * )GUS_Silence16; *size = 1024; SetBorderColor(0); return( DIG_MORE_DATA ); } */ { status = Voice->GetSound( Voice ); if ( status != SoundDone ) { if ( ( Voice->sound == NULL ) || ( status == NoMoreData ) ) { if ( Voice->bits == 8 ) { *buf = GUS_Silence8; } else { *buf = ( unsigned char * )GUS_Silence16; } *size = 256; } else { *buf = Voice->sound; *size = Voice->length; } return( DIG_MORE_DATA ); } } // SetBorderColor(16); return( DIG_DONE ); } if ( reason == DIG_DONE ) { Voice = VoiceStatus[ voice ].Voice; VoiceStatus[ voice ].playing = FALSE; if ( Voice != NULL ) { Voice->Active = FALSE; Voice->Playing = FALSE; // I'm commenting this out because a -1 could cause a crash if it // is sent to the GF1 code. This shouldn't be necessary since // Active should be false when GF1voice is -1, but this is just // a precaution. Adjust the pan on the wrong voice is a lot // more pleasant than a crash! // Voice->GF1voice = -1; LL_Remove( VoiceNode, &VoiceList, Voice ); LL_AddToTail( VoiceNode, &VoicePool, Voice ); } if ( GUSWAVE_CallBackFunc ) { GUSWAVE_CallBackFunc( Voice->callbackval ); } } return( DIG_DONE ); }
/* ================= AllocEdict Either finds a free edict, or allocates a new one. Try to avoid reusing an entity that was recently freed, because it can cause the client to think the entity morphed into something else instead of being removed and recreated, which can cause interpolated angles and bad trails. ================= */ gentity_t *Level::AllocEdict( Entity *ent ) { int i; gentity_t *edict; if ( spawn_entnum >= 0 ) { edict = &g_entities[ spawn_entnum ]; spawn_entnum = -1; assert( !edict->inuse && !edict->entity ); // free up the entity pointer in case we took one that still exists if ( edict->inuse && edict->entity ) { delete edict->entity; } } else { edict = &g_entities[ maxclients->integer ]; for ( i = maxclients->integer; i < globals.num_entities; i++, edict++ ) { // the first couple seconds of server time can involve a lot of // freeing and allocating, so relax the replacement policy if ( !edict->inuse && ( ( edict->freetime < ( 2.0f + startTime ) ) || ( time - edict->freetime > 0.5f ) ) ) { break; } } // allow two spots for none and world if ( i == game.maxentities - 2.0f ) { // Try one more time before failing, relax timing completely edict = &g_entities[ maxclients->integer ]; for ( i = maxclients->integer; i < globals.num_entities; i++, edict++ ) { if ( !edict->inuse ) { break; } } if ( i == game.maxentities - 2.0f ) { gi.Error( ERR_DROP, "Level::AllocEdict: no free edicts" ); } } } assert( edict->next ); assert( edict->prev ); LL_Remove( edict, next, prev ); InitEdict( edict ); assert( active_edicts.next ); assert( active_edicts.prev ); LL_Add( &active_edicts, edict, next, prev ); assert( edict->next ); assert( edict->prev ); assert( edict->next != &free_edicts ); assert( edict->prev != &free_edicts ); // Tell the server about our data since we just spawned something if ( ( edict->s.number < ENTITYNUM_WORLD ) && ( globals.num_entities <= edict->s.number ) ) { globals.num_entities = edict->s.number + 1; gi.LocateGameData( g_entities, globals.num_entities, sizeof( gentity_t ), &game.clients[ 0 ].ps, sizeof( game.clients[ 0 ] ) ); } edict->entity = ent; edict->s.instanceNumber = currentInstanceNumber; currentInstanceNumber++; if ( currentInstanceNumber < 0 ) currentInstanceNumber = 0; return edict; }
/* Gets space in the buffer presently being filled. If insufficient space can be found in the buffer, what is there is flushed to the stream and a new buffer large enough is allocated. Returns a pointer to starting writing at in 'data'. */ static BOOL midi_get_buffer(int length, unsigned char ** data) { int datalen; MidiBuffer * node; // determine the space to alloc. // the size of a MIDIEVENT is 3*sizeof(DWORD) = 12. // short messages need only that amount of space. // long messages need additional space equal to the length of // the message, padded to 4 bytes if (length <= 3) { datalen = 12; } else { datalen = 12 + length; if ((datalen & 3) > 0) { datalen += 4 - (datalen & 3); } } if (!midiThread) { assert(currentMidiBuffer == 0); } if (currentMidiBuffer && (currentMidiBuffer->hdr.dwBufferLength - currentMidiBuffer->hdr.dwBytesRecorded) >= datalen) { // there was enough space in the current buffer, so hand that back midi_setup_event(length, data); currentMidiBuffer->hdr.dwBytesRecorded += datalen; return TRUE; } if (currentMidiBuffer) { // not enough space in the current buffer to accommodate the // new data, so flush it to the stream midi_flush_current_buffer(); currentMidiBuffer = 0; } // check if there's a spare buffer big enough to hold the message if (midiThread) { for ( node = spareMidiBuffers.next; node != &spareMidiBuffers; node = node->next ) { if (node->hdr.dwBufferLength >= datalen) { // yes! LL_Remove( node, next, prev ); node->hdr.dwBytesRecorded = 0; memset(node->hdr.lpData, 0, node->hdr.dwBufferLength); currentMidiBuffer = node; //fprintf(stderr, "WinMM midi_get_buffer fetched buffer %p\n", node); break; } } } if (!currentMidiBuffer) { // there were no spare buffers, or none were big enough, so // allocate a new one int size; if (midiThread) { // playing a file, so allocate a buffer for more than // one event size = max(MIDI_BUFFER_SPACE, datalen); } else { // not playing a file, so allocate just a buffer for // the event we'll be sending immediately size = datalen; } node = (MidiBuffer *) malloc( sizeof(MidiBuffer) + size ); if (node == 0) { return FALSE; } memset(node, 0, sizeof(MidiBuffer) + datalen); node->hdr.dwUser = (DWORD_PTR) node; node->hdr.lpData = (LPSTR) ((intptr_t)node + sizeof(MidiBuffer)); node->hdr.dwBufferLength = size; node->hdr.dwBytesRecorded = 0; currentMidiBuffer = node; //fprintf(stderr, "WinMM midi_get_buffer allocated buffer %p\n", node); } midi_setup_event(length, data); currentMidiBuffer->hdr.dwBytesRecorded += datalen; return TRUE; }
/*--------------------------------------------------------------------- JBF: no synchronisation happens inside MV_ServiceVoc nor the supporting functions it calls. This would cause a deadlock between the mixer thread in the driver vs the nested locking in the user-space functions of MultiVoc. The call to MV_ServiceVoc is synchronised in the driver. ---------------------------------------------------------------------*/ static void MV_ServiceVoc(void) { // Toggle which buffer we'll mix next if (++MV_MixPage >= MV_NumberOfBuffers) MV_MixPage -= MV_NumberOfBuffers; if (MV_ReverbLevel == 0) { // Initialize buffer //Commented out so that the buffer is always cleared. //This is so the guys at Echo Speech can mix into the //buffer even when no sounds are playing. if (!MV_BufferEmpty[MV_MixPage]) { Bmemset(MV_MixBuffer[MV_MixPage], 0, MV_BufferSize); MV_BufferEmpty[ MV_MixPage ] = TRUE; } } else { char const *const end = MV_MixBuffer[0] + MV_BufferLength; char *dest = MV_MixBuffer[MV_MixPage]; char const *source = MV_MixBuffer[MV_MixPage] - MV_ReverbDelay; if (source < MV_MixBuffer[ 0 ]) source += MV_BufferLength; int32_t length = MV_BufferSize; while (length > 0) { int const count = (source + length > end) ? (end - source) : length; MV_16BitReverb(source, dest, MV_ReverbTable, count / 2); // if we go through the loop again, it means that we've wrapped around the buffer source = MV_MixBuffer[ 0 ]; dest += count; length -= count; } } // Play any waiting voices //DisableInterrupts(); VoiceNode *voice; if (!VoiceList.next || (voice = VoiceList.next) == &VoiceList) return; int iter = 0; VoiceNode *next; do { next = voice->next; if (++iter > MV_MaxVoices && MV_Printf) MV_Printf("more iterations than voices! iter: %d\n",iter); if (voice->Paused) continue; MV_BufferEmpty[ MV_MixPage ] = FALSE; MV_Mix(voice, MV_MixPage); // Is this voice done? if (!voice->Playing) { //JBF: prevent a deadlock caused by MV_StopVoice grabbing the mutex again //MV_StopVoice( voice ); LL_Remove(voice, next, prev); LL_Add((VoiceNode*) &VoicePool, voice, next, prev); switch (voice->wavetype) { #ifdef HAVE_VORBIS case FMT_VORBIS: MV_ReleaseVorbisVoice(voice); break; #endif #ifdef HAVE_FLAC case FMT_FLAC: MV_ReleaseFLACVoice(voice); break; #endif case FMT_XA: MV_ReleaseXAVoice(voice); break; default: break; } voice->handle = 0; if (MV_CallBackFunc) MV_CallBackFunc(voice->callbackval); } } while ((voice = next) != &VoiceList); //RestoreInterrupts(); }