public static int Width(int h) { int w = 0; uint i; // XboxTVResolution if (SupportList.ContainsKey(h)) { return(SupportList[h].W); } // ComputerTVResolution DEVMODE vDevMode = new DEVMODE(); vDevMode.dmSize = (ushort)Marshal.SizeOf(vDevMode); vDevMode.dmDriverExtra = 0; for (i = 0; Native.EnumDisplaySettings(null, i, ref vDevMode); i++) { TVResolution r = new TVResolution(vDevMode.dmPelsWidth, vDevMode.dmPelsHeight); if (H16V9 == r.P && h == r.H && r.Priority) { w = r.W; Debug.Write("+");// 表示命中 } else { Debug.Write("-"); } Debug.WriteLine("{0}x{1} Color:{2} Frequency:{3} AspectRatio[{4}]" , vDevMode.dmPelsWidth , vDevMode.dmPelsHeight , 1L << (int)vDevMode.dmBitsPerPel , vDevMode.dmDisplayFrequency , r.AspectRatio); } return(w != 0 ? w : Width(h, H16V9)); }
public static void AP(this Dictionary <int, TVResolution> d, TVResolution r) => d.Add(TVResolution.Per(r.W, r.H), r);
public static void AH(this Dictionary <int, TVResolution> d, TVResolution r) => d.Add(r.H, r);
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(); }