/// <summary> /// This creates a new DvMediaItem instance that refers /// to this instance, by simply specifying the intended ID. /// Generally, public programmers should use the /// <see cref="DvMediaContainer.AddReference"/> method /// to prevent object ID collisions. /// </summary> /// <returns>a new DvMediaItem instance that refers to this instance</returns> /// <exception cref="Error_PendingDeleteException"> /// Thrown if this item is marked for deletion. Cannot create a reference /// to an item that is pending removal from the content hierarchy. /// </exception> public IDvItem CreateReference(string id) { lock (this.m_LockReferences) { if (this.m_Deleting == false) { DvMediaItem newItem = new DvMediaItem(); newItem.m_ID = id; newItem.m_RefItem = this; if (m_ReferringItems == null) { this.m_ReferringItems = new ArrayList(1); } //this.m_ReferringItems.Add(new WeakReference(newItem)); this.m_ReferringItems.Add(newItem); // Set the remaining the base metadata by using values // from the underlying item. // newItem.m_Restricted = this.m_Restricted; newItem.SetClass(this.Class.ToString(), this.Class.FriendlyName); newItem.Title = this.Title; return(newItem); } else { throw new Error_PendingDeleteException(this); } } }
/// <summary> /// Creates a /// <see cref="DvMediaItem"/> /// object, given a metadata instantiation /// block. /// </summary> /// <param name="info"> /// The metadata to use when instantiating the media. /// </param> /// <returns>a new media item</returns> public static DvMediaItem CreateItem(MediaBuilder.item info) { DvMediaItem newObj = new DvMediaItem(); MediaBuilder.SetObjectProperties(newObj, info); newObj.TrackMetadataChanges = true; return(newObj); }
public DvMediaReference AddDvMediaReference(DvMediaItem underlyingItem) { underlyingItem.LockReferenceList(); DvMediaReference newItem = underlyingItem.CreateDvMediaReference(); this.AddObject(newItem, false); underlyingItem.UnlockReferenceList(); return(newItem); }
private static void EnableMetadataTracking(IDvMedia dvm) { DvMediaContainer dvc = dvm as DvMediaContainer; DvMediaItem dvi = dvm as DvMediaItem; if (dvc != null) { dvc.TrackMetadataChanges = true; foreach (IDvMedia child in dvc.CompleteList) { EnableMetadataTracking(child); } } else if (dvi != null) { dvi.TrackMetadataChanges = true; } }
/// <summary> /// This method should only be used when deserializing a media items. /// /// <para> /// A media item can point to another media item. The item doing the pointing /// is called the reference item. The item that is being pointed to is the /// underlying item. /// </para> /// /// <para> /// The standard binary serialization process destroys the object reference /// between a reference item and its underlying item. This method provides a means /// to restore the reference relationship. /// </para> /// </summary> /// <param name="underlyingItem"> /// The media item that is being referred. /// </param> /// <param name="refItem"> /// The media item that is doing the referring. /// </param> public static void AttachRefItem(DvMediaItem underlyingItem, DvMediaItem refItem) { underlyingItem.LockReferenceList(); if (underlyingItem.m_ReferringItems == null) { underlyingItem.m_ReferringItems = new ArrayList(); } //underlyingItem.m_ReferringItems.Add(new WeakReference(refItem)); underlyingItem.m_ReferringItems.Add(refItem); // Just to avoid confusion - a refitem is actually an underlying item. // The naming convention follows the AV spec - the spec opted to use // "refID" notation instead of using "underlyingItem"... refItem.m_RefItem = underlyingItem; refItem.m_RefID = ""; underlyingItem.UnlockReferenceList(); }
/// <summary> /// This creates a new DvMediaItem instance that refers /// to this instance, by simply specifying the intended ID. /// Generally, public programmers should use the /// <see cref="DvMediaContainer.AddReference"/> method /// to prevent object ID collisions. /// </summary> /// <returns>a new DvMediaItem instance that refers to this instance</returns> /// <exception cref="Error_PendingDeleteException"> /// Thrown if this item is marked for deletion. Cannot create a reference /// to an item that is pending removal from the content hierarchy. /// </exception> public IDvItem CreateReference(string id) { lock(this.m_LockReferences) { if (this.m_Deleting == false) { DvMediaItem newItem = new DvMediaItem(); newItem.m_ID = id; newItem.m_RefItem = this; if (m_ReferringItems == null) { this.m_ReferringItems = new ArrayList(1); } //this.m_ReferringItems.Add(new WeakReference(newItem)); this.m_ReferringItems.Add(newItem); // Set the remaining the base metadata by using values // from the underlying item. // newItem.m_Restricted = this.m_Restricted; newItem.SetClass(this.Class.ToString(), this.Class.FriendlyName); newItem.Title = this.Title; return newItem; } else { throw new Error_PendingDeleteException(this); } } }
public DvMediaReference(DvMediaItem underlyingItem) { m_uniqueId = MediaBuilder.GetUniqueId(); this.m_Underlying = underlyingItem; }
/// <summary> /// Method executes when a control point invokes the ContentDirectory.UpdateObject action. /// The caller must specify the object to be modified, the old XML values to replace, /// and the new XML values to use. /// </summary> /// <param name="objectID">update media object with this ID</param> /// <param name="currentTagValue"> /// Comma separated value list of current XML elements in the object. /// Empty value or double comma indicates that a new XML element is to be created. /// CDS spec defines that the text of the XML elements must match /// exactly with the text provided by the server. This means /// XML attributes have to be in the correct order within the XML element. /// XML elements need not be in any particular order though.. just the /// text between the commas separating things need to be that way. /// The order of XML elements correspond with the order of replacement /// XML elements. /// </param> /// <param name="newTagValue"> /// Comma separated value list of new/replace XML elements in the object. /// Empty value or double comma indicates that an existing XML element is to be deleted. /// The order of XML elements correspond with the order of current /// XML elements. /// </param> private void SinkCd_UpdateObject(System.String objectID, System.String currentTagValue, System.String newTagValue) { try { // Ensure that the specified object actually exists IDvMedia obj = (IDvMedia) this.GetCdsEntry(objectID); if (obj == null) { throw new Error_NoSuchObject("("+objectID+")"); } else if (obj.IsReference) { throw new UPnPCustomException(830, "This server will not allow UpdateObject() on a reference."); } // Set up text parsers. DText currentTagParser = new DText(); DText newTagParser = new DText(); currentTagParser.ATTRMARK = ","; newTagParser.ATTRMARK = ","; currentTagParser[0] = currentTagValue; newTagParser[0] = newTagValue; // ensure that the number of old xml values is equal // to the number of new values // BUG - Need to fix a case where the XML values include commas. int nFrags = currentTagParser.DCOUNT(); int nFrags2 = newTagParser.DCOUNT(); if (nFrags != nFrags2) { throw new Error_ParameterMismatch("The number of tag/value pairs is not the same between currentTagValue and newTagValue."); } // determine the base URL using the IP address and port // where the request came in from and then // build an DIDL-Lite representation of the // object that needs updating //TODO: get all interfaces string baseUrl = this.GetBaseUrlByInterface(); ArrayList properties = new ArrayList(); ArrayList entries = new ArrayList(); entries.Add(obj); string oldXml; try { oldXml = BuildXmlRepresentation(baseUrl, properties, entries); } catch (Exception e) { throw (e); } // At this point oldXml represents the object we're trying to // update, in an xml string format. Now go and replace (or add) all // of the text values appropriately. // string newXml = oldXml; for (int i=1; i <= nFrags; i++) { // grab the old and new value XML fragments string oldFrag = currentTagParser[i].Trim(); string newFrag = newTagParser[i].Trim(); if ( ((oldFrag.StartsWith("<") == false) || (oldFrag.EndsWith(">") == false)) && (oldFrag != "") ) { throw new Error_InvalidCurrentTagValue("Invalid args. (" + oldFrag + ") is not an xml element."); } int pos = newXml.IndexOf(oldFrag); if ((oldFrag != "") && (pos < 0)) { throw new Error_InvalidCurrentTagValue("Cannot find xml element (" +oldFrag+ ")."); } if (oldFrag == "") { // The old value XML fragment indicates that a completely // new XML element needs to be added. if (obj.IsContainer) { StringBuilder newVal = new StringBuilder(newFrag.Length + 10); newVal.AppendFormat("{0}</container>"); newXml = newXml.Replace("</container>", newVal.ToString()); } else { StringBuilder newVal = new StringBuilder(newFrag.Length + 10); newVal.AppendFormat("{0}</item>", newFrag); newXml = newXml.Replace("</item>", newVal.ToString()); } } else { // The new value XML fragment indicates that a current // XML fragment must be deleted. if (newFrag == "") { newXml = newXml.Replace(oldFrag, ""); } else { newXml = newXml.Replace(oldFrag, newFrag); } } } // At this point newXml represents what the proposed object should // look like with new changes. We'll continue by casting the // string into an xmldocument and instantiating a new IDvMedia // instance, making sure to keep the ID specified within the newXml. // // Cast the string into an XmlDocument so that we can instantiate // a media object using an XmlElement object. XmlDocument xmldoc = new XmlDocument(); xmldoc.LoadXml(newXml); XmlNodeList didlheader = xmldoc.GetElementsByTagName(T[_DIDL.DIDL_Lite]); XmlNode didlRoot = didlheader[0]; XmlElement xmlElement = (XmlElement) didlRoot.ChildNodes[0]; IDvMedia newObj; if (obj.IsContainer) { newObj = new DvMediaContainer(xmlElement); } else { newObj = new DvMediaItem(xmlElement); } // Iterate through the resources of the new object // and ensure that resources that carried over // from the original object's metadata are // properly mapped in the new object's list. // This way, upper software layers cannot effectively // tell the difference if a comparison-by-value is done. foreach (IMediaResource newRes in newObj.Resources) { string uri = newRes.ContentUri; int pos = uri.IndexOf(this.m_VirtualDirName); if (pos > 0) { // ensure that contentUri and importUri values don't violate automapping rule string subUri = uri.Substring(pos + this.m_VirtualDirName.Length); DText DirectiveParser = new DText(); DirectiveParser.ATTRMARK = "/"; DirectiveParser[0] = subUri; string resourceID = DirectiveParser[2]; string objID = DirectiveParser[3]; System.Diagnostics.Debug.Assert(objID == objectID); IDvResource res = this.GetResource(objectID, resourceID); newRes[T[_RESATTRIB.importUri]] = null; newRes.ContentUri = res.ContentUri; } } // Request upper software components to accept/reject // request to change metadata. The delegate should // throw an exception (preferably UPnPCustomExeption) // to indicate a rejection. if (this.OnRequestChangeMetadata != null) { this.OnRequestChangeMetadata (this, obj, newObj); } // If no rejection, then use the metadata of the new object // and apply it to the existing object. obj.UpdateObject(newObj); } catch (Exception e) { Exception ne = new Exception("MediaServer.SinkCd_UpdateObject()", e); throw ne; } this.m_Stats.UpdateObject++; this.FireStatsChange(); }
/// <summary> /// Creates a /// <see cref="DvMediaItem"/> /// object, given a metadata instantiation /// block. /// </summary> /// <param name="info"> /// The metadata to use when instantiating the media. /// </param> /// <returns>a new media item</returns> public static DvMediaItem CreateItem(MediaBuilder.item info) { DvMediaItem newObj = new DvMediaItem(); MediaBuilder.SetObjectProperties(newObj, info); newObj.TrackMetadataChanges = true; return newObj; }
public DvMediaReference AddDvMediaReference(DvMediaItem underlyingItem) { underlyingItem.LockReferenceList(); DvMediaReference newItem = underlyingItem.CreateDvMediaReference(); this.AddObject(newItem, false); underlyingItem.UnlockReferenceList(); return newItem; }