add per-channel call history button; better handle duplicate Rx and Tx situations;

pull/12/head
Bryan Biedenkapp 8 months ago
parent d9b635324b
commit 53ebb39a3e

@ -3,7 +3,7 @@
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">
Width="264" Height="110">
<UserControl.Effect>
<DropShadowEffect ShadowDepth="1" BlurRadius="16" Color="#FF686767" Opacity="0.3" />
</UserControl.Effect>
@ -24,7 +24,7 @@
</Grid.RowDefinitions>
<!-- Volume Meter -->
<local:VuMeterControl x:Name="VolumeMeter" HorizontalAlignment="Center" Width="220" Height="10" Grid.RowSpan="2" Grid.ColumnSpan="3" Margin="0,-60,0,0" />
<local:VuMeterControl x:Name="VolumeMeter" HorizontalAlignment="Center" Width="260" Height="10" Grid.RowSpan="2" Grid.ColumnSpan="3" Margin="0,-56,0,0" />
<!-- Main Info Section -->
<StackPanel Grid.Column="1" HorizontalAlignment="Left" Width="147" Height="50" Margin="22,5,0,4" Grid.ColumnSpan="2" Grid.Row="1">
@ -66,7 +66,7 @@
<!-- Volume Slider -->
<Slider Minimum="0" Maximum="4" Value="{Binding Volume, Mode=TwoWay}"
Height="21" VerticalAlignment="Center" x:Name="VolumeSlider"
ValueChanged="VolumeSlider_ValueChanged" Margin="12,0,72,0"
ValueChanged="VolumeSlider_ValueChanged" Margin="12,0,112,0"
Grid.ColumnSpan="2" Grid.Row="2" ToolTip="Channel Volume">
<Slider.Style>
<Style TargetType="Slider">
@ -102,14 +102,18 @@
<!-- Bottom Buttons -->
<StackPanel Grid.Column="1" Grid.Row="2" Orientation="Horizontal" Margin="87,-8,-2,0" Grid.RowSpan="2" Grid.ColumnSpan="2">
<Button x:Name="PageSelectButton" Width="40" Height="40" Click="PageSelectButton_Click" ToolTip="Select for Alert Tone" Padding="0"
<Button x:Name="PageSelectButton" Width="38" Height="40" Click="PageSelectButton_Click" ToolTip="Select for Alert Tone" Padding="0"
Style="{StaticResource MaterialDesignPaperDarkButton}">
<Image Source="/dvmconsole;component/Assets/pageselect.png" Width="39" Height="39" Margin="1.5,2,0,0"/>
<Image Source="/dvmconsole;component/Assets/pageselect.png" Width="36" Height="40" Margin="1.5,2,0,0"/>
</Button>
<Button x:Name="ChannelMarkerBtn" Width="40" Height="40" Click="ChannelMarkerBtn_Click" Margin="5,0,0,0" ToolTip="Transmit Channel Marker" Padding="0"
<Button x:Name="ChannelMarkerBtn" Width="38" Height="40" Click="ChannelMarkerBtn_Click" Margin="5,0,0,0" ToolTip="Transmit Channel Marker" Padding="0"
Style="{StaticResource MaterialDesignPaperDarkButton}">
<Image Source="/dvmconsole;component/Assets/channelmarker.png" Width="36" Height="40"/>
</Button>
<Button x:Name="ChannelCallHistoryBtn" Width="38" Height="40" Click="ChannelCallHistoryBtn_Click" Margin="5,0,0,0" ToolTip="Channel Call History" Padding="0"
Style="{StaticResource MaterialDesignPaperDarkButton}">
<Image Source="/dvmconsole;component/Assets/history.png" Width="32" Height="40"/>
</Button>
</StackPanel>
</Grid>
</Border>

@ -45,6 +45,8 @@ namespace dvmconsole.Controls
public readonly static LinearGradientBrush GREEN_GRADIENT; // Clear Rx Color
public readonly static LinearGradientBrush ORANGE_GRADIENT; // Encrypted Rx Color
private const string ERR_NO_LOADED_ENC_KEY = "does not have a loaded encryption key";
private readonly SelectedChannelsManager selectedChannelsManager;
private readonly AudioManager audioManager;
@ -95,10 +97,46 @@ namespace dvmconsole.Controls
private CallHistoryWindow callHistoryWindow;
private static int ChannelIdx = 0;
/*
** Events
*/
/// <summary>
/// Event action that handles the PTT button being clicked.
/// </summary>
public event EventHandler<ChannelBox> PTTButtonClicked;
/// <summary>
/// Event action that handles the PTT button being pressed.
/// </summary>
public event EventHandler<ChannelBox> PTTButtonPressed;
/// <summary>
/// Event action that handles the PTT button being released.
/// </summary>
public event EventHandler<ChannelBox> PTTButtonReleased;
/// <summary>
/// Event action that handles the page button being clicked.
/// </summary>
public event EventHandler<ChannelBox> PageButtonClicked;
/// <summary>
/// Event action that handles the hold channel button being clicked.
/// </summary>
public event EventHandler<ChannelBox> HoldChannelButtonClicked;
/// <summary>
/// Event action that occurs when a property changes on this control.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/*
** Properties
*/
/// <summary>
/// Private internal reference ID for this channel.
/// </summary>
public int InternalID { get; private set; }
/// <summary>
/// Textual name of channel.
/// </summary>
@ -129,35 +167,6 @@ namespace dvmconsole.Controls
}
}
/*
** Events
*/
/// <summary>
/// Event action that handles the PTT button being clicked.
/// </summary>
public event EventHandler<ChannelBox> PTTButtonClicked;
/// <summary>
/// Event action that handles the PTT button being pressed.
/// </summary>
public event EventHandler<ChannelBox> PTTButtonPressed;
/// <summary>
/// Event action that handles the PTT button being released.
/// </summary>
public event EventHandler<ChannelBox> PTTButtonReleased;
/// <summary>
/// Event action that handles the page button being clicked.
/// </summary>
public event EventHandler<ChannelBox> PageButtonClicked;
/// <summary>
/// Event action that handles the hold channel button being clicked.
/// </summary>
public event EventHandler<ChannelBox> HoldChannelButtonClicked;
/// <summary>
/// Event action that occurs when a property changes on this control.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Last Packet Time
/// </summary>
@ -328,7 +337,6 @@ namespace dvmconsole.Controls
/// </summary>
public uint RxStreamId { get; set; }
/*
** Methods
*/
@ -338,6 +346,8 @@ namespace dvmconsole.Controls
/// </summary>
static ChannelBox()
{
ChannelIdx = 0;
GRAY_GRADIENT = new LinearGradientBrush
{
StartPoint = new Point(0.5, 0),
@ -419,6 +429,9 @@ namespace dvmconsole.Controls
{
InitializeComponent();
this.InternalID = ChannelIdx;
ChannelIdx++;
DataContext = this;
this.selectedChannelsManager = selectedChannelsManager;
@ -427,6 +440,7 @@ namespace dvmconsole.Controls
flashingBackgroundManager = new FlashingBackgroundManager(this);
callHistoryWindow = new CallHistoryWindow(SettingsManager.Instance, MAX_CALL_HISTORY);
callHistoryWindow.Title = $"Call History - Channel: {channelName}";
ChannelName = channelName;
ChannelMode = "P25";
@ -454,14 +468,20 @@ namespace dvmconsole.Controls
PttButton.Background = GRAY_GRADIENT;
PageSelectButton.Background = GRAY_GRADIENT;
ChannelMarkerBtn.Background = GRAY_GRADIENT;
ChannelCallHistoryBtn.Background = GRAY_GRADIENT;
DisableControls();
if (SystemName == MainWindow.PLAYBACKSYS || ChannelName == MainWindow.PLAYBACKCHNAME || DstId == MainWindow.PLAYBACKTG)
{
PttButton.IsEnabled = false;
PageSelectButton.IsEnabled = false;
PageSelectButton.Visibility = Visibility.Hidden;
ChannelMarkerBtn.IsEnabled = false;
ChannelMarkerBtn.Visibility = Visibility.Hidden;
ChannelCallHistoryBtn.IsEnabled = false;
ChannelCallHistoryBtn.Visibility = Visibility.Hidden;
}
// initialize external AMBE vocoder
@ -485,8 +505,9 @@ namespace dvmconsole.Controls
private void EnableControls()
{
PttButton.IsEnabled = true;
ChannelMarkerBtn.IsEnabled = true;
PageSelectButton.IsEnabled = true;
ChannelMarkerBtn.IsEnabled = true;
ChannelCallHistoryBtn.IsEnabled = true;
VolumeSlider.IsEnabled = true;
}
@ -497,8 +518,9 @@ namespace dvmconsole.Controls
private void DisableControls()
{
PttButton.IsEnabled = false;
ChannelMarkerBtn.IsEnabled = false;
PageSelectButton.IsEnabled = false;
ChannelMarkerBtn.IsEnabled = false;
ChannelCallHistoryBtn.IsEnabled = false;
VolumeSlider.IsEnabled = false;
}
@ -539,6 +561,9 @@ namespace dvmconsole.Controls
PageSelectButton.Background = GRAY_GRADIENT;
}
/// <summary>
///
/// </summary>
private void UpdateHoldColor()
{
if (HoldState)
@ -646,10 +671,22 @@ namespace dvmconsole.Controls
selectedChannelsManager.RemoveSelectedChannel(this);
}
/// <summary>
///
/// </summary>
/// <param name="pttState"></param>
public void TriggerPTTState(bool pttState)
{
if (!IsSelected)
return;
if (IsTxEncrypted && !Crypter.HasKey())
{
MessageBox.Show($"{ChannelName} {ERR_NO_LOADED_ENC_KEY}.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
PttState = false;
return;
}
PttState = pttState;
PTTButtonClicked?.Invoke(null, this);
}
@ -664,6 +701,13 @@ namespace dvmconsole.Controls
if (!IsSelected)
return;
if (IsTxEncrypted && !Crypter.HasKey())
{
MessageBox.Show($"{ChannelName} {ERR_NO_LOADED_ENC_KEY}.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
PttState = false;
return;
}
PttState = !PttState;
PTTButtonClicked?.Invoke(sender, this);
}
@ -696,6 +740,13 @@ namespace dvmconsole.Controls
if (!IsSelected)
return;
if (IsTxEncrypted && !Crypter.HasKey())
{
MessageBox.Show($"{ChannelName} {ERR_NO_LOADED_ENC_KEY}.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
PttState = false;
return;
}
if (PttState)
await Task.Delay(500);
@ -763,6 +814,19 @@ namespace dvmconsole.Controls
HoldChannelButtonClicked.Invoke(sender, this);
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ChannelCallHistoryBtn_Click(object sender, RoutedEventArgs e)
{
if (!IsSelected)
return;
callHistoryWindow.Show();
}
/// <summary>
///
/// </summary>

@ -251,6 +251,9 @@ namespace dvmconsole
if (cpgChannel.Tgid != e.DstId.ToString())
continue;
if (channel.PttState)
continue;
if (!systemStatuses.ContainsKey(cpgChannel.Name + e.Slot))
systemStatuses[cpgChannel.Name + e.Slot] = new SlotStatus();
@ -263,10 +266,23 @@ namespace dvmconsole
channel.LastPktTime = pktTime;
// is the Rx stream ID being Rx'ed on any of our other channels?
bool duplicateRx = false;
foreach (ChannelBox other in selectedChannelsManager.GetSelectedChannels())
{
if (other.InternalID == channel.InternalID)
continue;
if ((other.RxStreamId > 0 && other.RxStreamId == e.StreamId) && other.InternalID != channel.InternalID)
{
duplicateRx = true;
break;
}
}
// is this duplicate traffic?
if ((channel.PeerId > 0 && channel.RxStreamId > 0) && (e.PeerId != channel.PeerId && e.StreamId == channel.RxStreamId))
if (((channel.PeerId > 0 && channel.RxStreamId > 0) && (e.PeerId != channel.PeerId && e.StreamId == channel.RxStreamId)) || duplicateRx)
{
Log.WriteLine($"({system.Name}) DMRD: Traffic *IGNORE DUP TRAF* PEER {e.PeerId} CALL_START PEER ID {channel.PeerId} SRC_ID {e.SrcId} TGID {e.DstId} ALGID {channel.algId} KID {channel.kId} [STREAM ID {e.StreamId}]");
Log.WriteLine($"({system.Name}) DMRD: Traffic *IGNORE DUP TRAF* PEER {e.PeerId} CALL_START PEER ID {channel.PeerId} SYS {system.Name} SRC_ID {e.SrcId} TGID {e.DstId} ALGID {channel.algId} KID {channel.kId} [STREAM ID {e.StreamId}]");
continue;
}
@ -279,7 +295,7 @@ namespace dvmconsole
// if we have a count of Tx channels this means we're sourcing traffic for the incoming stream ID
if (txChannels.Count() > 0)
{
Log.WriteLine($"({system.Name}) DMRD: Traffic *IGNORE TX TRAF * PEER {e.PeerId} CALL_START PEER ID {channel.PeerId} SRC_ID {e.SrcId} TGID {e.DstId} ALGID {channel.algId} KID {channel.kId} [STREAM ID {e.StreamId}]");
Log.WriteLine($"({system.Name}) DMRD: Traffic *IGNORE TX TRAF * PEER {e.PeerId} CALL_START PEER ID {channel.PeerId} SYS {system.Name} SRC_ID {e.SrcId} TGID {e.DstId} ALGID {channel.algId} KID {channel.kId} [STREAM ID {e.StreamId}]");
continue;
}
@ -291,7 +307,7 @@ namespace dvmconsole
channel.RxStreamId = e.StreamId;
systemStatuses[cpgChannel.Name + e.Slot].RxStart = pktTime;
Log.WriteLine($"({system.Name}) DMRD: Traffic *CALL START * PEER {e.PeerId} SRC_ID {e.SrcId} TGID {e.DstId} TS {e.Slot} [STREAM ID {e.StreamId}]");
Log.WriteLine($"({system.Name}) DMRD: Traffic *CALL START * PEER {e.PeerId} SYS {system.Name} SRC_ID {e.SrcId} TGID {e.DstId} TS {e.Slot} [STREAM ID {e.StreamId}]");
// if we can, use the LC from the voice header as to keep all options intact
if ((e.FrameType == FrameType.DATA_SYNC) && (e.DataType == DMRDataType.VOICE_LC_HEADER))
@ -340,7 +356,7 @@ namespace dvmconsole
channel.RxStreamId = 0;
TimeSpan callDuration = pktTime - systemStatuses[cpgChannel.Name + e.Slot].RxStart;
Log.WriteLine($"({system.Name}) DMRD: Traffic *CALL END * PEER {e.PeerId} SRC_ID {e.SrcId} TGID {e.DstId} TS {e.Slot} DUR {callDuration} [STREAM ID {e.StreamId}]");
Log.WriteLine($"({system.Name}) DMRD: Traffic *CALL END * PEER {e.PeerId} SYS {system.Name} SRC_ID {e.SrcId} TGID {e.DstId} TS {e.Slot} DUR {callDuration} [STREAM ID {e.StreamId}]");
channel.Background = ChannelBox.BLUE_GRADIENT;
channel.VolumeMeterLevel = 0;
callHistoryWindow.ChannelUnkeyed(cpgChannel.Name, (int)e.SrcId);

@ -448,6 +448,9 @@ namespace dvmconsole
if (cpgChannel.Tgid != e.DstId.ToString())
continue;
if (channel.PttState)
continue;
if (e.DUID == P25DUID.TSDU || e.DUID == P25DUID.PDU)
continue;
@ -479,10 +482,23 @@ namespace dvmconsole
}
}
// is the Rx stream ID being Rx'ed on any of our other channels?
bool duplicateRx = false;
foreach (ChannelBox other in selectedChannelsManager.GetSelectedChannels())
{
if (other.InternalID == channel.InternalID)
continue;
if ((other.RxStreamId > 0 && other.RxStreamId == e.StreamId) && other.InternalID != channel.InternalID)
{
duplicateRx = true;
break;
}
}
// is this duplicate traffic?
if ((channel.PeerId > 0 && channel.RxStreamId > 0) && (e.PeerId != channel.PeerId && e.StreamId == channel.RxStreamId))
if (((channel.PeerId > 0 && channel.RxStreamId > 0) && (e.PeerId != channel.PeerId && e.StreamId == channel.RxStreamId)) || duplicateRx)
{
Log.WriteLine($"({system.Name}) P25D: Traffic *IGNORE DUP TRAF* PEER {e.PeerId} CALL_START PEER ID {channel.PeerId} SRC_ID {e.SrcId} TGID {e.DstId} ALGID {channel.algId} KID {channel.kId} [STREAM ID {e.StreamId}]");
Log.WriteLine($"({system.Name}) P25D: Traffic *IGNORE DUP TRAF* PEER {e.PeerId} CALL_START PEER ID {channel.PeerId} SYS {system.Name} SRC_ID {e.SrcId} TGID {e.DstId} ALGID {channel.algId} KID {channel.kId} [STREAM ID {e.StreamId}]");
continue;
}
@ -495,7 +511,7 @@ namespace dvmconsole
// if we have a count of Tx channels this means we're sourcing traffic for the incoming stream ID
if (txChannels.Count() > 0)
{
Log.WriteLine($"({system.Name}) P25D: Traffic *IGNORE TX TRAF * PEER {e.PeerId} CALL_START PEER ID {channel.PeerId} SRC_ID {e.SrcId} TGID {e.DstId} ALGID {channel.algId} KID {channel.kId} [STREAM ID {e.StreamId}]");
Log.WriteLine($"({system.Name}) P25D: Traffic *IGNORE TX TRAF * PEER {e.PeerId} CALL_START PEER ID {channel.PeerId} SYS {system.Name} SRC_ID {e.SrcId} TGID {e.DstId} ALGID {channel.algId} KID {channel.kId} [STREAM ID {e.StreamId}]");
continue;
}
@ -507,7 +523,7 @@ namespace dvmconsole
channel.RxStreamId = e.StreamId;
slot.RxStart = pktTime;
Log.WriteLine($"({system.Name}) P25D: Traffic *CALL START * PEER {e.PeerId} SRC_ID {e.SrcId} TGID {e.DstId} ALGID {channel.algId} KID {channel.kId} [STREAM ID {e.StreamId}]");
Log.WriteLine($"({system.Name}) P25D: Traffic *CALL START * PEER {e.PeerId} SYS {system.Name} SRC_ID {e.SrcId} TGID {e.DstId} ALGID {channel.algId} KID {channel.kId} [STREAM ID {e.StreamId}]");
FneUtils.Memset(channel.mi, 0x00, P25Defines.P25_MI_LENGTH);
@ -520,7 +536,7 @@ namespace dvmconsole
callHistoryWindow.ChannelKeyed(cpgChannel.Name, (int)e.SrcId, encrypted);
if (channel.algId != P25Defines.P25_ALGO_UNENCRYPT)
Log.WriteLine($"({system.Name}) P25D: Traffic *CALL ENC PARMS * PEER {e.PeerId} SRC_ID {e.SrcId} TGID {e.DstId} ALGID {channel.algId} KID {channel.kId} [STREAM ID {e.StreamId}]");
Log.WriteLine($"({system.Name}) P25D: Traffic *CALL ENC PARMS * PEER {e.PeerId} SYS {system.Name} SRC_ID {e.SrcId} TGID {e.DstId} ALGID {channel.algId} KID {channel.kId} [STREAM ID {e.StreamId}]");
}
// reset the channel state if we're not Rx
@ -539,7 +555,7 @@ namespace dvmconsole
channel.RxStreamId = 0;
TimeSpan callDuration = pktTime - slot.RxStart;
Log.WriteLine($"({system.Name}) P25D: Traffic *CALL END * PEER {e.PeerId} SRC_ID {e.SrcId} TGID {e.DstId} DUR {callDuration} [STREAM ID {e.StreamId}]");
Log.WriteLine($"({system.Name}) P25D: Traffic *CALL END * PEER {e.PeerId} SYS {system.Name} SRC_ID {e.SrcId} TGID {e.DstId} DUR {callDuration} [STREAM ID {e.StreamId}]");
channel.Background = ChannelBox.BLUE_GRADIENT;
channel.VolumeMeterLevel = 0;
callHistoryWindow.ChannelUnkeyed(cpgChannel.Name, (int)e.SrcId);

Loading…
Cancel
Save

Powered by TurnKey Linux.