Add support for two way auio

pull/1/head
php 1 year ago
parent 937a03eb41
commit 238b598afe

@ -16,7 +16,7 @@
<TextBlock Text="{Binding SystemName}" Foreground="LightGray" FontSize="12" Grid.Row="1"/> <TextBlock Text="{Binding SystemName}" Foreground="LightGray" FontSize="12" Grid.Row="1"/>
<TextBlock Text="{Binding LastSrcId}" Foreground="LightGray" FontSize="12" Grid.Row="2"/> <TextBlock Text="{Binding LastSrcId}" Foreground="LightGray" FontSize="12" Grid.Row="2"/>
<Button Content="PTT" Width="80" Margin="0,5,0,0" Background="Green" Foreground="White" <Button Content="PTT" Width="80" Margin="0,5,0,0" Background="Green" Foreground="White" Name="PttButton"
HorizontalAlignment="Left" Grid.Row="3" Click="PTTButton_Click"/> HorizontalAlignment="Left" Grid.Row="3" Click="PTTButton_Click"/>
</Grid> </Grid>
</Border> </Border>

@ -18,6 +18,7 @@
* *
*/ */
using System.ComponentModel;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
@ -25,15 +26,42 @@ using System.Windows.Media;
namespace WhackerLinkConsoleV2.Controls namespace WhackerLinkConsoleV2.Controls
{ {
public partial class ChannelBox : UserControl public partial class ChannelBox : UserControl, INotifyPropertyChanged
{ {
private readonly SelectedChannelsManager _selectedChannelsManager;
private bool _pttState;
private string _lastSrcId = "0";
public event EventHandler<ChannelBox> PTTButtonClicked;
public event PropertyChangedEventHandler PropertyChanged;
public string ChannelName { get; set; } public string ChannelName { get; set; }
public string SystemName { get; set; } public string SystemName { get; set; }
public string LastSrcId { get; set; } = "0";
public event EventHandler<ChannelBox> PTTButtonClicked; public string LastSrcId
{
get => _lastSrcId;
set
{
if (_lastSrcId != value)
{
_lastSrcId = value;
OnPropertyChanged(nameof(LastSrcId));
}
}
}
private readonly SelectedChannelsManager _selectedChannelsManager; public bool PttState
{
get => _pttState;
set
{
_pttState = value;
UpdatePTTColor();
}
}
public string VoiceChannel { get; set; }
public bool IsEditMode { get; set; } public bool IsEditMode { get; set; }
@ -77,6 +105,16 @@ namespace WhackerLinkConsoleV2.Controls
} }
} }
private void UpdatePTTColor()
{
if (IsEditMode) return;
if (PttState)
PttButton.Background = new SolidColorBrush(Colors.Red);
else
PttButton.Background = new SolidColorBrush(Colors.Green);
}
private void UpdateBackground() private void UpdateBackground()
{ {
Background = IsSelected ? Brushes.DodgerBlue : Brushes.DarkGray; Background = IsSelected ? Brushes.DodgerBlue : Brushes.DarkGray;
@ -84,7 +122,13 @@ namespace WhackerLinkConsoleV2.Controls
private void PTTButton_Click(object sender, RoutedEventArgs e) private void PTTButton_Click(object sender, RoutedEventArgs e)
{ {
PttState = !PttState;
PTTButtonClicked.Invoke(sender, this); PTTButtonClicked.Invoke(sender, this);
} }
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
} }
} }

@ -34,6 +34,10 @@ using WhackerLinkLib.Utils;
using WhackerLinkLib.Models; using WhackerLinkLib.Models;
using WhackerLinkLib.Handlers; using WhackerLinkLib.Handlers;
using System.Net; using System.Net;
using NAudio.Wave;
using WhackerLinkLib.Interfaces;
using WhackerLinkLib.Models.IOSP;
using Nancy;
namespace WhackerLinkConsoleV2 namespace WhackerLinkConsoleV2
{ {
@ -47,17 +51,40 @@ namespace WhackerLinkConsoleV2
private double _offsetX; private double _offsetX;
private double _offsetY; private double _offsetY;
private bool _isDragging; private bool _isDragging;
private bool _stopSending;
private SettingsManager _settingsManager = new SettingsManager(); private SettingsManager _settingsManager = new SettingsManager();
private SelectedChannelsManager _selectedChannelsManager; private SelectedChannelsManager _selectedChannelsManager;
private WebSocketManager _webSocketManager = new WebSocketManager(); private WebSocketManager _webSocketManager = new WebSocketManager();
private readonly WaveInEvent _waveIn;
private readonly WaveOutEvent _waveOut;
private readonly BufferedWaveProvider _waveProvider;
public MainWindow() public MainWindow()
{ {
InitializeComponent(); InitializeComponent();
_settingsManager.LoadSettings(); _settingsManager.LoadSettings();
_selectedChannelsManager = new SelectedChannelsManager(); _selectedChannelsManager = new SelectedChannelsManager();
_waveIn = new WaveInEvent
{
WaveFormat = new WaveFormat(8000, 16, 1)
};
_waveIn.DataAvailable += WaveIn_DataAvailable;
_waveIn.RecordingStopped += WaveIn_RecordingStopped;
_waveIn.StartRecording();
_waveOut = new WaveOutEvent();
_waveProvider = new BufferedWaveProvider(new WaveFormat(8000, 16, 1))
{
DiscardOnBufferOverflow = true
};
_waveOut.Init(_waveProvider);
_waveOut.Play();
_selectedChannelsManager.SelectedChannelsChanged += SelectedChannelsChanged; _selectedChannelsManager.SelectedChannelsChanged += SelectedChannelsChanged;
Loaded += MainWindow_Loaded; Loaded += MainWindow_Loaded;
} }
@ -141,9 +168,13 @@ namespace WhackerLinkConsoleV2
_webSocketManager.AddWebSocketHandler(system.Name); _webSocketManager.AddWebSocketHandler(system.Name);
IWebSocketHandler handler = _webSocketManager.GetWebSocketHandler(system.Name);
handler.OnVoiceChannelResponse += HandleVoiceResponse;
handler.OnVoiceChannelRelease += HandleVoiceRelease;
handler.OnAudioData += HandleReceivedAudio;
Task.Factory.StartNew(() => Task.Factory.StartNew(() =>
{ {
WebSocketHandler handler = _webSocketManager.GetWebSocketHandler(system.Name);
handler.Connect(system.Address, system.Port); handler.Connect(system.Address, system.Port);
handler.OnUnitRegistrationResponse += (response) => handler.OnUnitRegistrationResponse += (response) =>
@ -243,24 +274,26 @@ namespace WhackerLinkConsoleV2
AdjustCanvasHeight(); AdjustCanvasHeight();
} }
private void HandleChannelUpdate(ChannelBox channelBox, string lastSrc = "0", bool receiving = false) private void WaveIn_RecordingStopped(object sender, EventArgs e)
{
/* stub */
}
private void WaveIn_DataAvailable(object sender, WaveInEventArgs e)
{ {
if (receiving) foreach (ChannelBox channel in _selectedChannelsManager.GetSelectedChannels())
{ {
Dispatcher.Invoke(() => Codeplug.System system = Codeplug.GetSystemForChannel(channel.ChannelName);
Codeplug.Channel cpgChannel = Codeplug.GetChannelByName(channel.ChannelName);
IWebSocketHandler handler = _webSocketManager.GetWebSocketHandler(system.Name);
if (channel.IsSelected && channel.VoiceChannel != null && !_stopSending)
{ {
channelBox.LastSrcId = lastSrc; handler.SendMessage(PacketFactory.CreateVoicePacket(system.Rid, cpgChannel.Tgid, channel.VoiceChannel, e.Buffer, system.Site));
if (channelBox.IsSelected)
channelBox.Background = new SolidColorBrush(Colors.Green);
});
} else } else
{ {
Dispatcher.Invoke(() => _stopSending = true;
{ }
channelBox.LastSrcId = lastSrc;
if (channelBox.IsSelected)
channelBox.Background = new SolidColorBrush(Colors.Blue);
});
} }
} }
@ -270,9 +303,9 @@ namespace WhackerLinkConsoleV2
{ {
Codeplug.System system = Codeplug.GetSystemForChannel(channel.ChannelName); Codeplug.System system = Codeplug.GetSystemForChannel(channel.ChannelName);
Codeplug.Channel cpgChannel = Codeplug.GetChannelByName(channel.ChannelName); Codeplug.Channel cpgChannel = Codeplug.GetChannelByName(channel.ChannelName);
WebSocketHandler handler = _webSocketManager.GetWebSocketHandler(system.Name); IWebSocketHandler handler = _webSocketManager.GetWebSocketHandler(system.Name);
if (channel.IsSelected) if (channel.IsSelected && handler.IsConnected)
handler.SendMessage(PacketFactory.CreateAffiliationRequest(system.Rid, cpgChannel.Tgid, system.Site)); handler.SendMessage(PacketFactory.CreateAffiliationRequest(system.Rid, cpgChannel.Tgid, system.Site));
} }
} }
@ -292,6 +325,97 @@ namespace WhackerLinkConsoleV2
} }
} }
private void HandleReceivedAudio(byte[] audioData, VoiceChannel voiceChannel)
{
foreach (ChannelBox channel in _selectedChannelsManager.GetSelectedChannels())
{
Codeplug.System system = Codeplug.GetSystemForChannel(channel.ChannelName);
Codeplug.Channel cpgChannel = Codeplug.GetChannelByName(channel.ChannelName);
IWebSocketHandler handler = _webSocketManager.GetWebSocketHandler(system.Name);
if (voiceChannel.SrcId != system.Rid && voiceChannel.Frequency == channel.VoiceChannel && voiceChannel.DstId == cpgChannel.Tgid)
{
_waveProvider.AddSamples(audioData, 0, audioData.Length);
}
}
}
private void HandleVoiceRelease(GRP_VCH_RLS response)
{
foreach (ChannelBox channel in _selectedChannelsManager.GetSelectedChannels())
{
Codeplug.System system = Codeplug.GetSystemForChannel(channel.ChannelName);
Codeplug.Channel cpgChannel = Codeplug.GetChannelByName(channel.ChannelName);
IWebSocketHandler handler = _webSocketManager.GetWebSocketHandler(system.Name);
if (response.DstId == cpgChannel.Tgid && response.SrcId != system.Rid)
{
Dispatcher.Invoke(() =>
{
if (channel.IsSelected)
channel.Background = Brushes.DodgerBlue;
else
channel.Background = new SolidColorBrush(Colors.DarkGray);
});
channel.VoiceChannel = null;
}
}
}
private void HandleVoiceResponse(GRP_VCH_RSP response)
{
foreach (ChannelBox channel in _selectedChannelsManager.GetSelectedChannels())
{
Codeplug.System system = Codeplug.GetSystemForChannel(channel.ChannelName);
Codeplug.Channel cpgChannel = Codeplug.GetChannelByName(channel.ChannelName);
IWebSocketHandler handler = _webSocketManager.GetWebSocketHandler(system.Name);
if (channel.PttState && response.Status == (int)ResponseType.GRANT && response.Channel != null && response.SrcId == system.Rid && response.DstId == cpgChannel.Tgid)
{
channel.VoiceChannel = response.Channel;
_stopSending = false;
} else if (response.Status == (int)ResponseType.GRANT && response.SrcId != system.Rid && response.DstId == cpgChannel.Tgid)
{
channel.VoiceChannel = response.Channel;
channel.LastSrcId = "Last SRC: " + response.SrcId;
Dispatcher.Invoke(() =>
{
channel.Background = new SolidColorBrush(Colors.DarkCyan);
});
}
else
{
Dispatcher.Invoke(() =>
{
if (channel.IsSelected)
Background = new SolidColorBrush(Colors.DodgerBlue);
else
Background = new SolidColorBrush(Colors.Gray);
});
channel.VoiceChannel = null;
_stopSending = true;
}
}
}
private void ChannelBox_PTTButtonClicked(object sender, ChannelBox e)
{
Codeplug.System system = Codeplug.GetSystemForChannel(e.ChannelName);
Codeplug.Channel cpgChannel = Codeplug.GetChannelByName(e.ChannelName);
IWebSocketHandler handler = _webSocketManager.GetWebSocketHandler(system.Name);
if (e.PttState)
handler.SendMessage(PacketFactory.CreateVoiceChannelRequest(system.Rid, cpgChannel.Tgid, system.Site));
else
{
_stopSending = true;
handler.SendMessage(PacketFactory.CreateVoiceChannelRelease(system.Rid, cpgChannel.Tgid, e.VoiceChannel, system.Site));
e.VoiceChannel = null;
}
}
private void ChannelBox_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) private void ChannelBox_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{ {
if (!isEditMode || !(sender is UIElement element)) return; if (!isEditMode || !(sender is UIElement element)) return;
@ -333,11 +457,6 @@ namespace WhackerLinkConsoleV2
_draggedElement = null; _draggedElement = null;
} }
private void ChannelBox_PTTButtonClicked(object sender, ChannelBox channelBox)
{
MessageBox.Show($"Imagine you were talking on {channelBox.ChannelName} rn", "PTT Action", MessageBoxButton.OK);
}
private void SystemStatusBox_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => ChannelBox_MouseLeftButtonDown(sender, e); private void SystemStatusBox_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => ChannelBox_MouseLeftButtonDown(sender, e);
private void SystemStatusBox_MouseMove(object sender, MouseEventArgs e) => ChannelBox_MouseMove(sender, e); private void SystemStatusBox_MouseMove(object sender, MouseEventArgs e) => ChannelBox_MouseMove(sender, e);

@ -11,6 +11,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="NAudio" Version="2.2.1" />
<PackageReference Include="YamlDotNet" Version="16.2.0" /> <PackageReference Include="YamlDotNet" Version="16.2.0" />
</ItemGroup> </ItemGroup>

Loading…
Cancel
Save

Powered by TurnKey Linux.