From a5ad792e6c90eb9412325e636c6e4eafc4a8a91d Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Mon, 12 Jul 2010 19:46:23 +0100
Subject: implement llSetPrimMediaParams()

Untested
---
 OpenSim/Framework/PrimitiveBaseShape.cs            |   1 +
 .../CoreModules/World/Media/Moap/MoapModule.cs     |  54 ++++++++--
 OpenSim/Region/Framework/Interfaces/IMoapModule.cs |  14 ++-
 OpenSim/Region/Framework/Scenes/SceneObjectPart.cs |   3 +-
 .../Shared/Api/Implementation/LSL_Api.cs           | 113 ++++++++++++++++++++-
 .../Shared/Api/Runtime/LSL_Constants.cs            |  12 ++-
 6 files changed, 184 insertions(+), 13 deletions(-)

diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs
index 517dbf6..85638ca 100644
--- a/OpenSim/Framework/PrimitiveBaseShape.cs
+++ b/OpenSim/Framework/PrimitiveBaseShape.cs
@@ -176,6 +176,7 @@ namespace OpenSim.Framework
         /// <summary>
         /// Entries to store media textures on each face
         /// </summary>
+        /// Do not change this value directly - always do it through an IMoapModule.
         public List<MediaEntry> Media { get; set; }
 
         public PrimitiveBaseShape()
diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
index 9f74367..064047d 100644
--- a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
+++ b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
@@ -102,16 +102,54 @@ namespace OpenSim.Region.CoreModules.Media.Moap
         public MediaEntry GetMediaEntry(SceneObjectPart part, int face)
         {
             if (face < 0)
-                throw new ArgumentException("Face cannot be less than zero");
+                throw new ArgumentException("Face cannot be less than zero");                                 
+            
+            int maxFaces = part.GetNumberOfSides() - 1;
+            if (face > maxFaces)
+                throw new ArgumentException(
+                    string.Format("Face argument was {0} but max is {1}", face, maxFaces));
             
-            List<MediaEntry> media = part.Shape.Media;           
+            List<MediaEntry> media = part.Shape.Media;
             
-            if (face > media.Count - 1)
+            if (null == media)
+            {
+                return null;
+            }
+            else
+            {            
+                // TODO: Really need a proper copy constructor down in libopenmetaverse
+                return MediaEntry.FromOSD(media[face].GetOSD());                        
+            }
+        }
+        
+        public void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me)
+        {
+            if (face < 0)
+                throw new ArgumentException("Face cannot be less than zero");
+                               
+            int maxFaces = part.GetNumberOfSides() - 1;
+            if (face > maxFaces)
                 throw new ArgumentException(
-                    string.Format("Face argument was {0} but max is {1}", face, media.Count - 1));
+                    string.Format("Face argument was {0} but max is {1}", face, maxFaces));            
             
-            // TODO: Really need a proper copy constructor down in libopenmetaverse
-            return MediaEntry.FromOSD(media[face].GetOSD());                        
+            if (null == part.Shape.Media)
+                part.Shape.Media = new List<MediaEntry>(maxFaces);
+                        
+            part.Shape.Media[face] = me;                                   
+            
+            if (null == part.MediaUrl)
+            {
+                // TODO: We can't set the last changer until we start tracking which cap we give to which agent id
+                part.MediaUrl = "x-mv:0000000000/" + UUID.Zero;
+            }
+            else
+            {
+                string rawVersion = part.MediaUrl.Substring(5, 10);
+                int version = int.Parse(rawVersion);
+                part.MediaUrl = string.Format("x-mv:{0:D10}/{1}", ++version, UUID.Zero);
+            }               
+            
+            part.ScheduleFullUpdate();
         }
         
         /// <summary>
@@ -140,7 +178,7 @@ namespace OpenSim.Region.CoreModules.Media.Moap
             throw new Exception(
                 string.Format(
                     "[MOAP]: ObjectMediaMessage has unrecognized ObjectMediaBlock of {0}", 
-                    omm.Request.GetType()));
+                    omm.Request.GetType()));         
         }
         
         /// <summary>
@@ -233,7 +271,7 @@ namespace OpenSim.Region.CoreModules.Media.Moap
             
             m_log.DebugFormat("[MOAP]: Storing media url [{0}] in prim {1} {2}", part.MediaUrl, part.Name, part.UUID);
             
-            // Arguably we don't need to send a full update to the avatar that just changed the texture.
+            // Arguably, we could avoid sending a full update to the avatar that just changed the texture.
             part.ScheduleFullUpdate();
             
             return string.Empty;
diff --git a/OpenSim/Region/Framework/Interfaces/IMoapModule.cs b/OpenSim/Region/Framework/Interfaces/IMoapModule.cs
index 4447f34..31bb6d8 100644
--- a/OpenSim/Region/Framework/Interfaces/IMoapModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IMoapModule.cs
@@ -39,9 +39,19 @@ namespace OpenSim.Region.Framework.Interfaces
         /// <summary>
         /// Get the media entry for a given prim face.
         /// </summary>
+        /// A copy of the media entry is returned rather than the original, so this can be altered at will without
+        /// affecting the original settings.
         /// <param name="part"></param>
         /// <param name="face"></param>
         /// <returns></returns>
-        MediaEntry GetMediaEntry(SceneObjectPart part, int face);        
-    }
+        MediaEntry GetMediaEntry(SceneObjectPart part, int face);
+        
+        /// <summary>
+        /// Set the media entry for a given prim face.
+        /// </summary>
+        /// <param name="SceneObjectPart"></param>
+        /// <param name="face"></param>
+        /// <param name="me"></param>
+        void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me);
+    }        
 }
\ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index a8c20dd..e6a1696 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -978,8 +978,9 @@ namespace OpenSim.Region.Framework.Scenes
         }
         
         /// <summary>
-        /// Used for media on a prim
+        /// Used for media on a prim.
         /// </summary>
+        /// Do not change this value directly - always do it through an IMoapModule.
         public string MediaUrl 
         { 
             get
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index e18e33e..4d57193 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -7816,7 +7816,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
             // LSL Spec http://wiki.secondlife.com/wiki/LlGetPrimMediaParams says to fail silently if face is invalid
             // TODO: Need to correctly handle case where a face has no media (which gives back an empty list).
             // Assuming silently fail means give back an empty list.  Ideally, need to check this.
-            if (face < 0 || face > m_host.Shape.Media.Count - 1)
+            if (face < 0 || face > m_host.GetNumberOfSides() - 1)
                 return new LSL_List();
             
             return GetLinkPrimMediaParams(face, rules);
@@ -7830,6 +7830,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
             
             MediaEntry me = module.GetMediaEntry(m_host, face);
             
+            // As per http://wiki.secondlife.com/wiki/LlGetPrimMediaParams
+            if (null == me)
+                return new LSL_List();
+            
             LSL_List res = new LSL_List();
 
             for (int i = 0; i < rules.Length; i++)
@@ -7912,6 +7916,113 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
             return res;
         }
         
+        public LSL_Integer llSetPrimMediaParams(int face, LSL_List rules)
+        {
+            m_host.AddScriptLPS(1);
+            ScriptSleep(1000);
+
+            // LSL Spec http://wiki.secondlife.com/wiki/LlSetPrimMediaParams says to fail silently if face is invalid
+            // Assuming silently fail means sending back LSL_STATUS_OK.  Ideally, need to check this.
+            // Don't perform the media check directly
+            if (face < 0 || face > m_host.GetNumberOfSides() - 1)
+                return ScriptBaseClass.LSL_STATUS_OK;
+            
+            return SetPrimMediaParams(face, rules);            
+        }
+        
+        public LSL_Integer SetPrimMediaParams(int face, LSL_List rules)
+        {
+            IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>();
+            if (null == module)
+                throw new Exception("Media on a prim functions not available");
+            
+            MediaEntry me = module.GetMediaEntry(m_host, face);
+            if (null == me)
+                me = new MediaEntry();
+            
+            int i = 0;
+            
+            while (i < rules.Length - 1)
+            {
+                int code = rules.GetLSLIntegerItem(i++);
+                
+                switch (code)
+                {
+                    case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE:
+                        me.EnableAlterntiveImage = (rules.GetLSLIntegerItem(i++) != 0 ? true : false);
+                        break;
+                        
+                    case ScriptBaseClass.PRIM_MEDIA_CONTROLS:
+                        int v = rules.GetLSLIntegerItem(i++);
+                        if (ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD == v)
+                            me.Controls = MediaControls.Standard;
+                        else
+                            me.Controls = MediaControls.Mini;
+                        break;
+                        
+                    case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL:
+                        me.CurrentURL = rules.GetLSLStringItem(i++);
+                        break;
+                        
+                    case ScriptBaseClass.PRIM_MEDIA_HOME_URL:
+                        me.HomeURL = rules.GetLSLStringItem(i++);
+                        break;
+                        
+                    case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP:
+                        me.AutoLoop = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
+                        break;
+                        
+                    case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY:
+                        me.AutoPlay = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
+                        break;
+                        
+                    case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE:
+                        me.AutoScale = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
+                        break;
+                        
+                    case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM:
+                        me.AutoZoom = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
+                        break;
+                        
+                    case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT:
+                        me.InteractOnFirstClick = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
+                        break;
+                        
+                    case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS:
+                        me.Width = (int)rules.GetLSLIntegerItem(i++);
+                        break;
+                        
+                    case ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS:
+                        me.Height = (int)rules.GetLSLIntegerItem(i++);
+                        break;
+                        
+                    case ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE:
+                        me.EnableWhiteList = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
+                        break;
+                        
+                    case ScriptBaseClass.PRIM_MEDIA_WHITELIST:
+                        string[] rawWhiteListUrls = rules.GetLSLStringItem(i++).ToString().Split(new char[] { ',' });
+                        List<string> whiteListUrls = new List<string>();
+                        Array.ForEach(
+                            rawWhiteListUrls, delegate(string rawUrl) { whiteListUrls.Add(rawUrl.Trim()); });
+                        me.WhiteList = whiteListUrls.ToArray();
+                        break;
+                        
+                    case ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT:
+                        me.InteractPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++);
+                        break;
+                        
+                    case ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL:
+                        me.ControlPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++);
+                        break;
+                }
+            }       
+                        
+            module.SetMediaEntry(m_host, face, me);
+            
+            return ScriptBaseClass.LSL_STATUS_OK;
+        }
+        
         //  <remarks>
         //  <para>
         //  The .NET definition of base 64 is:
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index 9a64f8c..6ef786a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -518,7 +518,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
         public static readonly vector TOUCH_INVALID_TEXCOORD = new vector(-1.0, -1.0, 0.0);
         public static readonly vector TOUCH_INVALID_VECTOR = ZERO_VECTOR;
         
-        // constants for llGetPrimMediaParams
+        // constants for llGetPrimMediaParams/llSetPrimMediaParams
         public const int PRIM_MEDIA_ALT_IMAGE_ENABLE = 0;
         public const int PRIM_MEDIA_CONTROLS = 1;
         public const int PRIM_MEDIA_CURRENT_URL = 2;
@@ -542,6 +542,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
         public const int PRIM_MEDIA_PERM_OWNER = 1;
         public const int PRIM_MEDIA_PERM_GROUP = 2;
         public const int PRIM_MEDIA_PERM_ANYONE = 4;
+        
+        // extra constants for llSetPrimMediaParams
+        public static readonly LSLInteger LSL_STATUS_OK = new LSLInteger(0);
+        public static readonly LSLInteger LSL_STATUS_MALFORMED_PARAMS = new LSLInteger(1000);
+        public static readonly LSLInteger LSL_STATUS_TYPE_MISMATCH = new LSLInteger(1001);
+        public static readonly LSLInteger LSL_STATUS_BOUNDS_ERROR = new LSLInteger(1002);
+        public static readonly LSLInteger LSL_STATUS_NOT_FOUND = new LSLInteger(1003);
+        public static readonly LSLInteger LSL_STATUS_NOT_SUPPORTED = new LSLInteger(1004);
+        public static readonly LSLInteger LSL_STATUS_INTERNAL_ERROR = new LSLInteger(1999);
+        public static readonly LSLInteger LSL_STATUS_WHITELIST_FAILED = new LSLInteger(2001);
 
         // Constants for default textures
         public const string TEXTURE_BLANK = "5748decc-f629-461c-9a36-a35a221fe21f";
-- 
cgit v1.1