Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Initialize an instance of NanoClient
 /// </summary>
 /// <param name="address">Console IP address string</param>
 /// <param name="session">Gamestream session from BroadcastChannel</param>
 public NanoClient(string address, GamestreamSession session)
     : this(address, session.TcpPort, session.UdpPort, session.Config, session.SessionId)
 {
 }
Ejemplo n.º 3
0
 /// <summary>
 /// Initialize an instance of NanoClient
 /// </summary>
 /// <param name="address">Console IP address</param>
 /// <param name="session">Gamestream session from BroadcastChannel</param>
 public NanoClient(IPAddress address, GamestreamSession session)
     : this(address.ToString(), session)
 {
 }
        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);
        }
Ejemplo n.º 5
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();
        }
Ejemplo n.º 6
0
        static void Main(string[] args)
        {
            var printHelp     = false;
            var fullscreen    = false;
            var useController = false;
            var ipAddress     = String.Empty;
            var tokenPath     = String.Empty;

            var p = new OptionSet {
                { "h|?|help", "Show this help and exit", v => printHelp = v != null },
                { "fullscreen", "Start in fullscreen mode", v => fullscreen = v != null },
                { "controller", "Use controller on this device", v => useController = v != null },
                { "a|address=", "Specify {IP ADDRESS} of target console", v =>
                  {
                      if (!VerifyIpAddress(v))
                      {
                          throw new OptionException("Invalid IP Address", "address");
                      }
                      ipAddress = v;
                  } },
                { "t|token=", "Specify {TOKEN FILEPATH} for connecting authenticated", v =>
                  {
                      if (!File.Exists(v))
                      {
                          throw new OptionException("Invalid tokenpath", "token");
                      }
                      tokenPath = v;
                  } }
            };

            List <string> extraArgs;

            try
            {
                extraArgs = p.Parse(args);
            }
            catch (OptionException e)
            {
                Console.WriteLine($"Failed parsing parameter \'{e.OptionName}\': {e.Message}");
                Console.WriteLine("Try 'SmartGlass.Nano.FFmpeg --help' for more information");
                return;
            }

            if (printHelp || String.IsNullOrEmpty(ipAddress))
            {
                Console.WriteLine("Usage: SmartGlass.Nano.FFmpeg [parameters]");
                Console.WriteLine("Gamestream from xbox one");
                Console.WriteLine();
                Console.WriteLine("Parameters:");
                p.WriteOptionDescriptions(Console.Out);
                return;
            }

            if (!Authenticate(tokenPath))
            {
                Console.WriteLine("Connecting anonymously to console, no XBL token available");
            }

            string hostName = ipAddress;

            Console.WriteLine($"Connecting to console {hostName}...");
            GamestreamConfiguration config = GamestreamConfiguration.GetStandardConfig();

            GamestreamSession session = ConnectToConsole(ipAddress, config).GetAwaiter().GetResult();

            if (session == null)
            {
                Console.WriteLine("Failed to connect to console!");
                return;
            }

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

            NanoClient nano = InitNano(hostName, session).GetAwaiter().GetResult();

            if (nano == null)
            {
                Console.WriteLine("Nano failed!");
                return;
            }

            // SDL / FFMPEG setup
            SdlProducer producer = new SdlProducer(nano, _audioFormat, _videoFormat, fullscreen, useController);

            nano.AudioFrameAvailable += producer.Decoder.ConsumeAudioData;
            nano.VideoFrameAvailable += producer.Decoder.ConsumeVideoData;

            producer.MainLoop();

            // finally (dirty)
            Process.GetCurrentProcess().Kill();
        }
Ejemplo n.º 7
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();
        }