diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRDecoderState.java b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRDecoderState.java index f83f5960c..88e09f5eb 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRDecoderState.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRDecoderState.java @@ -1361,10 +1361,11 @@ public void receiveDecoderStateEvent(DecoderStateEvent event) } break; case NOTIFICATION_SOURCE_FREQUENCY: + long previous = mCurrentFrequency; mCurrentFrequency = event.getFrequency(); if(hasTrafficChannelManager()) { - mTrafficChannelManager.setCurrentControlFrequency(mCurrentFrequency, mChannel); + mTrafficChannelManager.setCurrentControlFrequency(previous, mCurrentFrequency, mChannel); } break; default: diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRMessageProcessor.java b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRMessageProcessor.java index ee19b0687..fb29ca5e7 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRMessageProcessor.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRMessageProcessor.java @@ -25,6 +25,7 @@ import io.github.dsheirer.module.decode.dmr.identifier.DMRTalkgroup; import io.github.dsheirer.module.decode.dmr.message.CACH; import io.github.dsheirer.module.decode.dmr.message.DMRBurst; +import io.github.dsheirer.module.decode.dmr.message.data.DataMessageWithLinkControl; import io.github.dsheirer.module.decode.dmr.message.data.IDLEMessage; import io.github.dsheirer.module.decode.dmr.message.data.block.DataBlock; import io.github.dsheirer.module.decode.dmr.message.data.csbk.CSBKMessage; @@ -48,12 +49,13 @@ import io.github.dsheirer.module.decode.dmr.message.voice.VoiceMessage; import io.github.dsheirer.module.decode.dmr.message.voice.VoiceSuperFrameProcessor; import io.github.dsheirer.sample.Listener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.TreeMap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Processes DMR messages and performs re-assembly of link control fragments @@ -154,6 +156,12 @@ else if(message instanceof DMRBurst dmrBurst && isValid(dmrBurst)) } } + //Process data messages carrying a link control payload so that the LC payload can be processed/enriched + if(message instanceof DataMessageWithLinkControl linkControlCarrier) + { + receive(linkControlCarrier.getLCMessage()); + } + //Enrich messages that carry DMR Logical Channel Numbers with LCN to frequency mappings if(message instanceof ITimeslotFrequencyReceiver) { 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 8467ab01a..35bd45eeb 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 @@ -134,12 +134,38 @@ public DMRTrafficChannelManager(Channel parentChannel) /** * Sets the current parent control channel frequency so that channel grants for the current frequency do not * produce an additional traffic channel allocation. - * @param currentControlFrequency for current control channel. + * @param previousControlFrequency for the current control channel (to remove from allocated channels) + * @param currentControlFrequency for current control channel (to add to allocated channels) * @param channel for the current control channel */ - public void setCurrentControlFrequency(long currentControlFrequency, Channel channel) + public void setCurrentControlFrequency(long previousControlFrequency, long currentControlFrequency, Channel channel) { - mAllocatedChannelFrequencyMap.put(currentControlFrequency, channel); + if(previousControlFrequency == currentControlFrequency) + { + return; + } + + mLock.lock(); + + try + { + Channel existing = mAllocatedChannelFrequencyMap.get(previousControlFrequency); + + //Only remove the channel if it is non-null and it matches the current control channel. + if(channel.equals(existing)) + { + //Unlock the frequency in the channel rotation monitor + getInterModuleEventBus().post(FrequencyLockChangeRequest.unlock(previousControlFrequency)); + mAllocatedChannelFrequencyMap.remove(previousControlFrequency); + } + + mAllocatedChannelFrequencyMap.put(currentControlFrequency, channel); + getInterModuleEventBus().post(FrequencyLockChangeRequest.lock(currentControlFrequency)); + } + finally + { + mLock.unlock(); + } } /**