diff --git a/OpenMetaverse/Messages/LindenMessages.cs b/OpenMetaverse/Messages/LindenMessages.cs index 67677550..9cd75fa7 100644 --- a/OpenMetaverse/Messages/LindenMessages.cs +++ b/OpenMetaverse/Messages/LindenMessages.cs @@ -1181,7 +1181,7 @@ namespace OpenMetaverse.Messages.Linden /// The of the groups insignia public UUID GroupInsigniaID; /// The name of the group - public string GroupName; + public string GroupName; /// The aggregate permissions the agent has in the group for all roles the agent /// is assigned public GroupPowers GroupPowers; @@ -2205,7 +2205,7 @@ namespace OpenMetaverse.Messages.Linden #region Grid/Maps - /// Base class for Map Layers via Capabilities + /// Base class for Map Layers via Capabilities public abstract class MapLayerMessageBase { /// @@ -2246,7 +2246,7 @@ namespace OpenMetaverse.Messages.Linden /// A message sent from the simulator to the viewer which contains an array of map images and their grid coordinates /// public class MapLayerReplyVariant : MapLayerMessageBase - { + { /// /// An object containing map location details /// @@ -2896,7 +2896,7 @@ namespace OpenMetaverse.Messages.Linden this.ParcelLocalID = map["parcel_local_id"].AsInteger(); this.RegionName = map["region_name"].AsString(); OSDMap voiceMap = (OSDMap)map["voice_credentials"]; - this.ChannelUri = voiceMap["channel_uri"].AsString(); + this.ChannelUri = voiceMap["channel_uri"].AsString(); } #endregion @@ -3675,4 +3675,296 @@ namespace OpenMetaverse.Messages.Linden } #endregion + + #region Object Media Messages + /// + /// A message sent from the viewer to the simulator which + /// specifies that the user has changed current URL + /// of the specific media on a prim face + /// + public class ObjectMediaNavigateMessage : IMessage + { + /// + /// New URL + /// + public string URL; + + /// + /// Prim UUID where navigation occured + /// + public UUID PrimID; + + /// + /// Face index + /// + public int Face; + /// + /// Serialize the object + /// + /// An containing the objects data + public OSDMap Serialize() + { + OSDMap map = new OSDMap(3); + + map["current_url"] = OSD.FromString(URL); + map["object_id"] = OSD.FromUUID(PrimID); + map["texture_index"] = OSD.FromInteger(Face); + + return map; + } + + /// + /// Deserialize the message + /// + /// An containing the data + public void Deserialize(OSDMap map) + { + URL = map["current_url"].AsString(); + PrimID = map["object_id"].AsUUID(); + Face = map["texture_index"].AsInteger(); + } + } + + + /// Base class used for the ObjectMedia message + [Serializable] + public abstract class ObjectMediaBlock + { + public abstract OSDMap Serialize(); + public abstract void Deserialize(OSDMap map); + } + + /// + /// Message used to retrive prim media data + /// + public class ObjectMediaRequest : ObjectMediaBlock + { + /// + /// Prim UUID + /// + public UUID PrimID; + + /// + /// Requested operation, either GET or UPDATE + /// + public string Verb = "GET"; // "GET" or "UPDATE" + + /// + /// Serialize object + /// + /// Serialized object as OSDMap + public override OSDMap Serialize() + { + OSDMap map = new OSDMap(2); + map["object_id"] = OSD.FromUUID(PrimID); + map["verb"] = OSD.FromString(Verb); + return map; + } + + /// + /// Deserialize the message + /// + /// An containing the data + public override void Deserialize(OSDMap map) + { + PrimID = map["object_id"].AsUUID(); + Verb = map["verb"].AsString(); + } + } + + + /// + /// Message used to update prim media data + /// + public class ObjectMediaResponse : ObjectMediaBlock + { + /// + /// Prim UUID + /// + public UUID PrimID; + + /// + /// Array of media entries indexed by face number + /// + public MediaEntry[] FaceMedia; + + /// + /// Media version string + /// + public string Version; // String in this format: x-mv:0000000016/00000000-0000-0000-0000-000000000000 + + /// + /// Serialize object + /// + /// Serialized object as OSDMap + public override OSDMap Serialize() + { + OSDMap map = new OSDMap(2); + map["object_id"] = OSD.FromUUID(PrimID); + + if (FaceMedia == null) + { + map["object_media_data"] = new OSDArray(); + } + else + { + OSDArray mediaData = new OSDArray(FaceMedia.Length); + + for (int i = 0; i < FaceMedia.Length; i++) + { + mediaData[i] = FaceMedia[i].GetOSD(); + } + + map["object_media_data"] = mediaData; + } + + map["object_media_version"] = OSD.FromString(Version); + return map; + } + + /// + /// Deserialize the message + /// + /// An containing the data + public override void Deserialize(OSDMap map) + { + PrimID = map["object_id"].AsUUID(); + + if (map["object_media_data"].Type == OSDType.Array) + { + OSDArray mediaData = (OSDArray)map["object_media_data"]; + if (mediaData.Count > 0) + { + FaceMedia = new MediaEntry[mediaData.Count]; + for (int i = 0; i < mediaData.Count; i++) + { + if (mediaData[i].Type == OSDType.Map) + { + FaceMedia[i] = MediaEntry.FromOSD(mediaData[i]); + } + } + } + } + Version = map["object_media_version"].AsString(); + } + } + + + /// + /// Message used to update prim media data + /// + public class ObjectMediaUpdate : ObjectMediaBlock + { + /// + /// Prim UUID + /// + public UUID PrimID; + + /// + /// Array of media entries indexed by face number + /// + public MediaEntry[] FaceMedia; + + /// + /// Requested operation, either GET or UPDATE + /// + public string Verb = "UPDATE"; // "GET" or "UPDATE" + + /// + /// Serialize object + /// + /// Serialized object as OSDMap + public override OSDMap Serialize() + { + OSDMap map = new OSDMap(2); + map["object_id"] = OSD.FromUUID(PrimID); + + if (FaceMedia == null) + { + map["object_media_data"] = new OSDArray(); + } + else + { + OSDArray mediaData = new OSDArray(FaceMedia.Length); + + for (int i = 0; i < FaceMedia.Length; i++) + { + mediaData[i] = FaceMedia[i].GetOSD(); + } + + map["object_media_data"] = mediaData; + } + + map["verb"] = OSD.FromString(Verb); + return map; + } + + /// + /// Deserialize the message + /// + /// An containing the data + public override void Deserialize(OSDMap map) + { + PrimID = map["object_id"].AsUUID(); + + if (map["object_media_data"].Type == OSDType.Array) + { + OSDArray mediaData = (OSDArray)map["object_media_data"]; + if (mediaData.Count > 0) + { + FaceMedia = new MediaEntry[mediaData.Count]; + for (int i = 0; i < mediaData.Count; i++) + { + if (mediaData[i].Type == OSDType.Map) + { + FaceMedia[i] = MediaEntry.FromOSD(mediaData[i]); + } + } + } + } + Verb = map["verb"].AsString(); + } + } + + /// + /// Message for setting or getting per face MediaEntry + /// + [Serializable] + public class ObjectMediaMessage : IMessage + { + /// The request or response details block + public ObjectMediaBlock Request; + + /// + /// Serialize the object + /// + /// An containing the objects data + public OSDMap Serialize() + { + return Request.Serialize(); + } + + /// + /// Deserialize the message + /// + /// An containing the data + public void Deserialize(OSDMap map) + { + if (map.ContainsKey("verb")) + { + if (map["verb"].AsString() == "GET") + Request = new ObjectMediaRequest(); + else if (map["verb"].AsString() == "UPDATE") + Request = new ObjectMediaUpdate(); + } + else if (map.ContainsKey("object_media_version")) + Request = new ObjectMediaResponse(); + else + Logger.Log("Unable to deserialize ObjectMedia: No message handler exists for method: " + map.AsString(), Helpers.LogLevel.Warning); + + if (Request != null) + Request.Deserialize(map); + } + } + #endregion Object Media Messages } diff --git a/OpenMetaverse/Messages/MessageEventDecoder.cs b/OpenMetaverse/Messages/MessageEventDecoder.cs index 033e7692..7dfdb38e 100644 --- a/OpenMetaverse/Messages/MessageEventDecoder.cs +++ b/OpenMetaverse/Messages/MessageEventDecoder.cs @@ -88,6 +88,8 @@ namespace OpenMetaverse.Messages case "UploadBakedTexture": message = new UploadBakedTextureMessage(); break; case "WebFetchInventoryDescendents": message = new WebFetchInventoryDescendentsMessage(); break; case "RegionInfo": message = new RegionInfoMessage(); break; + case "ObjectMediaNavigate": message = new ObjectMediaNavigateMessage(); break; + case "ObjectMedia": message = new ObjectMediaMessage(); break; //case "ProductInfoRequest": message = new ProductInfoRequestMessage(); break; // Capabilities TODO: diff --git a/OpenMetaverse/PacketDecoder.cs b/OpenMetaverse/PacketDecoder.cs index cafbffbf..96b665d4 100644 --- a/OpenMetaverse/PacketDecoder.cs +++ b/OpenMetaverse/PacketDecoder.cs @@ -43,8 +43,8 @@ namespace OpenMetaverse.Packets public delegate string CustomPacketDecoder(string fieldName, object fieldData); private static Dictionary> Callbacks = new Dictionary>(); - - + + static PacketDecoder() { AddCallback("Color", DecodeColorField); @@ -66,7 +66,7 @@ namespace OpenMetaverse.Packets AddCallback("EveryoneMask", DecodePermissionMask); AddCallback("NextOwnerMask", DecodePermissionMask); AddCallback("GroupMask", DecodePermissionMask); - + // FetchInventoryDescendents AddCallback("InventoryData.SortOrder", DecodeInventorySort); @@ -78,7 +78,7 @@ namespace OpenMetaverse.Packets // BulkUpdateInventory AddCallback("ItemData.Type", DecodeInventoryType); AddCallback("ItemData.Flags", DecodeInventoryFlags); - + AddCallback("SaleType", DecodeObjectSaleType); AddCallback("ScriptControlChange.Data.Controls", DecodeScriptControls); @@ -105,7 +105,7 @@ namespace OpenMetaverse.Packets AddCallback("TextureAnim", DecodeObjectTextureAnim); AddCallback("ObjectUpdate.ObjectData.NameValue", DecodeNameValue); AddCallback("ObjectUpdate.ObjectData.Data", DecodeObjectData); - + AddCallback("ObjectUpdate.ObjectData.PSBlock", DecodeObjectParticleSystem); AddCallback("ParticleSys", DecodeObjectParticleSystem); AddCallback("ObjectUpdate.ObjectData.ExtraParams", DecodeObjectExtraParams); @@ -119,7 +119,7 @@ namespace OpenMetaverse.Packets AddCallback("ObjectData.State", DecodeObjectState); //AddCallback("ObjectUpdateCompressed.ObjectData.State", DecodeObjectState); //AddCallback("ImprovedTerseObjectUpdate.ObjectData.State", DecodeObjectState); - + // ChatFromSimulator AddCallback("ChatData.SourceType", DecodeChatSourceType); @@ -208,9 +208,9 @@ namespace OpenMetaverse.Packets private static string DecodeTerseUpdate(string fieldName, object fieldData) { - byte[] block = (byte[]) fieldData; + byte[] block = (byte[])fieldData; int i = 4; - + StringBuilder result = new StringBuilder(); // LocalID @@ -219,8 +219,8 @@ namespace OpenMetaverse.Packets Utils.BytesToUInt(block, 0), "Uint32"); - - + + // State byte point = block[i++]; result.AppendFormat("{0,30}: {1,-3} {2,-36} [{3}]" + Environment.NewLine, @@ -235,7 +235,7 @@ namespace OpenMetaverse.Packets "IsAvatar", isAvatar, "Boolean"); - + // Collision normal for avatar if (isAvatar) { @@ -243,7 +243,7 @@ namespace OpenMetaverse.Packets "CollisionPlane", new Vector4(block, i), "Vector4"); - + i += 16; } @@ -571,7 +571,7 @@ namespace OpenMetaverse.Packets "PathScaleY", Primitive.UnpackPathScale(block[i++]), "float"); - + result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine, "PathShearX", Primitive.UnpackPathShear((sbyte)block[i++]), @@ -699,7 +699,7 @@ namespace OpenMetaverse.Packets return result.ToString(); } - + private static string DecodeEstateParameter(string fieldName, object fieldData) { byte[] bytes = (byte[])fieldData; @@ -838,9 +838,9 @@ namespace OpenMetaverse.Packets } else { - result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine, + result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine, field.Name, - field.GetValue(obj), + field.GetValue(obj), field.FieldType.Name); } } @@ -917,7 +917,7 @@ namespace OpenMetaverse.Packets fieldData, "(" + (DirectoryManager.ClassifiedFlags)(byte)fieldData + ")"); } - + private static string DecodeGroupPowers(string fieldName, object fieldData) { return String.Format("{0,30}: {1,-20} {2,-19} [GroupPowers]", @@ -933,7 +933,7 @@ namespace OpenMetaverse.Packets fieldData, "(" + (AccessList)(uint)fieldData + ")"); } - + private static string SearchTypeFlags(string fieldName, object fieldData) { return String.Format("{0,30}: {1,-10} {2,-29} [DirectoryManager.SearchTypeFlags]", @@ -1208,7 +1208,7 @@ namespace OpenMetaverse.Packets fieldData, "(" + (TerrainPatch.LayerType)(byte)fieldData + ")"); } - + private static string DecodeMapAccess(string fieldName, object fieldData) { return String.Format("{0,30}: {1,-2} {2,-37} [SimAccess]", @@ -1267,7 +1267,7 @@ namespace OpenMetaverse.Packets private static string DecodeTerseTextureEntry(string fieldName, object fieldData) { - byte[] block = (byte[]) fieldData; + byte[] block = (byte[])fieldData; Primitive.TextureEntry te = new Primitive.TextureEntry(block, 4, block.Length - 4); @@ -1437,7 +1437,7 @@ namespace OpenMetaverse.Packets return String.Format("{0,30}: (No Decoder) Length={1}" + Environment.NewLine, fieldName, data.Length) + Utils.BytesToHexString(data, String.Format("{0,30}", "")); } } - + private static string DecodeAgentState(string fieldName, object fieldData) { return String.Format("{0,30}: {1,-2} {2,-37} [AgentState]", @@ -1445,7 +1445,7 @@ namespace OpenMetaverse.Packets fieldData, "(" + (AgentState)(byte)fieldData + ")"); } - + private static string DecodeAgentFlags(string fieldName, object fieldData) { return String.Format("{0,30}: {1,-2} {2,-37} [AgentFlags]", @@ -1523,7 +1523,7 @@ namespace OpenMetaverse.Packets } return result.ToString(); } - + public static string InterpretOptions(Header header) { return "[" @@ -1614,15 +1614,15 @@ namespace OpenMetaverse.Packets else if (packetValueField.FieldType.IsArray) { result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine, - packetValueField.Name, - Utils.BytesToString((byte[])packetValueField.GetValue(packetDataObject)), - /*packetValueField.FieldType.Name*/ "String"); + packetValueField.Name, + Utils.BytesToString((byte[])packetValueField.GetValue(packetDataObject)), + /*packetValueField.FieldType.Name*/ "String"); } else { result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine, packetValueField.Name, packetValueField.GetValue(packetDataObject), packetValueField.FieldType.Name); - + } } @@ -1736,8 +1736,15 @@ namespace OpenMetaverse.Packets result.AppendFormat("-- {0} --" + Environment.NewLine, messageField.FieldType.Name); foreach (object nestedArrayObject in messageObjectData as Array) { - result.AppendFormat("{0,30}" + Environment.NewLine, "-- " + nestedArrayObject.GetType().Name + " --"); - + if (nestedArrayObject == null) + { + result.AppendFormat("{0,30}" + Environment.NewLine, "-- null --"); + continue; + } + else + { + result.AppendFormat("{0,30}" + Environment.NewLine, "-- " + nestedArrayObject.GetType().Name + " --"); + } foreach (FieldInfo nestedField in nestedArrayObject.GetType().GetFields()) { if (nestedField.FieldType.IsEnum) @@ -1758,7 +1765,7 @@ namespace OpenMetaverse.Packets result.AppendFormat("{0, 30}: {1,-40} [{2}]" + Environment.NewLine, nestedField.Name, nestedField.GetValue(nestedArrayObject), - nestedField.GetValue(nestedArrayObject).GetType().Name); + nestedField.FieldType.Name); } } } diff --git a/OpenMetaverse/Primitives/ObjectMedia.cs b/OpenMetaverse/Primitives/ObjectMedia.cs new file mode 100644 index 00000000..3c520a10 --- /dev/null +++ b/OpenMetaverse/Primitives/ObjectMedia.cs @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2007-2010, openmetaverse.org + * All rights reserved. + * + * - Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * - Neither the name of the openmetaverse.org nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using OpenMetaverse.StructuredData; + +namespace OpenMetaverse +{ + #region enums + /// + /// Permissions for control of object media + /// + public enum MediaPermission : byte + { + None = 0, + Owner = 1, + Group = 2, + Anyone = 4, + All = None | Owner | Group | Anyone + } + + /// + /// Style of cotrols that shold be displayed to the user + /// + public enum MediaControls + { + Standard = 0, + Mini + } + #endregion enums + + public class MediaEntry + { + /// Is display of the alternative image enabled + public bool EnableAlterntiveImage; + + /// Should media auto loop + public bool AutoLoop; + + /// Shoule media be auto played + public bool AutoPlay; + + /// Auto scale media to prim face + public bool AutoScale; + + /// Should viewer automatically zoom in on the face when clicked + public bool AutoZoom; + + /// Should viewer interpret first click as interaction with the media + /// or when false should the first click be treated as zoom in commadn + public bool InteractOnFirstClick; + + /// Style of controls viewer should display when + /// viewer media on this face + public MediaControls Controls; + + /// Starting URL for the media + public string HomeURL; + + /// Currently navigated URL + public string CurrentURL; + + /// Media height in pixes + public int Height; + + /// Media width in pixels + public int Width; + + /// Who can controls the media + public MediaPermission ControlPermissions; + + /// Who can interact with the media + public MediaPermission InteractPermissions; + + /// Is URL whitelist enabled + public bool EnableWhiteList; + + /// Array of URLs that are whitelisted + public string[] WhiteList; + + public OSDMap GetOSD() + { + OSDMap map = new OSDMap(); + + map["alt_image_enable"] = OSD.FromBoolean(EnableAlterntiveImage); + map["auto_loop"] = OSD.FromBoolean(AutoLoop); + map["auto_play"] = OSD.FromBoolean(AutoPlay); + map["auto_scale"] = OSD.FromBoolean(AutoScale); + map["auto_zoom"] = OSD.FromBoolean(AutoZoom); + map["controls"] = OSD.FromInteger((int)Controls); + map["current_url"] = OSD.FromString(CurrentURL); + map["first_click_interact"] = OSD.FromBoolean(InteractOnFirstClick); + map["height_pixels"] = OSD.FromInteger(Height); + map["home_url"] = OSD.FromString(HomeURL); + map["perms_control"] = OSD.FromInteger((int)ControlPermissions); + map["perms_interact"] = OSD.FromInteger((int)InteractPermissions); + + List wl = new List(); + if (WhiteList != null && WhiteList.Length > 0) + { + for (int i = 0; i < WhiteList.Length; i++) + wl.Add(OSD.FromString(WhiteList[i])); + } + + map["whitelist"] = new OSDArray(wl); + map["whitelist_enable"] = OSD.FromBoolean(EnableWhiteList); + map["width_pixels"] = OSD.FromInteger(Width); + + return map; + } + + public static MediaEntry FromOSD(OSD osd) + { + MediaEntry m = new MediaEntry(); + OSDMap map = (OSDMap)osd; + + m.EnableAlterntiveImage = map["alt_image_enable"].AsBoolean(); + m.AutoLoop = map["auto_loop"].AsBoolean(); + m.AutoPlay = map["auto_play"].AsBoolean(); + m.AutoScale = map["auto_scale"].AsBoolean(); + m.AutoZoom = map["auto_zoom"].AsBoolean(); + m.Controls = (MediaControls)map["controls"].AsInteger(); + m.CurrentURL = map["current_url"].AsString(); + m.InteractOnFirstClick = map["first_click_interact"].AsBoolean(); + m.Height = map["height_pixels"].AsInteger(); + m.HomeURL = map["home_url"].AsString(); + m.ControlPermissions = (MediaPermission)map["perms_control"].AsInteger(); + m.InteractPermissions = (MediaPermission)map["perms_interact"].AsInteger(); + + if (map["whitelist"].Type == OSDType.Array) + { + OSDArray wl = (OSDArray)map["whitelist"]; + if (wl.Count > 0) + { + m.WhiteList = new string[wl.Count]; + for (int i = 0; i < wl.Count; i++) + { + m.WhiteList[i] = wl[i].AsString(); + } + } + } + + m.EnableWhiteList = map["whitelist_enable"].AsBoolean(); + m.Width = map["width_pixels"].AsInteger(); + + + return m; + } + } +}