OSDN Git Service

Fetch sound resources.
authorMojito Sorbet <mojitotech@gmail.com>
Tue, 18 May 2010 21:45:06 +0000 (21:45 +0000)
committerMojito Sorbet <mojitotech@gmail.com>
Tue, 18 May 2010 21:45:06 +0000 (21:45 +0000)
git-svn-id: https://radegast.googlecode.com/svn/branches/sounds@640 f7a694da-4d33-11de-9ad6-1127a62b9fcd

Radegast/Core/Media/BufferSound.cs
Radegast/Core/Media/MediaManager.cs
Radegast/Core/Media/MediaObject.cs
Radegast/Core/Media/Stream.cs
plugins/Radegast.Plugin.Speech/RadSpeech/Sound/FmodSound.cs

index e003743..19c680e 100644 (file)
 //\r
 using System;\r
 using System.Runtime.InteropServices;\r
+using System.Collections.Generic;\r
 using FMOD;\r
 using OpenMetaverse;\r
+using OpenMetaverse.Assets;\r
 \r
 namespace Radegast.Media\r
 {\r
@@ -39,24 +41,24 @@ namespace Radegast.Media
     public class BufferSound : MediaObject\r
     {\r
         private FMOD.CREATESOUNDEXINFO extendedInfo;\r
-\r
+        private UUID Id;\r
+        private Boolean prefetchOnly = false;\r
+        private FMOD.MODE mode;\r
         public Sound Sound { get { return sound; } }\r
 \r
         /// <summary>\r
         /// Creates a new sound object\r
         /// </summary>\r
         /// <param name="system">Sound system</param>\r
-        public BufferSound(byte[] buffer, bool loop, bool global, Vector3 worldpos )\r
+        public BufferSound( UUID soundId, bool loop, bool global, Vector3 worldpos, float vol )\r
             :base()\r
         {\r
+            allBuffers.AddLast(this);\r
             position = FromOMVSpace(worldpos);\r
-\r
-            extendedInfo.format = SOUND_FORMAT.PCM16;\r
-            extendedInfo.nonblockcallback += DispatchNonBlockCallback;\r
+            volume = vol;\r
 \r
             // Set flags to determine how it will be played.\r
-            FMOD.MODE mode = FMOD.MODE.SOFTWARE | FMOD.MODE._3D;\r
-            position = FromOMVSpace(worldpos);\r
+            FMOD.MODE mode = FMOD.MODE.SOFTWARE | FMOD.MODE._3D | FMOD.MODE.NONBLOCKING;\r
 \r
             // Set coordinate space interpretation.\r
             if (global)\r
@@ -64,31 +66,25 @@ namespace Radegast.Media
             else\r
                 mode |= FMOD.MODE._3D_HEADRELATIVE;\r
 \r
-            invoke(new SoundDelegate(delegate\r
-            {\r
-                FMODExec(system.createSound(buffer,\r
-                    mode,\r
-                    ref extendedInfo,\r
-                    ref sound));\r
-\r
-                // Register for callbacks.\r
-                RegisterSound(sound);\r
-\r
-                if (loop)\r
-                    FMODExec(sound.setLoopCount(-1));\r
-            }));\r
+            manager.Instance.Client.Assets.RequestAsset(\r
+                Id,\r
+                AssetType.Sound,\r
+                false,\r
+                new AssetManager.AssetReceivedCallback(Assets_OnSoundReceived));\r
         }\r
 \r
-        public BufferSound( BufferSound shared, bool loop, Vector3 worldpos)\r
+        public BufferSound( UUID soundId )\r
             : base()\r
         {\r
-            position = FromOMVSpace(worldpos);\r
-\r
-            // Share a previously loaded sound.\r
-            Cloned = true;\r
-            sound = shared.Sound;\r
-\r
-            NonBlockCallbackHandler(RESULT.OK );\r
+            allBuffers.AddLast(this);\r
+            prefetchOnly = true;\r
+            Id = soundId;\r
+\r
+            manager.Instance.Client.Assets.RequestAsset(\r
+                Id,\r
+                AssetType.Sound,\r
+                false,\r
+                new AssetManager.AssetReceivedCallback(Assets_OnSoundReceived));\r
         }\r
 \r
         /// <summary>\r
@@ -99,11 +95,49 @@ namespace Radegast.Media
             base.Dispose();\r
         }\r
 \r
+        /**\r
+         * Handle arrival of a sound resource.\r
+         */\r
+        void Assets_OnSoundReceived(AssetDownload transfer, Asset asset)\r
+        {\r
+            if (transfer.Success)\r
+            {\r
+                // If this was a Prefetch, just stop here.\r
+                if (prefetchOnly)\r
+                {\r
+                    allBuffers.Remove(this);\r
+                    return;\r
+                }\r
+\r
+                AssetSound s = asset as AssetSound;\r
+                s.Decode();\r
+\r
+                invoke(new SoundDelegate(delegate\r
+                {\r
+                    FMODExec(system.createSound(\r
+                        s.AssetData,\r
+                        mode,\r
+                        ref extendedInfo,\r
+                        ref sound));\r
+\r
+                    // Register for callbacks.\r
+                    RegisterSound(sound);\r
+\r
+//                    if (loop)\r
+//                        FMODExec(sound.setLoopCount(-1));\r
+                }));\r
+            }\r
+            else\r
+            {\r
+                Logger.Log("Failed to download sound: " + transfer.Status.ToString(),\r
+                    Helpers.LogLevel.Error);\r
+            }\r
+        }\r
         protected override RESULT NonBlockCallbackHandler(RESULT instatus)\r
         {\r
             if (instatus != RESULT.OK)\r
             {\r
-                Logger.Log("Error opening stream: ", Helpers.LogLevel.Debug);\r
+                Logger.Log("Error opening sound: ", Helpers.LogLevel.Error);\r
                 return RESULT.OK;\r
             }\r
 \r
@@ -111,16 +145,15 @@ namespace Radegast.Media
             {\r
                 // Allocate a channel and set initial volume.  Initially paused.\r
                 FMODExec(system.playSound(CHANNELINDEX.FREE, sound, true, ref channel));\r
-                volume = 0.5f;\r
                 FMODExec(channel.setVolume(volume));\r
 \r
                 // Take note of when the sound is finished playing.\r
                 FMODExec(channel.setCallback(EndCallback));\r
 \r
-                // Set speech attenuation limits.\r
+                // Set attenuation limits.\r
                 FMODExec(sound.set3DMinMaxDistance(\r
                     1.2f,       // Any closer than this gets no louder\r
-                    8.0f));     // Further than this gets no softer.\r
+                    20.0f));     // Further than this gets no softer.\r
 \r
                 // Set the sound point of origin.\r
                 FMODExec(channel.set3DAttributes(ref position, ref ZeroVector));\r
@@ -130,7 +163,7 @@ namespace Radegast.Media
             }\r
             catch (Exception ex)\r
             {\r
-                Logger.Log("Error starting stream: ", Helpers.LogLevel.Debug, ex);\r
+                Logger.Log("Error starting sound: ", Helpers.LogLevel.Debug, ex);\r
             }\r
 \r
             return RESULT.OK;\r
@@ -154,14 +187,16 @@ namespace Radegast.Media
             if (type != CHANNEL_CALLBACKTYPE.END) return RESULT.OK;\r
 \r
             // Release the buffer to avoid a big memory leak.\r
-            //TODO Should be a reference count on cloned sound buffers.\r
-            if (!Cloned && sound != null)\r
+\r
+            if (sound != null)\r
             {\r
                 sound.release();\r
                 sound = null;\r
             }\r
             channel = null;\r
 \r
+            allBuffers.Remove(this);\r
+\r
             return RESULT.OK;\r
         }\r
 \r
index 7677d34..a6f2f94 100644 (file)
@@ -34,6 +34,7 @@ using System.Text;
 using FMOD;
 using System.Threading;
 using OpenMetaverse;
+using OpenMetaverse.Assets;
 
 namespace Radegast.Media
 {
@@ -46,18 +47,19 @@ namespace Radegast.Media
         private bool soundSystemAvailable = false;
         private Thread soundThread;
         private Thread listenerThread;
-        RadegastInstance instance;
+        public RadegastInstance Instance;
 
         private List<MediaObject> sounds = new List<MediaObject>();
 
         public MediaManager(RadegastInstance instance)
             : base()
         {
-            this.instance = instance;
+            this.Instance = instance;
             manager = this;
 
             loadCallback = new FMOD.SOUND_NONBLOCKCALLBACK(DispatchNonBlockCallback);
             endCallback = new FMOD.CHANNEL_CALLBACK(DispatchEndCallback);
+            allBuffers = new LinkedList<BufferSound>();
 
             // Start the background thread that does all the FMOD calls.
             soundThread = new Thread(new ThreadStart(CommandLoop));
@@ -70,6 +72,11 @@ namespace Radegast.Media
             listenerThread.IsBackground = true;
             listenerThread.Name = "ListenerThread";
             listenerThread.Start();
+
+            // Subscribe to events about inworld sounds
+            instance.Client.Sound.SoundTrigger += new EventHandler<SoundTriggerEventArgs>(Sound_SoundTrigger);
+            instance.Client.Sound.AttachedSound += new EventHandler<AttachedSoundEventArgs>(Sound_AttachedSound);
+            instance.Client.Sound.PreloadSound += new EventHandler<PreloadSoundEventArgs>(Sound_PreloadSound);
         }
 
         private void CommandLoop()
@@ -249,7 +256,7 @@ namespace Radegast.Media
 
                 if (system == null) continue;
 
-                AgentManager my = instance.Client.Self;
+                AgentManager my = Instance.Client.Self;
 
                 // If we are standing still, nothing to update now, but
                 // FMOD needs a 'tick' anyway for callbacks, etc.  In looping
@@ -297,6 +304,45 @@ namespace Radegast.Media
             }
         }
 
+        /**
+         * Handle triggering a sound to play
+         */
+        private void Sound_SoundTrigger(object sender, SoundTriggerEventArgs e)
+        {
+            new BufferSound(
+                e.SoundID,
+                false,
+                true,
+                e.Position,
+                e.Gain);
+        }
+
+        private void Sound_AttachedSound(object sender, AttachedSoundEventArgs e)
+        {
+          
+        }
+
+        /**
+         * Handle request to preload a sound resource.
+         */
+        private void Sound_PreloadSound(object sender, PreloadSoundEventArgs e)
+        {
+            new BufferSound( e.SoundID );
+        }
+
+
+    }
+
+    public class PlayingSound
+    {
+        private UUID Id;
+        private Vector3 position;
+        private float volume;
+
+        public PlayingSound( UUID soundId )
+        {
+            Id = soundId;
+        }
     }
 
     public class MediaException : Exception
index 8fbc834..7e6e13e 100644 (file)
@@ -57,6 +57,7 @@ namespace Radegast.Media
         protected static MediaManager manager;
         protected static FMOD.CHANNEL_CALLBACK endCallback;
         protected static FMOD.SOUND_NONBLOCKCALLBACK loadCallback;
+        protected static LinkedList<BufferSound> allBuffers;
 
         /// <summary>
         /// FMOD channel controller, should not be used directly, add methods to Radegast.Media.Sound
index 61fd396..4b08e90 100644 (file)
@@ -144,6 +144,8 @@ namespace Radegast.Media
 \r
                         // If this is not Unix, try to get MP3 tags.\r
                         // getTag seems to break on Unix.\r
+#if NOT\r
+                        // Seems to break on Windows too now\r
                         if (false) //Environment.OSVersion.Platform != PlatformID.Unix)\r
                         {\r
                             TAG tag = new TAG();\r
@@ -162,8 +164,8 @@ namespace Radegast.Media
                                     catch (Exception) { }\r
                             }\r
                         }\r
+#endif\r
 \r
-//                      system.update();\r
                     }\r
                     catch (Exception ex)\r
                     {\r
index e85f14d..56a5f5c 100644 (file)
@@ -99,6 +99,7 @@ namespace RadegastSpeech.Sound
         // Handler for event when speech is done playing.
         private void SpeechDoneHandler(object sender, EventArgs e)
         {
+            // Poke the semaphore
             playing.Release();
         }