gc_result ga_mixer_dispatch(ga_Mixer* in_mixer) { ga_Mixer* m = in_mixer; gc_Link* link = m->dispatchList.next; while(link != &m->dispatchList) { gc_Link* oldLink = link; ga_Handle* oldHandle = (ga_Handle*)oldLink->data; link = link->next; /* Remove finished handles and call callbacks */ if(ga_handle_destroyed(oldHandle)) { if(!oldHandle->mixLink.next) { /* NOTES ABOUT THREADING POLICY WITH REGARD TO LINKED LISTS: */ /* Only a single thread may iterate through any list */ /* The thread that unlinks must be the only thread that iterates through the list */ /* A single auxiliary thread may link(), but must mutex-lock to avoid link/unlink collisions */ gc_mutex_lock(m->dispatchMutex); gc_list_unlink(&oldHandle->dispatchLink); gc_mutex_unlock(m->dispatchMutex); gaX_handle_cleanup(oldHandle); } } else if(oldHandle->callback && ga_handle_finished(oldHandle)) { oldHandle->callback(oldHandle, oldHandle->context); oldHandle->callback = 0; oldHandle->context = 0; } } return GC_SUCCESS; }
gc_int32 gauX_tell_jump_pop(gc_Link* in_head) { gau_TellJumpLink* link; if(in_head->next == in_head) return 0; link = (gau_TellJumpLink*)in_head->next; gc_list_unlink((gc_Link*)link); gcX_ops->freeFunc(link); return 1; }
gc_result ga_mixer_mix(ga_Mixer* in_mixer, void* out_buffer) { gc_int32 i; ga_Mixer* m = in_mixer; gc_Link* link; gc_int32 end = m->numSamples * m->format.numChannels; ga_Format* fmt = &m->format; gc_int32 mixSampleSize = ga_format_sampleSize(&m->mixFormat); memset(&m->mixBuffer[0], 0, m->numSamples * mixSampleSize); link = m->mixList.next; while(link != &m->mixList) { ga_Handle* h = (ga_Handle*)link->data; gc_Link* oldLink = link; link = link->next; gaX_mixer_mix_handle(m, (ga_Handle*)h, m->numSamples); if(ga_handle_finished(h)) { gc_mutex_lock(m->mixMutex); gc_list_unlink(oldLink); gc_mutex_unlock(m->mixMutex); } } switch(fmt->bitsPerSample) /* mixBuffer will already be correct bps */ { case 8: { gc_int8* mix = (gc_int8*)out_buffer; for(i = 0; i < end; ++i) { gc_int32 sample = m->mixBuffer[i]; mix[i] = (gc_int8)(sample > -128 ? (sample < 127 ? sample : 127) : -128); } break; } case 16: { gc_int16* mix = (gc_int16*)out_buffer; for(i = 0; i < end; ++i) { gc_int32 sample = m->mixBuffer[i]; mix[i] = (gc_int16)(sample > -32768 ? (sample < 32767 ? sample : 32767) : -32768); } break; } } return GC_SUCCESS; }
gc_int32 gauX_tell_jump_process(gc_Link* in_head, gc_int32 in_advance) { gc_int32 ret = 0; gau_TellJumpLink* link = (gau_TellJumpLink*)in_head->next; while((gc_Link*)link != in_head) { gau_TellJumpLink* oldLink = link; link = (gau_TellJumpLink*)link->link.next; oldLink->data.pos -= in_advance; if(oldLink->data.pos <= 0) { ret += oldLink->data.delta; gc_list_unlink((gc_Link*)oldLink); } } return ret; }
void ga_stream_manager_buffer(ga_StreamManager* in_mgr) { gc_Link* link = in_mgr->streamList.next; while(link != &in_mgr->streamList) { gc_int32 streamDead; gaX_StreamLink* streamLink; streamLink = (gaX_StreamLink*)link->data; link = link->next; streamDead = gaX_stream_link_produce(streamLink); if(streamDead) { gc_mutex_lock(in_mgr->streamListMutex); gc_list_unlink((gc_Link*)streamLink); gc_mutex_unlock(in_mgr->streamListMutex); gaX_stream_link_release(streamLink); } } }