public AVRenderer(int MaxConnections, ProtocolInfoString[] Info, ConnectionHandler h)
        {
            ConnectionMax = MaxConnections;
            OnNewConnection += h;

            InfoStrings = Info;
            device = UPnPDevice.CreateEmbeddedDevice(1,Guid.NewGuid().ToString());
            device.FriendlyName = "AVRenderer Device (" + Dns.GetHostName() +")";

            AVT = new DvAVTransport();
            AVT.GetUPnPService().Major = 1;
            AVT.GetUPnPService().Minor = 0;

            Manager = new DvConnectionManager();
            Manager.GetUPnPService().Major = 1;
            Manager.GetUPnPService().Minor = 0;

            Control = new DvRenderingControl();
            Control.GetUPnPService().Major = 1;
            Control.GetUPnPService().Minor = 0;

            Manager.External_PrepareForConnection = new DvConnectionManager.Delegate_PrepareForConnection(PrepareForConnectionSink);
            Manager.External_ConnectionComplete = new DvConnectionManager.Delegate_ConnectionComplete(ConnectionCompleteSink);
            Manager.External_GetCurrentConnectionIDs = new DvConnectionManager.Delegate_GetCurrentConnectionIDs(GetCurrentConnectionIDsSink);
            Manager.External_GetProtocolInfo = new DvConnectionManager.Delegate_GetProtocolInfo(GetProtocolInfoSink);
            Manager.External_GetCurrentConnectionInfo = new DvConnectionManager.Delegate_GetCurrentConnectionInfo(GetCurrentConnectionInfoSink);

            Manager.Evented_CurrentConnectionIDs = "";
            //Manager.Evented_PhysicalConnections = "";

            string Sink = "";
            foreach(ProtocolInfoString s in InfoStrings)
            {
                if(Sink=="")
                {
                    Sink = s.ToString();
                }
                else
                {
                    Sink = Sink + "," + s.ToString();
                }
            }

            Manager.Evented_SinkProtocolInfo = Sink;
            Manager.Evented_SourceProtocolInfo = "";

            AVT.Accumulator_LastChange = new InstanceID_LastChangeAccumulator("AVT");
            AVT.ModerationDuration_LastChange = 0.5;
            AVT.Evented_LastChange = "<Event xmlns = "urn:schemas-upnp-org:metadata-1-0/AVT/"/>";

            AVT.External_GetMediaInfo = new DvAVTransport.Delegate_GetMediaInfo(GetMediaInfoSink);
            AVT.External_GetPositionInfo = new DvAVTransport.Delegate_GetPositionInfo(GetPositionInfoSink);
            AVT.External_GetTransportInfo = new DvAVTransport.Delegate_GetTransportInfo(GetTransportInfoSink);
            AVT.External_GetTransportSettings = new DvAVTransport.Delegate_GetTransportSettings(GetTransportSettingsSink);
            AVT.External_GetDeviceCapabilities = new DvAVTransport.Delegate_GetDeviceCapabilities(GetDeviceCapabilitiesSink);
            AVT.External_GetCurrentTransportActions = new DvAVTransport.Delegate_GetCurrentTransportActions(GetCurrentTransportActionsSink);

            AVT.External_Play = new DvAVTransport.Delegate_Play(PlaySink);
            AVT.External_Stop = new DvAVTransport.Delegate_Stop(StopSink);
            AVT.External_Pause = new DvAVTransport.Delegate_Pause(PauseSink);
            AVT.External_Record = new DvAVTransport.Delegate_Record(RecordSink);
            AVT.External_Previous = new DvAVTransport.Delegate_Previous(PreviousSink);
            AVT.External_Next = new DvAVTransport.Delegate_Next(NextSink);
            AVT.External_Seek = new DvAVTransport.Delegate_Seek(SeekSink);
            AVT.External_SetAVTransportURI = new DvAVTransport.Delegate_SetAVTransportURI(SetAVTransportURISink);
            AVT.External_SetNextAVTransportURI = new DvAVTransport.Delegate_SetNextAVTransportURI(SetNextAVTransportURISink);
            AVT.External_SetPlayMode = new DvAVTransport.Delegate_SetPlayMode(SetPlayModeSink);
            AVT.External_SetRecordQualityMode = new DvAVTransport.Delegate_SetRecordQualityMode(SetRecordQualityModeSink);
            AVT.External_Record = new DvAVTransport.Delegate_Record(RecordSink);

            Control.Evented_LastChange = "<Event xmlns = "urn:schemas-upnp-org:metadata-1-0/RCS/"/>";

            Control.Accumulator_LastChange = new InstanceID_LastChangeAccumulator("RCS");
            Control.ModerationDuration_LastChange = 1;

            Control.External_GetMute = new DvRenderingControl.Delegate_GetMute(GetMuteSink);
            Control.External_SetMute = new DvRenderingControl.Delegate_SetMute(SetMuteSink);
            Control.External_GetVolume = new DvRenderingControl.Delegate_GetVolume(GetVolumeSink);
            Control.External_SetVolume = new DvRenderingControl.Delegate_SetVolume(SetVolumeSink);
            Control.External_GetBlueVideoBlackLevel  = new DvRenderingControl.Delegate_GetBlueVideoBlackLevel(GetBlueVideoBlackSink);
            Control.External_GetBlueVideoGain = new DvRenderingControl.Delegate_GetBlueVideoGain(GetBlueVideoGainSink);
            Control.External_SetBlueVideoBlackLevel = new DvRenderingControl.Delegate_SetBlueVideoBlackLevel(SetBlueVideoBlackSink);
            Control.External_SetBlueVideoGain = new DvRenderingControl.Delegate_SetBlueVideoGain(SetBlueVideoGainSink);
            Control.External_GetGreenVideoBlackLevel  = new DvRenderingControl.Delegate_GetGreenVideoBlackLevel(GetGreenVideoBlackSink);
            Control.External_GetGreenVideoGain = new DvRenderingControl.Delegate_GetGreenVideoGain(GetGreenVideoGainSink);
            Control.External_SetGreenVideoBlackLevel = new DvRenderingControl.Delegate_SetGreenVideoBlackLevel(SetGreenVideoBlackSink);
            Control.External_SetGreenVideoGain = new DvRenderingControl.Delegate_SetGreenVideoGain(SetGreenVideoGainSink);
            Control.External_GetRedVideoBlackLevel  = new DvRenderingControl.Delegate_GetRedVideoBlackLevel(GetRedVideoBlackSink);
            Control.External_GetRedVideoGain = new DvRenderingControl.Delegate_GetRedVideoGain(GetRedVideoGainSink);
            Control.External_SetRedVideoBlackLevel = new DvRenderingControl.Delegate_SetRedVideoBlackLevel(SetRedVideoBlackSink);
            Control.External_SetRedVideoGain = new DvRenderingControl.Delegate_SetRedVideoGain(SetRedVideoGainSink);
            Control.External_GetBrightness = new DvRenderingControl.Delegate_GetBrightness(GetBrightnessSink);
            Control.External_SetBrightness = new DvRenderingControl.Delegate_SetBrightness(SetBrightnessSink);
            Control.External_GetContrast = new DvRenderingControl.Delegate_GetContrast(GetContrastSink);
            Control.External_SetContrast = new DvRenderingControl.Delegate_SetContrast(SetContrastSink);
            Control.External_GetSharpness = new DvRenderingControl.Delegate_GetSharpness(GetSharpnessSink);
            Control.External_SetSharpness = new DvRenderingControl.Delegate_SetSharpness(SetSharpnessSink);

            Control.External_ListPresets = new DvRenderingControl.Delegate_ListPresets(ListPresetsSink);
            Control.External_SelectPreset = new DvRenderingControl.Delegate_SelectPreset(SelectPresetSink);

            device.Manufacturer = "OpenSource";
            device.ManufacturerURL = "";
            device.PresentationURL = "/";
            device.HasPresentation = false;
            device.ModelName = "Renderer";
            device.ModelDescription = "AV Media Renderer Device";
            device.ModelURL = new Uri("http://www.sourceforge.org");
            device.StandardDeviceType = "MediaRenderer";

            device.AddService(Manager);
            device.AddService(Control);
            device.AddService(AVT);

            if(ConnectionMax == 0)
            {
                Manager.Evented_CurrentConnectionIDs = "0";
                CurrentConnections = 1;
                AVConnection c = new AVConnection(this, "", "/", -1, DvConnectionManager.Enum_A_ARG_TYPE_Direction.INPUT, 0, 0, 0);
                c.Parent = this;
                c._WhoCreatedMe = new IPEndPoint(IPAddress.Parse("127.0.0.1"),0);
                ID_Table[(UInt32)0] = c;
                if(h!=null) h(this,c);
            }
        }
        protected void PrepareForConnectionSink(System.String RemoteProtocolInfo, System.String PeerConnectionManager, int PeerConnectionID, DvConnectionManager.Enum_A_ARG_TYPE_Direction Direction, out System.Int32 ConnectionID, out System.Int32 AVTransportID, out System.Int32 RcsID)
        {
            bool OK = false;
            ConnectionID = 0;
            string EventString = "";

            foreach(ProtocolInfoString s in InfoStrings)
            {
                if(s.Equals(new ProtocolInfoString(RemoteProtocolInfo)))
                {
                    OK = true;
                    break;
                }
            }

            if(OK==false)
            {
                // We don't support this protocol Info;
                throw(new UPnPCustomException(801,RemoteProtocolInfo + " NOT supported"));
            }

            OK = false;
            if(ManualPrepareForConnection!=null)
            {
                try
                {
                    ConnectionID = ManualPrepareForConnection(this,new ProtocolInfoString(RemoteProtocolInfo));
                    OK = true;
                    ID_Table[(UInt32)ConnectionID] = "";
                }
                catch(PrepareForConnectionFailedException pfcfe)
                {
                    throw(new UPnPCustomException(800,pfcfe.Message));
                }
            }

            lock(ConnectionLock)
            {
                if(OK==false)
                {
                    if(CurrentConnections<ConnectionMax)
                    {
                        ++ CurrentConnections;
                        Random r = new Random();
                        do
                        {
                            ConnectionID = r.Next(4096,65535);
                        }while(ID_Table.ContainsKey(ConnectionID)==true);
                        ID_Table[(UInt32)ConnectionID] = "";
                        OK = true;
                    }
                    else
                    {
                        OK = false;
                    }
                }
                if(OK==true)
                {
                    // BuildEventString
                    IDictionaryEnumerator KEYS = ID_Table.GetEnumerator();
                    while(KEYS.MoveNext())
                    {
                        if(EventString=="")
                        {
                            EventString = KEYS.Key.ToString();
                        }
                        else
                        {
                            EventString = EventString + "," + KEYS.Key.ToString();
                        }
                    }
                }
            }

            if(OK==false) throw(new UPnPCustomException(800,"No more resources"));

            AVTransportID = (int)ConnectionID;
            RcsID = (int)ConnectionID;

            AVConnection c = new AVConnection(this, RemoteProtocolInfo, PeerConnectionManager, PeerConnectionID, Direction, ConnectionID, AVTransportID, RcsID);
            c._WhoCreatedMe = AVT.GetCaller();

            ID_Table[(UInt32)ConnectionID] = c;

            Manager.Evented_CurrentConnectionIDs = EventString;

            if(OnNewConnection!=null) OnNewConnection(this,c);
        }
        public AVConnection(AVRenderer _parent, System.String RemoteProtocolInfo, System.String PeerConnectionManager, int PeerConnectionID, DvConnectionManager.Enum_A_ARG_TYPE_Direction Direction, System.Int32 ConnectionID, System.Int32 AVTransportID, System.Int32 RcsID)
        {
            Parent = _parent;
            foreach(string V in DvRenderingControl.Values_A_ARG_TYPE_Channel)
            {
                MuteChannelTable[V] = false;
                VolumeChannelTable[V] = (UInt16)0;
            }

            _InfoString = new ProtocolInfoString(RemoteProtocolInfo);
            _PeerManager = PeerConnectionManager;
            _PeerManagerID = PeerConnectionID;
            Connection_ID = ConnectionID;
            AVTransport_ID = AVTransportID;
            RenderingControl_ID = RcsID;
            _Direction = Direction;
        }
 protected void GetCurrentConnectionInfoSink(System.Int32 ConnectionID, out System.Int32 RcsID, out System.Int32 AVTransportID, out System.String ProtocolInfo, out System.String PeerConnectionManager, out System.Int32 PeerConnectionID, out DvConnectionManager.Enum_A_ARG_TYPE_Direction Direction, out DvConnectionManager.Enum_A_ARG_TYPE_ConnectionStatus Status)
 {
     if(ID_Table.ContainsKey((UInt32)ConnectionID)==false)
     {
         throw(new UPnPCustomException(802,ConnectionID.ToString() + " is not a valid ID"));
     }
     else
     {
         AVConnection c = (AVConnection)ID_Table[(UInt32)ConnectionID];
         RcsID = c.RenderingControl_ID;
         AVTransportID = c.AVTransport_ID;
         ProtocolInfo = c.InfoString.ToString();
         PeerConnectionManager = c.PeerConnectionManager;
         PeerConnectionID = c.PeerConnectionManagerID;
         Direction = c._Direction;
         Status = c._Status;
     }
 }
            /// <summary>
            /// Constructor - requires all of the information before the connection is created.
            /// </summary>
            /// <param name="id"></param>
            /// <param name="peerId"></param>
            /// <param name="rcs"></param>
            /// <param name="avt"></param>
            /// <param name="prot"></param>
            /// <param name="peer"></param>
            /// <param name="dir"></param>
            /// <param name="status"></param>
            /// <exception cref="ApplicationException">
            /// Thrown if the proposed connection ID is less than zero.
            /// </exception>
            public Connection(int id, int peerId, int rcs, int avt, ProtocolInfoString prot, string peer, DvConnectionManager.Enum_A_ARG_TYPE_Direction dir, DvConnectionManager.Enum_A_ARG_TYPE_ConnectionStatus status)
            {
                if (id < 0)
                {
                    throw new ApplicationException("ConnectionId cannot be negative.");
                }

                ConnectionId = id;
                PeerConnectionId = peerId;
                RcsId = rcs;
                AVTransportId = avt;
                ProtocolInfo = prot;
                PeerConnectionManager = peer;
                Direction = dir;
                Status = status;
            }
        /// <summary>
        /// Constructor instantiates a properly behaving UPnP-AV
        /// MediaServer device that has a root container.
        /// </summary>
        /// <param name="info">general information about the MediaServer like manufacturer info</param>
        /// <param name="isRootDevice">true if the MediaServer has no parent UPnP device</param>
        /// <param name="enableHttpContentServing">
        /// True, if the MediaServer should support the <see cref="MediaResource.AUTOMAPFILE"/>
        /// convention.
        /// </param>
        /// <param name="initialSourceProtocolInfoSet">
        /// Comma separated value list of protocolInfo strings for this MediaServer as a source.
        /// "HTTP-GET:*:*:*" is also allowed, indicating that any HTTP-GET resource is supported on the server.
        /// Generally, this value should be true unless the application logic for the
        /// MediaServer will always create resource objects with fully pathed URIs that are
        /// accessible from the UPNP network.
        /// </param>
        /// <param name="initialSinkProtocolInfoSet">
        /// Comma separated value list of protocolInfo strings for this MediaServer as a sink.
        /// This should generally be blank although it may be possible to eventually 
        /// migrate this implementation to behave both as a MediaRenderer and a MediaServer,
        /// although there may be subtleties that make such a device impossible.
        /// </param>
        public MediaServerDevice(
			DeviceInfo info,
			UPnPDevice parent,
			bool enableHttpContentServing,
			string initialSourceProtocolInfoSet,
			string initialSinkProtocolInfoSet
			)
        {
            // enable HTTP webserving of HTTP-GET resource/content?
            this.EnableHttp = enableHttpContentServing;

            // Wire up the delegate and weak event used when an HTTP transfer should be
            // removed from the server's list.
            // When an HTTP transfer completes it's progress info still needs to be
            // available for GetTransferProgress action for at least 30 seconds.
            // LifeTimeMonitor will delay the removal for such a time, and then
            // execute the delegate.
            this.LTMDelegate = new LifeTimeMonitor.LifeTimeHandler(this.Sink_OnExpired);
            this.m_LFT.OnExpired += LTMDelegate;

            // Create the UPnP device object - no servics are attached yet
            if (parent == null)
            {
                this.Device = UPnPDevice.CreateRootDevice(info.CacheTime, 1.0, info.LocalRootDirectory);
                if(info.CustomUDN!="")
                {
                    this.Device.UniqueDeviceName = info.CustomUDN;
                }
            }
            else
            {
                Guid udn = System.Guid.NewGuid();
                this.Device = UPnPDevice.CreateEmbeddedDevice(1.0, udn.ToString());
                parent.AddDevice(this.Device);
            }

            // transfer basic info about the device, like serial #, manufacturer, etc.
            this.Device.HasPresentation = false;
            this.Device.StandardDeviceType = "MediaServer";

            this.Device.FriendlyName		= info.FriendlyName;
            this.Device.Manufacturer		= info.Manufacturer;
            this.Device.ManufacturerURL	= info.ManufacturerURL;
            this.Device.ModelName			= info.ModelName;
            this.Device.ModelDescription	= info.ModelDescription;
            if (info.ModelURL != null)
            {
                try
                {
                    this.Device.ModelURL			= new Uri(info.ModelURL);
                }
                catch
                {
                    this.Device.ModelURL = null;
                }
            }
            this.Device.ModelNumber		= info.ModelNumber;

            if (info.INMPR03)
            {
                this.Device.AddCustomFieldInDescription("INMPR03", "1.0", "");
            }

            this.ConnectionManager = new DvConnectionManager();
            this.ContentDirectory = new DvContentDirectory();

            // Set periodic behavior for the moderated state variables.
            // Only state variables that do not overwrite a pending
            // value need an accumulator.
            //
            this.ContentDirectory.ModerationDuration_SystemUpdateID = 2;
            this.ContentDirectory.ModerationDuration_ContainerUpdateIDs = 2;
            this.ContentDirectory.Accumulator_ContainerUpdateIDs = new Accumulator_ContainerUpdateIDs();

            // Determine whether the application logic actually
            // wants control points to have access to content management
            // related methods. If not, then remove those actions.
            if (info.AllowRemoteContentManagement==false)
            {
                this.ContentDirectory.RemoveAction_CreateObject();
                this.ContentDirectory.RemoveAction_CreateReference();
                this.ContentDirectory.RemoveAction_DeleteResource();
                this.ContentDirectory.RemoveAction_DestroyObject();
                this.ContentDirectory.RemoveAction_ImportResource();
                this.ContentDirectory.RemoveAction_UpdateObject();
                this.ContentDirectory.RemoveAction_ExportResource();
                this.ContentDirectory.RemoveAction_GetTransferProgress();
                this.ContentDirectory.RemoveAction_StopTransferResource();
            }

            if (info.EnablePrepareForConnection==false)
            {
                this.ConnectionManager.RemoveAction_PrepareForConnection();
            }

            if (info.EnableConnectionComplete==false)
            {
                this.ConnectionManager.RemoveAction_ConnectionComplete();
            }

            if (
                (info.EnablePrepareForConnection==false) &&
                (info.EnableConnectionComplete==false)
                )
            {
                ProtocolInfoString protInfo = new ProtocolInfoString("http-get:*:*:*");
                DvConnectionManager.Enum_A_ARG_TYPE_ConnectionStatus status = DvConnectionManager.Enum_A_ARG_TYPE_ConnectionStatus.UNKNOWN;

                Connection newConnection = new Connection(GetConnectionID(), -1, -1, -1, protInfo, "/", OpenSource.UPnP.AV.DvConnectionManager.Enum_A_ARG_TYPE_Direction.OUTPUT, OpenSource.UPnP.AV.DvConnectionManager.Enum_A_ARG_TYPE_ConnectionStatus.UNKNOWN);
                this.AddConnection(newConnection);
            }

            if (info.EnableSearch == false)
            {
                this.ContentDirectory.RemoveAction_Search();
            }

            this.m_SearchCapabilities = info.SearchCapabilities;
            this.m_SortCapabilities = info.SortCapabilities;

            //AVTransport and RendererControl not used...yet.
            //this.m_AVTransports = new ArrayList();
            //this.m_RenderingControls = new ArrayList();

            // Set values for each state variable
            //
            if (this.ConnectionManager.Evented_CurrentConnectionIDs == null)
            {
                this.ConnectionManager.Evented_CurrentConnectionIDs = "";
            }

            // this state variable does not exist until UPNP-AV 1.1
            //this.ConnectionManager.Evented_PhysicalConnections = "";

            // have the device advertise the protocolInfo strings for
            // this media server
            this.UpdateProtocolInfoSet(false, initialSinkProtocolInfoSet);
            this.UpdateProtocolInfoSet(true, initialSourceProtocolInfoSet);

            // initialize state varaibles
            this.ContentDirectory.Evented_ContainerUpdateIDs = "";
            this.ContentDirectory.Evented_SystemUpdateID = 0;
            this.ContentDirectory.Evented_TransferIDs = "";

            // Wire up the ContentDirectory and ConnectionManager actions to actual methods
            // in this class that will actually do the work.
            this.ConnectionManager.External_ConnectionComplete			= new DvConnectionManager.Delegate_ConnectionComplete(this.SinkCm_ConnectionComplete);
            this.ConnectionManager.External_GetCurrentConnectionIDs		= new DvConnectionManager.Delegate_GetCurrentConnectionIDs(this.SinkCm_GetCurrentConnectionIDs);
            this.ConnectionManager.External_GetCurrentConnectionInfo	= new DvConnectionManager.Delegate_GetCurrentConnectionInfo(this.SinkCm_GetCurrentConnectionInfo);
            this.ConnectionManager.External_GetProtocolInfo				= new DvConnectionManager.Delegate_GetProtocolInfo(this.SinkCm_GetProtocolInfo);
            this.ConnectionManager.External_PrepareForConnection		= new DvConnectionManager.Delegate_PrepareForConnection(this.SinkCm_PrepareForConnection);

            this.ContentDirectory.External_Browse					= new DvContentDirectory.Delegate_Browse(this.SinkCd_Browse);
            this.ContentDirectory.External_CreateObject				= new DvContentDirectory.Delegate_CreateObject(this.SinkCd_CreateObject);
            this.ContentDirectory.External_CreateReference			= new DvContentDirectory.Delegate_CreateReference(this.SinkCd_CreateReference);
            this.ContentDirectory.External_DeleteResource			= new DvContentDirectory.Delegate_DeleteResource(this.SinkCd_DeleteResource);
            this.ContentDirectory.External_DestroyObject			= new DvContentDirectory.Delegate_DestroyObject(this.SinkCd_DestroyObject);
            this.ContentDirectory.External_ExportResource			= new DvContentDirectory.Delegate_ExportResource(this.SinkCd_ExportResource);
            this.ContentDirectory.External_GetSearchCapabilities	= new DvContentDirectory.Delegate_GetSearchCapabilities(this.SinkCd_GetSearchCapabilities);
            this.ContentDirectory.External_GetSortCapabilities		= new DvContentDirectory.Delegate_GetSortCapabilities(this.SinkCd_GetSortCapabilities);
            this.ContentDirectory.External_GetSystemUpdateID		= new DvContentDirectory.Delegate_GetSystemUpdateID(this.SinkCd_GetSystemUpdateID);
            this.ContentDirectory.External_GetTransferProgress		= new DvContentDirectory.Delegate_GetTransferProgress(this.SinkCd_GetTransferProgress);
            this.ContentDirectory.External_ImportResource			= new DvContentDirectory.Delegate_ImportResource(this.SinkCd_ImportResource);
            this.ContentDirectory.External_Search					= new DvContentDirectory.Delegate_Search(this.SinkCd_Search);
            this.ContentDirectory.External_StopTransferResource		= new DvContentDirectory.Delegate_StopTransferResource(this.SinkCd_StopTransferResource);
            this.ContentDirectory.External_UpdateObject				= new DvContentDirectory.Delegate_UpdateObject(this.SinkCd_UpdateObject);

            // add the services to the device - voila, it's now a useful device
            this.Device.AddService(this.ConnectionManager);
            this.Device.AddService(this.ContentDirectory);

            // set up a virtual directory for local webserving - we'll always
            // have this here, even if HTTP webserving is not enabled because
            // it really doesn't hurt to have the virtual directory.
            Interlocked.Increment(ref VirtualDirCounter);
            m_VirtualDirName = "MediaServerContent_" + VirtualDirCounter.ToString();
            this.Device.AddVirtualDirectory(m_VirtualDirName, new UPnPDevice.VirtualDirectoryHandler(this.WebServer_OnHeaderReceiveSink), new UPnPDevice.VirtualDirectoryHandler(this.WebServer_OnPacketReceiveSink));

            // create the root container for this media server's content hierarchy.
            // Prevent control points from modifying this root container or
            // creating new objects in the root.
            // Also need to wire up internally visible events so that the MediaServer
            // will properly event changes in the content hierarchy.
            MediaBuilder.container rootInfo = new MediaBuilder.container("Root");
            rootInfo.Searchable = true;
            rootInfo.IsRestricted = true;
            this.m_Root = (DvRootContainer) DvMediaBuilder.CreateRoot(rootInfo);
            this.m_Root.OnContainerChanged += new DvRootContainer.Delegate_OnContainerChanged(this.Sink_ContainerChanged);

            // At this point the device is ready to go... simply call the Start()
            // method to have the device advertise itself.
        }
        /// <summary>
        /// Method ensures that the protocolInfo for a PrepareForConnection request
        /// matches up correctly with a supported protocol on the device.
        /// The check is a trivial check and nothing more.
        /// <see cref="MediaServerDevice.SinkCm_PrepareForConnection"/>
        /// will do additional checks to ensure that the entire request is correct.
        /// </summary>
        /// <param name="protInfo">protocolInfo string proposed in the request</param>
        /// <param name="dir">direction of the stream, relative to the server</param>
        private void ValidateConnectionRequest(ProtocolInfoString protInfo, DvConnectionManager.Enum_A_ARG_TYPE_Direction dir)
        {
            bool incompatibleProtocol = true;

            // Grab the correct protocolInfo set, depending on whether
            // the stream is supposed to be a source or a sink.
            ArrayList al;
            if (dir == DvConnectionManager.Enum_A_ARG_TYPE_Direction.INPUT)
            {
                al = this.m_SinkProtocolInfoSet;
            }
            else if (dir == DvConnectionManager.Enum_A_ARG_TYPE_Direction.OUTPUT)
            {
                al = this.m_SourceProtocolInfoSet;
            }
            else
            {
                throw new Error_InvalidDirection("");
            }

            // Compare the requested protocol info string against the
            // list of available ones.
            //
            foreach (ProtocolInfoString prot in al)
            {
                if (protInfo.Matches(prot))
                {
                    incompatibleProtocol = false;
                    break;
                }
            }

            if (incompatibleProtocol)
            {
                throw new Error_IncompatibleProtocolInfo("("+protInfo.ToString()+")");
            }
        }
        /// <summary>
        /// Method executes when a control point invokes the ConnectionManager.PrepareForConnection action.
        /// The method will attempt to validate the connection request, reporting an error if
        /// the connection type is not supported. If the connection type is supported, but
        /// it is not based on HTTP-GET we execute the <see cref="MediaServerDevice.OnCallPrepareForConnection"/>
        /// delegate and ask upper-layer software to accept or reject the request.
        /// If the upper-layer is to reject, then it must throw a UPnPCustomException() that provides
        /// a reason for the failure.
        /// </summary>
        /// <param name="RemoteProtocolInfo">The protocolInfo string that identifies transport/network/mime-type/info for the proposed connection.</param>
        /// <param name="PeerConnectionManager">The UDN/Service-ID of the ConnectionManager service at the other end of the connection.</param>
        /// <param name="PeerConnectionID">The connection ID returned by the PrepareForConnection invocation on the other endpoint. Can be empty if unknown.</param>
        /// <param name="Direction">Should generally by OUTPUT.</param>
        /// <param name="ConnectionID">Returns ConnectionID used by this mediaserver to represent the new connection.</param>
        /// <param name="AVTransportID">
        /// Returns AVTransport instance ID used by this mediaserver to represent the new connection.
        /// Value is -1 for HTTP-GET content on a server.
        /// </param>
        /// <param name="RcsID">
        /// Returns RendererControl instance ID used by this mediaserver to represent the new connection.
        /// Value is -1 for HTTP-GET content on a server.
        /// </param>
        private void SinkCm_PrepareForConnection(System.String RemoteProtocolInfo, System.String PeerConnectionManager, System.Int32 PeerConnectionID, DvConnectionManager.Enum_A_ARG_TYPE_Direction Direction, out System.Int32 ConnectionID, out System.Int32 AVTransportID, out System.Int32 RcsID)
        {
            bool ownerProvidesIdInfo = true;
            ProtocolInfoString protInfo = new ProtocolInfoString(RemoteProtocolInfo);

            // Throw an exception if the protocol and direction are not supported by this device.
            //
            ValidateConnectionRequest(protInfo, Direction);

            // If the instance is configured to serve local HTTP content,
            // then we intercept any PrepareForConnection() invocation
            // that involves HTTP-GET / OUTPUT and create a new ConnectionID,
            // and provide -1 for AVT and RCS instance IDs.
            //
            // In all other cases, we fire an event asking the owner to
            // provide this information.
            //
            if ((this.EnableHttp) && (String.Compare(protInfo.Protocol, "http-get", true) == 0) && (Direction == DvConnectionManager.Enum_A_ARG_TYPE_Direction.OUTPUT))
            {
                ownerProvidesIdInfo = false;
            }

            // Obtain a valid connection ID regardless of whether the owner will provide
            // an AVTransportID and/or a RcsID.
            //
            ConnectionID = GetConnectionID();
            DvConnectionManager.Enum_A_ARG_TYPE_ConnectionStatus status = DvConnectionManager.Enum_A_ARG_TYPE_ConnectionStatus.UNKNOWN;

            if (ownerProvidesIdInfo)
            {
                if (this.OnCallPrepareForConnection != null)
                {
                    // Application logic needs to provide a instance IDs for AVTransport and Rendering Control services, as well as
                    // an initial value for the status.
                    this.OnCallPrepareForConnection(RemoteProtocolInfo, PeerConnectionManager, Direction, out AVTransportID, out RcsID, out status);
                }
                else
                {
                    throw new Error_InvalidServerConfiguration("PrepareForConnection() cannot be supported until the vendor configures the server correctly.");
                }
            }
            else
            {
                AVTransportID = -1;
                RcsID = -1;
            }

            Connection newConnection = new Connection((int)ConnectionID, PeerConnectionID, RcsID, AVTransportID, protInfo, PeerConnectionManager, Direction, status);
            this.AddConnection(newConnection);
            this.m_Stats.PrepareForConnection++;
            this.FireStatsChange();
        }
        /// <summary>
        /// Method executes when a control point invokes the ConnectionManager.GetCurrentConnectionInfo action.
        /// The method will attempt to find the Renderercontrol, AVTransport, peer connection, and other 
        /// information about a specified connection. If it fails, we report that the
        /// specified connection doesn't exist.
        /// </summary>
        /// <param name="ConnectionID">Find info about a connection with this ID.</param>
        /// <param name="RcsID">Return a RendererControl instance ID for the connection.</param>
        /// <param name="AVTransportID">Return a AVTransport instance ID for the connection.</param>
        /// <param name="ProtocolInfo">Return the protocolInfo string used at connection creation time.</param>
        /// <param name="PeerConnectionManager">Return the ConnectionManager UDN/service ID for the connection.</param>
        /// <param name="PeerConnectionID">Return the Connection ID used by the peer ConnectionManager for this connection.</param>
        /// <param name="Direction">Return the input/output value for this server's role. Should be output.</param>
        /// <param name="Status">Returns connection status information.</param>
        private void SinkCm_GetCurrentConnectionInfo(System.Int32 ConnectionID, out System.Int32 RcsID, out System.Int32 AVTransportID, out System.String ProtocolInfo, out System.String PeerConnectionManager, out System.Int32 PeerConnectionID, out DvConnectionManager.Enum_A_ARG_TYPE_Direction Direction, out DvConnectionManager.Enum_A_ARG_TYPE_ConnectionStatus Status)
        {
            if (m_Connections.ContainsKey(ConnectionID))
            {
                Connection c = (Connection) m_Connections[ConnectionID];

                RcsID = c.RcsId;
                AVTransportID = c.AVTransportId;
                ProtocolInfo = c.ProtocolInfo.ToString();
                PeerConnectionManager = c.PeerConnectionManager;
                PeerConnectionID = c.PeerConnectionId;
                Direction = c.Direction;
                Status = c.Status;
            }
            else
            {
                throw new Error_InvalidConnection("("+ConnectionID+")");
            }
            this.m_Stats.GetCurrentConnectionInfo++;
            this.FireStatsChange();
        }
Example #10
0
 internal _DvConnectionManager(DvConnectionManager n)
 {
     Outer = n;
     S = BuildUPnPService();
 }
 internal _DvConnectionManager(DvConnectionManager n)
 {
     Outer = n;
     S     = BuildUPnPService();
 }