#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 <dennis.sheirer@gmail.com>
This commit is contained in:
Denny Sheirer
2026-10-18 04:52:14 -04:00
committed by GitHub
parent 0460f2b77b
commit dc550f3121
4 changed files with 76 additions and 32 deletions

View File

@@ -872,7 +872,10 @@ public class DecoderFactory
copyAM.setSquelchAutoTrack(origAM.isSquelchAutoTrack()); copyAM.setSquelchAutoTrack(origAM.isSquelchAutoTrack());
return copyAM; return copyAM;
case DMR: case DMR:
return new DecodeConfigDMR(); DecodeConfigDMR originalDMR = (DecodeConfigDMR)config;
DecodeConfigDMR copyDMR = new DecodeConfigDMR();
transferJMBESettings(originalDMR, copyDMR);
return copyDMR;
case LTR_NET: case LTR_NET:
DecodeConfigLTRNet originalLTRNet = (DecodeConfigLTRNet)config; DecodeConfigLTRNet originalLTRNet = (DecodeConfigLTRNet)config;
DecodeConfigLTRNet copyLTRNet = new DecodeConfigLTRNet(); DecodeConfigLTRNet copyLTRNet = new DecodeConfigLTRNet();
@@ -908,17 +911,20 @@ public class DecoderFactory
copyNXDN.setChannelMap(origNXDN.getChannelMap()); copyNXDN.setChannelMap(origNXDN.getChannelMap());
copyNXDN.setTransmissionMode(origNXDN.getTransmissionMode()); copyNXDN.setTransmissionMode(origNXDN.getTransmissionMode());
copyNXDN.setTrafficChannelPoolSize(origNXDN.getTrafficChannelPoolSize()); copyNXDN.setTrafficChannelPoolSize(origNXDN.getTrafficChannelPoolSize());
transferJMBESettings(origNXDN, copyNXDN);
return copyNXDN; return copyNXDN;
case P25_PHASE1: case P25_PHASE1:
DecodeConfigP25Phase1 originalP25 = (DecodeConfigP25Phase1)config; DecodeConfigP25Phase1 originalP25P1 = (DecodeConfigP25Phase1)config;
DecodeConfigP25Phase1 copyP25 = new DecodeConfigP25Phase1(); DecodeConfigP25Phase1 copyP25P1 = new DecodeConfigP25Phase1();
copyP25.setIgnoreDataCalls(originalP25.getIgnoreDataCalls()); copyP25P1.setIgnoreDataCalls(originalP25P1.getIgnoreDataCalls());
copyP25.setModulation(originalP25.getModulation()); copyP25P1.setModulation(originalP25P1.getModulation());
copyP25.setTrafficChannelPoolSize(originalP25.getTrafficChannelPoolSize()); copyP25P1.setTrafficChannelPoolSize(originalP25P1.getTrafficChannelPoolSize());
return copyP25; transferJMBESettings(originalP25P1, copyP25P1);
return copyP25P1;
case P25_PHASE2: case P25_PHASE2:
DecodeConfigP25Phase2 originalP25P2 = (DecodeConfigP25Phase2)config; DecodeConfigP25Phase2 originalP25P2 = (DecodeConfigP25Phase2)config;
DecodeConfigP25Phase2 copyP25P2 = new DecodeConfigP25Phase2(); DecodeConfigP25Phase2 copyP25P2 = new DecodeConfigP25Phase2();
transferJMBESettings(originalP25P2, copyP25P2);
if(originalP25P2.getScrambleParameters() != null) if(originalP25P2.getScrambleParameters() != null)
{ {
@@ -934,4 +940,17 @@ public class DecoderFactory
return null; 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());
}
} }

View File

@@ -65,6 +65,7 @@ import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import org.jspecify.annotations.NonNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -188,24 +189,15 @@ public class DMRTrafficChannelManager extends TrafficChannelManager implements I
DecodeConfiguration decodeConfiguration = mParentChannel.getDecodeConfiguration(); DecodeConfiguration decodeConfiguration = mParentChannel.getDecodeConfiguration();
List<Channel> trafficChannelList = new ArrayList<>(); List<Channel> trafficChannelList = new ArrayList<>();
if(decodeConfiguration instanceof DecodeConfigDMR) if(decodeConfiguration instanceof DecodeConfigDMR decodeConfig)
{ {
DecodeConfigDMR decodeConfig = (DecodeConfigDMR)decodeConfiguration;
int maxTrafficChannels = decodeConfig.getTrafficChannelPoolSize(); int maxTrafficChannels = decodeConfig.getTrafficChannelPoolSize();
if(maxTrafficChannels > 0) if(maxTrafficChannels > 0)
{ {
for(int x = 0; x < maxTrafficChannels; x++) for(int x = 0; x < maxTrafficChannels; x++)
{ {
Channel trafficChannel = new Channel("T-" + mParentChannel.getName(), ChannelType.TRAFFIC); trafficChannelList.add(createTrafficChannel(decodeConfig));
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);
} }
} }
} }
@@ -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 * 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. * the original standard channel with the frequency specified for the new rest channel.

View File

@@ -64,6 +64,7 @@ import java.util.Queue;
import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import org.jspecify.annotations.NonNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -147,14 +148,7 @@ public class NXDNTrafficChannelManager extends TrafficChannelManager implements
{ {
for(int x = 0; x < trafficChannelPoolSize; x++) for(int x = 0; x < trafficChannelPoolSize; x++)
{ {
Channel trafficChannel = new Channel("T-" + mParentChannel.getName(), Channel.ChannelType.TRAFFIC); trafficChannelList.add(createTrafficChannel(decodeConfig));
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);
} }
} }
@@ -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 * 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. * timestamp, returns null, otherwise returns the current tracker.

View File

@@ -38,6 +38,7 @@ import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
import io.github.dsheirer.log.LoggingSuppressor; import io.github.dsheirer.log.LoggingSuppressor;
import io.github.dsheirer.message.IMessage; import io.github.dsheirer.message.IMessage;
import io.github.dsheirer.message.IMessageListener; 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.config.DecodeConfiguration;
import io.github.dsheirer.module.decode.event.DecodeEvent; import io.github.dsheirer.module.decode.event.DecodeEvent;
import io.github.dsheirer.module.decode.event.DecodeEventDuplicateDetector; import io.github.dsheirer.module.decode.event.DecodeEventDuplicateDetector;
@@ -118,14 +119,14 @@ public class P25TrafficChannelManager extends TrafficChannelManager implements I
private Map<Integer, IFrequencyBand> mFrequencyBandMap = new ConcurrentHashMap<>(); private Map<Integer, IFrequencyBand> mFrequencyBandMap = new ConcurrentHashMap<>();
private Listener<ChannelEvent> mChannelEventListener; private Listener<ChannelEvent> mChannelEventListener;
private Listener<IDecodeEvent> mDecodeEventListener; private Listener<IDecodeEvent> mDecodeEventListener;
private TrafficChannelTeardownMonitor mTrafficChannelTeardownMonitor = new TrafficChannelTeardownMonitor(); private final TrafficChannelTeardownMonitor mTrafficChannelTeardownMonitor = new TrafficChannelTeardownMonitor();
private Channel mParentChannel; private final Channel mParentChannel;
private ScrambleParameters mPhase2ScrambleParameters; private ScrambleParameters mPhase2ScrambleParameters;
private Listener<IMessage> mMessageListener; private Listener<IMessage> mMessageListener;
private boolean mIgnoreDataCalls; private boolean mIgnoreDataCalls;
//Used only for data calls //Used only for data calls
private DecodeEventDuplicateDetector mDuplicateDetector = new DecodeEventDuplicateDetector(); private final DecodeEventDuplicateDetector mDuplicateDetector = new DecodeEventDuplicateDetector();
private TalkerAliasManager mTalkerAliasManager = new TalkerAliasManager(); private final TalkerAliasManager mTalkerAliasManager = new TalkerAliasManager();
/** /**
* Constructs an instance. * Constructs an instance.
@@ -139,12 +140,16 @@ public class P25TrafficChannelManager extends TrafficChannelManager implements I
{ {
mIgnoreDataCalls = phase1.getIgnoreDataCalls(); mIgnoreDataCalls = phase1.getIgnoreDataCalls();
createPhase1TrafficChannels(phase1.getTrafficChannelPoolSize(), phase1); 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) else if(parentChannel.getDecodeConfiguration() instanceof DecodeConfigP25Phase2 phase2)
{ {
mIgnoreDataCalls = phase2.getIgnoreDataCalls(); mIgnoreDataCalls = phase2.getIgnoreDataCalls();
createPhase1TrafficChannels(phase2.getTrafficChannelPoolSize(), new DecodeConfigP25Phase1()); DecodeConfigP25Phase1 phase1 = new DecodeConfigP25Phase1();
DecoderFactory.transferJMBESettings(phase2, phase1);
createPhase1TrafficChannels(phase2.getTrafficChannelPoolSize(), phase1);
createPhase2TrafficChannels(phase2.getTrafficChannelPoolSize(), phase2); createPhase2TrafficChannels(phase2.getTrafficChannelPoolSize(), phase2);
} }
} }