/// <summary>
 /// Creates a MediaRendererDiscovery, subscribes to add and remove events and runs the start command
 /// </summary>
 public void StartSinkDisco()
 {
     _SinkDisco = new MediaRendererDiscovery();
     _SinkDisco.OnAddedDevice += new MediaRendererDiscovery.DiscoveryHandler(AddSink);
     _SinkDisco.OnRemovedDevice += new MediaRendererDiscovery.DiscoveryHandler(RemoveSink);
     _SinkDisco.Start();
 }
        private static void AddSink(MediaRendererDiscovery sender, UPnPDevice d)
        {
            Console.WriteLine("Added Device: " + d.FriendlyName);

            // To interace with a service, instantiate the appropriate wrapper class on the appropriate service
            // Traverse the device heirarchy to the correct device, and invoke 'GetServices', passing in the static field 'SERVICE_NAME'
            // of the appropriate wrapper class. This method returns an array of all services with this service type. For most purposes,
            // there will only be one service, in which case you can use array index 0.
            // Save a reference to this instance of the wrapper class for later use.
            //CpRenderingControl RenderingControl = new CpRenderingControl(d.GetServices(CpRenderingControl.SERVICE_NAME)[0]);

            // To subscribe to Events, call the '_subscribe' method of the wrapper class. The only parameter is
            // the duration of the event. A good value is 300 seconds.
            //RenderingControl._subscribe(300);

            // The wrapper class exposes all the evented state variables through events in the form 'OnStateVariable_xx', where xx is the variable name.

            // The wrapper class exposes methods in two formats. Asyncronous and Syncronous. The Async method calls are exposed simply
            // by the name of the method. The Syncronous version is the same, except with the word, 'Sync_' prepended to the name.
            // Asyncronous responses to th async method calls are dispatched through the event in the format, 'OnResult_x' where x is the method name.

            // Note: All arguments are automatically type checked. Allowed Values are abstracted through enumerations, that are defined in the wrapper class.
            // To access the list of allowed values or ranges for a given device, refer to the property 'Values_XXX' for a list of the allowed values for a
            // given state variable. Similarly, refer to the properties 'HasMaximum_XXX', 'HasMinimum_XXX', 'Maximum_XXX', and 'Minimum_XXX' where XXX is the variable name, for the Max/Min values.

            // To determine if a given service implements a particular StateVariable or Method, use the properties, 'HasStateVariableXXX' and 'HasActionXXX' where XXX is the method/variable name.
        }
        public MainWindow()
        {
            InitializeComponent();

            disco = new MediaRendererDiscovery();
            disco.OnAddedDevice += new MediaRendererDiscovery.DiscoveryHandler(AddSink);
            disco.OnRemovedDevice += new MediaRendererDiscovery.DiscoveryHandler(RemoveSink);

            disco.Start();
        }
        /// <summary>
        /// Eventfunction that is run when an UPnP sink is detected on the network. Only accepts sinks with the friendly name: "HiPi - Sink". 
        /// If it has the right name then it creates three stacks (AVTransport, ConnectionManager and RenderingControl)
        /// </summary>
        /// <param name="sender">The object that send the event</param>
        /// <param name="d">The discovered sink device</param>
        private void AddSink(MediaRendererDiscovery sender, UPnPDevice d)
        {
            Console.WriteLine("Added Sink Device: " + d.FriendlyName);
            if (d.FriendlyName == "HiPi - Sink")
            {
                UPnP_SinkFunctions func = new UPnP_SinkFunctions(
                    new SinkStack.CpAVTransport(d.GetServices(SinkStack.CpAVTransport.SERVICE_NAME)[0]),
                    new SinkStack.CpConnectionManager(d.GetServices(SinkStack.CpConnectionManager.SERVICE_NAME)[0]),
                    new SinkStack.CpRenderingControl(d.GetServices(SinkStack.CpRenderingControl.SERVICE_NAME)[0]));

                AddSinkEvent(func, null);
            }
        }
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        //[STAThread]
        //static void Main(string[] args)
        void function()
        {
            System.Console.WriteLine("UPnP .NET Framework Stack");
            System.Console.WriteLine("StackBuilder Build#Device Builder Build#1.0.4144.25068");

            MediaRendererDiscovery disco = new MediaRendererDiscovery();
            disco.OnAddedDevice += new MediaRendererDiscovery.DiscoveryHandler(AddSink);
            disco.OnRemovedDevice += new MediaRendererDiscovery.DiscoveryHandler(RemoveSink);

            System.Console.WriteLine("Press return to stop CP.");
            disco.Start();

            System.Console.ReadLine();
        }
        private void AddSink(MediaRendererDiscovery sender, UPnPDevice d)
        {
            MessageBox.Show("Sink detected: " + d.FriendlyName);

            try
            {
                _avTransport = new CpAVTransport(d.GetServices(CpAVTransport.SERVICE_NAME)[0]);

                _avTransport.OnStateVariable_LastChange += new CpAVTransport.StateVariableModifiedHandler_LastChange(Eventer);
            }
            catch (Exception m)
            {
                MessageBox.Show("Couldn't initialize AVTransport: " + m.Message);
            }

            try
            {
                _connectionManagerControl = new CpConnectionManager(d.GetServices(CpConnectionManager.SERVICE_NAME)[0]);
            }
            catch (Exception m)
            {
                MessageBox.Show("Couldn't initialize ConnectionManager: " + m.Message);
            }

            try
            {
                _renderingControl = new CpRenderingControl(d.GetServices(CpRenderingControl.SERVICE_NAME)[0]);
            }
            catch (Exception m)
            {
                MessageBox.Show("Couldn't initialize RenderingControl: " + m.Message);
            }

            //MessageBox.Show(d.DeviceURN);

            //RenderingControl._subscribe(300);
        }
 /// <summary>
 /// NOT IMPLEMENTED. Should remove the sink from the controlpoint. 
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="d"></param>
 private static void RemoveSink(MediaRendererDiscovery sender, UPnPDevice d)
 {
     Console.WriteLine("Removed Device: " + d.FriendlyName);
     //Todo: Remove device somehow
 }