Commits

Monroe Linden committed 5b6e262

svn merge -r 129841:129910 svn+ssh://svn.lindenlab.com/svn/linden/branches/moss/pluginapi_05-merge@129910

svn merge -r 129913:131718 svn+ssh://svn.lindenlab.com/svn/linden/branches/pluginapi/pluginapi_05

Some branch shenannigans in the pluginapi_05 branch caused this to become a two-part merge.

Comments (0)

Files changed (224)

 					<key>trusted-sender</key>
 					<boolean>true</boolean>
 				</map>
+
+				<key>ParcelMediaURLFilter</key>
+				<map>
+					<key>flavor</key>
+					<string>llsd</string>
+					<key>trusted-sender</key>
+					<boolean>false</boolean>
+				</map>
 				
+				<key>ParcelNavigateMedia</key>
+				<map>
+					<key>flavor</key>
+					<string>llsd</string>
+					<key>trusted-sender</key>
+					<boolean>false</boolean>
+				</map>
+
 				<key>ParcelObjectOwnersReply</key>
 				<map>
 					<key>flavor</key>

indra/CMakeLists.txt

 add_subdirectory(${LIBS_OPEN_PREFIX}llimagej2coj)
 add_subdirectory(${LIBS_OPEN_PREFIX}llinventory)
 add_subdirectory(${LIBS_OPEN_PREFIX}llmath)
-add_subdirectory(${LIBS_OPEN_PREFIX}llmedia)
 add_subdirectory(${LIBS_OPEN_PREFIX}llmessage)
 add_subdirectory(${LIBS_OPEN_PREFIX}llprimitive)
 add_subdirectory(${LIBS_OPEN_PREFIX}llrender)
 add_custom_target(viewer)
 if (VIEWER)
   add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger)
+  add_subdirectory(${LIBS_OPEN_PREFIX}llplugin)
   add_subdirectory(${LIBS_OPEN_PREFIX}llui)
   add_subdirectory(${LIBS_OPEN_PREFIX}llxuixml)
 
+  # viewer media plugins
+  add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins)
+
+  # llplugin testbed code (is this the right way to include it?)
+  if (NOT LINUX)
+    add_subdirectory(${VIEWER_PREFIX}test_apps/llplugintest)
+  endif (NOT LINUX)
+
   if (LINUX)
     add_subdirectory(${VIEWER_PREFIX}linux_crash_logger)
     add_subdirectory(${VIEWER_PREFIX}linux_updater)

indra/cmake/CMakeLists.txt

     FindXmlRpcEpi.cmake
     FMOD.cmake
     FreeType.cmake
-    GStreamer.cmake
+    GStreamer010Plugin.cmake
     GooglePerfTools.cmake
     JPEG.cmake
     LLAddBuildTest.cmake
     LLInventory.cmake
     LLKDU.cmake
     LLMath.cmake
-    LLMedia.cmake
     LLMessage.cmake
+    LLPlugin.cmake
     LLPrimitive.cmake
     LLRender.cmake
     LLScene.cmake
     LScript.cmake
     Linking.cmake
     MonoEmbed.cmake
-    Mozlib.cmake
     MySQL.cmake
     NDOF.cmake
     OPENAL.cmake
     PNG.cmake
     Python.cmake
     Prebuilt.cmake
-    QuickTime.cmake
     RunBuildTest.cmake
     TemplateCheck.cmake
     Tut.cmake

indra/cmake/GStreamer010Plugin.cmake

+# -*- cmake -*-
+include(Prebuilt)
+
+if (STANDALONE)
+  include(FindPkgConfig)
+
+  pkg_check_modules(GSTREAMER010 REQUIRED gstreamer-0.10)
+  pkg_check_modules(GSTREAMER010_PLUGINS_BASE REQUIRED gstreamer-plugins-base-0.10)
+elseif (LINUX)
+  use_prebuilt_binary(gstreamer)
+  # possible libxml should have its own .cmake file instead
+  use_prebuilt_binary(libxml)
+  set(GSTREAMER010_FOUND ON FORCE BOOL)
+  set(GSTREAMER010_PLUGINS_BASE_FOUND ON FORCE BOOL)
+  set(GSTREAMER010_INCLUDE_DIRS
+      ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/gstreamer-0.10
+      ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib-2.0
+      ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/libxml2
+      )
+  # We don't need to explicitly link against gstreamer itself, because
+  # LLMediaImplGStreamer probes for the system's copy at runtime.
+  set(GSTREAMER010_LIBRARIES
+      gobject-2.0
+      gmodule-2.0
+      dl
+      gthread-2.0
+      rt
+      glib-2.0
+      )
+endif (STANDALONE)
+
+if (GSTREAMER010_FOUND AND GSTREAMER010_PLUGINS_BASE_FOUND)
+  set(GSTREAMER010 ON CACHE BOOL "Build with GStreamer-0.10 streaming media support.")
+endif (GSTREAMER010_FOUND AND GSTREAMER010_PLUGINS_BASE_FOUND)
+
+if (GSTREAMER010)
+  add_definitions(-DLL_GSTREAMER010_ENABLED=1)
+endif (GSTREAMER010)
+

indra/cmake/Glui.cmake

+# -*- cmake -*-
+include(Linking)
+include(Prebuilt)
+
+if (STANDALONE)
+    set(GLUI OFF CACHE BOOL
+        "GLUI support for the llplugin/llmedia test apps.")
+else (STANDALONE)
+    use_prebuilt_binary(glui)
+    set(GLUI ON CACHE BOOL
+        "GLUI support for the llplugin/llmedia test apps.")
+endif (STANDALONE)
+
+if (LINUX)
+    set(GLUI ON CACHE BOOL
+        "llplugin media apps HACK for Linux.")
+endif (LINUX)
+
+if (DARWIN OR LINUX)
+    set(GLUI_LIBRARY
+        glui)
+endif (DARWIN OR LINUX)
+
+if (WINDOWS)
+    set(GLUI_LIBRARY
+        debug glui32.lib
+        optimized glui32.lib)
+endif (WINDOWS)

indra/cmake/Glut.cmake

+# -*- cmake -*-
+include(Linking)
+include(Prebuilt)
+
+if (WINDOWS)
+    use_prebuilt_binary(freeglut)
+    set(GLUT_LIBRARY
+        debug freeglut_static.lib
+        optimized freeglut_static.lib)
+endif (WINDOWS)
+
+if (LINUX)
+  FIND_LIBRARY(GLUT_LIBRARY glut)
+endif (LINUX)
+
+if (DARWIN)
+  include(CMakeFindFrameworks)
+  find_library(GLUT_LIBRARY GLUT)
+endif (DARWIN)

indra/cmake/LLPlugin.cmake

+# -*- cmake -*-
+
+
+set(LLPLUGIN_INCLUDE_DIRS
+    ${LIBS_OPEN_DIR}/llplugin
+    )
+
+set(LLPLUGIN_LIBRARIES llplugin)

indra/cmake/MediaPluginBase.cmake

+# -*- cmake -*-
+
+
+set(MEDIA_PLUGIN_BASE_INCLUDE_DIRS
+    ${LIBS_OPEN_DIR}/media_plugins/base/
+    )
+
+set(MEDIA_PLUGIN_BASE_LIBRARIES media_plugin_base)

indra/cmake/PluginAPI.cmake

+# -*- cmake -*-
+
+if (WINDOWS)
+  set(PLUGIN_API_WINDOWS_LIBRARIES
+      wsock32
+      ws2_32
+      psapi
+      netapi32
+      advapi32
+      user32
+      )
+else (WINDOWS)
+  set(PLUGIN_API_WINDOWS_LIBRARIES "")
+endif (WINDOWS)
+
+

indra/cmake/QuickTimePlugin.cmake

+# -*- cmake -*-
+
+if(INSTALL_PROPRIETARY)
+  include(Prebuilt)
+  use_prebuilt_binary(quicktime)
+endif(INSTALL_PROPRIETARY)
+
+if (DARWIN)
+  include(CMakeFindFrameworks)
+  find_library(QUICKTIME_LIBRARY QuickTime)
+elseif (WINDOWS)
+  set(QUICKTIME_SDK_DIR "$ENV{PROGRAMFILES}/QuickTime SDK"
+      CACHE PATH "Location of the QuickTime SDK.")
+
+  find_library(DEBUG_QUICKTIME_LIBRARY qtmlclient
+               PATHS
+               ${ARCH_PREBUILT_DIRS_DEBUG}
+               "${QUICKTIME_SDK_DIR}\\libraries"
+               )
+
+  find_library(RELEASE_QUICKTIME_LIBRARY qtmlclient
+               PATHS
+               ${ARCH_PREBUILT_DIRS_RELEASE}
+               "${QUICKTIME_SDK_DIR}\\libraries"
+               )
+
+  if (DEBUG_QUICKTIME_LIBRARY AND RELEASE_QUICKTIME_LIBRARY)
+    set(QUICKTIME_LIBRARY 
+        optimized ${RELEASE_QUICKTIME_LIBRARY}
+        debug ${DEBUG_QUICKTIME_LIBRARY}
+        )
+        
+  endif (DEBUG_QUICKTIME_LIBRARY AND RELEASE_QUICKTIME_LIBRARY)
+  
+  include_directories(
+    ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/quicktime
+    "${QUICKTIME_SDK_DIR}\\CIncludes"
+    )
+endif (DARWIN)
+
+mark_as_advanced(QUICKTIME_LIBRARY)
+
+if (QUICKTIME_LIBRARY)
+  set(QUICKTIME ON CACHE BOOL "Build with QuickTime streaming media support.")
+endif (QUICKTIME_LIBRARY)
+

indra/cmake/WebKitLibPlugin.cmake

+# -*- cmake -*-
+include(Linking)
+include(Prebuilt)
+
+if (STANDALONE)
+    set(WEBKITLIBPLUGIN OFF CACHE BOOL
+        "WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.")
+else (STANDALONE)
+    use_prebuilt_binary(webkitlibplugin)
+    set(WEBKITLIBPLUGIN ON CACHE BOOL
+        "WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.")
+endif (STANDALONE)
+
+if (WINDOWS)
+    set(WEBKIT_PLUGIN_LIBRARIES 
+    debug llwebkitlibd
+    debug QtWebKitd4
+    debug QtOpenGLd4
+    debug QtNetworkd4
+    debug QtGuid4
+    debug QtCored4
+    debug qtmaind
+    optimized llwebkitlib
+    optimized QtWebKit4
+    optimized QtOpenGL4
+    optimized QtNetwork4
+    optimized QtGui4
+    optimized QtCore4
+    optimized qtmain
+    )
+elseif (DARWIN)
+    set(WEBKIT_PLUGIN_LIBRARIES
+        optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libllwebkitlib.dylib
+        debug ${ARCH_PREBUILT_DIRS_RELEASE}/libllwebkitlib.dylib
+        )
+elseif (LINUX)
+    set(WEBKIT_PLUGIN_LIBRARIES
+        llwebkitlib
+
+        qgif
+#        qico
+        qjpeg
+#        qpng
+#        qtiff
+#        qsvg
+
+#        QtSvg
+        QtWebKit
+        QtOpenGL
+        QtNetwork
+        QtGui
+        QtCore
+
+        fontconfig
+        X11
+        GL
+
+#        sqlite3
+#        Xi
+#        SM
+        )
+endif (WINDOWS)
 
         if job_count is None:
             hosts, job_count = count_distcc_hosts()
+            hostname = socket.gethostname()
             if hosts == 1:
-                hostname = socket.gethostname()
                 if hostname.startswith('station'):
                     hosts, job_count = mk_distcc_hosts('station', 36, 2)
                     os.environ['DISTCC_HOSTS'] = hosts
                 if hostname.startswith('eniac'):
                     hosts, job_count = mk_distcc_hosts('eniac', 71, 2)
                     os.environ['DISTCC_HOSTS'] = hosts
-            if job_count > 12:
-                job_count = 12;
+            if hostname.startswith('build'):
+                max_jobs = 6
+            else:
+                max_jobs = 12
+            if job_count > max_jobs:
+                job_count = max_jobs;
             opts.extend(['-j', str(job_count)])
 
         if targets:
             targets = ' '.join(['-target ' + repr(t) for t in targets])
         else:
             targets = ''
-        # cmd = ('xcodebuild -parallelizeTargets ' # parallelizeTargets is suspected of non-deterministic build failures. + poppy 2009-06-05
-        cmd = ('xcodebuild '
-               '-configuration %s %s %s' %
+        cmd = ('xcodebuild -configuration %s %s %s' %
                (self.build_type, ' '.join(opts), targets))
         for d in self.build_dirs():
             try:

indra/llaudio/CMakeLists.txt

 
 include(00-Common)
 include(Audio)
+include(LLAudio)
 include(FMOD)
 include(OPENAL)
 include(LLCommon)
 include(LLMath)
 include(LLMessage)
 include(LLVFS)
-include(LLMedia)
 
 include_directories(
+    ${LLAUDIO_INCLUDE_DIRS}
     ${FMOD_INCLUDE_DIR}
     ${LLCOMMON_INCLUDE_DIRS}
     ${LLMATH_INCLUDE_DIRS}
     ${VORBIS_INCLUDE_DIRS}
     ${OPENAL_LIB_INCLUDE_DIRS}
     ${FREEAULT_LIB_INCLUDE_DIRS}
-    ${LLMEDIA_INCLUDE_DIRS}
     )
 
 set(llaudio_SOURCE_FILES
-    audioengine.cpp
-    listener.cpp
+    llaudioengine.cpp
+    lllistener.cpp
     llaudiodecodemgr.cpp
-    vorbisdecode.cpp
-    vorbisencode.cpp
+    llvorbisdecode.cpp
+    llvorbisencode.cpp
     )
 
 set(llaudio_HEADER_FILES
     CMakeLists.txt
 
-    audioengine.h
-    listener.h
+    llaudioengine.h
+    lllistener.h
     llaudiodecodemgr.h
-    vorbisdecode.h
-    vorbisencode.h
-    windgen.h
+    llvorbisdecode.h
+    llvorbisencode.h
+    llwindgen.h
     )
 
 if (FMOD)
     list(APPEND llaudio_SOURCE_FILES
-         audioengine_fmod.cpp
-         listener_fmod.cpp
+         llaudioengine_fmod.cpp
+         lllistener_fmod.cpp
+         llstreamingaudio_fmod.cpp
          )
 
     list(APPEND llaudio_HEADER_FILES
-         audioengine_fmod.h
-         listener_fmod.h
+         llaudioengine_fmod.h
+         lllistener_fmod.h
+         llstreamingaudio_fmod.h
          )
 
     if (LINUX)
       if (${CXX_VERSION} MATCHES "4.[23]")
-        set_source_files_properties(audioengine_fmod.cpp
+        set_source_files_properties(llaudioengine_fmod.cpp
                                     COMPILE_FLAGS -Wno-error=write-strings)
       endif (${CXX_VERSION} MATCHES "4.[23]")
     endif (LINUX)
 
 if (OPENAL)
   list(APPEND llaudio_SOURCE_FILES
-    audioengine_openal.cpp
-    listener_openal.cpp
+    llaudioengine_openal.cpp
+    lllistener_openal.cpp
     )
   
   list(APPEND llaudio_HEADER_FILES
-    audioengine_openal.h
-    listener_openal.h
+    llaudioengine_openal.h
+    lllistener_openal.h
     )
 endif (OPENAL)
 

indra/llaudio/llaudiodecodemgr.cpp

 
 #include "llaudiodecodemgr.h"
 
-#include "vorbisdecode.h"
-#include "audioengine.h"
+#include "llvorbisdecode.h"
+#include "llaudioengine.h"
 #include "lllfsthread.h"
 #include "llvfile.h"
 #include "llstring.h"

indra/llaudio/llaudioengine.cpp

+ /** 
+ * @file audioengine.cpp
+ * @brief implementation of LLAudioEngine class abstracting the Open
+ * AL audio support
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ * 
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llaudioengine.h"
+#include "llstreamingaudio.h"
+
+#include "llerror.h"
+#include "llmath.h"
+
+#include "sound_ids.h"  // temporary hack for min/max distances
+
+#include "llvfs.h"
+#include "lldir.h"
+#include "llaudiodecodemgr.h"
+#include "llassetstorage.h"
+
+
+// necessary for grabbing sounds from sim (implemented in viewer)	
+extern void request_sound(const LLUUID &sound_guid);
+
+LLAudioEngine* gAudiop = NULL;
+
+
+//
+// LLAudioEngine implementation
+//
+
+
+LLAudioEngine::LLAudioEngine()
+{
+	setDefaults();
+}
+
+
+LLAudioEngine::~LLAudioEngine()
+{
+}
+
+LLStreamingAudioInterface* LLAudioEngine::getStreamingAudioImpl()
+{
+	return mStreamingAudioImpl;
+}
+
+void LLAudioEngine::setStreamingAudioImpl(LLStreamingAudioInterface *impl)
+{
+	mStreamingAudioImpl = impl;
+}
+
+void LLAudioEngine::setDefaults()
+{
+	mMaxWindGain = 1.f;
+
+	mListenerp = NULL;
+
+	mMuted = false;
+	mUserData = NULL;
+
+	mLastStatus = 0;
+
+	mNumChannels = 0;
+	mEnableWind = false;
+
+	S32 i;
+	for (i = 0; i < MAX_CHANNELS; i++)
+	{
+		mChannels[i] = NULL;
+	}
+	for (i = 0; i < MAX_BUFFERS; i++)
+	{
+		mBuffers[i] = NULL;
+	}
+
+	mMasterGain = 1.f;
+	mNextWindUpdate = 0.f;
+
+	mStreamingAudioImpl = NULL;
+
+	for (U32 i = 0; i < LLAudioEngine::AUDIO_TYPE_COUNT; i++)
+		mSecondaryGain[i] = 1.0f;
+}
+
+
+bool LLAudioEngine::init(const S32 num_channels, void* userdata)
+{
+	setDefaults();
+
+	mNumChannels = num_channels;
+	mUserData = userdata;
+	
+	allocateListener();
+
+	// Initialize the decode manager
+	gAudioDecodeMgrp = new LLAudioDecodeMgr;
+
+	llinfos << "LLAudioEngine::init() AudioEngine successfully initialized" << llendl;
+
+	return true;
+}
+
+
+void LLAudioEngine::shutdown()
+{
+	// Clean up decode manager
+	delete gAudioDecodeMgrp;
+	gAudioDecodeMgrp = NULL;
+
+	// Clean up wind source
+	cleanupWind();
+
+	// Clean up audio sources
+	source_map::iterator iter_src;
+	for (iter_src = mAllSources.begin(); iter_src != mAllSources.end(); iter_src++)
+	{
+		delete iter_src->second;
+	}
+
+
+	// Clean up audio data
+	data_map::iterator iter_data;
+	for (iter_data = mAllData.begin(); iter_data != mAllData.end(); iter_data++)
+	{
+		delete iter_data->second;
+	}
+
+
+	// Clean up channels
+	S32 i;
+	for (i = 0; i < MAX_CHANNELS; i++)
+	{
+		delete mChannels[i];
+		mChannels[i] = NULL;
+	}
+
+	// Clean up buffers
+	for (i = 0; i < MAX_BUFFERS; i++)
+	{
+		delete mBuffers[i];
+		mBuffers[i] = NULL;
+	}
+}
+
+
+// virtual
+void LLAudioEngine::startInternetStream(const std::string& url)
+{
+	if (mStreamingAudioImpl)
+		mStreamingAudioImpl->start(url);
+}
+
+
+// virtual
+void LLAudioEngine::stopInternetStream()
+{
+	if (mStreamingAudioImpl)
+		mStreamingAudioImpl->stop();
+}
+
+// virtual
+void LLAudioEngine::pauseInternetStream(int pause)
+{
+	if (mStreamingAudioImpl)
+		mStreamingAudioImpl->pause(pause);
+}
+
+// virtual
+void LLAudioEngine::updateInternetStream()
+{
+	if (mStreamingAudioImpl)
+		mStreamingAudioImpl->update();
+}
+
+// virtual
+int LLAudioEngine::isInternetStreamPlaying()
+{
+	if (mStreamingAudioImpl)
+		return mStreamingAudioImpl->isPlaying();
+
+	return 0; // Stopped
+}
+
+
+// virtual
+void LLAudioEngine::setInternetStreamGain(F32 vol)
+{
+	if (mStreamingAudioImpl)
+		mStreamingAudioImpl->setGain(vol);
+}
+
+// virtual
+std::string LLAudioEngine::getInternetStreamURL()
+{
+	if (mStreamingAudioImpl)
+		return mStreamingAudioImpl->getURL();
+	else return std::string();
+}
+
+
+void LLAudioEngine::updateChannels()
+{
+	S32 i;
+	for (i = 0; i < MAX_CHANNELS; i++)
+	{
+		if (mChannels[i])
+		{
+			mChannels[i]->updateBuffer();
+			mChannels[i]->update3DPosition();
+			mChannels[i]->updateLoop();
+		}
+	}
+}
+
+static const F32 default_max_decode_time = .002f; // 2 ms
+void LLAudioEngine::idle(F32 max_decode_time)
+{
+	if (max_decode_time <= 0.f)
+	{
+		max_decode_time = default_max_decode_time;
+	}
+	
+	// "Update" all of our audio sources, clean up dead ones.
+	// Primarily does position updating, cleanup of unused audio sources.
+	// Also does regeneration of the current priority of each audio source.
+
+	if (getMuted())
+	{
+		setInternalGain(0.f);
+	}
+	else
+	{
+		setInternalGain(getMasterGain());
+	}
+
+	S32 i;
+	for (i = 0; i < MAX_BUFFERS; i++)
+	{
+		if (mBuffers[i])
+		{
+			mBuffers[i]->mInUse = false;
+		}
+	}
+
+	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();)
+	{
+		LLAudioSource *sourcep = iter->second;
+
+		// Update this source
+		sourcep->update();
+		sourcep->updatePriority();
+
+		if (sourcep->isDone())
+		{
+			// The source is done playing, clean it up.
+			delete sourcep;
+			mAllSources.erase(iter++);
+			continue;
+		}
+
+		if (!sourcep->getChannel() && sourcep->getCurrentBuffer())
+		{
+			// We could potentially play this sound if its priority is high enough.
+			if (sourcep->getPriority() > max_priority)
+			{
+				max_priority = sourcep->getPriority();
+				max_sourcep = sourcep;
+			}
+		}
+
+		// 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)
+		{
+			//llinfos << "Replacing source in channel due to priority!" << llendl;
+			max_sourcep->setChannel(channelp);
+			channelp->setSource(max_sourcep);
+			if (max_sourcep->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.
+				channelp->setWaiting(true);
+			}
+			else
+			{
+				channelp->setWaiting(false);
+				channelp->play();
+			}
+		}
+	}
+
+	
+	// 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)
+	{
+		// 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)
+		{
+			// Nothing queued, so we don't care.
+			continue;
+		}
+
+		LLAudioChannel *channelp = sourcep->getChannel();
+		if (!channelp)
+		{
+			// This sound isn't playing, so we just process move the queue
+			sourcep->mCurrentDatap = sourcep->mQueuedDatap;
+			sourcep->mQueuedDatap = NULL;
+
+			// 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);
+			}
+
+			// Actually play the associated data.
+			sourcep->setupChannel();
+			channelp = sourcep->getChannel();
+			if (channelp)
+			{
+				channelp->updateBuffer();
+				sourcep->getChannel()->play();
+			}
+			continue;
+		}
+		else
+		{
+			// Check to see if the current sound is done playing, or looped.
+			if (!channelp->isPlaying())
+			{
+				sourcep->mCurrentDatap = sourcep->mQueuedDatap;
+				sourcep->mQueuedDatap = NULL;
+
+				// 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);
+				}
+
+				// Actually play the associated data.
+				sourcep->setupChannel();
+				channelp->updateBuffer();
+				sourcep->getChannel()->play();
+			}
+			else if (sourcep->isLoop())
+			{
+				// It's a loop, we need to check and see if we're done with it.
+				if (channelp->mLoopedThisFrame)
+				{
+					sourcep->mCurrentDatap = sourcep->mQueuedDatap;
+					sourcep->mQueuedDatap = NULL;
+
+					// Actually, should do a time sync so if we're a loop master/slave
+					// we don't drift away.
+					sourcep->setupChannel();
+					sourcep->getChannel()->play();
+				}
+			}
+		}
+	}
+
+	// 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->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);
+				}
+			}
+		}
+	}
+
+	// Sync up everything that the audio engine needs done.
+	commitDeferredChanges();
+	
+	// Flush unused buffers that are stale enough
+	for (i = 0; i < MAX_BUFFERS; i++)
+	{
+		if (mBuffers[i])
+		{
+			if (!mBuffers[i]->mInUse && mBuffers[i]->mLastUseTimer.getElapsedTimeF32() > 30.f)
+			{
+				//llinfos << "Flushing unused buffer!" << llendl;
+				mBuffers[i]->mAudioDatap->mBufferp = NULL;
+				delete mBuffers[i];
+				mBuffers[i] = NULL;
+			}
+		}
+	}
+
+
+	// Clear all of the looped flags for the channels
+	for (i = 0; i < MAX_CHANNELS; i++)
+	{
+		if (mChannels[i])
+		{
+			mChannels[i]->mLoopedThisFrame = false;
+		}
+	}
+
+	// Decode audio files
+	gAudioDecodeMgrp->processQueue(max_decode_time);
+	
+	// Call this every frame, just in case we somehow
+	// missed picking it up in all the places that can add
+	// or request new data.
+	startNextTransfer();
+
+	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))
+	{
+		initWind();
+		mEnableWind = enable;
+	}
+	else if (mEnableWind && (!enable))
+	{
+		mEnableWind = enable;
+		cleanupWind();
+	}
+}
+
+
+LLAudioBuffer * LLAudioEngine::getFreeBuffer()
+{
+	S32 i;
+	for (i = 0; i < MAX_BUFFERS; i++)
+	{
+		if (!mBuffers[i])
+		{
+			mBuffers[i] = createBuffer();
+			return mBuffers[i];
+		}
+	}
+
+
+	// Grab the oldest unused buffer
+	F32 max_age = -1.f;
+	S32 buffer_id = -1;
+	for (i = 0; i < MAX_BUFFERS; i++)
+	{
+		if (mBuffers[i])
+		{
+			if (!mBuffers[i]->mInUse)
+			{
+				if (mBuffers[i]->mLastUseTimer.getElapsedTimeF32() > max_age)
+				{
+					max_age = mBuffers[i]->mLastUseTimer.getElapsedTimeF32();
+					buffer_id = i;
+				}
+			}
+		}
+	}
+
+	if (buffer_id >= 0)
+	{
+		llinfos << "Taking over unused buffer " << buffer_id << llendl;
+		//llinfos << "Flushing unused buffer!" << llendl;
+		mBuffers[buffer_id]->mAudioDatap->mBufferp = NULL;
+		delete mBuffers[buffer_id];
+		mBuffers[buffer_id] = createBuffer();
+		return mBuffers[buffer_id];
+	}
+	return NULL;
+}
+
+
+LLAudioChannel * LLAudioEngine::getFreeChannel(const F32 priority)
+{
+	S32 i;
+	for (i = 0; i < mNumChannels; i++)
+	{
+		if (!mChannels[i])
+		{
+			// No channel allocated here, use it.
+			mChannels[i] = createChannel();
+			return mChannels[i];
+		}
+		else
+		{
+			// Channel is allocated but not playing right now, use it.
+			if (!mChannels[i]->isPlaying() && !mChannels[i]->isWaiting())
+			{
+				mChannels[i]->cleanup();
+				if (mChannels[i]->getSource())
+				{
+					mChannels[i]->getSource()->setChannel(NULL);
+				}
+				return mChannels[i];
+			}
+		}
+	}
+
+	// All channels used, check priorities.
+	// Find channel with lowest priority and see if we want to replace it.
+	F32 min_priority = 10000.f;
+	LLAudioChannel *min_channelp = NULL;
+
+	for (i = 0; i < mNumChannels; i++)
+	{
+		LLAudioChannel *channelp = mChannels[i];
+		LLAudioSource *sourcep = channelp->getSource();
+		if (sourcep->getPriority() < min_priority)
+		{
+			min_channelp = channelp;
+			min_priority = sourcep->getPriority();
+		}
+	}
+
+	if (min_priority > priority || !min_channelp)
+	{
+		// All playing channels have higher priority, return.
+		return NULL;
+	}
+
+	// Flush the minimum priority channel, and return it.
+	min_channelp->cleanup();
+	min_channelp->getSource()->setChannel(NULL);
+	return min_channelp;
+}
+
+
+void LLAudioEngine::cleanupBuffer(LLAudioBuffer *bufferp)
+{
+	S32 i;
+	for (i = 0; i < MAX_BUFFERS; i++)
+	{
+		if (mBuffers[i] == bufferp)
+		{
+			delete mBuffers[i];
+			mBuffers[i] = NULL;
+		}
+	}
+}
+
+
+bool LLAudioEngine::preloadSound(const LLUUID &uuid)
+{
+	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
+
+	if (gAudioDecodeMgrp->addDecodeRequest(uuid))
+	{
+		// This means that we do have a local copy, and we're working on decoding it.
+		return true;
+	}
+
+	// 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;
+}
+
+
+bool LLAudioEngine::isWindEnabled()
+{
+	return mEnableWind;
+}
+
+
+void LLAudioEngine::setMuted(bool muted)
+{
+	mMuted = muted;
+	enableWind(!mMuted);
+}
+
+
+void LLAudioEngine::setMasterGain(const F32 gain)
+{
+	mMasterGain = gain;
+	setInternalGain(gain);
+}
+
+F32 LLAudioEngine::getMasterGain()
+{
+	return mMasterGain;
+}
+
+void LLAudioEngine::setSecondaryGain(S32 type, F32 gain)
+{
+	llassert(type < LLAudioEngine::AUDIO_TYPE_COUNT);
+	
+	mSecondaryGain[type] = gain;
+}
+
+F32 LLAudioEngine::getSecondaryGain(S32 type)
+{
+	return mSecondaryGain[type];
+}
+
+F32 LLAudioEngine::getInternetStreamGain()
+{
+	if (mStreamingAudioImpl)
+		return mStreamingAudioImpl->getGain();
+	else
+		return 1.0f;
+}
+
+void LLAudioEngine::setMaxWindGain(F32 gain)
+{
+	mMaxWindGain = gain;
+}
+
+
+F64 LLAudioEngine::mapWindVecToGain(LLVector3 wind_vec)
+{
+	F64 gain = 0.0;
+	
+	gain = wind_vec.magVec();
+
+	if (gain)
+	{
+		if (gain > 20)
+		{
+			gain = 20;
+		}
+		gain = gain/20.0;
+	}
+
+	return (gain);
+} 
+
+
+F64 LLAudioEngine::mapWindVecToPitch(LLVector3 wind_vec)
+{
+	LLVector3 listen_right;
+	F64 theta;
+  
+	// Wind frame is in listener-relative coordinates
+	LLVector3 norm_wind = wind_vec;
+	norm_wind.normVec();
+	listen_right.setVec(1.0,0.0,0.0);
+
+	// measure angle between wind vec and listener right axis (on 0,PI)
+	theta = acos(norm_wind * listen_right);
+
+	// put it on 0, 1
+	theta /= F_PI;					
+
+	// put it on [0, 0.5, 0]
+	if (theta > 0.5) theta = 1.0-theta;
+	if (theta < 0) theta = 0;
+
+	return (theta);
+}
+
+
+F64 LLAudioEngine::mapWindVecToPan(LLVector3 wind_vec)
+{
+	LLVector3 listen_right;
+	F64 theta;
+  
+	// Wind frame is in listener-relative coordinates
+	listen_right.setVec(1.0,0.0,0.0);
+
+	LLVector3 norm_wind = wind_vec;
+	norm_wind.normVec();
+
+	// measure angle between wind vec and listener right axis (on 0,PI)
+	theta = acos(norm_wind * listen_right);
+
+	// put it on 0, 1
+	theta /= F_PI;					
+
+	return (theta);
+}
+
+
+void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain,
+								 const S32 type, const LLVector3d &pos_global)
+{
+	// Create a new source (since this can't be associated with an existing source.
+	//llinfos << "Localized: " << audio_uuid << llendl;
+
+	if (mMuted)
+	{
+		return;
+	}
+
+	LLUUID source_id;
+	source_id.generate();
+
+	LLAudioSource *asp = new LLAudioSource(source_id, owner_id, gain, type);
+	gAudiop->addAudioSource(asp);
+	if (pos_global.isExactlyZero())
+	{
+		asp->setAmbient(true);
+	}
+	else
+	{
+		asp->setPositionGlobal(pos_global);
+	}
+	asp->updatePriority();
+	asp->play(audio_uuid);
+}
+
+
+void LLAudioEngine::setListenerPos(LLVector3 aVec)
+{
+	mListenerp->setPosition(aVec);  
+}
+
+
+LLVector3 LLAudioEngine::getListenerPos()
+{
+	if (mListenerp)
+	{
+		return(mListenerp->getPosition());  
+	}
+	else
+	{
+		return(LLVector3::zero);
+	}
+}
+
+
+void LLAudioEngine::setListenerVelocity(LLVector3 aVec)
+{
+	mListenerp->setVelocity(aVec);  
+}
+
+
+void LLAudioEngine::translateListener(LLVector3 aVec)
+{
+	mListenerp->translate(aVec);	
+}
+
+
+void LLAudioEngine::orientListener(LLVector3 up, LLVector3 at)
+{
+	mListenerp->orient(up, at);  
+}
+
+
+void LLAudioEngine::setListener(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at)
+{
+	mListenerp->set(pos,vel,up,at);  
+}
+
+
+void LLAudioEngine::setDopplerFactor(F32 factor)
+{
+	if (mListenerp)
+	{
+		mListenerp->setDopplerFactor(factor);  
+	}
+}
+
+
+F32 LLAudioEngine::getDopplerFactor()
+{
+	if (mListenerp)
+	{
+		return mListenerp->getDopplerFactor();
+	}
+	else
+	{
+		return 0.f;
+	}
+}
+
+
+void LLAudioEngine::setRolloffFactor(F32 factor)
+{
+	if (mListenerp)
+	{
+		mListenerp->setRolloffFactor(factor);  
+	}
+}
+
+
+F32 LLAudioEngine::getRolloffFactor()
+{
+	if (mListenerp)
+	{
+		return mListenerp->getRolloffFactor();  
+	}
+	else
+	{
+		return 0.f;
+	}
+}
+
+
+void LLAudioEngine::commitDeferredChanges()
+{
+	mListenerp->commitDeferredChanges();  
+}
+
+
+LLAudioSource * LLAudioEngine::findAudioSource(const LLUUID &source_id)
+{
+	source_map::iterator iter;
+	iter = mAllSources.find(source_id);
+
+	if (iter == mAllSources.end())
+	{
+		return NULL;
+	}
+	else
+	{
+		return iter->second;
+	}
+}
+
+
+LLAudioData * LLAudioEngine::getAudioData(const LLUUID &audio_uuid)
+{
+	data_map::iterator iter;
+	iter = mAllData.find(audio_uuid);
+	if (iter == mAllData.end())
+	{
+		// Create the new audio data
+		LLAudioData *adp = new LLAudioData(audio_uuid);
+		mAllData[audio_uuid] = adp;
+		return adp;
+	}
+	else
+	{
+		return iter->second;
+	}
+}
+
+void LLAudioEngine::addAudioSource(LLAudioSource *asp)
+{
+	mAllSources[asp->getID()] = asp;
+}
+
+
+void LLAudioEngine::cleanupAudioSource(LLAudioSource *asp)
+{
+	source_map::iterator iter;
+	iter = mAllSources.find(asp->getID());
+	if (iter == mAllSources.end())
+	{
+		llwarns << "Cleaning up unknown audio source!" << llendl;
+		return;
+	}
+	delete asp;
+	mAllSources.erase(iter);
+}
+
+
+bool LLAudioEngine::hasDecodedFile(const LLUUID &uuid)
+{
+	std::string uuid_str;
+	uuid.toString(uuid_str);
+
+	std::string wav_path;
+	wav_path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str);
+	wav_path += ".dsf";
+
+	if (gDirUtilp->fileExists(wav_path))
+	{
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+
+bool LLAudioEngine::hasLocalFile(const LLUUID &uuid)
+{
+	// See if it's in the VFS.
+	return gVFS->getExists(uuid, LLAssetType::AT_SOUND);
+}
+
+
+void LLAudioEngine::startNextTransfer()
+{
+	//llinfos << "LLAudioEngine::startNextTransfer()" << llendl;
+	if (mCurrentTransfer.notNull() || getMuted())
+	{
+		//llinfos << "Transfer in progress, aborting" << llendl;
+		return;
+	}
+
+	// Get the ID for the next asset that we want to transfer.
+	// Pick one in the following order:
+	LLUUID asset_id;
+	S32 i;
+	LLAudioSource *asp = NULL;
+	LLAudioData *adp = NULL;
+	data_map::iterator data_iter;
+
+	// Check all channels for currently playing sounds.
+	F32 max_pri = -1.f;
+	for (i = 0; i < MAX_CHANNELS; i++)
+	{
+		if (!mChannels[i])
+		{
+			continue;
+		}
+
+		asp = mChannels[i]->getSource();
+		if (!asp)
+		{
+			continue;
+		}
+		if (asp->getPriority() <= max_pri)
+		{
+			continue;
+		}
+
+		if (asp->getPriority() <= max_pri)
+		{
+			continue;
+		}
+
+		adp = asp->getCurrentData();
+		if (!adp)
+		{
+			continue;
+		}
+
+		if (!adp->hasLocalData() && adp->hasValidData())
+		{
+			asset_id = adp->getID();
+			max_pri = asp->getPriority();
+		}
+	}
+
+	// Check all channels for currently queued sounds.
+	if (asset_id.isNull())
+	{
+		max_pri = -1.f;
+		for (i = 0; i < MAX_CHANNELS; i++)
+		{
+			if (!mChannels[i])
+			{
+				continue;
+			}
+
+			LLAudioSource *asp;
+			asp = mChannels[i]->getSource();
+			if (!asp)
+			{
+				continue;
+			}
+
+			if (asp->getPriority() <= max_pri)
+			{
+				continue;
+			}
+
+			adp = asp->getQueuedData();
+			if (!adp)
+			{
+				continue;
+			}
+
+			if (!adp->hasLocalData() && adp->hasValidData())
+			{
+				asset_id = adp->getID();
+				max_pri = asp->getPriority();
+			}
+		}
+	}
+
+	// Check all live channels for other sounds (preloads).
+	if (asset_id.isNull())
+	{
+		max_pri = -1.f;
+		for (i = 0; i < MAX_CHANNELS; i++)
+		{
+			if (!mChannels[i])
+			{
+				continue;
+			}
+
+			LLAudioSource *asp;
+			asp = mChannels[i]->getSource();
+			if (!asp)
+			{
+				continue;
+			}
+
+			if (asp->getPriority() <= max_pri)
+			{
+				continue;
+			}
+
+
+			for (data_iter = asp->mPreloadMap.begin(); data_iter != asp->mPreloadMap.end(); data_iter++)
+			{
+				LLAudioData *adp = data_iter->second;
+				if (!adp)
+				{
+					continue;
+				}
+
+				if (!adp->hasLocalData() && adp->hasValidData())
+				{
+					asset_id = adp->getID();
+					max_pri = asp->getPriority();
+				}
+			}
+		}
+	}
+
+	// Check all sources
+	if (asset_id.isNull())
+	{
+		max_pri = -1.f;
+		source_map::iterator source_iter;
+		for (source_iter = mAllSources.begin(); source_iter != mAllSources.end(); source_iter++)
+		{
+			asp = source_iter->second;
+			if (!asp)
+			{
+				continue;
+			}
+
+			if (asp->getPriority() <= max_pri)
+			{
+				continue;
+			}
+
+			adp = asp->getCurrentData();
+			if (adp && !adp->hasLocalData() && adp->hasValidData())
+			{
+				asset_id = adp->getID();
+				max_pri = asp->getPriority();
+				continue;
+			}
+
+			adp = asp->getQueuedData();
+			if (adp && !adp->hasLocalData() && adp->hasValidData())
+			{
+				asset_id = adp->getID();
+				max_pri = asp->getPriority();
+				continue;
+			}
+
+			for (data_iter = asp->mPreloadMap.begin(); data_iter != asp->mPreloadMap.end(); data_iter++)
+			{
+				LLAudioData *adp = data_iter->second;
+				if (!adp)
+				{
+					continue;
+				}
+
+				if (!adp->hasLocalData() && adp->hasValidData())
+				{
+					asset_id = adp->getID();
+					max_pri = asp->getPriority();
+					break;
+				}
+			}
+		}
+	}
+
+	if (asset_id.notNull())
+	{
+		llinfos << "Getting asset data for: " << asset_id << llendl;
+		gAudiop->mCurrentTransfer = asset_id;
+		gAudiop->mCurrentTransferTimer.reset();
+		gAssetStorage->getAssetData(asset_id, LLAssetType::AT_SOUND,
+									assetCallback, NULL);
+	}
+	else
+	{
+		//llinfos << "No pending transfers?" << llendl;
+	}
+}
+
+
+// static
+void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status)
+{
+	if (result_code)
+	{
+		llinfos << "Boom, error in audio file transfer: " << LLAssetStorage::getErrorString( result_code ) << " (" << result_code << ")" << llendl;
+		// Need to mark data as bad to avoid constant rerequests.
+		LLAudioData *adp = gAudiop->getAudioData(uuid);
+		if (adp)
+        {
+			adp->setHasValidData(false);
+			adp->setHasLocalData(false);
+			adp->setHasDecodedData(false);
+		}
+	}
+	else
+	{
+		LLAudioData *adp = gAudiop->getAudioData(uuid);
+		if (!adp)
+        {
+			// Should never happen
+			llwarns << "Got asset callback without audio data for " << uuid << llendl;
+        }
+		else
+		{
+			adp->setHasValidData(true);
+		    adp->setHasLocalData(true);
+		    gAudioDecodeMgrp->addDecodeRequest(uuid);
+		}
+	}
+	gAudiop->mCurrentTransfer = LLUUID::null;
+	gAudiop->startNextTransfer();
+}
+
+
+//
+// LLAudioSource implementation
+//
+
+
+LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 gain, const S32 type)
+:	mID(id),
+	mOwnerID(owner_id),
+	mPriority(0.f),
+	mGain(gain),
+	mType(type),
+	mAmbient(false),
+	mLoop(false),
+	mSyncMaster(false),
+	mSyncSlave(false),
+	mQueueSounds(false),
+	mPlayedOnce(false),
+	mChannelp(NULL),
+	mCurrentDatap(NULL),
+	mQueuedDatap(NULL)
+{
+}
+
+
+LLAudioSource::~LLAudioSource()
+{
+	if (mChannelp)
+	{
+		// Stop playback of this sound
+		mChannelp->setSource(NULL);
+		mChannelp = NULL;
+	}
+}
+
+
+void LLAudioSource::setChannel(LLAudioChannel *channelp)
+{
+	if (channelp == mChannelp)
+	{
+		return;
+	}
+
+	mChannelp = channelp;
+}
+
+
+void LLAudioSource::update()
+{
+	if (!getCurrentBuffer())
+	{
+		if (getCurrentData())
+		{
+			// Hack - try and load the sound.  Will do this as a callback
+			// on decode later.
+			if (getCurrentData()->load())
+			{
+				play(getCurrentData()->getID());
+			}			
+		}
+	}
+}
+
+void LLAudioSource::updatePriority()
+{
+	if (isAmbient())
+	{
+		mPriority = 1.f;
+	}
+	else
+	{
+		// Priority is based on distance
+		LLVector3 dist_vec;
+		dist_vec.setVec(getPositionGlobal());
+		dist_vec -= gAudiop->getListenerPos();
+		F32 dist_squared = llmax(1.f, dist_vec.magVecSquared());
+
+		mPriority = mGain / dist_squared;
+	}
+}
+
+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);
+	return true;
+}
+
+
+bool LLAudioSource::play(const LLUUID &audio_uuid)
+{
+	if (audio_uuid.isNull())
+	{
+		if (getChannel())
+		{
+			getChannel()->setSource(NULL);