diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..335007ce2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,15 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Declare files that will always have CRLF line endings on checkout. +*.sln text eol=crlf + +*.c text eol=crlf +*.h text eol=crlf + +*.cpp text eol=crlf +*.cs text eol=crlf +*.xml text eol=crlf +*.xaml text eol=crlf +*.conf text eol=crlf +*.lua text eol=crlf \ No newline at end of file diff --git a/.gitignore b/.gitignore index bf0e316ef..f38939e1d 100644 --- a/.gitignore +++ b/.gitignore @@ -261,5 +261,5 @@ install-build/serverlog.txt install-build/ sign.bat - -.leu + +.leu diff --git a/AutoUpdater/MainWindow.xaml.cs b/AutoUpdater/MainWindow.xaml.cs index 1d6edd669..0723f05ea 100644 --- a/AutoUpdater/MainWindow.xaml.cs +++ b/AutoUpdater/MainWindow.xaml.cs @@ -1,24 +1,14 @@ using System; -using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Net; -using System.Text; +using System.Reflection; using System.Threading; using System.Threading.Tasks; using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Forms; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; using System.Windows.Threading; using Octokit; using MessageBox = System.Windows.MessageBox; @@ -42,6 +32,8 @@ public partial class MainWindow : Window private DispatcherTimer _progressCheckTimer; private double _lastValue = -1; + private bool _finished = false; + private string changelogURL = ""; public MainWindow() @@ -121,7 +113,30 @@ private async Task GetPathToLatestVersion() { changelogURL = release.HtmlUrl; Status.Content = "Downloading Version "+release.TagName; - return new System.Uri(releaseAsset.BrowserDownloadUrl); + + if (ServerInstall()) + { + //check the path and version + var path = ServerPath(); + + if (path.Length > 0) + { + var latestVersion = new Version(release.TagName.Replace("v", "")); + var serverVersion = Assembly.LoadFile(Path.Combine(path, "SR-Server.exe")).GetName().Version; + + if (serverVersion < latestVersion) + { + return new Uri(releaseAsset.BrowserDownloadUrl); + } + else + { + //no update + return null; + } + + } + } + return new Uri(releaseAsset.BrowserDownloadUrl); } } @@ -146,6 +161,36 @@ private bool AllowBeta() } + private string ServerPath() + { + foreach (var commandLineArg in Environment.GetCommandLineArgs()) + { + if (commandLineArg.Trim().StartsWith("-path=")) + { + var line = commandLineArg.Trim(); + line = line.Replace("-path=", ""); + + return line; + } + } + + return ""; + } + + private bool ServerInstall() + { + foreach (var arg in Environment.GetCommandLineArgs()) + { + if (arg.Trim().Equals("-server")) + { + return true; + } + + } + + return false; + } + public void ShowError() { MessageBox.Show("Error Auto Updating SRS - Please check internet connection and try again \n\nAlternatively: \n1. Download the latest DCS-SimpleRadioStandalone.zip from the SRS Github Release page\n2. Extract all the files to a temporary directory\n3. Run the installer.", @@ -162,6 +207,12 @@ public async void DownloadLatestVersion() { _uri = await GetPathToLatestVersion(); + if (_uri == null) + { + Environment.Exit(0); + } + + _directory = GetTemporaryDirectory(); _file = _directory + "\\temp.zip"; @@ -188,7 +239,7 @@ public async void DownloadLatestVersion() private void CheckProgress(object sender, EventArgs e) { - if (_lastValue == DownloadProgress.Value) + if (_lastValue == DownloadProgress.Value && _finished == false) { //no progress ShowError(); @@ -199,23 +250,65 @@ private void CheckProgress(object sender, EventArgs e) } + private bool ShouldRestart() + { + foreach (var arg in Environment.GetCommandLineArgs()) + { + if (arg.Trim().Equals("-restart")) + { + return true; + } + + } + + return false; + } + private void DownloadComplete(object sender, AsyncCompletedEventArgs e) { + _finished = true; if (!_cancel) { ZipFile.ExtractToDirectory(_file, Path.Combine(_directory, "extract")); Thread.Sleep(400); + if (!ServerInstall()) + { + var releaseNotes = MessageBox.Show( + "Do you want to read the release notes? \n\nHighly recommended before installing! \n\n", + "Read Release Notes?", + MessageBoxButton.YesNo, MessageBoxImage.Information); + + if (releaseNotes == MessageBoxResult.Yes) + { + Process.Start(changelogURL); + } + } + ProcessStartInfo procInfo = new ProcessStartInfo(); - procInfo.WorkingDirectory = Path.Combine(_directory, "extract"); - procInfo.Arguments = "-autoupdate"; + procInfo.WorkingDirectory = Path.Combine(_directory, "extract"); + if (ServerInstall()) + { + procInfo.Arguments = "-autoupdate"; + procInfo.Arguments += " -server "; + procInfo.Arguments += " -path=\"" + ServerPath() + "\""; + + if (ShouldRestart()) + { + procInfo.Arguments += " -restart "; + } + } + else + { + procInfo.Arguments = "-autoupdate"; + } procInfo.FileName = Path.Combine(Path.Combine(_directory, "extract"), "installer.exe"); procInfo.UseShellExecute = false; Process.Start(procInfo); - Process.Start(changelogURL); + //Process.Start(changelogURL); } Close(); diff --git a/AutoUpdater/Properties/AssemblyInfo.cs b/AutoUpdater/Properties/AssemblyInfo.cs index 0d9422d12..6a63e3cf5 100644 --- a/AutoUpdater/Properties/AssemblyInfo.cs +++ b/AutoUpdater/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.9.0.1")] -[assembly: AssemblyFileVersion("1.9.0.1")] +[assembly: AssemblyVersion("1.9.0.2")] +[assembly: AssemblyFileVersion("1.9.0.2")] diff --git a/DCS-SR-Client/App.config b/DCS-SR-Client/App.config index 7a4f25331..7b7e2e716 100644 --- a/DCS-SR-Client/App.config +++ b/DCS-SR-Client/App.config @@ -1,8 +1,7 @@  - - + @@ -10,6 +9,14 @@ + + + + + + + + - \ No newline at end of file + diff --git a/DCS-SR-Client/App.xaml.cs b/DCS-SR-Client/App.xaml.cs index 85ae6a6d1..98d79e9bd 100644 --- a/DCS-SR-Client/App.xaml.cs +++ b/DCS-SR-Client/App.xaml.cs @@ -15,6 +15,7 @@ using NLog.Config; using NLog.Targets; using NLog.Targets.Wrappers; +using Sentry; namespace DCS_SR_Client { @@ -29,6 +30,7 @@ public partial class App : Application public App() { + SentrySdk.Init("https://1b22a96cbcc34ee4b9db85c7fa3fe4e3@o414743.ingest.sentry.io/5304752"); AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionHandler); var location = AppDomain.CurrentDomain.BaseDirectory; @@ -59,9 +61,6 @@ public App() ListArgs(); - RequireAdmin(); - - #if !DEBUG if (IsClientRunning()) { @@ -99,6 +98,9 @@ public App() } } #endif + + RequireAdmin(); + InitNotificationIcon(); } @@ -222,21 +224,21 @@ private bool IsClientRunning() private void SetupLogging() { // If there is a configuration file then this will already be set - if(LogManager.Configuration != null) - { + if(LogManager.Configuration != null) + { loggingReady = true; - return; + return; } var config = new LoggingConfiguration(); - var fileTarget = new FileTarget - { - FileName = "clientlog.txt", - ArchiveFileName = "clientlog.old.txt", - MaxArchiveFiles = 1, - ArchiveAboveSize = 104857600, + var fileTarget = new FileTarget + { + FileName = "clientlog.txt", + ArchiveFileName = "clientlog.old.txt", + MaxArchiveFiles = 1, + ArchiveAboveSize = 104857600, Layout = - @"${longdate} | ${logger} | ${message} ${exception:format=toString,Data:maxInnerExceptionLevel=1}" + @"${longdate} | ${logger} | ${message} ${exception:format=toString,Data:maxInnerExceptionLevel=1}" }; var wrapper = new AsyncTargetWrapper(fileTarget, 5000, AsyncTargetWrapperOverflowAction.Discard); diff --git a/DCS-SR-Client/Audio/Providers/CachedLoopingAudioProvider.cs b/DCS-SR-Client/Audio/Providers/CachedLoopingAudioProvider.cs index 5029747fe..a47bf3f67 100644 --- a/DCS-SR-Client/Audio/Providers/CachedLoopingAudioProvider.cs +++ b/DCS-SR-Client/Audio/Providers/CachedLoopingAudioProvider.cs @@ -38,9 +38,9 @@ public int Read(byte[] buffer, int offset, int count) { int read = source.Read(buffer, offset, count); - if (!GlobalSettingsStore.Instance.ProfileSettingsStore.GetClientSettingBool(ProfileSettingsKeys.NATOTone)) - { - return read; + if (!GlobalSettingsStore.Instance.ProfileSettingsStore.GetClientSettingBool(ProfileSettingsKeys.NATOTone)) + { + return read; } var effectBytes = GetEffect(read / 2); @@ -60,8 +60,8 @@ public int Read(byte[] buffer, int offset, int count) buffer[(offset + i) * 2] = byte1; buffer[((i + offset) * 2) + 1] = byte2; - } - + } + return read; } diff --git a/DCS-SR-Client/Audio/Providers/RadioFilter.cs b/DCS-SR-Client/Audio/Providers/RadioFilter.cs index 9856c8235..7647a23e8 100644 --- a/DCS-SR-Client/Audio/Providers/RadioFilter.cs +++ b/DCS-SR-Client/Audio/Providers/RadioFilter.cs @@ -52,16 +52,16 @@ public int Read(float[] buffer, int offset, int sampleCount) { var samplesRead = _source.Read(buffer, offset, sampleCount); if (!_globalSettings.ProfileSettingsStore.GetClientSettingBool(ProfileSettingsKeys.RadioEffects) || samplesRead <= 0) - { - return samplesRead; + { + return samplesRead; } for (var n = 0; n < sampleCount; n++) { var audio = (double) buffer[offset + n]; - if (audio == 0) - { - continue; + if (audio == 0) + { + continue; } // because we have silence in one channel (if a user picks radio left or right ear) we don't want to transform it or it'll play in both diff --git a/DCS-SR-Client/Audio/Utility/SpeexWrapper.cs b/DCS-SR-Client/Audio/Utility/SpeexWrapper.cs index a85eeb3cf..ab6fed671 100644 --- a/DCS-SR-Client/Audio/Utility/SpeexWrapper.cs +++ b/DCS-SR-Client/Audio/Utility/SpeexWrapper.cs @@ -286,7 +286,7 @@ public Preprocessor(int frameSize, int sampleRate) _frameSize = frameSize; _format = new WaveFormat(1, sampleRate); - Reset(); + Reset(); RefreshSettings(true); } @@ -319,7 +319,7 @@ public void Reset() //every 40ms so 500 private int count = 0; - private void RefreshSettings(bool force) + private void RefreshSettings(bool force) { //only check every 5 seconds - 5000/40ms is 125 frames if (count > 125 || force) diff --git a/DCS-SR-Client/DCS-SR-Client.csproj b/DCS-SR-Client/DCS-SR-Client.csproj index ce267753d..9aecef0d9 100644 --- a/DCS-SR-Client/DCS-SR-Client.csproj +++ b/DCS-SR-Client/DCS-SR-Client.csproj @@ -1,499 +1,509 @@ - - - - - Debug - AnyCPU - {CFF33E05-1D37-4807-B1F7-5A1488D8EC4F} - WinExe - Properties - Ciribob.DCS.SimpleRadio.Standalone.Client - SR-ClientRadio - v4.6 - 512 - {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 4 - true - false - - - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - true - - - x64 - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - x64 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - DCS_SR_Client.App - - - - - - - false - - - - audio-headset.ico - - - true - bin\x64\Debug\ - DEBUG;TRACE - full - x64 - prompt - MinimumRecommendedRules.ruleset - true - - - bin\x64\Release\ - - - true - pdbonly - x64 - prompt - MinimumRecommendedRules.ruleset - true - - - - Properties\app.manifest - - - - ..\packages\Costura.Fody.1.6.2\lib\dotnet\Costura.dll - False - - - ..\packages\Easy.MessageHub.3.2.1\lib\net35\Easy.MessageHub.dll - - - ..\packages\MahApps.Metro.1.5.0\lib\net45\MahApps.Metro.dll - - - ..\packages\MathNet.Filtering.0.4.0\lib\net40\MathNet.Filtering.dll - - - ..\packages\MathNet.Numerics.3.8.0\lib\net40\MathNet.Numerics.dll - - - ..\packages\MvvmEventBinding.1.0.0\lib\net45\MvvmEventBinding.dll - True - - - ..\packages\Newtonsoft.Json.11.0.1\lib\net45\Newtonsoft.Json.dll - - - ..\packages\NLog.4.5.8\lib\net45\NLog.dll - - - ..\packages\sharpconfig.3.2.6.1\lib\net20\SharpConfig.dll - - - ..\packages\SharpDX.4.0.1\lib\net45\SharpDX.dll - - - ..\packages\SharpDX.DirectInput.4.0.1\lib\net45\SharpDX.DirectInput.dll - - - - - - - - - - - - - ..\packages\MahApps.Metro.1.5.0\lib\net45\System.Windows.Interactivity.dll - True - - - - - - - - - 4.0 - - - - - - ..\packages\WPFCustomMessageBox.1.0.7\lib\WPFCustomMessageBox.dll - - - ..\packages\Extended.Wpf.Toolkit.3.2.0\lib\net40\Xceed.Wpf.AvalonDock.dll - - - ..\packages\Extended.Wpf.Toolkit.3.2.0\lib\net40\Xceed.Wpf.AvalonDock.Themes.Aero.dll - - - ..\packages\Extended.Wpf.Toolkit.3.2.0\lib\net40\Xceed.Wpf.AvalonDock.Themes.Metro.dll - - - ..\packages\Extended.Wpf.Toolkit.3.2.0\lib\net40\Xceed.Wpf.AvalonDock.Themes.VS2010.dll - - - ..\packages\Extended.Wpf.Toolkit.3.2.0\lib\net40\Xceed.Wpf.DataGrid.dll - - - ..\packages\Extended.Wpf.Toolkit.3.2.0\lib\net40\Xceed.Wpf.Toolkit.dll - - - - - MSBuild:Compile - Designer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - True - Resources.resx - - - - - - - - - - - - ClientListWindow.xaml - - - RadioCapabilities.xaml - - - TransponderPanel.xaml - - - InputBindingControl.xaml - - - - - - - - - InputProfileWindow.xaml - - - PresetChannelsView.xaml - - - - RadioChannelConfigUI.xaml - - - - AwacsIntercomControlGroup.xaml - - - AwacsRadioControlGroup.xaml - - - AwacsOverlay.xaml - - - - FavouriteServersView.xaml - - - - IntercomControlGroup.xaml - - - RadioControlGroup.xaml - - - - RadioOverlay.xaml - - - - - ServerSettingsWindow.xaml - - - - - - - - - - - - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - App.xaml - Code - - - - MainWindow.xaml - Code - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - MSBuild:Compile - Designer - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - MSBuild:Compile - Designer - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - - - Code - - - True - Settings.settings - True - - - PublicResXFileCodeGenerator - Resources.Designer.cs - Designer - - - PreserveNewest - - - Always - - - Always - - - PreserveNewest - - - Designer - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - - - - - - - False - Microsoft .NET Framework 4.5.2 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 - false - - - - - {cf8da5c1-0105-4486-9e28-cb2321d8f122} - DCS-SR-Common - - - {da4f02e3-0b5e-42cd-b8d9-5583fa51d66e} - NAudio - - - {838bdb0b-5eb1-4c1e-9026-0a8842ac00c6} - OpusWrapper - - - - - Designer - - - - - - - - - - - - - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - - Always - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - + + + + + Debug + AnyCPU + {CFF33E05-1D37-4807-B1F7-5A1488D8EC4F} + WinExe + Properties + Ciribob.DCS.SimpleRadio.Standalone.Client + SR-ClientRadio + v4.6.1 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + false + + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + x64 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + x64 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + DCS_SR_Client.App + + + + + + + false + + + + audio-headset.ico + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x64\Release\ + + + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + + Properties\app.manifest + + + + ..\packages\Costura.Fody.1.6.2\lib\dotnet\Costura.dll + False + + + ..\packages\Easy.MessageHub.3.2.1\lib\net35\Easy.MessageHub.dll + + + ..\packages\MahApps.Metro.1.5.0\lib\net45\MahApps.Metro.dll + + + ..\packages\MathNet.Filtering.0.4.0\lib\net40\MathNet.Filtering.dll + + + ..\packages\MathNet.Numerics.3.8.0\lib\net40\MathNet.Numerics.dll + + + ..\packages\MvvmEventBinding.1.0.0\lib\net45\MvvmEventBinding.dll + True + + + ..\packages\Newtonsoft.Json.11.0.1\lib\net45\Newtonsoft.Json.dll + + + ..\packages\NLog.4.5.8\lib\net45\NLog.dll + + + ..\packages\Sentry.2.1.4\lib\net461\Sentry.dll + + + ..\packages\Sentry.PlatformAbstractions.1.1.1\lib\net45\Sentry.PlatformAbstractions.dll + + + ..\packages\Sentry.Protocol.2.1.4\lib\net46\Sentry.Protocol.dll + + + ..\packages\sharpconfig.3.2.6.1\lib\net20\SharpConfig.dll + + + ..\packages\SharpDX.4.0.1\lib\net45\SharpDX.dll + + + ..\packages\SharpDX.DirectInput.4.0.1\lib\net45\SharpDX.DirectInput.dll + + + + + + + + + + + + + + ..\packages\MahApps.Metro.1.5.0\lib\net45\System.Windows.Interactivity.dll + True + + + + + + + + + 4.0 + + + + + + ..\packages\WPFCustomMessageBox.1.0.7\lib\WPFCustomMessageBox.dll + + + ..\packages\Extended.Wpf.Toolkit.3.2.0\lib\net40\Xceed.Wpf.AvalonDock.dll + + + ..\packages\Extended.Wpf.Toolkit.3.2.0\lib\net40\Xceed.Wpf.AvalonDock.Themes.Aero.dll + + + ..\packages\Extended.Wpf.Toolkit.3.2.0\lib\net40\Xceed.Wpf.AvalonDock.Themes.Metro.dll + + + ..\packages\Extended.Wpf.Toolkit.3.2.0\lib\net40\Xceed.Wpf.AvalonDock.Themes.VS2010.dll + + + ..\packages\Extended.Wpf.Toolkit.3.2.0\lib\net40\Xceed.Wpf.DataGrid.dll + + + ..\packages\Extended.Wpf.Toolkit.3.2.0\lib\net40\Xceed.Wpf.Toolkit.dll + + + + + MSBuild:Compile + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + + + + + + + ClientListWindow.xaml + + + RadioCapabilities.xaml + + + TransponderPanel.xaml + + + InputBindingControl.xaml + + + + + + + + + InputProfileWindow.xaml + + + PresetChannelsView.xaml + + + + RadioChannelConfigUI.xaml + + + + AwacsIntercomControlGroup.xaml + + + AwacsRadioControlGroup.xaml + + + AwacsOverlay.xaml + + + + FavouriteServersView.xaml + + + + IntercomControlGroup.xaml + + + RadioControlGroup.xaml + + + + RadioOverlay.xaml + + + + + ServerSettingsWindow.xaml + + + + + + + + + + + + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + + MainWindow.xaml + Code + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + + + Code + + + True + Settings.settings + True + + + PublicResXFileCodeGenerator + Resources.Designer.cs + Designer + + + PreserveNewest + + + Always + + + Always + + + PreserveNewest + + + Designer + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + + False + Microsoft .NET Framework 4.5.2 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + + + {cf8da5c1-0105-4486-9e28-cb2321d8f122} + DCS-SR-Common + + + {da4f02e3-0b5e-42cd-b8d9-5583fa51d66e} + NAudio + + + {838bdb0b-5eb1-4c1e-9026-0a8842ac00c6} + OpusWrapper + + + + + Designer + + + + + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + + Always + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/DCS-SR-Client/Input/InputDeviceManager.cs b/DCS-SR-Client/Input/InputDeviceManager.cs index 3722ea103..96248b6a0 100644 --- a/DCS-SR-Client/Input/InputDeviceManager.cs +++ b/DCS-SR-Client/Input/InputDeviceManager.cs @@ -93,11 +93,11 @@ public void InitDevices() { //Workaround for Bad Devices that pretend to be joysticks if (IsBlackListed(deviceInstance.ProductGuid)) - { - Logger.Info("Found but ignoring blacklist device " + deviceInstance.ProductGuid + " Instance: " + - deviceInstance.InstanceGuid + " " + - deviceInstance.ProductName.Trim().Replace("\0", "") + " Type: " + deviceInstance.Type); - continue; + { + Logger.Info("Found but ignoring blacklist device " + deviceInstance.ProductGuid + " Instance: " + + deviceInstance.InstanceGuid + " " + + deviceInstance.ProductName.Trim().Replace("\0", "") + " Type: " + deviceInstance.Type); + continue; } Logger.Info("Found Device ID:" + deviceInstance.ProductGuid + @@ -110,7 +110,7 @@ public void InitDevices() Logger.Info("Already have device:" + deviceInstance.ProductGuid + " " + deviceInstance.ProductName.Trim().Replace("\0", "")); - continue; + continue; } @@ -193,16 +193,16 @@ private void LoadBlackList() private void LoadGuidFromPath(string path, HashSet _hashSet) { if (!File.Exists(path)) - { + { Logger.Info("File doesnt exist: " + path); - return; + return; } string[] lines = File.ReadAllLines(path); - if (lines?.Length <= 0) - { - return; - + if (lines?.Length <= 0) + { + return; + } foreach (var line in lines) @@ -260,8 +260,8 @@ public void AssignButton(DetectButton callback) for (var i = 0; i < deviceList.Count; i++) { if (deviceList[i] == null || deviceList[i].IsDisposed) - { - continue; + { + continue; } try @@ -331,8 +331,8 @@ public void AssignButton(DetectButton callback) for (var i = 0; i < _inputDevices.Count; i++) { if (deviceList[i] == null || deviceList[i].IsDisposed) - { - continue; + { + continue; } try @@ -512,8 +512,8 @@ public void StartDetectPtt(DetectPttCallback callback) var previousBind = bindStates[j]; if (!previousBind.IsActive) - { - continue; + { + continue; } if (previousBind.ModifierDevice == null && bindState.ModifierDevice != null) @@ -672,9 +672,9 @@ private bool GetButtonState(InputDevice inputDeviceBinding) var device = kpDevice.Value; if (device == null || device.IsDisposed || - !device.Information.InstanceGuid.Equals(inputDeviceBinding.InstanceGuid)) - { - continue; + !device.Information.InstanceGuid.Equals(inputDeviceBinding.InstanceGuid)) + { + continue; } try @@ -745,8 +745,8 @@ public List GenerateBindStateList() for (int i = (int)InputBinding.Intercom; i <= (int)InputBinding.RadioChannelDown; i++) { if (!currentInputProfile.ContainsKey((InputBinding)i)) - { - continue; + { + continue; } var input = currentInputProfile[(InputBinding)i]; diff --git a/DCS-SR-Client/NLog.config b/DCS-SR-Client/NLog.config index 0e8ac610a..f927e6b29 100644 --- a/DCS-SR-Client/NLog.config +++ b/DCS-SR-Client/NLog.config @@ -1,24 +1,24 @@ - - - - - - - - - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/DCS-SR-Client/Network/DCS/DCSRadioSyncHandler.cs b/DCS-SR-Client/Network/DCS/DCSRadioSyncHandler.cs index 8c5ae0809..d3c16fc6b 100644 --- a/DCS-SR-Client/Network/DCS/DCSRadioSyncHandler.cs +++ b/DCS-SR-Client/Network/DCS/DCSRadioSyncHandler.cs @@ -245,12 +245,15 @@ private bool UpdateRadio(DCSPlayerRadioInfo message) playerRadioInfo.unit = message.unit; - if (!_clientStateSingleton.ShouldUseLotATCPosition()) { _clientStateSingleton.UpdatePlayerPosition(message.latLng); } - + else + { + _clientStateSingleton.UpdatePlayerPosition(new DCSLatLngPosition()); + } + var overrideFreqAndVol = false; var newAircraft = playerRadioInfo.unitId != message.unitId || !playerRadioInfo.IsCurrent(); diff --git a/DCS-SR-Client/Network/SRSClientSyncHandler.cs b/DCS-SR-Client/Network/SRSClientSyncHandler.cs index 6d8011b47..7e52b8d2d 100644 --- a/DCS-SR-Client/Network/SRSClientSyncHandler.cs +++ b/DCS-SR-Client/Network/SRSClientSyncHandler.cs @@ -16,6 +16,7 @@ using Ciribob.DCS.SimpleRadio.Standalone.Common; using Ciribob.DCS.SimpleRadio.Standalone.Common.DCSState; using Ciribob.DCS.SimpleRadio.Standalone.Common.Network; +using Ciribob.DCS.SimpleRadio.Standalone.Common.Setting; using Easy.MessageHub; using Newtonsoft.Json; using NLog; @@ -52,12 +53,30 @@ public class SRSClientSyncHandler private static readonly int MAX_DECODE_ERRORS = 5; private VAICOMSyncHandler _vaicomSync; + private long _lastSent = -1; + private DispatcherTimer _idleTimeout; + public SRSClientSyncHandler(string guid, UpdateUICallback uiCallback, DCSRadioSyncHandler.NewAircraft _newAircraft) { _guid = guid; _updateUICallback = uiCallback; this._newAircraft = _newAircraft; + + _idleTimeout = new DispatcherTimer(DispatcherPriority.Background, Application.Current.Dispatcher) {Interval = TimeSpan.FromSeconds(1)}; + _idleTimeout.Tick += CheckIfIdleTimeOut; + _idleTimeout.Interval = TimeSpan.FromSeconds(10); + } + + private void CheckIfIdleTimeOut(object sender, EventArgs e) + { + var timeout = GlobalSettingsStore.Instance.GetClientSetting(GlobalSettingsKeys.IdleTimeOut).IntValue; + if (_lastSent != -1 && TimeSpan.FromTicks(DateTime.Now.Ticks - _lastSent).TotalSeconds > timeout) + { + Logger.Warn("Disconnecting - Idle Time out"); + Disconnect(); + } + } @@ -109,6 +128,9 @@ public void DisconnectExternalAWACSMode() private void Connect() { + _lastSent = DateTime.Now.Ticks; + _idleTimeout.Start(); + if (_radioDCSSync != null) { _radioDCSSync.Stop(); @@ -170,6 +192,7 @@ private void Connect() _radioDCSSync.Stop(); _lotATCSync.Stop(); _vaicomSync.Stop(); + _idleTimeout?.Stop(); //disconnect callback CallOnMain(false, connectionError); @@ -179,7 +202,8 @@ private void ClientRadioUpdated() { Logger.Debug("Sending Radio Update to Server"); var sideInfo = _clientStateSingleton.PlayerCoaltionLocationMetadata; - SendToServer(new NetworkMessage + + var message = new NetworkMessage { Client = new SRClient { @@ -187,28 +211,53 @@ private void ClientRadioUpdated() Name = sideInfo.name, Seat = sideInfo.seat, ClientGuid = _guid, - RadioInfo = _clientStateSingleton.DcsPlayerRadioInfo, - LatLngPosition = sideInfo.LngLngPosition + RadioInfo = _clientStateSingleton.DcsPlayerRadioInfo }, MsgType = NetworkMessage.MessageType.RADIO_UPDATE - }); + }; + + var needValidPosition = _serverSettings.GetSettingAsBool(ServerSettingsKeys.DISTANCE_ENABLED) || _serverSettings.GetSettingAsBool(ServerSettingsKeys.LOS_ENABLED); + + if (needValidPosition) + { + message.Client.LatLngPosition = sideInfo.LngLngPosition; + } + else + { + message.Client.LatLngPosition = new DCSLatLngPosition(); + } + + SendToServer(message); } private void ClientCoalitionUpdate() { var sideInfo = _clientStateSingleton.PlayerCoaltionLocationMetadata; - SendToServer(new NetworkMessage + + var message = new NetworkMessage { Client = new SRClient { Coalition = sideInfo.side, Name = sideInfo.name, Seat = sideInfo.seat, - LatLngPosition = sideInfo.LngLngPosition, ClientGuid = _guid }, MsgType = NetworkMessage.MessageType.UPDATE - }); + }; + + var needValidPosition = _serverSettings.GetSettingAsBool(ServerSettingsKeys.DISTANCE_ENABLED) || _serverSettings.GetSettingAsBool(ServerSettingsKeys.LOS_ENABLED); + + if (needValidPosition) + { + message.Client.LatLngPosition = sideInfo.LngLngPosition; + } + else + { + message.Client.LatLngPosition = new DCSLatLngPosition(); + } + + SendToServer(message); } private void CallOnMain(bool result, bool connectionError = false) @@ -267,7 +316,8 @@ private void ClientSyncLoop() Coalition = sideInfo.side, Name = sideInfo.name.Length > 0 ? sideInfo.name : _clientStateSingleton.LastSeenName, LatLngPosition = sideInfo.LngLngPosition, - ClientGuid = _guid + ClientGuid = _guid, + RadioInfo = _clientStateSingleton.DcsPlayerRadioInfo }, MsgType = NetworkMessage.MessageType.SYNC, }); @@ -502,8 +552,7 @@ private void ShowVersionMistmatchWarning(string serverVersion) MessageBox.Show($"The SRS server you're connecting to is incompatible with this Client. " + $"\n\nMake sure to always run the latest version of the SRS Server & Client" + $"\n\nServer Version: {serverVersion}" + - $"\nClient Version: {UpdaterChecker.VERSION}" + - $"\nMinimum Version: {UpdaterChecker.MINIMUM_PROTOCOL_VERSION}", + $"\nClient Version: {UpdaterChecker.VERSION}", "SRS Server Incompatible", MessageBoxButton.OK, MessageBoxImage.Error); @@ -513,7 +562,7 @@ private void SendToServer(NetworkMessage message) { try { - + _lastSent = DateTime.Now.Ticks; message.Version = UpdaterChecker.VERSION; var json = message.Encode(); @@ -543,6 +592,9 @@ public void Disconnect() { _stop = true; + _lastSent = DateTime.Now.Ticks; + _idleTimeout?.Stop(); + DisconnectExternalAWACSMode(); try diff --git a/DCS-SR-Client/Properties/AssemblyInfo.cs b/DCS-SR-Client/Properties/AssemblyInfo.cs index 5ca0cd9f8..ef050224c 100644 --- a/DCS-SR-Client/Properties/AssemblyInfo.cs +++ b/DCS-SR-Client/Properties/AssemblyInfo.cs @@ -52,5 +52,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.9.0.1")] -[assembly: AssemblyFileVersion("1.9.0.1")] \ No newline at end of file +[assembly: AssemblyVersion("1.9.0.2")] +[assembly: AssemblyFileVersion("1.9.0.2")] \ No newline at end of file diff --git a/DCS-SR-Client/Properties/Resources.Designer.cs b/DCS-SR-Client/Properties/Resources.Designer.cs index ca2457636..4c4ae7481 100644 --- a/DCS-SR-Client/Properties/Resources.Designer.cs +++ b/DCS-SR-Client/Properties/Resources.Designer.cs @@ -10,8 +10,8 @@ namespace Ciribob.DCS.SimpleRadio.Standalone.Client.Properties { using System; - - + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -19,19 +19,19 @@ namespace Ciribob.DCS.SimpleRadio.Standalone.Client.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Resources { - + private static global::System.Resources.ResourceManager resourceMan; - + private static global::System.Globalization.CultureInfo resourceCulture; - + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } - + /// /// Returns the cached ResourceManager instance used by this class. /// @@ -45,7 +45,7 @@ internal Resources() { return resourceMan; } } - + /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. @@ -59,7 +59,7 @@ internal Resources() { resourceCulture = value; } } - + /// /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). /// @@ -69,7 +69,7 @@ public static System.Drawing.Icon audio_headset { return ((System.Drawing.Icon)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -79,7 +79,7 @@ public static System.Drawing.Bitmap status_connected { return ((System.Drawing.Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -89,7 +89,7 @@ public static System.Drawing.Bitmap status_disconnected { return ((System.Drawing.Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -99,7 +99,7 @@ public static System.Drawing.Bitmap status_disconnected_error { return ((System.Drawing.Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/DCS-SR-Client/Properties/Resources.resx b/DCS-SR-Client/Properties/Resources.resx index 66f4246ec..2abee436f 100644 --- a/DCS-SR-Client/Properties/Resources.resx +++ b/DCS-SR-Client/Properties/Resources.resx @@ -1,136 +1,136 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - ..\audio-headset.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\status-connected.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\status-disconnected.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\status-disconnected-error.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\status-disconnected-game.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\audio-headset.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\status-connected.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\status-disconnected.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\status-disconnected-error.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\status-disconnected-game.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/DCS-SR-Client/Properties/Settings.Designer.cs b/DCS-SR-Client/Properties/Settings.Designer.cs index e772f71d9..82c2863ac 100644 --- a/DCS-SR-Client/Properties/Settings.Designer.cs +++ b/DCS-SR-Client/Properties/Settings.Designer.cs @@ -9,14 +9,14 @@ //------------------------------------------------------------------------------ namespace Ciribob.DCS.SimpleRadio.Standalone.Client.Properties { - - + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.3.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - + public static Settings Default { get { return defaultInstance; diff --git a/DCS-SR-Client/Settings/GlobalSettingsStore.cs b/DCS-SR-Client/Settings/GlobalSettingsStore.cs index b5e8b3155..c05c4e0f7 100644 --- a/DCS-SR-Client/Settings/GlobalSettingsStore.cs +++ b/DCS-SR-Client/Settings/GlobalSettingsStore.cs @@ -84,7 +84,10 @@ public enum GlobalSettingsKeys LotATCHeightOffset, DCSAutoConnectUDP, // 5069 - ShowTransmitterName + ShowTransmitterName, + + IdleTimeOut, + AutoConnect } public enum InputBinding @@ -314,6 +317,7 @@ public void SetClientSetting(GlobalSettingsKeys key, string[] strArray) private readonly Dictionary defaultGlobalSettings = new Dictionary() { + {GlobalSettingsKeys.AutoConnect.ToString(), "true"}, {GlobalSettingsKeys.AutoConnectPrompt.ToString(), "false"}, {GlobalSettingsKeys.AutoConnectMismatchPrompt.ToString(), "true"}, {GlobalSettingsKeys.RadioOverlayTaskbarHide.ToString(), "false"}, @@ -391,6 +395,8 @@ public void SetClientSetting(GlobalSettingsKeys key, string[] strArray) {GlobalSettingsKeys.VAICOMTXInhibitEnabled.ToString(), "true"}, {GlobalSettingsKeys.ShowTransmitterName.ToString(), "true"}, + {GlobalSettingsKeys.IdleTimeOut.ToString(), "600"}, // 10 mins + }; private readonly Dictionary defaultArraySettings = new Dictionary() diff --git a/DCS-SR-Client/Singletons/AudioInputSingleton.cs b/DCS-SR-Client/Singletons/AudioInputSingleton.cs index c8c549dc9..3faaf87bf 100644 --- a/DCS-SR-Client/Singletons/AudioInputSingleton.cs +++ b/DCS-SR-Client/Singletons/AudioInputSingleton.cs @@ -1,107 +1,107 @@ -using Ciribob.DCS.SimpleRadio.Standalone.Client.Settings; -using Ciribob.DCS.SimpleRadio.Standalone.Client.UI.ClientWindow; -using NAudio.Wave; -using NLog; -using System; -using System.Collections.Generic; -using System.Linq; -using NAudio.CoreAudioApi; - -namespace Ciribob.DCS.SimpleRadio.Standalone.Client.Singletons -{ - public class AudioInputSingleton - { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - - #region Singleton Definition - private static volatile AudioInputSingleton _instance; - private static object _lock = new Object(); - - public static AudioInputSingleton Instance - { - get - { - if (_instance == null) - { - lock (_lock) - { - if (_instance == null) - _instance = new AudioInputSingleton(); - } - } - - return _instance; - } - } - #endregion - - #region Instance Definition - - public List InputAudioDevices { get; } - - public AudioDeviceListItem SelectedAudioInput { get; set; } - - // Indicates whether a valid microphone is available - deactivating audio input controls and transmissions otherwise - public bool MicrophoneAvailable { get; private set; } - - private AudioInputSingleton() - { - InputAudioDevices = BuildAudioInputs(); - } - - private List BuildAudioInputs() - { - Logger.Info("Audio Input - Saved ID " + - GlobalSettingsStore.Instance.GetClientSetting(GlobalSettingsKeys.AudioInputDeviceId).RawValue); - - var inputs = new List(); - - var deviceEnum = new MMDeviceEnumerator(); - var devices = deviceEnum.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active).ToList(); - - if (devices.Count == 0) - { - MicrophoneAvailable = false; - Logger.Info("Audio Input - No audio input devices available, disabling mic preview"); - return inputs; - } - else - { - MicrophoneAvailable = true; - - } - - Logger.Info("Audio Input - " + devices.Count + " audio input devices available, configuring as usual"); - - inputs.Add(new AudioDeviceListItem() - { - Text = "Default Microphone", - Value = null - }); - SelectedAudioInput = inputs[0]; - - foreach (var item in devices) - { - var input = new AudioDeviceListItem() - { - Text = item.DeviceFriendlyName, - Value = item - }; - inputs.Add(input); - - Logger.Info("Audio Input - " + item.DeviceFriendlyName + " " + item.ID.ToString() + " - Name GUID" + - item.FriendlyName); - - if (item.ID.Trim().Equals(GlobalSettingsStore.Instance.GetClientSetting(GlobalSettingsKeys.AudioInputDeviceId).RawValue.Trim())) - { - SelectedAudioInput = input; - Logger.Info("Audio Input - Found Saved "); - } - } - - return inputs; - } - - #endregion - } -} +using Ciribob.DCS.SimpleRadio.Standalone.Client.Settings; +using Ciribob.DCS.SimpleRadio.Standalone.Client.UI.ClientWindow; +using NAudio.Wave; +using NLog; +using System; +using System.Collections.Generic; +using System.Linq; +using NAudio.CoreAudioApi; + +namespace Ciribob.DCS.SimpleRadio.Standalone.Client.Singletons +{ + public class AudioInputSingleton + { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + #region Singleton Definition + private static volatile AudioInputSingleton _instance; + private static object _lock = new Object(); + + public static AudioInputSingleton Instance + { + get + { + if (_instance == null) + { + lock (_lock) + { + if (_instance == null) + _instance = new AudioInputSingleton(); + } + } + + return _instance; + } + } + #endregion + + #region Instance Definition + + public List InputAudioDevices { get; } + + public AudioDeviceListItem SelectedAudioInput { get; set; } + + // Indicates whether a valid microphone is available - deactivating audio input controls and transmissions otherwise + public bool MicrophoneAvailable { get; private set; } + + private AudioInputSingleton() + { + InputAudioDevices = BuildAudioInputs(); + } + + private List BuildAudioInputs() + { + Logger.Info("Audio Input - Saved ID " + + GlobalSettingsStore.Instance.GetClientSetting(GlobalSettingsKeys.AudioInputDeviceId).RawValue); + + var inputs = new List(); + + var deviceEnum = new MMDeviceEnumerator(); + var devices = deviceEnum.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active).ToList(); + + if (devices.Count == 0) + { + MicrophoneAvailable = false; + Logger.Info("Audio Input - No audio input devices available, disabling mic preview"); + return inputs; + } + else + { + MicrophoneAvailable = true; + + } + + Logger.Info("Audio Input - " + devices.Count + " audio input devices available, configuring as usual"); + + inputs.Add(new AudioDeviceListItem() + { + Text = "Default Microphone", + Value = null + }); + SelectedAudioInput = inputs[0]; + + foreach (var item in devices) + { + var input = new AudioDeviceListItem() + { + Text = item.FriendlyName, + Value = item + }; + inputs.Add(input); + + Logger.Info("Audio Input - " + item.FriendlyName + " " + item.ID.ToString() + " - Name GUID" + + item.FriendlyName); + + if (item.ID.Trim().Equals(GlobalSettingsStore.Instance.GetClientSetting(GlobalSettingsKeys.AudioInputDeviceId).RawValue.Trim())) + { + SelectedAudioInput = input; + Logger.Info("Audio Input - Found Saved "); + } + } + + return inputs; + } + + #endregion + } +} diff --git a/DCS-SR-Client/Singletons/AudioOutputSingleton.cs b/DCS-SR-Client/Singletons/AudioOutputSingleton.cs index 7fdd46eb6..2697660ba 100644 --- a/DCS-SR-Client/Singletons/AudioOutputSingleton.cs +++ b/DCS-SR-Client/Singletons/AudioOutputSingleton.cs @@ -1,158 +1,158 @@ -using Ciribob.DCS.SimpleRadio.Standalone.Client.Settings; -using Ciribob.DCS.SimpleRadio.Standalone.Client.UI.ClientWindow; -using NAudio.CoreAudioApi; -using NAudio.Dmo; -using NLog; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Ciribob.DCS.SimpleRadio.Standalone.Client.Singletons -{ - public class AudioOutputSingleton - { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - - #region Singleton Definition - private static volatile AudioOutputSingleton _instance; - private static object _lock = new Object(); - - public static AudioOutputSingleton Instance - { - get - { - if (_instance == null) - { - lock (_lock) - { - if (_instance == null) - _instance = new AudioOutputSingleton(); - } - } - - return _instance; - } - } - #endregion - - #region Instance Definition - - public List OutputAudioDevices { get; } - public AudioDeviceListItem SelectedAudioOutput { get; set; } - - public List MicOutputAudioDevices { get; } - public AudioDeviceListItem SelectedMicAudioOutput { get; set; } - - - // Version of Windows without bundled multimedia stuff as part of European anti-trust settlement - // https://support.microsoft.com/en-us/help/11529/what-is-a-windows-7-n-edition - public bool WindowsN { get; set; } - - private AudioOutputSingleton() - { - WindowsN = DetectWindowsN(); - OutputAudioDevices = BuildNormalAudioOutputs(); - MicOutputAudioDevices = BuildMicAudioOutputs(); - } - - private List BuildNormalAudioOutputs() - { - Logger.Info("Building Normal Audio Outputs"); - Logger.Info("Audio Output - Saved ID " + - GlobalSettingsStore.Instance.GetClientSetting(GlobalSettingsKeys.AudioOutputDeviceId).RawValue); - - return BuildAudioOutputs("Default Speakers", false); - } - - private List BuildMicAudioOutputs() - { - Logger.Info("Building Microphone Audio Outputs"); - Logger.Info("Mic Audio Output - Saved ID " + - GlobalSettingsStore.Instance.GetClientSetting(GlobalSettingsKeys.MicAudioOutputDeviceId).RawValue); - - return BuildAudioOutputs("NO MIC OUTPUT / PASSTHROUGH", true); - } - - private List BuildAudioOutputs(string defaultItemText, bool micOutput) - { - var outputs = new List - { - new AudioDeviceListItem() - { - Text = defaultItemText, - Value = null - } - }; - - string savedDeviceId; - if (micOutput) - { - savedDeviceId = GlobalSettingsStore.Instance.GetClientSetting(GlobalSettingsKeys.MicAudioOutputDeviceId).RawValue; - SelectedMicAudioOutput = outputs[0]; - } else - { - savedDeviceId = GlobalSettingsStore.Instance.GetClientSetting(GlobalSettingsKeys.AudioOutputDeviceId).RawValue; - SelectedAudioOutput = outputs[0]; - } - - var enumerator = new MMDeviceEnumerator(); - var outputDeviceList = enumerator.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active); - - var i = 1; - foreach (var device in outputDeviceList) - { - try - { - Logger.Info("Audio Output - " + device.DeviceFriendlyName + " " + device.ID + " CHN:" + - device.AudioClient.MixFormat.Channels + " Rate:" + - device.AudioClient.MixFormat.SampleRate.ToString()); - - outputs.Add(new AudioDeviceListItem() - { - Text = device.FriendlyName, - Value = device - }); - - if (device.ID == savedDeviceId) - { - if (micOutput) - { - SelectedMicAudioOutput = outputs[i]; - } - else - { - SelectedAudioOutput = outputs[i]; - } - } - - i++; - - } - catch (Exception e) - { - Logger.Error(e, "Audio Output - Error processing device - device skipped"); - } - } - - return outputs; - } - - private bool DetectWindowsN() - { - try - { - var dmoResampler = new DmoResampler(); - dmoResampler.Dispose(); - return false; - } - catch (Exception) - { - Logger.Warn("Windows N Detected - using inbuilt resampler"); - return true; - } - } - #endregion - } -} +using Ciribob.DCS.SimpleRadio.Standalone.Client.Settings; +using Ciribob.DCS.SimpleRadio.Standalone.Client.UI.ClientWindow; +using NAudio.CoreAudioApi; +using NAudio.Dmo; +using NLog; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Ciribob.DCS.SimpleRadio.Standalone.Client.Singletons +{ + public class AudioOutputSingleton + { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + #region Singleton Definition + private static volatile AudioOutputSingleton _instance; + private static object _lock = new Object(); + + public static AudioOutputSingleton Instance + { + get + { + if (_instance == null) + { + lock (_lock) + { + if (_instance == null) + _instance = new AudioOutputSingleton(); + } + } + + return _instance; + } + } + #endregion + + #region Instance Definition + + public List OutputAudioDevices { get; } + public AudioDeviceListItem SelectedAudioOutput { get; set; } + + public List MicOutputAudioDevices { get; } + public AudioDeviceListItem SelectedMicAudioOutput { get; set; } + + + // Version of Windows without bundled multimedia stuff as part of European anti-trust settlement + // https://support.microsoft.com/en-us/help/11529/what-is-a-windows-7-n-edition + public bool WindowsN { get; set; } + + private AudioOutputSingleton() + { + WindowsN = DetectWindowsN(); + OutputAudioDevices = BuildNormalAudioOutputs(); + MicOutputAudioDevices = BuildMicAudioOutputs(); + } + + private List BuildNormalAudioOutputs() + { + Logger.Info("Building Normal Audio Outputs"); + Logger.Info("Audio Output - Saved ID " + + GlobalSettingsStore.Instance.GetClientSetting(GlobalSettingsKeys.AudioOutputDeviceId).RawValue); + + return BuildAudioOutputs("Default Speakers", false); + } + + private List BuildMicAudioOutputs() + { + Logger.Info("Building Microphone Audio Outputs"); + Logger.Info("Mic Audio Output - Saved ID " + + GlobalSettingsStore.Instance.GetClientSetting(GlobalSettingsKeys.MicAudioOutputDeviceId).RawValue); + + return BuildAudioOutputs("NO MIC OUTPUT / PASSTHROUGH", true); + } + + private List BuildAudioOutputs(string defaultItemText, bool micOutput) + { + var outputs = new List + { + new AudioDeviceListItem() + { + Text = defaultItemText, + Value = null + } + }; + + string savedDeviceId; + if (micOutput) + { + savedDeviceId = GlobalSettingsStore.Instance.GetClientSetting(GlobalSettingsKeys.MicAudioOutputDeviceId).RawValue; + SelectedMicAudioOutput = outputs[0]; + } else + { + savedDeviceId = GlobalSettingsStore.Instance.GetClientSetting(GlobalSettingsKeys.AudioOutputDeviceId).RawValue; + SelectedAudioOutput = outputs[0]; + } + + var enumerator = new MMDeviceEnumerator(); + var outputDeviceList = enumerator.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active); + + var i = 1; + foreach (var device in outputDeviceList) + { + try + { + Logger.Info("Audio Output - " + device.DeviceFriendlyName + " " + device.ID + " CHN:" + + device.AudioClient.MixFormat.Channels + " Rate:" + + device.AudioClient.MixFormat.SampleRate.ToString()); + + outputs.Add(new AudioDeviceListItem() + { + Text = device.FriendlyName, + Value = device + }); + + if (device.ID == savedDeviceId) + { + if (micOutput) + { + SelectedMicAudioOutput = outputs[i]; + } + else + { + SelectedAudioOutput = outputs[i]; + } + } + + i++; + + } + catch (Exception e) + { + Logger.Error(e, "Audio Output - Error processing device - device skipped"); + } + } + + return outputs; + } + + private bool DetectWindowsN() + { + try + { + var dmoResampler = new DmoResampler(); + dmoResampler.Dispose(); + return false; + } + catch (Exception) + { + Logger.Warn("Windows N Detected - using inbuilt resampler"); + return true; + } + } + #endregion + } +} diff --git a/DCS-SR-Client/Singletons/ClientStateSingleton.cs b/DCS-SR-Client/Singletons/ClientStateSingleton.cs index 77f70e64a..1160f0e8b 100644 --- a/DCS-SR-Client/Singletons/ClientStateSingleton.cs +++ b/DCS-SR-Client/Singletons/ClientStateSingleton.cs @@ -79,32 +79,32 @@ public bool IsVoipConnected private bool isConnectionErrored; public string ShortGUID { get; } - public bool IsConnectionErrored - { - get - { - return isConnectionErrored; - } - set - { - isConnectionErrored = value; - NotifyPropertyChanged("isConnectionErrored"); - } - } - - // Indicates the user's desire to be in External Awacs Mode or not - public bool ExternalAWACSModelSelected { get; set; } - - // Indicates whether we are *actually* connected in External Awacs Mode - // Used by the Name and Password related UI elements to determine if they are editable or not - public bool ExternalAWACSModeConnected - { - get - { - bool EamEnabled = SyncedServerSettings.Instance.GetSettingAsBool(Common.Setting.ServerSettingsKeys.EXTERNAL_AWACS_MODE); - return IsConnected && EamEnabled && ExternalAWACSModelSelected && !IsGameExportConnected; - } - } + public bool IsConnectionErrored + { + get + { + return isConnectionErrored; + } + set + { + isConnectionErrored = value; + NotifyPropertyChanged("isConnectionErrored"); + } + } + + // Indicates the user's desire to be in External Awacs Mode or not + public bool ExternalAWACSModelSelected { get; set; } + + // Indicates whether we are *actually* connected in External Awacs Mode + // Used by the Name and Password related UI elements to determine if they are editable or not + public bool ExternalAWACSModeConnected + { + get + { + bool EamEnabled = SyncedServerSettings.Instance.GetSettingAsBool(Common.Setting.ServerSettingsKeys.EXTERNAL_AWACS_MODE); + return IsConnected && EamEnabled && ExternalAWACSModelSelected && !IsGameExportConnected; + } + } public bool IsLotATCConnected { get { return LotATCLastReceived >= DateTime.Now.Ticks - 50000000; } } @@ -113,8 +113,8 @@ public bool ExternalAWACSModeConnected // Indicates an active game connection has been detected (1 tick = 100ns, 100000000 ticks = 10s stale timer), not updated by EAM public bool IsGameConnected { get { return IsGameGuiConnected && IsGameExportConnected; } } - public string LastSeenName { get; set; } - + public string LastSeenName { get; set; } + public VAICOMMessageWrapper InhibitTX { get; set; } = new VAICOMMessageWrapper(); //used to temporarily stop PTT for VAICOM private ClientStateSingleton() @@ -129,12 +129,12 @@ private ClientStateSingleton() // The following members are not updated due to events. Therefore we need to setup a polling action so that they are // periodically checked. DcsGameGuiLastReceived = 0; - DcsExportLastReceived = 0; - _timer.Interval = TimeSpan.FromSeconds(1); + DcsExportLastReceived = 0; + _timer.Interval = TimeSpan.FromSeconds(1); _timer.Tick += (s, e) => { NotifyPropertyChanged("IsGameConnected"); - NotifyPropertyChanged("IsLotATCConnected"); - NotifyPropertyChanged("ExternalAWACSModeConnected"); + NotifyPropertyChanged("IsLotATCConnected"); + NotifyPropertyChanged("ExternalAWACSModeConnected"); }; _timer.Start(); @@ -150,7 +150,7 @@ private ClientStateSingleton() IsConnected = false; ExternalAWACSModelSelected = false; - LastSeenName = Settings.GlobalSettingsStore.Instance.GetClientSetting(Settings.GlobalSettingsKeys.LastSeenName).StringValue; + LastSeenName = Settings.GlobalSettingsStore.Instance.GetClientSetting(Settings.GlobalSettingsKeys.LastSeenName).StringValue; } public static ClientStateSingleton Instance @@ -168,8 +168,8 @@ public static ClientStateSingleton Instance return _instance; } - } - + } + private void NotifyPropertyChanged(string propertyName = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); diff --git a/DCS-SR-Client/Singletons/ConnectedClientsSingleton.cs b/DCS-SR-Client/Singletons/ConnectedClientsSingleton.cs index a3d401b87..feb1f75e6 100644 --- a/DCS-SR-Client/Singletons/ConnectedClientsSingleton.cs +++ b/DCS-SR-Client/Singletons/ConnectedClientsSingleton.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.ComponentModel; +using System.ComponentModel; using System.Linq; using Ciribob.DCS.SimpleRadio.Standalone.Client.Settings; using Ciribob.DCS.SimpleRadio.Standalone.Common; @@ -9,17 +9,17 @@ using Ciribob.DCS.SimpleRadio.Standalone.Common.Setting; namespace Ciribob.DCS.SimpleRadio.Standalone.Client.Singletons -{ +{ public sealed class ConnectedClientsSingleton : INotifyPropertyChanged { private readonly ConcurrentDictionary _clients = new ConcurrentDictionary(); private static volatile ConnectedClientsSingleton _instance; private static object _lock = new Object(); private readonly string _guid = ClientStateSingleton.Instance.ShortGUID; - private readonly SyncedServerSettings _serverSettings = SyncedServerSettings.Instance; - - public event PropertyChangedEventHandler PropertyChanged; - + private readonly SyncedServerSettings _serverSettings = SyncedServerSettings.Instance; + + public event PropertyChangedEventHandler PropertyChanged; + private ConnectedClientsSingleton() { } public static ConnectedClientsSingleton Instance @@ -37,8 +37,8 @@ public static ConnectedClientsSingleton Instance return _instance; } - } - + } + private void NotifyPropertyChanged(string propertyName = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); @@ -47,29 +47,29 @@ private void NotifyPropertyChanged(string propertyName = "") public void NotifyAll() { NotifyPropertyChanged("Total"); - } - - public SRClient this[string key] - { - get - { - return _clients[key]; - } - set - { - _clients[key] = value; - NotifyAll(); - } - } - - public ICollection Values - { - get - { - return _clients.Values; - } - } - + } + + public SRClient this[string key] + { + get + { + return _clients[key]; + } + set + { + _clients[key] = value; + NotifyAll(); + } + } + + public ICollection Values + { + get + { + return _clients.Values; + } + } + public int Total { get @@ -78,30 +78,30 @@ public int Total } } - public bool TryRemove(string key, out SRClient value) - { - bool result = _clients.TryRemove(key, out value); - if (result) - { + public bool TryRemove(string key, out SRClient value) + { + bool result = _clients.TryRemove(key, out value); + if (result) + { NotifyPropertyChanged("Total"); - } - return result; + } + return result; } - public void Clear() - { - _clients.Clear(); + public void Clear() + { + _clients.Clear(); NotifyPropertyChanged("Total"); } - public bool TryGetValue(string key, out SRClient value) - { - return _clients.TryGetValue(key, out value); + public bool TryGetValue(string key, out SRClient value) + { + return _clients.TryGetValue(key, out value); } - public bool ContainsKey(string key) - { - return _clients.ContainsKey(key); + public bool ContainsKey(string key) + { + return _clients.ContainsKey(key); } public int ClientsOnFreq(double freq, RadioInformation.Modulation modulation) diff --git a/DCS-SR-Client/UI/ClientWindow/AudioDeviceListItem.cs b/DCS-SR-Client/UI/ClientWindow/AudioDeviceListItem.cs index fd9cd6334..e0e538229 100644 --- a/DCS-SR-Client/UI/ClientWindow/AudioDeviceListItem.cs +++ b/DCS-SR-Client/UI/ClientWindow/AudioDeviceListItem.cs @@ -8,7 +8,7 @@ namespace Ciribob.DCS.SimpleRadio.Standalone.Client.UI.ClientWindow { public class AudioDeviceListItem { - public string Text { get; set; } + public string Text { get; set; } public object Value { get; set; } public override string ToString() diff --git a/DCS-SR-Client/UI/ClientWindow/MainWindow.xaml b/DCS-SR-Client/UI/ClientWindow/MainWindow.xaml index 749ecccab..27609dabc 100644 --- a/DCS-SR-Client/UI/ClientWindow/MainWindow.xaml +++ b/DCS-SR-Client/UI/ClientWindow/MainWindow.xaml @@ -12,7 +12,7 @@ xmlns:converters="clr-namespace:Ciribob.DCS.SimpleRadio.Standalone.Client.Utils.ValueConverters" Title="DCS-SRS Client" Width="550" - Height="690" + Height="710" d:DataContext="{d:DesignInstance local:MainWindow}" ResizeMode="CanMinimize" mc:Ignorable="d"> @@ -310,7 +310,9 @@ Height="26" HorizontalAlignment="Center" Margin="5,0,0,0" /> + + @@ -639,16 +641,44 @@ +