Updates buffer overflow handling to occur coincident to other channel

states rather than being a channel state itself.  This was preventing
traffic channels that overflow from being torn down correctly.
This commit is contained in:
Denny
2018-09-16 05:21:46 -04:00
parent e94b6ae172
commit 335fb51456
9 changed files with 70 additions and 101 deletions

View File

@@ -20,6 +20,7 @@ package io.github.dsheirer.channel.metadata;
public enum Attribute public enum Attribute
{ {
BUFFER_OVERFLOW,
CHANNEL_CONFIGURATION_NAME, CHANNEL_CONFIGURATION_NAME,
CHANNEL_CONFIGURATION_SITE, CHANNEL_CONFIGURATION_SITE,
CHANNEL_CONFIGURATION_SYSTEM, CHANNEL_CONFIGURATION_SYSTEM,

View File

@@ -116,6 +116,16 @@ public class AttributeChangeRequest<T>
return null; return null;
} }
public Boolean getBooleanValue()
{
if(mValue instanceof Boolean)
{
return (Boolean)mValue;
}
return false;
}
/** /**
* Returns the value as a DecoderType or null if the value is not a DecoderType instance. * Returns the value as a DecoderType or null if the value is not a DecoderType instance.
*/ */

View File

@@ -1,19 +1,16 @@
/******************************************************************************* /*******************************************************************************
* sdrtrunk * sdr-trunk
* Copyright (C) 2014-2017 Dennis Sheirer * Copyright (C) 2014-2018 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
* it under the terms of the GNU General Public License as published by * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* the Free Software Foundation, either version 3 of the License, or * later version.
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* but WITHOUT ANY WARRANTY; without even the implied warranty of * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License along with this program.
* along with this program. If not, see <http://www.gnu.org/licenses/> * If not, see <http://www.gnu.org/licenses/>
* *
******************************************************************************/ ******************************************************************************/
package io.github.dsheirer.channel.metadata; package io.github.dsheirer.channel.metadata;
@@ -23,7 +20,7 @@ import io.github.dsheirer.controller.channel.Channel;
import io.github.dsheirer.sample.Listener; import io.github.dsheirer.sample.Listener;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import java.awt.*; import java.awt.EventQueue;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@@ -45,7 +42,7 @@ public class ChannelMetadataModel extends AbstractTableModel implements Listener
public static final int COLUMN_CONFIGURATION_NAME = 8; public static final int COLUMN_CONFIGURATION_NAME = 8;
public static final int COLUMN_MESSAGE = 9; public static final int COLUMN_MESSAGE = 9;
private static final String[] COLUMNS = {"State", "Decoder", "Channel", "Frequency", "Primary From", "Primary To", private static final String[] COLUMNS = {"Status", "Decoder", "Channel", "Frequency", "Primary From", "Primary To",
"Secondary From", "Secondary To", "Channel Name", "Message"}; "Secondary From", "Secondary To", "Channel Name", "Message"};
private List<MutableMetadata> mChannelMetadata = new ArrayList(); private List<MutableMetadata> mChannelMetadata = new ArrayList();
@@ -166,7 +163,14 @@ public class ChannelMetadataModel extends AbstractTableModel implements Listener
switch(columnIndex) switch(columnIndex)
{ {
case COLUMN_STATE: case COLUMN_STATE:
return metadata.getState(); if(metadata.isBufferOverflow())
{
return metadata.getState() + " *OVERFLOW*";
}
else
{
return metadata.getState();
}
case COLUMN_DECODER: case COLUMN_DECODER:
if(metadata.hasPrimaryDecoderType()) if(metadata.hasPrimaryDecoderType())
{ {

View File

@@ -120,8 +120,6 @@ public class ChannelMetadataPanel extends JPanel implements ListSelectionListene
mForegroundColors.put(State.FADE, Color.DARK_GRAY); mForegroundColors.put(State.FADE, Color.DARK_GRAY);
mBackgroundColors.put(State.IDLE, Color.WHITE); mBackgroundColors.put(State.IDLE, Color.WHITE);
mForegroundColors.put(State.IDLE, Color.DARK_GRAY); mForegroundColors.put(State.IDLE, Color.DARK_GRAY);
mBackgroundColors.put(State.OVERFLOW, Color.RED);
mForegroundColors.put(State.OVERFLOW, Color.YELLOW);
mBackgroundColors.put(State.RESET, Color.PINK); mBackgroundColors.put(State.RESET, Color.PINK);
mForegroundColors.put(State.RESET, Color.YELLOW); mForegroundColors.put(State.RESET, Color.YELLOW);
mBackgroundColors.put(State.TEARDOWN, Color.DARK_GRAY); mBackgroundColors.put(State.TEARDOWN, Color.DARK_GRAY);

View File

@@ -41,6 +41,7 @@ public class Metadata
protected boolean mUpdated; protected boolean mUpdated;
protected DecoderType mPrimaryDecoderType; protected DecoderType mPrimaryDecoderType;
protected boolean mSelected; protected boolean mSelected;
protected boolean mBufferOverflow;
protected State mState = State.IDLE; protected State mState = State.IDLE;
protected String mChannelConfigurationSystem; protected String mChannelConfigurationSystem;
protected String mChannelConfigurationSite; protected String mChannelConfigurationSite;
@@ -173,6 +174,14 @@ public class Metadata
return mSelected; return mSelected;
} }
/**
* Indicates if the channel for this metadata is in a buffer overflow state.
*/
public boolean isBufferOverflow()
{
return mBufferOverflow;
}
/** /**
* List of de-duplicated broadcast channels aggregated from the primary and secondary TO/FROM aliases. * List of de-duplicated broadcast channels aggregated from the primary and secondary TO/FROM aliases.
*/ */

View File

@@ -80,6 +80,10 @@ public class MutableMetadata extends Metadata implements Listener<AttributeChang
{ {
switch(request.getAttribute()) switch(request.getAttribute())
{ {
case BUFFER_OVERFLOW:
mBufferOverflow = request.getBooleanValue();
broadcast(Attribute.BUFFER_OVERFLOW);
break;
case CHANNEL_CONFIGURATION_SYSTEM: case CHANNEL_CONFIGURATION_SYSTEM:
mChannelConfigurationSystem = request.getStringValue(); mChannelConfigurationSystem = request.getStringValue();
broadcast(Attribute.CHANNEL_CONFIGURATION_SYSTEM); broadcast(Attribute.CHANNEL_CONFIGURATION_SYSTEM);

View File

@@ -346,8 +346,7 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
break; break;
} }
mMutableMetadata.receive(new AttributeChangeRequest<State>(Attribute.CHANNEL_STATE, mMutableMetadata.receive(new AttributeChangeRequest<State>(Attribute.CHANNEL_STATE, mState));
mSourceOverflow ? State.OVERFLOW : mState));
} }
} }
@@ -370,8 +369,19 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
{ {
mSourceOverflow = overflow; mSourceOverflow = overflow;
mMutableMetadata.receive(new AttributeChangeRequest<State>(Attribute.CHANNEL_STATE, mMutableMetadata.receive(new AttributeChangeRequest<Boolean>(Attribute.BUFFER_OVERFLOW, mSourceOverflow));
mSourceOverflow ? State.OVERFLOW : mState)); }
/**
* Indicates if this channel's sample buffer is in overflow state, meaning that the inbound sample
* stream is not being processed fast enough and samples are being thrown away until the processing can
* catch up.
*
* @return true if the channel is in overflow state.
*/
public boolean isOverflow()
{
return mSourceOverflow;
} }
/** /**

View File

@@ -34,7 +34,7 @@ public enum State
@Override @Override
public boolean canChangeTo(State state) public boolean canChangeTo(State state)
{ {
return state == CALL | return state == CALL ||
state == CONTROL || state == CONTROL ||
state == DATA || state == DATA ||
state == ENCRYPTED || state == ENCRYPTED ||
@@ -108,8 +108,7 @@ public enum State
public boolean canChangeTo(State state) public boolean canChangeTo(State state)
{ {
return state != FADE && return state != FADE &&
state != RESET && state != RESET;
state != OVERFLOW;
} }
}, },
/** /**
@@ -121,25 +120,10 @@ public enum State
public boolean canChangeTo(State state) public boolean canChangeTo(State state)
{ {
return state != TEARDOWN && return state != TEARDOWN &&
state != RESET && state != RESET;
state != OVERFLOW;
}
},
/**
* Indicates that the channel's sample buffer has overflowed and new buffer samples are no longer being
* delivered to the channel. This state persists until the processing catches up and reduces the number
* of samples in the input buffer below a threshold value. Transition to and from this state is exclusively
* managed by the Channel State and no other channel states can be processed from the channel decoders
* until the channel state is taken out of overflow.
*/
OVERFLOW("OVERFLOW")
{
@Override
public boolean canChangeTo(State state)
{
return false;
} }
}, },
/** /**
* Indicates that the channel has been reset and is ready to use for a new decoding session. * Indicates that the channel has been reset and is ready to use for a new decoding session.
*/ */

View File

@@ -30,10 +30,17 @@ import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.swing.*; import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
import java.awt.*; import java.awt.EventQueue;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
@@ -86,64 +93,6 @@ public class MessageActivityPanel extends JPanel implements Listener<ProcessingC
}); });
} }
// @Override
// public void channelChanged(ChannelEvent event)
// {
// boolean changed = false;
//
// if(event.getEvent() == Event.NOTIFICATION_SELECTION_CHANGE &&
// event.getChannel().isSelected())
// {
// if(mDisplayedChannel == null || (mDisplayedChannel != null && mDisplayedChannel != event.getChannel()))
// {
// mDisplayedChannel = event.getChannel();
//
// ProcessingChain chain = mChannelProcessingManager.getProcessingChain(mDisplayedChannel);
//
// if(chain != null)
// {
// mDisplayedModel = chain.getMessageActivityModel();
// }
// else
// {
// mDisplayedModel = EMPTY_MODEL;
// }
//
// mMessageTable.setModel(mDisplayedModel);
//
// if(mDisplayedChannel != null)
// {
// mManagementPanel.enableButtons();
// }
// else
// {
// mManagementPanel.disableButtons();
// }
//
// changed = true;
// }
// }
// else if(event.getEvent() == Event.NOTIFICATION_PROCESSING_STOP || event.getEvent() == Event.REQUEST_DISABLE)
// {
// if(mDisplayedChannel != null && mDisplayedChannel == event.getChannel())
// {
// mDisplayedChannel = null;
//
// mMessageTable.setModel(EMPTY_MODEL);
//
// mManagementPanel.disableButtons();
//
// changed = true;
// }
// }
//
// if(changed)
// {
// revalidate();
// repaint();
// }
// }
public class MessageManagementPanel extends JPanel public class MessageManagementPanel extends JPanel
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;