2 // Radegast Metaverse Client
\r
3 // Copyright (c) 2009, Radegast Development Team
\r
4 // All rights reserved.
\r
6 // Redistribution and use in source and binary forms, with or without
\r
7 // modification, are permitted provided that the following conditions are met:
\r
9 // * Redistributions of source code must retain the above copyright notice,
\r
10 // this list of conditions and the following disclaimer.
\r
11 // * Redistributions in binary form must reproduce the above copyright
\r
12 // notice, this list of conditions and the following disclaimer in the
\r
13 // documentation and/or other materials provided with the distribution.
\r
14 // * Neither the name of the application "Radegast", nor the names of its
\r
15 // contributors may be used to endorse or promote products derived from
\r
16 // this software without specific prior written permission.
\r
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
\r
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
\r
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
\r
21 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
\r
22 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
\r
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
\r
24 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
\r
25 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
\r
26 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
\r
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
29 // $Id: Sound.cs 502 2010-03-14 23:13:46Z latifer $
\r
32 using System.Runtime.InteropServices;
\r
34 using OpenMetaverse;
\r
36 namespace Radegast.Media
\r
38 public class StreamInfoArgs : EventArgs
\r
41 public string Value;
\r
43 public StreamInfoArgs(string key, string value)
\r
50 public class Stream : MediaObject
\r
53 /// Returns current position of the sound played in ms
\r
54 /// Do not confuse with the spatial Position on other suonds.
\r
56 public uint Position { get { return position; } }
\r
57 private uint position = 0;
\r
60 /// Is sound currently playing
\r
62 public bool Playing { get { return playing; } }
\r
63 private bool playing = false;
\r
66 /// Is sound currently paused
\r
68 public bool Paused { get { return paused; } }
\r
69 private bool paused = false;
\r
72 /// Fired when a stream meta data is received
\r
74 /// <param name="sender">Sender</param>
\r
75 /// <param name="e">Key, value are sent in e</param>
\r
76 public delegate void StreamInfoCallback(object sender, StreamInfoArgs e);
\r
79 /// Fired when a stream meta data is received
\r
81 public event StreamInfoCallback OnStreamInfo;
\r
83 private System.Timers.Timer timer;
\r
86 /// Creates a new sound object
\r
88 /// <param name="system">Sound system</param>
\r
92 timer = new System.Timers.Timer();
\r
93 timer.Interval = 50d;
\r
94 timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
\r
95 timer.Enabled = false;
\r
100 /// Releases resources of this sound object
\r
102 public override void Dispose()
\r
106 timer.Enabled = false;
\r
115 /// Plays audio stream
\r
117 /// <param name="url">URL of the stream</param>
\r
118 public void PlayStream(string url)
\r
122 invoke( new SoundDelegate(
\r
124 MediaManager.FMODExec(system.createSound(url,
\r
125 (MODE.HARDWARE | MODE._2D | MODE.CREATESTREAM | MODE.NONBLOCKING), ref sound));
\r
127 timer.Enabled = true;
\r
128 timer_Elapsed(null, null);
\r
134 /// Toggles sound pause
\r
136 public void TogglePaused()
\r
138 invoke(new SoundDelegate(delegate
\r
140 if (channel != null)
\r
142 channel.getPaused(ref paused);
\r
143 channel.setPaused(!paused);
\r
148 void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
\r
150 OPENSTATE openstate = 0;
\r
151 uint percentbuffered = 0;
\r
152 bool starving = false;
\r
158 // Query what the sound is doing.
\r
159 MediaManager.FMODExec(sound.getOpenState(ref openstate, ref percentbuffered, ref starving));
\r
161 // If a channel is not allocated yet, ask for one.
\r
162 if (openstate == OPENSTATE.READY && channel == null)
\r
164 // Allocate a channel and set initial volume.
\r
165 MediaManager.FMODExec(system.playSound( CHANNELINDEX.FREE, sound, false, ref channel));
\r
167 MediaManager.FMODExec(channel.setVolume(volume));
\r
171 if (channel != null)
\r
173 // Do not try to get MP3 tags om Unix. It breaks.
\r
174 if (Environment.OSVersion.Platform != PlatformID.Unix)
\r
178 TAG tag = new TAG();
\r
179 if (sound.getTag(null, -1, ref tag) != RESULT.OK)
\r
183 if (tag.datatype != TAGDATATYPE.STRING)
\r
189 if (OnStreamInfo != null)
\r
190 try { OnStreamInfo(this, new StreamInfoArgs(tag.name.ToLower(), Marshal.PtrToStringAnsi(tag.data))); }
\r
191 catch (Exception) { }
\r
196 // Get pause/play status
\r
197 MediaManager.FMODExec(channel.getPaused(ref paused));
\r
198 MediaManager.FMODExec(channel.isPlaying(ref playing));
\r
199 MediaManager.FMODExec(channel.getPosition(ref position, TIMEUNIT.MS));
\r
202 if (system != null)
\r
207 catch (Exception ex)
\r
209 playing = paused = false;
\r
210 timer.Enabled = false;
\r
211 Logger.Log("Error playing stream: ", Helpers.LogLevel.Debug, ex);
\r