diff --git a/dvmconsole/App.xaml b/dvmconsole/App.xaml index c1064e9..2428937 100644 --- a/dvmconsole/App.xaml +++ b/dvmconsole/App.xaml @@ -1,85 +1,15 @@  - - - + + + + + + diff --git a/dvmconsole/App.xaml.cs b/dvmconsole/App.xaml.cs index abb4dc9..ed1db8f 100644 --- a/dvmconsole/App.xaml.cs +++ b/dvmconsole/App.xaml.cs @@ -14,15 +14,20 @@ using System.IO; using System.Reflection; +using System.Text; using System.Windows; +using fnecore.Utility; + namespace dvmconsole { /// - /// + /// Encapsulates a Windows Presentation Foundation application. /// public partial class App : Application { + public static string USER_PROFILE_PATH_OVERRIDE = string.Empty; + /* ** Methods */ @@ -44,5 +49,58 @@ namespace dvmconsole return; } } + + /// + /// Internal helper to prints the program usage. + /// + private static void Usage(OptionSet p) + { + string messageBoxText = "[-h | --help][--userprofile ]\r\nOptions:\r\n"; + + using (MemoryStream ms = new MemoryStream()) + { + using (TextWriter writer = new StreamWriter(ms)) + p.WriteOptionDescriptions(writer); + + messageBoxText += Encoding.UTF8.GetString(ms.ToArray()); + } + + MessageBox.Show(messageBoxText, "Digital Voice Modem - Desktop Dispatch Console", + MessageBoxButton.OK, MessageBoxImage.Information); + + Application.Current.Shutdown(); + } + + /// + /// + /// + /// + /// + private void Application_Startup(object sender, StartupEventArgs e) + { + bool showHelp = false; + string configFile = string.Empty; + + // command line parameters + OptionSet options = new OptionSet() + { + { "h|help", "show this message and exit", v => showHelp = v != null }, + { "userprofile=", "sets the path to the UserProfile.yaml", v => USER_PROFILE_PATH_OVERRIDE = v }, + }; + + // attempt to parse the commandline + try + { + options.Parse(e.Args); + } + catch (OptionException) + { + /* ignore */ + } + + // show help? + if (showHelp) + Usage(options); + } } // public partial class App : Application } // namespace dvmconsole diff --git a/dvmconsole/AudioSettingsWindow.xaml b/dvmconsole/AudioSettingsWindow.xaml index 90f93be..ea33c21 100644 --- a/dvmconsole/AudioSettingsWindow.xaml +++ b/dvmconsole/AudioSettingsWindow.xaml @@ -1,7 +1,10 @@  @@ -12,16 +15,18 @@ - + - + - - - + diff --git a/dvmconsole/Controls/ChannelBox.xaml b/dvmconsole/Controls/ChannelBox.xaml index 8af51bf..5bed26c 100644 --- a/dvmconsole/Controls/ChannelBox.xaml +++ b/dvmconsole/Controls/ChannelBox.xaml @@ -2,12 +2,13 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:dvmconsole.Controls" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" Width="220" Height="110"> - + @@ -23,7 +24,7 @@ - + @@ -40,14 +41,14 @@ - @@ -101,22 +102,12 @@ - - diff --git a/dvmconsole/Controls/ChannelBox.xaml.cs b/dvmconsole/Controls/ChannelBox.xaml.cs index 00e584a..5022560 100644 --- a/dvmconsole/Controls/ChannelBox.xaml.cs +++ b/dvmconsole/Controls/ChannelBox.xaml.cs @@ -32,7 +32,9 @@ namespace dvmconsole.Controls { public readonly static Border BORDER_DEFAULT; public readonly static Border BORDER_GREEN; + public readonly static LinearGradientBrush GRAY_GRADIENT; + public readonly static LinearGradientBrush DARK_GRAY_GRADIENT; // Delected/Disconnected Color public readonly static LinearGradientBrush BLUE_GRADIENT; // Selected Channel Color public readonly static LinearGradientBrush RED_GRADIENT; // Playback Selected Color @@ -547,6 +549,7 @@ namespace dvmconsole.Controls if (SystemName == MainWindow.PLAYBACKSYS || ChannelName == MainWindow.PLAYBACKCHNAME || DstId == MainWindow.PLAYBACKTG) { ControlBorder.Background = IsSelected ? RED_GRADIENT : DARK_GRAY_GRADIENT; + SetVolumeMeterBg(ControlBorder.Background); return; } diff --git a/dvmconsole/Controls/SystemStatusBox.xaml b/dvmconsole/Controls/SystemStatusBox.xaml index cf5e4ed..b123943 100644 --- a/dvmconsole/Controls/SystemStatusBox.xaml +++ b/dvmconsole/Controls/SystemStatusBox.xaml @@ -7,8 +7,8 @@ - - + + diff --git a/dvmconsole/DVMConsole.csproj b/dvmconsole/DVMConsole.csproj index 1775aa0..16804ae 100644 --- a/dvmconsole/DVMConsole.csproj +++ b/dvmconsole/DVMConsole.csproj @@ -98,6 +98,7 @@ + diff --git a/dvmconsole/DigitalPageWindow.xaml b/dvmconsole/DigitalPageWindow.xaml index 3eba9a8..f57842f 100644 --- a/dvmconsole/DigitalPageWindow.xaml +++ b/dvmconsole/DigitalPageWindow.xaml @@ -4,15 +4,32 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:dvmconsole" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + TextElement.Foreground="{DynamicResource MaterialDesignBody}" TextElement.FontWeight="Regular" TextElement.FontSize="13" + Style="{StaticResource MaterialDesignWindow}" Background="{DynamicResource MaterialDesignPaper}" FontFamily="{DynamicResource MaterialDesignFont}" mc:Ignorable="d" Icon="/dvmconsole;component/Assets/page.png" - Title="Page Subscriber" Height="141" Width="330" WindowStartupLocation="CenterOwner"> + Title="Page Subscriber" Height="181" Width="340" WindowStartupLocation="CenterOwner"> - - - diff --git a/dvmconsole/DigitalPageWindow.xaml.cs b/dvmconsole/DigitalPageWindow.xaml.cs index 527f055..6e0982a 100644 --- a/dvmconsole/DigitalPageWindow.xaml.cs +++ b/dvmconsole/DigitalPageWindow.xaml.cs @@ -52,7 +52,7 @@ namespace dvmconsole /// /// /// - private void SendPageButton_Click(object sender, RoutedEventArgs e) + private void SendButton_Click(object sender, RoutedEventArgs e) { RadioSystem = SystemCombo.SelectedItem as Codeplug.System; DstId = DstIdText.Text; diff --git a/dvmconsole/KeyStatusWindow.xaml b/dvmconsole/KeyStatusWindow.xaml index dad79d6..752ee8c 100644 --- a/dvmconsole/KeyStatusWindow.xaml +++ b/dvmconsole/KeyStatusWindow.xaml @@ -3,16 +3,18 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + TextElement.Foreground="{DynamicResource MaterialDesignBody}" TextElement.FontWeight="Regular" TextElement.FontSize="13" + Style="{StaticResource MaterialDesignWindow}" Background="{DynamicResource MaterialDesignPaper}" FontFamily="{DynamicResource MaterialDesignFont}" mc:Ignorable="d" Icon="/dvmconsole;component/Assets/key.png" Title="Key Status Window" Height="450" Width="800" WindowStartupLocation="CenterOwner"> - + - - - - + + + + diff --git a/dvmconsole/MainWindow.xaml b/dvmconsole/MainWindow.xaml index 92c9abc..4f05d29 100644 --- a/dvmconsole/MainWindow.xaml +++ b/dvmconsole/MainWindow.xaml @@ -2,35 +2,29 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:dvmconsole.Controls" - Title="Digital Voice Modem - Desktop Dispatch Console" Height="600" Width="875" Background="#FFF2F2F2" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + Title="Digital Voice Modem - Desktop Dispatch Console" Height="600" Width="1024" + TextElement.Foreground="{DynamicResource MaterialDesignBody}" TextElement.FontWeight="Regular" TextElement.FontSize="13" + Style="{StaticResource MaterialDesignWindow}" Background="{DynamicResource MaterialDesignPaper}" FontFamily="{DynamicResource MaterialDesignFont}" Icon="/dvmconsole;component/Assets/AppIcon.ico"> - + - + - - - - - - - - - - - - + + + - + @@ -39,7 +33,7 @@ - + @@ -51,7 +45,7 @@ - + @@ -63,434 +57,117 @@ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + - - + + - - + - - - - + + - - + - - - - - - - - - - + - - + + - - + - - + + + + - - + + + + + + + + diff --git a/dvmconsole/MainWindow.xaml.cs b/dvmconsole/MainWindow.xaml.cs index 15abb7e..4c2cc7a 100644 --- a/dvmconsole/MainWindow.xaml.cs +++ b/dvmconsole/MainWindow.xaml.cs @@ -19,6 +19,7 @@ using System.Timers; using System.Windows; using System.Windows.Controls; using System.Windows.Input; +using System.Windows.Media; using System.Windows.Media.Imaging; using Microsoft.Win32; @@ -26,6 +27,8 @@ using Microsoft.Win32; using NAudio.Wave; using NWaves.Signals; +using MaterialDesignThemes.Wpf; + using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; @@ -101,6 +104,8 @@ namespace dvmconsole private FlashingBackgroundManager flashingManager; private WaveFilePlaybackManager emergencyAlertPlayback; + private Brush btnGlobalPttDefaultBg; + private ChannelBox playbackChannelBox; CallHistoryWindow callHistoryWindow = new CallHistoryWindow(); @@ -856,6 +861,17 @@ namespace dvmconsole /// private void UpdateBackground() { + // set the UI theme + PaletteHelper paletteHelper = new PaletteHelper(); + Theme theme = paletteHelper.GetTheme(); + + if (settingsManager.DarkMode) + theme.SetBaseTheme(BaseTheme.Dark); + else + theme.SetBaseTheme(BaseTheme.Light); + + paletteHelper.SetTheme(theme); + BitmapImage bg = new BitmapImage(); // do we have a user defined background? @@ -1112,6 +1128,8 @@ namespace dvmconsole menuDarkMode.IsChecked = settingsManager.DarkMode; UpdateBackground(); + btnGlobalPttDefaultBg = btnGlobalPtt.Background; + // set window configuration if (settingsManager.Maximized) { @@ -1185,7 +1203,14 @@ namespace dvmconsole if (pageWindow.ShowDialog() == true) { - PeerSystem handler = fneSystemManager.GetFneSystem(pageWindow.RadioSystem.Name); + // throw an error if the user does the dumb... + if (pageWindow.DstId == string.Empty) + { + MessageBox.Show($"Must supply a destination ID.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); + return; + } + + PeerSystem fne = fneSystemManager.GetFneSystem(pageWindow.RadioSystem.Name); IOSP_CALL_ALRT callAlert = new IOSP_CALL_ALRT(uint.Parse(pageWindow.DstId), uint.Parse(pageWindow.RadioSystem.Rid)); RemoteCallData callData = new RemoteCallData @@ -1199,7 +1224,7 @@ namespace dvmconsole callAlert.Encode(ref tsbk); - handler.SendP25TSBK(callData, tsbk); + fne.SendP25TSBK(callData, tsbk); } } @@ -1216,7 +1241,14 @@ namespace dvmconsole if (pageWindow.ShowDialog() == true) { - PeerSystem handler = fneSystemManager.GetFneSystem(pageWindow.RadioSystem.Name); + // throw an error if the user does the dumb... + if (pageWindow.DstId == string.Empty) + { + MessageBox.Show($"Must supply a destination ID.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); + return; + } + + PeerSystem fne = fneSystemManager.GetFneSystem(pageWindow.RadioSystem.Name); IOSP_EXT_FNCT extFunc = new IOSP_EXT_FNCT((ushort)ExtendedFunction.CHECK, uint.Parse(pageWindow.RadioSystem.Rid), uint.Parse(pageWindow.DstId)); RemoteCallData callData = new RemoteCallData @@ -1230,7 +1262,7 @@ namespace dvmconsole extFunc.Encode(ref tsbk); - handler.SendP25TSBK(callData, tsbk); + fne.SendP25TSBK(callData, tsbk); } } @@ -1247,7 +1279,14 @@ namespace dvmconsole if (pageWindow.ShowDialog() == true) { - PeerSystem handler = fneSystemManager.GetFneSystem(pageWindow.RadioSystem.Name); + // throw an error if the user does the dumb... + if (pageWindow.DstId == string.Empty) + { + MessageBox.Show($"Must supply a destination ID.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); + return; + } + + PeerSystem fne = fneSystemManager.GetFneSystem(pageWindow.RadioSystem.Name); IOSP_EXT_FNCT extFunc = new IOSP_EXT_FNCT((ushort)ExtendedFunction.INHIBIT, P25Defines.WUID_FNE, uint.Parse(pageWindow.DstId)); RemoteCallData callData = new RemoteCallData @@ -1261,7 +1300,7 @@ namespace dvmconsole extFunc.Encode(ref tsbk); - handler.SendP25TSBK(callData, tsbk); + fne.SendP25TSBK(callData, tsbk); } } @@ -1278,7 +1317,14 @@ namespace dvmconsole if (pageWindow.ShowDialog() == true) { - PeerSystem handler = fneSystemManager.GetFneSystem(pageWindow.RadioSystem.Name); + // throw an error if the user does the dumb... + if (pageWindow.DstId == string.Empty) + { + MessageBox.Show($"Must supply a destination ID.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); + return; + } + + PeerSystem fne = fneSystemManager.GetFneSystem(pageWindow.RadioSystem.Name); IOSP_EXT_FNCT extFunc = new IOSP_EXT_FNCT((ushort)ExtendedFunction.UNINHIBIT, P25Defines.WUID_FNE, uint.Parse(pageWindow.DstId)); RemoteCallData callData = new RemoteCallData @@ -1292,7 +1338,7 @@ namespace dvmconsole extFunc.Encode(ref tsbk); - handler.SendP25TSBK(callData, tsbk); + fne.SendP25TSBK(callData, tsbk); } } @@ -2028,7 +2074,7 @@ namespace dvmconsole if (globalPttState) btnGlobalPtt.Background = ChannelBox.RED_GRADIENT; else - btnGlobalPtt.Background = ChannelBox.GRAY_GRADIENT; + btnGlobalPtt.Background = btnGlobalPttDefaultBg; }); primaryChannel.PttButton_Click(sender, e); @@ -2082,7 +2128,7 @@ namespace dvmconsole { Dispatcher.Invoke(() => { - btnGlobalPtt.Background = ChannelBox.GRAY_GRADIENT; + btnGlobalPtt.Background = btnGlobalPttDefaultBg; channel.PttState = false; }); diff --git a/dvmconsole/PeerSystem.cs b/dvmconsole/PeerSystem.cs index 60df043..2e956c2 100644 --- a/dvmconsole/PeerSystem.cs +++ b/dvmconsole/PeerSystem.cs @@ -74,6 +74,8 @@ namespace dvmconsole string software = $"CONSOLE_R{_SEM_VERSION.Major.ToString("D2")}A{_SEM_VERSION.Minor.ToString("D2")}"; + if (system.Identity == null) + system.Identity = system.PeerId.ToString(); if (system.Identity.Length == 0) system.Identity = system.PeerId.ToString(); diff --git a/dvmconsole/Properties/launchSettings.json b/dvmconsole/Properties/launchSettings.json new file mode 100644 index 0000000..8582f22 --- /dev/null +++ b/dvmconsole/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "dvmconsole": { + "commandName": "Project", + "commandLineArgs": "--userprofile=." + } + } +} \ No newline at end of file diff --git a/dvmconsole/QuickCallPage.xaml b/dvmconsole/QuickCallPage.xaml index 16bdb3d..5e0eb83 100644 --- a/dvmconsole/QuickCallPage.xaml +++ b/dvmconsole/QuickCallPage.xaml @@ -4,16 +4,31 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:dvmconsole" + TextElement.Foreground="{DynamicResource MaterialDesignBody}" TextElement.FontWeight="Regular" TextElement.FontSize="13" + Style="{StaticResource MaterialDesignWindow}" Background="{DynamicResource MaterialDesignPaper}" FontFamily="{DynamicResource MaterialDesignFont}" mc:Ignorable="d" Icon="/dvmconsole;component/Assets/page.png" - Title="QuickCall II Page" Height="146" Width="330" WindowStartupLocation="CenterOwner"> + Title="QuickCall II Page" Height="166" Width="340" WindowStartupLocation="CenterOwner"> - - - - diff --git a/dvmconsole/SettingsManager.cs b/dvmconsole/SettingsManager.cs index 54084fe..b6ac853 100644 --- a/dvmconsole/SettingsManager.cs +++ b/dvmconsole/SettingsManager.cs @@ -31,9 +31,9 @@ namespace dvmconsole Environment.SpecialFolder.ApplicationData); public static readonly string RootAppDataPath = "DVMProject" + Path.DirectorySeparatorChar + "dvmconsole"; - public static readonly string UserAppDataPath = UserAppData + Path.DirectorySeparatorChar + RootAppDataPath; + public static string UserAppDataPath = UserAppData + Path.DirectorySeparatorChar + RootAppDataPath; - private static readonly string SettingsFilePath = UserAppDataPath + Path.DirectorySeparatorChar + "UserSettings.json"; + private static string SettingsFilePath = UserAppDataPath + Path.DirectorySeparatorChar + "UserSettings.json"; /* ** Properties @@ -144,8 +144,17 @@ namespace dvmconsole /// public bool LoadSettings() { - if (!Directory.Exists(UserAppDataPath)) - Directory.CreateDirectory(UserAppDataPath); + // was the user profile path being overridden? + if (App.USER_PROFILE_PATH_OVERRIDE != string.Empty) + { + UserAppDataPath = App.USER_PROFILE_PATH_OVERRIDE; + SettingsFilePath = UserAppDataPath + Path.DirectorySeparatorChar + "UserSettings.json"; + } + else + { + if (!Directory.Exists(UserAppDataPath)) + Directory.CreateDirectory(UserAppDataPath); + } if (!File.Exists(SettingsFilePath)) return false;