#648 Resolves issue with audio panel sometimes displaying stale metadata that doesn't clear until the next audio segment is loaded. (#1545)

Co-authored-by: Dennis Sheirer <dsheirer@github.com>
This commit is contained in:
Denny Sheirer
2023-05-10 04:29:46 -04:00
committed by GitHub
parent 0af5963d08
commit b39dd1a19f
2 changed files with 50 additions and 36 deletions

View File

@@ -79,6 +79,7 @@ public abstract class AudioOutput implements LineListener, Listener<IdentifierUp
private boolean mRunning = false; private boolean mRunning = false;
private ScheduledExecutorService mScheduledExecutorService; private ScheduledExecutorService mScheduledExecutorService;
private ScheduledFuture<?> mProcessorFuture; private ScheduledFuture<?> mProcessorFuture;
private boolean mDropDuplicates;
private long mOutputLastTimestamp = 0; private long mOutputLastTimestamp = 0;
private static final long STALE_PLAYBACK_THRESHOLD_MS = 500; private static final long STALE_PLAYBACK_THRESHOLD_MS = 500;
@@ -104,6 +105,7 @@ public abstract class AudioOutput implements LineListener, Listener<IdentifierUp
mScheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new NamingThreadFactory( mScheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new NamingThreadFactory(
"sdrtrunk audio output " + mixerChannel.name())); "sdrtrunk audio output " + mixerChannel.name()));
mUserPreferences = userPreferences; mUserPreferences = userPreferences;
mDropDuplicates = mUserPreferences.getDuplicateCallDetectionPreference().isDuplicatePlaybackSuppressionEnabled();
try try
{ {
@@ -163,7 +165,7 @@ public abstract class AudioOutput implements LineListener, Listener<IdentifierUp
updateToneInsertionAudioClips(); updateToneInsertionAudioClips();
//Register to receive directory preference update notifications so we can update the preference items //Register to receive preference update notifications so we can update the preference items
MyEventBus.getGlobalEventBus().register(this); MyEventBus.getGlobalEventBus().register(this);
} }
@@ -226,6 +228,10 @@ public abstract class AudioOutput implements LineListener, Listener<IdentifierUp
{ {
updateToneInsertionAudioClips(); updateToneInsertionAudioClips();
} }
else if(preferenceType == PreferenceType.DUPLICATE_CALL_DETECTION)
{
mDropDuplicates = mUserPreferences.getDuplicateCallDetectionPreference().isDuplicatePlaybackSuppressionEnabled();
}
} }
/** /**
@@ -301,6 +307,7 @@ public abstract class AudioOutput implements LineListener, Listener<IdentifierUp
mCurrentAudioSegment.decrementConsumerCount(); mCurrentAudioSegment.decrementConsumerCount();
mCurrentAudioSegment.removeIdentifierUpdateNotificationListener(this); mCurrentAudioSegment.removeIdentifierUpdateNotificationListener(this);
mCurrentAudioSegment = null; mCurrentAudioSegment = null;
broadcast(null);
} }
} }
@@ -352,10 +359,7 @@ public abstract class AudioOutput implements LineListener, Listener<IdentifierUp
*/ */
private boolean isThrowaway(AudioSegment audioSegment) private boolean isThrowaway(AudioSegment audioSegment)
{ {
return audioSegment != null && return audioSegment != null && (audioSegment.isDoNotMonitor() || mDropDuplicates && (audioSegment.isDuplicate()));
(audioSegment.isDoNotMonitor() ||
(audioSegment.isDuplicate() && mUserPreferences.getDuplicateCallDetectionPreference()
.isDuplicatePlaybackSuppressionEnabled()));
} }
/** /**
@@ -371,8 +375,8 @@ public abstract class AudioOutput implements LineListener, Listener<IdentifierUp
loadNextAudioSegment(); loadNextAudioSegment();
} }
//Reevaluate current audio segment to see if the status has changed for duplicate or do-not-monitor. //Evaluate current audio segment to see if the status has changed for duplicate or do-not-monitor.
if(isThrowaway(mCurrentAudioSegment)) while(isThrowaway(mCurrentAudioSegment))
{ {
if(mCurrentBufferIndex > 0) if(mCurrentBufferIndex > 0)
{ {
@@ -385,29 +389,42 @@ public abstract class AudioOutput implements LineListener, Listener<IdentifierUp
while(mCurrentAudioSegment != null && mCurrentBufferIndex < mCurrentAudioSegment.getAudioBufferCount()) while(mCurrentAudioSegment != null && mCurrentBufferIndex < mCurrentAudioSegment.getAudioBufferCount())
{ {
if(mCurrentBufferIndex == 0) //Continuously evaluate current audio segment to see if the status has changed for duplicate or do-not-monitor.
if(isThrowaway(mCurrentAudioSegment))
{ {
playAudio(mAudioSegmentStartTone); if(mCurrentBufferIndex > 0)
}
try
{
float[] audioBuffer = mCurrentAudioSegment.getAudioBuffers().get(mCurrentBufferIndex++);
if(audioBuffer != null)
{ {
ByteBuffer audio = convert(audioBuffer); playAudio(mAudioSegmentDropTone);
//This call blocks until all audio bytes are dumped into the data line.
playAudio(audio);
} }
disposeCurrentAudioSegment();
} }
catch(Exception e) else
{ {
mLog.error("Error while processing audio for [" + mMixerChannel.name() + "]", e); if(mCurrentBufferIndex == 0)
{
playAudio(mAudioSegmentStartTone);
}
try
{
float[] audioBuffer = mCurrentAudioSegment.getAudioBuffers().get(mCurrentBufferIndex++);
if(audioBuffer != null)
{
ByteBuffer audio = convert(audioBuffer);
//This call blocks until all audio bytes are dumped into the data line.
playAudio(audio);
}
}
catch(Exception e)
{
mLog.error("Error while processing audio for [" + mMixerChannel.name() + "]", e);
}
} }
} }
//Check for completed and fully-played audio segment -- load next audio segment //Check for completed and fully-played audio segment to closeout
if(mCurrentAudioSegment != null && if(mCurrentAudioSegment != null &&
mCurrentAudioSegment.isComplete() && mCurrentAudioSegment.isComplete() &&
(mCurrentBufferIndex >= mCurrentAudioSegment.getAudioBufferCount())) (mCurrentBufferIndex >= mCurrentAudioSegment.getAudioBufferCount()))
@@ -649,16 +666,6 @@ public abstract class AudioOutput implements LineListener, Listener<IdentifierUp
{ {
try try
{ {
//TODO: Debug hooks - remove after testing
if(mMixerChannel.name().equals("LEFT"))
{
int a = 0;
}
else if(mMixerChannel.name().equals("RIGHT"))
{
int a = 0;
}
processAudio(); processAudio();
} }
catch(Throwable t) catch(Throwable t)

View File

@@ -1,6 +1,6 @@
/* /*
* ***************************************************************************** * *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer * Copyright (C) 2014-2023 Dennis Sheirer
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -27,6 +27,8 @@ import io.github.dsheirer.gui.control.PrefixIdentFormatter;
import io.github.dsheirer.preference.UserPreferences; import io.github.dsheirer.preference.UserPreferences;
import io.github.dsheirer.preference.identifier.IntegerFormat; import io.github.dsheirer.preference.identifier.IntegerFormat;
import io.github.dsheirer.protocol.Protocol; import io.github.dsheirer.protocol.Protocol;
import java.util.ArrayList;
import java.util.List;
import javafx.beans.value.ChangeListener; import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.geometry.HPos; import javafx.geometry.HPos;
@@ -38,9 +40,6 @@ import javafx.scene.layout.GridPane;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
/** /**
* Editor for talkgroup range alias identifiers * Editor for talkgroup range alias identifiers
*/ */
@@ -291,6 +290,10 @@ public class TalkgroupRangeEditor extends IdentifierEditor<TalkgroupRange>
private List<TalkgroupDetail> createTalkgroupDetails() private List<TalkgroupDetail> createTalkgroupDetails()
{ {
List<TalkgroupDetail> details = new ArrayList<>(); List<TalkgroupDetail> details = new ArrayList<>();
details.add(new TalkgroupDetail(Protocol.AM, IntegerFormat.DECIMAL, new IntegerFormatter(0,65535),
new IntegerFormatter(0,65535), "Format 0 - 65535"));
details.add(new TalkgroupDetail(Protocol.AM, IntegerFormat.HEXADECIMAL, new IntegerFormatter(0,65535),
new IntegerFormatter(0,65535), "Format 0 - FFFF"));
details.add(new TalkgroupDetail(Protocol.APCO25, IntegerFormat.DECIMAL, new IntegerFormatter(0,65535), details.add(new TalkgroupDetail(Protocol.APCO25, IntegerFormat.DECIMAL, new IntegerFormatter(0,65535),
new IntegerFormatter(0,65535), "Format: 0 - 65535")); new IntegerFormatter(0,65535), "Format: 0 - 65535"));
details.add(new TalkgroupDetail(Protocol.APCO25, IntegerFormat.HEXADECIMAL, new HexFormatter(0,65535), details.add(new TalkgroupDetail(Protocol.APCO25, IntegerFormat.HEXADECIMAL, new HexFormatter(0,65535),
@@ -307,6 +310,10 @@ public class TalkgroupRangeEditor extends IdentifierEditor<TalkgroupRange>
details.add(new TalkgroupDetail(Protocol.MPT1327, IntegerFormat.FORMATTED, details.add(new TalkgroupDetail(Protocol.MPT1327, IntegerFormat.FORMATTED,
new PrefixIdentFormatter(0,0xFFFFF), new PrefixIdentFormatter(0,0xFFFFF), new PrefixIdentFormatter(0,0xFFFFF), new PrefixIdentFormatter(0,0xFFFFF),
"Format: PPP-IIII = Prefix (0-127), Ident (1-8191)")); "Format: PPP-IIII = Prefix (0-127), Ident (1-8191)"));
details.add(new TalkgroupDetail(Protocol.NBFM, IntegerFormat.DECIMAL, new IntegerFormatter(0,65535),
new IntegerFormatter(0,65535), "Format 0 - 65535"));
details.add(new TalkgroupDetail(Protocol.NBFM, IntegerFormat.HEXADECIMAL, new IntegerFormatter(0,65535),
new IntegerFormatter(0,65535), "Format 0 - FFFF"));
details.add(new TalkgroupDetail(Protocol.PASSPORT, IntegerFormat.DECIMAL, new IntegerFormatter(0,0xFFFF), details.add(new TalkgroupDetail(Protocol.PASSPORT, IntegerFormat.DECIMAL, new IntegerFormatter(0,0xFFFF),
new IntegerFormatter(0,0xFFFF), "Format: 0 - 65535")); new IntegerFormatter(0,0xFFFF), "Format: 0 - 65535"));
details.add(new TalkgroupDetail(Protocol.PASSPORT, IntegerFormat.HEXADECIMAL, new HexFormatter(0,0xFFFF), details.add(new TalkgroupDetail(Protocol.PASSPORT, IntegerFormat.HEXADECIMAL, new HexFormatter(0,0xFFFF),