--- /dev/null
+// \r
+// Radegast Metaverse Client\r
+// Copyright (c) 2009, Radegast Development Team\r
+// All rights reserved.\r
+// \r
+// Redistribution and use in source and binary forms, with or without\r
+// modification, are permitted provided that the following conditions are met:\r
+// \r
+// * Redistributions of source code must retain the above copyright notice,\r
+// this list of conditions and the following disclaimer.\r
+// * Redistributions in binary form must reproduce the above copyright\r
+// notice, this list of conditions and the following disclaimer in the\r
+// documentation and/or other materials provided with the distribution.\r
+// * Neither the name of the application "Radegast", nor the names of its\r
+// contributors may be used to endorse or promote products derived from\r
+// this software without specific prior written permission.\r
+// \r
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\r
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\r
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+//\r
+// $Id$\r
+//\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using FMOD;\r
+using OpenMetaverse;\r
+\r
+namespace Radegast.Media\r
+{\r
+ public class MediaManager : MediaObject\r
+ {\r
+ /// <summary>\r
+ /// Indicated wheather spund sytem is ready for use\r
+ /// </summary>\r
+ public bool SoundSystemAvailable { get { return soundSystemAvailable; } }\r
+ private bool soundSystemAvailable = false;\r
+\r
+ private FMOD.Sound stream = null;\r
+ private List<MediaObject> sounds = new List<MediaObject>();\r
+\r
+ /// <summary>\r
+ /// Parcel music stream player\r
+ /// </summary>\r
+ public Sound ParcelMusic { get { return parcelMusic; } }\r
+ private Sound parcelMusic;\r
+\r
+ public MediaManager()\r
+ : base(null)\r
+ {\r
+ try\r
+ {\r
+ FMODExec(FMOD.Factory.System_Create(ref system));\r
+ uint version = 0;\r
+ FMODExec(system.getVersion(ref version));\r
+\r
+ if (version < FMOD.VERSION.number)\r
+ throw new MediaException("You are using an old version of FMOD " + version.ToString("X") + ". This program requires " + FMOD.VERSION.number.ToString("X") + ".");\r
+\r
+ FMODExec(system.init(100, FMOD.INITFLAG.NORMAL, (IntPtr)null));\r
+ FMODExec(system.setStreamBufferSize(64 * 1024, FMOD.TIMEUNIT.RAWBYTES));\r
+\r
+ soundSystemAvailable = true;\r
+\r
+ //parcelMusic = new Sound(system);\r
+ //parcelMusic.PlayStream("http://scfire-ntc-aa06.stream.aol.com:80/stream/1065");\r
+\r
+ Logger.Log("Initialized FMOD Ex", Helpers.LogLevel.Debug);\r
+ }\r
+ catch (Exception ex)\r
+ {\r
+ Logger.Log("Failed to initialize the sound system", Helpers.LogLevel.Warning, ex);\r
+ }\r
+ }\r
+\r
+ public override void Dispose()\r
+ {\r
+ if (parcelMusic != null)\r
+ {\r
+ if (!parcelMusic.Disposed)\r
+ parcelMusic.Dispose();\r
+ parcelMusic = null;\r
+ }\r
+\r
+ lock(sounds)\r
+ {\r
+ for (int i=0; i<sounds.Count; i++)\r
+ {\r
+ if (!sounds[i].Disposed)\r
+ sounds[i].Dispose();\r
+ }\r
+ sounds.Clear();\r
+ }\r
+\r
+ sounds = null;\r
+\r
+ if (system != null)\r
+ {\r
+ system.release();\r
+ system = null;\r
+ }\r
+\r
+ base.Dispose();\r
+ }\r
+\r
+ public static void FMODExec(FMOD.RESULT result)\r
+ {\r
+ if (result != FMOD.RESULT.OK)\r
+ {\r
+ throw new MediaException("FMOD error! " + result + " - " + FMOD.Error.String(result));\r
+ }\r
+ }\r
+ }\r
+\r
+ public class MediaException : Exception\r
+ {\r
+ public MediaException(string msg)\r
+ : base(msg)\r
+ {\r
+ }\r
+ }\r
+}\r
--- /dev/null
+// \r
+// Radegast Metaverse Client\r
+// Copyright (c) 2009, Radegast Development Team\r
+// All rights reserved.\r
+// \r
+// Redistribution and use in source and binary forms, with or without\r
+// modification, are permitted provided that the following conditions are met:\r
+// \r
+// * Redistributions of source code must retain the above copyright notice,\r
+// this list of conditions and the following disclaimer.\r
+// * Redistributions in binary form must reproduce the above copyright\r
+// notice, this list of conditions and the following disclaimer in the\r
+// documentation and/or other materials provided with the distribution.\r
+// * Neither the name of the application "Radegast", nor the names of its\r
+// contributors may be used to endorse or promote products derived from\r
+// this software without specific prior written permission.\r
+// \r
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\r
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\r
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+//\r
+// $Id$\r
+//\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace Radegast.Media\r
+{\r
+ public abstract class MediaObject : Object, IDisposable\r
+ {\r
+ /// <summary>\r
+ /// Indicates if this object's resources have already been disposed\r
+ /// </summary>\r
+ public bool Disposed { get { return disposed; } }\r
+ private bool disposed = false;\r
+\r
+ /// <summary>\r
+ /// Base FMOD system object\r
+ /// </summary>\r
+ protected FMOD.System system = null;\r
+\r
+ public MediaObject(FMOD.System system)\r
+ {\r
+ this.system = system;\r
+ }\r
+\r
+ public virtual void Dispose()\r
+ {\r
+ if (system != null)\r
+ {\r
+ system.release();\r
+ system = null;\r
+ }\r
+ disposed = true;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+// \r
+// Radegast Metaverse Client\r
+// Copyright (c) 2009, Radegast Development Team\r
+// All rights reserved.\r
+// \r
+// Redistribution and use in source and binary forms, with or without\r
+// modification, are permitted provided that the following conditions are met:\r
+// \r
+// * Redistributions of source code must retain the above copyright notice,\r
+// this list of conditions and the following disclaimer.\r
+// * Redistributions in binary form must reproduce the above copyright\r
+// notice, this list of conditions and the following disclaimer in the\r
+// documentation and/or other materials provided with the distribution.\r
+// * Neither the name of the application "Radegast", nor the names of its\r
+// contributors may be used to endorse or promote products derived from\r
+// this software without specific prior written permission.\r
+// \r
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\r
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\r
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+//\r
+// $Id$\r
+//\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using FMOD;\r
+using OpenMetaverse;\r
+\r
+namespace Radegast.Media\r
+{\r
+\r
+ public class Sound : MediaObject\r
+ {\r
+ /// <summary>\r
+ /// FMOD channel controller, should not be used directly, add methods to Radegast.Media.Sound\r
+ /// </summary>\r
+ public FMOD.Channel FMODChannel { get { return channel; } }\r
+ private FMOD.Channel channel = null;\r
+\r
+ /// <summary>\r
+ /// FMOD sound object, should not be used directly, add methods to Radegast.Media.Sound\r
+ /// </summary>\r
+ public FMOD.Sound FMODSound { get { return sound; } }\r
+ private FMOD.Sound sound = null;\r
+\r
+ /// <summary>\r
+ /// Returns current position of the sound played in ms\r
+ /// </summary>\r
+ public uint Position { get { return position; } }\r
+ private uint position = 0;\r
+\r
+ /// <summary>\r
+ /// Is sound currently playing\r
+ /// </summary>\r
+ public bool Playing { get { return playing; } }\r
+ private bool playing = false;\r
+\r
+ /// <summary>\r
+ /// Is sound currently paused\r
+ /// </summary>\r
+ public bool Paused { get { return paused; } }\r
+ private bool paused = false;\r
+\r
+ private bool soundcreated = false;\r
+ private System.Timers.Timer timer;\r
+\r
+ /// <summary>\r
+ /// Creates a new sound object\r
+ /// </summary>\r
+ /// <param name="system">Sound system</param>\r
+ public Sound(FMOD.System system)\r
+ :base(system)\r
+ {\r
+ timer = new System.Timers.Timer();\r
+ timer.Interval = 10d;\r
+ timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);\r
+ timer.Enabled = false;\r
+ }\r
+\r
+\r
+ /// <summary>\r
+ /// Releases resources of this sound object\r
+ /// </summary>\r
+ public override void Dispose()\r
+ {\r
+ if (timer != null)\r
+ {\r
+ timer.Enabled = false;\r
+ timer.Dispose();\r
+ timer = null;\r
+ }\r
+\r
+ if (sound != null)\r
+ {\r
+ sound.release();\r
+ sound = null;\r
+ }\r
+ base.Dispose();\r
+ }\r
+\r
+ /// <summary>\r
+ /// Plays audio stream\r
+ /// </summary>\r
+ /// <param name="url">URL of the stream</param>\r
+ public void PlayStream(string url)\r
+ {\r
+ if (!soundcreated)\r
+ {\r
+ system.createSound(url, (FMOD.MODE.SOFTWARE | FMOD.MODE._2D | FMOD.MODE.CREATESTREAM | FMOD.MODE.NONBLOCKING), ref sound);\r
+ soundcreated = true;\r
+ timer.Enabled = true;\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Toggles sound pause\r
+ /// </summary>\r
+ public void TogglePaused()\r
+ {\r
+ if (channel != null)\r
+ {\r
+ channel.getPaused(ref paused);\r
+ channel.setPaused(!paused);\r
+ }\r
+ }\r
+\r
+ void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)\r
+ {\r
+ FMOD.OPENSTATE openstate = 0;\r
+ uint percentbuffered = 0;\r
+ bool starving = false;\r
+\r
+ try\r
+ {\r
+ if (soundcreated)\r
+ {\r
+ MediaManager.FMODExec(sound.getOpenState(ref openstate, ref percentbuffered, ref starving));\r
+\r
+ if (openstate == FMOD.OPENSTATE.READY && channel == null)\r
+ {\r
+ MediaManager.FMODExec(system.playSound(FMOD.CHANNELINDEX.FREE, sound, false, ref channel));\r
+ }\r
+ }\r
+\r
+ if (channel != null)\r
+ {\r
+ for (; ; )\r
+ {\r
+ FMOD.TAG tag = new FMOD.TAG();\r
+ if (sound.getTag(null, -1, ref tag) != FMOD.RESULT.OK)\r
+ {\r
+ break;\r
+ }\r
+ if (tag.datatype != FMOD.TAGDATATYPE.STRING)\r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ MediaManager.FMODExec(channel.getPaused(ref paused));\r
+ MediaManager.FMODExec(channel.isPlaying(ref playing));\r
+ MediaManager.FMODExec(channel.getPosition(ref position, FMOD.TIMEUNIT.MS));\r
+ }\r
+\r
+ if (system != null)\r
+ {\r
+ system.update();\r
+ }\r
+ }\r
+ catch (Exception ex)\r
+ {\r
+ playing = paused = false;\r
+ timer.Enabled = false;\r
+ Logger.Log("Error playing sound: ", Helpers.LogLevel.Debug, ex);\r
+ }\r
+ }\r
+ }\r
+}\r
using System.Reflection;\r
using System.Windows.Forms;\r
using Radegast.Netcom;\r
+using Radegast.Media;\r
using OpenMetaverse;\r
\r
namespace Radegast\r
\r
public readonly List<IRadegastPlugin> PluginsLoaded = new List<IRadegastPlugin>();\r
\r
+ private MediaManager mediaManager;\r
+ /// <summary>\r
+ /// Radegast media manager for playing streams and in world sounds\r
+ /// </summary>\r
+ public MediaManager MediaManager { get { return mediaManager; } }\r
+\r
public RadegastInstance(GridClient client0)\r
{\r
// incase something else calls GlobalInstance while we are loading\r
\r
netcom = new RadegastNetcom(client);\r
state = new StateManager(this);\r
+ mediaManager = new MediaManager();\r
+\r
InitializeLoggingAndConfig();\r
\r
client.Settings.MULTIPLE_SIMS = true;\r
});\r
}\r
\r
+ mediaManager.Dispose();\r
+ mediaManager = null;\r
state.Dispose();\r
state = null;\r
netcom.Dispose();\r
if (RadegastInstance.GlobalInstance.MainForm != null)\r
RadegastInstance.GlobalInstance.MainForm.AddLogMessage(loggingMessage, le.Level);\r
\r
- lock (this)\r
- {\r
- StreamWriter logfile = File.AppendText(RadegastInstance.GlobalInstance.GlobalLogFile);\r
- logfile.WriteLine(loggingMessage);\r
- logfile.Close();\r
- logfile.Dispose();\r
- }\r
string regex = @"^(?<Front>.*?)\[(?<Category>[^\]]+)\]:?(?<End>.*)";\r
\r
Regex RE = new Regex(regex, RegexOptions.Multiline);\r
{\r
System.Console.WriteLine(loggingMessage);\r
}\r
+\r
+ lock (this)\r
+ {\r
+ StreamWriter logfile = File.AppendText(RadegastInstance.GlobalInstance.GlobalLogFile);\r
+ logfile.WriteLine(loggingMessage);\r
+ logfile.Close();\r
+ logfile.Dispose();\r
+ }\r
}\r
- catch (Exception e)\r
- {\r
- System.Console.WriteLine("Couldn't write out log message", e.ToString());\r
- }\r
+ catch (Exception) { }\r
}\r
\r
private void WriteColorText(ConsoleColor color, string sender)\r
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>\r
</PropertyGroup>\r
<ItemGroup>\r
+ <Reference Include="fmodex-dotnet, Version=4.26.7.0, Culture=neutral, processorArchitecture=MSIL" />\r
<Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL" />\r
<Reference Include="System" />\r
<Reference Include="System.Core">\r
<ItemGroup>\r
<Compile Include="Core\AutoPilot.cs" />\r
<Compile Include="Core\ChatBufferItem.cs" />\r
+ <Compile Include="Core\Media\MediaManager.cs" />\r
+ <Compile Include="Core\Media\MediaObject.cs" />\r
+ <Compile Include="Core\Media\Sound.cs" />\r
<Compile Include="Core\Settings.cs" />\r
<Compile Include="Core\IRadegastPlugin.cs" />\r
<Compile Include="Core\ListItems\PreferencePaneListItem.cs" />\r
</BootstrapperPackage>\r
</ItemGroup>\r
<ItemGroup>\r
+ <None Include="fmodex-dotnet.dll.config">\r
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\r
+ </None>\r
+ <None Include="libfmodex-4.26.07.dylib">\r
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\r
+ </None>\r
+ <None Include="libfmodex-4.26.07.so">\r
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\r
+ </None>\r
+ <None Include="libfmodex64-4.26.07.so">\r
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\r
+ </None>\r
<None Include="libopenjpeg-dotnet-2.1.3.0-dotnet-1-i686.so">\r
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\r
</None>\r
<None Include="openjpeg-dotnet.dll">\r
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\r
</None>\r
+ <None Include="assemblies\fmodex-dotnet.dll" />\r
+ <None Include="fmodex.dll">\r
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\r
+ </None>\r
<Content Include="openmetaverse_data\avatar_lad.xml">\r
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\r
</Content>\r
-<?xml version="1.0" encoding="utf-8" ?>\r
+<?xml version="1.0" encoding="iso-8859-1" ?>\r
<!-- $Id$ -->\r
<configuration>\r
<dllmap dll="opengl32.dll">\r
--- /dev/null
+<?xml version="1.0" encoding="iso-8859-1" ?>\r
+<!-- $Id$ -->\r
+<configuration>\r
+ <dllmap dll="fmodex">\r
+ <dllentry os="!windows,osx" cpu="x86" dll="libfmodex-4.26.07" />\r
+ <dllentry os="!windows,osx" cpu="x86-64,ia64" dll="libfmodex64-4.26.07" />\r
+ <dllentry os="osx" dll="libfmodex-4.26.07.dylib" />\r
+ </dllmap>\r
+</configuration>\r