From 2d9c3c0aa45200a1f21e1d9e4259831a04e32398 Mon Sep 17 00:00:00 2001 From: Denny Date: Fri, 20 Jan 2017 21:12:57 -0500 Subject: [PATCH] #90 [WIP] Adds support for attribute monitors to all of the decoder states. Updates color scheme in 'Now Playing' view for channel states. Wires selection listener for selected channel metadata to the Events and Messages views. Finalizes format for horizontal audio panels, font and coloration. --- src/audio/AudioChannelPanel.java | 103 +-- src/audio/AudioChannelsPanel.java | 3 +- src/audio/broadcast/AudioBroadcaster.java | 11 +- .../AliasedIntegerAttributeMonitor.java | 99 +++ src/channel/metadata/AttributeMonitor.java | 10 +- .../metadata/ChannelMetadataModel.java | 145 +++- .../metadata/ChannelMetadataPanel.java | 293 ++++--- .../metadata/ChannelMetadataViewer.java | 50 +- .../traffic/TrafficChannelManager.java | 718 +++++++++--------- .../channel/ChannelProcessingManager.java | 37 +- .../event/CallEventAliasCellRenderer.java | 40 +- src/module/decode/event/CallEventModel.java | 325 ++++---- src/module/decode/event/CallEventPanel.java | 100 +-- .../decode/event/MessageActivityPanel.java | 232 +++--- .../fleetsync2/Fleetsync2DecoderState.java | 66 +- .../decode/lj1200/LJ1200DecoderState.java | 42 +- .../decode/ltrnet/LTRNetDecoderState.java | 110 +-- .../ltrstandard/LTRStandardDecoderState.java | 55 +- .../decode/mdc1200/MDCDecoderState.java | 74 +- .../decode/mpt1327/MPT1327DecoderState.java | 83 +- src/module/decode/p25/P25DecoderState.java | 5 +- .../decode/passport/PassportDecoderState.java | 74 +- .../decode/tait/Tait1200DecoderState.java | 90 +-- src/properties/SystemProperties.java | 561 +++++++------- src/settings/SettingsManager.java | 1 + 25 files changed, 1511 insertions(+), 1816 deletions(-) create mode 100644 src/channel/metadata/AliasedIntegerAttributeMonitor.java 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