/// <summary> /// Starts the UPnP server. /// </summary> public static void Start() { if (IsRunning) { Log.Info("An UPnP/DLNA server start was requested, but it is already running."); Stop(); } if (!Signature.IsActivated) { Log.Error("An UPnP/DLNA server start was requested, but the software is not activated."); return; } Log.Info("Starting UPnP/DLNA server..."); _ms = new MediaServerDevice(_di, null, true, "http-get:*:*:*", ""); _dw = new UPnPDeviceWatcher(_ms._Device); var dv = _ms.GetUPnPDevice(); if (_favicon == null) { _favicon = new Icon(Application.GetResourceStream(new Uri("pack://application:,,,/RSTVShowTracker;component/tv.ico")).Stream); _icon = new Bitmap(Application.GetResourceStream(new Uri("pack://application:,,,/RSTVShowTracker;component/Images/tv48.png")).Stream); _icon2 = new Bitmap(Application.GetResourceStream(new Uri("pack://application:,,,/RSTVShowTracker;component/Images/tv64.png")).Stream); } dv.favicon = _favicon; dv.Icon = _icon; dv.Icon2 = _icon2; _ms.Start(); IsRunning = true; _mimes = new HashSet<string>(); RebuildList(); }
public MediaServerCore(string friendlyName) { if (serverCore != null) throw new Exception("Only a single MediaServerCode instance is allowed"); serverCore = this; OpenSource.Utilities.EventLogger.SetLog("Media Server", "MediaServerCode", System.Windows.Forms.Application.ProductVersion.ToString()); DeviceInfo info = new DeviceInfo(); info.AllowRemoteContentManagement = true; info.FriendlyName = friendlyName; info.Manufacturer = "OpenSource"; info.ManufacturerURL = ""; info.ModelName = "Media Server"; info.ModelDescription = "Provides content through UPnP ContentDirectory service"; info.ModelURL = ""; info.ModelNumber = "0.765"; info.LocalRootDirectory = ""; Tags T = Tags.GetInstance(); info.SearchCapabilities = "dc:title,dc:creator,upnp:class,upnp:album,res@protocolInfo,res@size,res@bitrate"; info.SortCapabilities = "dc:title,dc:creator,upnp:class,upnp:album"; info.EnableSearch = true; info.CacheTime = MediaServerCore.CacheTime; info.CustomUDN = MediaServerCore.CustomUDN; info.INMPR03 = MediaServerCore.INMPR; // encode in UTF16 instead of UTF8 MediaObject.ENCODE_UTF8 = false; mediaServer = new MediaServerDevice(info, null, true, "http-get:*:*:*", ""); mediaServer.OnStatsChanged += new MediaServerDevice.Delegate_MediaServerHandler(StatsChangedChangedSink); mediaServer.OnHttpTransfersChanged += new MediaServerDevice.Delegate_MediaServerHandler(HttpTransfersChangedSink); mediaServer.OnFileNotMapped = new MediaServerDevice.Delegate_FileNotMappedHandler(this.Handle_OnRequestUnmappedFile); mediaServer.OnRequestAddBranch = new MediaServerDevice.Delegate_AddBranch(this.Handle_OnRequestAddBranch); mediaServer.OnRequestRemoveBranch = new MediaServerDevice.Delegate_RemoveBranch(this.Handle_OnRequestRemoveBranch); mediaServer.OnRequestChangeMetadata = new MediaServerDevice.Delegate_ChangeMetadata(this.Handle_OnRequestChangeMetadata); mediaServer.OnRequestSaveBinary = new MediaServerDevice.Delegate_ModifyBinary (this.Handle_OnRequestSaveBinary); mediaServer.OnRequestDeleteBinary = new MediaServerDevice.Delegate_ModifyBinary(this.Handle_OnRequestDeleteBinary); this.ResetCoreRoot(); this.m_DeviceWatcher = new UPnPDeviceWatcher(mediaServer._Device); this.m_DeviceWatcher.OnSniff += new OpenSource.UPnP.UPnPDeviceWatcher.SniffHandler(this.Sink_DeviceWatcherSniff); this.mediaServer.Start(); m_Paused = false; }
public void StatsChangedChangedSink(MediaServerDevice sender) { if (OnStatsChanged != null) OnStatsChanged(this); }
public void HttpTransfersChangedSink(MediaServerDevice sender) { if (OnHttpTransfersChanged != null) OnHttpTransfersChanged(this); }
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_OnRequestUnmappedFile(MediaServerDevice sender, MediaServerDevice.FileNotMapped getPacket) { string path_query = getPacket.RequestedResource.ContentUri.Substring(DvMediaResource.AUTOMAPFILE.Length); DText path_queryParser = new DText(); if (getPacket.RequestedResource.Owner.Class.IsA(MediaBuilder.StandardMediaClasses.ImageItem)) { path_queryParser.ATTRMARK = "?"; path_queryParser.MULTMARK = "="; path_queryParser.SUBVMARK = ","; path_queryParser[0] = path_query; string path = path_queryParser[1]; string query = path_queryParser[2]; string format = path_queryParser[2,1]; string resolution = path_queryParser[2,2]; string resX = path_queryParser[2,2,1]; string resY = path_queryParser[2,2,2]; int width = int.Parse(resX); int height = int.Parse(resY); int max = Math.Max(width, height); Image image = Image.FromFile(path); Image thumbnail = image.GetThumbnailImage(width, height, null, IntPtr.Zero); getPacket.RedirectedStream = new MemoryStream(); thumbnail.Save(getPacket.RedirectedStream, ImageFormat.Jpeg); } else if ( (getPacket.RequestedResource.Owner.Class.IsA(MediaBuilder.StandardMediaClasses.PlaylistContainer)) || (getPacket.RequestedResource.Owner.Class.IsA(MediaBuilder.StandardMediaClasses.PlaylistItem)) ) { path_queryParser.ATTRMARK = "?"; path_queryParser.MULTMARK = "="; path_queryParser[0] = path_query; string path = path_queryParser[1]; string query = path_queryParser[2]; string format = path_queryParser[2,1]; string baseUrl = getPacket.LocalInterface; FileInfo fi = (FileInfo) ((DvMediaResource) getPacket.RequestedResource).Tag; //TODO: build m3u MemoryStream m3u = new MemoryStream((int)fi.Length * 5); StreamWriter sw = new StreamWriter(m3u, System.Text.Encoding.UTF8); getPacket.RedirectedStream = m3u; sw.Write("\n"); sw.Flush(); m3u.Position = 0; DvMediaContainer dvc = (DvMediaContainer) getPacket.RequestedResource.Owner; sw.WriteLine("#EXTM3U"); foreach (DvMediaItem dvi in dvc.CompleteList) { StringBuilder extInfo = new StringBuilder(dvi.Title.Length + dvi.Creator.Length + 15); StringBuilder uri = new StringBuilder(1024); //digital home looks for a single '-' to delimit creator/title extInfo.AppendFormat("#EXTINF:-1,{0} - {1}", dvi.Creator.Replace("-", "_"), dvi.Title.Replace("-", "_")); sw.WriteLine(extInfo.ToString()); IList resources = dvi.MergedResources; DvMediaResource res = resources[0] as DvMediaResource; if (res != null) { if (res.ContentUri.StartsWith(MediaResource.AUTOMAPFILE)) { uri.AppendFormat("http://{0}/{1}{2}", baseUrl, mediaServer.VirtualDirName, res.RelativeContentUri); } else { uri.Append(res.ContentUri); } sw.WriteLine(uri); } else { StringBuilder msg = new StringBuilder(); if (resources.Count == 0) { msg.AppendFormat("MediaServerCore.Handle_OnRequestUnmappedFile() encountered a media object ID=\"{0}\" Title=\"{1}\" with zero resources.", dvi.ID, dvi.Title); } else { msg.AppendFormat("MediaServerCore.Handle_OnRequestUnmappedFile() encountered a media object ID=\"{0}\" Title=\"{1}\" with resource that is not a DvMediaResource.", dvi.ID, dvi.Title); } OpenSource.Utilities.EventLogger.Log(msg.ToString()); } } sw.Flush(); } }
private void Handle_OnRequestSaveBinary(MediaServerDevice sender, IDvResource res) { Exception error = null; this.m_LockRoot.WaitOne(); try {// Throw exceptions if files are to not be deleted. // if (res.AllowImport == false) { throw new Error_AccessDenied("The resource cannot be overwritten or created."); } } catch (Exception e) { error = e; } this.m_LockRoot.ReleaseMutex(); if (error != null) { throw new ApplicationException("Handle_OnRequestSaveBinary()", error); } }
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 Handle_OnRequestDeleteBinary(MediaServerDevice sender, IDvResource res) { Exception error = null; this.m_LockRoot.WaitOne(); try { // Throw exceptions if the file should not be deleted. // if (res.AllowImport == false) { //throw new Error_AccessDenied("The resource cannot be deleted."); } /// The UPNP layer will not delete the actual file from the local file system. /// I should note that if multiple resources are bound to the same file, then /// the logic in this method prevents the file from being deleted. /// if (res.ContentUri.StartsWith(DvMediaResource.AUTOMAPFILE)) { string filename = res.ContentUri.Substring(DvMediaResource.AUTOMAPFILE.Length); File.Delete(filename); } } catch (Exception e) { error = e; } this.m_LockRoot.ReleaseMutex(); if (error != null) { throw new ApplicationException("Handle_OnRequestDeleteBinary()", error); } }
private void Handle_OnRequestChangeMetadata(MediaServerDevice sender, IDvMedia oldObject, IDvMedia newObject) { Exception error = null; this.m_LockRoot.WaitOne(); try { /// TODO: Add permissions logic /// /// The following metadata fields must be the same between the old and new objects. /// ID, /// refID /// Parent /// IsRestricted /// if (oldObject.IsRestricted) { //Allow everything for now //throw new Error_RestrictedObject("Cannot modify a restricted object."); } if (oldObject.ID != newObject.ID) { throw new Error_ReadOnlyTag("Cannot modify ID"); } if (oldObject.IsContainer != newObject.IsContainer) { throw new Error_BadMetadata("Cannot change containers into items."); } if (oldObject.IsItem != newObject.IsItem) { throw new Error_BadMetadata("Cannot change items into containers."); } if (oldObject.IsRestricted != newObject.IsRestricted) { throw new Error_ReadOnlyTag("Cannot change the \"restricted\" attribute."); } if ((oldObject.IsReference) || (newObject.IsReference)) { if (oldObject.IsReference == newObject.IsReference) { DvMediaItem oldItem = (DvMediaItem) oldObject; DvMediaItem newItem = (DvMediaItem) newObject; string refid1 = oldItem.RefID; string refid2 = newItem.RefID; if (string.Compare(refid1, refid2) != 0) { throw new Error_ReadOnlyTag("Cannot change the \"refID\" attribute."); } } else { throw new Error_BadMetadata("Cannot change a reference item into a non-reference."); } } } catch (Exception e) { error = e; } this.m_LockRoot.ReleaseMutex(); if (error != null) { throw new ApplicationException("Handle_OnRequestChangeMetadata()", error); } // TODO: Actually check validity for metadata of media objects and their resources. }
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); } }
/// <summary> /// Indicates vendor-specific error code of 881. /// </summary> /// <param name="id"></param> /// <param name="transferInfo"></param> public Error_TransferProblem(UInt32 id, MediaServerDevice.HttpTransfer transferInfo) : base(881, "Error with transfer " + id.ToString()) { TransferId = id; TransferInfo = transferInfo; }
/// <summary> /// Stops the UPnP server. /// </summary> public static void Stop() { Log.Info("Stopping UPnP/DLNA server..."); IsRunning = false; _ms.Stop(); _ms.Dispose(); _ms = null; _dw = null; }