add support for DES-OFB; fix alert tone to behave as expected with primary channel; update fnecore submodule

pull/1/head
firealarmss 11 months ago
parent f13a4775e2
commit 5eb294f273

@ -42,7 +42,7 @@ zones:
tgid: "2001" tgid: "2001"
# Encryption Key Id (If 0 or blank, will be assumed clear) # Encryption Key Id (If 0 or blank, will be assumed clear)
keyId: 0x50 keyId: 0x50
# Algorithm AES ("aes"), ADP/ARC4 ("arc4"), None ("none") # Algorithm AES ("aes"), DES-OFB ("des"), ADP/ARC4 ("arc4"), None ("none")
algo: "aes" algo: "aes"
# Ignored now, we use dvmfne KMM support (This will be used in the future to ovveride FNE KMM support) # Ignored now, we use dvmfne KMM support (This will be used in the future to ovveride FNE KMM support)
encryptionKey: null encryptionKey: null

@ -206,6 +206,8 @@ namespace dvmconsole
{ {
case "aes": case "aes":
return P25Defines.P25_ALGO_AES; return P25Defines.P25_ALGO_AES;
case "des":
return P25Defines.P25_ALGO_DES;
case "arc4": case "arc4":
return P25Defines.P25_ALGO_ARC4; return P25Defines.P25_ALGO_ARC4;
default: default:

@ -11,12 +11,9 @@
* *
*/ */
using System.Diagnostics;
using fnecore; using fnecore;
using fnecore.DMR; using fnecore.DMR;
using NAudio.Wave;
namespace dvmconsole namespace dvmconsole
{ {
/// <summary> /// <summary>

@ -651,122 +651,125 @@ namespace dvmconsole
{ {
try try
{ {
var channel = selectedChannelsManager.PrimaryChannel; ChannelBox primaryChannel = selectedChannelsManager.PrimaryChannel;
if (channel == null) List<ChannelBox> channelsToProcess = primaryChannel != null
? new List<ChannelBox> { primaryChannel }
: selectedChannelsManager.GetSelectedChannels().ToList();
foreach (ChannelBox channel in channelsToProcess)
{ {
return;
}
if (channel.SystemName == PLAYBACKSYS || channel.ChannelName == PLAYBACKCHNAME || channel.DstId == PLAYBACKTG) if (channel.SystemName == PLAYBACKSYS || channel.ChannelName == PLAYBACKCHNAME || channel.DstId == PLAYBACKTG)
return; return;
Codeplug.System system = Codeplug.GetSystemForChannel(channel.ChannelName); Codeplug.System system = Codeplug.GetSystemForChannel(channel.ChannelName);
if (system == null) if (system == null)
{ {
Log.WriteLine($"{channel.ChannelName} refers to an {INVALID_SYSTEM} {channel.SystemName}. {ERR_INVALID_CODEPLUG}. {ERR_SKIPPING_AUDIO}."); Log.WriteLine($"{channel.ChannelName} refers to an {INVALID_SYSTEM} {channel.SystemName}. {ERR_INVALID_CODEPLUG}. {ERR_SKIPPING_AUDIO}.");
channel.IsSelected = false; channel.IsSelected = false;
selectedChannelsManager.RemoveSelectedChannel(channel); selectedChannelsManager.RemoveSelectedChannel(channel);
return; return;
} }
Codeplug.Channel cpgChannel = Codeplug.GetChannelByName(channel.ChannelName); Codeplug.Channel cpgChannel = Codeplug.GetChannelByName(channel.ChannelName);
if (cpgChannel == null) if (cpgChannel == null)
{ {
Log.WriteLine($"{channel.ChannelName} refers to an {INVALID_CODEPLUG_CHANNEL}. {ERR_INVALID_CODEPLUG}. {ERR_SKIPPING_AUDIO}."); Log.WriteLine($"{channel.ChannelName} refers to an {INVALID_CODEPLUG_CHANNEL}. {ERR_INVALID_CODEPLUG}. {ERR_SKIPPING_AUDIO}.");
channel.IsSelected = false; channel.IsSelected = false;
selectedChannelsManager.RemoveSelectedChannel(channel); selectedChannelsManager.RemoveSelectedChannel(channel);
return; return;
} }
PeerSystem fne = fneSystemManager.GetFneSystem(system.Name); PeerSystem fne = fneSystemManager.GetFneSystem(system.Name);
if (fne == null) if (fne == null)
{ {
Log.WriteLine($"{channel.ChannelName} has a {ERR_INVALID_FNE_REF}. {ERR_INVALID_CODEPLUG}. {ERR_SKIPPING_AUDIO}."); Log.WriteLine($"{channel.ChannelName} has a {ERR_INVALID_FNE_REF}. {ERR_INVALID_CODEPLUG}. {ERR_SKIPPING_AUDIO}.");
channel.IsSelected = false; channel.IsSelected = false;
selectedChannelsManager.RemoveSelectedChannel(channel); selectedChannelsManager.RemoveSelectedChannel(channel);
return; return;
} }
// if (channel.PageState || (forHold && channel.HoldState) || primaryChannel != null)
if (channel.PageState || (forHold && channel.HoldState)) {
{ byte[] pcmData;
byte[] pcmData;
Task.Run(async () => { Task.Run(async () =>
using (var waveReader = new WaveFileReader(filePath))
{ {
if (waveReader.WaveFormat.Encoding != WaveFormatEncoding.Pcm || using (var waveReader = new WaveFileReader(filePath))
waveReader.WaveFormat.SampleRate != 8000 ||
waveReader.WaveFormat.BitsPerSample != 16 ||
waveReader.WaveFormat.Channels != 1)
{ {
MessageBox.Show("The alert tone must be PCM 16-bit, Mono, 8000Hz format.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); if (waveReader.WaveFormat.Encoding != WaveFormatEncoding.Pcm ||
return; waveReader.WaveFormat.SampleRate != 8000 ||
} waveReader.WaveFormat.BitsPerSample != 16 ||
waveReader.WaveFormat.Channels != 1)
{
MessageBox.Show("The alert tone must be PCM 16-bit, Mono, 8000Hz format.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
using (MemoryStream ms = new MemoryStream()) using (MemoryStream ms = new MemoryStream())
{ {
waveReader.CopyTo(ms); waveReader.CopyTo(ms);
pcmData = ms.ToArray(); pcmData = ms.ToArray();
}
} }
}
int chunkSize = 1600; int chunkSize = 1600;
int totalChunks = (pcmData.Length + chunkSize - 1) / chunkSize; int totalChunks = (pcmData.Length + chunkSize - 1) / chunkSize;
if (pcmData.Length % chunkSize != 0) if (pcmData.Length % chunkSize != 0)
{ {
byte[] paddedData = new byte[totalChunks * chunkSize]; byte[] paddedData = new byte[totalChunks * chunkSize];
Buffer.BlockCopy(pcmData, 0, paddedData, 0, pcmData.Length); Buffer.BlockCopy(pcmData, 0, paddedData, 0, pcmData.Length);
pcmData = paddedData; pcmData = paddedData;
} }
Task.Run(() => Task.Run(() =>
{ {
audioManager.AddTalkgroupStream(cpgChannel.Tgid, pcmData); audioManager.AddTalkgroupStream(cpgChannel.Tgid, pcmData);
}); });
DateTime startTime = DateTime.UtcNow; DateTime startTime = DateTime.UtcNow;
for (int i = 0; i < totalChunks; i++) for (int i = 0; i < totalChunks; i++)
{ {
int offset = i * chunkSize; int offset = i * chunkSize;
byte[] chunk = new byte[chunkSize]; byte[] chunk = new byte[chunkSize];
Buffer.BlockCopy(pcmData, offset, chunk, 0, chunkSize); Buffer.BlockCopy(pcmData, offset, chunk, 0, chunkSize);
channel.chunkedPCM = AudioConverter.SplitToChunks(chunk); channel.chunkedPCM = AudioConverter.SplitToChunks(chunk);
foreach (byte[] audioChunk in channel.chunkedPCM) foreach (byte[] audioChunk in channel.chunkedPCM)
{
if (audioChunk.Length == PCM_SAMPLES_LENGTH)
{ {
if (cpgChannel.GetChannelMode() == Codeplug.ChannelMode.P25) if (audioChunk.Length == PCM_SAMPLES_LENGTH)
P25EncodeAudioFrame(audioChunk, fne, channel, cpgChannel, system); {
else if (cpgChannel.GetChannelMode() == Codeplug.ChannelMode.DMR) if (cpgChannel.GetChannelMode() == Codeplug.ChannelMode.P25)
DMREncodeAudioFrame(audioChunk, fne, channel, cpgChannel, system); P25EncodeAudioFrame(audioChunk, fne, channel, cpgChannel, system);
else if (cpgChannel.GetChannelMode() == Codeplug.ChannelMode.DMR)
DMREncodeAudioFrame(audioChunk, fne, channel, cpgChannel, system);
}
} }
}
DateTime nextPacketTime = startTime.AddMilliseconds((i + 1) * 100); DateTime nextPacketTime = startTime.AddMilliseconds((i + 1) * 100);
TimeSpan waitTime = nextPacketTime - DateTime.UtcNow; TimeSpan waitTime = nextPacketTime - DateTime.UtcNow;
if (waitTime.TotalMilliseconds > 0) if (waitTime.TotalMilliseconds > 0)
await Task.Delay(waitTime); await Task.Delay(waitTime);
} }
double totalDurationMs = ((double)pcmData.Length / 16000) + 250; double totalDurationMs = ((double)pcmData.Length / 16000) + 250;
await Task.Delay((int)totalDurationMs + 3000); await Task.Delay((int)totalDurationMs + 3000);
fne.SendP25TDU(uint.Parse(system.Rid), uint.Parse(cpgChannel.Tgid), false); fne.SendP25TDU(uint.Parse(system.Rid), uint.Parse(cpgChannel.Tgid), false);
Dispatcher.Invoke(() => Dispatcher.Invoke(() =>
{ {
if (forHold) if (forHold)
channel.PttButton.Background = ChannelBox.GRAY_GRADIENT; channel.PttButton.Background = ChannelBox.GRAY_GRADIENT;
else else
channel.PageState = false; channel.PageState = false;
});
}); });
}); }
} }
} }
catch (Exception ex) catch (Exception ex)

@ -1 +1 @@
Subproject commit 13a82b3a82054e4fe8299368c7258c51176cee87 Subproject commit 0419c2fac7351e67064437f94751bad21bc92975
Loading…
Cancel
Save

Powered by TurnKey Linux.