OSDN Git Service

RAD-21: Added parcel audio stream player (windows only for now)
authorLatif Khalifa <latifer@streamgrid.net>
Wed, 9 Sep 2009 06:46:18 +0000 (06:46 +0000)
committerLatif Khalifa <latifer@streamgrid.net>
Wed, 9 Sep 2009 06:46:18 +0000 (06:46 +0000)
git-svn-id: https://radegast.googlecode.com/svn/trunk@211 f7a694da-4d33-11de-9ad6-1127a62b9fcd

Radegast/Core/Media/MediaManager.cs
Radegast/Core/Media/MediaObject.cs
Radegast/Core/Media/Sound.cs
Radegast/Core/Types/DettachableControl.cs
Radegast/GUI/Consoles/MediaConsole.Designer.cs
Radegast/GUI/Consoles/MediaConsole.cs
Radegast/GUI/Consoles/MediaConsole.resx
Radegast/GUI/Dialogs/MainForm.Designer.cs
Radegast/GUI/Dialogs/MainForm.cs
Radegast/GUI/Dialogs/MainForm.resx

index ad5e5cc..f9cf85a 100644 (file)
@@ -49,13 +49,13 @@ namespace Radegast.Media
         /// <summary>\r
         /// Parcel music stream player\r
         /// </summary>\r
-        public Sound ParcelMusic { get { return parcelMusic; } }\r
+        public Sound ParcelMusic { get { return parcelMusic; } set { parcelMusic = value; } }\r
         private Sound parcelMusic;\r
 \r
         public MediaManager(RadegastInstance instance)\r
             : base(null)\r
         {\r
-            if (instance.MonoRuntime) return;\r
+            if (Environment.OSVersion.Platform == PlatformID.Unix) return;\r
 \r
             try\r
             {\r
@@ -66,11 +66,11 @@ namespace Radegast.Media
                 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
+                if (Environment.OSVersion.Platform == PlatformID.Unix)\r
+                    FMODExec(system.setOutput(FMOD.OUTPUTTYPE.ESD));\r
                 FMODExec(system.init(100, FMOD.INITFLAG.NORMAL, (IntPtr)null));\r
                 FMODExec(system.setStreamBufferSize(64 * 1024, FMOD.TIMEUNIT.RAWBYTES));\r
 \r
-                parcelMusic = new Sound(system);\r
-\r
                 soundSystemAvailable = true;\r
                 Logger.Log("Initialized FMOD Ex", Helpers.LogLevel.Debug);\r
             }\r
index c59b447..f83c9bb 100644 (file)
@@ -55,11 +55,6 @@ namespace Radegast.Media
 \r
         public virtual void Dispose()\r
         {\r
-            if (system != null)\r
-            {\r
-                system.release();\r
-                system = null;\r
-            }\r
             disposed = true;\r
         }\r
     }\r
index 4abbffa..37020b6 100644 (file)
@@ -37,6 +37,17 @@ using System.Runtime.InteropServices;
 \r
 namespace Radegast.Media\r
 {\r
+    public class StreamInfoArgs : EventArgs\r
+    {\r
+        public string Key;\r
+        public string Value;\r
+\r
+        public StreamInfoArgs(string key, string value)\r
+        {\r
+            Key = key;\r
+            Value = value;\r
+        }\r
+    }\r
 \r
     public class Sound : MediaObject\r
     {\r
@@ -70,6 +81,18 @@ namespace Radegast.Media
         public bool Paused { get { return paused; } }\r
         private bool paused = false;\r
 \r
+        /// <summary>\r
+        /// Fired when a stream meta data is received\r
+        /// </summary>\r
+        /// <param name="sender">Sender</param>\r
+        /// <param name="e">Key, value are sent in e</param>\r
+        public delegate void StreamInfoCallback(object sender, StreamInfoArgs e);\r
+\r
+        /// <summary>\r
+        /// Fired when a stream meta data is received\r
+        /// </summary>\r
+        public event StreamInfoCallback OnStreamInfo;\r
+\r
         private bool soundcreated = false;\r
         private System.Timers.Timer timer;\r
 \r
@@ -81,7 +104,7 @@ namespace Radegast.Media
             :base(system)\r
         {\r
             timer = new System.Timers.Timer();\r
-            timer.Interval = 100d;\r
+            timer.Interval = 500d;\r
             timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);\r
             timer.Enabled = false;\r
         }\r
@@ -115,9 +138,10 @@ namespace Radegast.Media
         {\r
             if (!soundcreated)\r
             {\r
-                system.createSound(url, (FMOD.MODE.HARDWARE | FMOD.MODE._2D | FMOD.MODE.CREATESTREAM | FMOD.MODE.NONBLOCKING), ref sound);\r
+                MediaManager.FMODExec(system.createSound(url, (FMOD.MODE.HARDWARE | FMOD.MODE._2D | FMOD.MODE.CREATESTREAM | FMOD.MODE.NONBLOCKING), ref sound));\r
                 soundcreated = true;\r
                 timer.Enabled = true;\r
+                timer_Elapsed(null, null);\r
             }\r
         }\r
 \r
@@ -133,6 +157,17 @@ namespace Radegast.Media
             }\r
         }\r
 \r
+        /// <summary>\r
+        /// Set or get current volume for this sound in range 0.0 - 1.0\r
+        /// </summary>\r
+        public float Volume\r
+        {\r
+            set { volume = value; }\r
+            get { return volume; }\r
+        }\r
+        private float volume = 0.5f;\r
+        private float currentVolume;\r
+\r
         void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)\r
         {\r
             FMOD.OPENSTATE openstate = 0;\r
@@ -148,11 +183,19 @@ namespace Radegast.Media
                     if (openstate == FMOD.OPENSTATE.READY && channel == null)\r
                     {\r
                         MediaManager.FMODExec(system.playSound(FMOD.CHANNELINDEX.FREE, sound, false, ref channel));\r
+                        MediaManager.FMODExec(channel.setVolume(volume));\r
+                        currentVolume = volume;\r
                     }\r
                 }\r
 \r
                 if (channel != null)\r
                 {\r
+                    if (currentVolume != volume)\r
+                    {\r
+                        currentVolume = volume;\r
+                        MediaManager.FMODExec(channel.setVolume(volume));\r
+                    }\r
+\r
                     for (; ; )\r
                     {\r
                         FMOD.TAG tag = new FMOD.TAG();\r
@@ -166,7 +209,9 @@ namespace Radegast.Media
                         }\r
                         else\r
                         {\r
-                           Logger.DebugLog("n" + tag.name + " = " + Marshal.PtrToStringAnsi(tag.data));\r
+                            if (OnStreamInfo != null)\r
+                                try { OnStreamInfo(this, new StreamInfoArgs(tag.name.ToLower(), Marshal.PtrToStringAnsi(tag.data))); }\r
+                                catch (Exception) { }\r
                         }\r
                     }\r
 \r
index 4f03586..b3266d7 100644 (file)
@@ -47,6 +47,11 @@ namespace Radegast
         protected Control OriginalParent;\r
         protected Size AttachedSize;\r
 \r
+        /// <summary>\r
+        /// If in detached state and detached form is closing and we have no parent\r
+        /// do we dispose ourselves</summary>\r
+        public bool DisposeOnDetachedClose = true;\r
+\r
         public DettachableControl()\r
             : base()\r
         {\r
@@ -145,16 +150,17 @@ namespace Radegast
             {\r
                 OriginalParent.ControlAdded -= new ControlEventHandler(originalParent_ControlAdded);\r
                 Size = AttachedSize;\r
-                Parent = OriginalParent;\r
             }\r
 \r
+            Parent = OriginalParent;\r
+\r
             if (detachedForm != null)\r
             {\r
                 detachedForm.Dispose();\r
                 detachedForm = null;\r
             }\r
 \r
-            if (OriginalParent == null)\r
+            if (OriginalParent == null && DisposeOnDetachedClose)\r
             {\r
                 Dispose();\r
             }\r
index 28e3147..69c19c6 100644 (file)
@@ -1,4 +1,34 @@
-namespace Radegast\r
+// \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: Sound.cs 208 2009-09-08 03:37:37Z latifer@gmail.com $\r
+//\r
+namespace Radegast\r
 {\r
     partial class MediaConsole\r
     {\r
@@ -31,7 +61,6 @@
             this.components = new System.ComponentModel.Container();\r
             this.volAudioStream = new System.Windows.Forms.TrackBar();\r
             this.pnlParcelAudio = new System.Windows.Forms.GroupBox();\r
-            this.pbAudioVolume = new System.Windows.Forms.ProgressBar();\r
             this.btnStop = new System.Windows.Forms.Button();\r
             this.btnPlay = new System.Windows.Forms.Button();\r
             this.cbKeep = new System.Windows.Forms.CheckBox();\r
             this.label2 = new System.Windows.Forms.Label();\r
             this.label1 = new System.Windows.Forms.Label();\r
             this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);\r
+            this.lblStation = new System.Windows.Forms.Label();\r
             ((System.ComponentModel.ISupportInitialize)(this.volAudioStream)).BeginInit();\r
             this.pnlParcelAudio.SuspendLayout();\r
             this.SuspendLayout();\r
             // \r
             // volAudioStream\r
             // \r
-            this.volAudioStream.LargeChange = 25;\r
+            this.volAudioStream.LargeChange = 10;\r
             this.volAudioStream.Location = new System.Drawing.Point(6, 19);\r
             this.volAudioStream.Maximum = 50;\r
             this.volAudioStream.Name = "volAudioStream";\r
             this.volAudioStream.Size = new System.Drawing.Size(347, 45);\r
-            this.volAudioStream.SmallChange = 10;\r
+            this.volAudioStream.SmallChange = 2;\r
             this.volAudioStream.TabIndex = 1;\r
             this.volAudioStream.Value = 25;\r
             // \r
             // pnlParcelAudio\r
             // \r
-            this.pnlParcelAudio.Controls.Add(this.pbAudioVolume);\r
+            this.pnlParcelAudio.Controls.Add(this.lblStation);\r
             this.pnlParcelAudio.Controls.Add(this.btnStop);\r
             this.pnlParcelAudio.Controls.Add(this.btnPlay);\r
             this.pnlParcelAudio.Controls.Add(this.cbKeep);\r
             this.pnlParcelAudio.Controls.Add(this.volAudioStream);\r
             this.pnlParcelAudio.Location = new System.Drawing.Point(3, 3);\r
             this.pnlParcelAudio.Name = "pnlParcelAudio";\r
-            this.pnlParcelAudio.Size = new System.Drawing.Size(359, 157);\r
+            this.pnlParcelAudio.Size = new System.Drawing.Size(359, 138);\r
             this.pnlParcelAudio.TabIndex = 2;\r
             this.pnlParcelAudio.TabStop = false;\r
-            this.pnlParcelAudio.Text = "Audio Stream";\r
-            // \r
-            // pbAudioVolume\r
-            // \r
-            this.pbAudioVolume.Location = new System.Drawing.Point(9, 96);\r
-            this.pbAudioVolume.Name = "pbAudioVolume";\r
-            this.pbAudioVolume.Size = new System.Drawing.Size(344, 14);\r
-            this.pbAudioVolume.TabIndex = 6;\r
+            this.pnlParcelAudio.Text = "Parcel Audio Stream";\r
             // \r
             // btnStop\r
             // \r
             this.btnStop.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;\r
             this.btnStop.Image = global::Radegast.Properties.Resources.btn_stop;\r
-            this.btnStop.Location = new System.Drawing.Point(36, 119);\r
+            this.btnStop.Location = new System.Drawing.Point(37, 99);\r
             this.btnStop.Margin = new System.Windows.Forms.Padding(0);\r
             this.btnStop.Name = "btnStop";\r
             this.btnStop.Size = new System.Drawing.Size(25, 25);\r
             this.btnStop.TabIndex = 5;\r
             this.btnStop.TextImageRelation = System.Windows.Forms.TextImageRelation.TextAboveImage;\r
             this.btnStop.UseVisualStyleBackColor = true;\r
+            this.btnStop.Click += new System.EventHandler(this.btnStop_Click);\r
             // \r
             // btnPlay\r
             // \r
             this.btnPlay.Image = global::Radegast.Properties.Resources.btn_play;\r
-            this.btnPlay.Location = new System.Drawing.Point(9, 119);\r
+            this.btnPlay.Location = new System.Drawing.Point(10, 99);\r
             this.btnPlay.Margin = new System.Windows.Forms.Padding(0);\r
             this.btnPlay.Name = "btnPlay";\r
             this.btnPlay.Size = new System.Drawing.Size(25, 25);\r
             this.btnPlay.TabIndex = 5;\r
             this.btnPlay.TextImageRelation = System.Windows.Forms.TextImageRelation.TextAboveImage;\r
             this.btnPlay.UseVisualStyleBackColor = true;\r
+            this.btnPlay.Click += new System.EventHandler(this.btnPlay_Click);\r
             // \r
             // cbKeep\r
             // \r
             this.cbKeep.AutoSize = true;\r
-            this.cbKeep.Location = new System.Drawing.Point(232, 124);\r
+            this.cbKeep.Location = new System.Drawing.Point(232, 109);\r
             this.cbKeep.Name = "cbKeep";\r
             this.cbKeep.Size = new System.Drawing.Size(121, 17);\r
             this.cbKeep.TabIndex = 4;\r
             // cbPlayAudioStream\r
             // \r
             this.cbPlayAudioStream.AutoSize = true;\r
-            this.cbPlayAudioStream.Location = new System.Drawing.Point(87, 124);\r
+            this.cbPlayAudioStream.Location = new System.Drawing.Point(79, 109);\r
             this.cbPlayAudioStream.Name = "cbPlayAudioStream";\r
-            this.cbPlayAudioStream.Size = new System.Drawing.Size(141, 17);\r
+            this.cbPlayAudioStream.Size = new System.Drawing.Size(108, 17);\r
             this.cbPlayAudioStream.TabIndex = 4;\r
-            this.cbPlayAudioStream.Text = "Play parcel audio stream";\r
+            this.cbPlayAudioStream.Text = "Auto start at login";\r
             this.cbPlayAudioStream.UseVisualStyleBackColor = true;\r
             // \r
             // txtSongTitle\r
             // \r
             this.txtSongTitle.BackColor = System.Drawing.SystemColors.Control;\r
-            this.txtSongTitle.Location = new System.Drawing.Point(41, 70);\r
+            this.txtSongTitle.Location = new System.Drawing.Point(49, 70);\r
             this.txtSongTitle.Name = "txtSongTitle";\r
             this.txtSongTitle.ReadOnly = true;\r
-            this.txtSongTitle.Size = new System.Drawing.Size(312, 20);\r
+            this.txtSongTitle.Size = new System.Drawing.Size(304, 20);\r
             this.txtSongTitle.TabIndex = 3;\r
             // \r
             // txtAudioURL\r
             // \r
             this.txtAudioURL.BackColor = System.Drawing.SystemColors.Control;\r
-            this.txtAudioURL.Location = new System.Drawing.Point(41, 48);\r
+            this.txtAudioURL.Location = new System.Drawing.Point(49, 48);\r
             this.txtAudioURL.Name = "txtAudioURL";\r
-            this.txtAudioURL.Size = new System.Drawing.Size(312, 20);\r
+            this.txtAudioURL.Size = new System.Drawing.Size(304, 20);\r
             this.txtAudioURL.TabIndex = 3;\r
             // \r
             // label2\r
             this.label1.AutoSize = true;\r
             this.label1.Location = new System.Drawing.Point(6, 51);\r
             this.label1.Name = "label1";\r
-            this.label1.Size = new System.Drawing.Size(29, 13);\r
+            this.label1.Size = new System.Drawing.Size(40, 13);\r
             this.label1.TabIndex = 2;\r
-            this.label1.Text = "URL";\r
+            this.label1.Text = "Stream";\r
+            // \r
+            // lblStation\r
+            // \r
+            this.lblStation.AutoSize = true;\r
+            this.lblStation.ForeColor = System.Drawing.Color.Blue;\r
+            this.lblStation.Location = new System.Drawing.Point(76, 93);\r
+            this.lblStation.Name = "lblStation";\r
+            this.lblStation.Size = new System.Drawing.Size(40, 13);\r
+            this.lblStation.TabIndex = 6;\r
+            this.lblStation.Text = "Station";\r
             // \r
             // MediaConsole\r
             // \r
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\r
             this.Controls.Add(this.pnlParcelAudio);\r
             this.Name = "MediaConsole";\r
-            this.Size = new System.Drawing.Size(423, 279);\r
+            this.Size = new System.Drawing.Size(368, 147);\r
             ((System.ComponentModel.ISupportInitialize)(this.volAudioStream)).EndInit();\r
             this.pnlParcelAudio.ResumeLayout(false);\r
             this.pnlParcelAudio.PerformLayout();\r
         private System.Windows.Forms.Button btnStop;\r
         private System.Windows.Forms.TextBox txtSongTitle;\r
         private System.Windows.Forms.Label label2;\r
-        private System.Windows.Forms.ProgressBar pbAudioVolume;\r
         private System.Windows.Forms.ToolTip toolTip1;\r
+        private System.Windows.Forms.Label lblStation;\r
     }\r
 }\r
index 7abb6e7..c6aae58 100644 (file)
@@ -7,6 +7,7 @@ using System.Text;
 using System.Windows.Forms;\r
 using OpenMetaverse;\r
 using OpenMetaverse.StructuredData;\r
+using Radegast.Media;\r
 \r
 namespace Radegast\r
 {\r
@@ -19,42 +20,215 @@ namespace Radegast
         {\r
             get\r
             {\r
-                return 50f / volAudioStream.Value;\r
+                return volAudioStream.Value / 50f;\r
             }\r
             set\r
             {\r
-                if (value >= 0f && value <0f)\r
+                if (value >= 0f && value < 1f)\r
                 {\r
                     volAudioStream.Value = (int)(50f * value);\r
                 }\r
             }\r
         }\r
+        private System.Threading.Timer configTimer;\r
+        private const int saveConfigTimeout = 3000;\r
+        private bool playing;\r
+        private string currentURL;\r
+        private MediaManager mngr;\r
 \r
         public MediaConsole(RadegastInstance instance)\r
         {\r
             InitializeComponent();\r
+            DisposeOnDetachedClose = false;\r
+            Text = "Media";\r
+\r
             Disposed += new EventHandler(MediaConsole_Disposed);\r
 \r
             this.instance = instance;\r
+            this.mngr = instance.MediaManager;\r
+\r
             s = instance.GlobalSettings;\r
 \r
             // Restore settings\r
             if (s["parcel_audio_url"].Type != OSDType.Unknown)\r
                 txtAudioURL.Text = s["parcel_audio_url"].AsString();\r
             if (s["parcel_audio_vol"].Type != OSDType.Unknown)\r
-                audioVolume = (float)s["parcel_audio_url"].AsReal();\r
+                audioVolume = (float)s["parcel_audio_vol"].AsReal();\r
             if (s["parcel_audio_play"].Type != OSDType.Unknown)\r
                 cbPlayAudioStream.Checked = s["parcel_audio_play"].AsBoolean();\r
             if (s["parcel_audio_keep_url"].Type != OSDType.Unknown)\r
-                cbPlayAudioStream.Checked = s["parcel_audio_keep_url"].AsBoolean();\r
+                cbKeep.Checked = s["parcel_audio_keep_url"].AsBoolean();\r
+\r
+            configTimer = new System.Threading.Timer(SaveConfig, null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);\r
+\r
+            if (!instance.MediaManager.SoundSystemAvailable)\r
+            {\r
+                foreach (Control c in pnlParcelAudio.Controls)\r
+                    c.Enabled = false;\r
+            }\r
+\r
+            // GUI Events\r
+            volAudioStream.Scroll += new EventHandler(volAudioStream_Scroll);\r
+            txtAudioURL.TextChanged += new EventHandler(txtAudioURL_TextChanged);\r
+            cbKeep.CheckedChanged += new EventHandler(cbKeep_CheckedChanged);\r
+            cbPlayAudioStream.CheckedChanged += new EventHandler(cbPlayAudioStream_CheckedChanged);\r
+            lblStation.Tag = lblStation.Text = string.Empty;\r
+            lblStation.Click += new EventHandler(lblStation_Click);\r
+\r
+            // Network callbacks\r
+            client.Parcels.OnParcelProperties += new ParcelManager.ParcelPropertiesCallback(Parcels_OnParcelProperties);\r
+        }\r
+\r
+        private void MediaConsole_Disposed(object sender, EventArgs e)\r
+        {\r
+            Stop();\r
+\r
+            client.Parcels.OnParcelProperties -= new ParcelManager.ParcelPropertiesCallback(Parcels_OnParcelProperties);\r
+\r
+            if (configTimer != null)\r
+            {\r
+                configTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);\r
+                configTimer.Dispose();\r
+                configTimer = null;\r
+            }\r
+        }\r
+\r
+        void Parcels_OnParcelProperties(Simulator simulator, Parcel parcel, ParcelResult result, int selectedPrims, int sequenceID, bool snapSelection)\r
+        {\r
+            if (cbKeep.Checked || result != ParcelResult.Single) return;\r
+\r
+            if (InvokeRequired)\r
+            {\r
+                BeginInvoke(new MethodInvoker(() => Parcels_OnParcelProperties(simulator, parcel, result, selectedPrims, sequenceID, snapSelection)));\r
+                return;\r
+            }\r
+\r
+            txtAudioURL.Text = parcel.MusicURL;\r
+            if (playing)\r
+            {\r
+                if (currentURL != txtAudioURL.Text)\r
+                {\r
+                    currentURL = txtAudioURL.Text;\r
+                    Play();\r
+                }\r
+            }\r
+            else if (cbPlayAudioStream.Checked)\r
+            {\r
+                currentURL = txtAudioURL.Text;\r
+                Play();\r
+            }\r
         }\r
 \r
-        void MediaConsole_Disposed(object sender, EventArgs e)\r
+        private void Stop()\r
         {\r
+            playing = false;\r
+            if (mngr.ParcelMusic != null)\r
+                mngr.ParcelMusic.Dispose();\r
+            mngr.ParcelMusic = null;\r
+            lblStation.Tag = lblStation.Text = string.Empty;\r
+            txtSongTitle.Text = string.Empty;\r
+        }\r
+\r
+        private void Play()\r
+        {\r
+            Stop();\r
+            playing = true;\r
+            mngr.ParcelMusic = new Sound(mngr.FMODSystem);\r
+            mngr.ParcelMusic.Volume = audioVolume;\r
+            mngr.ParcelMusic.PlayStream(currentURL);\r
+            mngr.ParcelMusic.OnStreamInfo += new Sound.StreamInfoCallback(ParcelMusic_OnStreamInfo);\r
+        }\r
+\r
+        void ParcelMusic_OnStreamInfo(object sender, StreamInfoArgs e)\r
+        {\r
+            if (InvokeRequired)\r
+            {\r
+                BeginInvoke(new MethodInvoker(() => ParcelMusic_OnStreamInfo(sender, e)));\r
+                return;\r
+            }\r
+\r
+            switch (e.Key)\r
+            {\r
+                case "artist":\r
+                    txtSongTitle.Text = e.Value;\r
+                    break;\r
+\r
+                case "title":\r
+                    txtSongTitle.Text += " - " + e.Value;\r
+                    break;\r
+\r
+                case "icy-name":\r
+                    lblStation.Text = e.Value;\r
+                    break;\r
+\r
+                case "icy-url":\r
+                    lblStation.Tag = e.Value;\r
+                    break;\r
+            }\r
+        }\r
+\r
+        private void SaveConfig(object state)\r
+        {\r
+            if (InvokeRequired)\r
+            {\r
+                BeginInvoke(new MethodInvoker(() => SaveConfig(state)));\r
+                return;\r
+            }\r
+\r
             s["parcel_audio_url"] = OSD.FromString(txtAudioURL.Text);\r
             s["parcel_audio_vol"] = OSD.FromReal(audioVolume);\r
             s["parcel_audio_play"] = OSD.FromBoolean(cbPlayAudioStream.Checked);\r
             s["parcel_audio_keep_url"] = OSD.FromBoolean(cbKeep.Checked);\r
         }\r
+\r
+        #region GUI event handlers\r
+        void lblStation_Click(object sender, EventArgs e)\r
+        {\r
+            if (lblStation.ToString() != string.Empty)\r
+            {\r
+                instance.MainForm.ProcessLink(lblStation.Tag.ToString());\r
+            }\r
+        }\r
+\r
+        private void volAudioStream_Scroll(object sender, EventArgs e)\r
+        {\r
+            configTimer.Change(saveConfigTimeout, System.Threading.Timeout.Infinite);\r
+            if (mngr.ParcelMusic != null)\r
+                mngr.ParcelMusic.Volume = volAudioStream.Value / 50f;\r
+        }\r
+\r
+        private void txtAudioURL_TextChanged(object sender, EventArgs e)\r
+        {\r
+            configTimer.Change(saveConfigTimeout, System.Threading.Timeout.Infinite);\r
+        }\r
+\r
+        void cbPlayAudioStream_CheckedChanged(object sender, EventArgs e)\r
+        {\r
+            configTimer.Change(saveConfigTimeout, System.Threading.Timeout.Infinite);\r
+        }\r
+\r
+        void cbKeep_CheckedChanged(object sender, EventArgs e)\r
+        {\r
+            configTimer.Change(saveConfigTimeout, System.Threading.Timeout.Infinite);\r
+        }\r
+\r
+        private void btnPlay_Click(object sender, EventArgs e)\r
+        {\r
+            if (!playing)\r
+            {\r
+                currentURL = txtAudioURL.Text;\r
+                Play();\r
+            }\r
+        }\r
+\r
+        private void btnStop_Click(object sender, EventArgs e)\r
+        {\r
+            if (playing)\r
+            {\r
+                currentURL = string.Empty;\r
+                Stop();\r
+            }\r
+        }\r
+        #endregion GUI event handlers\r
     }\r
 }\r
index 7ce03af..e641aef 100644 (file)
   <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">\r
     <value>17, 17</value>\r
   </metadata>\r
+  <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">\r
+    <value>17, 17</value>\r
+  </metadata>\r
 </root>
\ No newline at end of file
index 51d769b..5b7f3f2 100644 (file)
@@ -81,7 +81,6 @@ namespace Radegast
             this.tmnuPrefs = new System.Windows.Forms.ToolStripMenuItem();\r
             this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();\r
             this.tmnuExit = new System.Windows.Forms.ToolStripMenuItem();\r
-            this.mediaConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\r
             this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();\r
             this.tbtnDebug = new System.Windows.Forms.ToolStripDropDownButton();\r
             this.tmnuDebugLog = new System.Windows.Forms.ToolStripMenuItem();\r
@@ -127,6 +126,7 @@ namespace Radegast
             this.toolStripContainer1 = new System.Windows.Forms.ToolStripContainer();\r
             this.pnlDialog = new System.Windows.Forms.Panel();\r
             this.timerWorldClock = new System.Windows.Forms.Timer(this.components);\r
+            this.tbtnMedia = new System.Windows.Forms.ToolStripButton();\r
             this.toolStrip1.SuspendLayout();\r
             this.statusStrip1.SuspendLayout();\r
             this.toolStripContainer1.TopToolStripPanel.SuspendLayout();\r
@@ -147,7 +147,8 @@ namespace Radegast
             this.tbnPlugins,\r
             this.tbnObjects,\r
             this.tbtnGroups,\r
-            this.lblTime});\r
+            this.lblTime,\r
+            this.tbtnMedia});\r
             this.toolStrip1.Location = new System.Drawing.Point(0, 0);\r
             this.toolStrip1.Name = "toolStrip1";\r
             this.toolStrip1.Size = new System.Drawing.Size(738, 25);\r
@@ -166,8 +167,7 @@ namespace Radegast
             this.toolStripMenuItem3,\r
             this.tmnuPrefs,\r
             this.toolStripMenuItem2,\r
-            this.tmnuExit,\r
-            this.mediaConsoleToolStripMenuItem});\r
+            this.tmnuExit});\r
             this.tbtnSLeek.Image = global::Radegast.Properties.Resources.computer_16;\r
             this.tbtnSLeek.ImageTransparentColor = System.Drawing.Color.Magenta;\r
             this.tbtnSLeek.Name = "tbtnSLeek";\r
@@ -220,14 +220,6 @@ namespace Radegast
             this.tmnuExit.Text = "E&xit";\r
             this.tmnuExit.Click += new System.EventHandler(this.tmnuExit_Click);\r
             // \r
-            // mediaConsoleToolStripMenuItem\r
-            // \r
-            this.mediaConsoleToolStripMenuItem.Name = "mediaConsoleToolStripMenuItem";\r
-            this.mediaConsoleToolStripMenuItem.Size = new System.Drawing.Size(162, 22);\r
-            this.mediaConsoleToolStripMenuItem.Text = "Media Console...";\r
-            this.mediaConsoleToolStripMenuItem.Visible = false;\r
-            this.mediaConsoleToolStripMenuItem.Click += new System.EventHandler(this.mediaConsoleToolStripMenuItem_Click);\r
-            // \r
             // toolStripSeparator1\r
             // \r
             this.toolStripSeparator1.Name = "toolStripSeparator1";\r
@@ -645,6 +637,17 @@ namespace Radegast
             this.timerWorldClock.Interval = 1000;\r
             this.timerWorldClock.Tick += new System.EventHandler(this.timerWorldClock_Tick);\r
             // \r
+            // tbtnMedia\r
+            // \r
+            this.tbtnMedia.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;\r
+            this.tbtnMedia.Image = ((System.Drawing.Image)(resources.GetObject("tbtnMedia.Image")));\r
+            this.tbtnMedia.ImageTransparentColor = System.Drawing.Color.Magenta;\r
+            this.tbtnMedia.Name = "tbtnMedia";\r
+            this.tbtnMedia.Size = new System.Drawing.Size(44, 22);\r
+            this.tbtnMedia.Text = "Media";\r
+            this.tbtnMedia.Visible = false;\r
+            this.tbtnMedia.Click += new System.EventHandler(this.tbtnMedia_Click);\r
+            // \r
             // frmMain\r
             // \r
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);\r
@@ -732,7 +735,7 @@ namespace Radegast
         private System.Windows.Forms.ToolStripMenuItem tmnuTeleportHome;\r
         private System.Windows.Forms.ToolStripLabel lblTime;\r
         private System.Windows.Forms.Timer timerWorldClock;\r
-        private System.Windows.Forms.ToolStripMenuItem mediaConsoleToolStripMenuItem;\r
+        private System.Windows.Forms.ToolStripButton tbtnMedia;\r
     }\r
 }\r
 \r
index 8afcc41..c4526a1 100644 (file)
@@ -173,7 +173,11 @@ namespace Radegast
         {\r
             InitializeTabsConsole();\r
             InitializeDebugLogForm();\r
-            mediaConsole = new MediaConsole(instance);\r
+            if (instance.MediaManager.SoundSystemAvailable)\r
+            {\r
+                mediaConsole = new MediaConsole(instance);\r
+                tbtnMedia.Visible = true;\r
+            }\r
         }\r
 \r
         private void netcom_ClientLoginStatus(object sender, ClientLoginEventArgs e)\r
@@ -907,11 +911,14 @@ namespace Radegast
             lblTime.Text = now.ToString("h:mm tt", System.Globalization.CultureInfo.InvariantCulture);\r
         }\r
 \r
-        #endregion\r
-\r
-        private void mediaConsoleToolStripMenuItem_Click(object sender, EventArgs e)\r
+        private void tbtnMedia_Click(object sender, EventArgs e)\r
         {\r
-            this.MediaConsole.Detached = true;\r
+            if (!mediaConsole.Detached)\r
+                mediaConsole.Detached = true;\r
+            else\r
+                mediaConsole.Focus();\r
         }\r
+\r
+        #endregion\r
     }\r
 }
\ No newline at end of file
index 4cb03aa..453e9ca 100644 (file)
         KlSA8/zRh9ABIDUG+1JpAAAAAElFTkSuQmCC\r
 </value>\r
   </data>\r
+  <data name="tbtnMedia.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">\r
+    <value>\r
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8\r
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIISURBVDhPpZP7S1NxGMbPPxKaXVUkMEq8IpKUCoY/hGgI\r
+        ymqkDYYXcCjDZOANURSjCNGFQUTsl4GXVMxKk62YU4fXQpaIlygHQxBRH8/zwvyaIAYe+HLgnPN8nue9\r
+        HA3nvDTq63oW/jm13XOwvPTB3DYFY5MH+bXfcN8ygfTSMSSXfESicQDxBqdYHwH29g9w2tnZ3UcguIvN\r
+        rR3417exuBJE5N1n/wfwLgXEOc38Bc6xNRHb+/y4nm49G0Bnit2zf9H6bkliE/jKuYxrd6oVgDWfjB+K\r
+        TWeKMyrGEVfowITvD9re/9ABVQrAhh0HHK+ZselMMaN/mvwtDb+aVqkA7HYIwIj3ysfluPTorJnP6Ezx\r
+        oHsD1s5ZXEktUwCOioB5f1CEPR9+wTG6iuiserTo8dkwng7HT/R+XUPF8xlcTjErAOdMcW6NW8STiwG8\r
+        7vej8oUPN/PsEv3t8Ao0TZP3T1u8uJRkUgAuSYHtO97oLxmXd5t9Ho8aPTK+GzntqNfrLm2fFoihwYOI\r
+        xGIF4KjoGBLzY1OrF9k6OOFxnwDC4wxIMX1G0pMhgVyMNyoA13PAtS7OrJk1PrC69LUdQWxuF6IybHrX\r
+        LRI7JrtZdoDAo1XmbjMyD+tjSXxGcXRmnYg5ttD9QuxDhN0uUgDOmbvNTpPOJaGAo2K36cyaGZvOFIfd\r
+        KlSA8/zRh9ABIDUG+1JpAAAAAElFTkSuQmCC\r
+</value>\r
+  </data>\r
   <metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">\r
     <value>116, 17</value>\r
   </metadata>\r