diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp index 596a6dcff..eea39f0c1 100644 --- a/indra/llaudio/llaudiodecodemgr.cpp +++ b/indra/llaudio/llaudiodecodemgr.cpp @@ -685,6 +685,12 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs) mCurrentDecodep = new LLVorbisDecodeState(uuid, d_path); if (!mCurrentDecodep->initDecode()) { + LLAudioData *adp = gAudiop->getAudioData(uuid); + if(adp) + { + adp->setHasValidData(false); + adp->setHasCompletedDecode(true); + } mCurrentDecodep = NULL; } } diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index aab511ef8..62a804f9b 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -40,6 +40,9 @@ #include "llaudiodecodemgr.h" #include "llassetstorage.h" +#include +#include + // necessary for grabbing sounds from sim (implemented in viewer) extern void request_sound(const LLUUID &sound_guid); @@ -120,13 +123,11 @@ bool LLAudioEngine::init(const S32 num_channels, void* userdata) mNumChannels = num_channels; mUserData = userdata; - - allocateListener(); // Initialize the decode manager gAudioDecodeMgrp = new LLAudioDecodeMgr; - LL_INFOS("AudioEngine") << "LLAudioEngine::init() AudioEngine successfully initialized" << llendl; + LL_INFOS("AudioEngine") << "LLAudioEngine::init() AudioEngine successfully initialized" << LL_ENDL; return true; } @@ -288,6 +289,16 @@ void LLAudioEngine::updateChannels() checkStates(); } +typedef std::pair audio_source_t; +struct SourcePriorityComparator +{ + bool operator() (const audio_source_t& lhs, const audio_source_t& rhs) const + { + //Sort by priority value. If equal, sync masters get higher priority. + return lhs.second < rhs.second || (lhs.second == rhs.second && !lhs.first->isSyncMaster() && rhs.first->isSyncMaster()); + } +}; + static const F32 default_max_decode_time = .002f; // 2 ms void LLAudioEngine::idle(F32 max_decode_time) { @@ -309,18 +320,23 @@ void LLAudioEngine::idle(F32 max_decode_time) } } - F32 max_priority = -1.f; - LLAudioSource *max_sourcep = NULL; // Maximum priority source without a channel - source_map::iterator iter; - for (iter = mAllSources.begin(); iter != mAllSources.end();) + //Iterate down all queued sources. Remove finished ones, sort active ones by priority. Find highest priority 'master' source if present. + LLAudioSource *sync_masterp = NULL; //Highest priority syncmaster + LLAudioSource *sync_slavep = NULL; //Highest priority syncslave + + //Iterate over all sources. Update their decode or 'done' state, as well as their priorities. + //Also add sources that might be able to start playing to a priority queue. + //Only sources without channels, or are waiting for a syncmaster, should be added to this queue. + std::priority_queue >,SourcePriorityComparator> queue; + for (source_map::iterator iter = mAllSources.begin(); iter != mAllSources.end(); ++iter) { LLAudioSource *sourcep = iter->second; - // Update this source + //Load/decode/queue pop sourcep->update(); - sourcep->updatePriority(); - if (sourcep->isDone()) + //Done after update, as failure to load might mark source as corrupt, which causes isDone to return true. + if (sourcep->isDone()) { // The source is done playing, clean it up. delete sourcep; @@ -328,166 +344,106 @@ void LLAudioEngine::idle(F32 max_decode_time) continue; } - if (sourcep->isMuted()) + LLAudioData *adp = sourcep->getCurrentData(); + //If there is no current data at all, or if it hasn't loaded, we must skip this source. + if (!adp || !adp->getBuffer()) { - ++iter; - continue; + continue; } - if (!sourcep->getChannel() && sourcep->getCurrentBuffer()) + sourcep->updatePriority(); //Calculates current priority. 1.f=ambient. 0.f=muted. Otherwise based off of distance. + + if (sourcep->getPriority() < F_APPROXIMATELY_ZERO) { - // We could potentially play this sound if its priority is high enough. - if (sourcep->getPriority() > max_priority) + // Muted, or nothing queued, or too far, so we don't care. + continue; + } + else if(sourcep->isSyncMaster()) + { + if(!sync_masterp || sourcep->getPriority() > sync_masterp->getPriority()) { - max_priority = sourcep->getPriority(); - max_sourcep = sourcep; + sync_masterp = sourcep; } + //This is a hack. Don't add master to the queue yet. + //Add it after highest-priority sound slave is found so we can outrank its priority. + continue; } - - // Move on to the next source - iter++; - } - - // Now, do priority-based organization of audio sources. - // All channels used, check priorities. - // Find channel with lowest priority - if (max_sourcep) - { - LLAudioChannel *channelp = getFreeChannel(max_priority); - if (channelp) + else if(sourcep->isSyncSlave()) { - LL_DEBUGS("AudioEngine") << "Replacing source in channel due to priority!" << llendl; - llassert(max_sourcep->getChannel() == NULL); - - llassert(channelp->mCurrentBufferp == NULL); - channelp->setSource(max_sourcep); - - llassert(max_sourcep == channelp->getSource()); - llassert(channelp->mCurrentBufferp == max_sourcep->getCurrentBuffer()); - - if (max_sourcep->isSyncSlave()) + //Only care about syncslaves without channel, or are looping. + if(!sourcep->getChannel() || sourcep->isLoop() ) { - // A sync slave, it doesn't start playing until it's synced up with the master. - // Flag this channel as waiting for sync, and return true. - channelp->setWaiting(true); + if(!sync_slavep || sourcep->getPriority() > sync_slavep->getPriority()) + { + sync_slavep = sourcep; + } } else { - channelp->setWaiting(false); - channelp->play(); + continue; } } + else if(sourcep->getChannel()) + { + //If this is just a regular sound and is currently playing then do nothing special. + continue; + } + //Add to our queue. Highest priority will be at the front. + queue.push(std::make_pair(sourcep,sourcep->getPriority())); } - // Do this BEFORE we update the channels // Update the channels to sync up with any changes that the source made, // such as changing what sound was playing. updateChannels(); - // Update queued sounds (switch to next queued data if the current has finished playing) - for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter) + //Syncmaster must have priority greater than or equal to priority of highest priority syncslave. + if(sync_masterp && !sync_masterp->getChannel()) + { + //The case of slave priority equaling master priority is handled in the comparator (SourcePriorityComparator). + //Could have added an arbiturary small value to the priority, but the extra logic in the comparator is more correct. + if(sync_slavep) + queue.push(std::make_pair(sync_masterp, llmax(sync_slavep->getPriority(), sync_masterp->getPriority()))); + else + queue.push(std::make_pair(sync_masterp, sync_masterp->getPriority())); + } + + // Dispatch all soundsources. + bool syncmaster_started = false; + while(!queue.empty()) { // This is lame, instead of this I could actually iterate through all the sources // attached to each channel, since only those with active channels // can have anything interesting happen with their queue? (Maybe not true) - LLAudioSource *sourcep = iter->second; - if (!sourcep->mQueuedDatap || sourcep->isMuted()) + LLAudioSource *sourcep = queue.top().first; + queue.pop(); + + if (sourcep->isSyncSlave()) { - // Muted, or nothing queued, so we don't care. - continue; + //If the syncmaster hasn't just started playing, or hasn't just looped then skip this soundslave. + if(!sync_masterp || (!syncmaster_started && !(sync_masterp->getChannel() && sync_masterp->getChannel()->mLoopedThisFrame))) + continue; } LLAudioChannel *channelp = sourcep->getChannel(); - bool is_stopped = !channelp || !channelp->isPlaying(); - if (is_stopped || (sourcep->isLoop() && channelp->mLoopedThisFrame)) + + if (!channelp) { - // This sound isn't playing, so we just process move the queue - sourcep->mCurrentDatap = sourcep->mQueuedDatap; - sourcep->mQueuedDatap = NULL; + if(!(channelp = gAudiop->getFreeChannel(sourcep->getPriority()))) + continue; //No more channels. Don't abort the whole loop, however. Soundslaves might want to start up! - if(is_stopped) + //If this is the syncmaster that just started then we need to update non-playing syncslaves. + if(sourcep == sync_masterp) { - // Reset the timer so the source doesn't die. - sourcep->mAgeTimer.reset(); - // Make sure we have the buffer set up if we just decoded the data - if (sourcep->mCurrentDatap) - { - updateBufferForData(sourcep->mCurrentDatap); - } + syncmaster_started = true; } - - // Actually play the associated data. - sourcep->setupChannel(); - channelp = sourcep->getChannel(); - if (channelp) - { - channelp->updateBuffer(); - channelp->play(); - } - continue; + channelp->setSource(sourcep); //setSource calls updateBuffer and update3DPosition, and resets the source mAgeTimer } - } - // Lame, update the channels AGAIN. - // Update the channels to sync up with any changes that the source made, - // such as changing what sound was playing. - updateChannels(); - - // Hack! For now, just use a global sync master; - LLAudioSource *sync_masterp = NULL; - LLAudioChannel *master_channelp = NULL; - F32 max_sm_priority = -1.f; - for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter) - { - LLAudioSource *sourcep = iter->second; - if (sourcep->isMuted()) - { - continue; - } - if (sourcep->isSyncMaster()) - { - if (sourcep->getPriority() > max_sm_priority) - { - sync_masterp = sourcep; - master_channelp = sync_masterp->getChannel(); - max_sm_priority = sourcep->getPriority(); - } - } - } - - if (master_channelp && master_channelp->mLoopedThisFrame) - { - // Synchronize loop slaves with their masters - // Update queued sounds (switch to next queued data if the current has finished playing) - for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter) - { - LLAudioSource *sourcep = iter->second; - - if (!sourcep->isSyncSlave()) - { - // Not a loop slave, we don't need to do anything - continue; - } - - LLAudioChannel *channelp = sourcep->getChannel(); - if (!channelp) - { - // Not playing, don't need to bother. - continue; - } - - if (!channelp->isPlaying()) - { - // Now we need to check if our loop master has just looped, and - // start playback if that's the case. - if (sync_masterp->getChannel()) - { - channelp->playSynced(master_channelp); - channelp->setWaiting(false); - } - } - } + if(sourcep->isSyncSlave()) + channelp->playSynced(sync_masterp->getChannel()); + else + channelp->play(); } // Sync up everything that the audio engine needs done. @@ -500,7 +456,7 @@ void LLAudioEngine::idle(F32 max_decode_time) { if (!mBuffers[i]->mInUse && mBuffers[i]->mLastUseTimer.getElapsedTimeF32() > 30.f) { - LL_DEBUGS("AudioEngine") << "Flushing unused buffer!" << llendl; + LL_DEBUGS("AudioEngine") << "Flushing unused buffer!" << LL_ENDL; mBuffers[i]->mAudioDatap->mBufferp = NULL; delete mBuffers[i]; mBuffers[i] = NULL; @@ -529,42 +485,6 @@ void LLAudioEngine::idle(F32 max_decode_time) updateInternetStream(); } - - -bool LLAudioEngine::updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid) -{ - if (!adp) - { - return false; - } - - // Update the audio buffer first - load a sound if we have it. - // Note that this could potentially cause us to waste time updating buffers - // for sounds that actually aren't playing, although this should be mitigated - // by the fact that we limit the number of buffers, and we flush buffers based - // on priority. - if (!adp->getBuffer()) - { - if (adp->hasDecodedData()) - { - adp->load(); - } - else if (adp->hasLocalData()) - { - if (audio_uuid.notNull()) - { - gAudioDecodeMgrp->addDecodeRequest(audio_uuid); - } - } - else - { - return false; - } - } - return true; -} - - void LLAudioEngine::enableWind(bool enable) { if (enable && (!mEnableWind)) @@ -617,7 +537,7 @@ LLAudioBuffer * LLAudioEngine::getFreeBuffer() if (buffer_id >= 0) { - LL_DEBUGS("AudioEngine") << "Taking over unused buffer! max_age=" << max_age << llendl; + LL_DEBUGS("AudioEngine") << "Taking over unused buffer! max_age=" << max_age << LL_ENDL; mBuffers[buffer_id]->mAudioDatap->mBufferp = NULL; for (U32 i = 0; i < MAX_CHANNELS; i++) { @@ -652,14 +572,9 @@ LLAudioChannel * LLAudioEngine::getFreeChannel(const F32 priority) else { // Channel is allocated but not playing right now, use it. - if (!mChannels[i]->isPlaying() && !mChannels[i]->isWaiting()) + if (mChannels[i]->isFree()) { - LL_DEBUGS("AudioEngine") << "Replacing unused channel" << llendl; - mChannels[i]->cleanup(); - if (mChannels[i]->getSource()) - { - mChannels[i]->getSource()->setChannel(NULL); - } + LL_DEBUGS("AudioEngine") << "Replacing unused channel" << LL_ENDL; return mChannels[i]; } } @@ -687,7 +602,7 @@ LLAudioChannel * LLAudioEngine::getFreeChannel(const F32 priority) return NULL; } - LL_DEBUGS("AudioEngine") << "Flushing min channel" << llendl; + LL_DEBUGS("AudioEngine") << "Flushing min channel" << LL_ENDL; // Flush the minimum priority channel, and return it. min_channelp->cleanup(); return min_channelp; @@ -710,6 +625,9 @@ void LLAudioEngine::cleanupBuffer(LLAudioBuffer *bufferp) bool LLAudioEngine::preloadSound(const LLUUID &uuid) { + if(uuid.isNull()) + return false; + gAudiop->getAudioData(uuid); // We don't care about the return value, this is just to make sure // that we have an entry, which will mean that the audio engine knows about this @@ -719,10 +637,13 @@ bool LLAudioEngine::preloadSound(const LLUUID &uuid) return true; } + LL_INFOS("AudioEngine") << "Preloading system sound " << uuid << LL_ENDL; + mPreloadSystemList.push_back(uuid); + // At some point we need to have the audio/asset system check the static VFS // before it goes off and fetches stuff from the server. - //llwarns << "Used internal preload for non-local sound" << llendl; - return false; + //LL_INFOS("AudioEngine") << "Used internal preload for non-local sound" << LL_ENDL; + return true; } @@ -854,8 +775,10 @@ void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_i const S32 type, const LLVector3d &pos_global, const LLUUID source_object) // { + if(!mListenerp) + return; // Create a new source (since this can't be associated with an existing source. - //llinfos << "Localized: " << audio_uuid << llendl; + //LL_INFOS("AudioEngine") << "Localized: " << audio_uuid << LL_ENDL; if (mMuted || gain < FLT_EPSILON*2) { @@ -885,7 +808,10 @@ void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_i void LLAudioEngine::setListenerPos(LLVector3 aVec) { - mListenerp->setPosition(aVec); + if (mListenerp) + { + mListenerp->setPosition(aVec); + } } @@ -893,7 +819,7 @@ LLVector3 LLAudioEngine::getListenerPos() { if (mListenerp) { - return(mListenerp->getPosition()); + return mListenerp->getPosition(); } else { @@ -904,24 +830,37 @@ LLVector3 LLAudioEngine::getListenerPos() void LLAudioEngine::setListenerVelocity(LLVector3 aVec) { - mListenerp->setVelocity(aVec); + if (mListenerp) + { + mListenerp->setVelocity(aVec); + } } void LLAudioEngine::translateListener(LLVector3 aVec) { - mListenerp->translate(aVec); + if (mListenerp) + { + mListenerp->translate(aVec); + } } void LLAudioEngine::orientListener(LLVector3 up, LLVector3 at) { - mListenerp->orient(up, at); + if (mListenerp) + { + mListenerp->orient(up, at); + } } void LLAudioEngine::setListener(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at) { + if(!mListenerp) + { + allocateListener(); + } mListenerp->set(pos,vel,up,at); } @@ -972,7 +911,10 @@ F32 LLAudioEngine::getRolloffFactor() void LLAudioEngine::commitDeferredChanges() { - mListenerp->commitDeferredChanges(); + if(mListenerp) + { + mListenerp->commitDeferredChanges(); + } } @@ -1025,7 +967,7 @@ LLAudioData * LLAudioEngine::getAudioData(const LLUUID &audio_uuid) LLAudioChannel* chan=sourcep->getChannel(); if(chan) { - LL_DEBUGS("AudioEngine") << "removeAudioData" << llendl; + LL_DEBUGS("AudioEngine") << "removeAudioData" << LL_ENDL; chan->cleanup(); } delete sourcep; @@ -1063,7 +1005,7 @@ void LLAudioEngine::cleanupAudioSource(LLAudioSource *asp) iter = mAllSources.find(asp->getID()); if (iter == mAllSources.end()) { - LL_WARNS("AudioEngine") << "Cleaning up unknown audio source!" << llendl; + LL_WARNS("AudioEngine") << "Cleaning up unknown audio source!" << LL_ENDL; return; } delete asp; @@ -1100,10 +1042,10 @@ bool LLAudioEngine::hasLocalFile(const LLUUID &uuid) void LLAudioEngine::startNextTransfer() { - //llinfos << "LLAudioEngine::startNextTransfer()" << llendl; - if (mCurrentTransfer.notNull() || getMuted()) + //LL_INFOS("AudioEngine") << "LLAudioEngine::startNextTransfer()" << LL_ENDL; + if (!gAssetStorage->isUpstreamOK() || mCurrentTransfer.notNull() || getMuted()) { - //llinfos << "Transfer in progress, aborting" << llendl; + //LL_INFOS("AudioEngine") << "Transfer in progress, aborting" << LL_ENDL; return; } @@ -1282,9 +1224,21 @@ void LLAudioEngine::startNextTransfer() } } + if (asset_id.isNull() && !mPreloadSystemList.empty()) + { + asset_id = mPreloadSystemList.front(); + mPreloadSystemList.pop_front(); + } + else if(asset_id.notNull()) + { + std::list::iterator it = std::find(mPreloadSystemList.begin(),mPreloadSystemList.end(),asset_id); + if(it != mPreloadSystemList.end()) + mPreloadSystemList.erase(it); + } + if (asset_id.notNull()) { - LL_DEBUGS("AudioEngine") << "Getting asset data for: " << asset_id << llendl; + LL_DEBUGS("AudioEngine") << "Getting asset data for: " << asset_id << LL_ENDL; gAudiop->mCurrentTransfer = asset_id; gAudiop->mCurrentTransferTimer.reset(); gAssetStorage->getAssetData(asset_id, LLAssetType::AT_SOUND, @@ -1292,7 +1246,7 @@ void LLAudioEngine::startNextTransfer() } else { - //llinfos << "No pending transfers?" << llendl; + //LL_INFOS("AudioEngine") << "No pending transfers?" << LL_ENDL; } } @@ -1302,7 +1256,7 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E { if (result_code) { - LL_INFOS("AudioEngine") << "Boom, error in audio file transfer: " << LLAssetStorage::getErrorString( result_code ) << " (" << result_code << ")" << llendl; + LL_INFOS("AudioEngine") << "Boom, error in audio file transfer: " << LLAssetStorage::getErrorString( result_code ) << " (" << result_code << ")" << LL_ENDL; // Need to mark data as bad to avoid constant rerequests. LLAudioData *adp = gAudiop->getAudioData(uuid); if (adp) @@ -1319,11 +1273,11 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E if (!adp) { // Should never happen - LL_WARNS("AudioEngine") << "Got asset callback without audio data for " << uuid << llendl; + LL_WARNS("AudioEngine") << "Got asset callback without audio data for " << uuid << LL_ENDL; } else { - // llinfos << "Got asset callback with good audio data for " << uuid << ", making decode request" << llendl; + // LL_INFOS("AudioEngine") << "Got asset callback with good audio data for " << uuid << ", making decode request" << LL_ENDL; adp->setHasValidData(true); adp->setHasLocalData(true); gAudioDecodeMgrp->addDecodeRequest(uuid); @@ -1392,6 +1346,9 @@ void LLAudioSource::setChannel(LLAudioChannel *channelp) return; } + //Either this channel just finished playing, or just started. Either way, reset the age timer. + mAgeTimer.reset(); + // if (!channelp) { @@ -1410,23 +1367,42 @@ void LLAudioSource::update() return ; //no need to update } - //if (!getCurrentBuffer()) // Same as !adp->getBuffer() + // If data is queued up and we aren't playing it, shuffle it to current and try to load it. + if(isQueueSounds() && mPlayedOnce && mQueuedDatap && !mChannelp) { - LLAudioData *adp = getCurrentData(); - if (adp && !adp->getBuffer()) + mCurrentDatap = mQueuedDatap; + mQueuedDatap = NULL; + + //Make sure this source looks like its brand new again to prevent removal. + mPlayedOnce = false; + mAgeTimer.reset(); + + gAudiop->startNextTransfer(); + } + + LLAudioData *adp = getCurrentData(); + if (adp && !adp->getBuffer()) + { + // Update the audio buffer first - load a sound if we have it. + // Note that this could potentially cause us to waste time updating buffers + // for sounds that actually aren't playing, although this should be mitigated + // by the fact that we limit the number of buffers, and we flush buffers based + // on priority. + if (adp->hasDecodedData()) { - // Hack - try and load the sound. Will do this as a callback - // on decode later. - if (adp->load()) + if(!adp->load() && adp->hasCompletedDecode()) { - play(adp->getID()); - } - else if (adp->hasCompletedDecode()) // Only mark corrupted after decode is done - { - LL_WARNS("AudioEngine") << "Marking LLAudioSource corrupted for " << adp->getID() << llendl; + LL_WARNS("AudioEngine") << "Marking LLAudioSource corrupted for " << adp->getID() << LL_ENDL; mCorrupted = true ; } } + else if (adp->hasLocalData() && adp->hasValidData()) + { + if (adp->getID().notNull()) + { + gAudioDecodeMgrp->addDecodeRequest(adp->getID()); + } + } } } @@ -1452,42 +1428,6 @@ void LLAudioSource::updatePriority() } } -bool LLAudioSource::setupChannel() -{ - LLAudioData *adp = getCurrentData(); - - if (!adp->getBuffer()) - { - // We're not ready to play back the sound yet, so don't try and allocate a channel for it. - //llwarns << "Aborting, no buffer" << llendl; - return false; - } - - - if (!mChannelp) - { - // Update the priority, in case we need to push out another channel. - updatePriority(); - - setChannel(gAudiop->getFreeChannel(getPriority())); - } - - if (!mChannelp) - { - // Ugh, we don't have any free channels. - // Now we have to reprioritize. - // For now, just don't play the sound. - //llwarns << "Aborting, no free channels" << llendl; - return false; - } - - mChannelp->setSource(this); - llassert(this == mChannelp->getSource()); - llassert(mChannelp->mCurrentBufferp == getCurrentBuffer()); - return true; -} - - bool LLAudioSource::play(const LLUUID &audio_uuid) { // Special abuse of play(); don't play a sound, but kill it. @@ -1496,7 +1436,7 @@ bool LLAudioSource::play(const LLUUID &audio_uuid) if (getChannel()) { llassert(this == getChannel()->getSource()); - getChannel()->setSource(NULL); + getChannel()->cleanup(); if (!isMuted()) { mCurrentDatap = NULL; @@ -1514,171 +1454,103 @@ bool LLAudioSource::play(const LLUUID &audio_uuid) mAgeTimer.reset(); LLAudioData *adp = gAudiop->getAudioData(audio_uuid); - addAudioData(adp); - if (isMuted()) + if (isQueueSounds()) { - return false; + if(mQueuedDatap) + { + // We already have a sound queued up. Ignore new request. + return false; + } + else if (adp == mCurrentDatap && isLoop()) + { + // No point in queuing the same sound if + // we're looping. + return true; + } + else if(mCurrentDatap) + { + mQueuedDatap = adp; + return true; + } } + mCurrentDatap = adp; - bool has_buffer = gAudiop->updateBufferForData(adp, audio_uuid); - if (!has_buffer) - { - // Don't bother trying to set up a channel or anything, we don't have an audio buffer. - return false; - } + // Make sure the audio engine knows that we want to request this sound. + gAudiop->startNextTransfer(); - if (!setupChannel()) - { - return false; - } - - if (isSyncSlave()) - { - // A sync slave, it doesn't start playing until it's synced up with the master. - // Flag this channel as waiting for sync, and return true. - getChannel()->setWaiting(true); - return true; - } - - getChannel()->play(); return true; } bool LLAudioSource::isDone() const { + static const F32 MAX_AGE = 60.f; + static const F32 MAX_UNPLAYED_AGE = 15.f; + static const F32 MAX_MUTED_AGE = 11.f; + if(mCorrupted) { - return true ; + // If we decode bad data then just kill this source entirely. + return true; } - - const F32 MAX_AGE = 60.f; - const F32 MAX_UNPLAYED_AGE = 15.f; - const F32 MAX_MUTED_AGE = 11.f; - - if (isLoop()) + else if (isLoop()) { // Looped sources never die on their own. return false; } - - if (hasPendingPreloads()) + else if (hasPendingPreloads()) { + // If there are pending preload requests then keep it alive. return false; } - - if (mQueuedDatap) + else if (mQueuedDatap) { // Don't kill this sound if we've got something queued up to play. return false; } + else if(mPlayedOnce && (!mChannelp || !mChannelp->isPlaying())) + { + // This is a single-play source and it already did its thing. + return true; + } F32 elapsed = mAgeTimer.getElapsedTimeF32(); - // This is a single-play source if (!mChannelp) { - if ((elapsed > (mSourceMuted ? MAX_MUTED_AGE : MAX_UNPLAYED_AGE)) || mPlayedOnce) - { - // We don't have a channel assigned, and it's been - // over 15 seconds since we tried to play it. Don't bother. - //llinfos << "No channel assigned, source is done" << llendl; - return true; - } - else - { - return false; - } - } + LLAudioData* adp = mCurrentDatap; - if (mChannelp->isPlaying()) - { - if (elapsed > MAX_AGE) - { - // Arbitarily cut off non-looped sounds when they're old. - return true; - } - else - { - // Sound is still playing and we haven't timed out, don't kill it. + //Still decoding. + if(adp && !adp->hasDecodedData() && adp->hasValidData()) return false; - } - } - if ((elapsed > MAX_UNPLAYED_AGE) || mPlayedOnce) + // We don't have a channel assigned, and it's been + // over 15 seconds since we tried to play it. Don't bother. + return (elapsed > (mSourceMuted ? MAX_MUTED_AGE : MAX_UNPLAYED_AGE)); + } + else if (mChannelp->isPlaying()) { - // The sound isn't playing back after 15 seconds or we're already done playing it, kill it. - return true; + // Arbitarily cut off non-looped sounds when they're old. + return elapsed > MAX_AGE; + } + else if(!isSyncSlave()) + { + // The sound isn't playing back after 15 seconds, kill it. + // This might happen if all channels are in use and this source is low-priority + return elapsed > MAX_UNPLAYED_AGE; } return false; } -void LLAudioSource::addAudioData(LLAudioData *adp, const bool set_current) +void LLAudioSource::preload(const LLUUID &audio_id) { - // Only handle a single piece of audio data associated with a source right now, - // until I implement prefetch. - if (set_current) - { - if (!mCurrentDatap) - { - mCurrentDatap = adp; - if (mChannelp) - { - mChannelp->updateBuffer(); - mChannelp->play(); - } - - // Make sure the audio engine knows that we want to request this sound. - gAudiop->startNextTransfer(); - return; - } - else if (mQueueSounds) - { - // If we have current data, and we're queuing, put - // the object onto the queue. - if (mQueuedDatap) - { - // We only queue one sound at a time, and it's a FIFO. - // Don't put it onto the queue. - return; - } - - if (adp == mCurrentDatap && isLoop()) - { - // No point in queueing the same sound if - // we're looping. - return; - } - mQueuedDatap = adp; - - // Make sure the audio engine knows that we want to request this sound. - gAudiop->startNextTransfer(); - } - else - { - if (mCurrentDatap != adp) - { - // Right now, if we're currently playing this sound in a channel, we - // update the buffer that the channel's associated with - // and play it. This may not be the correct behavior. - mCurrentDatap = adp; - if (mChannelp) - { - mChannelp->updateBuffer(); - mChannelp->play(); - } - // Make sure the audio engine knows that we want to request this sound. - gAudiop->startNextTransfer(); - } - } - } - else + if(audio_id.notNull()) { // Add it to the preload list. - mPreloadMap[adp->getID()] = adp; + mPreloadMap[audio_id] = gAudiop->getAudioData(audio_id); gAudiop->startNextTransfer(); } } @@ -1740,18 +1612,16 @@ LLAudioChannel::LLAudioChannel() : mCurrentSourcep(NULL), mCurrentBufferp(NULL), mLoopedThisFrame(false), - mWaiting(false), mSecondaryGain(1.0f) { } - LLAudioChannel::~LLAudioChannel() { llassert(mCurrentBufferp == NULL); // Need to disconnect any sources which are using this channel. - //llinfos << "Cleaning up audio channel" << llendl; + //LL_INFOS("AudioEngine") << "Cleaning up audio channel" << LL_ENDL; cleanup(); } @@ -1761,29 +1631,14 @@ void LLAudioChannel::cleanup() mCurrentSourcep->setChannel(NULL); mCurrentBufferp = NULL; mCurrentSourcep = NULL; - mWaiting = false; } void LLAudioChannel::setSource(LLAudioSource *sourcep) { - //llinfos << this << ": setSource(" << sourcep << ")" << llendl; + llassert_always(sourcep); + llassert_always(!mCurrentSourcep); - if (!sourcep) - { - // Clearing the source for this channel, don't need to do anything. - LL_DEBUGS("AudioEngine") << "Clearing source for channel" << llendl; - cleanup(); - return; - } - - if (sourcep == mCurrentSourcep) - { - // Don't reallocate the channel, this will make FMOD goofy. - LL_DEBUGS("AudioEngine") << "Calling setSource with same source!" << llendl; - } - - cleanup(); mCurrentSourcep = sourcep; mCurrentSourcep->setChannel(this); @@ -1808,42 +1663,16 @@ bool LLAudioChannel::updateBuffer() } LLAudioBuffer *bufferp = mCurrentSourcep->getCurrentBuffer(); - if (bufferp == mCurrentBufferp) - { - if (bufferp) - { - // The source hasn't changed what buffer it's playing - bufferp->mLastUseTimer.reset(); - bufferp->mInUse = true; - } - return false; - } - // - // The source changed what buffer it's playing. We need to clean up - // the existing channel - // - LLAudioSource* source = mCurrentSourcep; - cleanup(); - mCurrentSourcep = source; - mCurrentSourcep->setChannel(this); - - llassert(mCurrentBufferp == NULL); - - mCurrentBufferp = bufferp; + //This buffer is still in use, so mark it as such, and reset the use timer. if (bufferp) { bufferp->mLastUseTimer.reset(); bufferp->mInUse = true; } - if (!mCurrentBufferp) - { - // There's no new buffer to be played, so we just abort. - return false; - } - - return true; + //Return true if the buffer changed and is not null. + return bufferp != mCurrentBufferp && !!(mCurrentBufferp = bufferp); } @@ -1888,7 +1717,7 @@ bool LLAudioData::load() if (mBufferp) { // We already have this sound in a buffer, don't do anything. - LL_INFOS("AudioEngine") << "Already have a buffer for this sound, don't bother loading!" << llendl; + LL_INFOS("AudioEngine") << "Already have a buffer for this sound, don't bother loading!" << LL_ENDL; return true; } @@ -1896,7 +1725,7 @@ bool LLAudioData::load() if (!mBufferp) { // No free buffers, abort. - LL_DEBUGS("AudioEngine") << "Not able to allocate a new audio buffer, aborting." << llendl; + LL_DEBUGS("AudioEngine") << "Not able to allocate a new audio buffer, aborting." << LL_ENDL; return false; } diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index c739e37bf..d1e23de96 100644 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -147,7 +147,7 @@ public: const LLVector3d &pos_global = LLVector3d::zero, const LLUUID source_object = LLUUID::null); // - bool preloadSound(const LLUUID &id); + bool preloadSound(const LLUUID &id); //Preloads sounds without requiring a source. void addAudioSource(LLAudioSource *asp); void cleanupAudioSource(LLAudioSource *asp); @@ -179,8 +179,6 @@ public: bool hasDecodedFile(const LLUUID &uuid); bool hasLocalFile(const LLUUID &uuid); - bool updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid = LLUUID::null); - void setAllowLargeSounds(bool allow) { mAllowLargeSounds = allow ;} bool getAllowLargeSounds() const {return mAllowLargeSounds;} @@ -244,6 +242,7 @@ public://Jay: IDGAF source_map mAllSources; protected: data_map mAllData; + std::list mPreloadSystemList; LLAudioChannel *mChannels[MAX_CHANNELS]; // Buffers needs to change into a different data structure, as the number of buffers @@ -287,9 +286,7 @@ public: virtual void update(); // Update this audio source void updatePriority(); - void preload(const LLUUID &audio_id); // Only used for preloading UI sounds, now. - - void addAudioData(LLAudioData *adp, bool set_current = TRUE); + void preload(const LLUUID &audio_id); void setAmbient(const bool ambient) { mAmbient = ambient; } bool isAmbient() const { return mAmbient; } @@ -450,11 +447,10 @@ protected: virtual void play() = 0; virtual void playSynced(LLAudioChannel *channelp) = 0; virtual void cleanup(); - void setWaiting(bool waiting) { mWaiting = waiting; } public: virtual bool isPlaying() = 0; - bool isWaiting() const { return mWaiting; } + bool isFree() const { return mCurrentSourcep==NULL; } protected: virtual bool updateBuffer(); // Check to see if the buffer associated with the source changed, and update if necessary. @@ -465,7 +461,6 @@ protected: LLAudioSource *mCurrentSourcep; LLAudioBuffer *mCurrentBufferp; bool mLoopedThisFrame; - bool mWaiting; // Waiting for sync. F32 mSecondaryGain; }; diff --git a/indra/llaudio/llaudioengine_fmodex.cpp b/indra/llaudio/llaudioengine_fmodex.cpp index bfdda0957..deb27e11d 100644 --- a/indra/llaudio/llaudioengine_fmodex.cpp +++ b/indra/llaudio/llaudioengine_fmodex.cpp @@ -97,17 +97,17 @@ public: DEAD, UNKNOWN }; - STATUS getPtrStatus(LLAudioChannelFMODEX* channel) + STATUS getPtrStatus(LLAudioChannel* channel) { if(!channel) return UNKNOWN; - return getPtrStatus(channel->mChannelp); + return getPtrStatus(dynamic_cast(channel)->mChannelp); } - STATUS getPtrStatus(LLAudioBufferFMODEX* sound) + STATUS getPtrStatus(LLAudioBuffer* sound) { if(!sound) return UNKNOWN; - return getPtrStatus(sound->mSoundp); + return getPtrStatus(dynamic_cast(sound)->mSoundp); } STATUS getPtrStatus(FMOD::Channel* channel) { @@ -131,18 +131,14 @@ public: } void addNewSound(FMOD::Sound* sound) { - llassert(getPtrStatus(sound) != ACTIVE); + assertActiveState(sound,true,false); mDeadSounds.erase(sound); mActiveSounds.insert(std::make_pair(sound,std::set())); } void removeSound(FMOD::Sound* sound) { -#ifdef SHOW_ASSERT - STATUS status = getPtrStatus(sound); - llassert(status != DEAD); - llassert(status != UNKNOWN); -#endif + assertActiveState(sound,true); active_sounds_t::const_iterator it = mActiveSounds.find(sound); llassert(it != mActiveSounds.end()); @@ -150,49 +146,39 @@ public: { if(!it->second.empty()) { -#ifdef LL_RELEASE_FOR_DOWNLOAD LL_WARNS("AudioImpl") << "Removing sound " << sound << " with attached channels: \n"; -#else - LL_ERRS("AudioImpl") << "Removing sound " << sound << " with attached channels: \n"; -#endif for(std::set::iterator it2 = it->second.begin(); it2 != it->second.end();++it2) { switch(getPtrStatus(*it2)) { case ACTIVE: - llcont << " Channel " << *it2 << " ACTIVE\n"; + LL_CONT << " Channel " << *it2 << " ACTIVE\n"; break; case DEAD: - llcont << " Channel " << *it2 << " DEAD\n"; + LL_CONT << " Channel " << *it2 << " DEAD\n"; break; default: - llcont << " Channel " << *it2 << " UNKNOWN\n"; + LL_CONT << " Channel " << *it2 << " UNKNOWN\n"; } } - llcont << llendl; + LL_CONT << LL_ENDL; } + llassert(it->second.empty()); mDeadSounds.insert(sound); mActiveSounds.erase(sound); } } void addNewChannelToSound(FMOD::Sound* sound,FMOD::Channel* channel) { - STATUS status = getPtrStatus(sound); - llassert(status != DEAD); - llassert(status != UNKNOWN); - status = getPtrStatus(channel); - llassert(status != ACTIVE); + assertActiveState(sound,true); + assertActiveState(channel,true,false); mActiveSounds[sound].insert(channel); mActiveChannels.insert(std::make_pair(channel,sound)); } void removeChannel(FMOD::Channel* channel) { -#ifdef SHOW_ASSERT - STATUS status = getPtrStatus(channel); - llassert(status != DEAD); - llassert(status != UNKNOWN); -#endif + gSoundCheck.assertActiveState(channel,true); active_channels_t::const_iterator it = mActiveChannels.find(channel); llassert(it != mActiveChannels.end()); @@ -214,25 +200,32 @@ public: mActiveChannels.erase(channel); } } + + template + void assertActiveState(T ptr, bool try_log=false, bool active=true) + { +#ifndef SHOW_ASSERT + if(try_log && sVerboseDebugging) +#endif + { + CFMODSoundChecks::STATUS chan = gSoundCheck.getPtrStatus(ptr); + if(try_log && sVerboseDebugging) + { + if(active) + { + if(chan == CFMODSoundChecks::DEAD) + LL_WARNS("AudioImpl") << __FUNCTION__ << ": Using unexpectedly dead " << typeid(T*).name() << " " << ptr << LL_ENDL; + else if(chan == CFMODSoundChecks::UNKNOWN) + LL_WARNS("AudioImpl") << __FUNCTION__ << ": Using unexpectedly unknown " << typeid(T*).name() << " " << ptr << LL_ENDL; + } + else if(chan == CFMODSoundChecks::ACTIVE) + LL_WARNS("AudioImpl") << __FUNCTION__ << ": Using unexpectedly active " << typeid(T*).name() << " " << ptr << LL_ENDL; + } + llassert( active == (chan == CFMODSoundChecks::ACTIVE) ); + } + } } gSoundCheck; -bool isActive(LLAudioChannel* channel) -{ - return gSoundCheck.getPtrStatus(dynamic_cast(channel)) == CFMODSoundChecks::ACTIVE; -} -bool isActive(LLAudioBuffer* sound) -{ - return gSoundCheck.getPtrStatus(dynamic_cast(sound)) == CFMODSoundChecks::ACTIVE; -} - -#define CHECK_PTR(ptr) \ - if(sVerboseDebugging){\ - CFMODSoundChecks::STATUS chan = gSoundCheck.getPtrStatus(ptr); \ - if(chan == CFMODSoundChecks::DEAD) \ - LL_DEBUGS("AudioImpl") << __FUNCTION__ << ": Using dead " << typeid(ptr).name() << " " << ptr << llendl; \ - else if(chan == CFMODSoundChecks::UNKNOWN) \ - LL_DEBUGS("AudioImpl") << __FUNCTION__ << ": Using unknown " << typeid(ptr).name() << " " << ptr << llendl;} \ - LLAudioEngine_FMODEX::LLAudioEngine_FMODEX(bool enable_profiler, bool verbose_debugging) { sVerboseDebugging = verbose_debugging; @@ -253,7 +246,7 @@ inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string) { if(result == FMOD_OK) return false; - LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << llendl; + LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL; return true; } @@ -261,11 +254,11 @@ void* F_STDCALL decode_alloc(unsigned int size, FMOD_MEMORY_TYPE type, const cha { if(type & FMOD_MEMORY_STREAM_DECODE) { - LL_INFOS("AudioImpl") << "Decode buffer size: " << size << llendl; + LL_INFOS("AudioImpl") << "Decode buffer size: " << size << LL_ENDL; } else if(type & FMOD_MEMORY_STREAM_FILE) { - LL_INFOS("AudioImpl") << "Stream buffer size: " << size << llendl; + LL_INFOS("AudioImpl") << "Stream buffer size: " << size << LL_ENDL; } return new char[size]; } @@ -504,7 +497,7 @@ void LLAudioEngine_FMODEX::allocateListener(void) mListenerp = (LLListener *) new LLListener_FMODEX(mSystem); if (!mListenerp) { - LL_WARNS("AudioImpl") << "Listener creation failed" << llendl; + LL_WARNS("AudioImpl") << "Listener creation failed" << LL_ENDL; } } @@ -513,16 +506,18 @@ void LLAudioEngine_FMODEX::shutdown() { stopInternetStream(); - LL_INFOS("AudioImpl") << "About to LLAudioEngine::shutdown()" << llendl; + LL_INFOS("AudioImpl") << "About to LLAudioEngine::shutdown()" << LL_ENDL; LLAudioEngine::shutdown(); - LL_INFOS("AudioImpl") << "LLAudioEngine_FMODEX::shutdown() closing FMOD Ex" << llendl; + LL_INFOS("AudioImpl") << "LLAudioEngine_FMODEX::shutdown() closing FMOD Ex" << LL_ENDL; if ( mSystem ) // speculative fix for MAINT-2657 { - mSystem->close(); - mSystem->release(); + LL_INFOS("AudioImpl") << "LLAudioEngine_FMODEX::shutdown() Requesting FMOD Ex system closure" << LL_ENDL; + mSystem->close(); + LL_INFOS("AudioImpl") << "LLAudioEngine_FMODEX::shutdown() Requesting FMOD Ex system release" << LL_ENDL; + mSystem->release(); } - LL_INFOS("AudioImpl") << "LLAudioEngine_FMODEX::shutdown() done closing FMOD Ex" << llendl; + LL_INFOS("AudioImpl") << "LLAudioEngine_FMODEX::shutdown() done closing FMOD Ex" << LL_ENDL; delete mListenerp; mListenerp = NULL; @@ -654,7 +649,7 @@ LLAudioChannelFMODEX::LLAudioChannelFMODEX(FMOD::System *system) : LLAudioChanne LLAudioChannelFMODEX::~LLAudioChannelFMODEX() { if(sVerboseDebugging) - LL_DEBUGS("AudioImpl") << "Destructing Audio Channel. mChannelp = " << mChannelp << llendl; + LL_DEBUGS("AudioImpl") << "Destructing Audio Channel. mChannelp = " << mChannelp << LL_ENDL; cleanup(); } @@ -678,7 +673,7 @@ void LLAudioChannelFMODEX::onRelease() { llassert(mChannelp); if(sVerboseDebugging) - LL_DEBUGS("AudioImpl") << "Fmod signaled channel release for channel " << mChannelp << llendl; + LL_DEBUGS("AudioImpl") << "Fmod signaled channel release for channel " << mChannelp << LL_ENDL; gSoundCheck.removeChannel(mChannelp); mChannelp = NULL; //Null out channel here so cleanup doesn't try to redundantly stop it. cleanup(); @@ -688,42 +683,32 @@ bool LLAudioChannelFMODEX::updateBuffer() { if (LLAudioChannel::updateBuffer()) { - // Base class update returned true, which means that we need to actually - // set up the channel for a different buffer. - - LLAudioBufferFMODEX *bufferp = (LLAudioBufferFMODEX *)mCurrentSourcep->getCurrentBuffer(); - - llassert(mCurrentBufferp != NULL); - llassert(mCurrentBufferp == bufferp); + // Base class update returned true, which means the channel buffer was changed, and not is null. // Grab the FMOD sample associated with the buffer - FMOD::Sound *soundp = bufferp->getSound(); + FMOD::Sound *soundp = ((LLAudioBufferFMODEX*)mCurrentBufferp)->getSound(); if (!soundp) { // This is bad, there should ALWAYS be a sound associated with a legit // buffer. - LL_ERRS("AudioImpl") << "No FMOD sound!" << llendl; + LL_ERRS("AudioImpl") << "No FMOD sound!" << LL_ENDL; return false; } - // Actually play the sound. Start it off paused so we can do all the necessary // setup. if(!mChannelp) { - llassert(!isActive(this)); - FMOD_RESULT result = getSystem()->playSound(FMOD_CHANNEL_FREE, soundp, true, &mChannelp); Check_FMOD_Error(result, "FMOD::System::playSound"); if(result == FMOD_OK) { if(sVerboseDebugging) - LL_DEBUGS("AudioImpl") << "Created channel " << mChannelp << " for sound " << soundp << llendl; + LL_DEBUGS("AudioImpl") << "Created channel " << mChannelp << " for sound " << soundp << LL_ENDL; gSoundCheck.addNewChannelToSound(soundp,mChannelp); mChannelp->setCallback(&channel_callback); mChannelp->setUserData(this); - llassert(isActive(this)); } } } @@ -731,11 +716,9 @@ bool LLAudioChannelFMODEX::updateBuffer() // If we have a source for the channel, we need to update its gain. if (mCurrentSourcep && mChannelp) { - // SJB: warnings can spam and hurt framerate, disabling FMOD_RESULT result; - CHECK_PTR(mChannelp); - + gSoundCheck.assertActiveState(this); result = mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain()); Check_FMOD_Error(result, "FMOD::Channel::setVolume"); result = mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF); @@ -762,7 +745,7 @@ void LLAudioChannelFMODEX::update3DPosition() return; } - CHECK_PTR(mChannelp); + gSoundCheck.assertActiveState(this); if (mCurrentSourcep->isAmbient()) { @@ -790,7 +773,7 @@ void LLAudioChannelFMODEX::updateLoop() return; } - CHECK_PTR(mChannelp); + gSoundCheck.assertActiveState(this); // // Hack: We keep track of whether we looped or not by seeing when the @@ -814,26 +797,19 @@ void LLAudioChannelFMODEX::cleanup() if (!mChannelp) { - llassert(!isActive(this)); llassert(mCurrentBufferp == NULL); - //llinfos << "Aborting cleanup with no channel handle." << llendl; + //LL_INFOS("AudioImpl") << "Aborting cleanup with no channel handle." << LL_ENDL; return; } - CHECK_PTR(mChannelp); - if(sVerboseDebugging) - LL_DEBUGS("AudioImpl") << "Stopping channel " << mChannelp << llendl; + LL_DEBUGS("AudioImpl") << "Stopping channel " << mChannelp << LL_ENDL; + gSoundCheck.removeChannel(mChannelp); mChannelp->setCallback(NULL); - if(!Check_FMOD_Error(mChannelp->stop(),"FMOD::Channel::stop")) - { - gSoundCheck.removeChannel(mChannelp); - } + Check_FMOD_Error(mChannelp->stop(),"FMOD::Channel::stop"); mChannelp = NULL; - llassert(!isActive(this)); - } @@ -841,18 +817,16 @@ void LLAudioChannelFMODEX::play() { if (!mChannelp) { - LL_WARNS("AudioImpl") << "Playing without a channel handle, aborting" << llendl; + LL_WARNS("AudioImpl") << "Playing without a channel handle, aborting" << LL_ENDL; return; } - llassert(isActive(this)); - - CHECK_PTR(mChannelp); + gSoundCheck.assertActiveState(this,true); Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::setPaused"); if(sVerboseDebugging) - LL_DEBUGS("AudioImpl") << "Playing channel " << mChannelp << llendl; + LL_DEBUGS("AudioImpl") << "Playing channel " << mChannelp << LL_ENDL; getSource()->setPlayedOnce(true); @@ -870,10 +844,10 @@ void LLAudioChannelFMODEX::playSynced(LLAudioChannel *channelp) return; } - CHECK_PTR(mChannelp); + gSoundCheck.assertActiveState(this,true); U32 cur_pos; - if(Check_FMOD_Error(mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES), "Unable to retrieve current position")) + if(Check_FMOD_Error(fmod_channelp->mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES), "Unable to retrieve current position")) return; cur_pos %= mCurrentBufferp->getLength(); @@ -893,7 +867,7 @@ bool LLAudioChannelFMODEX::isPlaying() return false; } - CHECK_PTR(mChannelp); + gSoundCheck.assertActiveState(this); bool paused, playing; Check_FMOD_Error(mChannelp->getPaused(&paused),"FMOD::Channel::getPaused"); @@ -917,11 +891,10 @@ LLAudioBufferFMODEX::~LLAudioBufferFMODEX() if(mSoundp) { if(sVerboseDebugging) - LL_DEBUGS("AudioImpl") << "Release sound " << mSoundp << llendl; + LL_DEBUGS("AudioImpl") << "Release sound " << mSoundp << LL_ENDL; - CHECK_PTR(mSoundp); - Check_FMOD_Error(mSoundp->release(),"FMOD::Sound::Release"); gSoundCheck.removeSound(mSoundp); + Check_FMOD_Error(mSoundp->release(),"FMOD::Sound::Release"); mSoundp = NULL; } } @@ -945,10 +918,9 @@ bool LLAudioBufferFMODEX::loadWAV(const std::string& filename) if (mSoundp) { - CHECK_PTR(mSoundp); + gSoundCheck.removeSound(mSoundp); // If there's already something loaded in this buffer, clean it up. Check_FMOD_Error(mSoundp->release(),"FMOD::Sound::release"); - gSoundCheck.removeSound(mSoundp); mSoundp = NULL; } @@ -967,7 +939,7 @@ bool LLAudioBufferFMODEX::loadWAV(const std::string& filename) if (result != FMOD_OK) { // We failed to load the file for some reason. - LL_WARNS("AudioImpl") << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << llendl; + LL_WARNS("AudioImpl") << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << LL_ENDL; // // If we EVER want to load wav files provided by end users, we need @@ -992,7 +964,7 @@ U32 LLAudioBufferFMODEX::getLength() return 0; } - CHECK_PTR(mSoundp); + gSoundCheck.assertActiveState(this); U32 length; Check_FMOD_Error(mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES),"FMOD::Sound::getLength"); return length; @@ -1001,7 +973,7 @@ U32 LLAudioBufferFMODEX::getLength() void LLAudioChannelFMODEX::set3DMode(bool use3d) { - CHECK_PTR(mChannelp); + gSoundCheck.assertActiveState(this); FMOD_MODE current_mode; if(Check_FMOD_Error(mChannelp->getMode(¤t_mode),"FMOD::Channel::getMode")) diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h index 0ad4dad1d..7129e2f03 100644 --- a/indra/llmessage/llassetstorage.h +++ b/indra/llmessage/llassetstorage.h @@ -249,6 +249,10 @@ public: virtual ~LLAssetStorage(); void setUpstream(const LLHost &upstream_host); + bool isUpstreamOK() const + { + return mUpstreamHost.isOk(); + } virtual BOOL hasLocalAsset(const LLUUID &uuid, LLAssetType::EType type); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 88307e49b..6be1d5c96 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1534,33 +1534,6 @@ bool LLAppViewer::cleanup() llinfos << "Global stuff deleted" << llendflush; - if (gAudiop) - { - // shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem. - - LLStreamingAudioInterface *sai = gAudiop->getStreamingAudioImpl(); - delete sai; - gAudiop->setStreamingAudioImpl(NULL); - - // shut down the audio subsystem - - bool want_longname = false; - if (gAudiop->getDriverName(want_longname) == "FMOD") - { - // This hack exists because fmod likes to occasionally - // crash or hang forever when shutting down, for no - // apparent reason. - llwarns << "Hack, skipping FMOD audio engine cleanup" << llendflush; - } - else - { - gAudiop->shutdown(); - } - - delete gAudiop; - gAudiop = NULL; - } - // Note: this is where LLFeatureManager::getInstance()-> used to be deleted. // Patch up settings for next time @@ -3942,6 +3915,9 @@ void LLAppViewer::idle() gViewerWindow->updateUI(); + //updateUI may have created sounds (clicks, etc). Call idleAudio to dispatch asap. + idleAudio(); + /////////////////////////////////////// // Agent and camera movement // @@ -4120,22 +4096,6 @@ void LLAppViewer::idle() gObjectList.updateApparentAngles(gAgent); } - { - gFrameStats.start(LLFrameStats::AUDIO); - LLFastTimer t(FTM_AUDIO_UPDATE); - - if (gAudiop) - { - audio_update_volume(false); - audio_update_listener(); - audio_update_wind(false); - - // this line actually commits the changes we've made to source positions, etc. - const F32 max_audio_decode_time = 0.002f; // 2 ms decode time - gAudiop->idle(max_audio_decode_time); - } - } - // Execute deferred tasks. LLDeferredTaskList::instance().run(); @@ -4440,6 +4400,51 @@ void LLAppViewer::idleNetwork() } } +void LLAppViewer::idleAudio() +{ + gFrameStats.start(LLFrameStats::AUDIO); + LLFastTimer t(FTM_AUDIO_UPDATE); + + if (gAudiop) + { + audio_update_volume(); + audio_update_listener(); + + // this line actually commits the changes we've made to source positions, etc. + const F32 max_audio_decode_time = 0.002f; // 2 ms decode time + gAudiop->idle(max_audio_decode_time); + } +} +void LLAppViewer::shutdownAudio() +{ + if (gAudiop) + { + // shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem. + + LLStreamingAudioInterface *sai = gAudiop->getStreamingAudioImpl(); + delete sai; + gAudiop->setStreamingAudioImpl(NULL); + + // shut down the audio subsystem + + bool want_longname = false; + if (gAudiop->getDriverName(want_longname) == "FMOD") + { + // This hack exists because fmod likes to occasionally + // crash or hang forever when shutting down, for no + // apparent reason. + llwarns << "Hack, skipping FMOD audio engine cleanup" << llendflush; + } + else + { + gAudiop->shutdown(); + } + + delete gAudiop; + gAudiop = NULL; + } +} + void LLAppViewer::disconnectViewer() { if (gDisconnected) @@ -4540,6 +4545,9 @@ void LLAppViewer::disconnectViewer() LLDestroyClassList::instance().fireCallbacks(); cleanup_xfer_manager(); + + shutdownAudio(); + gDisconnected = TRUE; } diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 251762040..f461c259b 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -210,6 +210,8 @@ private: // update avatar SLID and display name caches void idleNameCache(); void idleNetwork(); + void idleAudio(); + void shutdownAudio(); void sendLogoutRequest(); void disconnectViewer(); diff --git a/indra/newview/llfloaterblacklist.cpp b/indra/newview/llfloaterblacklist.cpp index 2b9b9dd05..dd80e2138 100644 --- a/indra/newview/llfloaterblacklist.cpp +++ b/indra/newview/llfloaterblacklist.cpp @@ -174,7 +174,8 @@ void LLFloaterBlacklist::addEntry(LLUUID key, LLSD data) std::string wav_path= gDirUtilp->getExpandedFilename(LL_PATH_CACHE,sound_id.asString()) + ".dsf"; if(LLAPRFile::isExist(wav_path, LL_APR_RPB)) LLAPRFile::remove(wav_path); - gAudiop->removeAudioData(sound_id); + if(gAudiop) + gAudiop->removeAudioData(sound_id); } blacklist_entries.insert(std::pair(key,data)); updateBlacklists(); diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp index 5dc3e4324..eaa563278 100644 --- a/indra/newview/llfloaterchat.cpp +++ b/indra/newview/llfloaterchat.cpp @@ -498,6 +498,7 @@ void LLFloaterChat::triggerAlerts(const std::string& text) { if ((std::string)highlight["sound_lluuid"] != LLUUID::null.asString()) { + if(gAudiop) gAudiop->triggerSound(highlight["sound_lluuid"].asUUID(), gAgent.getID(), 1.f, diff --git a/indra/newview/llfloaterexploresounds.cpp b/indra/newview/llfloaterexploresounds.cpp index d1dacf4e3..36caef3e9 100644 --- a/indra/newview/llfloaterexploresounds.cpp +++ b/indra/newview/llfloaterexploresounds.cpp @@ -304,6 +304,7 @@ void LLFloaterExploreSounds::handle_play_locally(void* user_data) if(std::find(asset_list.begin(), asset_list.end(), item.mAssetID) == asset_list.end()) { asset_list.push_back(item.mAssetID); + if(gAudiop) gAudiop->triggerSound(item.mAssetID, LLUUID::null, 1.0f, LLAudioEngine::AUDIO_TYPE_UI); } } diff --git a/indra/newview/llpreviewsound.cpp b/indra/newview/llpreviewsound.cpp index bdab29153..163ba6056 100644 --- a/indra/newview/llpreviewsound.cpp +++ b/indra/newview/llpreviewsound.cpp @@ -93,13 +93,13 @@ LLPreviewSound::LLPreviewSound(const std::string& name, const LLRect& rect, cons // preload the sound if(item && gAudiop) { - gAudiop->preloadSound(item->getAssetUUID()); // // that thing above doesn't actually start a sound transfer, so I will do it - //LLAudioSource *asp = new LLAudioSource(gAgent.getID(), gAgent.getID(), F32(1.0f), LLAudioEngine::AUDIO_TYPE_UI); LLAudioSource *asp = gAgentAvatarp->getAudioSource(gAgent.getID()); - LLAudioData *datap = gAudiop->getAudioData(item->getAssetUUID()); - asp->addAudioData(datap, FALSE); + if(asp) + { + asp->preload(item->getAssetUUID()); + } // } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index a71be5efd..43e8ca335 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -375,6 +375,88 @@ void hooked_process_sound_trigger(LLMessageSystem *msg, void **) LLFloaterAvatarList::sound_trigger_hook(msg,NULL); } +void init_audio() +{ + if (FALSE == gSavedSettings.getBOOL("NoAudio")) + { + gAudiop = NULL; + +#ifdef LL_FMODEX + if (!gAudiop +#if !LL_WINDOWS + && NULL == getenv("LL_BAD_FMODEX_DRIVER") +#endif // !LL_WINDOWS + ) + { + gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODEX(gSavedSettings.getBOOL("SHEnableFMODExProfiler"),gSavedSettings.getBOOL("SHEnableFMODEXVerboseDebugging")); + } +#endif + +#ifdef LL_OPENAL + if (!gAudiop +#if !LL_WINDOWS + && NULL == getenv("LL_BAD_OPENAL_DRIVER") +#endif // !LL_WINDOWS + ) + { + gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL(); + } +#endif + +#ifdef LL_FMOD + if (!gAudiop +#if !LL_WINDOWS + && NULL == getenv("LL_BAD_FMOD_DRIVER") +#endif // !LL_WINDOWS + ) + { + gAudiop = (LLAudioEngine *) new LLAudioEngine_FMOD(); + } +#endif + + if (gAudiop) + { +#if LL_WINDOWS + // FMOD on Windows needs the window handle to stop playing audio + // when window is minimized. JC + void* window_handle = (HWND)gViewerWindow->getPlatformWindow(); +#else + void* window_handle = NULL; +#endif + bool init = gAudiop->init(kAUDIO_NUM_SOURCES, window_handle); + if(init) + { + gAudiop->setMuted(TRUE); + if(gSavedSettings.getBOOL("AllowLargeSounds")) + gAudiop->setAllowLargeSounds(true); + } + else + { + LL_WARNS("AppInit") << "Unable to initialize audio engine" << LL_ENDL; + delete gAudiop; + gAudiop = NULL; + } + + if (gAudiop) + { + // if the audio engine hasn't set up its own preferred handler for streaming audio then set up the generic streaming audio implementation which uses media plugins + if (NULL == gAudiop->getStreamingAudioImpl()) + { + LL_INFOS("AppInit") << "Using media plugins to render streaming audio" << LL_ENDL; + gAudiop->setStreamingAudioImpl(new LLStreamingAudio_MediaPlugins()); + } + // Unmute audio if desired and setup volumes. + // This is a not-uncommon crash site, so surround it with + // llinfos output to aid diagnosis. + LL_INFOS("AppInit") << "Doing first audio_update_volume..." << LL_ENDL; + audio_update_volume(false); + LL_INFOS("AppInit") << "Done first audio_update_volume." << LL_ENDL; + } + } + } + LL_INFOS("AppInit") << "Audio Engine Initialized." << LL_ENDL; +} + // Returns false to skip other idle processing. Should only return // true when all initialization done. bool idle_startup() @@ -674,85 +756,6 @@ bool idle_startup() //------------------------------------------------- AIFilePicker::loadFile("filepicker_contexts.xml"); - - //------------------------------------------------- - // Init audio, which may be needed for prefs dialog - // or audio cues in connection UI. - //------------------------------------------------- - - if (FALSE == gSavedSettings.getBOOL("NoAudio")) - { - gAudiop = NULL; - -#ifdef LL_FMODEX - if (!gAudiop -#if !LL_WINDOWS - && NULL == getenv("LL_BAD_FMODEX_DRIVER") -#endif // !LL_WINDOWS - ) - { - gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODEX(gSavedSettings.getBOOL("SHEnableFMODExProfiler"),gSavedSettings.getBOOL("SHEnableFMODEXVerboseDebugging")); - } -#endif - -#ifdef LL_OPENAL - if (!gAudiop -#if !LL_WINDOWS - && NULL == getenv("LL_BAD_OPENAL_DRIVER") -#endif // !LL_WINDOWS - ) - { - gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL(); - } -#endif - -#ifdef LL_FMOD - if (!gAudiop -#if !LL_WINDOWS - && NULL == getenv("LL_BAD_FMOD_DRIVER") -#endif // !LL_WINDOWS - ) - { - gAudiop = (LLAudioEngine *) new LLAudioEngine_FMOD(); - } -#endif - - if (gAudiop) - { -#if LL_WINDOWS - // FMOD on Windows needs the window handle to stop playing audio - // when window is minimized. JC - void* window_handle = (HWND)gViewerWindow->getPlatformWindow(); -#else - void* window_handle = NULL; -#endif - bool init = gAudiop->init(kAUDIO_NUM_SOURCES, window_handle); - if(init) - { - gAudiop->setMuted(TRUE); - if(gSavedSettings.getBOOL("AllowLargeSounds")) - gAudiop->setAllowLargeSounds(true); - } - else - { - LL_WARNS("AppInit") << "Unable to initialize audio engine" << LL_ENDL; - delete gAudiop; - gAudiop = NULL; - } - - if (gAudiop) - { - // if the audio engine hasn't set up its own preferred handler for streaming audio then set up the generic streaming audio implementation which uses media plugins - if (NULL == gAudiop->getStreamingAudioImpl()) - { - LL_INFOS("AppInit") << "Using media plugins to render streaming audio" << LL_ENDL; - gAudiop->setStreamingAudioImpl(new LLStreamingAudio_MediaPlugins()); - } - } - } - } - - LL_INFOS("AppInit") << "Audio Engine Initialized." << LL_ENDL; if (LLTimer::knownBadTimer()) { @@ -889,15 +892,13 @@ bool idle_startup() if (login_history.size() > 0) { LLPanelLogin::setFields(*login_history.getEntries().rbegin()); - display_startup(); } else { LLPanelLogin::setFields(firstname, lastname, password); - display_startup(); - LLPanelLogin::giveFocus(); } - + display_startup(); + LLPanelLogin::giveFocus(); gSavedSettings.setBOOL("FirstRunThisInstall", FALSE); @@ -2356,7 +2357,7 @@ bool idle_startup() if (!gNoRender) { - // JC: Initializing audio requests many sounds for download. + //Now that we're loading the world, initialize the audio engine. init_audio(); display_startup(); @@ -2535,6 +2536,8 @@ bool idle_startup() LLViewerShaderMgr::instance()->setShaders(); display_startup(); } + //Precache UI sounds. + precache_audio(); } return TRUE; @@ -2677,13 +2680,8 @@ bool idle_startup() gSavedSettings.setF32("RenderFarClip", 32.0f); } - // Unmute audio if desired and setup volumes. - // Unmute audio if desired and setup volumes. - // This is a not-uncommon crash site, so surround it with - // llinfos output to aid diagnosis. - LL_INFOS("AppInit") << "Doing first audio_update_volume..." << LL_ENDL; - audio_update_volume(); - LL_INFOS("AppInit") << "Done first audio_update_volume." << LL_ENDL; + //Agent avatar is ready. Create the listener. + audio_update_listener(); // reset keyboard focus to sane state of pointing at world gFocusMgr.setKeyboardFocus(NULL); diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index fd8915e84..7a6b74e35 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -46,28 +46,15 @@ ///////////////////////////////////////////////////////// -void init_audio() +void precache_audio() { - if (!gAudiop) - { - llwarns << "Failed to create an appropriate Audio Engine" << llendl; + static bool already_precached = false; + if(already_precached) return; - } - LLVector3d lpos_global = gAgentCamera.getCameraPositionGlobal(); - LLVector3 lpos_global_f; + already_precached = true; - lpos_global_f.setVec(lpos_global); - - gAudiop->setListener(lpos_global_f, - LLVector3::zero, // LLViewerCamera::getInstance()->getVelocity(), // !!! BUG need to replace this with smoothed velocity! - LLViewerCamera::getInstance()->getUpAxis(), - LLViewerCamera::getInstance()->getAtAxis()); - -// load up our initial set of sounds we'll want so they're in memory and ready to be played - - BOOL mute_audio = gSavedSettings.getBOOL("MuteAudio"); - - if (!mute_audio && FALSE == gSavedSettings.getBOOL("NoPreload")) + // load up our initial set of sounds we'll want so they're in memory and ready to be played + if (gAudiop && !gSavedSettings.getBOOL("MuteAudio") && !gSavedSettings.getBOOL("NoPreload")) { gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndAlert"))); gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndBadKeystroke"))); @@ -110,11 +97,9 @@ void init_audio() gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndWindowClose"))); gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndWindowOpen"))); } - - audio_update_volume(true); } -void audio_update_volume(bool force_update) +void audio_update_volume( bool wind_fade ) { static const LLCachedControl master_volume("AudioLevelMaster",1.0); static const LLCachedControl audio_level_sfx("AudioLevelSFX",1.0); @@ -154,11 +139,6 @@ void audio_update_volume(bool force_update) gAudiop->setRolloffFactor( audio_level_underwater_rolloff ); gAudiop->setMuted(mute_audio); - - if (force_update) - { - audio_update_wind(true); - } // handle secondary gains gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_SFX, @@ -167,6 +147,8 @@ void audio_update_volume(bool force_update) mute_ui ? 0.f : audio_level_ui); gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_AMBIENT, mute_ambient ? 0.f : audio_level_ambient); + + audio_update_wind(wind_fade); } // Streaming Music @@ -217,17 +199,23 @@ void audio_update_listener() } } -void audio_update_wind(bool force_update) +void audio_update_wind(bool fade) { #ifdef kAUDIO_ENABLE_WIND - if(gAgent.getRegion()) + if(gAgent.getRegion() && gAudiop) { // Scale down the contribution of weather-simulation wind to the // ambient wind noise. Wind velocity averages 3.5 m/s, with gusts to 7 m/s // whereas steady-state avatar walk velocity is only 3.2 m/s. // Without this the world feels desolate on first login when you are // standing still. - static LLCachedControl wind_level("AudioLevelWind", 0.5f); + + static LLCachedControl wind_level("AudioLevelWind", 0.5f); + static LLCachedControl mute_audio("MuteAudio", false); + static LLCachedControl mute_ambient("MuteAmbient", false); + static LLCachedControl audio_level_master("AudioLevelMaster", 1.f); + static LLCachedControl audio_level_ambient("AudioLevelAmbient", 1.f); + LLVector3 scaled_wind_vec = gWindVec * wind_level; // Mix in the avatar's motion, subtract because when you walk north, @@ -240,18 +228,18 @@ void audio_update_wind(bool force_update) // don't use the setter setMaxWindGain() because we don't // want to screw up the fade-in on startup by setting actual source gain // outside the fade-in. - F32 master_volume = gSavedSettings.getBOOL("MuteAudio") ? 0.f : gSavedSettings.getF32("AudioLevelMaster"); - F32 ambient_volume = gSavedSettings.getBOOL("MuteAmbient") ? 0.f : gSavedSettings.getF32("AudioLevelAmbient"); + F32 master_volume = mute_audio ? 0.f : audio_level_master; + F32 ambient_volume = mute_ambient ? 0.f : audio_level_ambient; F32 max_wind_volume = master_volume * ambient_volume; const F32 WIND_SOUND_TRANSITION_TIME = 2.f; - // amount to change volume this frame - F32 volume_delta = (LLFrameTimer::getFrameDeltaTimeF32() / WIND_SOUND_TRANSITION_TIME) * max_wind_volume; - if (force_update) + + F32 volume_delta = 1.f; + + if(fade) { - // initialize wind volume (force_update) by using large volume_delta - // which is sufficient to completely turn off or turn on wind noise - volume_delta = 1.f; + // amount to change volume this frame + volume_delta = (LLFrameTimer::getFrameDeltaTimeF32() / WIND_SOUND_TRANSITION_TIME) * max_wind_volume; } static LLCachedControl MuteWind("MuteWind"); diff --git a/indra/newview/llvieweraudio.h b/indra/newview/llvieweraudio.h index a80f03047..7e08024c1 100644 --- a/indra/newview/llvieweraudio.h +++ b/indra/newview/llvieweraudio.h @@ -39,9 +39,9 @@ #define kAUDIO_NUM_BUFFERS 30 #define kAUDIO_NUM_SOURCES 30 -void init_audio(); -void audio_update_volume(bool force_update = true); +void precache_audio(); +void audio_update_volume(bool wind_fade = true); void audio_update_listener(); -void audio_update_wind(bool force_update = true); +void audio_update_wind(bool fade); #endif //LL_VIEWER_H diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 545de0e3b..23e407d40 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -355,7 +355,7 @@ static bool handleChatPersistTimeChanged(const LLSD& newvalue) static void handleAudioVolumeChanged(const LLSD& newvalue) { - audio_update_volume(true); + audio_update_volume(false); } static bool handleJoystickChanged(const LLSD& newvalue) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 9e4b21ac2..fb0264b56 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -5328,8 +5328,6 @@ void process_preload_sound(LLMessageSystem *msg, void **user_data) LLAudioSource *sourcep = objectp->getAudioSource(owner_id); if (!sourcep) return; - LLAudioData *datap = gAudiop->getAudioData(sound_id); - // Note that I don't actually do any loading of the // audio data into a buffer at this point, as it won't actually // help us out. @@ -5338,8 +5336,8 @@ void process_preload_sound(LLMessageSystem *msg, void **user_data) LLVector3d pos_global = objectp->getPositionGlobal(); if (gAgent.canAccessMaturityAtGlobal(pos_global)) { - // Add audioData starts a transfer internally. - sourcep->addAudioData(datap, FALSE); + // Preload starts a transfer internally. + sourcep->preload(sound_id); } } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index bb5526873..894b01b79 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1432,7 +1432,7 @@ BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated) } // Unmute audio - audio_update_volume(); + audio_update_volume(false); } else { @@ -1457,7 +1457,7 @@ BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated) stopGL(); } // Mute audio - audio_update_volume(); + audio_update_volume(false); } return TRUE; } diff --git a/indra/newview/shfloatermediaticker.cpp b/indra/newview/shfloatermediaticker.cpp index c44b3fdb9..744ac5561 100644 --- a/indra/newview/shfloatermediaticker.cpp +++ b/indra/newview/shfloatermediaticker.cpp @@ -83,6 +83,9 @@ SHFloaterMediaTicker::SHFloaterMediaTicker() : LLFloater()/*, LLSingletongetStreamingAudioImpl()->isPlaying() != 1; //will return 1 if playing. bool dirty = setPaused(stream_paused); @@ -119,7 +122,7 @@ void SHFloaterMediaTicker::updateTickerText() //called via draw. void SHFloaterMediaTicker::drawOscilloscope() //called via draw. { - if(!mVisualizer || !gAudiop->getStreamingAudioImpl()->supportsWaveData()) + if(!gAudiop || !mVisualizer || !gAudiop->getStreamingAudioImpl()->supportsWaveData()) return; static const S32 NUM_LINE_STRIPS = 64; //How many lines to draw. 64 is more than enough.