From bed6c763a5004a2bba2c7df26514747422f1e43a Mon Sep 17 00:00:00 2001 From: Homer Horwitz Date: Sat, 11 Oct 2008 15:18:55 +0000 Subject: * Rework llParcelMediaCommandList * Add missing PARCEL_MEDIA_COMMAND_* constants * Fix a copy/paste error in SendParcelMediaUpdate llParcelMediaCommandList should work now --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 2 +- .../Shared/Api/Implementation/LSL_Api.cs | 236 ++++++++++++++++----- .../Shared/Api/Runtime/LSL_Constants.cs | 3 + 3 files changed, 185 insertions(+), 56 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 6ec9f7f..4714bb3 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -6745,7 +6745,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP updatePacket.DataBlockExtended.MediaType = Utils.StringToBytes(mediaType); updatePacket.DataBlockExtended.MediaDesc = Utils.StringToBytes(mediaDesc); updatePacket.DataBlockExtended.MediaWidth = mediaWidth; - updatePacket.DataBlockExtended.MediaWidth = mediaHeight; + updatePacket.DataBlockExtended.MediaHeight = mediaHeight; updatePacket.DataBlockExtended.MediaLoop = mediaLoop; OutPacket(updatePacket, ThrottleOutPacketType.Unknown); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index a2c82cf..165e213 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7184,98 +7184,224 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llParcelMediaCommandList(LSL_List commandList) { - //TO DO: Implement the missing commands - //PARCEL_MEDIA_COMMAND_STOP Stop the media stream and go back to the first frame. - //PARCEL_MEDIA_COMMAND_PAUSE Pause the media stream (stop playing but stay on current frame). - //PARCEL_MEDIA_COMMAND_PLAY Start the media stream playing from the current frame and stop when the end is reached. - //PARCEL_MEDIA_COMMAND_LOOP Start the media stream playing from the current frame. When the end is reached, loop to the beginning and continue. - //PARCEL_MEDIA_COMMAND_TEXTURE key uuid Use this to get or set the parcel's media texture. - //PARCEL_MEDIA_COMMAND_URL string url Used to get or set the parcel's media url. - //PARCEL_MEDIA_COMMAND_TIME float time Move a media stream to a specific time. - //PARCEL_MEDIA_COMMAND_AGENT key uuid Applies the media command to the specified agent only. - //PARCEL_MEDIA_COMMAND_UNLOAD Completely unloads the movie and restores the original texture. - //PARCEL_MEDIA_COMMAND_AUTO_ALIGN integer boolean Sets the parcel option 'Auto scale content'. - //PARCEL_MEDIA_COMMAND_TYPE string mime_type Use this to get or set the parcel media MIME type (e.g. "text/html"). (1.19.1 RC0 or later) - //PARCEL_MEDIA_COMMAND_SIZE integer x, integer y Use this to get or set the parcel media pixel resolution. (1.19.1 RC0 or later) - //PARCEL_MEDIA_COMMAND_DESC string desc Use this to get or set the parcel media description. (1.19.1 RC0 or later) - //PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later) + // TODO: Not implemented yet (missing in libomv?): + // PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later) + m_host.AddScriptLPS(1); + + // according to the docs, this command only works if script owner and land owner are the same + UUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); + if (landowner == UUID.Zero || landowner != m_host.ObjectOwner) return; + + bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)? + + LandData landData = World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); + string url = landData.MediaURL; + string texture = landData.MediaID.ToString(); + bool autoAlign = landData.MediaAutoScale != 0; + string mediaType = ""; // TODO these have to be added as soon as LandData supports it + string description = ""; + int width = 0; + int height = 0; + + ParcelMediaCommandEnum? commandToSend = null; + float time = 0.0f; // default is from start + + ScenePresence presence = null; + for (int i = 0; i < commandList.Data.Length; i++) { - switch ((ParcelMediaCommandEnum)commandList.Data[i]) + ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; + switch (command) { - case ParcelMediaCommandEnum.Play: - List scenePresencePlayList = World.GetScenePresences(); - foreach (ScenePresence agent in scenePresencePlayList) + case ParcelMediaCommandEnum.Agent: + // we send only to one agent + if ((i + 1) < commandList.Length) { - if (!agent.IsChildAgent) + if (commandList.Data[i + 1] is LSL_String) { - agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Play, 0); + UUID agentID; + if (UUID.TryParse((LSL_String)commandList.Data[i + 1], out agentID)) + { + presence = World.GetScenePresence(agentID); + } } + else ShoutError("The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key"); + ++i; } break; + + case ParcelMediaCommandEnum.Loop: + case ParcelMediaCommandEnum.Play: + case ParcelMediaCommandEnum.Pause: case ParcelMediaCommandEnum.Stop: - List scenePresenceStopList = World.GetScenePresences(); - foreach (ScenePresence agent in scenePresenceStopList) + case ParcelMediaCommandEnum.Unload: + commandToSend = command; + break; + + case ParcelMediaCommandEnum.Url: + if ((i + 1) < commandList.Length) { - if (!agent.IsChildAgent) + if (commandList.Data[i + 1] is LSL_String) { - agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Stop, 0); + url = (LSL_String)commandList.Data[i + 1]; + update = true; } + else ShoutError("The argument of PARCEL_MEDIA_COMMAND_URL must be a string."); + ++i; } break; - case ParcelMediaCommandEnum.Pause: - List scenePresencePauseList = World.GetScenePresences(); - foreach (ScenePresence agent in scenePresencePauseList) + + case ParcelMediaCommandEnum.Texture: + if ((i + 1) < commandList.Length) { - if (!agent.IsChildAgent) + if (commandList.Data[i + 1] is LSL_String) { - agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Pause, 0); + texture = (LSL_String)commandList.Data[i + 1]; + update = true; } + else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or key."); + ++i; } break; - case ParcelMediaCommandEnum.Url: + case ParcelMediaCommandEnum.Time: if ((i + 1) < commandList.Length) { - if (commandList.Data[i + 1] is string) + if (commandList.Data[i + 1] is LSL_Float) { - UUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); + time = (float)(LSL_Float)commandList.Data[i + 1]; + } + else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TIME must be a float."); + ++i; + } + break; - if (landowner == UUID.Zero) - { - return; - } + case ParcelMediaCommandEnum.AutoAlign: + if ((i + 1) < commandList.Length) + { + if (commandList.Data[i + 1] is LSL_Integer) + { + autoAlign = (LSL_Integer)commandList.Data[i + 1]; + update = true; + } - if (landowner != m_host.ObjectOwner) - { - return; - } + else ShoutError("The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer."); + ++i; + } + break; + + case ParcelMediaCommandEnum.Type: + if ((i + 1) < commandList.Length) + { + if (commandList.Data[i + 1] is LSL_String) + { + mediaType = (LSL_String)commandList.Data[i + 1]; + update = true; + } + else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string."); + ++i; + } + break; - World.SetLandMediaURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, (string)commandList.GetLSLStringItem(i + 1)); + case ParcelMediaCommandEnum.Desc: + if ((i + 1) < commandList.Length) + { + if (commandList.Data[i + 1] is LSL_String) + { + description = (LSL_String)commandList.Data[i + 1]; + update = true; + } + else ShoutError("The argument of PARCEL_MEDIA_COMMAND_DESC must be a string."); + ++i; + } + break; - List scenePresenceList = World.GetScenePresences(); - LandData landData = World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); - //Send an update of the mediaURL to all the clients that are in the parcel - foreach (ScenePresence agent in scenePresenceList) + case ParcelMediaCommandEnum.Size: + if ((i + 2) < commandList.Length) + { + if (commandList.Data[i + 1] is LSL_Integer) + { + if (commandList.Data[i + 2] is LSL_Integer) { - if (!agent.IsChildAgent) - { - //Send parcel media update to the client - agent.ControllingClient.SendParcelMediaUpdate(landData.MediaURL, landData.MediaID, landData.MediaAutoScale, "", landData.Description, 0, 0, 1); - } + width = (LSL_Integer)commandList.Data[i + 1]; + height = (LSL_Integer)commandList.Data[i + 2]; + update = true; } - + else ShoutError("The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer."); } - i++; + else ShoutError("The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer."); + i += 2; } break; + default: - ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; - NotImplemented("llParcelMediaCommandList parameter do not supported yet: " + Enum.Parse(mediaCommandEnum.GetType(), commandList.Data[i].ToString()).ToString()); + NotImplemented("llParcelMediaCommandList parameter not supported yet: " + Enum.Parse(typeof(ParcelMediaCommandEnum), commandList.Data[i].ToString()).ToString()); break; }//end switch + }//end for + + // if we didn't get a presence, we send to all and change the url + // if we did get a presence, we only send to the agent specified, and *don't change the land settings*! + + // did something important change or do we only start/stop/pause? + if (update) + { + if (presence == null) + { + // we send to all + + landData.MediaID = new UUID(texture); + landData.MediaAutoScale = autoAlign ? (byte)1 : (byte)0; + // do that one last, it will cause a ParcelPropertiesUpdate + World.SetLandMediaURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url); + + // now send to all (non-child) agents + List agents = World.GetAvatars(); + foreach(ScenePresence agent in agents) + { + agent.ControllingClient.SendParcelMediaUpdate(landData.MediaURL, + landData.MediaID, + landData.MediaAutoScale, + mediaType, + description, + width, height, + 1); // TODO do some LOOP logic here + } + } + else if(!presence.IsChildAgent) + { + // we only send to one (root) agent + presence.ControllingClient.SendParcelMediaUpdate(url, + new UUID(texture), + autoAlign ? (byte)1 : (byte)0, + mediaType, + description, + width, height, + 1); // TODO do some LOOP logic here + } + } + if (commandToSend != null) + { + // the commandList contained a start/stop/... command, too + if (presence == null) + { + // send to all (non-child) agents + List agents = World.GetAvatars(); + foreach(ScenePresence agent in agents) + { + agent.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? + (ParcelMediaCommandEnum)commandToSend, + time); + } + } + else if(!presence.IsChildAgent) + { + presence.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? + (ParcelMediaCommandEnum)commandToSend, + time); + } } // ScriptSleep(2000); } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 2c5c0b3..c3d3270 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -372,6 +372,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int PARCEL_MEDIA_COMMAND_AGENT = 7; public const int PARCEL_MEDIA_COMMAND_UNLOAD = 8; public const int PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9; + public const int PARCEL_MEDIA_COMMAND_TYPE = 10; + public const int PARCEL_MEDIA_COMMAND_SIZE = 11; + public const int PARCEL_MEDIA_COMMAND_DESC = 12; public const int PARCEL_FLAG_ALLOW_FLY = 0x1; // parcel allows flying public const int PARCEL_FLAG_ALLOW_SCRIPTS = 0x2; // parcel allows outside scripts -- cgit v1.1