OSDN Git Service

Protect against nullref in StopSound(). Override EndCallback to free memory.
[radegast/radegast.git] / Radegast / Core / Media / BufferSound.cs
index 0b4519c..088fe56 100644 (file)
@@ -56,8 +56,8 @@ namespace Radegast.Media
         /// Creates a new sound object\r
         /// </summary>\r
         /// <param name="system">Sound system</param>\r
-        public BufferSound( UUID objectId, UUID soundId, bool loop, bool global, Vector3 worldpos, float vol )\r
-            :base()\r
+        public BufferSound(UUID objectId, UUID soundId, bool loop, bool global, Vector3 worldpos, float vol)\r
+            : base()\r
         {\r
             InitBuffer(objectId, soundId, loop, global, worldpos, vol);\r
         }\r
@@ -72,7 +72,7 @@ namespace Radegast.Media
         {\r
             // Do not let this get garbage-collected.\r
             lock (allBuffers)\r
-                allBuffers[objectId] =this;\r
+                allBuffers[objectId] = this;\r
 \r
             ContainerId = objectId;\r
             Id = soundId;\r
@@ -109,7 +109,7 @@ namespace Radegast.Media
                 new AssetManager.AssetReceivedCallback(Assets_OnSoundReceived));\r
         }\r
 \r
-        public static void Kill( UUID id )\r
+        public static void Kill(UUID id)\r
         {\r
             if (allBuffers.ContainsKey(id))\r
             {\r
@@ -150,11 +150,11 @@ namespace Radegast.Media
         private void AdjustVolume()\r
         {\r
             //TODO This is disabled until we find why FMOD objects to the handle\r
-//            Volume = volumeSetting * AllObjectVolume;\r
+            //            Volume = volumeSetting * AllObjectVolume;\r
         }\r
 \r
         // A simpler constructor used by PreFetchSound.\r
-        public BufferSound( UUID soundId )\r
+        public BufferSound(UUID soundId)\r
             : base()\r
         {\r
             lock (allBuffers)\r
@@ -194,7 +194,7 @@ namespace Radegast.Media
                     return;\r
                 }\r
 \r
-//                Logger.Log("Opening sound " + Id.ToString(), Helpers.LogLevel.Debug);\r
+                //                Logger.Log("Opening sound " + Id.ToString(), Helpers.LogLevel.Debug);\r
 \r
                 // Decode the Ogg Vorbis buffer.\r
                 AssetSound s = asset as AssetSound;\r
@@ -204,6 +204,7 @@ namespace Radegast.Media
                 // Describe the data to FMOD\r
                 extraInfo.length = (uint)data.Length;\r
                 extraInfo.nonblockcallback = loadCallback;\r
+                extraInfo.cbsize = Marshal.SizeOf(extraInfo);\r
 \r
                 invoke(new SoundDelegate(delegate\r
                 {\r
@@ -216,7 +217,7 @@ namespace Radegast.Media
 \r
                     // Register for callbacks.\r
                     RegisterSound(sound);\r
-                    }));\r
+                }));\r
             }\r
             else\r
             {\r
@@ -242,7 +243,7 @@ namespace Radegast.Media
                     {\r
                         uint soundlen = 0;\r
                         FMODExec(sound.getLength(ref soundlen, TIMEUNIT.PCM));\r
-                        FMODExec( sound.setLoopPoints( 0, TIMEUNIT.PCM, soundlen-1, TIMEUNIT.PCM ));\r
+                        FMODExec(sound.setLoopPoints(0, TIMEUNIT.PCM, soundlen - 1, TIMEUNIT.PCM));\r
                         FMODExec(sound.setLoopCount(-1));\r
                     }\r
 \r
@@ -254,7 +255,11 @@ namespace Radegast.Media
                              sound.getRaw().ToString("X"),\r
                              Id),\r
                         Helpers.LogLevel.Debug);\r
-                    FMODExec(channel.setVolume(volumeSetting * AllObjectVolume ));\r
+\r
+                    lock (allChannels)\r
+                        allChannels[channel.getRaw()] = this;\r
+\r
+                    FMODExec(channel.setVolume(volumeSetting * AllObjectVolume));\r
 \r
                     // Take note of when the sound is finished playing.\r
                     FMODExec(channel.setCallback(endCallback));\r
@@ -280,24 +285,12 @@ namespace Radegast.Media
         }\r
 \r
         /// <summary>\r
-        /// Callback handler for reaching the end of a sound.\r
+        /// Handles stop sound even from FMOD\r
         /// </summary>\r
-        /// <param name="channelraw"></param>\r
-        /// <param name="type"></param>\r
-        /// <param name="commanddata1"></param>\r
-        /// <param name="commanddata2"></param>\r
-        /// <returns></returns>\r
-        private RESULT EndCallback(\r
-            IntPtr channelraw,\r
-            CHANNEL_CALLBACKTYPE type,\r
-            IntPtr commanddata1,\r
-            IntPtr commanddata2)\r
+        /// <returns>RESULT.OK</returns>\r
+        protected override RESULT EndCallbackHandler()\r
         {\r
-            // Ignore other callback types.\r
-            if (type != CHANNEL_CALLBACKTYPE.END) return RESULT.OK;\r
-\r
             StopSound();\r
-\r
             return RESULT.OK;\r
         }\r
 \r
@@ -307,24 +300,28 @@ namespace Radegast.Media
 \r
             invoke(new SoundDelegate(delegate\r
             {\r
-                Logger.Log( String.Format("Removing channel {0} sound {1} ID {2}",\r
-                        channel.getRaw().ToString("X"),\r
-                        sound.getRaw().ToString("X"),\r
-                        Id.ToString()),\r
-                    Helpers.LogLevel.Debug);\r
+                string chanStr = "none";\r
+                string soundStr = "none";\r
 \r
                 // Release the buffer to avoid a big memory leak.\r
                 if (channel != null)\r
                 {\r
+                    chanStr = channel.getRaw().ToString("X");\r
                     channel.stop();\r
                     channel = null;\r
                 }\r
                 if (sound != null)\r
                 {\r
+                    soundStr = sound.getRaw().ToString("X");\r
                     sound.release();\r
                     sound = null;\r
                 }\r
-                channel = null;\r
+\r
+                Logger.Log(String.Format("Removing channel {0} sound {1} ID {2}",\r
+                    chanStr,\r
+                    soundStr,\r
+                    Id.ToString()),\r
+                    Helpers.LogLevel.Debug);\r
 \r
                 lock (allBuffers)\r
                     allBuffers.Remove(ContainerId);\r