From 36c8c92098004c4f2eb80114a49f3660a2d3dcbb Mon Sep 17 00:00:00 2001
From: maksymsproductengine <maksymsproductengine@lindenlab.com>
Date: Fri, 14 Mar 2014 06:39:09 +0200
Subject: MAINT-3804 FIXED Crash in LLAudioEngine::getAudioData when playing
 gestures with audio device disabled.

---
 indra/llaudio/llaudiodecodemgr.cpp   | 17 +++++---
 indra/llaudio/llaudioengine.cpp      | 66 +++++++++++++++++++++++++------
 indra/newview/lldeferredsounds.cpp   |  5 ++-
 indra/newview/llpanelnearbymedia.cpp |  9 +++++
 indra/newview/llpreviewsound.cpp     |  2 +
 indra/newview/llstartup.cpp          |  9 ++---
 indra/newview/llvieweraudio.cpp      | 76 +++++++++++++++++++++++-------------
 indra/newview/llviewermessage.cpp    | 13 ++++--
 indra/newview/llviewerobject.cpp     | 10 ++---
 indra/newview/llviewerwindow.cpp     |  5 +--
 10 files changed, 147 insertions(+), 65 deletions(-)

diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp
index 8c31f8b4de..ef63b2cc04 100755
--- a/indra/llaudio/llaudiodecodemgr.cpp
+++ b/indra/llaudio/llaudiodecodemgr.cpp
@@ -570,9 +570,14 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs)
 				// We had an error when decoding, abort.
 				LL_WARNS("AudioEngine") << mCurrentDecodep->getUUID() << " has invalid vorbis data, aborting decode" << LL_ENDL;
 				mCurrentDecodep->flushBadFile();
-				LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID());
-				adp->setHasValidData(false);
-				adp->setHasCompletedDecode(true);
+
+				if (gAudiop)
+				{
+					LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID());
+					adp->setHasValidData(false);
+					adp->setHasCompletedDecode(true);
+				}
+
 				mCurrentDecodep = NULL;
 				done = TRUE;
 			}
@@ -584,7 +589,7 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs)
 			}
 			else if (mCurrentDecodep)
 			{
-				if (mCurrentDecodep->finishDecode())
+				if (gAudiop && mCurrentDecodep->finishDecode())
 				{
 					// We finished!
 					LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID());
@@ -625,7 +630,7 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs)
 			{
 				LLUUID uuid;
 				mDecodeQueue.pop(uuid);
-				if (gAudiop->hasDecodedFile(uuid))
+				if (!gAudiop || gAudiop->hasDecodedFile(uuid))
 				{
 					// This file has already been decoded, don't decode it again.
 					continue;
@@ -671,7 +676,7 @@ void LLAudioDecodeMgr::processQueue(const F32 num_secs)
 
 BOOL LLAudioDecodeMgr::addDecodeRequest(const LLUUID &uuid)
 {
-	if (gAudiop->hasDecodedFile(uuid))
+	if (gAudiop && gAudiop->hasDecodedFile(uuid))
 	{
 		// Already have a decoded version, don't need to decode it.
 		LL_DEBUGS("AudioEngine") << "addDecodeRequest for " << uuid << " has decoded file already" << LL_ENDL;
diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp
index ca614f5395..ecdfcaf73a 100755
--- a/indra/llaudio/llaudioengine.cpp
+++ b/indra/llaudio/llaudioengine.cpp
@@ -674,8 +674,8 @@ void LLAudioEngine::cleanupBuffer(LLAudioBuffer *bufferp)
 bool LLAudioEngine::preloadSound(const LLUUID &uuid)
 {
 	LL_DEBUGS("AudioEngine")<<"( "<<uuid<<" )"<<LL_ENDL;
-	
-	gAudiop->getAudioData(uuid);	// We don't care about the return value, this is just to make sure
+
+	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
 
 	if (gAudioDecodeMgrp->addDecodeRequest(uuid))
@@ -828,7 +828,7 @@ void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_i
 	source_id.generate();
 
 	LLAudioSource *asp = new LLAudioSource(source_id, owner_id, gain, type);
-	gAudiop->addAudioSource(asp);
+	addAudioSource(asp);
 	if (pos_global.isExactlyZero())
 	{
 		asp->setAmbient(true);
@@ -1211,8 +1211,8 @@ void LLAudioEngine::startNextTransfer()
 	if (asset_id.notNull())
 	{
 		LL_INFOS("AudioEngine") << "Getting audio asset data for: " << asset_id << LL_ENDL;
-		gAudiop->mCurrentTransfer = asset_id;
-		gAudiop->mCurrentTransferTimer.reset();
+		mCurrentTransfer = asset_id;
+		mCurrentTransferTimer.reset();
 		gAssetStorage->getAssetData(asset_id, LLAssetType::AT_SOUND,
 									assetCallback, NULL);
 	}
@@ -1226,6 +1226,12 @@ void LLAudioEngine::startNextTransfer()
 // static
 void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status)
 {
+	if (!gAudiop)
+	{
+		LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
+		return;
+	}
+
 	if (result_code)
 	{
 		LL_INFOS("AudioEngine") << "Boom, error in audio file transfer: " << LLAssetStorage::getErrorString( result_code ) << " (" << result_code << ")" << LL_ENDL;
@@ -1350,7 +1356,12 @@ void LLAudioSource::updatePriority()
 		// Priority is based on distance
 		LLVector3 dist_vec;
 		dist_vec.setVec(getPositionGlobal());
-		dist_vec -= gAudiop->getListenerPos();
+
+		if (gAudiop)
+		{
+			dist_vec -= gAudiop->getListenerPos();
+		}
+
 		F32 dist_squared = llmax(1.f, dist_vec.magVecSquared());
 
 		mPriority = mGain / dist_squared;
@@ -1367,6 +1378,11 @@ bool LLAudioSource::setupChannel()
 		return false;
 	}
 
+	if (!gAudiop)
+	{
+		LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
+		return false;
+	}
 
 	if (!mChannelp)
 	{
@@ -1410,6 +1426,12 @@ bool LLAudioSource::play(const LLUUID &audio_uuid)
 	// Reset our age timeout if someone attempts to play the source.
 	mAgeTimer.reset();
 
+	if (!gAudiop)
+	{
+		LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
+		return false;
+	}
+
 	LLAudioData *adp = gAudiop->getAudioData(audio_uuid);
 	addAudioData(adp);
 
@@ -1517,6 +1539,13 @@ void LLAudioSource::addAudioData(LLAudioData *adp, const bool set_current)
 {
 	// Only handle a single piece of audio data associated with a source right now,
 	// until I implement prefetch.
+
+	if (!gAudiop)
+	{
+		LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
+		return;
+	}
+
 	if (set_current)
 	{
 		if (!mCurrentDatap)
@@ -1685,6 +1714,12 @@ void LLAudioChannel::setSource(LLAudioSource *sourcep)
 
 bool LLAudioChannel::updateBuffer()
 {
+	if (!gAudiop)
+	{
+		LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
+		return false;
+	}
+
 	if (!mCurrentSourcep)
 	{
 		// This channel isn't associated with any source, nothing
@@ -1693,10 +1728,7 @@ bool LLAudioChannel::updateBuffer()
 	}
 
 	// Initialize the channel's gain setting for this sound.
-	if(gAudiop)
-	{
-		setSecondaryGain(gAudiop->getSecondaryGain(mCurrentSourcep->getType()));
-	}
+	setSecondaryGain(gAudiop->getSecondaryGain(mCurrentSourcep->getType()));
 
 	LLAudioBuffer *bufferp = mCurrentSourcep->getCurrentBuffer();
 	if (bufferp == mCurrentBufferp)
@@ -1753,8 +1785,14 @@ LLAudioData::LLAudioData(const LLUUID &uuid) :
 		// This is a null sound.
 		return;
 	}
+
+	if (!gAudiop)
+	{
+		LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
+		return;
+	}
 	
-	if (gAudiop && gAudiop->hasDecodedFile(uuid))
+	if (gAudiop->hasDecodedFile(uuid))
 	{
 		// Already have a decoded version, don't need to decode it.
 		setHasLocalData(true);
@@ -1777,6 +1815,12 @@ bool LLAudioData::load()
 		LL_INFOS("AudioEngine") << "Already have a buffer for this sound, don't bother loading!" << LL_ENDL;
 		return true;
 	}
+
+	if (!gAudiop)
+	{
+		LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
+		return false;
+	}
 	
 	mBufferp = gAudiop->getFreeBuffer();
 	if (!mBufferp)
diff --git a/indra/newview/lldeferredsounds.cpp b/indra/newview/lldeferredsounds.cpp
index 9416e7cd29..e1613e4719 100755
--- a/indra/newview/lldeferredsounds.cpp
+++ b/indra/newview/lldeferredsounds.cpp
@@ -39,7 +39,10 @@ void LLDeferredSounds::playdeferredSounds()
 {
 	while(soundVector.size())
 	{
-		gAudiop->triggerSound(soundVector.back());
+		if (gAudiop)
+		{
+			gAudiop->triggerSound(soundVector.back());
+		}
 		soundVector.pop_back();
 	}
 }
diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp
index a50d9074f7..edcf0d0452 100755
--- a/indra/newview/llpanelnearbymedia.cpp
+++ b/indra/newview/llpanelnearbymedia.cpp
@@ -876,7 +876,10 @@ void LLPanelNearByMedia::onClickParcelAudioPlay()
 	// playing and updated as they cross to other parcels etc.
 	mParcelAudioAutoStart = true;
 	if (!gAudiop)
+	{
+		LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
 		return;
+	}
 
 	if (LLAudioEngine::AUDIO_PAUSED == gAudiop->isInternetStreamPlaying())
 	{
@@ -896,7 +899,10 @@ void LLPanelNearByMedia::onClickParcelAudioStop()
 	// they explicitly start it again.
 	mParcelAudioAutoStart = false;
 	if (!gAudiop)
+	{
+		LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
 		return;
+	}
 
 	LLViewerAudio::getInstance()->stopInternetStreamWithAutoFade();
 }
@@ -904,7 +910,10 @@ void LLPanelNearByMedia::onClickParcelAudioStop()
 void LLPanelNearByMedia::onClickParcelAudioPause()
 {
 	if (!gAudiop)
+	{
+		LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
 		return;
+	}
 
 	// 'true' means pause
 	gAudiop->pauseInternetStream(true);
diff --git a/indra/newview/llpreviewsound.cpp b/indra/newview/llpreviewsound.cpp
index 39ec6def91..11b81a58fc 100755
--- a/indra/newview/llpreviewsound.cpp
+++ b/indra/newview/llpreviewsound.cpp
@@ -55,7 +55,9 @@ BOOL	LLPreviewSound::postBuild()
 	{
 		getChild<LLUICtrl>("desc")->setValue(item->getDescription());
 		if (gAudiop)
+		{
 			gAudiop->preloadSound(item->getAssetUUID()); // preload the sound
+		}
 	}
 	
 	childSetAction("Sound play btn",&LLPreviewSound::playSound,this);
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index d5f8a1e46e..635776713d 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -624,25 +624,22 @@ bool idle_startup()
 
 		if (FALSE == gSavedSettings.getBOOL("NoAudio"))
 		{
+			delete gAudiop;
 			gAudiop = NULL;
 
 #ifdef LL_FMODEX		
-			if (!gAudiop
 #if !LL_WINDOWS
-			    && NULL == getenv("LL_BAD_FMODEX_DRIVER")
+			if (NULL == getenv("LL_BAD_FMODEX_DRIVER")
 #endif // !LL_WINDOWS
-			    )
 			{
 				gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODEX(gSavedSettings.getBOOL("FMODExProfilerEnable"));
 			}
 #endif
 
 #ifdef LL_OPENAL
-			if (!gAudiop
 #if !LL_WINDOWS
-			    && NULL == getenv("LL_BAD_OPENAL_DRIVER")
+			if (NULL == getenv("LL_BAD_OPENAL_DRIVER")
 #endif // !LL_WINDOWS
-			    )
 			{
 				gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL();
 			}
diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp
index 826d296117..fce42a1587 100755
--- a/indra/newview/llvieweraudio.cpp
+++ b/indra/newview/llvieweraudio.cpp
@@ -93,7 +93,12 @@ void LLViewerAudio::startInternetStreamWithAutoFade(std::string streamURI)
 
 	switch (mFadeState)
 	{
-		case FADE_IDLE:
+	case FADE_IDLE:
+		if (!gAudiop)
+		{
+			LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
+			break;
+		}
 		// If a stream is playing fade it out first
 		if (!gAudiop->getInternetStreamURL().empty())
 		{
@@ -115,18 +120,18 @@ void LLViewerAudio::startInternetStreamWithAutoFade(std::string streamURI)
 			break;
 		}
 
-		case FADE_OUT:
-			startFading();
-			registerIdleListener();
-			break;
+	case FADE_OUT:
+		startFading();
+		registerIdleListener();
+		break;
 
-		case FADE_IN:
-			registerIdleListener();
-			break;
+	case FADE_IN:
+		registerIdleListener();
+		break;
 
-		default:
-			llwarns << "Unknown fading state: " << mFadeState << llendl;
-			break;
+	default:
+		llwarns << "Unknown fading state: " << mFadeState << llendl;
+		break;
 	}
 }
 
@@ -157,19 +162,26 @@ bool LLViewerAudio::onIdleUpdate()
 		// we have finished the current fade operation
 		if (mFadeState == FADE_OUT)
 		{
-			// Clear URI
-			gAudiop->startInternetStream(LLStringUtil::null);
-			gAudiop->stopInternetStream();
+			if (gAudiop)
+			{
+				// Clear URI
+				gAudiop->startInternetStream(LLStringUtil::null);
+				gAudiop->stopInternetStream();
+			}
 				
 			if (!mNextStreamURI.empty())
 			{
 				mFadeState = FADE_IN;
 
-				LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl();
-				if(stream && stream->supportsAdjustableBufferSizes())
-					stream->setBufferSizes(gSavedSettings.getU32("FMODExStreamBufferSize"),gSavedSettings.getU32("FMODExDecodeBufferSize"));
+				if (gAudiop)
+				{
+					LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl();
+					if(stream && stream->supportsAdjustableBufferSizes())
+						stream->setBufferSizes(gSavedSettings.getU32("FMODExStreamBufferSize"),gSavedSettings.getU32("FMODExDecodeBufferSize"));
+
+					gAudiop->startInternetStream(mNextStreamURI);
+				}
 
-				gAudiop->startInternetStream(mNextStreamURI);
 				startFading();
 			}
 			else
@@ -181,7 +193,7 @@ bool LLViewerAudio::onIdleUpdate()
 		}
 		else if (mFadeState == FADE_IN)
 		{
-			if (mNextStreamURI != gAudiop->getInternetStreamURL())
+			if (gAudiop && mNextStreamURI != gAudiop->getInternetStreamURL())
 			{
 				mFadeState = FADE_OUT;
 				startFading();
@@ -203,9 +215,12 @@ void LLViewerAudio::stopInternetStreamWithAutoFade()
 	mFadeState = FADE_IDLE;
 	mNextStreamURI = LLStringUtil::null;
 	mDone = true;
-
-	gAudiop->startInternetStream(LLStringUtil::null);
-	gAudiop->stopInternetStream();
+	
+	if (gAudiop)
+	{
+		gAudiop->startInternetStream(LLStringUtil::null);
+		gAudiop->stopInternetStream();
+	}
 }
 
 void LLViewerAudio::startFading()
@@ -267,7 +282,7 @@ F32 LLViewerAudio::getFadeVolume()
 
 void LLViewerAudio::onTeleportStarted()
 {
-	if (!LLViewerAudio::getInstance()->getForcedTeleportFade())
+	if (gAudiop && !LLViewerAudio::getInstance()->getForcedTeleportFade())
 	{
 		// Even though the music was turned off it was starting up (with autoplay disabled) occasionally
 		// after a failed teleport or after an intra-parcel teleport.  Also, the music sometimes was not
@@ -393,9 +408,10 @@ void audio_update_volume(bool force_update)
 	}
 	F32 mute_volume = mute_audio ? 0.0f : 1.0f;
 
-	// Sound Effects
 	if (gAudiop) 
 	{
+		// Sound Effects
+
 		gAudiop->setMasterGain ( master_volume );
 
 		gAudiop->setDopplerFactor(gSavedSettings.getF32("AudioLevelDoppler"));
@@ -425,11 +441,9 @@ void audio_update_volume(bool force_update)
 								  gSavedSettings.getBOOL("MuteUI") ? 0.f : gSavedSettings.getF32("AudioLevelUI"));
 		gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_AMBIENT,
 								  gSavedSettings.getBOOL("MuteAmbient") ? 0.f : gSavedSettings.getF32("AudioLevelAmbient"));
-	}
 
-	// Streaming Music
-	if (gAudiop) 
-	{
+		// Streaming Music
+
 		if (!progress_view_visible && LLViewerAudio::getInstance()->getForcedTeleportFade())
 		{
 			LLViewerAudio::getInstance()->setWasPlaying(!gAudiop->getInternetStreamURL().empty());
@@ -527,6 +541,12 @@ void audio_update_wind(bool force_update)
 			volume_delta = 1.f;
 		}
 
+		if (!gAudiop)
+		{
+			LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
+			return;
+		}
+
 		// mute wind when not flying
 		if (gAgent.getFlying())
 		{
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 2dbdceed66..9d12587801 100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -4652,7 +4652,11 @@ void process_time_synch(LLMessageSystem *mesgsys, void **user_data)
 
 void process_sound_trigger(LLMessageSystem *msg, void **)
 {
-	if (!gAudiop) return;
+	if (!gAudiop)
+	{
+		LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
+		return;
+	}
 
 	U64		region_handle = 0;
 	F32		gain = 0;
@@ -4712,6 +4716,7 @@ void process_preload_sound(LLMessageSystem *msg, void **user_data)
 {
 	if (!gAudiop)
 	{
+		LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
 		return;
 	}
 
@@ -4742,9 +4747,9 @@ 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);
-}
+		// Add audioData starts a transfer internally.
+		sourcep->addAudioData(datap, FALSE);
+	}
 }
 
 void process_attached_sound(LLMessageSystem *msg, void **user_data)
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index e62998db70..c789719291 100755
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -4950,6 +4950,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow
 {
 	if (!gAudiop)
 	{
+		LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
 		return;
 	}
 	
@@ -5032,7 +5033,10 @@ LLAudioSource *LLViewerObject::getAudioSource(const LLUUID& owner_id)
 		LLAudioSourceVO *asvop = new LLAudioSourceVO(mID, owner_id, 0.01f, this);
 
 		mAudioSourcep = asvop;
-		if(gAudiop) gAudiop->addAudioSource(asvop);
+		if(gAudiop)
+		{
+			gAudiop->addAudioSource(asvop);
+		}
 	}
 
 	return mAudioSourcep;
@@ -5040,10 +5044,6 @@ LLAudioSource *LLViewerObject::getAudioSource(const LLUUID& owner_id)
 
 void LLViewerObject::adjustAudioGain(const F32 gain)
 {
-	if (!gAudiop)
-	{
-		return;
-	}
 	if (mAudioSourcep)
 	{
 		mAudioGain = gain;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 3193a2955b..f2b5ef54fd 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -438,10 +438,7 @@ public:
 		}
 		if (gDisplayWindInfo)
 		{
-			if (gAudiop)
-			{
-				audio_text= llformat("Audio for wind: %d", gAudiop->isWindEnabled());
-			}
+			audio_text = llformat("Audio for wind: %d", gAudiop ? gAudiop->isWindEnabled() : -1);
 			addText(xpos, ypos, audio_text);  ypos += y_inc;
 		}
 		if (gDisplayFOV)
-- 
cgit v1.2.3