diff --git a/src/audio/AudioChannelPanel.java b/src/audio/AudioChannelPanel.java index af0cc602..2181d093 100644 --- a/src/audio/AudioChannelPanel.java +++ b/src/audio/AudioChannelPanel.java @@ -25,6 +25,7 @@ import icon.IconManager; import net.miginfocom.swing.MigLayout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import properties.SystemProperties; import sample.Listener; import settings.ColorSetting; import settings.ColorSetting.ColorSettingName; @@ -41,23 +42,27 @@ public class AudioChannelPanel extends JPanel private static final long serialVersionUID = 1L; private static final Logger mLog = LoggerFactory.getLogger(AudioChannelPanel.class); + public static final String PROPERTY_PREFIX = "audio.channel.panel.color."; + public static final String PROPERTY_COLOR_BACKGROUND = PROPERTY_PREFIX + "background"; + public static final String PROPERTY_COLOR_LABEL = PROPERTY_PREFIX + "label"; + public static final String PROPERTY_COLOR_MUTED = PROPERTY_PREFIX + "muted"; + public static final String PROPERTY_COLOR_VALUE = PROPERTY_PREFIX + "value"; + private Font mFont = new Font(Font.MONOSPACED, Font.PLAIN, 16); + + private Color mBackgroundColor; private Color mLabelColor; - private Color mDetailsColor; + private Color mMutedColor; + private Color mValueColor; private IconManager mIconManager; private SettingsManager mSettingsManager; private AudioOutput mAudioOutput; + private JLabel mMutedLabel = new JLabel("M"); private JLabel mChannelName = new JLabel(" "); - private JLabel mToLabel = new JLabel("TO:"); - private JLabel mTo = new JLabel("-----"); private JLabel mToAlias = new JLabel(" "); - - private JLabel mMutedLabel = new JLabel("MUTED"); - private JLabel mFromLabel = new JLabel("FROM:"); - private JLabel mFrom = new JLabel("-----"); - private JLabel mFromAlias = new JLabel(" "); + private JLabel mTo = new JLabel("-----"); private boolean mConfigured = false; @@ -75,67 +80,36 @@ public class AudioChannelPanel extends JPanel mAudioOutput.setMetadataListener(new AudioMetadataProcessor()); } - mLabelColor = mSettingsManager.getColorSetting( - ColorSettingName.CHANNEL_STATE_LABEL_DECODER).getColor(); - mDetailsColor = mSettingsManager.getColorSetting( - ColorSettingName.CHANNEL_STATE_LABEL_DETAILS).getColor(); + mBackgroundColor = SystemProperties.getInstance().get(PROPERTY_COLOR_BACKGROUND, Color.BLACK); + mLabelColor = SystemProperties.getInstance().get(PROPERTY_COLOR_LABEL, Color.LIGHT_GRAY); + mMutedColor = SystemProperties.getInstance().get(PROPERTY_COLOR_MUTED, Color.RED); + mValueColor = SystemProperties.getInstance().get(PROPERTY_COLOR_VALUE, Color.GREEN); init(); } private void init() { - setLayout(new MigLayout("align center center, insets 0 0 0 0", - "[][][right][grow,fill][grow,fill][right][grow,fill][grow,fill]", "")); - setBackground(Color.BLACK); + setLayout(new MigLayout("align center center, insets 0 0 0 0", "[][][align right]0[grow,fill]", "")); + setBackground(mBackgroundColor); mMutedLabel.setFont(mFont); - mMutedLabel.setForeground(Color.RED); + mMutedLabel.setForeground(mMutedColor); mMutedLabel.setVisible(false); add(mMutedLabel); mChannelName = new JLabel(mAudioOutput != null ? mAudioOutput.getChannelName() : " "); mChannelName.setFont(mFont); - mChannelName.setForeground(mDetailsColor); + mChannelName.setForeground(mLabelColor); add(mChannelName); - mToLabel.setFont(mFont); - if(mAudioOutput != null) - { - mToLabel.setForeground(mLabelColor); - } - else - { - mToLabel.setForeground(getBackground()); - } - add(mToLabel); - - mTo.setFont(mFont); - mTo.setForeground(mLabelColor); - add(mTo); - mToAlias.setFont(mFont); - mToAlias.setForeground(mLabelColor); + mToAlias.setForeground(mValueColor); add(mToAlias); - mFromLabel.setFont(mFont); - if(mAudioOutput != null) - { - mFromLabel.setForeground(mLabelColor); - } - else - { - mFromLabel.setForeground(getBackground()); - } - add(mFromLabel); - - mFrom.setFont(mFont); - mFrom.setForeground(mLabelColor); - add(mFrom); - - mFromAlias.setFont(mFont); - mFromAlias.setForeground(mLabelColor); - add(mFromAlias); + mTo.setFont(mFont); + mTo.setForeground(mValueColor); + add(mTo); } @Override @@ -175,7 +149,6 @@ public class AudioChannelPanel extends JPanel */ private void resetLabels() { - updateLabel(mFrom, null, mFromAlias, null); updateLabel(mTo, null, mToAlias, null); mConfigured = false; @@ -190,14 +163,15 @@ public class AudioChannelPanel extends JPanel { if(value != null) { - valueLabel.setText(value); if(alias != null) { - aliasLabel.setIcon(mIconManager.getIcon(alias.getIconName(), 16)); + valueLabel.setText(alias.getName()); + aliasLabel.setIcon(mIconManager.getIcon(alias.getIconName(), 18)); } else { + valueLabel.setText(value); aliasLabel.setIcon(null); } } @@ -224,9 +198,6 @@ public class AudioChannelPanel extends JPanel @Override public void run() { - updateLabel(mFrom, metadata.getPrimaryAddressFrom().getIdentifier(), - mFromAlias, metadata.getPrimaryAddressFrom().getAlias()); - updateLabel(mTo, metadata.getPrimaryAddressTo().getIdentifier(), mToAlias, metadata.getPrimaryAddressTo().getAlias()); @@ -249,14 +220,6 @@ public class AudioChannelPanel extends JPanel switch(colorSetting.getColorSettingName()) { case CHANNEL_STATE_LABEL_DECODER: - if(mFrom != null) - { - mFrom.setForeground(mLabelColor); - } - if(mFromAlias != null) - { - mFromAlias.setForeground(mLabelColor); - } if(mTo != null) { mTo.setForeground(mLabelColor); @@ -266,16 +229,6 @@ public class AudioChannelPanel extends JPanel mToAlias.setForeground(mLabelColor); } break; - case CHANNEL_STATE_LABEL_DETAILS: - if(mFromLabel != null) - { - mFromLabel.setForeground(mDetailsColor); - } - if(mToLabel != null) - { - mToLabel.setForeground(mDetailsColor); - } - break; default: break; } diff --git a/src/audio/AudioChannelsPanel.java b/src/audio/AudioChannelsPanel.java index 63a31e44..b2d94fb6 100644 --- a/src/audio/AudioChannelsPanel.java +++ b/src/audio/AudioChannelsPanel.java @@ -33,7 +33,8 @@ public class AudioChannelsPanel extends JPanel public AudioChannelsPanel(IconManager iconManager, SettingsManager settingsManager, IAudioController controller) { - setLayout(new MigLayout("insets 0 0 0 0", "[][grow,fill][][grow,fill]", "[grow,fill]")); +// setLayout(new MigLayout("insets 0 0 0 0", "[][grow,fill][][grow,fill]", "[grow,fill]")); + setLayout(new MigLayout("insets 0 0 0 0", "[][sg,grow,fill][][sg,grow,fill]", "[grow,fill]")); setBackground(Color.BLACK); diff --git a/src/audio/broadcast/AudioBroadcaster.java b/src/audio/broadcast/AudioBroadcaster.java index 2115480b..877543fc 100644 --- a/src/audio/broadcast/AudioBroadcaster.java +++ b/src/audio/broadcast/AudioBroadcaster.java @@ -259,8 +259,15 @@ public abstract class AudioBroadcaster implements Listener //Remove all pending audio recordings while(!mAudioRecordingQueue.isEmpty()) { - AudioRecording recording = mAudioRecordingQueue.get(0); - recording.removePendingReplay(); + try + { + AudioRecording recording = mAudioRecordingQueue.get(0); + recording.removePendingReplay(); + } + catch(Exception e) + { + //Ignore + } } } } diff --git a/src/channel/metadata/AliasedIntegerAttributeMonitor.java b/src/channel/metadata/AliasedIntegerAttributeMonitor.java new file mode 100644 index 00000000..dbc0b6ae --- /dev/null +++ b/src/channel/metadata/AliasedIntegerAttributeMonitor.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * sdrtrunk + * Copyright (C) 2014-2017 Dennis Sheirer + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * 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 + * along with this program. If not, see + * + ******************************************************************************/ +package channel.metadata; + +import alias.Alias; +import alias.AliasList; +import alias.id.AliasIDType; +import sample.Listener; + +import static alias.id.AliasIDType.*; + +public class AliasedIntegerAttributeMonitor extends AttributeMonitor +{ + private static final AliasIDType[] VALID_ID_TYPES = {STATUS, LTR_NET_UID}; + + private AliasList mAliasList; + private AliasIDType mAliasIDType; + + /** + * Provides monitoring of a String attribute's values with occurrence heuristics enabled and alias lookup with each + * change in the attribute's value. + * + * @param attribute to monitor + * @param listener to receive change requests + * @param aliasList to lookup alias from + * @param aliasIDType to determine correct alias lookup method in alias list + */ + public AliasedIntegerAttributeMonitor(Attribute attribute, Listener listener, AliasList aliasList, + AliasIDType aliasIDType) + { + super(attribute, listener); + + if(!isValidIDType(aliasIDType)) + { + throw new IllegalArgumentException("Alias ID Type [" + aliasIDType.name() + "] is not supported"); + } + mAliasList = aliasList; + mAliasIDType = aliasIDType; + } + + /** + * Indicates if the alias ID type is a supported/valid type for this monitor. + */ + public static boolean isValidIDType(AliasIDType type) + { + for(AliasIDType validType: VALID_ID_TYPES) + { + if(type == validType) + { + return true; + } + } + + return false; + } + + /** + * Lookup of the alias that corresponds to the value's alias ID type + */ + @Override + protected Alias getAlias() + { + Alias alias = null; + + if(mAliasList != null) + { + if(hasValue()) + { + switch(mAliasIDType) + { + case STATUS: + alias = mAliasList.getStatus(getValue()); + break; + case LTR_NET_UID: + alias = mAliasList.getUniqueID(getValue()); + break; + } + } + } + + return alias; + } +} diff --git a/src/channel/metadata/AttributeMonitor.java b/src/channel/metadata/AttributeMonitor.java index 74bfd281..81bb477e 100644 --- a/src/channel/metadata/AttributeMonitor.java +++ b/src/channel/metadata/AttributeMonitor.java @@ -51,13 +51,15 @@ public class AttributeMonitor * different from the current value, has a higher occurrence count than the current value. If heuristics are * disabled, then a change is emitted at each change in the value. * @param t + * + * @return true if the value was changed after processing */ - public void process(T t) + public boolean process(T t) { + boolean changed = false; + if(t != null && !mIllegalValues.contains(t)) { - boolean changed = false; - if(mHeuristicsEnabled) { if(mOccurrenceCounts.containsKey(t)) @@ -103,6 +105,8 @@ public class AttributeMonitor mListener.receive(new AttributeChangeRequest(mAttribute, getValue(), getAlias())); } } + + return changed; } /** diff --git a/src/channel/metadata/ChannelMetadataModel.java b/src/channel/metadata/ChannelMetadataModel.java index 1d0eae08..6829b06e 100644 --- a/src/channel/metadata/ChannelMetadataModel.java +++ b/src/channel/metadata/ChannelMetadataModel.java @@ -18,11 +18,13 @@ ******************************************************************************/ package channel.metadata; +import channel.state.State; import controller.channel.Channel; import sample.Listener; import javax.swing.table.AbstractTableModel; import java.awt.*; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -30,22 +32,28 @@ import java.util.Map; public class ChannelMetadataModel extends AbstractTableModel implements Listener { - public static final int COLUMN_STATE = 0; - public static final int COLUMN_FREQUENCY = 1; - public static final int COLUMN_PRIMARY = 2; - public static final int COLUMN_SECONDARY = 3; - public static final int COLUMN_MESSAGE = 4; - public static final int COLUMN_NETWORK = 5; - public static final int COLUMN_CONFIGURATION = 6; + private final DecimalFormat FREQUENCY_FORMATTER = new DecimalFormat( "#.0000" ); - private static final String[] COLUMNS = - {"State", "Frequency", "Primary", "Secondary", "Message", "Network", "Configuration"}; + public static final int COLUMN_STATE = 0; + public static final int COLUMN_DECODER = 1; + public static final int COLUMN_CHANNEL = 2; + public static final int COLUMN_FREQUENCY = 3; + public static final int COLUMN_PRIMARY_FROM = 4; + public static final int COLUMN_PRIMARY_TO = 5; + public static final int COLUMN_SECONDARY_FROM = 6; + public static final int COLUMN_SECONDARY_TO = 7; + public static final int COLUMN_CONFIGURATION_NAME = 8; + public static final int COLUMN_MESSAGE = 9; + + private static final String[] COLUMNS = {"State", "Decoder", "Channel", "Frequency", "Primary From", "Primary To", + "Secondary From", "Secondary To", "Channel Name", "Message"}; private List mChannelMetadata = new ArrayList(); private Map mMetadataChannelMap = new HashMap(); public void add(MutableMetadata metadata, Channel channel) { + //Execute on the swing thread to avoid threading issues EventQueue.invokeLater(new Runnable() { @Override @@ -65,6 +73,7 @@ public class ChannelMetadataModel extends AbstractTableModel implements Listener public void remove(MutableMetadata metadata) { + //Execute on the swing thread to avoid threading issues EventQueue.invokeLater(new Runnable() { @Override @@ -82,6 +91,27 @@ public class ChannelMetadataModel extends AbstractTableModel implements Listener }); } + /** + * Get the channel metadata at the specified model row index + */ + public Metadata getMetadata(int row) + { + if(row < mChannelMetadata.size()) + { + return mChannelMetadata.get(row); + } + + return null; + } + + /** + * Returns the channel that matches the metadata or null + */ + public Channel getChannelFromMetadata(Metadata metadata) + { + return mMetadataChannelMap.get(metadata); + } + @Override public int getRowCount() { @@ -103,7 +133,27 @@ public class ChannelMetadataModel extends AbstractTableModel implements Listener @Override public Class getColumnClass(int columnIndex) { - return MutableMetadata.class; + switch(columnIndex) + { + case COLUMN_STATE: + return State.class; + + case COLUMN_DECODER: + case COLUMN_CHANNEL: + case COLUMN_FREQUENCY: + case COLUMN_MESSAGE: + case COLUMN_CONFIGURATION_NAME: + return String.class; + + case COLUMN_PRIMARY_TO: + case COLUMN_PRIMARY_FROM: + case COLUMN_SECONDARY_TO: + case COLUMN_SECONDARY_FROM: + return MutableMetadata.class; + + default: + return String.class; + } } @Override @@ -111,7 +161,57 @@ public class ChannelMetadataModel extends AbstractTableModel implements Listener { if(rowIndex <= mChannelMetadata.size()) { - return mChannelMetadata.get(rowIndex); + Metadata metadata = mChannelMetadata.get(rowIndex); + + switch(columnIndex) + { + case COLUMN_STATE: + return metadata.getState(); + case COLUMN_DECODER: + if(metadata.hasPrimaryDecoderType()) + { + return metadata.getPrimaryDecoderType().getShortDisplayString(); + } + + return null; + case COLUMN_CHANNEL: + return metadata.getChannelFrequencyLabel(); + case COLUMN_FREQUENCY: + if(metadata.hasChannelFrequency()) + { + return FREQUENCY_FORMATTER.format((double)metadata.getChannelFrequency() / 1E6d); + } + + return null; + case COLUMN_MESSAGE: + if(metadata.hasMessageType() | metadata.hasMessage()) + { + StringBuilder sb = new StringBuilder(); + if(metadata.hasMessageType()) + { + sb.append(metadata.getMessageType()).append(" "); + } + + if(metadata.hasMessage()) + { + sb.append(metadata.getMessage()); + } + + return sb.toString(); + } + + return null; + case COLUMN_CONFIGURATION_NAME: + return metadata.getChannelConfigurationLabel1(); + case COLUMN_PRIMARY_TO: + case COLUMN_PRIMARY_FROM: + case COLUMN_SECONDARY_TO: + case COLUMN_SECONDARY_FROM: + return metadata; + + default: + return String.class; + } } return null; @@ -120,6 +220,7 @@ public class ChannelMetadataModel extends AbstractTableModel implements Listener @Override public void receive(MutableMetadataChangeEvent mutableMetadataChangeEvent) { + //Execute on the swing thread to avoid threading issues EventQueue.invokeLater(new Runnable() { @Override @@ -132,13 +233,16 @@ public class ChannelMetadataModel extends AbstractTableModel implements Listener switch(mutableMetadataChangeEvent.getAttribute()) { case CHANNEL_CONFIGURATION_LABEL_1: + break; case CHANNEL_CONFIGURATION_LABEL_2: - fireTableCellUpdated(rowIndex, COLUMN_CONFIGURATION); + fireTableCellUpdated(rowIndex, COLUMN_CONFIGURATION_NAME); break; case CHANNEL_FREQUENCY: - case CHANNEL_FREQUENCY_LABEL: fireTableCellUpdated(rowIndex, COLUMN_FREQUENCY); break; + case CHANNEL_FREQUENCY_LABEL: + fireTableCellUpdated(rowIndex, COLUMN_CHANNEL); + break; case CHANNEL_STATE: fireTableCellUpdated(rowIndex, COLUMN_STATE); break; @@ -146,17 +250,20 @@ public class ChannelMetadataModel extends AbstractTableModel implements Listener case MESSAGE_TYPE: fireTableCellUpdated(rowIndex, COLUMN_MESSAGE); break; - case NETWORK_ID_1: - case NETWORK_ID_2: - fireTableCellUpdated(rowIndex, COLUMN_NETWORK); - break; case PRIMARY_ADDRESS_FROM: + fireTableCellUpdated(rowIndex, COLUMN_PRIMARY_FROM); + break; case PRIMARY_ADDRESS_TO: - fireTableCellUpdated(rowIndex, COLUMN_PRIMARY); + fireTableCellUpdated(rowIndex, COLUMN_PRIMARY_TO); + break; + case PRIMARY_DECODER_TYPE: + fireTableCellUpdated(rowIndex, COLUMN_DECODER); break; case SECONDARY_ADDRESS_FROM: + fireTableCellUpdated(rowIndex, COLUMN_SECONDARY_FROM); + break; case SECONDARY_ADDRESS_TO: - fireTableCellUpdated(rowIndex, COLUMN_SECONDARY); + fireTableCellUpdated(rowIndex, COLUMN_SECONDARY_TO); break; } } diff --git a/src/channel/metadata/ChannelMetadataPanel.java b/src/channel/metadata/ChannelMetadataPanel.java index 6742ac09..c3a07090 100644 --- a/src/channel/metadata/ChannelMetadataPanel.java +++ b/src/channel/metadata/ChannelMetadataPanel.java @@ -19,26 +19,39 @@ package channel.metadata; import alias.Alias; +import channel.state.State; +import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory; +import controller.channel.Channel; +import controller.channel.ChannelProcessingManager; import icon.IconManager; -import icon.IconTableModel; +import module.ProcessingChain; import net.miginfocom.swing.MigLayout; +import properties.SystemProperties; +import sample.Broadcaster; +import sample.Listener; import javax.swing.*; +import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; -import javax.swing.table.TableCellRenderer; +import javax.swing.table.DefaultTableCellRenderer; import java.awt.*; -import java.text.DecimalFormat; -public class ChannelMetadataPanel extends JPanel +public class ChannelMetadataPanel extends JPanel implements ListSelectionListener { - private ChannelMetadataModel mChannelMetadataModel; + private static final String PROPERTY_PREFIX_BACKGROUND = "channel.metadata.panel.state.color."; + private static final String PROPERTY_PREFIX_FOREGROUND = "channel.metadata.panel.text.color."; + private ChannelProcessingManager mChannelProcessingManager; private IconManager mIconManager; private JTable mTable; + private Broadcaster mSelectedProcessingChainBroadcaster = new Broadcaster<>(); - public ChannelMetadataPanel(ChannelMetadataModel channelMetadataModel, IconManager iconManager) + /** + * Table view for currently decoding channel metadata + */ + public ChannelMetadataPanel(ChannelProcessingManager channelProcessingManager, IconManager iconManager) { - mChannelMetadataModel = channelMetadataModel; mIconManager = iconManager; + mChannelProcessingManager = channelProcessingManager; init(); } @@ -50,199 +63,165 @@ public class ChannelMetadataPanel extends JPanel { setLayout( new MigLayout( "insets 0 0 0 0", "[grow,fill]", "[grow,fill]") ); - mTable = new JTable(mChannelMetadataModel); - mTable.setRowHeight(35); + mTable = new JTable(mChannelProcessingManager.getChannelMetadataModel()); - mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_STATE).setCellRenderer(new StateCellRenderer()); + DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)mTable.getDefaultRenderer(String.class); + renderer.setHorizontalAlignment(SwingConstants.CENTER); - mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_FREQUENCY) - .setCellRenderer(new FrequencyCellRenderer()); + mTable.getSelectionModel().addListSelectionListener(this); - mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_PRIMARY) - .setCellRenderer(new AliasedValueCellRenderer(Attribute.PRIMARY_ADDRESS_TO, Attribute.PRIMARY_ADDRESS_FROM)); - - mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_SECONDARY) - .setCellRenderer(new AliasedValueCellRenderer(Attribute.SECONDARY_ADDRESS_TO, Attribute.SECONDARY_ADDRESS_FROM)); - - mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_MESSAGE) - .setCellRenderer(new AliasedValueCellRenderer(Attribute.MESSAGE, Attribute.MESSAGE_TYPE)); - - mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_NETWORK) - .setCellRenderer(new AliasedValueCellRenderer(Attribute.NETWORK_ID_1, Attribute.NETWORK_ID_2)); - - mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_CONFIGURATION) - .setCellRenderer(new AliasedValueCellRenderer(Attribute.CHANNEL_CONFIGURATION_LABEL_1, - Attribute.CHANNEL_CONFIGURATION_LABEL_2)); + mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_STATE) + .setCellRenderer(new ColoredStateCellRenderer()); + mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_PRIMARY_TO) + .setCellRenderer(new AliasedValueCellRenderer(Attribute.PRIMARY_ADDRESS_TO)); + mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_PRIMARY_FROM) + .setCellRenderer(new AliasedValueCellRenderer(Attribute.PRIMARY_ADDRESS_FROM)); + mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_SECONDARY_TO) + .setCellRenderer(new AliasedValueCellRenderer(Attribute.SECONDARY_ADDRESS_TO)); + mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_SECONDARY_FROM) + .setCellRenderer(new AliasedValueCellRenderer(Attribute.SECONDARY_ADDRESS_FROM)); JScrollPane scrollPane = new JScrollPane(mTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); add(scrollPane); +// new TableColumnWidthMonitor(mTable, PROPERTY_PREFIX, new int[] {15,15,15,15,25,25,25,25,15,40}); } - /** - * Adds a selection listener to the contained metadata JTable - */ - public void addListSelectionListener(ListSelectionListener listener) + @Override + public void valueChanged(ListSelectionEvent e) { - mTable.getSelectionModel().addListSelectionListener(listener); - } - - /** - * Removes the selection listener from the contained metadata JTable - */ - public void removeListSelectionListener(ListSelectionListener listener) - { - mTable.getSelectionModel().removeListSelectionListener(listener); - } - - public class AliasedValueCellRenderer extends JPanel implements TableCellRenderer - { - private JLabel mLabel1; - private JLabel mAlias1; - private JLabel mLabel2; - private JLabel mAlias2; - - private Attribute mAttribute1; - private Attribute mAttribute2; - - public AliasedValueCellRenderer(Attribute attribute1, Attribute attribute2) + if(!mTable.getSelectionModel().getValueIsAdjusting()) { - mAttribute1 = attribute1; - mAttribute2 = attribute2; + ProcessingChain processingChain = null; - setLayout( new MigLayout( "insets 0 0 0 0", "[12][grow,fill]", "[grow,fill]0[grow,fill]") ); + int selectedViewRow = mTable.getSelectedRow(); - mAlias1 = new JLabel(); - add(mAlias1); - mLabel1 = new JLabel("---"); - mLabel1.setFont(mTable.getFont()); - add(mLabel1,"wrap"); - mAlias2 = new JLabel(); - add(mAlias2); - mLabel2 = new JLabel("---"); - mLabel2.setFont(mTable.getFont()); - add(mLabel2,"wrap"); + if(selectedViewRow >= 0) + { + int selectedModelRow = mTable.convertRowIndexToModel(selectedViewRow); + + Metadata selectedMetadata = mChannelProcessingManager.getChannelMetadataModel() + .getMetadata(selectedModelRow); + + if(selectedMetadata != null) + { + Channel selectedChannel = mChannelProcessingManager.getChannelMetadataModel() + .getChannelFromMetadata(selectedMetadata); + + processingChain = mChannelProcessingManager.getProcessingChain(selectedChannel); + } + } + + mSelectedProcessingChainBroadcaster.broadcast(processingChain); + } + } + + /** + * Adds the listener to receive the processing chain associated with the metadata selected in the + * metadata table. + */ + public void addProcessingChainSelectionListener(Listener listener) + { + mSelectedProcessingChainBroadcaster.addListener(listener); + } + + public class AliasedValueCellRenderer extends DefaultTableCellRenderer + { + private Attribute mAttribute; + + public AliasedValueCellRenderer(Attribute attribute) + { + assert(attribute != null); + mAttribute = attribute; + setHorizontalAlignment(JLabel.CENTER); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - MutableMetadata metadata = (MutableMetadata)value; + JLabel label = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - if(mAttribute1 != null) - { - String value1 = metadata.getValue(mAttribute1); - mLabel1.setText(value1); + Metadata metadata = (Metadata)value; + String value1 = metadata.getValue(mAttribute); + Alias alias = metadata.getAlias(mAttribute); - Alias alias1 = metadata.getAlias(mAttribute1); + label.setText(alias != null ? alias.getName() : value1); + label.setIcon(alias != null ? mIconManager.getIcon(alias.getIconName(), IconManager.DEFAULT_ICON_SIZE) : null); + label.setForeground(alias != null ? alias.getDisplayColor() : table.getForeground()); - if(alias1 != null) - { - mAlias1.setIcon(mIconManager.getIcon(alias1.getIconName(), IconManager.DEFAULT_ICON_SIZE)); - mLabel1.setForeground(alias1.getDisplayColor()); - } - else - { - mAlias1.setIcon(null); - mLabel1.setForeground(mTable.getForeground()); - } - } - - if(mAttribute2 != null) - { - String value2 = metadata.getValue(mAttribute2); - mLabel2.setText(value2); - - Alias alias2 = metadata.getAlias(mAttribute2); - - if(alias2 != null) - { - mAlias2.setIcon(mIconManager.getIcon(alias2.getIconName(), IconManager.DEFAULT_ICON_SIZE)); - mLabel2.setForeground(alias2.getDisplayColor()); - } - else - { - mAlias2.setIcon(null); - mLabel2.setForeground(mTable.getForeground()); - } - } - - setBackground(isSelected ? table.getSelectionBackground() : table.getBackground()); - - return this; + return label; } } - public class FrequencyCellRenderer extends JPanel implements TableCellRenderer + public class ColoredStateCellRenderer extends DefaultTableCellRenderer { - private final DecimalFormat FREQUENCY_FORMATTER = new DecimalFormat( "#.000000" ); - - private JLabel mLabel1; - private JLabel mLabel2; - - public FrequencyCellRenderer() + public ColoredStateCellRenderer() { - setLayout( new MigLayout( "insets 0 0 0 0", "[grow,fill,align center]", "[grow,fill]0[grow,fill]") ); - - mLabel1 = new JLabel(); - mLabel1.setFont(mTable.getFont()); - add(mLabel1,"wrap"); - mLabel2 = new JLabel(); - mLabel2.setFont(mTable.getFont()); - add(mLabel2); + setHorizontalAlignment(SwingConstants.CENTER); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - MutableMetadata metadata = (MutableMetadata)value; + JLabel label = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - if(metadata.hasChannelFrequency()) + Color background = table.getBackground(); + Color foreground = table.getForeground(); + + if(value instanceof State) { - mLabel1.setText(FREQUENCY_FORMATTER.format((double)metadata.getChannelFrequency() / 1E6d)); + State state = (State)value; + label.setText(state.getDisplayValue()); + + switch(state) + { + case CALL: + background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "call", Color.BLUE); + foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "call", Color.YELLOW); + break; + case CONTROL: + background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "control", Color.ORANGE); + foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "control", Color.BLUE); + break; + case DATA: + background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "data", Color.GREEN); + foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "data", Color.BLUE); + break; + case ENCRYPTED: + background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "encrypted", Color.MAGENTA); + foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "encrypted", Color.WHITE); + break; + case FADE: + background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "fade", Color.LIGHT_GRAY.BLUE); + foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "fade", Color.YELLOW); + break; + case IDLE: + background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "idle", Color.WHITE); + foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "idle", Color.BLUE); + break; + case RESET: + background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "reset", Color.PINK); + foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "reset", Color.YELLOW); + break; + case TEARDOWN: + background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "teardown", Color.DARK_GRAY); + foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "teardown", Color.WHITE); + break; + } } else { - mLabel1.setText(null); + setText(""); } - mLabel2.setText(metadata.getChannelFrequencyLabel()); + setBackground(background); + setForeground(foreground); - setBackground(isSelected ? table.getSelectionBackground() : table.getBackground()); - - return this; + return label; } } - - public class StateCellRenderer extends JPanel implements TableCellRenderer - { - private JLabel mLabel1; - - public StateCellRenderer() - { - setLayout( new MigLayout( "insets 0 0 0 0", "[grow,fill,align center]", "[grow,fill,align center]") ); - - mLabel1 = new JLabel(); - mLabel1.setFont(mTable.getFont()); - add(mLabel1); - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, - int row, int column) - { - MutableMetadata metadata = (MutableMetadata)value; - - mLabel1.setText(metadata.getState().getDisplayValue()); - - setBackground(isSelected ? table.getSelectionBackground() : table.getBackground()); - - return this; - } - } - } diff --git a/src/channel/metadata/ChannelMetadataViewer.java b/src/channel/metadata/ChannelMetadataViewer.java index 50531128..e40b0b00 100644 --- a/src/channel/metadata/ChannelMetadataViewer.java +++ b/src/channel/metadata/ChannelMetadataViewer.java @@ -22,7 +22,6 @@ import com.jidesoft.swing.JideSplitPane; import com.jidesoft.swing.JideTabbedPane; import controller.channel.ChannelProcessingManager; import icon.IconManager; -import icon.IconTableModel; import module.decode.event.CallEventPanel; import module.decode.event.MessageActivityPanel; import net.miginfocom.swing.MigLayout; @@ -30,6 +29,7 @@ import settings.SettingsManager; import spectrum.ChannelSpectrumPanel; import javax.swing.*; +import java.awt.*; public class ChannelMetadataViewer extends JPanel { @@ -45,11 +45,10 @@ public class ChannelMetadataViewer extends JPanel public ChannelMetadataViewer(ChannelProcessingManager channelProcessingManager, IconManager iconManager, SettingsManager settingsManager) { - mCallEventPanel = new CallEventPanel(iconManager, channelProcessingManager); + mCallEventPanel = new CallEventPanel(iconManager); mMessageActivityPanel = new MessageActivityPanel(channelProcessingManager); mChannelSpectrumPanel = new ChannelSpectrumPanel(settingsManager, channelProcessingManager); - mChannelMetadataPanel = new ChannelMetadataPanel(channelProcessingManager.getChannelMetadataModel(), - iconManager); + mChannelMetadataPanel = new ChannelMetadataPanel(channelProcessingManager, iconManager); init(); } @@ -59,49 +58,20 @@ public class ChannelMetadataViewer extends JPanel setLayout( new MigLayout( "insets 0 0 0 0", "[grow,fill]", "[grow,fill]") ); JideTabbedPane tabbedPane = new JideTabbedPane(); - tabbedPane.addTab("Details", new JPanel()); +// tabbedPane.addTab("Details", new JPanel()); tabbedPane.addTab("Events", mCallEventPanel); tabbedPane.addTab("Messages", mMessageActivityPanel); - tabbedPane.addTab("Spectrum", mChannelSpectrumPanel); +// tabbedPane.addTab("Spectrum", mChannelSpectrumPanel); + tabbedPane.setFont(this.getFont()); + tabbedPane.setForeground(Color.BLACK); JideSplitPane splitPane = new JideSplitPane(JideSplitPane.VERTICAL_SPLIT); + splitPane.setShowGripper(true); splitPane.add(mChannelMetadataPanel); splitPane.add(tabbedPane); add(splitPane); -//TODO: move this change listener to the metadata table view -// /** -// * Change listener to enable/disable the channel spectrum display -// * only when the tab is visible, and a channel has been selected -// */ -// mTabbedPane.addChangeListener(new ChangeListener() -// { -// @Override -// public void stateChanged(ChangeEvent event) -// { -// int index = mTabbedPane.getSelectedIndex(); -// -// Component component = mTabbedPane.getComponentAt(index); -// -// if(component instanceof ChannelSpectrumPanel) -// { -// mChannelSpectrumPanel.setEnabled(true); -// } -// else -// { -// mChannelSpectrumPanel.setEnabled(false); -// } -// } -// }); - -//TODO: call, message and spectrum should listen to the metadata table now -// -// -// /* Register each of the components to receive channel events when the -// * channels are selected or change */ -// mChannelModel.addListener(mCallEventPanel); -// mChannelModel.addListener(mChannelSpectrumPanel); -// mChannelModel.addListener(mMessageActivityPanel); - + mChannelMetadataPanel.addProcessingChainSelectionListener(mCallEventPanel); + mChannelMetadataPanel.addProcessingChainSelectionListener(mMessageActivityPanel); } } diff --git a/src/channel/traffic/TrafficChannelManager.java b/src/channel/traffic/TrafficChannelManager.java index 2d9829c5..1a706cf0 100644 --- a/src/channel/traffic/TrafficChannelManager.java +++ b/src/channel/traffic/TrafficChannelManager.java @@ -18,30 +18,10 @@ ******************************************************************************/ package channel.traffic; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ScheduledExecutorService; - -import channel.state.DecoderStateEvent; -import channel.state.IDecoderStateEventListener; -import module.Module; -import module.decode.config.DecodeConfiguration; -import module.decode.event.CallEvent; -import module.decode.event.CallEvent.CallEventType; -import module.decode.event.ICallEventProvider; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import record.config.RecordConfiguration; -import sample.Listener; -import source.config.SourceConfigTuner; -import source.tuner.TunerChannel; -import source.tuner.TunerChannel.Type; import alias.Alias; import alias.id.priority.Priority; +import channel.state.DecoderStateEvent; +import channel.state.IDecoderStateEventListener; import controller.channel.Channel; import controller.channel.Channel.ChannelType; import controller.channel.ChannelEvent; @@ -49,203 +29,211 @@ import controller.channel.ChannelEvent.Event; import controller.channel.ChannelModel; import controller.channel.ChannelProcessingManager; import controller.channel.TrafficChannelEvent; +import module.Module; +import module.decode.config.DecodeConfiguration; +import module.decode.event.CallEvent; +import module.decode.event.CallEvent.CallEventType; +import module.decode.event.ICallEventProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import record.config.RecordConfiguration; +import sample.Listener; +import source.config.SourceConfigTuner; +import source.tuner.TunerChannel; +import source.tuner.TunerChannel.Type; -public class TrafficChannelManager extends Module - implements ICallEventProvider, IDecoderStateEventListener +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledExecutorService; + +public class TrafficChannelManager extends Module implements ICallEventProvider, IDecoderStateEventListener { - private final static Logger mLog = LoggerFactory.getLogger( TrafficChannelManager.class ); + private final static Logger mLog = LoggerFactory.getLogger(TrafficChannelManager.class); public static final String CHANNEL_START_REJECTED = "CHANNEL START REJECTED"; public static final String NO_TUNER_AVAILABLE = "NO TUNER AVAILABLE"; public static final String UNKNOWN_FREQUENCY = "UNKNOWN FREQUENCY"; - private int mTrafficChannelPoolMaximumSize = - DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_DEFAULT; - private List mTrafficChannelPool = new ArrayList(); - private Map mTrafficChannelsInUse = new ConcurrentHashMap(); + private int mTrafficChannelPoolMaximumSize = DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_DEFAULT; + private List mTrafficChannelPool = new ArrayList(); + private Map mTrafficChannelsInUse = new ConcurrentHashMap(); - private DecoderStateEventListener mEventListener = new DecoderStateEventListener(); - private Listener mCallEventListener; + private DecoderStateEventListener mEventListener = new DecoderStateEventListener(); + private Listener mCallEventListener; - private ChannelModel mChannelModel; - private ChannelProcessingManager mChannelProcessingManager; - private DecodeConfiguration mDecodeConfiguration; - private RecordConfiguration mRecordConfiguration; - private String mSystem; - private String mSite; - private String mAliasListName; - private CallEvent mPreviousDoNotMonitorCallEvent; + private ChannelModel mChannelModel; + private ChannelProcessingManager mChannelProcessingManager; + private DecodeConfiguration mDecodeConfiguration; + private RecordConfiguration mRecordConfiguration; + private String mSystem; + private String mSite; + private String mAliasListName; + private CallEvent mPreviousDoNotMonitorCallEvent; - /** - * Monitors call events and allocates traffic decoder channels in response - * to traffic channel allocation call events. Manages a pool of reusable - * traffic channel allocations. - * + /** + * Monitors call events and allocates traffic decoder channels in response + * to traffic channel allocation call events. Manages a pool of reusable + * traffic channel allocations. + * * @param channelModel containing channels currently in use - * * @param channelProcessingManager - * - * @param decodeConfiguration - decoder configuration to use for each - * traffic channel allocation. - * - * @param recordConfiguration - recording options for each traffic channel - * + * @param decodeConfiguration - decoder configuration to use for each + * traffic channel allocation. + * @param recordConfiguration - recording options for each traffic channel * @param system label to use to describe the system - * * @param site label to use to describe the site - * * @param aliasListName designated for the channel - * - * @param trafficChannelTimeout - millisecond call timer limit used when an - * end of call signalling event is not decoded. - * - * @param trafficChannelPoolSize - maximum number of allocated traffic channels - * in the pool - */ - public TrafficChannelManager( ChannelModel channelModel, - ChannelProcessingManager channelProcessingManager, - DecodeConfiguration decodeConfiguration, - RecordConfiguration recordConfiguration, - String system, - String site, - String aliasListName, - long trafficChannelTimeout, - int trafficChannelPoolSize ) - { - mChannelModel = channelModel; - mChannelProcessingManager = channelProcessingManager; - mDecodeConfiguration = decodeConfiguration; - mRecordConfiguration = recordConfiguration; - mSystem = system; - mSite = site; - mAliasListName = aliasListName; - mTrafficChannelPoolMaximumSize = trafficChannelPoolSize; - } - - @Override - public void dispose() - { - for( Channel trafficChannel: mTrafficChannelPool ) - { - mChannelModel.broadcast( new ChannelEvent( trafficChannel, Event.REQUEST_DISABLE ) ); - } + * @param trafficChannelTimeout - millisecond call timer limit used when an + * end of call signalling event is not decoded. + * @param trafficChannelPoolSize - maximum number of allocated traffic channels + * in the pool + */ + public TrafficChannelManager(ChannelModel channelModel, + ChannelProcessingManager channelProcessingManager, + DecodeConfiguration decodeConfiguration, + RecordConfiguration recordConfiguration, + String system, + String site, + String aliasListName, + long trafficChannelTimeout, + int trafficChannelPoolSize) + { + mChannelModel = channelModel; + mChannelProcessingManager = channelProcessingManager; + mDecodeConfiguration = decodeConfiguration; + mRecordConfiguration = recordConfiguration; + mSystem = system; + mSite = site; + mAliasListName = aliasListName; + mTrafficChannelPoolMaximumSize = trafficChannelPoolSize; + } - mTrafficChannelPool.clear(); - - mTrafficChannelsInUse.clear(); - - mCallEventListener = null; - mDecodeConfiguration = null; - mPreviousDoNotMonitorCallEvent = null; - } + @Override + public void dispose() + { + for(Channel trafficChannel : mTrafficChannelPool) + { + mChannelModel.broadcast(new ChannelEvent(trafficChannel, Event.REQUEST_DISABLE)); + } - /** - * Provides a channel by either reusing an existing channel or constructing - * a new one, limited by the total number of constructed channels allowed. - * - * Note: you must enforce thread safety on the mTrafficChannelsInUse - * external to this method. - * - * @param channelNumber - * @param tunerChannel - * @return - */ - private Channel getChannel( String channelNumber, TunerChannel tunerChannel ) - { - Channel channel = null; - - if( !mTrafficChannelsInUse.containsKey( channelNumber ) ) - { - for( Channel configuredChannel: mTrafficChannelPool ) - { - if( !configuredChannel.getEnabled() ) - { - channel = configuredChannel; - break; - } - } - - if( channel == null && mTrafficChannelPool.size() < mTrafficChannelPoolMaximumSize ) - { - channel = new Channel( "Traffic", ChannelType.TRAFFIC ); - - channel.setDecodeConfiguration( mDecodeConfiguration ); - - channel.setRecordConfiguration( mRecordConfiguration ); - - channel.setAliasListName( mAliasListName ); - - mChannelModel.addChannel( channel ); - - mTrafficChannelPool.add( channel ); - } + mTrafficChannelPool.clear(); + + mTrafficChannelsInUse.clear(); + + mCallEventListener = null; + mDecodeConfiguration = null; + mPreviousDoNotMonitorCallEvent = null; + } + + /** + * Provides a channel by either reusing an existing channel or constructing + * a new one, limited by the total number of constructed channels allowed. + * + * Note: you must enforce thread safety on the mTrafficChannelsInUse + * external to this method. + * + * @param channelNumber + * @param tunerChannel + * @return + */ + private Channel getChannel(String channelNumber, TunerChannel tunerChannel) + { + Channel channel = null; + + if(!mTrafficChannelsInUse.containsKey(channelNumber)) + { + for(Channel configuredChannel : mTrafficChannelPool) + { + if(!configuredChannel.getEnabled()) + { + channel = configuredChannel; + break; + } + } + + if(channel == null && mTrafficChannelPool.size() < mTrafficChannelPoolMaximumSize) + { + channel = new Channel("Traffic", ChannelType.TRAFFIC); + + channel.setDecodeConfiguration(mDecodeConfiguration); + + channel.setRecordConfiguration(mRecordConfiguration); + + channel.setAliasListName(mAliasListName); + + mChannelModel.addChannel(channel); + + mTrafficChannelPool.add(channel); + } /* If we have a configured channel, update metadata */ - if( channel != null ) - { - channel.setSourceConfiguration( new SourceConfigTuner( tunerChannel ) ); - channel.setSystem( mSystem ); - channel.setSite( mSite ); - channel.setName( channelNumber ); + if(channel != null) + { + channel.setSourceConfiguration(new SourceConfigTuner(tunerChannel)); + channel.setSystem(mSystem); + channel.setSite(mSite); + channel.setName(channelNumber); - mChannelModel.broadcast( new ChannelEvent( channel, Event.NOTIFICATION_CONFIGURATION_CHANGE ) ); - } - } + mChannelModel.broadcast(new ChannelEvent(channel, Event.NOTIFICATION_CONFIGURATION_CHANGE)); + } + } - return channel; - } - - /** - * Processes the event and creates a traffic channel is resources are - * available - */ - private void process( TrafficChannelAllocationEvent event ) - { - CallEvent callEvent = event.getCallEvent(); + return channel; + } + + /** + * Processes the event and creates a traffic channel is resources are + * available + */ + private void process(TrafficChannelAllocationEvent event) + { + CallEvent callEvent = event.getCallEvent(); /* Check for duplicate events and suppress */ - synchronized( mTrafficChannelsInUse ) - { - if( mTrafficChannelsInUse.containsKey( callEvent.getChannel() ) ) - { - return; - } + synchronized(mTrafficChannelsInUse) + { + if(mTrafficChannelsInUse.containsKey(callEvent.getChannel())) + { + return; + } + + long frequency = callEvent.getFrequency(); - long frequency = callEvent.getFrequency(); - /* Check the from/to aliases for do not monitor priority */ - if( isDoNotMonitor( callEvent ) ) - { - callEvent.setCallEventType( CallEventType.CALL_DO_NOT_MONITOR ); + if(isDoNotMonitor(callEvent)) + { + callEvent.setCallEventType(CallEventType.CALL_DO_NOT_MONITOR); - if( isSameCallEvent( mPreviousDoNotMonitorCallEvent, callEvent ) ) - { - return; - } - else - { - mPreviousDoNotMonitorCallEvent = callEvent; - } - } - else if( frequency > 0 ) - { - Channel channel = getChannel( callEvent.getChannel(), new TunerChannel( Type.TRAFFIC, - frequency, mDecodeConfiguration.getDecoderType().getChannelBandwidth() ) ); + if(isSameCallEvent(mPreviousDoNotMonitorCallEvent, callEvent)) + { + return; + } + else + { + mPreviousDoNotMonitorCallEvent = callEvent; + } + } + else if(frequency > 0) + { + Channel channel = getChannel(callEvent.getChannel(), new TunerChannel(Type.TRAFFIC, + frequency, mDecodeConfiguration.getDecoderType().getChannelBandwidth())); - if( channel != null ) - { - TrafficChannelEvent trafficChannelEvent = - new TrafficChannelEvent( this, channel, Event.REQUEST_ENABLE, callEvent ); - - //Request to enable the channel - mChannelModel.broadcast( trafficChannelEvent ); + if(channel != null) + { + TrafficChannelEvent trafficChannelEvent = + new TrafficChannelEvent(this, channel, Event.REQUEST_ENABLE, callEvent); - if( channel.getEnabled() ) - { - mTrafficChannelsInUse.put( callEvent.getChannel(), channel ); - } - else - { - callEvent.setCallEventType( CallEventType.CALL_DETECT ); + //Request to enable the channel + mChannelModel.broadcast(trafficChannelEvent); + + if(channel.getEnabled()) + { + mTrafficChannelsInUse.put(callEvent.getChannel(), channel); + } + else + { + callEvent.setCallEventType(CallEventType.CALL_DETECT); String details = callEvent.getDetails(); @@ -255,15 +243,14 @@ public class TrafficChannelManager extends Module } else if(!details.contains(CHANNEL_START_REJECTED)) { - callEvent.setDetails(new StringBuilder(CHANNEL_START_REJECTED) - .append(" : ") - .append(callEvent.getDetails()).toString()); + callEvent.setDetails(new StringBuilder(CHANNEL_START_REJECTED).append(" : ") + .append(callEvent.getDetails()).toString()); } - } - } - else - { - callEvent.setCallEventType( CallEventType.CALL_DETECT ); + } + } + else + { + callEvent.setCallEventType(CallEventType.CALL_DETECT); String details = callEvent.getDetails(); @@ -273,15 +260,14 @@ public class TrafficChannelManager extends Module } else if(!details.contains(NO_TUNER_AVAILABLE)) { - callEvent.setDetails(new StringBuilder(NO_TUNER_AVAILABLE) - .append(" : ") - .append(callEvent.getDetails()).toString()); + callEvent.setDetails(new StringBuilder(NO_TUNER_AVAILABLE).append(" : ") + .append(callEvent.getDetails()).toString()); } - } - } - else - { - callEvent.setCallEventType( CallEventType.CALL_DETECT ); + } + } + else + { + callEvent.setCallEventType(CallEventType.CALL_DETECT); String details = callEvent.getDetails(); @@ -291,187 +277,171 @@ public class TrafficChannelManager extends Module } else if(!details.contains(UNKNOWN_FREQUENCY)) { - callEvent.setDetails(new StringBuilder(UNKNOWN_FREQUENCY) - .append(" : ") - .append(callEvent.getDetails()).toString()); + callEvent.setDetails(new StringBuilder(UNKNOWN_FREQUENCY).append(" : ") + .append(callEvent.getDetails()).toString()); } - } + } - final Listener listener = mCallEventListener; - - if( listener != null ) - { - listener.receive( callEvent ); - } - } - } + final Listener listener = mCallEventListener; - /** - * Compares the call type, channel and to fields for equivalence and the - * from field for either both null, or equivalence. - * - * @param e1 - * @param e2 - * @return - */ - public static boolean isSameCallEvent( CallEvent e1, CallEvent e2 ) - { - if( e1 == null || e2 == null ) - { - return false; - } + if(listener != null) + { + listener.receive(callEvent); + } + } + } - if( e1.getCallEventType() != e2.getCallEventType() ) - { - return false; - } + /** + * Compares the call type, channel and to fields for equivalence and the + * from field for either both null, or equivalence. + * + * @param e1 + * @param e2 + * @return + */ + public static boolean isSameCallEvent(CallEvent e1, CallEvent e2) + { + if(e1 == null || e2 == null) + { + return false; + } - if( e1.getChannel() == null || - e2.getChannel() == null || - !e1.getChannel().contentEquals( e2.getChannel() ) ) - { - return false; - } - - if( e1.getToID() == null || - e2.getToID() == null || - !e1.getToID().contentEquals( e2.getToID() ) ) - { - return false; - } + if(e1.getCallEventType() != e2.getCallEventType()) + { + return false; + } - if( e1.getFromID() == null || e2.getFromID() == null ) - { - if( e1.getFromID() == null && e2.getFromID() == null ) - { - return true; - } - else - { - return false; - } - } - else if( e1.getFromID().contentEquals( e2.getFromID() ) ) - { - return true; - } - - return false; - } - - /** - * Checks for aliases that contain a do not follow/process priority. - * - * @param event - * @return - true if there is an alias that has a do not process alias id - */ - private boolean isDoNotMonitor( CallEvent event ) - { - Alias to = event.getToIDAlias(); + if(e1.getChannel() == null || e2.getChannel() == null || !e1.getChannel().contentEquals(e2.getChannel())) + { + return false; + } - if( to != null && - to.hasCallPriority() && - to.getCallPriority() == Priority.DO_NOT_MONITOR ) - { - return true; - } - - Alias from = event.getFromIDAlias(); + if(e1.getToID() == null || e2.getToID() == null || !e1.getToID().contentEquals(e2.getToID())) + { + return false; + } - if( from != null && - from.hasCallPriority() && - from.getCallPriority() == Priority.DO_NOT_MONITOR ) - { - return true; - } - - return false; - } + if(e1.getFromID() == null || e2.getFromID() == null) + { + return (e1.getFromID() == null && e2.getFromID() == null); + } + else if(e1.getFromID().contentEquals(e2.getFromID())) + { + return true; + } - @Override - public Listener getDecoderStateListener() - { - return mEventListener; - } + return false; + } - @Override - public void addCallEventListener( Listener listener ) - { - mCallEventListener = listener; - } + /** + * Checks for aliases that contain a do not follow/process priority. + * + * @param event + * @return - true if there is an alias that has a do not process alias id + */ + private boolean isDoNotMonitor(CallEvent event) + { + Alias to = event.getToIDAlias(); - @Override - public void removeCallEventListener( Listener listener ) - { - mCallEventListener = null; - } + if(to != null && to.hasCallPriority() && to.getCallPriority() == Priority.DO_NOT_MONITOR) + { + return true; + } - @Override - public void reset() - { - } - - @Override - public void start( ScheduledExecutorService executor ) - { - } + Alias from = event.getFromIDAlias(); - @Override - public void stop() - { - if( !mTrafficChannelsInUse.isEmpty() ) - { - List channels = new ArrayList<>(); + if(from != null && from.hasCallPriority() && from.getCallPriority() == Priority.DO_NOT_MONITOR) + { + return true; + } + + return false; + } + + @Override + public Listener getDecoderStateListener() + { + return mEventListener; + } + + @Override + public void addCallEventListener(Listener listener) + { + mCallEventListener = listener; + } + + @Override + public void removeCallEventListener(Listener listener) + { + mCallEventListener = null; + } + + @Override + public void reset() + { + } + + @Override + public void start(ScheduledExecutorService executor) + { + } + + @Override + public void stop() + { + if(!mTrafficChannelsInUse.isEmpty()) + { + List channels = new ArrayList<>(); /* Copy the keyset so we don't get concurrent modification of the map */ - channels.addAll( mTrafficChannelsInUse.keySet() ); - - for( String channel: channels ) - { - callEnd( channel ); - } - } - } + channels.addAll(mTrafficChannelsInUse.keySet()); - /** - * Callback used by the TrafficChannelStatusListener class to signal the - * end of a an allocated traffic channel call event - * - * @param channelNumber - channel number from the call event that signaled - * the start of a traffic channel allocation - */ - public void callEnd( String channelNumber ) - { - synchronized( mTrafficChannelsInUse ) - { - if( channelNumber != null && mTrafficChannelsInUse.containsKey( channelNumber ) ) - { - Channel channel = mTrafficChannelsInUse.get( channelNumber ); + for(String channel : channels) + { + callEnd(channel); + } + } + } - mChannelModel.broadcast( new ChannelEvent( channel, Event.REQUEST_DISABLE ) ); - - mTrafficChannelsInUse.remove( channelNumber ); - } - } - } - - /** - * Wrapper class for the decoder state event listener interface to catch - * traffic channel allocation requests - */ - public class DecoderStateEventListener implements Listener - { - @Override - public void receive( DecoderStateEvent event ) - { - switch( event.getEvent() ) - { - case TRAFFIC_CHANNEL_ALLOCATION: - process( (TrafficChannelAllocationEvent)event ); - break; - default: - break; - } - } - } + /** + * Callback used by the TrafficChannelStatusListener class to signal the + * end of a an allocated traffic channel call event + * + * @param channelNumber - channel number from the call event that signaled + * the start of a traffic channel allocation + */ + public void callEnd(String channelNumber) + { + synchronized(mTrafficChannelsInUse) + { + if(channelNumber != null && mTrafficChannelsInUse.containsKey(channelNumber)) + { + Channel channel = mTrafficChannelsInUse.get(channelNumber); + + mChannelModel.broadcast(new ChannelEvent(channel, Event.REQUEST_DISABLE)); + + mTrafficChannelsInUse.remove(channelNumber); + } + } + } + + /** + * Wrapper class for the decoder state event listener interface to catch + * traffic channel allocation requests + */ + public class DecoderStateEventListener implements Listener + { + @Override + public void receive(DecoderStateEvent event) + { + switch(event.getEvent()) + { + case TRAFFIC_CHANNEL_ALLOCATION: + process((TrafficChannelAllocationEvent) event); + break; + default: + break; + } + } + } } diff --git a/src/controller/channel/ChannelProcessingManager.java b/src/controller/channel/ChannelProcessingManager.java index 7cdf4151..d4b16f63 100644 --- a/src/controller/channel/ChannelProcessingManager.java +++ b/src/controller/channel/ChannelProcessingManager.java @@ -31,6 +31,7 @@ import message.Message; import module.Module; import module.ProcessingChain; import module.decode.DecoderFactory; +import module.decode.DecoderType; import module.decode.event.MessageActivityModel; import module.log.EventLogManager; import org.slf4j.Logger; @@ -41,6 +42,8 @@ import sample.Listener; import source.Source; import source.SourceException; import source.SourceManager; +import source.SourceType; +import source.config.SourceConfigTuner; import java.util.HashMap; import java.util.List; @@ -184,8 +187,7 @@ public class ChannelProcessingManager implements ChannelEventListener { channel.setEnabled(false); - mChannelModel.broadcast( - new ChannelEvent(channel, Event.NOTIFICATION_ENABLE_REJECTED)); + mChannelModel.broadcast(new ChannelEvent(channel, Event.NOTIFICATION_ENABLE_REJECTED)); return; } @@ -224,31 +226,20 @@ public class ChannelProcessingManager implements ChannelEventListener } //Inject channel metadata that will be inserted into audio packets for recorder manager and streaming - StringBuilder sb = new StringBuilder(); + processingChain.getChannelState().getMutableMetadata().receive( + new AttributeChangeRequest(Attribute.CHANNEL_CONFIGURATION_LABEL_1, channel.getName())); - if(channel.getSystem() != null) + if(channel.getSourceConfiguration().getSourceType() == SourceType.TUNER) { - sb.append(channel.getSystem()); + long frequency = ((SourceConfigTuner)channel.getSourceConfiguration()).getFrequency(); + + processingChain.getChannelState().getMutableMetadata().receive( + new AttributeChangeRequest(Attribute.CHANNEL_FREQUENCY, frequency)); } - if(channel.getSite() != null) - { - if(sb.length() > 0) - { - sb.append(" - "); - } - - sb.append(channel.getSite()); - } - - if(sb.length() > 0) - { - processingChain.getChannelState().getMutableMetadata() - .receive(new AttributeChangeRequest(Attribute.CHANNEL_CONFIGURATION_LABEL_1, sb.toString())); - } - - processingChain.getChannelState().getMutableMetadata() - .receive(new AttributeChangeRequest(Attribute.CHANNEL_CONFIGURATION_LABEL_2, channel.getName())); + processingChain.getChannelState().getMutableMetadata().receive( + new AttributeChangeRequest(Attribute.PRIMARY_DECODER_TYPE, + channel.getDecodeConfiguration().getDecoderType())); } /* Setup event logging */ diff --git a/src/module/decode/event/CallEventAliasCellRenderer.java b/src/module/decode/event/CallEventAliasCellRenderer.java index c85a0a65..9daa9752 100644 --- a/src/module/decode/event/CallEventAliasCellRenderer.java +++ b/src/module/decode/event/CallEventAliasCellRenderer.java @@ -19,10 +19,14 @@ package module.decode.event; import alias.Alias; +import gui.SDRTrunk; import icon.IconManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.swing.*; import javax.swing.table.DefaultTableCellRenderer; +import java.awt.*; /** * Custom renderer for JTable cells that contain Alias objects. Renders the @@ -32,6 +36,7 @@ import javax.swing.table.DefaultTableCellRenderer; public class CallEventAliasCellRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1L; + private final static Logger mLog = LoggerFactory.getLogger(CallEventAliasCellRenderer.class); private IconManager mIconManager; @@ -41,35 +46,26 @@ public class CallEventAliasCellRenderer extends DefaultTableCellRenderer mIconManager = iconManager; } - public void setValue(Object obj) + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - if(obj != null && obj instanceof Alias) + JLabel label = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + + if(value instanceof Alias) { - Alias alias = (Alias) obj; + Alias alias = (Alias)value; - setText(alias.getName()); - - ImageIcon icon = getIcon(alias, IconManager.DEFAULT_ICON_SIZE); - - if(icon != null) - { - setIcon(icon); - } + label.setText(alias.getName()); + label.setForeground(alias.getDisplayColor()); + label.setIcon(mIconManager.getIcon(alias.getIconName(), IconManager.DEFAULT_ICON_SIZE)); } else { - setText(" "); - setIcon(null); - } - } - - private ImageIcon getIcon(Alias alias, int height) - { - if(mIconManager != null && alias != null) - { - return mIconManager.getIcon(alias.getIconName(), height); + label.setText(""); + label.setForeground(table.getForeground()); + label.setIcon(null); } - return null; + return label; } } diff --git a/src/module/decode/event/CallEventModel.java b/src/module/decode/event/CallEventModel.java index c39d3dfc..a65d993d 100644 --- a/src/module/decode/event/CallEventModel.java +++ b/src/module/decode/event/CallEventModel.java @@ -1,38 +1,38 @@ /******************************************************************************* * SDR Trunk * Copyright (C) 2014,2015 Dennis Sheirer - * + * * 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 * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * 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 * along with this program. If not, see ******************************************************************************/ package module.decode.event; +import alias.Alias; +import module.decode.event.CallEvent.CallEventType; +import sample.Listener; + +import javax.swing.table.AbstractTableModel; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; -import javax.swing.table.AbstractTableModel; - -import module.decode.event.CallEvent.CallEventType; -import sample.Listener; - public class CallEventModel extends AbstractTableModel implements Listener { private static final long serialVersionUID = 1L; - private static DecimalFormat mFrequencyFormatter = new DecimalFormat( "0.000000" ); - + private static DecimalFormat mFrequencyFormatter = new DecimalFormat("0.000000"); + public static final int TIME = 0; public static final int EVENT = 1; public static final int FROM_ID = 2; @@ -43,168 +43,179 @@ public class CallEventModel extends AbstractTableModel implements Listener mEvents = new ArrayList(); + protected List mEvents = new ArrayList(); - protected String[] mHeaders = new String[] { "Time", - "Event", - "From", - "Alias", - "To", - "Alias", - "Channel", - "Frequency", - "Details" }; + protected String[] mHeaders = new String[]{"Time", + "Event", + "From", + "Alias", + "To", + "Alias", + "Channel", + "Frequency", + "Details"}; - private SimpleDateFormat mSDFTime = new SimpleDateFormat( "HH:mm:ss" ); - - public CallEventModel() - { - } - - public void dispose() - { - mEvents.clear(); - } - - public void reset() - { - mEvents.clear(); - - fireTableDataChanged(); - } - - public int getMaxMessageCount() - { - return mMaxMessages; - } + private SimpleDateFormat mSDFTime = new SimpleDateFormat("HH:mm:ss"); - public void setMaxMessageCount( int count ) - { - mMaxMessages = count; - } + public CallEventModel() + { + } - /** - * Adds, updates or deletes the event from the model. Producers can send - * the same call event multiple times to indicate that information in the - * event is updated. Producers can also mark the event as invalid and the - * event will be removed from the model. - */ - public void receive( final CallEvent event ) - { - if( event.isValid() ) - { - if( !mEvents.contains( event ) ) - { - mEvents.add( 0, event ); - - fireTableRowsInserted( 0, 0 ); + public void dispose() + { + mEvents.clear(); + } - prune(); - } - else - { - int row = mEvents.indexOf( event ); - - fireTableRowsUpdated( row, row ); - } - } - else - { - if( mEvents.contains( event ) ) - { - int row = mEvents.indexOf( event ); - - mEvents.remove( event ); - - fireTableRowsDeleted( row, row ); - } - } - } - - private void prune() - { - while( mEvents.size() > mMaxMessages ) - { - int index = mEvents.size() - 1; - mEvents.remove( index ); - - fireTableRowsDeleted( index, index ); - } - } + public void reset() + { + mEvents.clear(); - @Override + fireTableDataChanged(); + } + + public int getMaxMessageCount() + { + return mMaxMessages; + } + + public void setMaxMessageCount(int count) + { + mMaxMessages = count; + } + + /** + * Adds, updates or deletes the event from the model. Producers can send + * the same call event multiple times to indicate that information in the + * event is updated. Producers can also mark the event as invalid and the + * event will be removed from the model. + */ + public void receive(final CallEvent event) + { + if(event.isValid()) + { + if(!mEvents.contains(event)) + { + mEvents.add(0, event); + + fireTableRowsInserted(0, 0); + + prune(); + } + else + { + int row = mEvents.indexOf(event); + + fireTableRowsUpdated(row, row); + } + } + else + { + if(mEvents.contains(event)) + { + int row = mEvents.indexOf(event); + + mEvents.remove(event); + + fireTableRowsDeleted(row, row); + } + } + } + + private void prune() + { + while(mEvents.size() > mMaxMessages) + { + int index = mEvents.size() - 1; + mEvents.remove(index); + + fireTableRowsDeleted(index, index); + } + } + + @Override public int getRowCount() { - return mEvents.size(); + return mEvents.size(); } - @Override + @Override public int getColumnCount() { - return mHeaders.length; + return mHeaders.length; } - public String getColumnName( int column ) - { - return mHeaders[ column ]; - } - - @Override - public Object getValueAt( int rowIndex, int columnIndex ) + public String getColumnName(int column) { - synchronized( mEvents ) - { - switch( columnIndex ) - { - case TIME: - StringBuilder sb = new StringBuilder(); - - sb.append( mSDFTime.format( - mEvents.get( rowIndex ).getEventStartTime() ) ); - - if( mEvents.get( rowIndex ).getEventEndTime() != 0 ) - { - sb.append( " - " ); - sb.append( mSDFTime.format( - mEvents.get( rowIndex ).getEventEndTime() ) ); - } - else if( mEvents.get( rowIndex ) - .getCallEventType() == CallEventType.CALL ) - { - sb.append( " - In Progress" ); - } - - return sb.toString(); - case EVENT: - return mEvents.get( rowIndex ).getCallEventType(); - case FROM_ID: - return mEvents.get( rowIndex ).getFromID(); - case FROM_ALIAS: - return mEvents.get( rowIndex ).getFromIDAlias(); - case TO_ID: - return mEvents.get( rowIndex ).getToID(); - case TO_ALIAS: - return mEvents.get( rowIndex ).getToIDAlias(); - case CHANNEL: - return mEvents.get( rowIndex ).getChannel(); - case FREQUENCY: - long frequency = mEvents.get( rowIndex ).getFrequency(); - - if( frequency != 0 ) - { - return mFrequencyFormatter.format( (double)frequency / 1E6d ); - } - else - { - return null; - } - case DETAILS: - return mEvents.get( rowIndex ).getDetails(); - } - } - - return null; + return mHeaders[column]; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) + { + synchronized(mEvents) + { + switch(columnIndex) + { + case TIME: + StringBuilder sb = new StringBuilder(); + + sb.append(mSDFTime.format( + mEvents.get(rowIndex).getEventStartTime())); + + if(mEvents.get(rowIndex).getEventEndTime() != 0) + { + sb.append(" - "); + sb.append(mSDFTime.format( + mEvents.get(rowIndex).getEventEndTime())); + } + else if(mEvents.get(rowIndex) + .getCallEventType() == CallEventType.CALL) + { + sb.append(" - In Progress"); + } + + return sb.toString(); + case EVENT: + return mEvents.get(rowIndex).getCallEventType(); + case FROM_ID: + return mEvents.get(rowIndex).getFromID(); + case FROM_ALIAS: + return mEvents.get(rowIndex).getFromIDAlias(); + case TO_ID: + return mEvents.get(rowIndex).getToID(); + case TO_ALIAS: + return mEvents.get(rowIndex).getToIDAlias(); + case CHANNEL: + return mEvents.get(rowIndex).getChannel(); + case FREQUENCY: + long frequency = mEvents.get(rowIndex).getFrequency(); + + if(frequency != 0) + { + return mFrequencyFormatter.format((double) frequency / 1E6d); + } + else + { + return null; + } + case DETAILS: + return mEvents.get(rowIndex).getDetails(); + } + } + + return null; + } + + @Override + public Class getColumnClass(int columnIndex) + { + if(columnIndex == FROM_ALIAS || columnIndex == TO_ALIAS) + { + return Alias.class; + } + + return super.getColumnClass(columnIndex); } } diff --git a/src/module/decode/event/CallEventPanel.java b/src/module/decode/event/CallEventPanel.java index c4e6ca49..9b8cedd1 100644 --- a/src/module/decode/event/CallEventPanel.java +++ b/src/module/decode/event/CallEventPanel.java @@ -18,112 +18,58 @@ ******************************************************************************/ package module.decode.event; -import controller.channel.Channel; -import controller.channel.ChannelEvent; -import controller.channel.ChannelEvent.Event; -import controller.channel.ChannelEventListener; -import controller.channel.ChannelProcessingManager; import icon.IconManager; import module.ProcessingChain; import net.miginfocom.swing.MigLayout; +import sample.Listener; import javax.swing.*; import java.awt.*; -public class CallEventPanel extends JPanel implements ChannelEventListener +public class CallEventPanel extends JPanel implements Listener { private static final long serialVersionUID = 1L; - + private JTable mTable; + private CallEventModel mEmptyCallEventModel = new CallEventModel(); private JScrollPane mEmptyScroller; - private Channel mDisplayedChannel; private CallEventAliasCellRenderer mRenderer; - private ChannelProcessingManager mChannelProcessingManager; - public CallEventPanel(IconManager iconManager, ChannelProcessingManager channelProcessingManager) + /** + * View for call event table + * @param iconManager to display alias icons in table rows + */ + public CallEventPanel(IconManager iconManager) { - mChannelProcessingManager = channelProcessingManager; + setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill]")); - setLayout(new MigLayout("insets 0 0 0 0 ", "[grow,fill]", "[grow,fill]")); - - JTable table = new JTable(new CallEventModel()); - table.setAutoCreateRowSorter(true); - table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); + mTable = new JTable(mEmptyCallEventModel); + mTable.setAutoCreateRowSorter(true); + mTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); mRenderer = new CallEventAliasCellRenderer(iconManager); - table.getColumnModel().getColumn(CallEventModel.FROM_ALIAS).setCellRenderer(mRenderer); - table.getColumnModel().getColumn(CallEventModel.TO_ALIAS).setCellRenderer(mRenderer); - - mEmptyScroller = new JScrollPane(table); + mEmptyScroller = new JScrollPane(mTable); add(mEmptyScroller); } @Override - public void channelChanged(final ChannelEvent event) + public void receive(ProcessingChain processingChain) { - if(event.getEvent() == Event.NOTIFICATION_SELECTION_CHANGE && event.getChannel().isSelected()) + EventQueue.invokeLater(new Runnable() { - if(mDisplayedChannel == null || (mDisplayedChannel != null && mDisplayedChannel != event.getChannel())) + @Override + public void run() { - ProcessingChain chain = mChannelProcessingManager.getProcessingChain(event.getChannel()); + mTable.setModel(processingChain != null ? processingChain.getCallEventModel() : mEmptyCallEventModel); - if(chain != null) + if(processingChain != null) { - final CallEventModel model = chain.getCallEventModel(); - - if(model != null) - { - EventQueue.invokeLater(new Runnable() - { - @Override - public void run() - { - removeAll(); - - JTable table = new JTable(model); - - table.setAutoCreateRowSorter(true); - table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); - - table.getColumnModel().getColumn(CallEventModel.FROM_ALIAS) - .setCellRenderer(mRenderer); - - table.getColumnModel().getColumn(CallEventModel.TO_ALIAS) - .setCellRenderer(mRenderer); - - add(new JScrollPane(table)); - - mDisplayedChannel = event.getChannel(); - - revalidate(); - repaint(); - } - }); - } + mTable.getColumnModel().getColumn(CallEventModel.FROM_ALIAS).setCellRenderer(mRenderer); + mTable.getColumnModel().getColumn(CallEventModel.TO_ALIAS).setCellRenderer(mRenderer); } } - } - else if(event.getEvent() == Event.NOTIFICATION_PROCESSING_STOP || event.getEvent() == Event.REQUEST_DISABLE) - { - if(mDisplayedChannel != null && mDisplayedChannel == event.getChannel()) - { - mDisplayedChannel = null; - - EventQueue.invokeLater(new Runnable() - { - @Override - public void run() - { - removeAll(); - add(mEmptyScroller); - - revalidate(); - repaint(); - } - }); - } - } + }); } } diff --git a/src/module/decode/event/MessageActivityPanel.java b/src/module/decode/event/MessageActivityPanel.java index 7b6d308b..a79cefcd 100644 --- a/src/module/decode/event/MessageActivityPanel.java +++ b/src/module/decode/event/MessageActivityPanel.java @@ -32,6 +32,7 @@ import module.ProcessingChain; import net.miginfocom.swing.MigLayout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import sample.Listener; import javax.swing.*; import javax.swing.event.ChangeEvent; @@ -42,7 +43,7 @@ import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; -public class MessageActivityPanel extends JPanel implements ChannelEventListener +public class MessageActivityPanel extends JPanel implements Listener { private static final long serialVersionUID = 1L; @@ -50,10 +51,7 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener private static MessageActivityModel EMPTY_MODEL = new MessageActivityModel(); - private JTable mMessageTable; - - private Channel mDisplayedChannel; - private MessageActivityModel mDisplayedModel = EMPTY_MODEL; + private JTable mTable = new JTable(EMPTY_MODEL); private MessageManagementPanel mManagementPanel = new MessageManagementPanel(); @@ -67,37 +65,20 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener add(mManagementPanel, "span,growx"); - mMessageTable = new JTable(mDisplayedModel); - - add(new JScrollPane(mMessageTable), "span,grow"); + add(new JScrollPane(mTable), "span,grow"); } @Override - public void channelChanged(ChannelEvent event) + public void receive(ProcessingChain processingChain) { - boolean changed = false; - - if(event.getEvent() == Event.NOTIFICATION_SELECTION_CHANGE && - event.getChannel().isSelected()) + EventQueue.invokeLater(new Runnable() { - if(mDisplayedChannel == null || (mDisplayedChannel != null && mDisplayedChannel != event.getChannel())) + @Override + public void run() { - mDisplayedChannel = event.getChannel(); + mTable.setModel(processingChain != null ? processingChain.getMessageActivityModel() : EMPTY_MODEL); - ProcessingChain chain = mChannelProcessingManager.getProcessingChain(mDisplayedChannel); - - if(chain != null) - { - mDisplayedModel = chain.getMessageActivityModel(); - } - else - { - mDisplayedModel = EMPTY_MODEL; - } - - mMessageTable.setModel(mDisplayedModel); - - if(mDisplayedChannel != null) + if(processingChain != null) { mManagementPanel.enableButtons(); } @@ -105,31 +86,68 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener { 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(); - } + }); } + // @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 { private static final long serialVersionUID = 1L; @@ -184,8 +202,7 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener @Override public void mouseClicked(MouseEvent arg0) { - if(SwingUtilities.isLeftMouseButton(arg0) && - arg0.getClickCount() == 2) + if(SwingUtilities.isLeftMouseButton(arg0) && arg0.getClickCount() == 2) { slider.setValue(500); //default } @@ -208,24 +225,13 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener } }); - if(mDisplayedModel != null) - { - slider.setValue(mDisplayedModel.getMaxMessageCount()); - } - else - { - slider.setValue(500); - } - + slider.setValue(((MessageActivityModel)mTable.getModel()).getMaxMessageCount()); slider.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent arg0) { - if(mDisplayedModel != null) - { - mDisplayedModel.setMaxMessageCount(slider.getValue()); - } + ((MessageActivityModel)mTable.getModel()).setMaxMessageCount(slider.getValue()); } }); @@ -239,10 +245,7 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener @Override public void actionPerformed(ActionEvent e) { - if(mDisplayedModel != null) - { - mDisplayedModel.clear(); - } + ((MessageActivityModel)mTable.getModel()).clear(); } }); } @@ -261,61 +264,46 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener @Override public void actionPerformed(ActionEvent arg0) { - if(mDisplayedChannel == null) + final JFrame editor = new JFrame(); + + editor.setTitle("Message Filter Editor"); + editor.setSize(600, 400); + editor.setLocationRelativeTo(MessageFilterButton.this); + editor.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + editor.setLayout(new MigLayout("", "[grow,fill]", + "[grow,fill][][]")); + + @SuppressWarnings("unchecked") + FilterSet filter = (FilterSet) ((MessageActivityModel)mTable.getModel()).getMessageFilter(); + + FilterEditorPanel panel = new FilterEditorPanel(filter); + + JScrollPane scroller = new JScrollPane(panel); + scroller.setViewportView(panel); + + editor.add(scroller, "wrap"); + + editor.add(new JLabel("Right-click to select/deselect all nodes"), "wrap"); + + JButton close = new JButton("Close"); + close.addActionListener(new ActionListener() { - JOptionPane.showMessageDialog(MessageFilterButton.this, - "Please enable and select a decoding channel to " - + "adjust the channel's message display filter"); - } - else - { - if(mDisplayedModel != null) + @Override + public void actionPerformed(ActionEvent e) { - final JFrame editor = new JFrame(); - - editor.setTitle("Message Filter Editor"); - editor.setSize(600, 400); - editor.setLocationRelativeTo(MessageFilterButton.this); - editor.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - editor.setLayout(new MigLayout("", "[grow,fill]", - "[grow,fill][][]")); - - @SuppressWarnings("unchecked") - FilterSet filter = (FilterSet) - mDisplayedModel.getMessageFilter(); - - FilterEditorPanel panel = - new FilterEditorPanel(filter); - - JScrollPane scroller = new JScrollPane(panel); - scroller.setViewportView(panel); - - editor.add(scroller, "wrap"); - - editor.add(new JLabel("Right-click to select/deselect " - + "all nodes"), "wrap"); - - JButton close = new JButton("Close"); - close.addActionListener(new ActionListener() - { - @Override - public void actionPerformed(ActionEvent e) - { - editor.dispose(); - } - }); - - editor.add(close); - - EventQueue.invokeLater(new Runnable() - { - public void run() - { - editor.setVisible(true); - } - }); + editor.dispose(); } - } + }); + + editor.add(close); + + EventQueue.invokeLater(new Runnable() + { + public void run() + { + editor.setVisible(true); + } + }); } }); } diff --git a/src/module/decode/fleetsync2/Fleetsync2DecoderState.java b/src/module/decode/fleetsync2/Fleetsync2DecoderState.java index 658fbc6b..e3aa69ec 100644 --- a/src/module/decode/fleetsync2/Fleetsync2DecoderState.java +++ b/src/module/decode/fleetsync2/Fleetsync2DecoderState.java @@ -20,6 +20,8 @@ package module.decode.fleetsync2; import alias.Alias; import alias.AliasList; +import alias.id.AliasIDType; +import channel.metadata.AliasedStringAttributeMonitor; import channel.metadata.Attribute; import channel.metadata.AttributeChangeRequest; import channel.state.DecoderState; @@ -39,20 +41,20 @@ public class Fleetsync2DecoderState extends DecoderState private TreeSet mIdents = new TreeSet(); private TreeSet mEmergencyIdents = new TreeSet(); - private String mFrom; - private Alias mFromAlias; - - private String mTo; - private Alias mToAlias; - + private AliasedStringAttributeMonitor mFromAttribute; + private AliasedStringAttributeMonitor mToAttribute; private String mMessage; private String mMessageType; - private long mFrequency; public Fleetsync2DecoderState(AliasList aliasList) { super(aliasList); + + mFromAttribute = new AliasedStringAttributeMonitor(Attribute.SECONDARY_ADDRESS_FROM, + getAttributeChangeRequestListener(), getAliasList(), AliasIDType.FLEETSYNC); + mToAttribute = new AliasedStringAttributeMonitor(Attribute.SECONDARY_ADDRESS_TO, + getAttributeChangeRequestListener(), getAliasList(), AliasIDType.FLEETSYNC); } @Override @@ -99,10 +101,8 @@ public class Fleetsync2DecoderState extends DecoderState */ public void resetState() { - mFrom = null; - mFromAlias = null; - mTo = null; - mToAlias = null; + mFromAttribute.reset(); + mToAttribute.reset(); mMessage = null; mMessageType = null; } @@ -118,14 +118,14 @@ public class Fleetsync2DecoderState extends DecoderState { State state = State.CALL; - setFromID(fleetsync.getFromID()); + mFromAttribute.process(fleetsync.getFromID()); mIdents.add(fleetsync.getFromID()); FleetsyncMessageType type = fleetsync.getMessageType(); if(type != FleetsyncMessageType.ANI) { - setToID(fleetsync.getToID()); + mToAttribute.process(fleetsync.getToID()); mIdents.add(fleetsync.getToID()); } @@ -175,46 +175,6 @@ public class Fleetsync2DecoderState extends DecoderState } } - public String getFromID() - { - return mFrom; - } - - public Alias getFromIDAlias() - { - return mFromAlias; - } - - public void setFromID(String from) - { - if(!StringUtils.isEqual(mFrom, from)) - { - mFrom = from; - mFromAlias = hasAliasList() ? getAliasList().getFleetsyncAlias(mFrom) : null; - broadcast(new AttributeChangeRequest(Attribute.SECONDARY_ADDRESS_FROM, mFrom, mFromAlias)); - } - } - - public String getToID() - { - return mTo; - } - - public Alias getToIDAlias() - { - return mToAlias; - } - - public void setToID(String to) - { - if(!StringUtils.isEqual(mTo, to)) - { - mTo = to; - mToAlias = hasAliasList() ? getAliasList().getFleetsyncAlias(mTo) : null; - broadcast(new AttributeChangeRequest(Attribute.SECONDARY_ADDRESS_TO, mTo, mToAlias)); - } - } - public String getMessage() { return mMessage; diff --git a/src/module/decode/lj1200/LJ1200DecoderState.java b/src/module/decode/lj1200/LJ1200DecoderState.java index 413a5b2a..e54e6729 100644 --- a/src/module/decode/lj1200/LJ1200DecoderState.java +++ b/src/module/decode/lj1200/LJ1200DecoderState.java @@ -20,6 +20,8 @@ package module.decode.lj1200; import alias.Alias; import alias.AliasList; +import alias.id.AliasIDType; +import channel.metadata.AliasedStringAttributeMonitor; import channel.metadata.Attribute; import channel.metadata.AttributeChangeRequest; import channel.state.DecoderState; @@ -45,12 +47,14 @@ public class LJ1200DecoderState extends DecoderState private Set mAddresses = new TreeSet(); - private String mAddress; - private Alias mAddressAlias; + private AliasedStringAttributeMonitor mAddressAttribute; public LJ1200DecoderState(AliasList aliasList) { super(aliasList); + + mAddressAttribute = new AliasedStringAttributeMonitor(Attribute.SECONDARY_ADDRESS_TO, + getAttributeChangeRequestListener(), getAliasList(), AliasIDType.LOJACK); } @Override @@ -69,16 +73,6 @@ public class LJ1200DecoderState extends DecoderState { } - public String getAddress() - { - return mAddress; - } - - public Alias getAddressAlias() - { - return mAddressAlias; - } - @Override public void receive(Message message) { @@ -88,10 +82,10 @@ public class LJ1200DecoderState extends DecoderState if(lj.isValid()) { - setAddress(lj.getAddress()); - setAddressAlias(lj.getTransponderAlias()); + String address = lj.getAddress(); - mAddresses.add(mAddress); + mAddressAttribute.process(address); + mAddresses.add(address); broadcast(LJ1200CallEvent.getLJ1200Event(lj)); @@ -104,21 +98,6 @@ public class LJ1200DecoderState extends DecoderState } } - private void setAddress(String address) - { - if(!StringUtils.isEqual(mAddress, address)) - { - mAddress = address; - broadcast(new AttributeChangeRequest(Attribute.SECONDARY_ADDRESS_TO, mAddress, mAddressAlias)); - } - } - - private void setAddressAlias(Alias alias) - { - mAddressAlias = alias; - broadcast(new AttributeChangeRequest(Attribute.SECONDARY_ADDRESS_TO, mAddress, mAddressAlias)); - } - @Override public String getActivitySummary() { @@ -163,8 +142,7 @@ public class LJ1200DecoderState extends DecoderState private void resetState() { - mAddress = null; - mAddressAlias = null; + mAddressAttribute.reset(); } @Override diff --git a/src/module/decode/ltrnet/LTRNetDecoderState.java b/src/module/decode/ltrnet/LTRNetDecoderState.java index 60e7263f..e643b558 100644 --- a/src/module/decode/ltrnet/LTRNetDecoderState.java +++ b/src/module/decode/ltrnet/LTRNetDecoderState.java @@ -19,6 +19,9 @@ package module.decode.ltrnet; import alias.Alias; import alias.AliasList; +import alias.id.AliasIDType; +import channel.metadata.AliasedIntegerAttributeMonitor; +import channel.metadata.AliasedStringAttributeMonitor; import channel.metadata.Attribute; import channel.metadata.AttributeChangeRequest; import channel.state.DecoderState; @@ -57,10 +60,9 @@ public class LTRNetDecoderState extends DecoderState new HashMap(); private HashMap mActiveCalls = new HashMap(); - private String mToTalkgroup; - private Alias mToTalkgroupAlias; - private String mFromTalkgroup; - private Alias mFromTalkgroupAlias; + private AliasedStringAttributeMonitor mToAttribute; + private AliasedIntegerAttributeMonitor mFromUIDAttribute; + private AliasedStringAttributeMonitor mESNAttribute; private String mMessage; private String mMessageType; private int mChannelNumber; @@ -69,6 +71,16 @@ public class LTRNetDecoderState extends DecoderState public LTRNetDecoderState(AliasList aliasList) { super(aliasList); + + mToAttribute = new AliasedStringAttributeMonitor(Attribute.PRIMARY_ADDRESS_TO, + getAttributeChangeRequestListener(), getAliasList(), AliasIDType.TALKGROUP); + mToAttribute.addIllegalValue("0-00-000"); + + mFromUIDAttribute = new AliasedIntegerAttributeMonitor(Attribute.PRIMARY_ADDRESS_TO, + getAttributeChangeRequestListener(), getAliasList(), AliasIDType.LTR_NET_UID); + + mESNAttribute = new AliasedStringAttributeMonitor(Attribute.SECONDARY_ADDRESS_FROM, + getAttributeChangeRequestListener(), getAliasList(), AliasIDType.ESN); } @Override @@ -204,8 +216,7 @@ public class LTRNetDecoderState extends DecoderState broadcast(mCurrentCallEvent); } - setFromTalkgroup(String.valueOf(uniqueID)); - setFromTalkgroupAlias(ltr.getRadioUniqueIDAlias()); + mFromUIDAttribute.process(uniqueID); break; case ID_SITE: String siteID = ltr.getSiteID(); @@ -243,8 +254,7 @@ public class LTRNetDecoderState extends DecoderState } setMessageType("ESN"); - setFromTalkgroup(ltr.getESN()); - setFromTalkgroupAlias(ltr.getESNAlias()); + mESNAttribute.process(ltr.getESN()); broadcast(new DecoderStateEvent(this, Event.DECODE, State.DATA)); @@ -272,8 +282,7 @@ public class LTRNetDecoderState extends DecoderState mUniqueIDs.add(uniqueid); setMessageType("REGISTER UID"); - setToTalkgroup(String.valueOf(uniqueid)); - setToTalkgroupAlias(ltr.getRadioUniqueIDAlias()); + mFromUIDAttribute.process(uniqueid); if(getCurrentLTRCallEvent() == null) { @@ -609,10 +618,11 @@ public class LTRNetDecoderState extends DecoderState if(isValidTalkgroup(talkgroup)) { + mToAttribute.process(talkgroup); + final LTRCallEvent current = getCurrentLTRCallEvent(); - /* If this is a new call or the talkgroup is different from the current - * call, create a new call event */ + //If this is a new call or the talkgroup is different from the current call, create a new call event if(current == null || isDifferentTalkgroup(talkgroup)) { /* Invalidate the current call */ @@ -622,22 +632,18 @@ public class LTRNetDecoderState extends DecoderState broadcast(current); } - setToTalkgroup(message.getTalkgroupID()); - /* A talkgroup must be seen at least once before it will be added * to the mTalkgroups list that is used in the activity summary, * so that we don't pollute the summary with one-off error talkgroups */ - if(mTalkgroupsFirstHeard.contains(mToTalkgroup)) + if(mTalkgroupsFirstHeard.contains(talkgroup)) { - mTalkgroups.add(mToTalkgroup); + mTalkgroups.add(talkgroup); } else { - mTalkgroupsFirstHeard.add(mToTalkgroup); + mTalkgroupsFirstHeard.add(talkgroup); } - setToTalkgroupAlias(message.getTalkgroupIDAlias()); - CallEvent callEvent = new LTRCallEvent.Builder(DecoderType.LTR_NET, CallEventType.CALL) .aliasList(getAliasList()) .channel(String.valueOf(message.getChannel())) @@ -704,71 +710,13 @@ public class LTRNetDecoderState extends DecoderState mCurrentCallEvent = null; - mToTalkgroup = null; - - mToTalkgroupAlias = null; - + mToAttribute.reset(); + mESNAttribute.reset(); + mFromUIDAttribute.reset(); + mMessage = null; mMessageType = null; } - public String getToTalkgroup() - { - return mToTalkgroup; - } - - public void setToTalkgroup(String toTalkgroup) - { - if(!StringUtils.isEqual(mToTalkgroup, toTalkgroup)) - { - mToTalkgroup = toTalkgroup; - broadcast(new AttributeChangeRequest(Attribute.PRIMARY_ADDRESS_TO, mToTalkgroup, mToTalkgroupAlias)); - } - } - - public Alias getToTalkgroupAlias() - { - return mToTalkgroupAlias; - } - - public void setToTalkgroupAlias(Alias alias) - { - if(mToTalkgroupAlias == null || (alias != null && mToTalkgroupAlias != alias)) - { - mToTalkgroupAlias = alias; - broadcast(new AttributeChangeRequest(Attribute.PRIMARY_ADDRESS_TO, mToTalkgroup, mToTalkgroupAlias)); - } - } - - public String getFromTalkgroup() - { - return mFromTalkgroup; - } - - public void setFromTalkgroup(String fromTalkgroup) - { - if(!StringUtils.isEqual(mFromTalkgroup, fromTalkgroup)) - { - mFromTalkgroup = fromTalkgroup; - broadcast(new AttributeChangeRequest(Attribute.PRIMARY_ADDRESS_FROM, mFromTalkgroup, - mFromTalkgroupAlias)); - } - } - - public Alias getFromTalkgroupAlias() - { - return mFromTalkgroupAlias; - } - - public void setFromTalkgroupAlias(Alias alias) - { - if(mFromTalkgroupAlias == null || (alias != null && alias != mFromTalkgroupAlias)) - { - mFromTalkgroupAlias = alias; - broadcast(new AttributeChangeRequest(Attribute.PRIMARY_ADDRESS_FROM, mFromTalkgroup, - mFromTalkgroupAlias)); - } - } - public String getMessage() { return mMessage; diff --git a/src/module/decode/ltrstandard/LTRStandardDecoderState.java b/src/module/decode/ltrstandard/LTRStandardDecoderState.java index 59bb2ebe..a826ceeb 100644 --- a/src/module/decode/ltrstandard/LTRStandardDecoderState.java +++ b/src/module/decode/ltrstandard/LTRStandardDecoderState.java @@ -20,6 +20,8 @@ package module.decode.ltrstandard; import alias.Alias; import alias.AliasList; +import alias.id.AliasIDType; +import channel.metadata.AliasedStringAttributeMonitor; import channel.metadata.Attribute; import channel.metadata.AttributeChangeRequest; import channel.state.DecoderState; @@ -56,14 +58,16 @@ public class LTRStandardDecoderState extends DecoderState private Set mTalkgroupsFirstHeard = new HashSet<>(); private Set mTalkgroups = new TreeSet<>(); - private String mTalkgroup; - private Alias mTalkgroupAlias; + private AliasedStringAttributeMonitor mTalkgroupAttribute; private long mFrequency; private LCNTracker mLCNTracker = new LCNTracker(); public LTRStandardDecoderState(AliasList aliasList) { super(aliasList); + + mTalkgroupAttribute = new AliasedStringAttributeMonitor(Attribute.PRIMARY_ADDRESS_TO, + getAttributeChangeRequestListener(), getAliasList(), AliasIDType.TALKGROUP); } @Override @@ -134,11 +138,9 @@ public class LTRStandardDecoderState extends DecoderState if(mLCNTracker.isCurrentChannel(channel)) { - setTalkgroup(start.getToID()); - - processTalkgroup(mTalkgroup); - - setTalkgroupAlias(start.getToIDAlias()); + String talkgroup = start.getToID(); + mTalkgroupAttribute.process(talkgroup); + processTalkgroup(talkgroup); } } @@ -156,11 +158,9 @@ public class LTRStandardDecoderState extends DecoderState if(mLCNTracker.isCurrentChannel(repeater)) { - setTalkgroup(end.getToID()); - - processTalkgroup(mTalkgroup); - - setTalkgroupAlias(end.getToIDAlias()); + String talkgroup = end.getToID(); + mTalkgroupAttribute.process(talkgroup); + processTalkgroup(talkgroup); LTRCallEvent event = mActiveCalls.remove(repeater); @@ -231,36 +231,7 @@ public class LTRStandardDecoderState extends DecoderState mActiveCalls.clear(); - mTalkgroup = null; - mTalkgroupAlias = null; - } - - public String getTalkgroup() - { - return mTalkgroup; - } - - private void setTalkgroup(String talkgroup) - { - if(!StringUtils.isEqual(mTalkgroup, talkgroup)) - { - mTalkgroup = talkgroup; - broadcast(new AttributeChangeRequest(Attribute.PRIMARY_ADDRESS_TO, mTalkgroup, mTalkgroupAlias)); - } - } - - public Alias getTalkgroupAlias() - { - return mTalkgroupAlias; - } - - private void setTalkgroupAlias(Alias alias) - { - if(mTalkgroupAlias == null || (alias != null && mTalkgroupAlias != alias)) - { - mTalkgroupAlias = alias; - broadcast(new AttributeChangeRequest(Attribute.PRIMARY_ADDRESS_TO, mTalkgroup, mTalkgroupAlias)); - } + mTalkgroupAttribute.reset(); } public boolean hasChannelNumber() diff --git a/src/module/decode/mdc1200/MDCDecoderState.java b/src/module/decode/mdc1200/MDCDecoderState.java index a2bf9c7c..eecd0de9 100644 --- a/src/module/decode/mdc1200/MDCDecoderState.java +++ b/src/module/decode/mdc1200/MDCDecoderState.java @@ -20,6 +20,8 @@ package module.decode.mdc1200; import alias.Alias; import alias.AliasList; +import alias.id.AliasIDType; +import channel.metadata.AliasedStringAttributeMonitor; import channel.metadata.Attribute; import channel.metadata.AttributeChangeRequest; import channel.state.DecoderState; @@ -39,16 +41,16 @@ public class MDCDecoderState extends DecoderState private TreeSet mIdents = new TreeSet(); private TreeSet mEmergencyIdents = new TreeSet(); - private String mFrom; - private Alias mFromAlias; - private String mTo; - private Alias mToAlias; + private AliasedStringAttributeMonitor mFromAttribute; private String mMessage; private String mMessageType; public MDCDecoderState(AliasList aliasList) { super(aliasList); + + mFromAttribute = new AliasedStringAttributeMonitor(Attribute.SECONDARY_ADDRESS_FROM, + getAttributeChangeRequestListener(), getAliasList(), AliasIDType.MDC1200); } @Override @@ -78,10 +80,7 @@ public class MDCDecoderState extends DecoderState private void resetState() { - mFrom = null; - mFromAlias = null; - mTo = null; - mToAlias = null; + mFromAttribute.reset(); mMessage = null; mMessageType = null; } @@ -100,8 +99,7 @@ public class MDCDecoderState extends DecoderState mEmergencyIdents.add(mdc.getUnitID()); } - setFrom(mdc.getFromID()); - setFromAlias(mdc.getFromIDAlias()); + mFromAttribute.process(mdc.getFromID()); MDCMessageType type = mdc.getMessageType(); @@ -145,62 +143,6 @@ public class MDCDecoderState extends DecoderState } } - public String getFrom() - { - return mFrom; - } - - public void setFrom(String from) - { - if(!StringUtils.isEqual(mFrom, from)) - { - mFrom = from; - broadcast(new AttributeChangeRequest(Attribute.SECONDARY_ADDRESS_FROM, mFrom, mFromAlias)); - } - } - - public Alias getFromAlias() - { - return mFromAlias; - } - - public void setFromAlias(Alias alias) - { - if(mFromAlias == null || (alias != null && mFromAlias != alias)) - { - mFromAlias = alias; - broadcast(new AttributeChangeRequest(Attribute.SECONDARY_ADDRESS_FROM, mFrom, mFromAlias)); - } - } - - public String getTo() - { - return mTo; - } - - public void setTo(String to) - { - if(!StringUtils.isEqual(mTo, to)) - { - mTo = to; - broadcast(new AttributeChangeRequest(Attribute.SECONDARY_ADDRESS_TO, mTo, mToAlias)); - } - } - - public Alias getToAlias() - { - return mToAlias; - } - - public void setToAlias(Alias alias) - { - if(mToAlias == null || (alias != null && mToAlias != alias)) - { - mToAlias = alias; - broadcast(new AttributeChangeRequest(Attribute.SECONDARY_ADDRESS_TO, mTo, mToAlias)); - } - } - public String getMessage() { return mMessage; diff --git a/src/module/decode/mpt1327/MPT1327DecoderState.java b/src/module/decode/mpt1327/MPT1327DecoderState.java index a62fd95d..0d8da4ba 100644 --- a/src/module/decode/mpt1327/MPT1327DecoderState.java +++ b/src/module/decode/mpt1327/MPT1327DecoderState.java @@ -20,6 +20,8 @@ package module.decode.mpt1327; import alias.Alias; import alias.AliasList; +import alias.id.AliasIDType; +import channel.metadata.AliasedStringAttributeMonitor; import channel.metadata.Attribute; import channel.metadata.AttributeChangeRequest; import channel.state.ChangeChannelTimeoutEvent; @@ -56,8 +58,8 @@ public class MPT1327DecoderState extends DecoderState private HashMap> mGroups = new HashMap>(); private String mSite; - private String mFromTalkgroup; - private String mToTalkgroup; + private AliasedStringAttributeMonitor mFromAttribute; + private AliasedStringAttributeMonitor mToAttribute; private int mChannelNumber; private ChannelType mChannelType; @@ -73,6 +75,10 @@ public class MPT1327DecoderState extends DecoderState mChannelMap = channelMap; mChannelType = channelType; mCallTimeout = callTimeout; + mFromAttribute = new AliasedStringAttributeMonitor(Attribute.PRIMARY_ADDRESS_FROM, + getAttributeChangeRequestListener(), getAliasList(), AliasIDType.MPT1327); + mToAttribute = new AliasedStringAttributeMonitor(Attribute.PRIMARY_ADDRESS_TO, + getAttributeChangeRequestListener(), getAliasList(), AliasIDType.MPT1327); } @Override @@ -277,7 +283,7 @@ public class MPT1327DecoderState extends DecoderState broadcast(mCurrentCallEvent); } - setToTalkgroup(mpt.getToID()); + mToAttribute.process(mpt.getToID()); broadcast(new DecoderStateEvent(this, Event.START, State.CALL)); } @@ -298,8 +304,8 @@ public class MPT1327DecoderState extends DecoderState private void resetState() { - mFromTalkgroup = null; - mToTalkgroup = null; + mFromAttribute.reset(); + mToAttribute.reset(); /** * If this is a standard channel, reset the fade timeout to the default @@ -359,67 +365,6 @@ public class MPT1327DecoderState extends DecoderState mChannelMap = channelMap; } - public String getFromTalkgroup() - { - return mFromTalkgroup; - } - - /** - * Set the talkgroup. This is used primarily for traffic channels since - * the talkgroup will already have been identified prior to the traffic - * channel being created. - */ - public void setFromTalkgroup(String fromTalkgroup) - { - if(!StringUtils.isEqual(mFromTalkgroup, fromTalkgroup)) - { - mFromTalkgroup = fromTalkgroup; - broadcast(new AttributeChangeRequest(Attribute.PRIMARY_ADDRESS_FROM, mFromTalkgroup, - getFromTalkgroupAlias())); - } - } - - public Alias getFromTalkgroupAlias() - { - if(hasAliasList()) - { - return getAliasList().getMPT1327Alias(mFromTalkgroup); - } - - return null; - } - - public String getToTalkgroup() - { - return mToTalkgroup; - } - - /** - * Set the talkgroup. This is used primarily for traffic channels since - * the talkgroup will already have been identified prior to the traffic - * channel being created. - */ - public void setToTalkgroup(String toTalkgroup) - { - if(!StringUtils.isEqual(mToTalkgroup, toTalkgroup)) - { - mToTalkgroup = toTalkgroup; - broadcast(new AttributeChangeRequest(Attribute.PRIMARY_ADDRESS_TO, mToTalkgroup, - getToTalkgroupAlias())); - } - } - - public Alias getToTalkgroupAlias() - { - if(hasAliasList()) - { - return getAliasList().getMPT1327Alias(mToTalkgroup); - } - - return null; - } - - public int getChannelNumber() { return mChannelNumber; @@ -588,6 +533,8 @@ public class MPT1327DecoderState extends DecoderState TrafficChannelAllocationEvent allocationEvent = (TrafficChannelAllocationEvent) event; + broadcast(new AttributeChangeRequest(Attribute.CHANNEL_CONFIGURATION_LABEL_1, "TRAFFIC")); + String channel = allocationEvent.getCallEvent().getChannel(); if(channel != null) @@ -606,8 +553,8 @@ public class MPT1327DecoderState extends DecoderState broadcast(new AttributeChangeRequest(Attribute.CHANNEL_FREQUENCY, allocationEvent.getCallEvent().getFrequency())); - setFromTalkgroup(allocationEvent.getCallEvent().getFromID()); - setToTalkgroup(allocationEvent.getCallEvent().getToID()); + mFromAttribute.process(allocationEvent.getCallEvent().getFromID()); + mToAttribute.process(allocationEvent.getCallEvent().getToID()); } } break; diff --git a/src/module/decode/p25/P25DecoderState.java b/src/module/decode/p25/P25DecoderState.java index 0f3165a6..7acb939a 100644 --- a/src/module/decode/p25/P25DecoderState.java +++ b/src/module/decode/p25/P25DecoderState.java @@ -3669,8 +3669,9 @@ public class P25DecoderState extends DecoderState { if(event instanceof TrafficChannelAllocationEvent) { - TrafficChannelAllocationEvent allocationEvent = - (TrafficChannelAllocationEvent) event; + TrafficChannelAllocationEvent allocationEvent = (TrafficChannelAllocationEvent) event; + + broadcast(new AttributeChangeRequest(Attribute.CHANNEL_CONFIGURATION_LABEL_1, "TRAFFIC")); mCurrentCallEvent = (P25CallEvent) allocationEvent.getCallEvent(); diff --git a/src/module/decode/passport/PassportDecoderState.java b/src/module/decode/passport/PassportDecoderState.java index 557dbb9e..ee5370e7 100644 --- a/src/module/decode/passport/PassportDecoderState.java +++ b/src/module/decode/passport/PassportDecoderState.java @@ -20,6 +20,8 @@ package module.decode.passport; import alias.Alias; import alias.AliasList; +import alias.id.AliasIDType; +import channel.metadata.AliasedStringAttributeMonitor; import channel.metadata.Attribute; import channel.metadata.AttributeChangeRequest; import channel.state.DecoderState; @@ -32,7 +34,6 @@ import module.decode.event.CallEvent; import module.decode.event.CallEvent.CallEventType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import util.StringUtils; import java.util.ArrayList; import java.util.Collections; @@ -53,10 +54,8 @@ public class PassportDecoderState extends DecoderState private HashMap mSiteLCNs = new HashMap(); private HashMap mNeighborLCNs = new HashMap(); - private String mTalkgroup; - private Alias mTalkgroupAlias; - private String mMobileID; - private Alias mMobileIDAlias; + private AliasedStringAttributeMonitor mFromMobileIDAttribute; + private AliasedStringAttributeMonitor mToTalkgroupAttribute; private int mChannelNumber; private int mSiteNumber; private PassportBand mSiteBand; @@ -66,6 +65,11 @@ public class PassportDecoderState extends DecoderState public PassportDecoderState(AliasList aliasList) { super(aliasList); + + mFromMobileIDAttribute = new AliasedStringAttributeMonitor(Attribute.PRIMARY_ADDRESS_FROM, + getAttributeChangeRequestListener(), getAliasList(), AliasIDType.MIN); + mToTalkgroupAttribute = new AliasedStringAttributeMonitor(Attribute.PRIMARY_ADDRESS_TO, + getAttributeChangeRequestListener(), getAliasList(), AliasIDType.TALKGROUP); } @Override @@ -146,7 +150,7 @@ public class PassportDecoderState extends DecoderState /* Call on this channel */ if(passport.getLCN() == mChannelNumber) { - setTalkgroup(talkgroup); + mToTalkgroupAttribute.process(talkgroup); PassportCallEvent current = getCurrentCallEvent(); @@ -207,7 +211,7 @@ public class PassportDecoderState extends DecoderState String.valueOf(passport.getTalkgroupID()); logTalkgroup(endTalkgroup); - setTalkgroup(endTalkgroup); + mToTalkgroupAttribute.process(endTalkgroup); broadcast(new DecoderStateEvent(this, Event.END, State.CALL)); @@ -234,11 +238,11 @@ public class PassportDecoderState extends DecoderState { setChannelNumber(passport.getLCN()); } - + /* Data call on this channel */ if(passport.getLCN() == mChannelNumber) { - setTalkgroup(dataTalkgroup); + mToTalkgroupAttribute.process(dataTalkgroup); PassportCallEvent current = getCurrentCallEvent(); @@ -299,7 +303,7 @@ public class PassportDecoderState extends DecoderState String.valueOf(passport.getTalkgroupID()); logTalkgroup(dataEndTalkgroup); - setTalkgroup(dataEndTalkgroup); + mToTalkgroupAttribute.process(dataEndTalkgroup); broadcast(new DecoderStateEvent(this, Event.END, State.DATA)); @@ -321,7 +325,7 @@ public class PassportDecoderState extends DecoderState mMobileIDs.add(min); } - setMobileID(min); + mFromMobileIDAttribute.process(min); final CallEvent current = getCurrentCallEvent(); @@ -519,10 +523,8 @@ public class PassportDecoderState extends DecoderState private void resetState() { - mTalkgroup = null; - mTalkgroupAlias = null; - mMobileID = null; - mMobileIDAlias = null; + mToTalkgroupAttribute.reset(); + mFromMobileIDAttribute.reset(); } public int getChannelNumber() @@ -568,48 +570,6 @@ public class PassportDecoderState extends DecoderState } } - public String getTalkgroup() - { - return mTalkgroup; - } - - public void setTalkgroup(String talkgroup) - { - if(!StringUtils.isEqual(mTalkgroup, talkgroup)) - { - mTalkgroup = talkgroup; - mTalkgroupAlias = hasAliasList() ? getAliasList().getTalkgroupAlias(getTalkgroup()) : null; - broadcast(new AttributeChangeRequest(Attribute.PRIMARY_ADDRESS_TO, getTalkgroup(), - getTalkgroupAlias())); - } - } - - public Alias getTalkgroupAlias() - { - return mTalkgroupAlias; - } - - public String getMobileID() - { - return mMobileID; - } - - public void setMobileID(String id) - { - if(!StringUtils.isEqual(mMobileID, id)) - { - mMobileID = id; - mMobileIDAlias = hasAliasList() ? getAliasList().getMobileIDNumberAlias(getMobileID()) : null; - broadcast(new AttributeChangeRequest(Attribute.PRIMARY_ADDRESS_FROM, getMobileID(), - getMobileIDAlias())); - } - } - - public Alias getMobileIDAlias() - { - return mMobileIDAlias; - } - @Override public void receiveDecoderStateEvent(DecoderStateEvent event) { diff --git a/src/module/decode/tait/Tait1200DecoderState.java b/src/module/decode/tait/Tait1200DecoderState.java index 7367ff20..b18ccb24 100644 --- a/src/module/decode/tait/Tait1200DecoderState.java +++ b/src/module/decode/tait/Tait1200DecoderState.java @@ -20,6 +20,8 @@ package module.decode.tait; import alias.Alias; import alias.AliasList; +import alias.id.AliasIDType; +import channel.metadata.AliasedStringAttributeMonitor; import channel.metadata.Attribute; import channel.metadata.AttributeChangeRequest; import channel.state.DecoderState; @@ -42,18 +44,19 @@ public class Tait1200DecoderState extends DecoderState { private TreeSet mIdents = new TreeSet(); - private String mFrom; - private Alias mFromAlias; - - private String mTo; - private Alias mToAlias; - + private AliasedStringAttributeMonitor mFromAttribute; + private AliasedStringAttributeMonitor mToAttribute; private String mMessage; private String mMessageType; public Tait1200DecoderState(AliasList aliasList) { super(aliasList); + + mFromAttribute = new AliasedStringAttributeMonitor(Attribute.SECONDARY_ADDRESS_FROM, + getAttributeChangeRequestListener(), getAliasList(), AliasIDType.TALKGROUP); + mToAttribute = new AliasedStringAttributeMonitor(Attribute.SECONDARY_ADDRESS_TO, + getAttributeChangeRequestListener(), getAliasList(), AliasIDType.TALKGROUP); } @Override @@ -82,10 +85,8 @@ public class Tait1200DecoderState extends DecoderState private void resetState() { - mFrom = null; - mFromAlias = null; - mTo = null; - mToAlias = null; + mFromAttribute.reset(); + mToAttribute.reset(); mMessage = null; mMessageType = null; } @@ -97,12 +98,10 @@ public class Tait1200DecoderState extends DecoderState { Tait1200GPSMessage gps = (Tait1200GPSMessage) message; - setFromID(gps.getFromID()); - setFromIDAlias(gps.getFromIDAlias()); + mFromAttribute.process(gps.getFromID()); mIdents.add(gps.getFromID()); - setToID(gps.getToID()); - setToIDAlias(gps.getToIDAlias()); + mToAttribute.process(gps.getToID()); mIdents.add(gps.getToID()); GeoPosition position = gps.getGPSLocation(); @@ -123,13 +122,10 @@ public class Tait1200DecoderState extends DecoderState else if(message instanceof Tait1200ANIMessage) { Tait1200ANIMessage ani = (Tait1200ANIMessage) message; - - setFromID(ani.getFromID()); - setFromIDAlias(ani.getFromIDAlias()); + mFromAttribute.process(ani.getFromID()); mIdents.add(ani.getFromID()); - setToID(ani.getToID()); - setToIDAlias(ani.getToIDAlias()); + mToAttribute.process(ani.getToID()); mIdents.add(ani.getToID()); setMessage(null); @@ -202,62 +198,6 @@ public class Tait1200DecoderState extends DecoderState } } - public String getFromID() - { - return mFrom; - } - - public void setFromID(String from) - { - if(!StringUtils.isEqual(mFrom, from)) - { - mFrom = from; - broadcast(new AttributeChangeRequest(Attribute.SECONDARY_ADDRESS_FROM, getFromID(), getFromIDAlias())); - } - } - - public Alias getFromIDAlias() - { - return mFromAlias; - } - - public void setFromIDAlias(Alias alias) - { - if(mFromAlias == null || (alias != null && mFromAlias != alias)) - { - mFromAlias = alias; - broadcast(new AttributeChangeRequest(Attribute.SECONDARY_ADDRESS_FROM, getFromID(), getFromIDAlias())); - } - } - - public String getToID() - { - return mTo; - } - - public void setToID(String to) - { - if(!StringUtils.isEqual(mTo, to)) - { - mTo = to; - broadcast(new AttributeChangeRequest(Attribute.SECONDARY_ADDRESS_TO, getToID(), getToIDAlias())); - } - } - - public Alias getToIDAlias() - { - return mToAlias; - } - - public void setToIDAlias(Alias alias) - { - if(mToAlias == null || (alias != null && mToAlias != alias)) - { - mToAlias = alias; - broadcast(new AttributeChangeRequest(Attribute.SECONDARY_ADDRESS_TO, getToID(), getToIDAlias())); - } - } - public String getMessage() { return mMessage; diff --git a/src/properties/SystemProperties.java b/src/properties/SystemProperties.java index de25de05..e717aa61 100644 --- a/src/properties/SystemProperties.java +++ b/src/properties/SystemProperties.java @@ -1,22 +1,26 @@ /******************************************************************************* * SDR Trunk * Copyright (C) 2014 Dennis Sheirer - * + * * 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 * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * 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 * along with this program. If not, see ******************************************************************************/ package properties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.awt.*; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -30,9 +34,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Properties; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * SystemProperties - provides an isolated instance of properties for the * application @@ -40,301 +41,325 @@ import org.slf4j.LoggerFactory; public class SystemProperties { - private final static Logger mLog = - LoggerFactory.getLogger( SystemProperties.class ); + private final static Logger mLog = + LoggerFactory.getLogger(SystemProperties.class); - private static String sDEFAULT_APP_ROOT = "SDRTrunk"; - private static String sPROPERTIES_FILENAME = "SDRTrunk.properties"; - - private static SystemProperties mInstance; - private static Properties mProperties; - private Path mPropertiesPath; - private String mApplicationName; - - private SystemProperties() - { - mProperties = new Properties(); - } - - /** - * Returns a SINGLETON instance of the application properties set - * @return - */ - public static SystemProperties getInstance() - { - if( mInstance == null ) - { - mInstance = new SystemProperties(); - } - - return mInstance; - } + private static String sDEFAULT_APP_ROOT = "SDRTrunk"; + private static String sPROPERTIES_FILENAME = "SDRTrunk.properties"; - /** - * Saves any currently changed settings to the application properties file - */ - public void save() - { - Path propsPath = - getApplicationRootPath().resolve( sPROPERTIES_FILENAME ); + private static SystemProperties mInstance; + private static Properties mProperties; + private Path mPropertiesPath; + private String mApplicationName; - OutputStream out = null; - - try - { - out = new FileOutputStream( propsPath.toString() ); + private SystemProperties() + { + mProperties = new Properties(); + } - String comments = - "SDRTrunk - SDR Trunking Decoder Application Settings"; - - mProperties.store( out, comments ); - } - catch( Exception e ) - { - mLog.error( "SystemProperties - exception while saving " + - "application properties", e ); - } - finally - { - if( out != null ) - { - try + /** + * Returns a SINGLETON instance of the application properties set + * + * @return + */ + public static SystemProperties getInstance() + { + if(mInstance == null) + { + mInstance = new SystemProperties(); + } + + return mInstance; + } + + /** + * Saves any currently changed settings to the application properties file + */ + public void save() + { + Path propsPath = + getApplicationRootPath().resolve(sPROPERTIES_FILENAME); + + OutputStream out = null; + + try + { + out = new FileOutputStream(propsPath.toString()); + + String comments = + "SDRTrunk - SDR Trunking Decoder Application Settings"; + + mProperties.store(out, comments); + } + catch(Exception e) + { + mLog.error("SystemProperties - exception while saving " + + "application properties", e); + } + finally + { + if(out != null) + { + try { - out.close(); + out.close(); } - catch ( IOException e ) + catch(IOException e) { } - } - } - } + } + } + } - /** - * Application root directory. Normally returns "SDRTRunk" from the user's - * home directory, unless that has been changed to another location on the - * file system by the user. - */ - public Path getApplicationRootPath() - { - Path retVal = null; - - String root = get( "root.directory", sDEFAULT_APP_ROOT ); - - if( root.equalsIgnoreCase( sDEFAULT_APP_ROOT ) ) - { - retVal = Paths.get( - System.getProperty( "user.home" ), sDEFAULT_APP_ROOT ); - } - else - { - retVal = Paths.get( root ); - } - - return retVal; - } - - public Path getApplicationFolder( String folder ) - { - Path retVal = getApplicationRootPath().resolve( folder ); - - if( !Files.exists( retVal ) ) - { - try - { - Files.createDirectory( retVal ); - } - catch ( IOException e ) - { - mLog.error( "SystemProperties - exception while creating " + - "app folder [" + folder + "]", e ); - } - } - - return retVal; - } - - public void logCurrentSettings() - { - if( mPropertiesPath == null ) - { - mLog.info( "SystemProperties - no properties file loaded - using defaults" ); - } - else - { - mLog.info( "SystemProperties - application properties loaded [" + mPropertiesPath.toString() + "]" ); - } - } - - /** - * Loads the properties file into this properties set - * @param file - */ - public void load( Path propertiesPath ) - { - if( propertiesPath != null ) - { - mPropertiesPath = propertiesPath; - - InputStream in = null; - + /** + * Application root directory. Normally returns "SDRTRunk" from the user's + * home directory, unless that has been changed to another location on the + * file system by the user. + */ + public Path getApplicationRootPath() + { + Path retVal = null; + + String root = get("root.directory", sDEFAULT_APP_ROOT); + + if(root.equalsIgnoreCase(sDEFAULT_APP_ROOT)) + { + retVal = Paths.get( + System.getProperty("user.home"), sDEFAULT_APP_ROOT); + } + else + { + retVal = Paths.get(root); + } + + return retVal; + } + + public Path getApplicationFolder(String folder) + { + Path retVal = getApplicationRootPath().resolve(folder); + + if(!Files.exists(retVal)) + { try { - in = new FileInputStream( propertiesPath.toString() ); + Files.createDirectory(retVal); } - catch ( FileNotFoundException e ) + catch(IOException e) { - mLog.error( "SDRTrunk - exception while opening inputstream on " + - "application properties file", e ); + mLog.error("SystemProperties - exception while creating " + + "app folder [" + folder + "]", e); + } + } + + return retVal; + } + + public void logCurrentSettings() + { + if(mPropertiesPath == null) + { + mLog.info("SystemProperties - no properties file loaded - using defaults"); + } + else + { + mLog.info("SystemProperties - application properties loaded [" + mPropertiesPath.toString() + "]"); + } + } + + /** + * Loads the properties file into this properties set + * + * @param file + */ + public void load(Path propertiesPath) + { + if(propertiesPath != null) + { + mPropertiesPath = propertiesPath; + + InputStream in = null; + + try + { + in = new FileInputStream(propertiesPath.toString()); + } + catch(FileNotFoundException e) + { + mLog.error("SDRTrunk - exception while opening inputstream on " + + "application properties file", e); } - if( in != null ) - { - try + if(in != null) + { + try { - mProperties.load( in ); + mProperties.load(in); } - catch ( IOException e ) + catch(IOException e) { - mLog.error( "SDRTrunk - exception while loading properties " + - "inputstream into SystemProperties", e ); + mLog.error("SDRTrunk - exception while loading properties " + + "inputstream into SystemProperties", e); } - finally - { - try + finally + { + try { - in.close(); + in.close(); } - catch ( IOException e ) + catch(IOException e) { } - } - } - } - - mLog.info( "SystemProperties - loaded [" + - propertiesPath.toString() + "]" ); - } + } + } + } - public String getApplicationName() - { - if(mApplicationName == null) - { - StringBuilder sb = new StringBuilder(); + mLog.info("SystemProperties - loaded [" + + propertiesPath.toString() + "]"); + } - sb.append( "sdrtrunk" ); + public String getApplicationName() + { + if(mApplicationName == null) + { + StringBuilder sb = new StringBuilder(); - try(BufferedReader reader = new BufferedReader( - new InputStreamReader( this.getClass() - .getResourceAsStream( "/sdrtrunk-version" ) ) ) ) - { - String version = reader.readLine(); + sb.append("sdrtrunk"); - if( version != null ) - { - sb.append( " V" ); - sb.append( version ); - } - } - catch( Exception e ) - { - mLog.error( "Couldn't read sdrtrunk version from application jar file" ); - } + try(BufferedReader reader = new BufferedReader( + new InputStreamReader(this.getClass() + .getResourceAsStream("/sdrtrunk-version")))) + { + String version = reader.readLine(); - mApplicationName = sb.toString(); - } + if(version != null) + { + sb.append(" V"); + sb.append(version); + } + } + catch(Exception e) + { + mLog.error("Couldn't read sdrtrunk version from application jar file"); + } - return mApplicationName; - } + mApplicationName = sb.toString(); + } - /** - * Returns the value of the property, or null if the property doesn't exist - */ - private String get( String key ) - { - return mProperties.getProperty( key ); - } + return mApplicationName; + } - /** - * Returns the value of the property, or the defaultValue if the - * property doesn't exist - */ - public String get( String key, String defaultValue ) - { - String value = get( key ); - - if( value != null ) - { - return value; - } + /** + * Returns the value of the property, or null if the property doesn't exist + */ + private String get(String key) + { + return mProperties.getProperty(key); + } - set( key, defaultValue ); - - return defaultValue; - } - - /** - * Returns the value of the property, or the defaultValue if the - * property doesn't exist - */ - public boolean get( String key, boolean defaultValue ) - { - String value = get( key ); - - if( value != null ) - { - try - { - boolean stored = Boolean.parseBoolean( value ); - - return stored; - } - catch( Exception e ) - { - //Do nothing, we couldn't parse the stored value - } - } + /** + * Returns the value of the property, or the defaultValue if the + * property doesn't exist + */ + public String get(String key, String defaultValue) + { + String value = get(key); - set( key, String.valueOf( defaultValue ) ); - - return defaultValue; - } - - /** - * Returns the value of the property, or the defaultValue if the - * property doesn't exist - */ - public int get( String key, int defaultValue ) - { - String value = get( key ); - - if( value != null ) - { - try - { - int stored = Integer.parseInt( value ); - - return stored; - } - catch( Exception e ) - { - //Do nothing, we couldn't parse the stored value - } - } + if(value != null) + { + return value; + } - set( key, String.valueOf( defaultValue ) ); - - return defaultValue; - } + set(key, defaultValue); + + return defaultValue; + } + + /** + * Returns the value of the property, or the defaultValue if the + * property doesn't exist + */ + public boolean get(String key, boolean defaultValue) + { + String value = get(key); + + if(value != null) + { + try + { + boolean stored = Boolean.parseBoolean(value); + + return stored; + } + catch(Exception e) + { + //Do nothing, we couldn't parse the stored value + } + } + + set(key, String.valueOf(defaultValue)); + + return defaultValue; + } + + /** + * Returns the value of the property, or the defaultValue if the + * property doesn't exist + */ + public int get(String key, int defaultValue) + { + String value = get(key); + + if(value != null) + { + try + { + int stored = Integer.parseInt(value); + + return stored; + } + catch(Exception e) + { + //Do nothing, we couldn't parse the stored value + } + } + + set(key, String.valueOf(defaultValue)); + + return defaultValue; + } + + /** + * Sets (overrides) the property key with the new value + */ + public void set(String key, String value) + { + mProperties.setProperty(key, value); + + save(); + } + + /** + * Gets the named color property, storing the default value in properties file if it doesn't exist. + * + * @param key identifying the color property + * @param defaultColor to use for creating the property if it doesn't exist + * @return named color + */ + public Color get(String key, Color defaultColor) + { + return new Color(get(key, defaultColor.getRGB()), true); + } + + /** + * Creates a new color instance with the RGB values from color argument and translucency (alpha) argument + * @param color containing RGB values + * @param alpha desired translucency/alpha value + * @return new color with adjusted alpha value + */ + public static Color getTranslucent(Color color, int alpha) + { + return new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha); + } - /** - * Sets (overrides) the property key with the new value - */ - public void set( String key, String value ) - { - mProperties.setProperty( key, value ); - - save(); - } - - } diff --git a/src/settings/SettingsManager.java b/src/settings/SettingsManager.java index 849839c1..3906504b 100644 --- a/src/settings/SettingsManager.java +++ b/src/settings/SettingsManager.java @@ -135,6 +135,7 @@ public class SettingsManager implements Listener return setting; } + /** * Fetches the current setting and applies the parameter(s) to it. Creates * the setting if it does not exist