public static async Task <NanoClient> InitNano(string ipAddress, GamestreamSession session)
        {
            NanoClient nano = new NanoClient(ipAddress, session);

            try
            {
                // General Handshaking & Opening channels
                await nano.InitializeProtocolAsync();

                await nano.OpenInputChannelAsync(1280, 720);

                // Audio & Video client handshaking
                // Sets desired AV formats
                _audioFormat = nano.AudioFormats[0];
                _videoFormat = nano.VideoFormats[0];

                await nano.InitializeStreamAsync(_audioFormat, _videoFormat);

                // TODO: Send opus audio chat samples to console
                _chatAudioFormat = new AudioFormat(1, 24000, AudioCodec.Opus);
                await nano.OpenChatAudioChannelAsync(_chatAudioFormat);

                // Tell console to start sending AV frames
                await nano.StartStreamAsync();
            }
            catch (Exception e)
            {
                Console.WriteLine($"Failed to init Nano, error: {e}");
                return(null);
            }

            return(nano);
        }
        /*
         * Protocol
         */

        public async Task StartStream(SurfaceTexture surface)
        {
            System.Diagnostics.Debug.WriteLine($"Connecting to console...");

            _smartGlassClient = await SmartGlassClient.ConnectAsync(_hostName);

            // Get general gamestream configuration
            var config = GamestreamConfiguration.GetStandardConfig();

            /* Modify standard config, if desired */

            var broadcastChannel = _smartGlassClient.BroadcastChannel;
            var session          = await broadcastChannel.StartGamestreamAsync(config);

            System.Diagnostics.Debug.WriteLine(
                $"Connecting to Nano, TCP: {session.TcpPort}, UDP: {session.UdpPort}");

            _nanoClient = new NanoClient(_hostName, session);

            // General Handshaking & Opening channels
            await _nanoClient.InitializeProtocolAsync();

            // Audio & Video client handshaking
            // Sets desired AV formats
            Packets.AudioFormat audioFormat = _nanoClient.AudioFormats[0];
            Packets.VideoFormat videoFormat = _nanoClient.VideoFormats[0];
            await _nanoClient.InitializeStreamAsync(audioFormat, videoFormat);

            // Start ChatAudio channel
            Packets.AudioFormat chatAudioFormat = new Packets.AudioFormat(1, 24000, AudioCodec.Opus);
            await _nanoClient.OpenChatAudioChannelAsync(chatAudioFormat);

            _mcConsumer = new MediaCoreConsumer(surface, audioFormat, videoFormat);
            _nanoClient.AddConsumer(_mcConsumer);

            // Tell console to start sending AV frames
            await _nanoClient.StartStreamAsync();

            // Start Controller input channel
            await _nanoClient.OpenInputChannelAsync(1280, 720);

            System.Diagnostics.Debug.WriteLine($"Nano connected and running.");
        }
        public override async Task <CommandResult> ExecuteAsync(CancellationToken cancel)
        {
            if (TokenFilePath != null)
            {
                using (FileStream fs = File.Open(TokenFilePath, FileMode.Open))
                {
                    AuthService = await AuthenticationService.LoadFromJsonFileStream(fs);

                    await AuthService.AuthenticateAsync();
                }

                await AuthService.DumpToJsonFileAsync(TokenFilePath);
            }

            Console.WriteLine($"Connecting to {Hostname}...");

            GamestreamSession session = null;
            SmartGlassClient  Client  = null;

            try
            {
                Client = await SmartGlassClient.ConnectAsync(Hostname,
                                                             AuthService == null?null : AuthService.XToken.UserInformation.Userhash,
                                                             AuthService == null?null : AuthService.XToken.Jwt);
            }
            catch (SmartGlassException e)
            {
                Console.WriteLine($"Failed to connect: {e.Message}");
                return(CommandResult.RuntimeFailure);
            }
            catch (TimeoutException)
            {
                Console.WriteLine($"Timeout while connecting");
                return(CommandResult.RuntimeFailure);
            }

            var broadcastChannel = Client.BroadcastChannel;

            var config = GamestreamConfiguration.GetStandardConfig();

            try
            {
                session = await broadcastChannel.StartGamestreamAsync(config);
            }
            catch (Exception e)
            {
                Console.WriteLine($"Failed to send StartGamestream: {e.Message}");
                return(CommandResult.RuntimeFailure);
            }

            Console.WriteLine($"Connecting to Nano, TCP: {session.TcpPort}, UDP: {session.UdpPort}");
            var nano = new NanoClient(Hostname, session);

            try
            {
                Console.WriteLine($"Running protocol init...");
                await nano.InitializeProtocolAsync();

                await nano.OpenInputChannelAsync(1280, 720);

                await nano.OpenChatAudioChannelAsync(
                    new Nano.Packets.AudioFormat(1, 24000, AudioCodec.Opus));

                Console.WriteLine("Adding FileConsumer");
                FileConsumer consumer = new FileConsumer("nanostream");
                nano.AddConsumer(consumer);

                Console.WriteLine("Initializing AV stream (handshaking)...");
                await nano.InitializeStreamAsync(nano.AudioFormats[0],
                                                 nano.VideoFormats[0]);

                Console.WriteLine("Starting stream...");
                await nano.StartStreamAsync();
            }
            catch (Exception e)
            {
                Console.WriteLine($"Failed to initialize gamestream: {e}");
                return(CommandResult.RuntimeFailure);
            }

            Console.WriteLine("Stream is running");

            var loop = new Loop(typeof(SessionCommandType));

            loop.Execute();

            return(CommandResult.Success);
        }
Exemple #4
0
        static void Main(string[] args)
        {
            Native.AllocConsole();

            if (args.Length > 0)
            {
                Config.CurrentMapping.Init(args);
                _tokenFilePath = Config.CurrentMapping.TokenFilePath;
                Authenticate();
            }
            else
            {
                _tokenFilePath = Shell.WriteReadLine("tokenFilePath: ");
                Config.CurrentMapping.TokenFilePath = _tokenFilePath;

                if (File.Exists(_tokenFilePath))
                {
                    Authenticate();
                }
                else
                {
                    Shell.Warning("\'{0}\' file not found.\n", _tokenFilePath);
                    Shell.WriteLine("1) Open following URL in your WebBrowser:\n\n{0}\n\n"
                                    + "2) Authenticate with your Microsoft Account\n"
                                    + "3) Paste returned URL from addressbar: \n"
                                    , AuthenticationService.GetWindowsLiveAuthenticationUrl());

                    Authenticate(Shell.WriteReadLine());
                }

                if (Config.CurrentMapping.IP.Length == 0)
                {
                    Shell.WriteLine("{0,-15} {1,-36} {2,-15} {3,-16}", "Name", "HardwareId", "Address", "LiveId");
                    IEnumerable <Device> devices = Device.DiscoverAsync().GetAwaiter().GetResult();
                    foreach (Device device in devices)
                    {
                        Shell.WriteLine("{0,-15} {1,-36} {2,-15} {3,-16}"
                                        , device.Name
                                        , device.HardwareId
                                        , device.Address
                                        , device.LiveId);
                    }

                    string ip = Shell.WriteReadLine("Input IP Address or hostname: ");
                    Config.CurrentMapping.Init($"{_tokenFilePath} ${ip}");
                }
            }

            // Get general gamestream configuration
            GamestreamConfiguration config = GamestreamConfiguration.GetStandardConfig();

            // Modify standard config, if desired

            /*
             * GAME_STREAMING_VERY_HIGH_QUALITY_SETTINGS: 12000000,1080,60,59,0,10,40,170
             * GAME_STREAMING_HIGH_QUALITY_SETTINGS: 8000000,720,60,59,0,10,40,170
             * GAME_STREAMING_MEDIUM_QUALITY_SETTINGS: 6000002,720,60,3600,0,40,70,200
             * GAME_STREAMING_LOW_QUALITY_SETTINGS: 3000001,480,30,3600,0,40,70,200
             *
             * 12000000 = 12Mbit/s = 12Mbps
             *
             * SETTINGS:
             * Unknown1,Unknown2,Unknown3,Unknown4,Unknown5,Unknown6,Unknown7,Unknown8
             * Unknown1 UrcpMaximumRate         FIXME: Or AudioBufferLengthHns, both??
             * Unknown2 VideoMaximumHeight
             * Unknown3 VideoMaximumFrameRate
             * Unknown4                         FIXME: Which is Unknown4?
             * Unknown5                         FIXME: Which is Unknown5?
             * Unknown6 AudioSyncMinLatency
             * Unknown7 AudioSyncDesiredLatency
             * Unknown8 AudioSyncMaxLatency
             *
             * refer to: https://github.com/OpenXbox/xbox-smartglass-nano-python/issues/7
             * standard: GAME_STREAMING_MEDIUM_QUALITY_SETTINGS
             */
            //config.UrcpMaximumRate = 12000000;// 2后面6个0
            //config.VideoMaximumHeight = 480;
            //config.VideoMaximumFrameRate = 30;
            //config.Unknown4 = 3600;
            //config.Unknown5 = 0;
            //config.AudioSyncMinLatency = 40;
            //config.AudioSyncDesiredLatency = 70;
            //config.AudioSyncMaxLatency = 200;
            config.UrcpMaximumRate       = Config.CurrentMapping.Quality.Unknown1;
            config.VideoMaximumHeight    = Config.CurrentMapping.Quality.Unknown2;
            config.VideoMaximumFrameRate = Config.CurrentMapping.Quality.Unknown3;
            //config.Unknown4 = Config.CurrentMapping.Quality.Unknown4;
            //config.Unknown5 = Config.CurrentMapping.Quality.Unknown5;
            config.AudioSyncMinLatency     = Config.CurrentMapping.Quality.Unknown6;
            config.AudioSyncDesiredLatency = Config.CurrentMapping.Quality.Unknown7;
            config.AudioSyncMaxLatency     = Config.CurrentMapping.Quality.Unknown8;

            config.VideoMaximumWidth = TVResolution.Width(config.VideoMaximumHeight);

            Shell.WriteLine("Connecting to {0}...", Config.CurrentMapping.IP);
            GamestreamSession session = ConnectToConsole(Config.CurrentMapping.IP, config);

            Shell.WriteLine("Connecting to NANO // TCP: {0}, UDP: {1}", session.TcpPort, session.UdpPort);
            Nano = new NanoClient(Config.CurrentMapping.IP, session);
            try
            {
                // General Handshaking & Opening channels
                Shell.WriteLine("Running protocol init...");
                Nano.InitializeProtocolAsync().Wait();

                // Start Controller input channel
                Nano.OpenInputChannelAsync(Nano.Video.Width, Nano.Video.Height).Wait();

                // Audio & Video client handshaking
                // Sets desired AV formats
                AudioFormat = Nano.AudioFormats[0];
                VideoFormat = Nano.VideoFormats[0];

                Shell.WriteLine("Initializing AV stream (handshaking)...");
                Nano.InitializeStreamAsync(AudioFormat, VideoFormat).Wait();

                // Start ChatAudio channel
                // TODO: Send opus audio chat samples to console
                ChatAudioFormat = new AudioFormat(1, 24000, AudioCodec.Opus);
                Nano.OpenChatAudioChannelAsync(ChatAudioFormat).Wait();

                // Tell console to start sending AV frames
                Shell.WriteLine("Starting stream...");
                Nano.StartStreamAsync().Wait();
                Shell.Note("Stream is running");
            }
            catch (Exception e)
            {
                throw Shell.Log("Failed to init Nano, error: {e.Message}", e, e.Message);
            }

#if !DEBUG
            Trace.Listeners.Clear();
            Trace.Listeners.Add(new Logger(_tokenFilePath));
            Native.FreeConsole();
#endif

            // Run a mainloop, to gather controller input events or similar
            Application.SetHighDpiMode(HighDpiMode.SystemAware);
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Xstream());

            // finally (dirty)
            Process.GetCurrentProcess().Kill();
        }
Exemple #5
0
        static void Main()
        {
            AllocConsole();

            Console.Write("tokenFilePath: ");
            string tokenFilePath = Console.ReadLine();

            AuthenticationService auth;

            if (!File.Exists(tokenFilePath))
            {
                Shell.WriteLine("Warning: '{0}' file not found.\n", tokenFilePath);

                string reqURL = AuthenticationService.GetWindowsLiveAuthenticationUrl();

                Console.WriteLine("1) Open following URL in your WebBrowser:\n\n{0}\n\n" +
                                  "2) Authenticate with your Microsoft Account\n" +
                                  "3) Paste returned URL from addressbar: \n", reqURL);

                // Call requestUrl via WebWidget or manually and authenticate

                try
                {
                    string url = Console.ReadLine();
                    WindowsLiveResponse rep = AuthenticationService.ParseWindowsLiveResponse(url);
                    auth = new AuthenticationService(rep);

                    auth.Authenticate();
                }
                catch (Exception e)
                {
                    Shell.WriteLine($"Error: Authentication failed, error: {e.Message}");
                    Shell.PressAnyKeyToContinue();
                    return;
                }

                Console.WriteLine(auth.XToken);
                Console.WriteLine(auth.UserInformation);

                // Save token to JSON

                FileStream tokenOutputFile = null;
                try
                {
                    tokenOutputFile = new FileStream(tokenFilePath, FileMode.Create);
                }
                catch (Exception e)
                {
                    Shell.WriteLine("Error: Failed to open token outputfile \'{0}\', error: {1}",
                                    tokenOutputFile, e.Message);
                    Shell.PressAnyKeyToContinue();
                    return;
                }
                auth.DumpToFile(tokenOutputFile);
                tokenOutputFile.Close();

                Console.WriteLine("Storing tokens to file \'{0}\' on successful auth",
                                  tokenOutputFile.Name);
            }
            else
            {
                // Load token from JSON

                FileStream fs = new FileStream(tokenFilePath, FileMode.Open);
                auth = AuthenticationService.LoadFromFile(fs);
                try
                {
                    auth.Authenticate();
                }
                catch (Exception e)
                {
                    Shell.WriteLine($"Error: Failed to refresh XBL tokens, error: {e.Message}");
                    Shell.PressAnyKeyToContinue();
                    return;
                }
                fs.Close();
            }

            UserHash = auth.XToken.UserInformation.Userhash;
            XToken   = auth.XToken.Jwt;

            Discover().Wait();

            Console.Write("Input IP Address or hostname: ");
            string addressOrHostname = Console.ReadLine();

            Console.WriteLine($"Connecting to {addressOrHostname}...");
            SmartGlassClient client;

            try
            {
                Task <SmartGlassClient> connect = SmartGlassClient.ConnectAsync(
                    addressOrHostname, UserHash, XToken);

                // 如果Task失败了GetAwaiter()会直接抛出异常,而Task.Wait()会抛出AggregateException
                client = connect.GetAwaiter().GetResult();
            }
            catch (Exception e)
            {
                if (e is SmartGlassException)
                {
                    Shell.WriteLine($"Error: Failed to connect: {e.Message}");
                }
                else if (e is TimeoutException)
                {
                    Shell.WriteLine($"Error: Timeout while connecting: {e.Message}");
                }
                else
                {
                    Shell.WriteLine($"Error: {e}");
                }

                Shell.PressAnyKeyToContinue();
                return;
            }

            // Get general gamestream configuration
            GamestreamConfiguration config = GamestreamConfiguration.GetStandardConfig();
            // Modify standard config, if desired

            GamestreamSession session = client.BroadcastChannel.StartGamestreamAsync(config)
                                        .GetAwaiter().GetResult();

            Console.WriteLine($"Connecting to NANO // TCP: {session.TcpPort}, UDP: {session.UdpPort}");

            Console.WriteLine($"Running protocol init...");
            Nano = new NanoClient(addressOrHostname, session);
            try
            {
                // General Handshaking & Opening channels
                Nano.InitializeProtocolAsync().Wait();

                // Start Controller input channel
                Nano.OpenInputChannelAsync(1280, 720).Wait();

                //IConsumer consumer = /* initialize consumer */;
                //nano.AddConsumer(consumer);

                // Start consumer, if necessary
                //consumer.Start();

                // Audio & Video client handshaking
                // Sets desired AV formats
                Console.WriteLine("Initializing AV stream (handshaking)...");

                AudioFormat = Nano.AudioFormats[0];
                VideoFormat = Nano.VideoFormats[0];

                Nano.InitializeStreamAsync(AudioFormat, VideoFormat).Wait();

                // Start ChatAudio channel
                // TODO: Send opus audio chat samples to console
                ChatAudioFormat = new AudioFormat(1, 24000, AudioCodec.Opus);
                Nano.OpenChatAudioChannelAsync(ChatAudioFormat).Wait();

                // Tell console to start sending AV frames
                Console.WriteLine("Starting stream...");

                Nano.StartStreamAsync().Wait();

                Shell.WriteLine("Note: Stream is running");
            }
            catch (Exception e)
            {
                Shell.WriteLine($"Error: Failed to init Nano, error: {e}");
                Shell.PressAnyKeyToContinue();
                return;
            }

            // Run a mainloop, to gather controller input events or similar

            FreeConsole();

            Application.SetHighDpiMode(HighDpiMode.SystemAware);
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Xstream());

            // finally (dirty)
            Process.GetCurrentProcess().Kill();
        }