/** * Initialize platform level services. * * \note This must be called from the main thread due to issues with the devices * we use via the WINAPI, MCI (cdaudio, mixer etc) on the WIN32 platform. */ void Sys_Init(void) { uint startTime; Con_Message("Setting up platform state..."); startTime = (verbose >= 2? Timer_RealMilliseconds() : 0); VERBOSE( Con_Message("Initializing Audio subsystem...") ) S_Init(); #ifdef DENG_CATCH_SIGNALS // Register handler for abnormal situations (in release build). signal(SIGSEGV, handler); signal(SIGTERM, handler); signal(SIGILL, handler); signal(SIGFPE, handler); signal(SIGILL, handler); signal(SIGABRT, handler); #endif #ifndef WIN32 // We are not worried about broken pipes. When a TCP connection closes, // we prefer to receive an error code instead of a signal. signal(SIGPIPE, SIG_IGN); #endif VERBOSE( Con_Message("Initializing Network subsystem...") ) N_Init(); VERBOSE2( Con_Message("Sys_Init: Completed in %.2f seconds.", (Timer_RealMilliseconds() - startTime) / 1000.0f) ); }
/* * Remove stopped logical sounds from the hash. */ void Sfx_PurgeLogical(void) { static uint lastTime = 0; uint i, nowTime = Timer_RealMilliseconds(); logicsound_t *it, *next; if(nowTime - lastTime < PURGE_INTERVAL) { // It's too early. return; } lastTime = nowTime; // Check all sounds in the hash. for(i = 0; i < LOGIC_HASH_SIZE; i++) { for(it = logicHash[i].first; it; it = next) { next = it->next; /*#ifdef _DEBUG Con_Printf("LS:%i orig=%i(%p) %s\n", it->id, it->origin? it->origin->thinker.id : 0, it->origin, it->isRepeating? "[repeat]" : ""); #endif */ if(!it->isRepeating && it->endTime < nowTime) { // This has stopped. Sfx_DestroyLogical(it); } } } }
void Sys_BlockUntilRealTime(uint realTimeMs) { uint remaining = realTimeMs - Timer_RealMilliseconds(); if(remaining > 50) { // Target time is in the past; or the caller is attempting to wait for // too long a time. return; } while(Timer_RealMilliseconds() < realTimeMs) { // Do nothing; don't yield execution. We want to exit here at the // precise right moment. } }
void DD_WaitForOptimalUpdateTime(void) { // All times are in milliseconds. static uint prevUpdateTime = 0; uint nowTime, elapsed = 0; uint targetUpdateTime; // optimalDelta is integer on purpose: we're measuring time at a 1 ms // accuracy, so we can't use fractions of a millisecond. const uint optimalDelta = (maxFrameRate > 0? 1000/maxFrameRate : 1); if(Sys_IsShuttingDown()) return; // No need for finesse. // This is when we would ideally like to make the update. targetUpdateTime = prevUpdateTime + optimalDelta; // Check the current time. nowTime = Timer_RealMilliseconds(); elapsed = nowTime - prevUpdateTime; if(elapsed < optimalDelta) { uint needSleepMs = optimalDelta - elapsed; // We need to wait until the optimal time has passed. if(needSleepMs > 5) { // Longer sleep, yield to other threads. Sys_Sleep(needSleepMs - 3); // Leave some room for inaccuracies. } // Attempt to make sure we really wait until the optimal time. Sys_BlockUntilRealTime(targetUpdateTime); nowTime = Timer_RealMilliseconds(); elapsed = nowTime - prevUpdateTime; } // The time for this update. prevUpdateTime = nowTime; timeDeltaStatistics((int)elapsed - (int)optimalDelta); }
/** * Buffer streamer. Called by the Sfx refresh thread. * @param buf Sound buffer. */ void DS_Dummy_SFX_Refresh(sfxbuffer_t* buf) { // Can only be done if there is a sample and the buffer is playing. if(!buf || !buf->sample || !(buf->flags & SFXBF_PLAYING)) return; // Have we passed the predicted end of sample? if(!(buf->flags & SFXBF_REPEAT) && Timer_RealMilliseconds() >= buf->endTime) { // Time for the sound to stop. DS_Dummy_SFX_Stop(buf); } }
void Net_SendPing(int player, int count) { client_t *cl = clients + player; // Valid destination? if((player == consolePlayer) || (isClient && player)) return; if(count) { // We can't start a new ping run until the old one is done. if(cl->ping.sent) return; // Start a new ping session. if(count > MAX_PINGS) count = MAX_PINGS; cl->ping.current = 0; cl->ping.total = count; } else { // Continue or finish the current pinger. if(++cl->ping.current >= cl->ping.total) { // We're done. cl->ping.sent = 0; // Print a summary (average ping, loss %). Net_ShowPingSummary(netBuffer.player); return; } } // Send a new ping. Msg_Begin(PKT_PING); cl->ping.sent = Timer_RealMilliseconds(); Writer_WriteUInt32(msgWriter, cl->ping.sent); Msg_End(); // Update the length of the message. netBuffer.player = player; N_SendPacket(10000); }
void DS_Dummy_SFX_Play(sfxbuffer_t* buf) { // Playing is quite impossible without a sample. if(!buf || !buf->sample) return; // Do we need to reload? if(buf->flags & SFXBF_RELOAD) DS_Dummy_SFX_Load(buf, buf->sample); // The sound starts playing now? if(!(buf->flags & SFXBF_PLAYING)) { // Calculate the end time (milliseconds). buf->endTime = Timer_RealMilliseconds() + DS_DummyBufferLength(buf); } // The buffer is now playing. buf->flags |= SFXBF_PLAYING; }
/* * Returns true if the sound is currently playing somewhere in the world. * It doesn't matter if it's audible or not. * * id=0: true if any sounds are playing using the specified origin */ boolean Sfx_IsPlaying(int id, mobj_t *origin) { uint nowTime = Timer_RealMilliseconds(); logicsound_t *it; int i; if(id) { for(it = Sfx_LogicHash(id)->first; it; it = it->next) { if(it->id == id && it->origin == origin && (it->endTime > nowTime || it->isRepeating)) { // This one is still playing. return true; } } } else if(origin) { // Check if the origin is playing any sound. for(i = 0; i < LOGIC_HASH_SIZE; i++) { for(it = logicHash[i].first; it; it = it->next) { if(it->origin == origin && (it->endTime > nowTime || it->isRepeating)) { // This one is playing. return true; } } } } // The sound was not found. return false; }
// Called when a ping packet comes in. void Net_PingResponse(void) { client_t* cl = &clients[netBuffer.player]; int time = Reader_ReadUInt32(msgReader); // Is this a response to our ping? if(time == cl->ping.sent) { // Record the time and send the next ping. cl->ping.times[cl->ping.current] = (Timer_RealMilliseconds() - time) / 1000.0f; // Show a notification. /*Con_Printf( "Ping to plr %i: %.0f ms.\n", netbuffer.player, cl->ping.times[cl->ping.current] * 1000); */ // Send the next ping. Net_SendPing(netBuffer.player, 0); } else { // Not ours, just respond. Net_SendBuffer(netBuffer.player, 10000); } }
/* * The sound is entered into the list of playing sounds. Called when a * 'world class' sound is started, regardless of whether it's actually * started on the local system. */ void Sfx_StartLogical(int id, mobj_t *origin, boolean isRepeating) { logicsound_t *node; uint length = (isRepeating ? 1 : Sfx_GetSoundLength(id)); if(!length) { // This is not a valid sound. return; } if(origin && sfxOneSoundPerEmitter) { // Stop all previous sounds from this origin (only one per origin). Sfx_StopLogical(0, origin); } id &= ~DDSF_FLAG_MASK; node = Sfx_CreateLogical(id); node->origin = origin; node->isRepeating = isRepeating; node->endTime = Timer_RealMilliseconds() + length; }