/// <summary> /// <see cref="DvMediaContainer"/> objects /// use this method to event changes in their state. This /// method simply fires the /// <see cref="DvRootContainer.OnContainerChanged"/> /// event. /// </summary> /// <param name="thisChanged"></param> internal void FireOnContainerChanged(DvMediaContainer thisChanged) { if (this.OnContainerChanged != null) { this.OnContainerChanged(this, thisChanged); } }
/// <summary> /// Creates a /// <see cref="DvMediaContainer"/> /// 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 DvMediaContainer CreateContainer(MediaBuilder.container info) { DvMediaContainer newObj = new DvMediaContainer(); MediaBuilder.SetObjectProperties(newObj, info); newObj.TrackMetadataChanges = true; return newObj; }
/// <summary> /// Creates a /// <see cref="DvMediaContainer"/> /// 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 DvMediaContainer CreateContainer(MediaBuilder.container info) { DvMediaContainer newObj = new DvMediaContainer(); MediaBuilder.SetObjectProperties(newObj, info); newObj.TrackMetadataChanges = true; return(newObj); }
/// <summary> /// Calls DvMediaContainer.CheckProtection() if the item has a parent. /// This method is used to prevent /// public programmers from doing a set() on the Parent /// property. /// </summary> /// <param name="st"></param> public override void CheckRuntimeBindings(StackTrace st) { #if (DEBUG) if (this.Parent != null) { DvMediaContainer parent = (DvMediaContainer)this.Parent; parent.CheckRuntimeBindings(st); } #endif }
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> /// <para> /// Calls the parent container's /// <see cref="DvMediaContainer.NotifyRootOfChange"/> method. /// </para> /// /// <para> /// Enumerates through this item's reference items and instructs /// each to notify their parents of the change. /// </para> /// </summary> /// <exception cref="InvalidCastException"> /// Thrown when parent container is not a <see cref="DvMediaContainer"/> object. /// </exception> public void NotifyRootOfChange() { DvMediaContainer mc = (DvMediaContainer)this.m_Parent; if (mc != null) { mc.NotifyRootOfChange(); } this.LockReferenceList(); if (this.m_ReferringItems != null) { foreach (IDvItem refItem in this.m_ReferringItems) { mc = (DvMediaContainer)refItem.Parent; if (mc != null) { mc.NotifyRootOfChange(); } } } this.UnlockReferenceList(); }
/// <summary> /// Updates the metadata of container, container's children, and /// resources associated with both. /// /// <para> /// We currently use a file system watcher to manage the metadata /// for most things. The only thing we don't do is calcuate the /// used storage space of a folder and other storage stats. /// </para> /// </summary> /// <param name="container"></param> private void Sink_UpdateContainerMetadata(DvMediaContainer container) { // Determine the used space by calculating the sum of the storage used by all child objects' resources. /* long storageUsed = 0; if (container.Class.FullClassName.StartsWith("object.container.storage")) { foreach (IUPnPMedia child in container.CompleteList) { foreach (IMediaResource res in child.Resources) { if (res.HasSize) { // silly UPnP-AV/CDS authors forgot to make size into // a signed value, so i'll just fudge the value here // so that I remain schema-compliant in every way... // AV Forum should eventually change this though. long v; if (res.Size.m_Value > long.MaxValue) { v = long.MaxValue; } else { v = (long) res.Size.m_Value; } storageUsed += v; } } } container.SetPropertyValue_Long(Tags.GetInstance()[CommonPropertyNames.storageUsed], storageUsed); } */ }
/// <summary> /// This recursively method serializes the content hierarchy. /// </summary> /// <param name="fstream"></param> /// <param name="container"></param> private void SerializeContainer(BinaryFormatter formatter, FileStream fstream, DvMediaContainer container, Hashtable refItems) { IList children = container.CompleteList; // Indicate that a container is being serialized, then // serialize the metadata for this container, // and serialize the number of children, // then recursively serialize formatter.Serialize(fstream, container); formatter.Serialize(fstream, children.Count); foreach (IUPnPMedia child in children) { DvMediaContainer dvc = child as DvMediaContainer; DvMediaItem dvi = child as DvMediaItem; if (dvc != null) { this.SerializeContainer(formatter, fstream, dvc, refItems); } else if (dvi != null) { // This is an item, so serialize the media item. // If the item is a refItem, provide a mapping // from item ID to refID. formatter.Serialize(fstream, dvi); if (dvi.IsReference) { if ((dvi.RefID != null) && (dvi.RefID != "")) { refItems[dvi.ID] = dvi.RefID; } } } else { throw new ApplicationException("The MediaServer has a IUPnPMedia item with ID=\"" + child.ID +"\" that is neither a DvMediaItem nor a DvMediaContainer."); } } }
/// <summary> /// Changes the target media object's parent to a different parent. /// </summary> /// <param name="target">target object</param> /// <param name="np">new parent</param> /// <exception cref="InvalidCastException"> /// Thrown when the target's current parent is not a <see cref="DvMediaContainer"/>. /// </exception> internal static void ChangeParent2(IDvMedia target, DvMediaContainer np) { Exception error = null; IUPnPMedia errorDuplicate = null; IDvMedia[] removeThese = new IDvMedia[1]; removeThese[0] = target; DvMediaContainer dvp = (DvMediaContainer)target.Parent; // fire about to remove event if (dvp.OnChildrenToRemove != null) { dvp.OnChildrenToRemove(dvp, removeThese); } // acquire locks dvp.m_LockListing.AcquireWriterLock(-1); np.m_LockListing.AcquireWriterLock(-1); try { // remove target from current parent int i = dvp.HashingMethod.Get(dvp.m_Listing, target); dvp.m_Listing.RemoveAt(i); target.Parent = null; if (dvp.m_Listing.Count == 0) { dvp.m_Listing = null; } // add target to new parent if (np.m_Listing == null) { np.m_Listing = new ArrayList(); } try { np.HashingMethod.Set(np.m_Listing, target, true); target.Parent = np; } catch (KeyCollisionException) { errorDuplicate = target; } } catch (Exception e) { error = e; } // release locks np.m_LockListing.ReleaseWriterLock(); dvp.m_LockListing.ReleaseWriterLock(); // throw exceptions if appropriate if (error != null) { throw new Exception("Unexpected rrror in DvMediaContainer.ChangeParent2", error); } if (errorDuplicate != null) { throw new Error_DuplicateIdException(errorDuplicate); } // fire children removed event if (dvp.OnChildrenRemoved != null) { dvp.OnChildrenRemoved(dvp, removeThese); } // notify upnp network that two containers changed. dvp.NotifyRootOfChange(); np.NotifyRootOfChange(); }
private bool AddDirectoryEx(DvMediaContainer container, DirectoryInfo directory) { if (directory.Exists == false) return false; MediaBuilder.storageFolder storageInfo = new MediaBuilder.storageFolder(directory.Name); storageInfo.Searchable = true; storageInfo.IsRestricted = false; DvMediaContainer newContainer = DvMediaBuilder.CreateContainer(storageInfo); newContainer.OnChildrenRemoved += new DvDelegates.Delegate_OnChildrenRemove(this.Sink_OnChildRemoved); newContainer.Callback_UpdateMetadata = new DvMediaContainer.Delegate_UpdateMetadata(this.Sink_UpdateContainerMetadata); InnerMediaDirectory mediadir = new InnerMediaDirectory(); mediadir.directory = directory; mediadir.directoryname = directory.FullName; mediadir.watcher = new FileSystemWatcher(directory.FullName); mediadir.watcher.Changed += new FileSystemEventHandler(OnDirectoryChangedSink); mediadir.watcher.Created += new FileSystemEventHandler(OnDirectoryCreatedSink); mediadir.watcher.Deleted += new FileSystemEventHandler(OnDirectoryDeletedSink); mediadir.watcher.Renamed += new RenamedEventHandler(OnFileSystemRenameSink); mediadir.restricted = true; mediadir.readOnly = true; watcherTable.Add(mediadir.watcher,newContainer); mediadir.watcher.EnableRaisingEvents = true; newContainer.Tag = mediadir; FileInfo[] files = directory.GetFiles(); ArrayList addedFiles = new ArrayList(files.Length); foreach (FileInfo file in files) { IDvMedia newObj = CreateObjFromFile(file, new ArrayList()); if (newObj != null) { addedFiles.Add(newObj); totalFileCount++; } } newContainer.AddObjects(addedFiles, true); // Add the new container to an existing container. container.AddObject(newContainer, true); foreach (IDvMedia item in addedFiles) { if (item.Class.IsA(MediaBuilder.StandardMediaClasses.AudioItem)) { this.m_AudioItems.AddReference((DvMediaItem)item); } else if (item.Class.IsA(MediaBuilder.StandardMediaClasses.ImageItem)) { this.m_ImageItems.AddReference((DvMediaItem)item); } else if (item.Class.IsA(MediaBuilder.StandardMediaClasses.VideoItem)) { this.m_VideoItems.AddReference((DvMediaItem)item); } else if (item.Class.IsA(MediaBuilder.StandardMediaClasses.PlaylistContainer)) { // References to playlists are not allowed, so we have to build // completely new instances of the container and its resources. // However the new container can have references to the items. DvMediaContainer originalC = (DvMediaContainer) item; MediaBuilder.playlistContainer plcInfo = new MediaBuilder.playlistContainer(originalC.Title); DvMediaContainer newC = DvMediaBuilder.CreateContainer(plcInfo); foreach (DvMediaResource res in originalC.Resources) { ResourceBuilder.AllResourceAttributes resAttribs = new ResourceBuilder.AllResourceAttributes(); resAttribs.contentUri = res.ContentUri; foreach (string attribute in res.ValidAttributes) { object obj = res[attribute]; _RESATTRIB attribName = (_RESATTRIB) Enum.Parse(typeof(_RESATTRIB), attribute, true); switch (attribName) { case _RESATTRIB.bitrate: resAttribs.bitrate = (_UInt) obj; break; case _RESATTRIB.bitsPerSample: resAttribs.bitsPerSample = (_UInt) obj; break; case _RESATTRIB.colorDepth: resAttribs.colorDepth = (_UInt) obj; break; case _RESATTRIB.duration: resAttribs.duration = (_TimeSpan) obj; break; case _RESATTRIB.importUri: //do not allow import break; case _RESATTRIB.nrAudioChannels: resAttribs.nrAudioChannels = (_UInt) obj; break; case _RESATTRIB.protection: resAttribs.protection = (string) obj; break; case _RESATTRIB.protocolInfo: resAttribs.protocolInfo = new ProtocolInfoString(((ProtocolInfoString)obj).ToString()); break; case _RESATTRIB.resolution: resAttribs.resolution = (ImageDimensions) obj; break; case _RESATTRIB.sampleFrequency: resAttribs.sampleFrequency = (_UInt) obj; break; case _RESATTRIB.size: resAttribs.size = (_ULong) obj; break; } } DvMediaResource newCR = DvResourceBuilder.CreateResource(resAttribs, false); newCR.AllowImport = res.AllowImport; newCR.CheckAutomapFileExists = res.CheckAutomapFileExists; newCR.HideContentUri = res.HideContentUri; newCR.MakeStreamAtHttpGetTime = res.MakeStreamAtHttpGetTime; newCR.Tag = res.Tag; newC.AddResource(newCR); } // The child container should only have items. // If the child-container has child containers, then // then this is bad because those child playlists // should have been converted to a flat list // in the recursive building of the hierarchy foreach (DvMediaItem childItem in originalC.CompleteList) { newC.AddReference(childItem); } this.m_Playlists.AddObject(newC, true); } } DirectoryInfo[] directories = directory.GetDirectories(); foreach (DirectoryInfo dir in directories) { AddDirectoryEx(newContainer,dir); } totalDirectoryCount++; if (OnStatsChanged != null) OnStatsChanged(this); return true; }
public void ResetCoreRoot() { MediaBuilder.SetNextID(0); rootContainer = mediaServer.Root; MediaBuilder.container containerImagesInfo = new MediaBuilder.container("All Image Items"); containerImagesInfo.IsRestricted = true; MediaBuilder.container containerAudioItemsInfo = new MediaBuilder.container("All Audio Items"); containerAudioItemsInfo.IsRestricted = true; MediaBuilder.container containerVideoItemsInfo = new MediaBuilder.container("All Video Items"); containerVideoItemsInfo.IsRestricted = true; MediaBuilder.container containerPlaylistsInfo = new MediaBuilder.container("All Playlists"); containerPlaylistsInfo.IsRestricted = true; m_ImageItems = (DvMediaContainer) DvMediaBuilder.CreateContainer(containerImagesInfo); m_AudioItems = (DvMediaContainer) DvMediaBuilder.CreateContainer(containerAudioItemsInfo); m_VideoItems = (DvMediaContainer) DvMediaBuilder.CreateContainer(containerVideoItemsInfo); m_Playlists = (DvMediaContainer) DvMediaBuilder.CreateContainer(containerPlaylistsInfo); rootContainer.AddObject(m_ImageItems, true); rootContainer.AddObject(m_AudioItems, true); rootContainer.AddObject(m_VideoItems, true); rootContainer.AddObject(m_Playlists, true); }
/// <summary> /// /// </summary> /// <param name="container"></param> /// <param name="formatter"></param> /// <param name="fstream"></param> private void DeserializeContainer(DvMediaContainer container, BinaryFormatter formatter, FileStream fstream) { // get number of children in container int count = (int) formatter.Deserialize (fstream); ArrayList children = new ArrayList(count); object obj; DvMediaItem dvi; DvMediaContainer dvc; for (int i=0; i<count; i++) { try { obj = formatter.Deserialize(fstream); } catch (Exception e) { throw new SerializationException("Error deserializing a child of containerID=\"" +container.ID+ "\" Title=\"" +container.Title+ "\".", e); } dvi = obj as DvMediaItem; dvc = obj as DvMediaContainer; if (dvc != null) { this.DeserializeContainer(dvc, formatter, fstream); children.Add(dvc); } else if (dvi != null) { children.Add(dvi); } else { throw new ApplicationException("The MediaServer deserialized an object that is neither a DvMediaItem nor a DvMediaContainer."); } } container.AddObjects(children, true); }
/// <summary> /// Method executes when the root container indicates that a descendent container has changed. /// Method's purpose is to cause the ContainerUpdateIDs state variable to event /// the change. /// </summary> /// <param name="sender"></param> /// <param name="thisChanged"></param> private void Sink_ContainerChanged(DvRootContainer sender, DvMediaContainer thisChanged) { this.Lock_SystemUpdateID.WaitOne(); this.ContentDirectory.Evented_SystemUpdateID = this.ContentDirectory.Evented_SystemUpdateID + 1; this.Lock_SystemUpdateID.ReleaseMutex(); this.Lock_ContainerUpdateIDs.WaitOne(); StringBuilder sb = new StringBuilder(20); sb.AppendFormat("{0}{1}{2}", thisChanged.ID, Accumulator_ContainerUpdateIDs.Delimitor, thisChanged.UpdateID); this.ContentDirectory.Evented_ContainerUpdateIDs = sb.ToString(); this.Lock_ContainerUpdateIDs.ReleaseMutex(); }
/// <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(); }
private void ValidateBranch(DvMediaContainer branchFrom, IDvMedia branch, bool allowNewLocalResources) { DvMediaContainer parent = branchFrom; string basePath = ""; if (allowNewLocalResources) { /// The parent container's TAG field will have one of two things: /// 1) string representation of the local path that it maps to.. /// 2) InnerMediaDirectory structure describing the local path that it maps to. /// 3) Empty string value or null if no mapping to a local file. /// if (parent.Tag == null) { } else if (parent.Tag.GetType() == new InnerMediaDirectory().GetType()) { InnerMediaDirectory imd = (InnerMediaDirectory) parent.Tag; basePath = imd.directory.FullName + "\\"; } else if (parent.Tag.GetType() == typeof(string)) { basePath = parent.Tag + "\\"; } /// The new branch must be a storage container in order to /// map to a local file of sort. May consider making /// the class more restricted to object.container.storageFolder. /// if (branch.IsContainer) { DvMediaContainer container = (DvMediaContainer) branch; if (container.Class.ToString().StartsWith("object.container.storage")) //if (true) { container.Tag = basePath + container.Title; } else { container.Tag = null; } } } if (branch.IsContainer) { DvMediaContainer container = (DvMediaContainer) branch; foreach (IDvMedia child in container.CompleteList) { ValidateBranch(container, child, allowNewLocalResources); } } else if (branch.IsItem) { } else { throw new Exception("Error: Could not validate branch. Branch must be a container, reference, or item."); } if (branch.IsReference == false) { /// Each of these resources should be actual children of the item. /// They should not be resources obtained through a reference. /// This impelementation does not allow references to declare /// their own resources. /// IList resources = branch.Resources; if (resources != null) { if (resources.Count > 0) { foreach (DvMediaResource res in resources) { if (res.ContentUri.StartsWith(DvMediaResource.AUTOMAPFILE)) { if (allowNewLocalResources) { string filePath = res.ContentUri.Substring(DvMediaResource.AUTOMAPFILE.Length); if (File.Exists(filePath)) { if (Directory.Exists(filePath)) { throw new UPnPCustomException(810, "The specified local file-uri is a directory. (" +res.ContentUri+")"); } FileInfo fi = new FileInfo(filePath); string protocol = "http-get"; string network = "*"; string mime; string classType; MimeTypes.ExtensionToMimeType(fi.Extension, out mime, out classType); string info = "*"; StringBuilder sb = new StringBuilder(100); sb.AppendFormat("{0}:{1}:{2}:{3}", protocol, network, mime, info); ProtocolInfoString protInfo = new ProtocolInfoString(sb.ToString()); res.SetProtocolInfo(protInfo); } else { throw new UPnPCustomException(811, "The specified local file-uri does not exist. (" +res.ContentUri+")"); } } else { throw new Error_BadMetadata("Cannot create local http-get resources that are descendents from the specified container."); } } else if ((res.ContentUri == "") && (basePath != "")) { // Get a unique filename where we can save the binary when it gets imported // or sent. string filePath = res.GenerateLocalFilePath(basePath); /// Set the content uri to map to the determined local path... /// although it's understood that the file does not exist yet. /// res.SetContentUri(filePath); } else if (res.ContentUri != "") { string importUri = res.ImportUri; //int x = 3; } else { throw new Error_RestrictedObject("The container specified does not allow creation of storage containers or resources."); } } } } } }
public void Dispose() { rootContainer = null; mediaServer.Dispose(); mediaServer = null; serverCore = null; this.m_DeviceWatcher = null; this.m_DeviceWatcher.OnSniff -= new OpenSource.UPnP.UPnPDeviceWatcher.SniffHandler(this.Sink_DeviceWatcherSniff); }
private void Handle_OnRequestAddBranch(MediaServerDevice sender, DvMediaContainer parentContainer, ref IDvMedia[] addTheseBranches) { Exception error = null; this.m_LockRoot.WaitOne(); try { if (parentContainer == this.mediaServer.Root) { throw new Error_RestrictedObject("Cannot create objects directly in the root container."); } else if (parentContainer.IsRestricted) { throw new Error_RestrictedObject("Cannot create objects in a restricted container."); } InnerMediaDirectory mediadir = (InnerMediaDirectory) parentContainer.Tag; bool allowNewLocalResources = true; if (mediadir != null) { allowNewLocalResources = Directory.Exists(mediadir.directory.FullName); } foreach (IDvMedia branch in addTheseBranches) { // Throw an exception if ANYTHING is bad. Add is always // atomic per request. // ValidateBranch(parentContainer, branch, allowNewLocalResources); } foreach (IDvMedia branch in addTheseBranches) { // No exceptions were thrown so go ahead and add new // files and directories to the local file system // for the new tree. // if (branch.IsReference == true) { parentContainer.AddBranch(branch); } else { ModifyLocalFileSystem(parentContainer, branch); } } } catch (Exception e) { error = e; } this.m_LockRoot.ReleaseMutex(); if (error != null) { throw new ApplicationException("Handle_OnRequestAddBranch()", error); } }
public void UpdatePermissionsEx(DvMediaContainer container, bool restricted, bool readOnly) { // if (readOnly) // { // //container.WriteStatus = OpenSource.UPnP.AV.CdsMetadata.EnumWriteStatus.NOT_WRITABLE; // } // else // { // //container.WriteStatus = OpenSource.UPnP.AV.CdsMetadata.EnumWriteStatus.WRITABLE; // } container.IsRestricted = restricted; foreach (DvMediaItem i in container.Items) { // if (readOnly) // { // //i.WriteStatus = OpenSource.UPnP.AV.CdsMetadata.EnumWriteStatus.NOT_WRITABLE; // } // else // { // //i.WriteStatus = OpenSource.UPnP.AV.CdsMetadata.EnumWriteStatus.WRITABLE; // } i.IsRestricted = restricted; foreach (DvMediaResource res in i.Resources) { if ((container.IsRestricted == false) && (i.IsRestricted == false)) { res.AllowImport = true; } else { res.AllowImport = false; } } } foreach (DvMediaContainer c in container.Containers) { UpdatePermissionsEx(c,restricted,readOnly); } }
private void Handle_OnRequestRemoveBranch(MediaServerDevice sender, DvMediaContainer parentContainer, IDvMedia removeThisBranch) { Exception error = null; this.m_LockRoot.WaitOne(); try { parentContainer.RemoveBranch(removeThisBranch); } catch (Exception e) { error = e; } this.m_LockRoot.ReleaseMutex(); if (error != null) { throw new ApplicationException("Handle_OnRequestRemoveBranch()", error); } }
private void AdjustContainer(DvMediaContainer c) { InnerMediaDirectory imd = c.Tag as InnerMediaDirectory; bool dirExists = false; // Remove non-root containers if the associated directory no longer exists. if (c.IsRootContainer == false) { if (imd != null) { imd.directory = new DirectoryInfo(imd.directoryname); if (imd.directory.Exists == false) { c.Parent.RemoveObject(c); } else { dirExists = true; } } } // c.CompleteList returns a shallow copy foreach (IDvMedia dv in c.CompleteList) { if (dv.IsContainer) { this.AdjustContainer((DvMediaContainer) dv); } else if (dv.IsReference) { // ignore references } else { // this is an item; dv.Resources returns a shallow copy foreach (IDvResource res in dv.Resources) { if (res.ContentUri.StartsWith(MediaResource.AUTOMAPFILE)) { string localPath = res.ContentUri.Remove(0, MediaResource.AUTOMAPFILE.Length); int quesMark = localPath.LastIndexOf('?'); if (quesMark >= 0) { localPath = localPath.Substring(0, localPath.LastIndexOf('?')); } if (File.Exists(localPath) == false) { dv.RemoveResource(res); } } } // if the item has no resources, remove it if (dv.Resources.Length == 0) { dv.Parent.RemoveObject(dv); } } } if (dirExists) { this.totalDirectoryCount++; // Scan the directory for containers and files that don't exist // in the current tree DirectoryInfo[] subdirs = imd.directory.GetDirectories(); FileInfo[] files = imd.directory.GetFiles(); IList containers = c.Containers; IList items = c.Items; foreach (DirectoryInfo subdir in subdirs) { bool found = false; foreach (IDvContainer dvc in containers) { InnerMediaDirectory imd2 = dvc.Tag as InnerMediaDirectory; if (imd2 != null) { // this container has a mapping to a local directory, // so determine if the container matches the // target name if (string.Compare(subdir.FullName, imd2.directoryname, true) == 0) { found = true; break; } } } if (found == false) { // the subdirectory wasn't found as a container in the tree, // so go ahead and add it this.AddDirectoryEx(c, subdir); } } foreach (FileInfo file in files) { bool found = false; foreach (IDvItem dvi in items) { if (dvi.IsReference == false) { bool foundRes = false; foreach (IDvResource res in dvi.Resources) { string localPath = res.ContentUri.Remove(0, MediaResource.AUTOMAPFILE.Length); int quesMark = localPath.LastIndexOf('?'); if (quesMark >= 0) { localPath = localPath.Substring(0, localPath.LastIndexOf('?')); } if (string.Compare(localPath, file.FullName, true) == 0) { foundRes = true; } break; } if (foundRes) { found = true; break; } } } foreach (IDvContainer dvc in containers) { if (dvc.Class.IsA(MediaBuilder.StandardMediaClasses.PlaylistContainer)) { FileInfo plfi = dvc.Tag as FileInfo; if (plfi != null) { if (string.Compare(plfi.FullName, file.FullName, true) == 0) { found = true; } } } } if (found == false) { // the file wasn't found as a resource in the // content hierarchy, so go ahead and add it IDvMedia newItem = this.CreateObjFromFile(file, new ArrayList()); c.AddObject(newItem, true); } // we either already had a media item for the file, or we just added one this.totalFileCount++; } // Also initialize inner media directory objects with a file // system watcher if the directory still exists. // We do this at the end because we don't want to subscribe // to changes until after we've added files. imd.watcher = new FileSystemWatcher(imd.directory.FullName); imd.watcher.Changed += new FileSystemEventHandler(OnDirectoryChangedSink); imd.watcher.Created += new FileSystemEventHandler(OnDirectoryCreatedSink); imd.watcher.Deleted += new FileSystemEventHandler(OnDirectoryDeletedSink); imd.watcher.Renamed += new RenamedEventHandler(OnFileSystemRenameSink); } }
private void ModifyLocalFileSystem(DvMediaContainer branchFrom, IDvMedia branch) { DvMediaContainer parent = (DvMediaContainer) branchFrom; IList resources = branch.Resources; if (branch.IsContainer) { DvMediaContainer container = (DvMediaContainer) branch; if (container.Class.ToString().StartsWith("object.container.storage")) { // This container is a storage container of some sort // so it should map to local directory. // string newDirPath = ""; if (container.Tag != null) { newDirPath = container.Tag.ToString(); } // Make a directory representing this container // and set the container's tag to point to the // media dir info. // DirectoryInfo newDirInfo = Directory.CreateDirectory(newDirPath); InnerMediaDirectory mediadir = new InnerMediaDirectory(); mediadir.directory = newDirInfo; mediadir.directoryname = newDirInfo.FullName; container.Tag = mediadir; } else if (container.Class.ToString().StartsWith("object.container")) { // This is a container, but it doesn't nececessarily map // to a local directory. The container subtree may have // items and references, so persist them virtually // in the hierarchy but not on disk. // container.Tag = null; } foreach (IDvMedia child in container.CompleteList) { ModifyLocalFileSystem(container, child); } } }
private void RemoveContainerEx(DvMediaContainer container) { InnerMediaDirectory mediadir = (InnerMediaDirectory)container.Tag; mediadir.watcher.EnableRaisingEvents = false; watcherTable.Remove(mediadir.watcher); mediadir.watcher.Changed -= new FileSystemEventHandler(OnDirectoryChangedSink); mediadir.watcher.Created -= new FileSystemEventHandler(OnDirectoryCreatedSink); mediadir.watcher.Deleted -= new FileSystemEventHandler(OnDirectoryDeletedSink); mediadir.watcher.Renamed -= new RenamedEventHandler(OnFileSystemRenameSink); mediadir.watcher.Dispose(); mediadir.watcher = null; mediadir.directory = null; RemoveInnerContainers(container); totalDirectoryCount--; totalFileCount -= container.Items.Count; if (OnStatsChanged != null) OnStatsChanged(this); }
private void RemoveInnerContainers(DvMediaContainer container) { foreach (DvMediaContainer c in container.Containers) { InnerMediaDirectory mediadir = c.Tag as InnerMediaDirectory; if (mediadir != null) { mediadir.watcher.EnableRaisingEvents = false; watcherTable.Remove(mediadir.watcher); mediadir.watcher.Changed -= new FileSystemEventHandler(OnDirectoryChangedSink); mediadir.watcher.Created -= new FileSystemEventHandler(OnDirectoryCreatedSink); mediadir.watcher.Deleted -= new FileSystemEventHandler(OnDirectoryDeletedSink); mediadir.watcher.Renamed -= new RenamedEventHandler(OnFileSystemRenameSink); mediadir.watcher.Dispose(); mediadir.watcher = null; mediadir.directory = null; RemoveInnerContainers(c); totalFileCount -= c.Items.Count; container.RemoveBranch(c); totalDirectoryCount--; if (OnStatsChanged != null) OnStatsChanged(this); } else if (c.Tag.GetType() == typeof(FileInfo)) { // this is a playlist container, so decrement // the file count totalFileCount--; } } }
/// <summary> /// Changes this object's parent to another container. /// Strongly recommended that this container already /// share the object's current hierarchy. /// </summary> /// <param name="diffParent"></param> /// <exception cref="InvalidCastException"> /// Thrown if this object was improperly added to a /// container that is not a <see cref="DvMediaContainer"/>. /// </exception> public void ChangeParent(IDvContainer diffParent) { DvMediaContainer.ChangeParent2(this, (DvMediaContainer)diffParent); }
/// <summary> /// Changes the target media object's parent to a different parent. /// </summary> /// <param name="target">target object</param> /// <param name="np">new parent</param> /// <exception cref="InvalidCastException"> /// Thrown when the target's current parent is not a <see cref="DvMediaContainer"/>. /// </exception> internal static void ChangeParent2(IDvMedia target, DvMediaContainer np) { Exception error = null; IUPnPMedia errorDuplicate = null; IDvMedia[] removeThese = new IDvMedia[1]; removeThese[0] = target; DvMediaContainer dvp = (DvMediaContainer) target.Parent; // fire about to remove event if (dvp.OnChildrenToRemove != null) { dvp.OnChildrenToRemove(dvp, removeThese); } // acquire locks dvp.m_LockListing.AcquireWriterLock(-1); np.m_LockListing.AcquireWriterLock(-1); try { // remove target from current parent int i = dvp.HashingMethod.Get(dvp.m_Listing, target); dvp.m_Listing.RemoveAt(i); target.Parent = null; if (dvp.m_Listing.Count == 0) { dvp.m_Listing = null; } // add target to new parent if (np.m_Listing == null) { np.m_Listing = new ArrayList(); } try { np.HashingMethod.Set(np.m_Listing, target, true); target.Parent = np; } catch (KeyCollisionException) { errorDuplicate = target; } } catch (Exception e) { error = e; } // release locks np.m_LockListing.ReleaseWriterLock(); dvp.m_LockListing.ReleaseWriterLock(); // throw exceptions if appropriate if (error != null) { throw new Exception("Unexpected rrror in DvMediaContainer.ChangeParent2", error); } if (errorDuplicate != null) { throw new Error_DuplicateIdException(errorDuplicate); } // fire children removed event if (dvp.OnChildrenRemoved != null) { dvp.OnChildrenRemoved (dvp, removeThese); } // notify upnp network that two containers changed. dvp.NotifyRootOfChange(); np.NotifyRootOfChange(); }