/// <summary> /// Makes a request to a remote media server to import the binary file from a URI to /// a resource that is part of the server's content hierarchy. /// </summary> /// <param name="sourceUri">the URI where binary should be pulled</param> /// <param name="importHere">the <see cref="ICpResource"/> object that represents the /// destination of the imported binary /// </param> /// <param name="Tag"> /// Miscellaneous, user-provided object for tracking this /// asynchronous call. Can be used as a means to pass a /// user-defined "state object" at invoke-time so that /// the executed callback during results-processing can be /// aware of the component's state at the time of the call. /// </param> /// <param name="callback">the callback to execute when results become available</param> /// <exception cref="Error_ResourceNotOnServer"> /// Thrown when attempting to delete a resource object that /// is not part of the server's content hierarchy. /// </exception> /// <exception cref="NullReferenceException"> /// Thrown when attempting a remove a resource that has /// a null/empty value for its contentUri. /// </exception> /// <exception cref="Error_CannotGetParent"> /// Thrown if the parent of this object is null. /// </exception> /// <exception cref="InvalidCastException"> /// Thrown if the parent of this object is not a <see cref="CpMediaContainer"/>. /// </exception> public void RequestImportResource(System.Uri sourceUri, ICpResource importHere, object Tag, CpMediaDelegates.Delegate_ResultImportResource callback) { // calls parent's implementation of method CpMediaContainer parent = (CpMediaContainer)this.Parent; parent.RequestImportResource(sourceUri, importHere, Tag, callback); }
/// <summary> /// Requests a remote media server to delete a resource from its local file system. /// </summary> /// <param name="deleteThisResource">the resource to request for deletion</param> /// <param name="Tag"> /// Miscellaneous, user-provided object for tracking this /// asynchronous call. Can be used as a means to pass a /// user-defined "state object" at invoke-time so that /// the executed callback during results-processing can be /// aware of the component's state at the time of the call. /// </param> /// <param name="callback">callback to execute when results have been obtained</param> /// <exception cref="Error_ResourceNotOnServer"> /// Thrown when attempting to delete a resource object that /// is not part of the server's content hierarchy. /// </exception> /// <exception cref="NullReferenceException"> /// Thrown when attempting a remove a resource that has /// a null/empty value for its contentUri. /// </exception> /// <exception cref="Error_CannotGetParent"> /// Thrown if the parent of this object is null. /// </exception> /// <exception cref="InvalidCastException"> /// Thrown if the parent of this object is not a <see cref="CpMediaContainer"/>. /// </exception> public void RequestDeleteResource(ICpResource deleteThisResource, object Tag, CpMediaDelegates.Delegate_ResultDeleteResource callback) { // calls parent's implementation of method CpMediaContainer parent = (CpMediaContainer)this.Parent; parent.RequestDeleteResource(deleteThisResource, Tag, callback); }
/// <summary> /// Creates a /// <see cref="CpMediaContainer"/> /// object, given a metadata instantiation /// block. /// </summary> /// <param name="info"> /// The metadata to use when instantiating the media. /// </param> /// <returns>a new media container</returns> public static CpMediaContainer CreateContainer(MediaBuilder.container info) { CpMediaContainer newObj = new CpMediaContainer(); MediaBuilder.SetObjectProperties(newObj, info); return(newObj); }
/// <summary> /// <see cref="CpMediaContainer"/> objects /// use this method to event changes in their state. This /// method simply fires the /// <see cref="CpRootContainer.OnContainerChanged"/> /// event. /// </summary> /// <param name="thisChanged"><see cref="CpMediaContainer"/> that observed the change.</param> internal void FireOnContainerChanged(CpMediaContainer thisChanged) { if (this.OnContainerChanged != null) { this.OnContainerChanged(this, thisChanged); } }
/// <summary> /// Makes a request to a remote media server to export one of its binary files /// to another location. /// </summary> /// <param name="exportThis"> /// The resource (of this media object) that should be exported. /// </param> /// <param name="sendHere"> /// The uri where the binary should be sent. /// </param> /// <param name="Tag"> /// Miscellaneous, user-provided object for tracking this /// asynchronous call. Can be used as a means to pass a /// user-defined "state object" at invoke-time so that /// the executed callback during results-processing can be /// aware of the component's state at the time of the call. /// </param> /// <param name="callback">the callback to execute when results become available</param> /// <exception cref="Error_CannotGetParent"> /// Thrown if the parent of this object is null. /// </exception> public void RequestExportResource(ICpResource exportThis, System.Uri sendHere, object Tag, CpMediaDelegates.Delegate_ResultExportResource callback) { // calls parent's implementation of method CpMediaContainer parent = (CpMediaContainer)this.Parent; parent.RequestExportResource(exportThis, sendHere, Tag, callback); }
/// <summary> /// <see cref="CpMediaContainer.NotifySpidersRemove"/> calls this /// method to indicate that child objects have been removed /// from the container. /// </summary> /// <param name="thisChanged">the container that witnessed the change</param> /// <param name="removeThese">an ArrayList of STRONG REFERENCES to <see cref="ICpMedia"/> objects</param> internal void NotifySinkRemove(CpMediaContainer thisChanged, ArrayList removeThese) { ArrayList removedObjects = new ArrayList(removeThese.Count); lock (this.m_Matches.SyncRoot) { foreach (ICpMedia obj in this.m_Matches) { if (removeThese.Contains(obj)) { removedObjects.Add(obj); } } foreach (ICpMedia obj in removedObjects) { this.m_Matches.Remove(obj); } } if (removedObjects.Count > 0) { if (this.OnMatchesRemoved != null) { this.OnMatchesRemoved(this, removedObjects); } } }
/// <summary> /// Calls the parent object's implementation of <see cref="CpMediaContainer.CheckRuntimeBindings"/>. /// </summary> /// <param name="st">stack trace object, created in the method that desires runtime checking</param> public override void CheckRuntimeBindings(StackTrace st) { if (this.Parent != null) { CpMediaContainer parent = (CpMediaContainer)this.Parent; parent.CheckRuntimeBindings(st); } }
internal void NotifySinkBrowsingError(CpMediaContainer thisChanged, Exception e) { if (thisChanged == this.m_MonitorThis) { this.m_BrowsingError = e; if (this.OnUpdateDone != null) { this.OnUpdateDone(this, null); } } }
/// <summary> /// This method will invoke a CDS browse request and provide the results /// directly the application-caller. /// <para> /// Implementation simply calls the parent owner's implementation of /// <see cref="CpMediaContainer.RequestBrowse "/>(ICpMedia, CpContentDirectory.Enum_A_ARG_TYPE_BrowseFlag, string, uint, uint, string). /// </para> /// </summary> /// <param name="BrowseFlag">browse metadata or direct children</param> /// <param name="Filter"> /// Comma-separated value list of metadata names to include /// in the response. For all metadata, use * character. /// </param> /// <param name="StartingIndex"> /// If obtaining children, the start index of the results. /// Otherwise set to zero. /// </param> /// <param name="RequestedCount"> /// If obtaining children the max number of child objects /// to retrieve. Otherwise use zero. /// </param> /// <param name="SortCriteria"> /// Comma-separated value list of metadata names to use for /// sorting, such that preceding each metadata name (but after /// the comma) a + or - character is present to indicate /// ascending or descending sort order for that property. /// </param> /// <param name="Tag"> /// Miscellaneous, user-provided object for tracking this /// asynchronous call. Can be used as a means to pass a /// user-defined "state object" at invoke-time so that /// the executed callback during results-processing can be /// aware of the component's state at the time of the call. /// </param> /// <param name="callback">the callback to execute when results become available</param> /// <exception cref="ApplicationException"> /// Thrown if the BrowseFlag value is BrowseDirectChildren because only the /// object's metadata can be obtained use browse. /// </exception> public void RequestBrowse(CpContentDirectory.Enum_A_ARG_TYPE_BrowseFlag BrowseFlag, string Filter, uint StartingIndex, uint RequestedCount, string SortCriteria, object Tag, CpMediaDelegates.Delegate_ResultBrowse callback) { if (BrowseFlag == CpContentDirectory.Enum_A_ARG_TYPE_BrowseFlag.BROWSEDIRECTCHILDREN) { throw new ApplicationException("BrowseFlag cannot be BROWSEDIRECTCHILDREN"); } CpMediaContainer parent = (CpMediaContainer)this.Parent; parent.RequestBrowse(this, BrowseFlag, Filter, StartingIndex, RequestedCount, SortCriteria, Tag, callback); }
/// <summary> /// Decrements the number of spiders that have indicated /// this item to be of interest to them. /// This method is called by CdsSpider to indicate /// that the spider is not interested in the container anymore. /// If no spiders are interested in the item, then /// the item is removed. /// </summary> internal void DecrementSpiderMatches() { System.Threading.Interlocked.Decrement(ref this.m_SpiderClients); if (this.m_SpiderClients == 0) { CpMediaContainer p = (CpMediaContainer)this.Parent; if (p != null) { p.RemoveObject(this); } } }
/// <summary> /// Method executes when a contentdirectory events a change in a container. /// </summary> /// <param name="sender"></param> /// <param name="NewValue"></param> private void Sink_OnContainerUpdateIDsChanged(CpContentDirectory sender, System.String NewValue) { string csv_containers = NewValue; Hashtable cache = new Hashtable(); DText parser = new DText(); DText parser2 = new DText(); parser.ATTRMARK = ","; parser2.ATTRMARK = ","; if (csv_containers != "") { parser[0] = csv_containers; int dcnt = parser.DCOUNT(); for (int i = 1; i <= dcnt; i++) { string id, update; if (Accumulator_ContainerUpdateIDs.Delimitor == ",") { id = parser[i++]; update = parser[i]; } else { string pair = parser[i]; parser2[0] = pair; id = parser2[1]; update = parser2[2]; } CpMediaContainer cpc = (CpMediaContainer)this.GetDescendent(id, cache); if (cpc != null) { try { UInt32 updateId = UInt32.Parse(update); if (updateId != cpc.UpdateID) { cpc.ForceUpdate(false); } } catch { cpc.ForceUpdate(false); } } } } cache.Clear(); }
/// <summary> /// Allows a programmer to request a remote mediaserver to change the metadata /// for this item. /// </summary> /// <param name="useThisMetadata"> /// Media object that represents what the new metadata should be for the object. /// </param> /// <param name="Tag"> /// Miscellaneous, user-provided object for tracking this /// asynchronous call. Can be used as a means to pass a /// user-defined "state object" at invoke-time so that /// the executed callback during results-processing can be /// aware of the component's state at the time of the call. /// </param> /// <param name="callback"> /// Delegate executes when the results for the method are available. /// </param> /// <exception cref="Error_CannotGetParent"> /// Thrown if the parent of this object is null. /// </exception> /// <exception cref="InvalidCastException"> /// Thrown if this object's parent is not a /// <see cref="CpMediaContainer"/> object. /// </exception> public void RequestUpdateObject(IUPnPMedia useThisMetadata, object Tag, CpMediaDelegates.Delegate_ResultUpdateObject callback) { CpMediaContainer p = (CpMediaContainer)this.Parent; if (p != null) { p.RequestUpdateObject(this, useThisMetadata, Tag, callback); } else { throw new Error_CannotGetParent(this); } }
/// <summary> /// Makes a request on the remote media server to delete this /// object from its parent. /// </summary> /// <param name="Tag"> /// Miscellaneous, user-provided object for tracking this /// asynchronous call. Can be used as a means to pass a /// user-defined "state object" at invoke-time so that /// the executed callback during results-processing can be /// aware of the component's state at the time of the call. /// </param> /// <param name="callback"> /// Delegate executes when the results for the method are available. /// </param> /// <exception cref="Error_CannotGetParent"> /// Thrown if the parent of this object is null. /// </exception> /// <exception cref="InvalidCastException"> /// Thrown if this object's parent is not a /// <see cref="CpMediaContainer"/> object. /// </exception> public void RequestDestroyObject(object Tag, CpMediaDelegates.Delegate_ResultDestroyObject callback) { CpMediaContainer p = (CpMediaContainer)this.Parent; if (p != null) { p.RequestDestroyObject(this, Tag, callback); } else { throw new Error_CannotGetParent(this); } }
/// <summary> /// Call this method if a spider is no longer interested in an object /// that was earlier marked as being of interest to this spider. /// </summary> /// <param name="obj"></param> private void DecrementMatch(ICpMedia obj) { CpMediaContainer cpc = obj as CpMediaContainer; CpMediaItem cpi = obj as CpMediaItem; if (cpc != null) { cpc.DecrementSpiderMatches(); } else if (cpi != null) { cpi.DecrementSpiderMatches(); } }
/// <summary> /// <see cref="CpMediaContainer.NotifySpidersAdd"/> calls this /// method to indicate that a container's contents have changed. /// Upon exiting this method, the /// CdsSpider acknowledges that the container has changed /// and that the container has no obligation to keep its /// references to child objects any longer. /// </summary> /// <param name="thisChanged">the container that has changed</param> /// <param name="addThese"> /// A reliable listing of new matches for the container's current state. /// Each element will be a strong reference to an <see cref="ICpMedia"/> object. /// Assume that the container has already filtered the results so that /// addThese only contains elements that match the comparer for this spider. /// </param> internal void NotifySinkAdd(CpMediaContainer thisChanged, ArrayList addThese) { bool eventAdded = false; lock (this.m_Matches.SyncRoot) { if (thisChanged == this.MonitorThis) { ExpectingResults = false; if (addThese.Count > 0) { if ((this.m_Matches.Count == 0)) { this.m_Matches = new ArrayList(addThese.Count); } if (this.m_Sorter != null) { // perform a sorted insert for each item _SortedList sortThese = new _SortedList(this.m_Sorter, true); foreach (ICpMedia obj in addThese) { sortThese.Set(this.m_Matches, obj, false); } } else { this.m_Matches.AddRange((ICollection)addThese); } eventAdded = true; } } } if (eventAdded) { if (this.OnMatchesAdded != null) { this.OnMatchesAdded(this, addThese); } } }
/// <summary> /// <see cref="CpMediaContainer.NotifySpidersOfGoneContainer"/> calls this /// method to indicate that the container the spider happens /// to be monitoring no longer exists. /// </summary> /// <param name="thisChanged"></param> internal void NotifySinkContainerGone(CpMediaContainer thisChanged) { lock (this.m_Matches.SyncRoot) { if (thisChanged == this.MonitorThis) { this.m_IsDead = true; if (this.OnContainerGone != null) { this.OnContainerGone(this, null); } if (this.MonitorThis == thisChanged) { this.MonitorThis = null; } } } }
/// <summary> /// <see cref="CpMediaContainer.NotifySpidersAdd"/> calls this /// method to indicate that a container's contents have changed. /// Upon exiting this method, the /// CdsSpider acknowledges that the container has changed /// and that the container has no obligation to keep its /// references to child objects any longer. /// </summary> /// <param name="thisChanged">the container that has changed</param> /// <param name="addThese"> /// A reliable listing of new matches for the container's current state. /// Each element will be a strong reference to an <see cref="ICpMedia"/> object. /// Assume that the container has already filtered the results so that /// addThese only contains elements that match the comparer for this spider. /// </param> internal void NotifySinkAdd(CpMediaContainer thisChanged, ArrayList addThese) { bool eventAdded = false; lock (this.m_Matches.SyncRoot) { if (thisChanged == this.MonitorThis) { ExpectingResults = false; if (addThese.Count > 0) { if ((this.m_Matches.Count == 0)) { this.m_Matches = new ArrayList(addThese.Count); } if (this.m_Sorter != null) { // perform a sorted insert for each item _SortedList sortThese = new _SortedList(this.m_Sorter, true); foreach (ICpMedia obj in addThese) { sortThese.Set(this.m_Matches, obj, false); } } else { this.m_Matches.AddRange((ICollection) addThese); } eventAdded = true; } } } if (eventAdded) { if (this.OnMatchesAdded != null) { this.OnMatchesAdded (this, addThese); } } }
private CdsSpider GetSpider(CpMediaContainer mc) { if (InvokeRequired == true) { int tt = 5; } CdsSpider spider; lock (this.m_ContainerToSpider) { spider = (CdsSpider) this.m_ContainerToSpider[mc]; if (spider == null) { spider = new CdsSpider(); spider.OnMatchesAdded += new CdsSpider.Delegate_OnMatchesChanged(this.Sink_SpiderOnMatchesAdded); spider.OnMatchesCleared += new CdsSpider.Delegate_OnMatchesChanged(this.Sink_SpiderOnMatchesCleared); spider.OnMatchesRemoved += new CdsSpider.Delegate_OnMatchesChanged(this.Sink_SpiderOnMatchesRemoved); spider.OnUpdateDone += new CdsSpider.Delegate_OnMatchesChanged(this.Sink_SpiderOnMatchesUpdated); if (deviceTree.SelectedNode != null) { IMediaContainer selected = deviceTree.SelectedNode.Tag as IMediaContainer; if (selected != null) { if (mc.Parent == selected) { spider.Comparer = MainForm.MatchContainers; } else if (mc.Parent != null) { if ( (mc.Parent.Parent == selected) && (! (selected is CpRootCollectionContainer)) && (selected != null) ) { spider.Comparer = MainForm.MatchContainers; } else { spider.Comparer = MainForm.MatchNever; } } else { spider.Comparer = MainForm.MatchNever; } } else { spider.Comparer = MainForm.MatchNever; } } else { spider.Comparer = MainForm.MatchNever; } spider.Sorter = null; spider.MonitorThis = mc; this.m_ContainerToSpider[mc] = spider; } spider.Tag = DateTime.Now; } return spider; }
private void ContainerChangedSink(CpRootContainer sender, CpMediaContainer thisChanged) { if (InvokeRequired) { this.Invoke(new CpRootContainer.Delegate_OnContainerChanged(ContainerChangedSink), sender, thisChanged); return; } // Update the tree view this.GetSpider(thisChanged); // Throw spiders on every child container foreach (CpMediaContainer cpc in thisChanged.Containers) { this.GetSpider(cpc); } try { lock (this.m_ContainerToSpider) { TreeNode node = NodeTagSearch(cdsRootNode,thisChanged); if (node == null) { //Update on unknown node Event("Container " + thisChanged.Title,"Unknown Container Changed"); } else { Event("Container " + thisChanged.Title,"Changed"); // get the curren listing of child containers for the // container reporting the change IList newcontainers = thisChanged.Containers; if (newcontainers != null) { ArrayList noderemovelist = new ArrayList(); ArrayList existingcontainers = new ArrayList(); // iterate through the treeview's representation // of the last known set of child containers foreach (TreeNode n in node.Nodes) { // get the container associated with the node CpMediaContainer c = (CpMediaContainer) n.Tag; if (newcontainers.Contains(c) == false) { // If the node's container is no longer associated // with the container, then the node should be removed. noderemovelist.Add(n); } else { // If the node's container is still associated with // the container, then the container and node // should remain. existingcontainers.Add(c); } } foreach (TreeNode n in noderemovelist) { this.CleanupRemovedNode(n); // Remove the subtree of tree nodes. // For some reason, we need to remove // all of the nodes after we clean up. // I had memory leaks when the nodes // were removed from within the code // for CleanupRemovedNode() n.Remove(); } foreach (CpMediaContainer c in newcontainers) { // Iterate through the new list of containers, but recurse // and update the treeview only with containers that // are brand new. if (existingcontainers.Contains(c) == false) { TreeNode cNode; // Depending on the type of container, ensure // that we use the right icon in the treeview. if (c.GetType() == typeof(CpRootContainer)) { cNode = new TreeNode(c.Title,1,1); } else { cNode = new TreeNode(c.Title,2,3); } cNode.Tag = c; node.Nodes.Add(cNode); ContainerChangedSink(null,c); } } } } cdsRootNode.Expand(); } } catch (Exception ex) { MessageBox.Show(ex.ToString()); } }
/// <summary> /// Creates a /// <see cref="CpMediaContainer"/> /// object, given a metadata instantiation /// block. /// </summary> /// <param name="info"> /// The metadata to use when instantiating the media. /// </param> /// <returns>a new media container</returns> public static CpMediaContainer CreateContainer(MediaBuilder.container info) { CpMediaContainer newObj = new CpMediaContainer(); MediaBuilder.SetObjectProperties(newObj, info); return newObj; }
private void OnAllRootsContainerChanged(CpRootContainer sender, CpMediaContainer thisChanged) { IncrementalFillMediaList(); }
/// <summary> /// Sets the container to a new parent. /// </summary> /// <param name="newParent"></param> internal void SetParent(CpMediaContainer newParent) { this.m_Parent = newParent; }
/// <summary> /// Simply calls the owner object's implementation of Update(). /// </summary> /// <exception cref="NullReferenceException"> /// Thrown if the parent object is null. /// </exception> /// <exception cref="InvalidCastException"> /// Thrown if the parent object is not a <see cref="CpMediaContainer"/>, /// which should always be the case. /// </exception> public void Update() { CpMediaContainer parent = (CpMediaContainer)this.Parent; parent.Update(); }
/// <summary> /// <see cref="CpMediaContainer"/> call this method to /// indicate that it's done giving notifications /// for new/removed/updated items for a while. /// </summary> /// <param name="thisChanged"></param> internal void NotifySinkUpdateDone(CpMediaContainer thisChanged) { if (thisChanged == this.m_MonitorThis) { this.m_BrowsingError = null; if (this.OnUpdateDone != null) { this.OnUpdateDone(this, null); } } }
/// <summary> /// <see cref="CpMediaContainer.NotifySpidersRemove"/> calls this /// method to indicate that child objects have been removed /// from the container. /// </summary> /// <param name="thisChanged">the container that witnessed the change</param> /// <param name="removeThese">an ArrayList of STRONG REFERENCES to <see cref="ICpMedia"/> objects</param> internal void NotifySinkRemove(CpMediaContainer thisChanged, ArrayList removeThese) { ArrayList removedObjects = new ArrayList(removeThese.Count); lock (this.m_Matches.SyncRoot) { foreach (ICpMedia obj in this.m_Matches) { if (removeThese.Contains(obj)) { removedObjects.Add(obj); } } foreach (ICpMedia obj in removedObjects) { this.m_Matches.Remove(obj); } } if (removedObjects.Count > 0) { if (this.OnMatchesRemoved != null) { this.OnMatchesRemoved (this, removedObjects); } } }