From dc550f312172007f6471a1296dee1f998a095c08 Mon Sep 17 00:00:00 2001 From: Denny Sheirer Date: Sun, 18 Oct 2026 04:52:14 -0400 Subject: [PATCH] #2499 JMBE settings are now carried over when cloning channel configurations and P25 JMBE settings now carry over from the parent control channel configuration when traffic channels are a mix of phase 1 and phase 2. (#2502) Co-authored-by: denny --- .../module/decode/DecoderFactory.java | 33 +++++++++++++++---- .../decode/dmr/DMRTrafficChannelManager.java | 31 ++++++++++------- .../nxdn/NXDNTrafficChannelManager.java | 27 ++++++++++----- .../decode/p25/P25TrafficChannelManager.java | 17 ++++++---- 4 files changed, 76 insertions(+), 32 deletions(-) diff --git a/src/main/java/io/github/dsheirer/module/decode/DecoderFactory.java b/src/main/java/io/github/dsheirer/module/decode/DecoderFactory.java index cf4448a9..2508a4c0 100644 --- a/src/main/java/io/github/dsheirer/module/decode/DecoderFactory.java +++ b/src/main/java/io/github/dsheirer/module/decode/DecoderFactory.java @@ -872,7 +872,10 @@ public class DecoderFactory copyAM.setSquelchAutoTrack(origAM.isSquelchAutoTrack()); return copyAM; case DMR: - return new DecodeConfigDMR(); + DecodeConfigDMR originalDMR = (DecodeConfigDMR)config; + DecodeConfigDMR copyDMR = new DecodeConfigDMR(); + transferJMBESettings(originalDMR, copyDMR); + return copyDMR; case LTR_NET: DecodeConfigLTRNet originalLTRNet = (DecodeConfigLTRNet)config; DecodeConfigLTRNet copyLTRNet = new DecodeConfigLTRNet(); @@ -908,17 +911,20 @@ public class DecoderFactory copyNXDN.setChannelMap(origNXDN.getChannelMap()); copyNXDN.setTransmissionMode(origNXDN.getTransmissionMode()); copyNXDN.setTrafficChannelPoolSize(origNXDN.getTrafficChannelPoolSize()); + transferJMBESettings(origNXDN, copyNXDN); return copyNXDN; case P25_PHASE1: - DecodeConfigP25Phase1 originalP25 = (DecodeConfigP25Phase1)config; - DecodeConfigP25Phase1 copyP25 = new DecodeConfigP25Phase1(); - copyP25.setIgnoreDataCalls(originalP25.getIgnoreDataCalls()); - copyP25.setModulation(originalP25.getModulation()); - copyP25.setTrafficChannelPoolSize(originalP25.getTrafficChannelPoolSize()); - return copyP25; + DecodeConfigP25Phase1 originalP25P1 = (DecodeConfigP25Phase1)config; + DecodeConfigP25Phase1 copyP25P1 = new DecodeConfigP25Phase1(); + copyP25P1.setIgnoreDataCalls(originalP25P1.getIgnoreDataCalls()); + copyP25P1.setModulation(originalP25P1.getModulation()); + copyP25P1.setTrafficChannelPoolSize(originalP25P1.getTrafficChannelPoolSize()); + transferJMBESettings(originalP25P1, copyP25P1); + return copyP25P1; case P25_PHASE2: DecodeConfigP25Phase2 originalP25P2 = (DecodeConfigP25Phase2)config; DecodeConfigP25Phase2 copyP25P2 = new DecodeConfigP25Phase2(); + transferJMBESettings(originalP25P2, copyP25P2); if(originalP25P2.getScrambleParameters() != null) { @@ -934,4 +940,17 @@ public class DecoderFactory return null; } + + /** + * Transfers the JMBE audio codec settings from one JMBE decode configuration to another. This works both ways + * since both phase 1 and phase 2 decode configurations extend from a common JMBE decode configuration. + * @param from decode configuration + * @param to decode configuration + */ + public static void transferJMBESettings(DecodeConfigJMBE from, DecodeConfigJMBE to) + { + to.setAGC(from.isAGC()); + to.setNoiseGain(from.getNoiseGain()); + to.setToneGain(from.getToneGain()); + } } \ No newline at end of file diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRTrafficChannelManager.java b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRTrafficChannelManager.java index 67441e5d..6dab5959 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRTrafficChannelManager.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRTrafficChannelManager.java @@ -65,6 +65,7 @@ import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.locks.ReentrantLock; +import org.jspecify.annotations.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -188,24 +189,15 @@ public class DMRTrafficChannelManager extends TrafficChannelManager implements I DecodeConfiguration decodeConfiguration = mParentChannel.getDecodeConfiguration(); List trafficChannelList = new ArrayList<>(); - if(decodeConfiguration instanceof DecodeConfigDMR) + if(decodeConfiguration instanceof DecodeConfigDMR decodeConfig) { - DecodeConfigDMR decodeConfig = (DecodeConfigDMR)decodeConfiguration; - int maxTrafficChannels = decodeConfig.getTrafficChannelPoolSize(); if(maxTrafficChannels > 0) { for(int x = 0; x < maxTrafficChannels; x++) { - Channel trafficChannel = new Channel("T-" + mParentChannel.getName(), ChannelType.TRAFFIC); - trafficChannel.setAliasListName(mParentChannel.getAliasListName()); - trafficChannel.setSystem(mParentChannel.getSystem()); - trafficChannel.setSite(mParentChannel.getSite()); - trafficChannel.setDecodeConfiguration(decodeConfig); - trafficChannel.setEventLogConfiguration(mParentChannel.getEventLogConfiguration()); - trafficChannel.setRecordConfiguration(mParentChannel.getRecordConfiguration()); - trafficChannelList.add(trafficChannel); + trafficChannelList.add(createTrafficChannel(decodeConfig)); } } } @@ -218,6 +210,23 @@ public class DMRTrafficChannelManager extends TrafficChannelManager implements I } } + /** + * Creates a child traffic channel that share's the same parent decode configuration + * @param decodeConfig from the parent + * @return traffic channel + */ + private @NonNull Channel createTrafficChannel(DecodeConfigDMR decodeConfig) + { + Channel trafficChannel = new Channel("T-" + mParentChannel.getName(), ChannelType.TRAFFIC); + trafficChannel.setAliasListName(mParentChannel.getAliasListName()); + trafficChannel.setSystem(mParentChannel.getSystem()); + trafficChannel.setSite(mParentChannel.getSite()); + trafficChannel.setDecodeConfiguration(decodeConfig); + trafficChannel.setEventLogConfiguration(mParentChannel.getEventLogConfiguration()); + trafficChannel.setRecordConfiguration(mParentChannel.getRecordConfiguration()); + return trafficChannel; + } + /** * Used with Capacity Plus systems to convert the existing standard channel to a traffic channel and then recreate * the original standard channel with the frequency specified for the new rest channel. diff --git a/src/main/java/io/github/dsheirer/module/decode/nxdn/NXDNTrafficChannelManager.java b/src/main/java/io/github/dsheirer/module/decode/nxdn/NXDNTrafficChannelManager.java index 1362e55e..b6356ed4 100644 --- a/src/main/java/io/github/dsheirer/module/decode/nxdn/NXDNTrafficChannelManager.java +++ b/src/main/java/io/github/dsheirer/module/decode/nxdn/NXDNTrafficChannelManager.java @@ -64,6 +64,7 @@ import java.util.Queue; import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import org.jspecify.annotations.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -147,14 +148,7 @@ public class NXDNTrafficChannelManager extends TrafficChannelManager implements { for(int x = 0; x < trafficChannelPoolSize; x++) { - Channel trafficChannel = new Channel("T-" + mParentChannel.getName(), Channel.ChannelType.TRAFFIC); - trafficChannel.setAliasListName(mParentChannel.getAliasListName()); - trafficChannel.setSystem(mParentChannel.getSystem()); - trafficChannel.setSite(mParentChannel.getSite()); - trafficChannel.setDecodeConfiguration(decodeConfig); - trafficChannel.setEventLogConfiguration(mParentChannel.getEventLogConfiguration()); - trafficChannel.setRecordConfiguration(mParentChannel.getRecordConfiguration()); - trafficChannelList.add(trafficChannel); + trafficChannelList.add(createTrafficChannel(decodeConfig)); } } @@ -163,6 +157,23 @@ public class NXDNTrafficChannelManager extends TrafficChannelManager implements } } + /** + * Creates a child traffic channel that share's the parent decode configuration + * @param decodeConfig from the parent + * @return traffic channel. + */ + private @NonNull Channel createTrafficChannel(DecodeConfigNXDN decodeConfig) + { + Channel trafficChannel = new Channel("T-" + mParentChannel.getName(), Channel.ChannelType.TRAFFIC); + trafficChannel.setAliasListName(mParentChannel.getAliasListName()); + trafficChannel.setSystem(mParentChannel.getSystem()); + trafficChannel.setSite(mParentChannel.getSite()); + trafficChannel.setDecodeConfiguration(decodeConfig); + trafficChannel.setEventLogConfiguration(mParentChannel.getEventLogConfiguration()); + trafficChannel.setRecordConfiguration(mParentChannel.getRecordConfiguration()); + return trafficChannel; + } + /** * Retrieves the current event tracker for the specified channel and if the tracker is stale relative to the * timestamp, returns null, otherwise returns the current tracker. diff --git a/src/main/java/io/github/dsheirer/module/decode/p25/P25TrafficChannelManager.java b/src/main/java/io/github/dsheirer/module/decode/p25/P25TrafficChannelManager.java index 534bc768..857b70c8 100644 --- a/src/main/java/io/github/dsheirer/module/decode/p25/P25TrafficChannelManager.java +++ b/src/main/java/io/github/dsheirer/module/decode/p25/P25TrafficChannelManager.java @@ -38,6 +38,7 @@ import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier; import io.github.dsheirer.log.LoggingSuppressor; import io.github.dsheirer.message.IMessage; import io.github.dsheirer.message.IMessageListener; +import io.github.dsheirer.module.decode.DecoderFactory; import io.github.dsheirer.module.decode.config.DecodeConfiguration; import io.github.dsheirer.module.decode.event.DecodeEvent; import io.github.dsheirer.module.decode.event.DecodeEventDuplicateDetector; @@ -118,14 +119,14 @@ public class P25TrafficChannelManager extends TrafficChannelManager implements I private Map mFrequencyBandMap = new ConcurrentHashMap<>(); private Listener mChannelEventListener; private Listener mDecodeEventListener; - private TrafficChannelTeardownMonitor mTrafficChannelTeardownMonitor = new TrafficChannelTeardownMonitor(); - private Channel mParentChannel; + private final TrafficChannelTeardownMonitor mTrafficChannelTeardownMonitor = new TrafficChannelTeardownMonitor(); + private final Channel mParentChannel; private ScrambleParameters mPhase2ScrambleParameters; private Listener mMessageListener; private boolean mIgnoreDataCalls; //Used only for data calls - private DecodeEventDuplicateDetector mDuplicateDetector = new DecodeEventDuplicateDetector(); - private TalkerAliasManager mTalkerAliasManager = new TalkerAliasManager(); + private final DecodeEventDuplicateDetector mDuplicateDetector = new DecodeEventDuplicateDetector(); + private final TalkerAliasManager mTalkerAliasManager = new TalkerAliasManager(); /** * Constructs an instance. @@ -139,12 +140,16 @@ public class P25TrafficChannelManager extends TrafficChannelManager implements I { mIgnoreDataCalls = phase1.getIgnoreDataCalls(); createPhase1TrafficChannels(phase1.getTrafficChannelPoolSize(), phase1); - createPhase2TrafficChannels(phase1.getTrafficChannelPoolSize(), new DecodeConfigP25Phase2()); + DecodeConfigP25Phase2 phase2 = new DecodeConfigP25Phase2(); + DecoderFactory.transferJMBESettings(phase1, phase2); + createPhase2TrafficChannels(phase1.getTrafficChannelPoolSize(), phase2); } else if(parentChannel.getDecodeConfiguration() instanceof DecodeConfigP25Phase2 phase2) { mIgnoreDataCalls = phase2.getIgnoreDataCalls(); - createPhase1TrafficChannels(phase2.getTrafficChannelPoolSize(), new DecodeConfigP25Phase1()); + DecodeConfigP25Phase1 phase1 = new DecodeConfigP25Phase1(); + DecoderFactory.transferJMBESettings(phase2, phase1); + createPhase1TrafficChannels(phase2.getTrafficChannelPoolSize(), phase1); createPhase2TrafficChannels(phase2.getTrafficChannelPoolSize(), phase2); } }