diff --git a/.idea/dictionaries/denny.xml b/.idea/dictionaries/denny.xml
index 3721dbce5..2c06cff85 100644
--- a/.idea/dictionaries/denny.xml
+++ b/.idea/dictionaries/denny.xml
@@ -23,6 +23,7 @@
shoutcaststreamabletalkgroup
+ talkgroupstgidultravoxwacn
diff --git a/.idea/misc.xml b/.idea/misc.xml
index d4b0813c4..6746d6276 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,7 +1,7 @@
-
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 000000000..b386659b9
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 3d4dd9f6c..a6d25f94f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -24,7 +24,7 @@ plugins {
id 'java'
id 'idea'
id 'org.openjfx.javafxplugin' version '0.0.8'
- id 'org.beryx.runtime' version '1.8.0'
+ id 'org.beryx.runtime' version '1.8.1'
}
repositories {
@@ -33,7 +33,7 @@ repositories {
maven { url "https://jitpack.io" }
}
-version = '0.4.0'
+version = '0.5.0-alpha1'
sourceCompatibility = '13'
sourceSets {
@@ -65,7 +65,7 @@ dependencies {
implementation 'com.miglayout:miglayout-swing:5.2'
implementation 'com.mpatric:mp3agic:0.9.1'
implementation 'eu.hansolo:charts:1.0.5'
- implementation 'io.github.dsheirer:radio-reference-api:15.1.2'
+ implementation 'io.github.dsheirer:radio-reference-api:15.1.4'
implementation 'javax.usb:usb-api:1.0.2'
implementation 'net.coderazzi:tablefilter-swing:5.4.0'
implementation 'org.apache.commons:commons-lang3:3.8.1'
@@ -124,7 +124,7 @@ jar {
}
/**
- * Java Development Kit (JDK) locations. In order to build OS-specific images, these paths must point to the 'bin'
+ * Java Development Kit (JDK) locations. In order to build OS-specific images, these paths must point to the 'bin'
* directory within a JDK for each of the specified architectures. These JDKs are used by the runtime and runtimeZip
* tasks to produce platform-specific builds. If none of these paths exists, then an image will be created for the
* host OS using the installed JDK.
@@ -174,7 +174,7 @@ runtime {
}
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
- modules = ['java.desktop', 'java.naming', 'jdk.unsupported', 'jdk.unsupported.desktop', 'java.net.http']
+ modules = ['java.desktop', 'java.naming', 'jdk.unsupported', 'jdk.unsupported.desktop', 'java.net.http', 'java.sql']
imageZip = hasTargetJdk ? file("$buildDir/image/sdr-trunk.zip") : file("$buildDir/image/sdr-trunk-" + version + ".zip")
}
diff --git a/sdr-trunk.ipr b/sdr-trunk.ipr
index 50ef3e983..aeef19113 100644
--- a/sdr-trunk.ipr
+++ b/sdr-trunk.ipr
@@ -34,6 +34,8 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -309,6 +338,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -353,6 +398,13 @@
+
+
+
+
+
+
+
@@ -417,13 +469,13 @@
-
+
-
+
-
+
@@ -481,15 +533,15 @@
-
+
-
+
-
+
-
+
@@ -536,15 +588,15 @@
-
+
-
+
-
+
-
+
@@ -613,6 +665,17 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -668,6 +731,17 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -745,6 +819,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -778,6 +874,17 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/io/github/dsheirer/alias/Alias.java b/src/main/java/io/github/dsheirer/alias/Alias.java
index cd50e0db1..2b75a1e1f 100644
--- a/src/main/java/io/github/dsheirer/alias/Alias.java
+++ b/src/main/java/io/github/dsheirer/alias/Alias.java
@@ -1,21 +1,23 @@
/*
- * ******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2018 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.
+ * * ******************************************************************************
+ * * Copyright (C) 2014-2020 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
+ * * *****************************************************************************
*
- * 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 io.github.dsheirer.alias;
@@ -28,161 +30,465 @@
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
import io.github.dsheirer.alias.id.priority.Priority;
import io.github.dsheirer.alias.id.record.Record;
+import javafx.beans.Observable;
+import javafx.beans.binding.Bindings;
+import javafx.beans.binding.BooleanBinding;
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.IntegerProperty;
+import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.property.SimpleIntegerProperty;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.collections.transformation.FilteredList;
+import javafx.util.Callback;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.awt.Color;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
+/**
+ * Alias provides an aliasing (e.g. name, color, etc) container that is linked to multiple alias identifiers and
+ * provides a corresponding set of actions related to the alias.
+ */
@JacksonXmlRootElement(localName = "alias")
public class Alias
{
- private String mList;
- private String mGroup;
- private String mName;
- private int mColor;
- private String mIconName;
- private List mAliasIDs = new ArrayList();
- private List mAliasActions = new ArrayList();
+ private final static Logger mLog = LoggerFactory.getLogger(Alias.class);
+
+ private BooleanProperty mRecordable = new SimpleBooleanProperty();
+ private BooleanProperty mStreamable = new SimpleBooleanProperty();
+ private BooleanProperty mOverlap = new SimpleBooleanProperty();
+ private IntegerProperty mColor = new SimpleIntegerProperty();
+ private IntegerProperty mPriority = new SimpleIntegerProperty(Priority.DEFAULT_PRIORITY);
+ private IntegerProperty mNonAudioIdentifierCount = new SimpleIntegerProperty();
+ private StringProperty mAliasListName = new SimpleStringProperty();
+ private StringProperty mGroup = new SimpleStringProperty();
+ private StringProperty mIconName = new SimpleStringProperty();
+ private StringProperty mName = new SimpleStringProperty();
+ private ObservableList mAliasIDs = FXCollections.observableArrayList();
+ private ObservableList mAliasActions = FXCollections.observableArrayList();
+ /**
+ * Constructs an instance and sets the specified name.
+ * @param name for the alias
+ */
+ public Alias(String name)
+ {
+ mName.set(name);
+
+ //Bind the non-audio identifier count property to the size of a filtered list of alias identifiers
+ mNonAudioIdentifierCount.bind(Bindings.size(new FilteredList<>(mAliasIDs, aliasID -> {
+ return aliasID != null && !aliasID.isAudioIdentifier();
+ })));
+ }
+
+ /**
+ * Constructs an instance
+ */
public Alias()
{
+ this(null);
}
- public Alias(String name)
+ /**
+ * Count of non-audio identifiers for this alias
+ */
+ @JsonIgnore
+ public IntegerProperty nonAudioIdentifierCountProperty()
+ {
+ return mNonAudioIdentifierCount;
+ }
+
+ /**
+ * Audio playback priority
+ */
+ @JsonIgnore
+ public IntegerProperty priorityProperty()
+ {
+ return mPriority;
+ }
+
+ /**
+ * Indicates if one or more of the identifiers for this alias overlap with identifiers from another alias
+ * within the same alias list.
+ */
+ @JsonIgnore
+ public BooleanProperty overlapProperty()
+ {
+ return mOverlap;
+ }
+
+ /**
+ * Recordable property
+ */
+ @JsonIgnore
+ public BooleanProperty recordableProperty()
+ {
+ return mRecordable;
+ }
+
+ /**
+ * Streamable property
+ */
+ @JsonIgnore
+ public BooleanProperty streamableProperty()
{
- mName = name;
+ return mStreamable;
}
+ /**
+ * Alias list name property
+ */
+ @JsonIgnore
+ public StringProperty aliasListNameProperty()
+ {
+ return mAliasListName;
+ }
+
+ /**
+ * Group property
+ */
+ @JsonIgnore
+ public StringProperty groupProperty()
+ {
+ return mGroup;
+ }
+
+ /**
+ * Alias name property
+ * @return
+ */
+ @JsonIgnore
+ public StringProperty nameProperty()
+ {
+ return mName;
+ }
+
+ /**
+ * Alias color value property
+ */
+ @JsonIgnore
+ public IntegerProperty colorProperty()
+ {
+ return mColor;
+ }
+
+ /**
+ * Icon name property
+ */
+ @JsonIgnore
+ public StringProperty iconNameProperty()
+ {
+ return mIconName;
+ }
+
+ /**
+ * Alias identifiers list property
+ */
+ @JsonIgnore
+ public ObservableList aliasIds()
+ {
+ return mAliasIDs;
+ }
+
+ /**
+ * Alias actions list property
+ */
+ @JsonIgnore
+ public ObservableList aliasActions()
+ {
+ return mAliasActions;
+ }
+
+ /**
+ * Uses name value for string representation
+ */
public String toString()
{
return getName();
}
+ /**
+ * Alias name
+ */
@JacksonXmlProperty(isAttribute = true, localName = "name")
public String getName()
{
- return mName;
+ return mName.get();
}
public void setName(String name)
{
- mName = name;
+ mName.set(name);
}
+ /**
+ * Alias list name for the alias list that this alias belongs to
+ */
@JacksonXmlProperty(isAttribute = true, localName = "list")
- public String getList()
+ public String getAliasListName()
{
- return mList;
+ return mAliasListName.get();
}
- public void setList(String list)
+ public void setAliasListName(String aliasListName)
{
- mList = list;
+ mAliasListName.set(aliasListName);
}
+ @JsonIgnore
+ public boolean matchesAliasList(String aliasList)
+ {
+ boolean isEmptyArgument = aliasList == null || aliasList.isEmpty() || aliasList.contentEquals(AliasModel.NO_ALIAS_LIST);
+ boolean isEmptyThis = getAliasListName() == null || getAliasListName().isEmpty();
+
+ if(isEmptyArgument && isEmptyThis)
+ {
+ return true;
+ }
+ else if(!isEmptyArgument && !isEmptyThis && aliasList.contentEquals(getAliasListName()))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Indicates if this alias has a specified alias list name
+ */
public boolean hasList()
{
- return mList != null;
+ return mAliasListName.get() != null;
}
+ /**
+ * Grouping tag for this alias.
+ */
@JacksonXmlProperty(isAttribute = true, localName = "group")
public String getGroup()
{
- return mGroup;
+ return mGroup.get();
}
public void setGroup(String group)
{
- mGroup = group;
+ mGroup.set(group);
}
+ /**
+ * Indicates if this alias has a grouping tag
+ */
public boolean hasGroup()
{
- return mGroup != null;
+ return mGroup.get() != null;
}
+ /**
+ * Color (RGBA) value to use for this alias
+ */
@JacksonXmlProperty(isAttribute = true, localName = "color")
public int getColor()
{
- return mColor;
+ return mColor.get();
+ }
+
+ @JsonIgnore
+ public String getColorHex()
+ {
+ return String.format("#%06X", (0xFFFFFF & mColor.get()));
}
public void setColor(int color)
{
- mColor = color;
+ mColor.set(color);
}
+ /**
+ * Display color for this alias.
+ */
@JsonIgnore
public Color getDisplayColor()
{
return new Color(getColor());
}
+ /**
+ * Icon name of the icon to use for this alias.
+ */
@JacksonXmlProperty(isAttribute = true, localName = "iconName")
public String getIconName()
{
- return mIconName;
+ return mIconName.get();
}
public void setIconName(String iconName)
{
- mIconName = iconName;
+ mIconName.set(iconName);
}
+ /**
+ * List of alias identifiers for this alias.
+ */
@JacksonXmlProperty(isAttribute = false, localName = "id")
- public List getId()
+ public List getAliasIdentifiers()
{
return mAliasIDs;
}
- public void setId(ArrayList id)
+ public void setAliasIdentifiers(List id)
{
- mAliasIDs = id;
+ mAliasIDs.clear();
+
+ for(AliasID aliasID : id)
+ {
+ addAliasID(aliasID);
+ }
}
+ /**
+ * Adds an alias identifier to this alias and updates the recordable and streamable attributes.
+ */
public void addAliasID(AliasID id)
{
mAliasIDs.add(id);
+ validate();
+ updateOverlapBinding();
}
+ /**
+ * Removes an alias identifier from this alias and updates the recordable and streamable attributes.
+ */
public void removeAliasID(AliasID id)
{
- mAliasIDs.remove(id);
+ if(id != null)
+ {
+ mAliasIDs.remove(id);
+ validate();
+ updateOverlapBinding();
+ }
}
+ /**
+ * List of alias actions associated with this alias.
+ */
@JacksonXmlProperty(isAttribute = false, localName = "action")
- public List getAction()
+ public List getAliasActions()
{
return mAliasActions;
}
- public void setAction(List actions)
+ public void setAliasActions(List actions)
{
- mAliasActions = actions;
+ mAliasActions.setAll(actions);
}
+ /**
+ * Adds the specified alias action to this alias
+ */
public void addAliasAction(AliasAction action)
{
mAliasActions.add(action);
}
+ /**
+ * Removes the specified alias action from this alias
+ */
public void removeAliasAction(AliasAction action)
{
mAliasActions.remove(action);
}
+ /**
+ * Indicates if this alias has any associated
+ * @return
+ */
public boolean hasActions()
{
return !mAliasActions.isEmpty();
}
+
+ /**
+ * Updates the playback priority this alias
+ */
+ private void updatePriority()
+ {
+ for(AliasID aliasID: mAliasIDs)
+ {
+ if(aliasID instanceof Priority)
+ {
+ mPriority.set(((Priority)aliasID).getPriority());
+ return;
+ }
+ }
+
+ mPriority.set(Priority.DEFAULT_PRIORITY);
+ }
+
+ private void updateOverlapBinding()
+ {
+ mOverlap.unbind();
+
+ BooleanBinding binding = new SimpleBooleanProperty(true).not();
+
+ for(AliasID aliasID: mAliasIDs)
+ {
+ binding = binding.or(aliasID.overlapProperty());
+ }
+
+ mOverlap.bind(binding);
+ }
+
+ /**
+ * Updates the recordable status for this alias
+ */
+ private void updateRecordable()
+ {
+ for(AliasID aliasID: mAliasIDs)
+ {
+ if(aliasID instanceof Record)
+ {
+ mRecordable.set(true);
+ return;
+ }
+ }
+
+ mRecordable.set(false);
+ }
+
+ /**
+ * Updates the streamable status for this alias
+ */
+ private void updateStreamable()
+ {
+ for(AliasID aliasID: mAliasIDs)
+ {
+ if(aliasID instanceof BroadcastChannel)
+ {
+ mStreamable.set(true);
+ return;
+ }
+ }
+
+ mStreamable.set(false);
+ }
+
/**
* Perform any validation/cleanup actions on this alias.
*/
public void validate()
{
+ updatePriority();
+ updateRecordable();
+ updateStreamable();
}
/**
@@ -220,22 +526,23 @@ public boolean hasCallPriority()
*/
public void setCallPriority(int priority)
{
- if(priority == Priority.DO_NOT_MONITOR ||
- (Priority.MIN_PRIORITY <= priority && priority <= Priority.MAX_PRIORITY))
+ AliasID priorityID = null;
+
+ for(AliasID aliasID: mAliasIDs)
{
- for(AliasID id : mAliasIDs)
+ if(aliasID instanceof Priority)
{
- if(id.getType() == AliasIDType.PRIORITY)
- {
- ((Priority)id).setPriority(priority);
- return;
- }
+ priorityID = aliasID;
}
+ }
+
+ removeAliasID(priorityID);
- //If we don't find a priority id, create one
- Priority p = new Priority();
- p.setPriority(priority);
- addAliasID(p);
+ //Don't add a priority alias id if the priority is MAX_PRIORITY or DEFAULT_PRIORITY since the getCallPriority()
+ //will return that as the default value
+ if(priority == Priority.DO_NOT_MONITOR || (Priority.MIN_PRIORITY <= priority && priority < Priority.MAX_PRIORITY))
+ {
+ addAliasID(new Priority(priority));
}
}
@@ -245,15 +552,7 @@ public void setCallPriority(int priority)
@JsonIgnore
public boolean isRecordable()
{
- for(AliasID id : getId())
- {
- if(id.getType() == AliasIDType.RECORD)
- {
- return true;
- }
- }
-
- return false;
+ return mRecordable.get();
}
/**
@@ -261,35 +560,21 @@ public boolean isRecordable()
*/
public void setRecordable(boolean recordable)
{
- if(recordable)
+ AliasID recordID = null;
+
+ for(AliasID aliasID: mAliasIDs)
{
- for(AliasID id : getId())
+ if(aliasID instanceof Record)
{
- if(id.getType() == AliasIDType.RECORD)
- {
- return;
- }
+ recordID = aliasID;
}
-
- addAliasID(new Record());
}
- else
- {
- AliasID toRemove = null;
- for(AliasID id : getId())
- {
- if(id.getType() == AliasIDType.RECORD)
- {
- toRemove = id;
- break;
- }
- }
+ removeAliasID(recordID);
- if(toRemove != null)
- {
- removeAliasID(toRemove);
- }
+ if(recordable)
+ {
+ addAliasID(new Record());
}
}
@@ -299,15 +584,7 @@ public void setRecordable(boolean recordable)
@JsonIgnore
public boolean isStreamable()
{
- for(AliasID id : getId())
- {
- if(id.getType() == AliasIDType.BROADCAST_CHANNEL)
- {
- return true;
- }
- }
-
- return false;
+ return mStreamable.get();
}
/**
@@ -318,7 +595,7 @@ public Set getBroadcastChannels()
{
Set broadcastChannels = new TreeSet<>();
- for(AliasID id : getId())
+ for(AliasID id : getAliasIdentifiers())
{
if(id.getType() == AliasIDType.BROADCAST_CHANNEL)
{
@@ -339,7 +616,7 @@ public boolean hasBroadcastChannel(String channel)
return false;
}
- for(AliasID id : getId())
+ for(AliasID id : getAliasIdentifiers())
{
if(id.getType() == AliasIDType.BROADCAST_CHANNEL &&
((BroadcastChannel)id).getChannelName().contentEquals(channel))
@@ -350,4 +627,85 @@ public boolean hasBroadcastChannel(String channel)
return false;
}
+
+ /**
+ * Removes any broadcast channel(s) that match the argument
+ */
+ public void removeBroadcastChannel(String channel)
+ {
+ if(channel == null || channel.isEmpty())
+ {
+ return;
+ }
+
+ List toRemove = new ArrayList<>();
+
+ for(AliasID aliasID: getAliasIdentifiers())
+ {
+ if(aliasID instanceof BroadcastChannel &&
+ ((BroadcastChannel)aliasID).getChannelName().contentEquals(channel))
+ {
+ toRemove.add(aliasID);
+ }
+ }
+
+ for(AliasID aliasID: toRemove)
+ {
+ removeAliasID(aliasID);
+ }
+ }
+
+ /**
+ * Removes (clears) all broadcast channels from this alias
+ */
+ public void removeAllBroadcastChannels()
+ {
+ List toRemove = new ArrayList<>();
+ for(AliasID aliasID: mAliasIDs)
+ {
+ if(aliasID instanceof BroadcastChannel)
+ {
+ toRemove.add(aliasID);
+ }
+ }
+
+ for(AliasID aliasID: toRemove)
+ {
+ removeAliasID(aliasID);
+ }
+ }
+
+ /**
+ * Removes all non audio identifiers to prepare for replacing them from an editor.
+ */
+ public void removeNonAudioIdentifiers()
+ {
+ Iterator it = mAliasIDs.iterator();
+
+ while(it.hasNext())
+ {
+ if(!it.next().isAudioIdentifier())
+ {
+ it.remove();
+ }
+ }
+ }
+
+ /**
+ * Removes all alias actions from this alias
+ */
+ public void removeAllActions()
+ {
+ mAliasActions.clear();
+ }
+
+ /**
+ * Creates an observable property extractor for use with observable lists to detect changes internal to this object.
+ */
+ public static Callback extractor()
+ {
+ return (Alias a) -> new Observable[] {a.recordableProperty(), a.streamableProperty(), a.colorProperty(),
+ a.aliasListNameProperty(), a.groupProperty(), a.iconNameProperty(), a.nameProperty(), a.aliasIds(),
+ a.aliasActions(), a.nonAudioIdentifierCountProperty(), a.overlapProperty()};
+ }
}
diff --git a/src/main/java/io/github/dsheirer/alias/AliasController.java b/src/main/java/io/github/dsheirer/alias/AliasController.java
deleted file mode 100644
index 4b321d913..000000000
--- a/src/main/java/io/github/dsheirer/alias/AliasController.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * ******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2019 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 io.github.dsheirer.alias;
-
-import com.jidesoft.swing.JideSplitPane;
-import io.github.dsheirer.audio.broadcast.BroadcastModel;
-import io.github.dsheirer.gui.editor.Editor;
-import io.github.dsheirer.icon.IconManager;
-import io.github.dsheirer.preference.UserPreferences;
-import io.github.dsheirer.preference.swing.JTableColumnWidthMonitor;
-import net.coderazzi.filters.gui.AutoChoices;
-import net.coderazzi.filters.gui.TableFilterHeader;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.ImageIcon;
-import javax.swing.JButton;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTable;
-import javax.swing.ListSelectionModel;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.table.DefaultTableCellRenderer;
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Dimension;
-import java.awt.Rectangle;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.ArrayList;
-import java.util.List;
-
-public class AliasController extends JPanel implements ActionListener, ListSelectionListener
-{
- private static final long serialVersionUID = 1L;
-
- private static final String TABLE_PREFERENCE_KEY = "alias.controller";
- private AliasModel mAliasModel;
- private JTable mAliasTable;
- private TableFilterHeader mTableFilterHeader;
- private AliasEditor mAliasEditor;
- private MultipleAliasEditor mMultipleAliasEditor;
- private JideSplitPane mSplitPane;
- private UserPreferences mUserPreferences;
-
- private static final String NEW_ALIAS = "New";
- private static final String COPY_ALIAS = "Copy";
- private static final String DELETE_ALIAS = "Delete";
-
- private JButton mNewButton = new JButton(NEW_ALIAS);
- private JButton mCopyButton = new JButton(COPY_ALIAS);
- private JButton mDeleteButton = new JButton(DELETE_ALIAS);
-
- private IconCellRenderer mIconCellRenderer;
- private JTableColumnWidthMonitor mColumnWidthMonitor;
-
- public AliasController(AliasModel aliasModel, BroadcastModel broadcastModel, IconManager iconManager,
- UserPreferences userPreferences)
- {
- mAliasModel = aliasModel;
- mAliasEditor = new AliasEditor(mAliasModel, broadcastModel, iconManager);
- mMultipleAliasEditor = new MultipleAliasEditor(mAliasModel, broadcastModel, iconManager);
- mIconCellRenderer = new IconCellRenderer(iconManager);
- mUserPreferences = userPreferences;
-
- init();
-
- mAliasModel.addListener(mAliasEditor);
- }
-
- private void init()
- {
- setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill]"));
-
- //System Configuration View and Editor
- mAliasTable = new JTable(mAliasModel);
- mAliasTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
- mAliasTable.getSelectionModel().addListSelectionListener(this);
- mAliasTable.setAutoCreateRowSorter(true);
-
- mAliasTable.getColumnModel().getColumn(AliasModel.COLUMN_COLOR).setCellRenderer(new ColorCellRenderer());
-
- mAliasTable.getColumnModel().getColumn(AliasModel.COLUMN_ICON).setCellRenderer(mIconCellRenderer);
-
- mColumnWidthMonitor = new JTableColumnWidthMonitor(mUserPreferences, mAliasTable, TABLE_PREFERENCE_KEY);
-
- mTableFilterHeader = new TableFilterHeader(mAliasTable, AutoChoices.ENABLED);
- mTableFilterHeader.setFilterOnUpdates(true);
-
- JScrollPane tableScroller = new JScrollPane(mAliasTable);
-
- JPanel buttonsPanel = new JPanel();
-
- buttonsPanel.setLayout(new MigLayout("insets 0 0 0 0",
- "[grow,fill][grow,fill][grow,fill]", "[]"));
-
- mNewButton.addActionListener(this);
- mNewButton.setToolTipText("Adds a new alias");
- buttonsPanel.add(mNewButton);
-
- mCopyButton.addActionListener(this);
- mCopyButton.setEnabled(false);
- mCopyButton.setToolTipText("Creates a copy of the currently selected alias and adds it");
- buttonsPanel.add(mCopyButton);
-
- mDeleteButton.addActionListener(this);
- mDeleteButton.setEnabled(false);
- mDeleteButton.setToolTipText("Deletes the currently selected alias");
- buttonsPanel.add(mDeleteButton);
-
- JPanel listAndButtonsPanel = new JPanel();
-
- listAndButtonsPanel.setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]",
- "[grow,fill][]"));
-
- listAndButtonsPanel.add(tableScroller, "wrap");
- listAndButtonsPanel.add(buttonsPanel);
-
- mSplitPane = new JideSplitPane(JideSplitPane.HORIZONTAL_SPLIT);
- mSplitPane.setDividerSize(5);
- mSplitPane.setShowGripper(true);
- mSplitPane.add(listAndButtonsPanel);
- mSplitPane.add(mAliasEditor);
-
- add(mSplitPane);
- }
-
- /**
- * Sets the editor argument as the currently visible alias editor
- */
- private void setEditor(Editor> editor)
- {
- if(mSplitPane.getComponentCount() == 3)
- {
- Component component = mSplitPane.getComponent(2);
-
- if(component instanceof Editor> && component != editor)
- {
- //Get current divider location so that we can reapply it after
- //changing out the editors, so that the interface doesn't move
- int location = mSplitPane.getDividerLocation(0);
-
- ((Editor>) component).setItem(null);
-
- mSplitPane.remove(component);
- editor.setPreferredSize(new Dimension(100, 100));
- mSplitPane.add(editor);
-
- mSplitPane.validate();
- mSplitPane.setDividerLocation(0, location);
- mSplitPane.repaint();
- }
- }
- }
-
- private Alias getAlias(int selectedRow)
- {
- if(selectedRow >= 0)
- {
- int index = mAliasTable.convertRowIndexToModel(selectedRow);
-
- return mAliasModel.getAliasAtIndex(index);
- }
-
- return null;
- }
-
- @Override
- public void valueChanged(ListSelectionEvent event)
- {
- //Limits event firing to only when selection is complete
- if(!event.getValueIsAdjusting())
- {
- int[] selectedRows = mAliasTable.getSelectedRows();
-
- if(selectedRows.length == 0)
- {
- mAliasEditor.setItem(null);
- mCopyButton.setEnabled(false);
- mDeleteButton.setEnabled(false);
- }
- else if(selectedRows.length == 1)
- {
- setEditor(mAliasEditor);
-
- Alias selectedAlias = getAlias(selectedRows[0]);
-
- mAliasEditor.setItem(selectedAlias);
-
- if(selectedAlias != null)
- {
- mCopyButton.setEnabled(true);
- mDeleteButton.setEnabled(true);
- }
- else
- {
- mCopyButton.setEnabled(false);
- mDeleteButton.setEnabled(false);
- }
- }
- else
- {
- setEditor(mMultipleAliasEditor);
-
- mCopyButton.setEnabled(true);
- mDeleteButton.setEnabled(true);
-
- List selectedAliases = new ArrayList();
-
- for(int selectedRow : selectedRows)
- {
- Alias alias = getAlias(selectedRow);
-
- selectedAliases.add(alias);
- }
-
- mMultipleAliasEditor.setItem(selectedAliases);
- }
- }
- }
-
- /**
- * Adds the alias to the alias table/model and scrolls the view it
- */
- private void addAlias(Alias alias)
- {
- //Remove any column headers so that the newly added alias shows correctly.
- mTableFilterHeader.resetFilter();
-
- int index = mAliasModel.addAlias(alias);
-
- if(index >= 0)
- {
- int translatedIndex = mAliasTable.convertRowIndexToView(index);
- mAliasTable.setRowSelectionInterval(translatedIndex, translatedIndex);
- mAliasTable.scrollRectToVisible(
- new Rectangle(mAliasTable.getCellRect(translatedIndex, 0, true)));
- }
- }
-
- private List getSelectedAliases()
- {
- List selected = new ArrayList<>();
-
- int[] rows = mAliasTable.getSelectedRows();
-
- for(int row : rows)
- {
- if(row >= 0)
- {
- Alias alias = mAliasModel.getAliasAtIndex(mAliasTable.convertRowIndexToModel(row));
-
- if(alias != null)
- {
- selected.add(alias);
- }
- }
- }
-
- return selected;
- }
-
- /**
- * Responds to New, Copy and Delete Channel button invocations
- */
- @Override
- public void actionPerformed(ActionEvent event)
- {
- switch(event.getActionCommand())
- {
- case NEW_ALIAS:
- addAlias(new Alias("New Alias"));
- break;
- case COPY_ALIAS:
- for(Alias alias : getSelectedAliases())
- {
- addAlias(AliasFactory.copyOf(alias));
- }
- break;
- case DELETE_ALIAS:
- List toDelete = getSelectedAliases();
-
- if(toDelete != null && !toDelete.isEmpty())
- {
- String title = toDelete.size() == 1 ? "Delete Alias?" : "Delete Aliases?";
- String prompt = toDelete.size() == 1 ? "Do you want to delete this alias?" :
- "Do you want to delete these " + toDelete.size() + " aliases?";
-
- int choice = JOptionPane.showConfirmDialog(AliasController.this,
- prompt, title, JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
-
- if(choice == JOptionPane.YES_OPTION)
- {
- for(Alias alias : toDelete)
- {
- mAliasModel.removeAlias(alias);
- }
- }
- }
- break;
- default:
- break;
- }
- }
-
- /**
- * Colorizes the cell based on the cell's integer value
- */
- public class ColorCellRenderer extends DefaultTableCellRenderer
- {
- private static final long serialVersionUID = 1L;
-
- @Override
- public Component getTableCellRendererComponent(JTable table,
- Object value, boolean isSelected, boolean hasFocus, int row,
- int column)
- {
- JLabel label = (JLabel) super.getTableCellRendererComponent(table,
- value, isSelected, hasFocus, row, column);
-
- label.setBackground(new Color((int) value));
-
- label.setText("");
-
- return label;
- }
- }
-
- /**
- * Displays cell's icon and name
- */
- public class IconCellRenderer extends DefaultTableCellRenderer
- {
- private static final long serialVersionUID = 1L;
-
- private IconManager mIconManager;
-
- public IconCellRenderer(IconManager iconManager)
- {
- mIconManager = iconManager;
- }
-
- @Override
- public Component getTableCellRendererComponent(JTable table,
- Object value, boolean isSelected, boolean hasFocus, int row,
- int column)
- {
- JLabel label = (JLabel) super.getTableCellRendererComponent(table,
- value, isSelected, hasFocus, row, column);
-
- ImageIcon icon = mIconManager.getIcon(label.getText(), 12);
-
- if(icon != null)
- {
- label.setIcon(icon);
- }
-
- return label;
- }
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/AliasEditor.java b/src/main/java/io/github/dsheirer/alias/AliasEditor.java
deleted file mode 100644
index 7becf5b51..000000000
--- a/src/main/java/io/github/dsheirer/alias/AliasEditor.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 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 io.github.dsheirer.alias;
-
-import com.jidesoft.swing.JideTabbedPane;
-import io.github.dsheirer.alias.action.AliasActionEditor;
-import io.github.dsheirer.alias.id.AliasIdentifierEditor;
-import io.github.dsheirer.audio.broadcast.BroadcastModel;
-import io.github.dsheirer.gui.editor.Editor;
-import io.github.dsheirer.icon.IconManager;
-import io.github.dsheirer.sample.Listener;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-public class AliasEditor extends Editor implements ActionListener, Listener
-{
- private static final long serialVersionUID = 1L;
-
- private static final String DEFAULT_NAME = "select an alias";
-
- private AliasModel mAliasModel;
-
- private JLabel mAliasLabel;
- private AliasNameEditor mAliasNameEditor;
- private AliasIdentifierEditor mAliasIdentifierEditor;
- private AliasActionEditor mAliasActionEditor;
-
- public AliasEditor(AliasModel aliasModel, BroadcastModel broadcastModel, IconManager iconManager )
- {
- mAliasModel = aliasModel;
- mAliasNameEditor = new AliasNameEditor( mAliasModel, iconManager );
- mAliasIdentifierEditor = new AliasIdentifierEditor( aliasModel, broadcastModel );
- mAliasActionEditor = new AliasActionEditor( aliasModel );
-
- mAliasModel.addListener( this );
-
- init();
- }
-
-
- @Override
- public void setItem( Alias alias )
- {
- super.setItem( alias );
-
- if( hasItem() )
- {
- mAliasLabel.setText( getItem().getName() );
- }
- else
- {
- mAliasLabel.setText( DEFAULT_NAME );
- }
-
- mAliasNameEditor.setItem( alias );
- mAliasIdentifierEditor.setItem( alias );
- mAliasActionEditor.setItem( alias );
- }
-
- private void init()
- {
- setLayout( new MigLayout( "fill,wrap 2", "[grow,fill][grow,fill]",
- "[][][][][][grow,fill]" ) );
-
- add( new JLabel( "Alias:" ), "align right" );
- mAliasLabel = new JLabel( DEFAULT_NAME );
- add( mAliasLabel, "align left" );
-
- add( new JSeparator( JSeparator.HORIZONTAL ), "span,growx,push" );
-
- JideTabbedPane tabs = new JideTabbedPane();
- tabs.setFont( this.getFont() );
- tabs.setForeground( Color.BLACK );
-
- tabs.addTab( "Alias", mAliasNameEditor );
- tabs.addTab( "Audio / Identifier", mAliasIdentifierEditor );
- tabs.addTab( "Action", mAliasActionEditor );
- add( tabs, "span,grow" );
-
- //Playlist management buttons
- JButton btnSave = new JButton( "Save" );
- btnSave.setToolTipText( "Save alias changes to the playlist" );
- btnSave.addActionListener( AliasEditor.this );
- add( btnSave );
-
- JButton btnReset = new JButton( "Reset" );
- btnReset.setToolTipText( "Reset alias changes since last save" );
- btnReset.addActionListener( AliasEditor.this );
- add( btnReset, "wrap" );
- }
-
- @Override
- public void receive( AliasEvent event )
- {
- //If this is the currently displayed alias, reload it
- if( hasItem() && getItem() == event.getAlias() )
- {
- switch( event.getEvent() )
- {
- case CHANGE:
- //Alias changed - reset the editor with changed alias
- setItem( event.getAlias() );
- break;
- case DELETE:
- setItem( null );
- break;
- default:
- break;
- }
- }
- }
-
- @Override
- public void actionPerformed( ActionEvent e )
- {
- if( hasItem() )
- {
- String command = e.getActionCommand();
-
- if( command.contentEquals( "Save" ) )
- {
- save();
- }
- else if( command.contentEquals( "Reset" ) )
- {
- reset();
- }
- }
- }
-
- @Override
- public void save()
- {
- mAliasNameEditor.save();
- mAliasIdentifierEditor.save();
- mAliasActionEditor.save();
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/AliasFactory.java b/src/main/java/io/github/dsheirer/alias/AliasFactory.java
index 707e207d1..2618e47d1 100644
--- a/src/main/java/io/github/dsheirer/alias/AliasFactory.java
+++ b/src/main/java/io/github/dsheirer/alias/AliasFactory.java
@@ -1,7 +1,7 @@
/*
*
* * ******************************************************************************
- * * Copyright (C) 2014-2019 Dennis Sheirer
+ * * Copyright (C) 2014-2020 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
@@ -24,55 +24,37 @@
import io.github.dsheirer.alias.action.AliasAction;
import io.github.dsheirer.alias.action.AliasActionType;
import io.github.dsheirer.alias.action.beep.BeepAction;
-import io.github.dsheirer.alias.action.beep.BeepActionEditor;
import io.github.dsheirer.alias.action.clip.ClipAction;
-import io.github.dsheirer.alias.action.clip.ClipActionEditor;
import io.github.dsheirer.alias.action.script.ScriptAction;
-import io.github.dsheirer.alias.action.script.ScriptActionEditor;
import io.github.dsheirer.alias.id.AliasID;
import io.github.dsheirer.alias.id.AliasIDType;
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
-import io.github.dsheirer.alias.id.broadcast.BroadcastChannelEditor;
-import io.github.dsheirer.alias.id.esn.ESNEditor;
import io.github.dsheirer.alias.id.esn.Esn;
import io.github.dsheirer.alias.id.legacy.fleetsync.FleetsyncID;
-import io.github.dsheirer.alias.id.legacy.fleetsync.FleetsyncIDEditor;
import io.github.dsheirer.alias.id.legacy.mdc.MDC1200ID;
-import io.github.dsheirer.alias.id.legacy.mdc.MDC1200IDEditor;
-import io.github.dsheirer.alias.id.legacy.mobileID.MINEditor;
import io.github.dsheirer.alias.id.legacy.mobileID.Min;
import io.github.dsheirer.alias.id.legacy.mpt1327.MPT1327ID;
-import io.github.dsheirer.alias.id.legacy.mpt1327.MPT1327IDEditor;
import io.github.dsheirer.alias.id.legacy.nonrecordable.NonRecordable;
-import io.github.dsheirer.alias.id.legacy.nonrecordable.NonRecordableEditor;
import io.github.dsheirer.alias.id.legacy.siteID.SiteID;
-import io.github.dsheirer.alias.id.legacy.siteID.SiteIDEditor;
import io.github.dsheirer.alias.id.legacy.talkgroup.LegacyTalkgroupID;
-import io.github.dsheirer.alias.id.legacy.talkgroup.LegacyTalkgroupIDEditor;
import io.github.dsheirer.alias.id.legacy.uniqueID.UniqueID;
-import io.github.dsheirer.alias.id.legacy.uniqueID.UniqueIDEditor;
import io.github.dsheirer.alias.id.lojack.LoJackFunctionAndID;
-import io.github.dsheirer.alias.id.lojack.LoJackIDEditor;
import io.github.dsheirer.alias.id.priority.Priority;
-import io.github.dsheirer.alias.id.priority.PriorityEditor;
import io.github.dsheirer.alias.id.radio.Radio;
-import io.github.dsheirer.alias.id.radio.RadioEditor;
import io.github.dsheirer.alias.id.radio.RadioRange;
-import io.github.dsheirer.alias.id.radio.RadioRangeEditor;
import io.github.dsheirer.alias.id.record.Record;
-import io.github.dsheirer.alias.id.record.RecordEditor;
-import io.github.dsheirer.alias.id.status.StatusID;
-import io.github.dsheirer.alias.id.status.StatusIDEditor;
+import io.github.dsheirer.alias.id.status.UnitStatusID;
+import io.github.dsheirer.alias.id.status.UserStatusID;
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
-import io.github.dsheirer.alias.id.talkgroup.TalkgroupEditor;
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
-import io.github.dsheirer.alias.id.talkgroup.TalkgroupRangeEditor;
-import io.github.dsheirer.audio.broadcast.BroadcastModel;
-import io.github.dsheirer.gui.editor.Editor;
-import io.github.dsheirer.gui.editor.EmptyEditor;
+import io.github.dsheirer.alias.id.tone.TonesID;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class AliasFactory
{
+ private static final Logger mLog = LoggerFactory.getLogger(AliasFactory.class);
+
public static AliasID copyOf(AliasID id)
{
switch(id.getType())
@@ -87,11 +69,6 @@ public static AliasID copyOf(AliasID id)
Esn copyESN = new Esn();
copyESN.setEsn(originalESN.getEsn());
return copyESN;
- case LTR_NET_UID:
- UniqueID originalUniqueID = (UniqueID)id;
- UniqueID copyUniqueID = new UniqueID();
- copyUniqueID.setUid(originalUniqueID.getUid());
- return copyUniqueID;
case LOJACK:
LoJackFunctionAndID originalLoJackFunctionAndID = (LoJackFunctionAndID)id;
LoJackFunctionAndID copyLoJackFunctionAndID = new LoJackFunctionAndID();
@@ -111,11 +88,13 @@ public static AliasID copyOf(AliasID id)
case RADIO_ID:
Radio originalRadio = (Radio)id;
Radio copyRadio = new Radio(originalRadio.getProtocol(), originalRadio.getValue());
+ copyRadio.setOverlap(originalRadio.overlapProperty().get());
return copyRadio;
case RADIO_ID_RANGE:
RadioRange originalRadioRange = (RadioRange)id;
RadioRange copyRadioRange = new RadioRange(originalRadioRange.getProtocol(), originalRadioRange.getMinRadio(),
originalRadioRange.getMaxRadio());
+ copyRadioRange.setOverlap(originalRadioRange.overlapProperty().get());
return copyRadioRange;
case RECORD:
return new Record();
@@ -125,27 +104,45 @@ public static AliasID copyOf(AliasID id)
copySiteID.setSite(originalSiteID.getSite());
return copySiteID;
case STATUS:
- StatusID originalStatusID = (StatusID)id;
- StatusID copyStatusID = new StatusID();
- copyStatusID.setStatus(originalStatusID.getStatus());
- return copyStatusID;
+ UserStatusID originalUserStatusID = (UserStatusID)id;
+ UserStatusID copyUserStatusID = new UserStatusID();
+ copyUserStatusID.setStatus(originalUserStatusID.getStatus());
+ copyUserStatusID.setOverlap(originalUserStatusID.overlapProperty().get());
+ return copyUserStatusID;
case TALKGROUP:
Talkgroup originalTalkgroup = (Talkgroup)id;
Talkgroup copyTalkgroup = new Talkgroup(originalTalkgroup.getProtocol(), originalTalkgroup.getValue());
+ copyTalkgroup.setOverlap(originalTalkgroup.overlapProperty().get());
return copyTalkgroup;
case TALKGROUP_RANGE:
TalkgroupRange originalRange = (TalkgroupRange)id;
TalkgroupRange copyRange = new TalkgroupRange(originalRange.getProtocol(), originalRange.getMinTalkgroup(),
originalRange.getMaxTalkgroup());
+ copyRange.setOverlap(originalRange.overlapProperty().get());
return copyRange;
+ case TONES:
+ TonesID originalTones = (TonesID)id;
+ TonesID copyTones = new TonesID();
+ copyTones.setToneSequence(originalTones.getToneSequence().copyOf());
+ return copyTones;
+ case UNIT_STATUS:
+ UnitStatusID originalUnitStatus = (UnitStatusID)id;
+ UnitStatusID copyUnitStatusID = new UnitStatusID();
+ copyUnitStatusID.setStatus(originalUnitStatus.getStatus());
+ copyUnitStatusID.setOverlap(originalUnitStatus.overlapProperty().get());
+ return copyUnitStatusID;
//Legacy identifiers ... not supported
case FLEETSYNC:
case LEGACY_TALKGROUP:
+ case LTR_NET_UID:
case MDC1200:
case MPT1327:
case NON_RECORDABLE:
+ return null;
default:
+ mLog.warn("Unrecognized Alias ID Type [" + id.getType() + "] cannot make copy of instance");
+ break;
}
return null;
@@ -155,7 +152,11 @@ public static AliasAction copyOf(AliasAction action)
{
if(action instanceof BeepAction)
{
- return new BeepAction();
+ BeepAction original = (BeepAction)action;
+ BeepAction copyBeep = new BeepAction();
+ copyBeep.setInterval(original.getInterval());
+ copyBeep.setPeriod(original.getPeriod());
+ return copyBeep;
}
else if(action instanceof ClipAction)
{
@@ -182,12 +183,12 @@ else if(action instanceof ScriptAction)
public static Alias copyOf(Alias original)
{
Alias copy = new Alias(original.getName());
- copy.setList(original.getList());
+ copy.setAliasListName(original.getAliasListName());
copy.setGroup(original.getGroup());
copy.setColor(original.getColor());
copy.setIconName(original.getIconName());
- for(AliasID id : original.getId())
+ for(AliasID id : original.getAliasIdentifiers())
{
AliasID copyID = copyOf(id);
@@ -197,7 +198,7 @@ public static Alias copyOf(Alias original)
}
}
- for(AliasAction action : original.getAction())
+ for(AliasAction action : original.getAliasActions())
{
AliasAction copyAction = copyOf(action);
@@ -210,77 +211,6 @@ public static Alias copyOf(Alias original)
return copy;
}
- public static Editor getEditor(AliasID aliasID, BroadcastModel broadcastModel)
- {
- if(aliasID != null)
- {
- switch(aliasID.getType())
- {
- case BROADCAST_CHANNEL:
- return new BroadcastChannelEditor(aliasID, broadcastModel);
- case ESN:
- return new ESNEditor(aliasID);
- case LTR_NET_UID:
- return new UniqueIDEditor(aliasID);
- case LOJACK:
- return new LoJackIDEditor(aliasID);
- case MIN:
- return new MINEditor(aliasID);
- case PRIORITY:
- return new PriorityEditor(aliasID);
- case RADIO_ID:
- return new RadioEditor(aliasID);
- case RADIO_ID_RANGE:
- return new RadioRangeEditor(aliasID);
- case RECORD:
- return new RecordEditor(aliasID);
- case SITE:
- return new SiteIDEditor(aliasID);
- case STATUS:
- return new StatusIDEditor(aliasID);
- case TALKGROUP:
- return new TalkgroupEditor(aliasID);
- case TALKGROUP_RANGE:
- return new TalkgroupRangeEditor(aliasID);
-
- case FLEETSYNC:
- return new FleetsyncIDEditor(aliasID);
- case LEGACY_TALKGROUP:
- return new LegacyTalkgroupIDEditor(aliasID);
- case MDC1200:
- return new MDC1200IDEditor(aliasID);
- case MPT1327:
- return new MPT1327IDEditor(aliasID);
- case NON_RECORDABLE:
- return new NonRecordableEditor(aliasID);
- default:
- break;
- }
- }
-
- return new EmptyEditor();
- }
-
- public static Editor getEditor(AliasAction aliasAction)
- {
- if(aliasAction != null)
- {
- switch(aliasAction.getType())
- {
- case BEEP:
- return new BeepActionEditor(aliasAction);
- case CLIP:
- return new ClipActionEditor(aliasAction);
- case SCRIPT:
- return new ScriptActionEditor(aliasAction);
- default:
- break;
- }
- }
-
- return new EmptyEditor();
- }
-
public static AliasID getAliasID(AliasIDType type)
{
switch(type)
@@ -318,7 +248,7 @@ public static AliasID getAliasID(AliasIDType type)
case SITE:
return new SiteID();
case STATUS:
- return new StatusID();
+ return new UserStatusID();
case LEGACY_TALKGROUP:
return new LegacyTalkgroupID();
default:
diff --git a/src/main/java/io/github/dsheirer/alias/AliasList.java b/src/main/java/io/github/dsheirer/alias/AliasList.java
index 36e4b5d63..6c2293ea0 100644
--- a/src/main/java/io/github/dsheirer/alias/AliasList.java
+++ b/src/main/java/io/github/dsheirer/alias/AliasList.java
@@ -1,7 +1,7 @@
/*
*
* * ******************************************************************************
- * * Copyright (C) 2014-2019 Dennis Sheirer
+ * * Copyright (C) 2014-2020 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
@@ -28,9 +28,11 @@
import io.github.dsheirer.alias.id.priority.Priority;
import io.github.dsheirer.alias.id.radio.Radio;
import io.github.dsheirer.alias.id.radio.RadioRange;
-import io.github.dsheirer.alias.id.status.StatusID;
+import io.github.dsheirer.alias.id.status.UnitStatusID;
+import io.github.dsheirer.alias.id.status.UserStatusID;
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
+import io.github.dsheirer.alias.id.tone.TonesID;
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.identifier.IdentifierCollection;
import io.github.dsheirer.identifier.esn.ESNIdentifier;
@@ -40,8 +42,12 @@
import io.github.dsheirer.identifier.status.UnitStatusIdentifier;
import io.github.dsheirer.identifier.status.UserStatusIdentifier;
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
+import io.github.dsheirer.identifier.tone.ToneIdentifier;
+import io.github.dsheirer.identifier.tone.ToneSequence;
import io.github.dsheirer.protocol.Protocol;
import io.github.dsheirer.sample.Listener;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -57,9 +63,12 @@ public class AliasList implements Listener
private Map mTalkgroupProtocolMap = new EnumMap<>(Protocol.class);
private Map mRadioProtocolMap = new EnumMap<>(Protocol.class);
private Map mESNMap = new HashMap<>();
- private Map mStatusMap = new HashMap<>();
+ private Map mUnitStatusMap = new HashMap<>();
+ private Map mUserStatusMap = new HashMap<>();
+ private Map mToneSequenceMap = new HashMap<>();
private boolean mHasAliasActions = false;
private String mName;
+ private ObservableList mAliases = FXCollections.observableArrayList(Alias.extractor());
/**
* List of aliases where all aliases share the same list name. Contains
@@ -72,6 +81,14 @@ public AliasList(String name)
mName = name;
}
+ /**
+ * Observable list of aliases contained in this alias list
+ */
+ public ObservableList aliases()
+ {
+ return mAliases;
+ }
+
/**
* Adds the alias to this list
*/
@@ -79,7 +96,7 @@ public void addAlias(Alias alias)
{
if(alias != null)
{
- for(AliasID aliasID : alias.getId())
+ for(AliasID aliasID : alias.getAliasIdentifiers())
{
addAliasID(aliasID, alias);
}
@@ -89,6 +106,8 @@ public void addAlias(Alias alias)
{
mHasAliasActions = true;
}
+
+ mAliases.add(alias);
}
/**
@@ -163,7 +182,67 @@ private void addAliasID(AliasID id, Alias alias)
}
break;
case STATUS:
- mStatusMap.put(((StatusID) id).getStatus(), alias);
+ int userStatus = ((UserStatusID)id).getStatus();
+
+ if(mUserStatusMap.containsKey(userStatus))
+ {
+ id.setOverlap(true);
+
+ Alias existing = mUserStatusMap.get(userStatus);
+
+ for(AliasID aliasID: existing.getAliasIdentifiers())
+ {
+ if(aliasID instanceof UserStatusID && ((UserStatusID)aliasID).getStatus() == userStatus)
+ {
+ aliasID.setOverlap(true);
+ }
+ }
+ }
+ mUserStatusMap.put(userStatus, alias);
+ break;
+ case UNIT_STATUS:
+ int unitStatus = ((UnitStatusID)id).getStatus();
+
+ if(mUnitStatusMap.containsKey(unitStatus))
+ {
+ id.setOverlap(true);
+
+ Alias existing = mUnitStatusMap.get(unitStatus);
+
+ for(AliasID aliasID: existing.getAliasIdentifiers())
+ {
+ if(aliasID instanceof UnitStatusID && ((UnitStatusID)aliasID).getStatus() == unitStatus)
+ {
+ aliasID.setOverlap(true);
+ }
+ }
+ }
+ mUnitStatusMap.put(unitStatus, alias);
+ break;
+ case TONES:
+ ToneSequence toneSequence = ((TonesID)id).getToneSequence();
+
+ if(toneSequence != null)
+ {
+ if(mToneSequenceMap.containsKey(toneSequence))
+ {
+ id.setOverlap(true);
+
+ Alias existing = mToneSequenceMap.get(toneSequence);
+
+ for(AliasID aliasID: existing.getAliasIdentifiers())
+ {
+ if(aliasID instanceof TonesID && ((TonesID)aliasID).equals(id))
+ {
+ aliasID.setOverlap(true);
+ }
+ }
+ }
+ else
+ {
+ mToneSequenceMap.put(toneSequence, alias);
+ }
+ }
break;
}
}
@@ -174,18 +253,112 @@ private void addAliasID(AliasID id, Alias alias)
}
}
+ /**
+ * Removes the alias and alias identifier to the internal type mapping.
+ */
+ private void removeAliasID(AliasID id, Alias alias)
+ {
+ try
+ {
+ switch(id.getType())
+ {
+ case TALKGROUP:
+ Talkgroup talkgroup = (Talkgroup)id;
+
+ TalkgroupAliasList talkgroupAliasList = mTalkgroupProtocolMap.get(talkgroup.getProtocol());
+
+ if(talkgroupAliasList != null)
+ {
+ talkgroupAliasList.remove(talkgroup, alias);
+ }
+ break;
+ case TALKGROUP_RANGE:
+ TalkgroupRange talkgroupRange = (TalkgroupRange)id;
+
+ TalkgroupAliasList talkgroupRangeAliasList = mTalkgroupProtocolMap.get(talkgroupRange.getProtocol());
+
+ if(talkgroupRangeAliasList != null)
+ {
+ talkgroupRangeAliasList.remove(talkgroupRange, alias);
+ }
+ break;
+ case RADIO_ID:
+ Radio radio = (Radio)id;
+
+ RadioAliasList radioAliasList = mRadioProtocolMap.get(radio.getProtocol());
+
+ if(radioAliasList != null)
+ {
+ radioAliasList.remove(radio, alias);
+ }
+ break;
+ case RADIO_ID_RANGE:
+ RadioRange radioRange = (RadioRange)id;
+
+ RadioAliasList radioRangeAliasList = mRadioProtocolMap.get(radioRange.getProtocol());
+
+ if(radioRangeAliasList != null)
+ {
+ radioRangeAliasList.remove(radioRange, alias);
+ }
+ break;
+ case ESN:
+ String esn = ((Esn) id).getEsn();
+
+ if(esn != null && !esn.isEmpty())
+ {
+ String key = esn.toLowerCase();
+
+ if(mESNMap.containsKey(key) && mESNMap.get(key) == alias)
+ {
+ mESNMap.remove(key);
+ }
+ }
+ break;
+ case STATUS:
+ int status = ((UserStatusID)id).getStatus();
+
+ if(mUserStatusMap.containsKey(status) && mUserStatusMap.get(status) == alias)
+ {
+ mUserStatusMap.remove(status);
+ }
+ break;
+ case UNIT_STATUS:
+ int unitStatus = ((UnitStatusID)id).getStatus();
+
+ if(mUnitStatusMap.containsKey(unitStatus) && mUnitStatusMap.get(unitStatus) == alias)
+ {
+ mUnitStatusMap.remove(unitStatus);
+ }
+ break;
+ case TONES:
+ ToneSequence toneSequence = ((TonesID)id).getToneSequence();
+
+ if(toneSequence != null && mToneSequenceMap.containsKey(toneSequence) &&
+ mToneSequenceMap.get(toneSequence) == alias)
+ {
+ mToneSequenceMap.remove(toneSequence);
+ }
+ break;
+ }
+ }
+ catch(Exception e)
+ {
+ mLog.error("Couldn't remove alias ID " + id + " for alias " + alias, e);
+ }
+ }
+
/**
* Removes the alias from this list
*/
public void removeAlias(Alias alias)
{
- for(TalkgroupAliasList talkgroupAliasList: mTalkgroupProtocolMap.values())
+ for(AliasID aliasID: alias.getAliasIdentifiers())
{
- talkgroupAliasList.remove(alias);
+ removeAliasID(aliasID, alias);
}
- remove(alias, mStatusMap);
- remove(alias, mESNMap);
+ mAliases.remove(alias);
}
/**
@@ -241,20 +414,13 @@ public void receive(AliasEvent event)
switch(event.getEvent())
{
case ADD:
- if(alias.getList() != null && getName().equalsIgnoreCase(alias.getList()))
+ if(alias.getAliasListName() != null && getName().equalsIgnoreCase(alias.getAliasListName()))
{
addAlias(alias);
}
break;
- case CHANGE:
- if(alias.getList() != null && getName().equalsIgnoreCase(alias.getList()))
- {
- removeAlias(alias);
- addAlias(alias);
- }
- break;
case DELETE:
- if(alias.getList() != null && getName().equalsIgnoreCase(alias.getList()))
+ if(alias.getAliasListName() != null && getName().equalsIgnoreCase(alias.getAliasListName()))
{
removeAlias(alias);
}
@@ -336,14 +502,31 @@ public List getAliases(Identifier identifier)
if(identifier instanceof UnitStatusIdentifier)
{
int status = ((UnitStatusIdentifier)identifier).getValue();
- return toList(mStatusMap.get(status));
+ return toList(mUserStatusMap.get(status));
}
break;
case USER_STATUS:
if(identifier instanceof UserStatusIdentifier)
{
int status = ((UserStatusIdentifier)identifier).getValue();
- return toList(mStatusMap.get(status));
+ return toList(mUserStatusMap.get(status));
+ }
+ break;
+ case TONE:
+ if(identifier instanceof ToneIdentifier)
+ {
+ ToneSequence toneSequence = ((ToneIdentifier)identifier).getValue();
+
+ if(toneSequence != null && toneSequence.hasTones())
+ {
+ for(Map.Entry entry: mToneSequenceMap.entrySet())
+ {
+ if(entry.getKey().isContainedIn(toneSequence))
+ {
+ return toList(entry.getValue());
+ }
+ }
+ }
}
break;
}
@@ -477,13 +660,32 @@ public List getBroadcastChannels(IdentifierCollection identifi
}
/**
- * Removes the alias (as a value) from the specified map
+ * Identifies all aliases that have alias identifiers that match the alias ID and are in the same alias list.
+ * @param alias for the list to search
+ * @param aliasID to find matches
+ * @return list of one or more aliases that have matching alias identifiers
*/
- public static void remove(Alias alias, Map map)
+ public List getOverlappingAliases(Alias alias, AliasID aliasID)
{
- map.entrySet().removeIf(entry -> alias.equals(((Map.Entry)entry).getValue()));
- }
+ List aliases = new ArrayList<>();
+ for(Alias otherAlias: mAliases)
+ {
+ if(otherAlias != alias)
+ {
+ for(AliasID otherId: otherAlias.getAliasIdentifiers())
+ {
+ if(otherId.matches(aliasID) || otherId.overlaps(aliasID))
+ {
+ aliases.add(otherAlias);
+ continue;
+ }
+ }
+ }
+ }
+
+ return aliases;
+ }
/**
* Listing of talkgroups and ranges for a specific protocol
@@ -520,16 +722,22 @@ public Alias getAlias(TalkgroupIdentifier identifier)
public void add(Talkgroup talkgroup, Alias alias)
{
- //Detect talkgroup collisions
+ //Detect talkgroup collisions and set overlap flag for both
if(mTalkgroupAliasMap.containsKey(talkgroup.getValue()))
{
Alias existing = mTalkgroupAliasMap.get(talkgroup.getValue());
if(!existing.equals(alias))
{
- mLog.warn("Alias [" + alias.getName() + "] talkgroup [" + talkgroup.getValue() +
- "] has the same talkgroup value as alias [" + existing.getName() +
- "] - alias [" + alias.getName() + "] will be used for alias list [" + getName() + "]");
+ talkgroup.setOverlap(true);
+
+ for(AliasID aliasID: existing.getAliasIdentifiers())
+ {
+ if(aliasID instanceof Talkgroup && ((Talkgroup)aliasID).getValue() == talkgroup.getValue())
+ {
+ aliasID.setOverlap(true);
+ }
+ }
}
}
@@ -543,32 +751,29 @@ public void add(TalkgroupRange talkgroupRange, Alias alias)
{
if(talkgroupRange.overlaps(entry.getKey()) && !entry.getValue().equals(alias))
{
- mLog.warn("Alias [" + alias.getName() + "] with talkgroup range [" + talkgroupRange.toString() +
- "] overlaps with alias [" + entry.getValue().getName() +
- "] with talkgroup range [" + entry.getKey().toString() + "] for alias list [" + getName() + "]");
+ talkgroupRange.setOverlap(true);
+ entry.getKey().setOverlap(true);
}
}
mTalkgroupRangeAliasMap.put(talkgroupRange, alias);
}
- public void remove(Talkgroup talkgroup)
- {
- mTalkgroupAliasMap.remove(talkgroup.getValue());
- }
-
- public void remove(TalkgroupRange talkgroupRange)
+ public void remove(Talkgroup talkgroup, Alias alias)
{
- mTalkgroupRangeAliasMap.remove(talkgroupRange);
+ if(mTalkgroupAliasMap.containsKey(talkgroup.getValue()) && mTalkgroupAliasMap.get(talkgroup.getValue()) == alias)
+ {
+ mTalkgroupAliasMap.remove(talkgroup.getValue());
+ }
}
- /**
- * Removes the alias from all internal maps
- */
- public void remove(Alias alias)
+ public void remove(TalkgroupRange talkgroupRange, Alias alias)
{
- AliasList.remove(alias, mTalkgroupAliasMap);
- AliasList.remove(alias, mTalkgroupRangeAliasMap);
+ //Only remove the entry if both the key and the value match
+ if(mTalkgroupRangeAliasMap.containsKey(talkgroupRange) && mTalkgroupRangeAliasMap.get(talkgroupRange) == alias)
+ {
+ mTalkgroupRangeAliasMap.remove(talkgroupRange);
+ }
}
}
@@ -614,9 +819,15 @@ public void add(Radio radio, Alias alias)
if(!existing.equals(alias))
{
- mLog.warn("Alias [" + alias.getName() + "] radio ID [" + radio.getValue() +
- "] has the same value as alias [" + existing.getName() +
- "] - alias [" + alias.getName() + "] will be used for alias list [" + getName() + "]");
+ radio.setOverlap(true);
+
+ for(AliasID aliasID: existing.getAliasIdentifiers())
+ {
+ if(aliasID instanceof Radio && ((Radio)aliasID).getValue() == radio.getValue())
+ {
+ aliasID.setOverlap(true);
+ }
+ }
}
}
@@ -630,32 +841,30 @@ public void add(RadioRange radioRange, Alias alias)
{
if(radioRange.overlaps(entry.getKey()) && !entry.getValue().equals(alias))
{
- mLog.warn("Alias [" + alias.getName() + "] with radio ID range [" + radioRange.toString() +
- "] overlaps with alias [" + entry.getValue().getName() +
- "] with range [" + entry.getKey().toString() + "] for alias list [" + getName() + "]");
+ radioRange.setOverlap(true);
+ entry.getKey().setOverlap(true);
}
}
mRadioRangeAliasMap.put(radioRange, alias);
}
- public void remove(Radio radio)
- {
- mRadioAliasMap.remove(radio.getValue());
- }
-
- public void remove(RadioRange radioRange)
+ public void remove(Radio radio, Alias alias)
{
- mRadioRangeAliasMap.remove(radioRange);
+ //Only remove the entry if both the key and the value match
+ if(mRadioAliasMap.containsKey(radio.getValue()) && mRadioAliasMap.get(radio.getValue()) == alias)
+ {
+ mRadioAliasMap.remove(radio.getValue());
+ }
}
- /**
- * Removes the alias from all internal maps
- */
- public void remove(Alias alias)
+ public void remove(RadioRange radioRange, Alias alias)
{
- AliasList.remove(alias, mRadioAliasMap);
- AliasList.remove(alias, mRadioRangeAliasMap);
+ //Only remove the entry if both the key and the value match
+ if(mRadioRangeAliasMap.containsKey(radioRange) && mRadioRangeAliasMap.get(radioRange) == alias)
+ {
+ mRadioRangeAliasMap.remove(radioRange);
+ }
}
}
}
diff --git a/src/main/java/io/github/dsheirer/alias/AliasModel.java b/src/main/java/io/github/dsheirer/alias/AliasModel.java
index 9b990173d..e14e64570 100644
--- a/src/main/java/io/github/dsheirer/alias/AliasModel.java
+++ b/src/main/java/io/github/dsheirer/alias/AliasModel.java
@@ -1,59 +1,73 @@
/*
- * ******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2018 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.
+ * * ******************************************************************************
+ * * Copyright (C) 2014-2020 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
+ * * *****************************************************************************
*
- * 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 io.github.dsheirer.alias;
+import io.github.dsheirer.alias.id.AliasID;
+import io.github.dsheirer.alias.id.AliasIDType;
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
import io.github.dsheirer.identifier.IdentifierCollection;
import io.github.dsheirer.identifier.configuration.AliasListConfigurationIdentifier;
import io.github.dsheirer.sample.Broadcaster;
import io.github.dsheirer.sample.Listener;
+import javafx.collections.FXCollections;
+import javafx.collections.ListChangeListener;
+import javafx.collections.ObservableList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
-import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.CopyOnWriteArrayList;
/**
* Alias Model contains all aliases and is responsible for creation and management of alias lists. Alias lists are a
* set of aliases that all share a common alias list name and can be attached to a decoding channel for aliasing
* identifiers produced by channel decoder(s).
*/
-public class AliasModel extends AbstractTableModel
+public class AliasModel
{
- private static final long serialVersionUID = 1L;
-
- public static final int COLUMN_LIST = 0;
- public static final int COLUMN_GROUP = 1;
- public static final int COLUMN_NAME = 2;
- public static final int COLUMN_ICON = 3;
- public static final int COLUMN_COLOR = 4;
-
- private List mAliases = new CopyOnWriteArrayList<>();
+ private final static Logger mLog = LoggerFactory.getLogger(AliasModel.class);
+ public static final String NO_ALIAS_LIST = "(No Alias List)";
+ private ObservableList mAliases = FXCollections.observableArrayList(Alias.extractor());
+ private ObservableList mAliasListNames = FXCollections.observableArrayList();
private Broadcaster mAliasEventBroadcaster = new Broadcaster<>();
private Map mAliasListMap = new HashMap<>();
public AliasModel()
{
+ //Register a listener to detect alias changes and broadcast change events to cause playlist save requests
+ mAliases.addListener(new AliasListChangeListener());
+ }
+
+ public ObservableList aliasList()
+ {
+ return mAliases;
+ }
+
+ public ObservableList aliasListNames()
+ {
+ return mAliasListNames;
}
/**
@@ -64,14 +78,17 @@ public List getAliases()
return Collections.unmodifiableList(mAliases);
}
- public Alias getAliasAtIndex(int row)
+ /**
+ * Removes all aliases from the list and broadcasts the alias delete event for each
+ */
+ public void clear()
{
- if(mAliases.size() >= row)
+ List aliasToRemove = new ArrayList<>(mAliases);
+
+ for(Alias alias: aliasToRemove)
{
- return mAliases.get(row);
+ removeAlias(alias);
}
-
- return null;
}
/**
@@ -126,7 +143,7 @@ public AliasList getAliasList(String name)
for(Alias alias : mAliases)
{
- if(alias.hasList() && alias.getList().equalsIgnoreCase(name))
+ if(alias.hasList() && alias.getAliasListName().equalsIgnoreCase(name))
{
aliasList.addAlias(alias);
}
@@ -145,19 +162,7 @@ public AliasList getAliasList(String name)
*/
public List getListNames()
{
- List listNames = new ArrayList<>();
-
- for(Alias alias : mAliases)
- {
- if(alias.hasList() && !listNames.contains(alias.getList()))
- {
- listNames.add(alias.getList());
- }
- }
-
- Collections.sort(listNames);
-
- return listNames;
+ return mAliasListNames;
}
/**
@@ -180,33 +185,6 @@ public List getGroupNames()
return groupNames;
}
- /**
- * Returns a list of alias group names for all aliases that have a matching
- * list name value
- */
- public List getGroupNames(String listName)
- {
- List groupNames = new ArrayList<>();
-
- if(listName != null)
- {
- for(Alias alias : mAliases)
- {
- if(alias.hasList() &&
- alias.hasGroup() &&
- listName.equals(alias.getList()) &&
- !groupNames.contains(alias.getGroup()))
- {
- groupNames.add(alias.getGroup());
- }
- }
- }
-
- Collections.sort(groupNames);
-
- return groupNames;
- }
-
/**
* Bulk loading of aliases
*/
@@ -226,19 +204,33 @@ public int addAlias(Alias alias)
if(alias != null)
{
mAliases.add(alias);
-
+ addAliasList(alias.getAliasListName());
int index = mAliases.size() - 1;
-
- fireTableRowsInserted(index, index);
-
broadcast(new AliasEvent(alias, AliasEvent.Event.ADD));
-
return index;
}
return -1;
}
+ public void addAliasList(String aliasListName)
+ {
+ if(aliasListName != null && !aliasListName.isEmpty())
+ {
+ if(!mAliasListNames.contains(aliasListName))
+ {
+ mAliasListNames.add(aliasListName);
+ FXCollections.sort(mAliasListNames);
+ }
+ }
+ else if(!mAliasListNames.contains(NO_ALIAS_LIST))
+ {
+ //This list allows users to view unassigned aliases so that they can move them to a valid alias list, but
+ // it is not assignable to a channel
+ mAliasListNames.add(NO_ALIAS_LIST);
+ }
+ }
+
/**
* Removes the channel from the model and broadcasts a channel remove event
*/
@@ -246,119 +238,94 @@ public void removeAlias(Alias alias)
{
if(alias != null)
{
- int index = mAliases.indexOf(alias);
-
mAliases.remove(alias);
-
- fireTableRowsDeleted(index, index);
-
broadcast(new AliasEvent(alias, AliasEvent.Event.DELETE));
}
}
/**
- * Renames any broadcast channels that have the previous name.
- *
- * @param previousName to rename
- * @param newName to assign to the broadcast channel
+ * Retrieves all aliases that match the alias list and have at least one alias ID of the specified type
+ * @param aliasListName to search
+ * @param type to find
+ * @return list of aliases
*/
- public void renameBroadcastChannel(String previousName, String newName)
+ public List getAliases(String aliasListName, AliasIDType type)
{
- if(previousName == null || previousName.isEmpty() || newName == null || newName.isEmpty())
- {
- return;
- }
+ List aliases = new ArrayList<>();
for(Alias alias : mAliases)
{
- if(alias.hasBroadcastChannel(previousName))
+ if(alias.hasList() && alias.getAliasListName().equalsIgnoreCase(aliasListName))
{
- for(BroadcastChannel broadcastChannel : alias.getBroadcastChannels())
+ for(AliasID aliasID: alias.getAliasIdentifiers())
{
- if(broadcastChannel.getChannelName().contentEquals(previousName))
+ if(aliasID.getType() == type)
{
- broadcastChannel.setChannelName(newName);
+ aliases.add(alias);
+ break;
}
}
}
}
- }
-
- @Override
- public int getRowCount()
- {
- return mAliases.size();
- }
- @Override
- public int getColumnCount()
- {
- return 5;
+ return aliases;
}
- @Override
- public String getColumnName(int columnIndex)
+ /**
+ * Indicates that one or more of the aliases managed by this model are configured to stream to the specified
+ * broadcast channel argument.
+ * @param broadcastChannel to check
+ * @return true if the broadcast channel is non-null, non-empty and at least one alias is configured to stream to
+ * the specified stream name.
+ */
+ public boolean hasAliasesWithBroadcastChannel(String broadcastChannel)
{
- switch(columnIndex)
+ if(broadcastChannel == null || broadcastChannel.isEmpty())
{
- case COLUMN_LIST:
- return "List";
- case COLUMN_GROUP:
- return "Group";
- case COLUMN_NAME:
- return "Name";
- case COLUMN_ICON:
- return "Icon";
- case COLUMN_COLOR:
- return "Color";
+ return false;
}
- return null;
- }
-
- @Override
- public Class> getColumnClass(int columnIndex)
- {
- if(columnIndex == COLUMN_COLOR)
+ for(Alias alias: mAliases)
{
- return Integer.class;
+ if(alias.hasBroadcastChannel(broadcastChannel))
+ {
+ return true;
+ }
}
- return String.class;
- }
-
- @Override
- public boolean isCellEditable(int rowIndex, int columnIndex)
- {
return false;
}
- @Override
- public Object getValueAt(int rowIndex, int columnIndex)
+ /**
+ * Updates all aliases configured to stream to the previousStreamName with the updatedStreamName
+ * @param previousStreamName to be removed
+ * @param updatedStreamName to be added
+ */
+ public void updateBroadcastChannel(String previousStreamName, String updatedStreamName)
{
- Alias alias = mAliases.get(rowIndex);
-
- switch(columnIndex)
+ if(previousStreamName == null || previousStreamName.isEmpty() || updatedStreamName == null || updatedStreamName.isEmpty())
{
- case COLUMN_LIST:
- return alias.getList();
- case COLUMN_GROUP:
- return alias.getGroup();
- case COLUMN_NAME:
- return alias.getName();
- case COLUMN_ICON:
- return alias.getIconName();
- case COLUMN_COLOR:
- return alias.getColor();
+ return;
}
- return null;
- }
+ for(Alias alias: mAliases)
+ {
+ if(alias.hasBroadcastChannel(previousStreamName))
+ {
+ for(BroadcastChannel broadcastChannel: alias.getBroadcastChannels())
+ {
+ if(broadcastChannel.getChannelName().contentEquals(previousStreamName))
+ {
+ alias.removeAliasID(broadcastChannel);
- @Override
- public void setValueAt(Object aValue, int rowIndex, int columnIndex)
- {
- throw new IllegalArgumentException("Not yet implemented");
+ if(!alias.hasBroadcastChannel(updatedStreamName))
+ {
+ alias.addAliasID(new BroadcastChannel(updatedStreamName));
+ }
+ }
+ }
+ }
+ }
}
public void broadcast(AliasEvent event)
@@ -371,13 +338,6 @@ public void broadcast(AliasEvent event)
alias.validate();
}
- if(event.getEvent() == AliasEvent.Event.CHANGE)
- {
- int index = mAliases.indexOf(event.getAlias());
-
- fireTableRowsUpdated(index, index);
- }
-
mAliasEventBroadcaster.broadcast(event);
}
@@ -390,4 +350,40 @@ public void removeListener(Listener listener)
{
mAliasEventBroadcaster.removeListener(listener);
}
+
+
+ /**
+ * Observable list change listener for both channels and traffic channels lists
+ */
+ public class AliasListChangeListener implements ListChangeListener
+ {
+ @Override
+ public void onChanged(ListChangeListener.Change extends Alias> change)
+ {
+ while(change.next())
+ {
+ if(change.wasAdded())
+ {
+ for(Alias alias: change.getAddedSubList())
+ {
+ mAliasEventBroadcaster.broadcast(new AliasEvent(alias, AliasEvent.Event.ADD));
+ }
+ }
+ else if(change.wasRemoved())
+ {
+ for(Alias alias: change.getRemoved())
+ {
+ mAliasEventBroadcaster.broadcast(new AliasEvent(alias, AliasEvent.Event.DELETE));
+ }
+ }
+ else if(change.wasUpdated())
+ {
+ for(int x = change.getFrom(); x < change.getTo(); x++)
+ {
+ mAliasEventBroadcaster.broadcast(new AliasEvent(change.getList().get(x), AliasEvent.Event.CHANGE));
+ }
+ }
+ }
+ }
+ }
}
diff --git a/src/main/java/io/github/dsheirer/alias/AliasNameEditor.java b/src/main/java/io/github/dsheirer/alias/AliasNameEditor.java
deleted file mode 100644
index c0c2f74d8..000000000
--- a/src/main/java/io/github/dsheirer/alias/AliasNameEditor.java
+++ /dev/null
@@ -1,333 +0,0 @@
-/*******************************************************************************
- * 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 io.github.dsheirer.alias;
-
-import io.github.dsheirer.gui.editor.Editor;
-import io.github.dsheirer.icon.Icon;
-import io.github.dsheirer.icon.IconListCellRenderer;
-import io.github.dsheirer.icon.IconManager;
-import io.github.dsheirer.icon.IconTableModel;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.*;
-import javax.swing.event.DocumentEvent;
-import javax.swing.event.DocumentListener;
-import javax.swing.event.TableModelEvent;
-import javax.swing.event.TableModelListener;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.List;
-
-public class AliasNameEditor extends Editor
-{
- private static final long serialVersionUID = 1L;
-
- private static ComboBoxModel EMPTY_LIST_MODEL = new DefaultComboBoxModel<>();
- private static ComboBoxModel EMPTY_GROUP_MODEL = new DefaultComboBoxModel<>();
-
- private JComboBox mListCombo = new JComboBox<>(EMPTY_LIST_MODEL);
- private JComboBox mGroupCombo = new JComboBox<>(EMPTY_GROUP_MODEL);
- private JComboBox mIconCombo;
- private JTextField mName;
- private JButton mButtonColor;
- private JButton mBtnIconManager;
-
- private AliasModel mAliasModel;
- private IconManager mIconManager;
-
- public AliasNameEditor(AliasModel aliasModel, IconManager iconManager)
- {
- mAliasModel = aliasModel;
- mIconManager = iconManager;
-
- mIconManager.getModel().addTableModelListener(new TableModelListener()
- {
- @Override
- public void tableChanged(TableModelEvent e)
- {
- refreshIcons();
- }
- });
-
- init();
- }
-
- private void init()
- {
- setLayout(new MigLayout("fill,wrap 2", "[right][grow,fill]", "[][][][][][][grow]"));
-
- add(new JLabel("Name:"));
- mName = new JTextField();
- mName.getDocument().addDocumentListener(new DocumentListener()
- {
- @Override
- public void removeUpdate(DocumentEvent e)
- {
- setModified(true);
- }
-
- @Override
- public void insertUpdate(DocumentEvent e)
- {
- setModified(true);
- }
-
- @Override
- public void changedUpdate(DocumentEvent e)
- {
- }
- });
- add(mName, "wrap");
-
- add(new JLabel("List:"));
- mListCombo.setEditable(true);
- mListCombo.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- if(mListCombo.getSelectedItem() != null)
- {
- List groups = mAliasModel
- .getGroupNames((String) mListCombo.getSelectedItem());
-
- if(groups.isEmpty())
- {
- mGroupCombo.setModel(EMPTY_GROUP_MODEL);
- }
- else
- {
- mGroupCombo.setModel(new DefaultComboBoxModel(
- groups.toArray(new String[0])));
- ;
- }
- }
-
- setModified(true);
- }
- });
- add(mListCombo, "wrap");
-
- add(new JLabel("Group:"));
- mGroupCombo.setEditable(true);
- mGroupCombo.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- setModified(true);
- }
- });
- add(mGroupCombo, "wrap");
-
- add(new JLabel("Color:"));
-
- mButtonColor = new JButton("Select ...");
- mButtonColor.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- Color newColor = JColorChooser.showDialog(
- AliasNameEditor.this,
- "Choose color for this alias",
- (hasItem() ? getItem().getDisplayColor() : null));
-
- if(newColor != null)
- {
- mButtonColor.setForeground(newColor);
- mButtonColor.setBackground(newColor);
-
- setModified(true);
- }
- }
- });
- add(mButtonColor, "wrap");
-
- add(new JLabel("Icon:"));
-
- mIconCombo = new JComboBox(mIconManager.getIcons());
-
- IconListCellRenderer renderer = new IconListCellRenderer(mIconManager);
- renderer.setPreferredSize(new Dimension(200, 30));
- mIconCombo.setRenderer(renderer);
- mIconCombo.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- setModified(true);
- }
- });
-
- add(mIconCombo, "wrap");
-
- //Dummy place holder
- add(new JLabel());
-
- mBtnIconManager = new JButton("Icon Manager");
- mBtnIconManager.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent arg0)
- {
- mIconManager.showEditor(AliasNameEditor.this);
- }
- });
-
- add(mBtnIconManager, "span 2,wrap");
-
- setModified(false);
- }
-
- private void refreshIcons()
- {
- if(mIconCombo != null)
- {
- EventQueue.invokeLater(new Runnable()
- {
- @Override
- public void run()
- {
- mIconCombo.setModel(new DefaultComboBoxModel<>(mIconManager.getIcons()));
-
- if(hasItem())
- {
- String iconName = getItem().getIconName();
- Icon aliasIcon = mIconManager.getModel().getIcon(iconName);
-
- if(aliasIcon != null)
- {
- mIconCombo.setSelectedItem(aliasIcon);
- }
- }
- }
- });
- }
- }
-
- @Override
- public void setItem(Alias alias)
- {
- super.setItem(alias);
-
- if(hasItem())
- {
- mName.setText(alias.getName());
-
- mIconCombo.setModel(new DefaultComboBoxModel<>(mIconManager.getIcons()));
-
- List listNames = mAliasModel.getListNames();
-
- if(listNames.isEmpty())
- {
- mListCombo.setModel(EMPTY_LIST_MODEL);
- }
- else
- {
- mListCombo.setModel(new DefaultComboBoxModel(
- listNames.toArray(new String[0])));
- ;
- }
-
- mListCombo.setSelectedItem(alias.getList());
-
- List groupNames = mAliasModel.getGroupNames(alias.getList());
-
- if(groupNames.isEmpty())
- {
- mGroupCombo.setModel(EMPTY_GROUP_MODEL);
- }
- else
- {
- mGroupCombo.setModel(new DefaultComboBoxModel(
- groupNames.toArray(new String[0])));
- ;
- }
-
- mGroupCombo.setSelectedItem(alias.getGroup());
-
- Color color = alias.getDisplayColor();
-
- mButtonColor.setBackground(color);
- mButtonColor.setForeground(color);
-
- String iconName = alias.getIconName();
-
- if(iconName == null)
- {
- iconName = IconTableModel.DEFAULT_ICON;
- }
-
- Icon savedIcon = mIconManager.getModel().getIcon(iconName);
-
- if(savedIcon != null)
- {
- mIconCombo.setSelectedItem(savedIcon);
- }
- }
- else
- {
- mListCombo.setModel(EMPTY_LIST_MODEL);
- mGroupCombo.setModel(EMPTY_GROUP_MODEL);
- mName.setText(null);
-
- mButtonColor.setBackground(getBackground());
- mButtonColor.setForeground(getForeground());
- }
-
- repaint();
-
- setModified(false);
- }
-
- @Override
- public void save()
- {
- if(hasItem() && isModified())
- {
- Alias alias = getItem();
-
- if(mListCombo.getSelectedItem() != null)
- {
- alias.setList((String) mListCombo.getSelectedItem());
- }
-
- if(mGroupCombo.getSelectedItem() != null)
- {
- alias.setGroup((String) mGroupCombo.getSelectedItem());
- }
-
- alias.setName(mName.getText());
-
- alias.setColor(mButtonColor.getBackground().getRGB());
-
- if(mIconCombo.getSelectedItem() != null)
- {
- alias.setIconName(((Icon) mIconCombo.getSelectedItem()).getName());
- }
-
- setModified(false);
-
- //Broadcast an alias change event to save the updates
- mAliasModel.broadcast(new AliasEvent(getItem(), AliasEvent.Event.CHANGE));
- }
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/ComponentEditor.java b/src/main/java/io/github/dsheirer/alias/ComponentEditor.java
deleted file mode 100644
index 7bae5fcff..000000000
--- a/src/main/java/io/github/dsheirer/alias/ComponentEditor.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 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 io.github.dsheirer.alias;
-
-import javax.swing.*;
-import javax.swing.event.DocumentListener;
-
-public abstract class ComponentEditor extends JPanel implements DocumentListener
-{
- private static final long serialVersionUID = 1L;
- private boolean mModified;
- private ComponentModificationListener mListener;
- protected T mComponent;
-
- /**
- * Abstract class for editor with notifications when contents are modified
- * and methods for saving or resetting the component values with the
- * contents of the editor.
- */
- public ComponentEditor( T component )
- {
- mComponent = component;
- }
-
- public ComponentEditor()
- {
- }
-
- public void dispose()
- {
- mComponent = null;
- mListener = null;
- }
-
- public T getComponent()
- {
- return mComponent;
- }
-
- protected void setModified( boolean modified )
- {
- mModified = modified;
-
- if( modified && mListener != null )
- {
- mListener.componentModified();
- }
- }
-
- /**
- * Indicates if the contents of the editor have been modified
- */
- public boolean isModified()
- {
- return mModified;
- }
-
- public void setComponentModificationListener( ComponentModificationListener listener )
- {
- mListener = listener;
- }
-
- /**
- * Sets or resets the editable component
- */
- public abstract void setComponent( T t );
-
- /**
- * Saves changed editor values to the component
- */
- public abstract void save();
-
- /**
- * Reloads the editor contents from the source component and resets the
- * modified flag
- */
- public void reset()
- {
- setComponent( getComponent() );
- }
-
- /**
- * Validate contents of other editors against this component editor before
- * saving. Override this method to allow controller to pass other editors
- * to this editor for content inspection/validation before indicating that
- * this editor passes validation. This allows for validating editor contents
- * that are contingent on settings in other editors.
- *
- * @throws ComponentValidationException if the contents of the editor
- * argument cannot be validated, with the exception containing a detailed
- * description of the issue.
- */
- public void validate( ComponentEditor> editor ) throws ComponentValidationException
- {
- }
-
- /**
- * Listener interface to receive notification that the contents of the
- * editor have been modified from the original component value and either
- * need to be saved or reset
- */
- public interface ComponentModificationListener
- {
- public void componentModified();
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/ComponentValidationException.java b/src/main/java/io/github/dsheirer/alias/ComponentValidationException.java
deleted file mode 100644
index 9bf0445a5..000000000
--- a/src/main/java/io/github/dsheirer/alias/ComponentValidationException.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package io.github.dsheirer.alias;
-
-public class ComponentValidationException extends Exception
-{
- private static final long serialVersionUID = 1L;
-
- /**
- * Component editor contents validation error
- */
- public ComponentValidationException( String message )
- {
- super( message );
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/MultipleAliasEditor.java b/src/main/java/io/github/dsheirer/alias/MultipleAliasEditor.java
deleted file mode 100644
index d2d9c6552..000000000
--- a/src/main/java/io/github/dsheirer/alias/MultipleAliasEditor.java
+++ /dev/null
@@ -1,466 +0,0 @@
-package io.github.dsheirer.alias;
-
-import io.github.dsheirer.alias.id.AliasIDType;
-import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
-import io.github.dsheirer.alias.id.priority.Priority;
-import io.github.dsheirer.audio.broadcast.BroadcastModel;
-import io.github.dsheirer.gui.editor.Editor;
-import io.github.dsheirer.icon.Icon;
-import io.github.dsheirer.icon.IconListCellRenderer;
-import io.github.dsheirer.icon.IconManager;
-import io.github.dsheirer.sample.Listener;
-import net.miginfocom.swing.MigLayout;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.swing.*;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import javax.swing.event.TableModelEvent;
-import javax.swing.event.TableModelListener;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.List;
-
-public class MultipleAliasEditor extends Editor>
- implements Listener
-{
- private static final long serialVersionUID = 1L;
- private final static Logger mLog = LoggerFactory.getLogger(MultipleAliasEditor.class);
-
- private static String HELP_TEXT =
- "Select attributes below to change for all selected aliases";
-
- private JLabel mAliasCountLabel;
- private JLabel mAliasCount;
-
- private JCheckBox mListCheckBox = new JCheckBox("List");
- private JComboBox mListCombo = new JComboBox<>();
- private JCheckBox mGroupCheckBox = new JCheckBox("Group");
- private JComboBox mGroupCombo = new JComboBox<>();
- private JCheckBox mIconCheckBox = new JCheckBox("Icon");
- private JComboBox mIconCombo;
- private JCheckBox mColorCheckBox = new JCheckBox("Color");
- private JButton mButtonColor;
- private JButton mBtnIconManager;
- private JCheckBox mRecordCheckBox = new JCheckBox("Record");
- private JComboBox mRecordActionCombo = new JComboBox<>(Record.values());
- private JCheckBox mPriorityCheckBox = new JCheckBox("Priority");
- private JSlider mPrioritySlider;
- private JLabel mPrioritySliderLabel;
- private JCheckBox mStreamCheckBox = new JCheckBox("Stream");
- private JComboBox mStreamCombo;
-
- private AliasModel mAliasModel;
- private BroadcastModel mBroadcastModel;
- private IconManager mIconManager;
-
- public MultipleAliasEditor(AliasModel aliasModel, BroadcastModel broadcastModel, IconManager iconManager)
- {
- mAliasModel = aliasModel;
- mBroadcastModel = broadcastModel;
- mIconManager = iconManager;
-
- mAliasModel.addListener(this);
- mIconManager.getModel().addTableModelListener(new TableModelListener()
- {
- @Override
- public void tableChanged(TableModelEvent e)
- {
- refreshIcons();
- }
- });
-
- init();
- }
-
- public List getAliases()
- {
- if (hasItem())
- {
- return (List) getItem();
- }
-
- return null;
- }
-
- public void init()
- {
- setLayout(new MigLayout("fill,wrap 2", "[grow,fill][grow,fill]",
- "[][][][][][][][][][][][][][grow,fill]"));
-
- mAliasCountLabel = new JLabel("Alias:");
- add(mAliasCountLabel);
-
- mAliasCount = new JLabel("Multiple");
- add(mAliasCount, "span");
-
- add(new JSeparator(), "span");
-
- add(new JLabel(HELP_TEXT), "span");
-
- add(mListCheckBox);
-
- mListCombo.setEditable(true);
- add(mListCombo, "wrap");
-
- add(mGroupCheckBox);
-
- mGroupCombo.setEditable(true);
- add(mGroupCombo, "wrap");
-
- add(mColorCheckBox);
-
- mButtonColor = new JButton("Select ...");
- mButtonColor.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- Color newColor = JColorChooser.showDialog(
- MultipleAliasEditor.this,
- "Choose color for this alias", null);
-
- if (newColor != null)
- {
- mButtonColor.setForeground(newColor);
- mButtonColor.setBackground(newColor);
- }
- }
- });
- add(mButtonColor, "wrap");
-
- add(mIconCheckBox);
-
- mIconCombo = new JComboBox(mIconManager.getIcons());
-
- IconListCellRenderer renderer = new IconListCellRenderer(mIconManager);
- renderer.setPreferredSize(new Dimension(200, 30));
- mIconCombo.setRenderer(renderer);
- add(mIconCombo, "wrap");
-
- //Dummy place holder
- add(new JLabel());
-
- mBtnIconManager = new JButton("Icon Manager");
- mBtnIconManager.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent arg0)
- {
- mIconManager.showEditor(MultipleAliasEditor.this);
- }
- });
-
- add(mBtnIconManager, "span,wrap");
-
- add(mRecordCheckBox);
- add(mRecordActionCombo);
-
- //Placeholder
- add(new JLabel(" "));
- mPrioritySliderLabel = new JLabel("Audio Priority: " + Priority.MIN_PRIORITY);
- add(mPrioritySliderLabel);
-
- add(mPriorityCheckBox);
-
- mPrioritySlider = new JSlider(JSlider.HORIZONTAL,
- Priority.MIN_PRIORITY,
- Priority.MAX_PRIORITY + 1,
- Priority.MIN_PRIORITY);
-
- mPrioritySlider.setMajorTickSpacing(20);
- mPrioritySlider.setMinorTickSpacing(5);
- mPrioritySlider.setPaintTicks(true);
- mPrioritySlider.setLabelTable(mPrioritySlider.createStandardLabels(25, 25));
- mPrioritySlider.setPaintLabels(true);
- mPrioritySlider.addChangeListener(new ChangeListener()
- {
- @Override
- public void stateChanged(ChangeEvent e)
- {
- int priority = mPrioritySlider.getValue();
-
- if (priority > Priority.MAX_PRIORITY)
- {
- mPrioritySliderLabel.setText("Audio Priority: Do Not Monitor");
- }
- else
- {
- mPrioritySliderLabel.setText("Audio Priority: " + mPrioritySlider.getValue());
- }
- }
- });
- mPrioritySlider.setToolTipText(HELP_TEXT);
-
- add(mPrioritySlider);
-
- add(mStreamCheckBox);
-
- mStreamCombo = new JComboBox();
- mStreamCombo.setEditable(true);
- add(mStreamCombo, "wrap");
-
- JButton saveButton = new JButton("Save");
- saveButton.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- save();
- }
- });
- add(saveButton);
-
- JButton resetButton = new JButton("Reset");
- resetButton.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- reset();
- }
- });
- add(resetButton);
-
- setModified(false);
- }
-
- private void refreshIcons()
- {
- if(mIconCombo != null)
- {
- EventQueue.invokeLater(new Runnable()
- {
- @Override
- public void run()
- {
- mIconCombo.setModel(new DefaultComboBoxModel<>(mIconManager.getIcons()));
- }
- });
- }
- }
-
- @Override
- public void setItem(List item)
- {
- super.setItem(item);
-
- StringBuilder sb = new StringBuilder();
- sb.append("Multiple Selected [ ");
-
- if (hasItem())
- {
- sb.append(String.valueOf(getAliases().size()));
- }
- else
- {
- sb.append("0");
- }
-
- sb.append(" ]");
-
- mAliasCount.setText(sb.toString());
-
- List listNames = mAliasModel.getListNames();
- listNames.add(0, "");
- mListCombo.setModel(new DefaultComboBoxModel(
- listNames.toArray(new String[0])));
-
- List groupNames = mAliasModel.getGroupNames();
- groupNames.add(0, "");
- mGroupCombo.setModel(new DefaultComboBoxModel(
- groupNames.toArray(new String[0])));
-
- List streamNames = mBroadcastModel.getBroadcastConfigurationNames();
- mStreamCombo.setModel(new DefaultComboBoxModel(streamNames.toArray(new String[0])));
-
- mIconCombo.setModel(new DefaultComboBoxModel<>(mIconManager.getIcons()));
-
- setCheckBoxesUnselected();
-
- setModified(false);
- }
-
- private void setCheckBoxesUnselected()
- {
- mListCheckBox.setSelected(false);
- mGroupCheckBox.setSelected(false);
- mColorCheckBox.setSelected(false);
- mIconCheckBox.setSelected(false);
- mRecordCheckBox.setSelected(false);
- mPriorityCheckBox.setSelected(false);
- mStreamCheckBox.setSelected(false);
- }
-
- @Override
- public void reset()
- {
- List listNames = mAliasModel.getListNames();
- listNames.add(0, "");
- mListCombo.setModel(new DefaultComboBoxModel(
- listNames.toArray(new String[0])));
-
- List groupNames = mAliasModel.getGroupNames();
- groupNames.add(0, "");
- mGroupCombo.setModel(new DefaultComboBoxModel(
- groupNames.toArray(new String[0])));
-
- mButtonColor.setForeground(getForeground());
- mButtonColor.setBackground(getBackground());
-
- super.reset();
- }
-
- private boolean hasRequestedChanges()
- {
- return mListCheckBox.isSelected() ||
- mGroupCheckBox.isSelected() ||
- mColorCheckBox.isSelected() ||
- mIconCheckBox.isSelected() ||
- mRecordCheckBox.isSelected() ||
- mPriorityCheckBox.isSelected() ||
- mStreamCheckBox.isSelected();
- }
-
- @Override
- public void save()
- {
- if (hasRequestedChanges() && hasItem())
- {
- List aliases = getAliases();
-
- for (Alias alias : aliases)
- {
- if (mListCheckBox.isSelected())
- {
- String list = null;
-
- if (mListCombo.getSelectedItem() != null)
- {
- list = (String) mListCombo.getSelectedItem();
- }
-
- alias.setList(list);
- }
-
- if (mGroupCheckBox.isSelected())
- {
- String group = null;
-
- if (mGroupCombo.getSelectedItem() != null)
- {
- group = (String) mGroupCombo.getSelectedItem();
- }
-
- alias.setGroup(group);
- }
-
- if (mColorCheckBox.isSelected())
- {
- alias.setColor(mButtonColor.getForeground().getRGB());
- }
-
- if (mIconCheckBox.isSelected())
- {
- if (mIconCombo.getSelectedItem() != null)
- {
- alias.setIconName(((Icon)mIconCombo.getSelectedItem()).getName());
- }
- else
- {
- alias.setIconName(null);
- }
- }
-
- if (mRecordCheckBox.isSelected())
- {
- Record action =
- (Record) mRecordActionCombo.getSelectedItem();
-
- alias.setRecordable(action == Record.RECORDABLE);
- }
-
- if (mPriorityCheckBox.isSelected())
- {
- int priority = mPrioritySlider.getValue();
-
- //This is a work-around -- we use max priority + 1 in the
- //gui to indicate do not monitor, and change the value here
- if (priority == Priority.MAX_PRIORITY + 1)
- {
- priority = Priority.DO_NOT_MONITOR;
- }
-
- alias.setCallPriority(priority);
- }
-
- if(mStreamCheckBox.isSelected())
- {
- if(mStreamCombo.getSelectedItem() != null)
- {
- String streamName = (String)mStreamCombo.getSelectedItem();
-
- boolean hasChannel = false;
-
- //Ensure the alias doesn't already have the channel
- for(BroadcastChannel channel: alias.getBroadcastChannels())
- {
- if(channel.getChannelName().equals(streamName))
- {
- hasChannel = true;
- continue;
- }
- }
-
- if(!hasChannel)
- {
- BroadcastChannel channel = (BroadcastChannel)AliasFactory
- .getAliasID(AliasIDType.BROADCAST_CHANNEL);
-
- channel.setChannelName(streamName);
- alias.addAliasID(channel);
- }
- }
- }
- }
-
- for (Alias alias : aliases)
- {
- //Broadcast an alias change event to save the updates
- mAliasModel.broadcast(new AliasEvent(alias, AliasEvent.Event.CHANGE));
- }
- }
- }
-
- @Override
- public void receive(AliasEvent event)
- {
- if (event.getEvent() == AliasEvent.Event.DELETE &&
- hasItem() &&
- getAliases().contains(event.getAlias()))
- {
- getAliases().remove(event.getAlias());
- setItem(getAliases());
- }
- }
-
- public enum Record
- {
- NON_RECORDABLE("Non-Recordable"),
- RECORDABLE("Recordable");
-
- private String mLabel;
-
- private Record(String label)
- {
- mLabel = label;
- }
-
- public String toString()
- {
- return mLabel;
- }
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/action/AliasAction.java b/src/main/java/io/github/dsheirer/alias/action/AliasAction.java
index 6018019da..8c009de39 100644
--- a/src/main/java/io/github/dsheirer/alias/action/AliasAction.java
+++ b/src/main/java/io/github/dsheirer/alias/action/AliasAction.java
@@ -27,6 +27,9 @@
import io.github.dsheirer.alias.action.clip.ClipAction;
import io.github.dsheirer.alias.action.script.ScriptAction;
import io.github.dsheirer.message.IMessage;
+import javafx.beans.Observable;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.util.Callback;
/**
* Alias action defines an action to execute when an alias is detected active.
@@ -41,10 +44,33 @@
@JacksonXmlRootElement(localName = "action")
public abstract class AliasAction
{
+ private SimpleStringProperty mValueProperty = new SimpleStringProperty();
+
public AliasAction()
{
}
+ /**
+ * String property representation of this alias ID
+ */
+ @JsonIgnore
+ public SimpleStringProperty valueProperty()
+ {
+ return mValueProperty;
+ }
+
+ /**
+ * Updates the value property for this alias ID. Note: this method is intended to be invoked by all subclasses
+ * each time that any of the subclass member variable values change.
+ */
+ public void updateValueProperty()
+ {
+ valueProperty().set(toString());
+
+ //Hack: harmless, but the list extractor does not consistently update unless we do this.
+ valueProperty().get();
+ }
+
@JsonIgnore
public abstract AliasActionType getType();
@@ -60,4 +86,12 @@ public AliasAction()
* Dismiss a persistent alias action
*/
public abstract void dismiss(boolean reset);
+
+ /**
+ * Creates an observable property extractor for use with observable lists to detect changes internal to this object.
+ */
+ public static Callback extractor()
+ {
+ return (AliasAction aliasAction) -> new Observable[] {aliasAction.valueProperty()};
+ }
}
diff --git a/src/main/java/io/github/dsheirer/alias/action/AliasActionEditor.java b/src/main/java/io/github/dsheirer/alias/action/AliasActionEditor.java
deleted file mode 100644
index b6cce86aa..000000000
--- a/src/main/java/io/github/dsheirer/alias/action/AliasActionEditor.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 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 io.github.dsheirer.alias.action;
-
-import io.github.dsheirer.alias.Alias;
-import io.github.dsheirer.alias.AliasEvent;
-import io.github.dsheirer.alias.AliasEvent.Event;
-import io.github.dsheirer.alias.AliasFactory;
-import io.github.dsheirer.alias.AliasModel;
-import io.github.dsheirer.gui.editor.Editor;
-import io.github.dsheirer.gui.editor.EmptyEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.*;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-public class AliasActionEditor extends Editor
-{
- private static final long serialVersionUID = 1L;
-
- private static ListModel EMPTY_MODEL = new DefaultListModel<>();
- private JList mAliasActionList = new JList<>( EMPTY_MODEL );
- private JButton mNewActionButton;
- private JButton mCloneActionButton;
- private JButton mDeleteActionButton;
- private EditorContainer mEditorContainer = new EditorContainer();
-
- private AliasModel mAliasModel;
-
- public AliasActionEditor( AliasModel model )
- {
- mAliasModel = model;
- init();
- }
-
- private void init()
- {
- setLayout( new MigLayout( "fill,wrap 3",
- "[grow,fill][grow,fill][grow,fill]", "[][grow,fill][]" ) );
-
- mAliasActionList.setVisibleRowCount( 6 );
- mAliasActionList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
- mAliasActionList.setLayoutOrientation( JList.VERTICAL );
- mAliasActionList.addListSelectionListener( new ListSelectionListener()
- {
- @Override
- public void valueChanged( ListSelectionEvent event )
- {
- if( !event.getValueIsAdjusting() )
- {
- JList> list = (JList>)event.getSource();
-
- Object selectedItem = list.getSelectedValue();
-
- if( selectedItem != null && selectedItem instanceof AliasAction )
- {
- AliasAction selected = (AliasAction)selectedItem;
-
- mEditorContainer.setAliasAction( selected );
-
- mCloneActionButton.setEnabled( true );
- mDeleteActionButton.setEnabled( true );
- }
- else
- {
- mCloneActionButton.setEnabled( false );
- mDeleteActionButton.setEnabled( false );
- }
- }
- }
- } );
-
- JScrollPane scroller = new JScrollPane( mAliasActionList );
- add( scroller, "span,grow" );
-
- add( mEditorContainer, "span,grow" );
-
- mNewActionButton = new JButton( "New ..." );
- mNewActionButton.setToolTipText( "Create a new Alias Action" );
- mNewActionButton.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JPopupMenu menu = new JPopupMenu();
-
- menu.add( new AddAliasActionItem( AliasActionType.BEEP ) );
- menu.add( new AddAliasActionItem( AliasActionType.CLIP ) );
- menu.add( new AddAliasActionItem( AliasActionType.SCRIPT ) );
-
- menu.show( e.getComponent(), e.getX(), e.getY() );
- }
- } );
-
- add( mNewActionButton );
-
- mCloneActionButton = new JButton( "Clone" );
- mCloneActionButton.setToolTipText( "Create a copy of the currently selected action" );
- mCloneActionButton.setEnabled( false );
- mCloneActionButton.addActionListener( new ActionListener()
- {
- @Override
- public void actionPerformed( ActionEvent e )
- {
- AliasAction selected = mAliasActionList.getSelectedValue();
-
- if( selected != null )
- {
- AliasAction clone = AliasFactory.copyOf( selected );
-
- if( clone != null )
- {
- addAliasActionToList( clone );
- }
- }
- }
- } );
- add( mCloneActionButton );
-
- mDeleteActionButton = new JButton( "Delete" );
- mDeleteActionButton.setToolTipText( "Delete the currently selected action" );
- mDeleteActionButton.setEnabled( false );
- mDeleteActionButton.addActionListener( new ActionListener()
- {
- @Override
- public void actionPerformed( ActionEvent e )
- {
- final AliasAction selected = mAliasActionList.getSelectedValue();
-
- if( selected != null )
- {
- int choice = JOptionPane.showConfirmDialog( mDeleteActionButton,
- "Do you want to delete [" + selected.toString() + "]",
- "Are you sure?", JOptionPane.YES_NO_OPTION );
-
- if( choice == JOptionPane.YES_OPTION && hasItem() )
- {
- Alias alias = getItem();
-
- alias.removeAliasAction( selected );
-
- mAliasModel.broadcast( new AliasEvent( alias, Event.CHANGE ) );
-
- setItem( alias );
- }
- }
- }
- } );
- add( mDeleteActionButton, "wrap" );
- }
-
- @Override
- public void setItem( Alias alias )
- {
- super.setItem( alias );
-
- if( alias == null || alias.getAction().isEmpty() )
- {
- mAliasActionList.setModel( EMPTY_MODEL );
- }
- else
- {
- DefaultListModel model = new DefaultListModel<>();
-
- List actions = alias.getAction();
-
- actions.sort(Comparator.comparing(Object::toString));
-
- for( AliasAction action: actions )
- {
- model.addElement( action );
- }
-
- mAliasActionList.setModel( model );
- }
-
- mEditorContainer.setAliasAction( null );
- }
-
- @Override
- public void save()
- {
- if( isModified() || mEditorContainer.isModified() )
- {
- if( mEditorContainer.isModified() )
- {
- mEditorContainer.save();
- }
-
- setModified( false );
-
- if( hasItem() )
- {
- mAliasModel.broadcast( new AliasEvent( getItem(), Event.CHANGE ) );
- }
- }
- }
-
- public class EditorContainer extends JPanel
- {
- private static final long serialVersionUID = 1L;
-
- private Editor mEditor = new EmptyEditor<>();
-
- public EditorContainer()
- {
- setLayout( new MigLayout( "","[grow,fill]", "[grow,fill]" ) );
-
- add( mEditor );
- }
-
- public boolean isModified()
- {
- if( mEditor != null )
- {
- return mEditor.isModified();
- }
-
- return false;
- }
-
- public void save()
- {
- if( mEditor != null )
- {
- mEditor.save();
- }
- }
-
- public void setAliasAction( AliasAction aliasAction )
- {
- if( mEditor != null )
- {
- if( mEditor.isModified() )
- {
- int option = JOptionPane.showConfirmDialog(
- EditorContainer.this,
- "Action settings have changed. Do you want to save these changes?",
- "Save Changes?",
- JOptionPane.YES_NO_OPTION,
- JOptionPane.QUESTION_MESSAGE );
-
- if( option == JOptionPane.YES_OPTION )
- {
- mEditor.save();
- }
- }
- }
- removeAll();
-
- //This will always give us an editor
- mEditor = AliasFactory.getEditor( aliasAction );
-
- add( mEditor );
-
- revalidate();
- }
- }
-
- private void addAliasActionToList( final AliasAction action )
- {
- if( action != null && hasItem() )
- {
- final Alias alias = getItem();
-
- alias.addAliasAction( action );
-
- EventQueue.invokeLater( new Runnable()
- {
- @Override
- public void run()
- {
- setItem( alias );
-
- mAliasActionList.setSelectedValue( action, true );
-
- AliasActionEditor.this.setModified( true );
- }
- } );
- }
- }
-
- public class AddAliasActionItem extends JMenuItem
- {
- private static final long serialVersionUID = 1L;
-
- private AliasActionType mAliasActionType;
-
- public AddAliasActionItem( AliasActionType type )
- {
- super( type.toString() );
-
- mAliasActionType = type;
-
- addActionListener( new ActionListener()
- {
- @Override
- public void actionPerformed( ActionEvent e )
- {
- final AliasAction action =
- AliasFactory.getAliasAction( mAliasActionType );
-
- addAliasActionToList( action );
- }
- } );
- }
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/action/AliasActionManager.java b/src/main/java/io/github/dsheirer/alias/action/AliasActionManager.java
index d69885853..39a13842f 100644
--- a/src/main/java/io/github/dsheirer/alias/action/AliasActionManager.java
+++ b/src/main/java/io/github/dsheirer/alias/action/AliasActionManager.java
@@ -1,21 +1,23 @@
/*
- * ******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2018 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.
+ * * ******************************************************************************
+ * * Copyright (C) 2014-2020 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
+ * * *****************************************************************************
*
- * 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 io.github.dsheirer.alias.action;
@@ -63,7 +65,7 @@ public void receive(IMessage message)
{
if(alias != null && alias.hasActions())
{
- for(AliasAction action: alias.getAction())
+ for(AliasAction action: alias.getAliasActions())
{
action.execute(alias, message);
}
@@ -76,13 +78,13 @@ public void receive(IMessage message)
@Override
public void reset()
{
- //No actions neeeded
+ //No actions needed
}
@Override
public void start()
{
- //No actions neeeded
+ //No actions needed
}
@Override
diff --git a/src/main/java/io/github/dsheirer/alias/action/RecurringAction.java b/src/main/java/io/github/dsheirer/alias/action/RecurringAction.java
index 5df291080..31535c648 100644
--- a/src/main/java/io/github/dsheirer/alias/action/RecurringAction.java
+++ b/src/main/java/io/github/dsheirer/alias/action/RecurringAction.java
@@ -61,7 +61,7 @@ public void execute(Alias alias, IMessage message)
break;
case UNTIL_DISMISSED:
mPerpetualAction = ThreadPool.SCHEDULED.scheduleAtFixedRate(
- new PerformActionTask(alias, message), mPeriod, mPeriod, TimeUnit.SECONDS);
+ new PerformActionTask(alias, message), 0, mPeriod, TimeUnit.SECONDS);
StringBuilder sb = new StringBuilder();
sb.append("
Alias [");
@@ -120,6 +120,7 @@ public int getPeriod()
public void setPeriod(int period)
{
mPeriod = period;
+ updateValueProperty();
}
@JacksonXmlProperty(isAttribute = true, localName = "interval")
@@ -131,14 +132,14 @@ public Interval getInterval()
public void setInterval(Interval interval)
{
mInterval = interval;
-
mRunning.set(false);
+ updateValueProperty();
}
public enum Interval
{
ONCE("Once"),
- DELAYED_RESET("Once, Reset After Delay"),
+ DELAYED_RESET("Once - Reset After Delay"),
UNTIL_DISMISSED("Until Dismissed");
private String mLabel;
diff --git a/src/main/java/io/github/dsheirer/alias/action/beep/BeepAction.java b/src/main/java/io/github/dsheirer/alias/action/beep/BeepAction.java
index 644b655da..d2e993ca4 100644
--- a/src/main/java/io/github/dsheirer/alias/action/beep/BeepAction.java
+++ b/src/main/java/io/github/dsheirer/alias/action/beep/BeepAction.java
@@ -24,10 +24,43 @@
import io.github.dsheirer.alias.Alias;
import io.github.dsheirer.alias.action.AliasActionType;
import io.github.dsheirer.alias.action.RecurringAction;
+import io.github.dsheirer.audio.AudioFormats;
+import io.github.dsheirer.gui.preference.playback.ToneFrequency;
+import io.github.dsheirer.gui.preference.playback.ToneUtil;
+import io.github.dsheirer.gui.preference.playback.ToneVolume;
import io.github.dsheirer.message.IMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.ShortBuffer;
public class BeepAction extends RecurringAction
{
+ private static final Logger mLog = LoggerFactory.getLogger(BeepAction.class);
+ private byte[] mToneBytes;
+
+ public BeepAction()
+ {
+ setInterval(Interval.ONCE);
+ float[] tone = ToneUtil.getTone(ToneFrequency.F700, ToneVolume.V10, 1000);
+
+ /* Little-endian byte buffer */
+ ByteBuffer buffer = ByteBuffer.allocate(tone.length * 2).order(ByteOrder.LITTLE_ENDIAN);
+
+ ShortBuffer shortBuffer = buffer.asShortBuffer();
+
+ for(float sample : tone)
+ {
+ shortBuffer.put((short) (sample * Short.MAX_VALUE));
+ }
+
+ mToneBytes = buffer.array();
+ }
@JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
@Override
@@ -39,12 +72,48 @@ public AliasActionType getType()
@Override
public void performAction(Alias alias, IMessage message )
{
- System.out.println( "\007" );
+ DataLine.Info info = new DataLine.Info(Clip.class, AudioFormats.PCM_SIGNED_8KHZ_16BITS_MONO);
+
+ if(!AudioSystem.isLineSupported(info))
+ {
+ mLog.error("Audio clip playback is not supported on this system");
+ return;
+ }
+
+ try
+ {
+ Clip clip = (Clip)AudioSystem.getLine(info);
+ clip.open(AudioFormats.PCM_SIGNED_8KHZ_16BITS_MONO, mToneBytes, 0, mToneBytes.length);
+ clip.start();
+ }
+ catch(Exception e)
+ {
+ mLog.error("Error attempting to play audio test tone");
+ }
}
@Override
public String toString()
{
- return "Beep";
+ StringBuilder sb = new StringBuilder();
+ sb.append("Beep");
+
+ if(getInterval() != null)
+ {
+ switch(getInterval())
+ {
+ case ONCE:
+ sb.append(" Once");
+ break;
+ case DELAYED_RESET:
+ sb.append(" Once, Reset After ").append(getPeriod()).append(" Seconds");
+ break;
+ case UNTIL_DISMISSED:
+ sb.append(" Every ").append(getPeriod()).append(" Seconds Until Dismissed");
+ break;
+ }
+ }
+
+ return sb.toString();
}
}
diff --git a/src/main/java/io/github/dsheirer/alias/action/beep/BeepActionEditor.java b/src/main/java/io/github/dsheirer/alias/action/beep/BeepActionEditor.java
deleted file mode 100644
index 109eea708..000000000
--- a/src/main/java/io/github/dsheirer/alias/action/beep/BeepActionEditor.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 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 io.github.dsheirer.alias.action.beep;
-
-import io.github.dsheirer.alias.action.AliasAction;
-import io.github.dsheirer.alias.action.RecurringAction;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.*;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-public class BeepActionEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private static final String HELP_TEXT =
- "
Beep Action
"
- + "This action will sound a beep according to the interval "
- + "that you select:
"
- + "Once: Beep the first time the alias is active and "
- + "never again
"
- + "Once, Reset After Delay: Beep once and suppress "
- + "subsequent beeps for the specified period in seconds. "
- + "After the reset period, beep again when the alias is active.
"
- + "Until Dismissed: Beep every period seconds until you "
- + "click OK on the dialog that appears. Alerting is suppressed "
- + "for 15 seconds after you click OK. "
- + "";
-
- private JComboBox mComboInterval;
- private JSlider mPeriodSlider;
- private JLabel mPeriodSliderLabel;
-
- public BeepActionEditor( AliasAction aliasAction )
- {
- init();
-
- setItem( aliasAction );
- }
-
- public BeepAction getBeepAction()
- {
- if( getItem() instanceof BeepAction )
- {
- return (BeepAction)getItem();
- }
-
- return null;
- }
-
- private void init()
- {
- setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][]" ) );
-
- add( new JLabel( "Beep Interval:" ) );
-
- mComboInterval = new JComboBox( RecurringAction.Interval.values() );
- mComboInterval.setToolTipText( HELP_TEXT );
- mComboInterval.addActionListener( new ActionListener()
- {
- @Override
- public void actionPerformed( ActionEvent e )
- {
- RecurringAction.Interval selected = mComboInterval
- .getItemAt( mComboInterval.getSelectedIndex() );
-
- if( selected != null )
- {
- /* Enable/disable period spinner based on selection */
- boolean enabled = selected != RecurringAction.Interval.ONCE;
-
- mPeriodSlider.setEnabled( enabled );
- mPeriodSliderLabel.setEnabled( enabled );
- }
-
- setModified( true );
- }
- });
- add( mComboInterval, "wrap" );
-
- final SpinnerModel model = new SpinnerNumberModel( 1, 1, 30, 1 );
- model.addChangeListener( new ChangeListener()
- {
- @Override
- public void stateChanged( ChangeEvent e )
- {
- setModified( true );
- }
- } );
-
- mPeriodSlider = new JSlider( JSlider.HORIZONTAL, 1, 60, 1 );
- mPeriodSlider.setMajorTickSpacing( 10 );
- mPeriodSlider.setMinorTickSpacing( 2 );
- mPeriodSlider.setPaintTicks( true );
- mPeriodSlider.setLabelTable( mPeriodSlider.createStandardLabels( 10, 10 ) );
- mPeriodSlider.setPaintLabels( true );
- mPeriodSlider.addChangeListener( new ChangeListener()
- {
- @Override
- public void stateChanged( ChangeEvent e )
- {
- mPeriodSliderLabel.setText( "Period: " + mPeriodSlider.getValue() );
- setModified( true );
- }
- } );
- mPeriodSlider.setToolTipText( HELP_TEXT );
-
- mPeriodSliderLabel = new JLabel( "Period: " + mPeriodSlider.getValue() + " " );
- add( mPeriodSliderLabel );
- add( mPeriodSlider, "wrap,grow" );
-
- JLabel help = new JLabel( "Help ..." );
- help.setForeground( Color.BLUE.brighter() );
- help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
- help.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JOptionPane.showMessageDialog( BeepActionEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
- }
- } );
- add( help, "align left" );
- }
-
- @Override
- public void setItem( AliasAction item )
- {
- super.setItem( item );
-
- if( hasItem() )
- {
- BeepAction beep = getBeepAction();
-
- RecurringAction.Interval interval = beep.getInterval();
-
- mComboInterval.setSelectedItem( interval );
-
- boolean enabled = interval != RecurringAction.Interval.ONCE;
-
- mPeriodSliderLabel.setEnabled( enabled );
- mPeriodSlider.setEnabled( enabled );
- mPeriodSlider.setValue( beep.getPeriod() );
- }
-
- setModified( false );
- }
-
- @Override
- public void save()
- {
- if( hasItem() && isModified() )
- {
- BeepAction beep = getBeepAction();
-
- beep.setInterval( (RecurringAction.Interval)mComboInterval.getSelectedItem() );
- beep.setPeriod( mPeriodSlider.getValue() );
- }
-
- setModified( false );
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/action/clip/ClipAction.java b/src/main/java/io/github/dsheirer/alias/action/clip/ClipAction.java
index 9bea39334..439ccc701 100644
--- a/src/main/java/io/github/dsheirer/alias/action/clip/ClipAction.java
+++ b/src/main/java/io/github/dsheirer/alias/action/clip/ClipAction.java
@@ -45,6 +45,7 @@ public class ClipAction extends RecurringAction
public ClipAction()
{
+ updateValueProperty();
}
@JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
@@ -62,6 +63,7 @@ public String getPath()
public void setPath(String path)
{
mFilePath = path;
+ updateValueProperty();
}
@Override
@@ -87,8 +89,7 @@ public void play() throws Exception
{
mClip = AudioSystem.getClip();
- AudioInputStream ais =
- AudioSystem.getAudioInputStream(new File(mFilePath));
+ AudioInputStream ais = AudioSystem.getAudioInputStream(new File(mFilePath));
mClip.open(ais);
}
@@ -113,17 +114,33 @@ public void play() throws Exception
}
}
-
@Override
public String toString()
{
- if(mFilePath == null)
+ StringBuilder sb = new StringBuilder();
+ sb.append("Play Audio Clip");
+
+ if(getInterval() != null)
{
- return "Play Clip";
+ switch(getInterval())
+ {
+ case ONCE:
+ sb.append(" Once");
+ break;
+ case DELAYED_RESET:
+ sb.append(" Once, Reset After ").append(getPeriod()).append(" Seconds");
+ break;
+ case UNTIL_DISMISSED:
+ sb.append(" Every ").append(getPeriod()).append(" Seconds Until Dismissed");
+ break;
+ }
}
- else
+
+ if(getPath() == null)
{
- return "Play Clip: " + mFilePath;
+ sb.append(" - (audio file empty)");
}
+
+ return sb.toString();
}
}
diff --git a/src/main/java/io/github/dsheirer/alias/action/clip/ClipActionEditor.java b/src/main/java/io/github/dsheirer/alias/action/clip/ClipActionEditor.java
deleted file mode 100644
index b8d31a0aa..000000000
--- a/src/main/java/io/github/dsheirer/alias/action/clip/ClipActionEditor.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 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 io.github.dsheirer.alias.action.clip;
-
-import io.github.dsheirer.alias.action.AliasAction;
-import io.github.dsheirer.alias.action.RecurringAction;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.*;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.io.File;
-
-public class ClipActionEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private static final String PLEASE_SELECT_A_FILE = "Please select a file";
- private static final String HELP_TEXT =
- "
Clip Action
"
- + "This action will play an audio clip according to the interval "
- + "that you select:
"
- + "Once: play the first time the alias is active and "
- + "never again
"
- + "Once, Reset After Delay: play once and suppress "
- + "subsequent runs for the specified period in seconds. "
- + "After the reset period, play again when the alias is active.
"
- + "Until Dismissed: play every period seconds until you "
- + "click OK on the dialog that appears. Alerting is suppressed "
- + "for 15 seconds after you click OK. "
- + "";
-
- private JComboBox mComboInterval;
- private JSlider mPeriodSlider;
- private JLabel mPeriodSliderLabel;
- private JTextField mTextFilePath;
-
- public ClipActionEditor( AliasAction aliasAction )
- {
- init();
-
- setItem( aliasAction );
- }
-
- public ClipAction getClipAction()
- {
- if( getItem() instanceof ClipAction )
- {
- return (ClipAction)getItem();
- }
-
- return null;
- }
-
- private void init()
- {
- setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][][][]" ) );
-
- add( new JLabel( "Play Interval:" ) );
-
- mComboInterval = new JComboBox( RecurringAction.Interval.values() );
- mComboInterval.setToolTipText( HELP_TEXT );
- mComboInterval.addActionListener( new ActionListener()
- {
- @Override
- public void actionPerformed( ActionEvent e )
- {
- RecurringAction.Interval selected = mComboInterval
- .getItemAt( mComboInterval.getSelectedIndex() );
-
- if( selected != null )
- {
- /* Enable/disable period slider based on selection */
- boolean enabled = selected != RecurringAction.Interval.ONCE;
-
- mPeriodSlider.setEnabled( enabled );
- mPeriodSliderLabel.setEnabled( enabled );
- }
-
- setModified( true );
- }
- });
- add( mComboInterval );
-
- final SpinnerModel model = new SpinnerNumberModel( 1, 1, 30, 1 );
- model.addChangeListener( new ChangeListener()
- {
- @Override
- public void stateChanged( ChangeEvent e )
- {
- setModified( true );
- }
- } );
-
- mPeriodSlider = new JSlider( JSlider.HORIZONTAL, 1, 60, 1 );
- mPeriodSlider.setMajorTickSpacing( 10 );
- mPeriodSlider.setMinorTickSpacing( 2 );
- mPeriodSlider.setPaintTicks( true );
- mPeriodSlider.setLabelTable( mPeriodSlider.createStandardLabels( 10, 10 ) );
- mPeriodSlider.setPaintLabels( true );
- mPeriodSlider.addChangeListener( new ChangeListener()
- {
- @Override
- public void stateChanged( ChangeEvent e )
- {
- mPeriodSliderLabel.setText( "Period: " + mPeriodSlider.getValue() );
- setModified( true );
- }
- } );
- mPeriodSlider.setToolTipText( HELP_TEXT );
-
- mPeriodSliderLabel = new JLabel( "Period: " + mPeriodSlider.getValue() + " " );
- add( mPeriodSliderLabel );
- add( mPeriodSlider, "wrap,grow" );
-
- mTextFilePath = new JTextField( PLEASE_SELECT_A_FILE );
- add( mTextFilePath, "growx,span" );
-
- JButton fileButton = new JButton( "File" );
-
- fileButton.addActionListener( new ActionListener()
- {
- @Override
- public void actionPerformed( ActionEvent e )
- {
- final JFileChooser chooser = new JFileChooser();
-
- int value = chooser.showOpenDialog( ClipActionEditor.this );
-
- if( value == JFileChooser.APPROVE_OPTION )
- {
- File file = chooser.getSelectedFile();
-
- mTextFilePath.setText( file.getAbsolutePath() );
-
- setModified( true );
- }
- }
- } );
-
- add( fileButton, "grow" );
-
- JButton testButton = new JButton( "Test" );
-
- testButton.addActionListener( new ActionListener()
- {
- @Override
- public void actionPerformed( ActionEvent e )
- {
- if( hasItem() )
- {
- String path = mTextFilePath.getText();
-
- if( path == null || path.trim().isEmpty() )
- {
- JOptionPane.showMessageDialog( ClipActionEditor.this,
- "Please select an audio file", PLEASE_SELECT_A_FILE,
- JOptionPane.ERROR_MESSAGE );
- }
- else
- {
- if( isModified() )
- {
- int option = JOptionPane.showConfirmDialog(
- ClipActionEditor.this,
- "Settings have changed. Do you want to save these changes?",
- "Save Changes?",
- JOptionPane.YES_NO_OPTION,
- JOptionPane.QUESTION_MESSAGE );
-
- if( option == JOptionPane.YES_OPTION )
- {
- save();
- }
- }
-
- new Thread( new Runnable()
- {
- @Override
- public void run()
- {
- try
- {
- getClipAction().play();
- }
- catch( Exception e1 )
- {
- JOptionPane.showMessageDialog( ClipActionEditor.this,
- "Couldn't play audio clip [" + e1.getMessage() + "]",
- "Error", JOptionPane.ERROR_MESSAGE );
- }
- }
- }).start();
- }
- }
- }
- } );
-
- add( testButton, "grow,wrap" );
-
- JLabel help = new JLabel( "Help ..." );
- help.setForeground( Color.BLUE.brighter() );
- help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
- help.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JOptionPane.showMessageDialog( ClipActionEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
- }
- } );
- add( help, "align left" );
- }
-
- @Override
- public void setItem( AliasAction item )
- {
- super.setItem( item );
-
- if( hasItem() )
- {
- ClipAction clip = getClipAction();
-
- RecurringAction.Interval interval = clip.getInterval();
-
- mComboInterval.setSelectedItem( interval );
-
- boolean enabled = interval != RecurringAction.Interval.ONCE;
-
- mPeriodSliderLabel.setEnabled( enabled );
- mPeriodSlider.setEnabled( enabled );
- mPeriodSlider.setValue( clip.getPeriod() );
-
- String filepath = clip.getPath();
-
- if( filepath != null && !filepath.isEmpty() )
- {
- mTextFilePath.setText( filepath );
- }
- else
- {
- mTextFilePath.setText( PLEASE_SELECT_A_FILE );
- }
- }
-
- setModified( false );
- }
-
- @Override
- public void save()
- {
- if( hasItem() && isModified() )
- {
- ClipAction script = getClipAction();
-
- script.setInterval( (RecurringAction.Interval)mComboInterval.getSelectedItem() );
- script.setPeriod( mPeriodSlider.getValue() );
- script.setPath( mTextFilePath.getText() );
- }
-
- setModified( false );
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/action/script/ScriptAction.java b/src/main/java/io/github/dsheirer/alias/action/script/ScriptAction.java
index e837010d2..7a771ed0a 100644
--- a/src/main/java/io/github/dsheirer/alias/action/script/ScriptAction.java
+++ b/src/main/java/io/github/dsheirer/alias/action/script/ScriptAction.java
@@ -39,6 +39,7 @@ public class ScriptAction extends RecurringAction
public ScriptAction()
{
+ updateValueProperty();
}
@JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
@@ -56,6 +57,7 @@ public String getScript()
public void setScript(String script)
{
mScript = script;
+ updateValueProperty();
}
@Override
@@ -104,13 +106,30 @@ public void play() throws Exception
@Override
public String toString()
{
- if(mScript == null)
+ StringBuilder sb = new StringBuilder();
+ sb.append("Run Script");
+
+ if(getInterval() != null)
{
- return "Run Script";
+ switch(getInterval())
+ {
+ case ONCE:
+ sb.append(" Once");
+ break;
+ case DELAYED_RESET:
+ sb.append(" Once, Reset After ").append(getPeriod()).append(" Seconds");
+ break;
+ case UNTIL_DISMISSED:
+ sb.append(" Every ").append(getPeriod()).append(" Seconds Until Dismissed");
+ break;
+ }
}
- else
+
+ if(getScript() == null)
{
- return "Run Script: " + mScript;
+ sb.append(" - (script file empty)");
}
+
+ return sb.toString();
}
}
diff --git a/src/main/java/io/github/dsheirer/alias/action/script/ScriptActionEditor.java b/src/main/java/io/github/dsheirer/alias/action/script/ScriptActionEditor.java
deleted file mode 100644
index 533f19419..000000000
--- a/src/main/java/io/github/dsheirer/alias/action/script/ScriptActionEditor.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 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 io.github.dsheirer.alias.action.script;
-
-import io.github.dsheirer.alias.action.AliasAction;
-import io.github.dsheirer.alias.action.RecurringAction;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.*;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.io.File;
-
-public class ScriptActionEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private static final String PLEASE_SELECT_A_FILE = "Please select a file";
- private static final String HELP_TEXT =
- "
Script Action
"
- + "This action will run a script according to the interval "
- + "that you select:
"
- + "Once: run the first time the alias is active and "
- + "never again
"
- + "Once, Reset After Delay: run once and suppress "
- + "subsequent runs for the specified period in seconds. "
- + "After the reset period, run again when the alias is active.
"
- + "Until Dismissed: run every period seconds until you "
- + "click OK on the dialog that appears. Alerting is suppressed "
- + "for 15 seconds after you click OK. "
- + "";
-
- private JComboBox mComboInterval;
- private JSlider mPeriodSlider;
- private JLabel mPeriodSliderLabel;
- private JTextField mTextFilePath;
-
- public ScriptActionEditor( AliasAction aliasAction )
- {
- init();
-
- setItem( aliasAction );
- }
-
- public ScriptAction getScriptAction()
- {
- if( getItem() instanceof ScriptAction )
- {
- return (ScriptAction)getItem();
- }
-
- return null;
- }
-
- private void init()
- {
- setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][][][]" ) );
-
- add( new JLabel( "Run Interval:" ) );
-
- mComboInterval = new JComboBox( RecurringAction.Interval.values() );
- mComboInterval.setToolTipText( HELP_TEXT );
- mComboInterval.addActionListener( new ActionListener()
- {
- @Override
- public void actionPerformed( ActionEvent e )
- {
- RecurringAction.Interval selected = mComboInterval
- .getItemAt( mComboInterval.getSelectedIndex() );
-
- if( selected != null )
- {
- /* Enable/disable period slider based on selection */
- boolean enabled = selected != RecurringAction.Interval.ONCE;
-
- mPeriodSlider.setEnabled( enabled );
- mPeriodSliderLabel.setEnabled( enabled );
- }
-
- setModified( true );
- }
- });
- add( mComboInterval );
-
- final SpinnerModel model = new SpinnerNumberModel( 1, 1, 30, 1 );
- model.addChangeListener( new ChangeListener()
- {
- @Override
- public void stateChanged( ChangeEvent e )
- {
- setModified( true );
- }
- } );
-
- mPeriodSlider = new JSlider( JSlider.HORIZONTAL, 1, 60, 1 );
- mPeriodSlider.setMajorTickSpacing( 10 );
- mPeriodSlider.setMinorTickSpacing( 2 );
- mPeriodSlider.setPaintTicks( true );
- mPeriodSlider.setLabelTable( mPeriodSlider.createStandardLabels( 10, 10 ) );
- mPeriodSlider.setPaintLabels( true );
- mPeriodSlider.addChangeListener( new ChangeListener()
- {
- @Override
- public void stateChanged( ChangeEvent e )
- {
- mPeriodSliderLabel.setText( "Period: " + mPeriodSlider.getValue() );
- setModified( true );
- }
- } );
- mPeriodSlider.setToolTipText( HELP_TEXT );
-
- mPeriodSliderLabel = new JLabel( "Period: " + mPeriodSlider.getValue() + " " );
- add( mPeriodSliderLabel );
- add( mPeriodSlider, "wrap,grow" );
-
- mTextFilePath = new JTextField( PLEASE_SELECT_A_FILE );
- add( mTextFilePath, "growx,span" );
-
- JButton fileButton = new JButton( "File" );
-
- fileButton.addActionListener( new ActionListener()
- {
- @Override
- public void actionPerformed( ActionEvent e )
- {
- final JFileChooser chooser = new JFileChooser();
-
- int value = chooser.showOpenDialog( ScriptActionEditor.this );
-
- if( value == JFileChooser.APPROVE_OPTION )
- {
- File file = chooser.getSelectedFile();
-
- mTextFilePath.setText( file.getAbsolutePath() );
-
- setModified( true );
- }
- }
- } );
-
- add( fileButton, "grow" );
-
- JButton testButton = new JButton( "Test" );
- testButton.addActionListener( new ActionListener()
- {
- @Override
- public void actionPerformed( ActionEvent actionEvent )
- {
- String script = mTextFilePath.getText();
-
- if( script == null || script.trim().isEmpty() )
- {
- JOptionPane.showMessageDialog( ScriptActionEditor.this,
- "Please select a script file", PLEASE_SELECT_A_FILE,
- JOptionPane.ERROR_MESSAGE );
- }
- else
- {
- if( isModified() )
- {
- int option = JOptionPane.showConfirmDialog(
- ScriptActionEditor.this,
- "Settings have changed. Do you want to save these changes?",
- "Save Changes?",
- JOptionPane.YES_NO_OPTION,
- JOptionPane.QUESTION_MESSAGE );
-
- if( option == JOptionPane.YES_OPTION )
- {
- save();
- }
- }
-
- new Thread( new Runnable()
- {
- @Override
- public void run()
- {
- try
- {
- getScriptAction().play();
- }
- catch( Exception e1 )
- {
- JOptionPane.showMessageDialog( ScriptActionEditor.this,
- e1.getMessage(), "Error", JOptionPane.ERROR_MESSAGE );
- }
- }
- }).start();
- }
-
- }
- } );
-
- add( testButton, "grow,wrap" );
-
- JLabel help = new JLabel( "Help ..." );
- help.setForeground( Color.BLUE.brighter() );
- help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
- help.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JOptionPane.showMessageDialog( ScriptActionEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
- }
- } );
- add( help, "align left" );
- }
-
- @Override
- public void setItem( AliasAction item )
- {
- super.setItem( item );
-
- if( hasItem() )
- {
- ScriptAction script = getScriptAction();
-
- RecurringAction.Interval interval = script.getInterval();
-
- mComboInterval.setSelectedItem( interval );
-
- boolean enabled = interval != RecurringAction.Interval.ONCE;
-
- mPeriodSliderLabel.setEnabled( enabled );
- mPeriodSlider.setEnabled( enabled );
- mPeriodSlider.setValue( script.getPeriod() );
-
- String filepath = script.getScript();
-
- if( filepath != null && !filepath.isEmpty() )
- {
- mTextFilePath.setText( filepath );
- }
- else
- {
- mTextFilePath.setText( PLEASE_SELECT_A_FILE );
- }
- }
-
- setModified( false );
- }
-
- @Override
- public void save()
- {
- if( hasItem() && isModified() )
- {
- ScriptAction script = getScriptAction();
-
- script.setInterval( (RecurringAction.Interval)mComboInterval.getSelectedItem() );
- script.setPeriod( mPeriodSlider.getValue() );
- script.setScript( mTextFilePath.getText() );
- }
-
- setModified( false );
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/AliasID.java b/src/main/java/io/github/dsheirer/alias/id/AliasID.java
index 86b5c93b2..f8b09ea72 100644
--- a/src/main/java/io/github/dsheirer/alias/id/AliasID.java
+++ b/src/main/java/io/github/dsheirer/alias/id/AliasID.java
@@ -40,43 +40,126 @@
import io.github.dsheirer.alias.id.radio.Radio;
import io.github.dsheirer.alias.id.radio.RadioRange;
import io.github.dsheirer.alias.id.record.Record;
-import io.github.dsheirer.alias.id.status.StatusID;
+import io.github.dsheirer.alias.id.status.UnitStatusID;
+import io.github.dsheirer.alias.id.status.UserStatusID;
import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
+import io.github.dsheirer.alias.id.tone.TonesID;
+import javafx.beans.Observable;
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.util.Callback;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = BroadcastChannel.class, name = "broadcastChannel"),
@JsonSubTypes.Type(value = Esn.class, name = "esn"),
@JsonSubTypes.Type(value = FleetsyncID.class, name = "fleetsyncID"),
+ @JsonSubTypes.Type(value = LegacyTalkgroupID.class, name = "talkgroupID"),
@JsonSubTypes.Type(value = LoJackFunctionAndID.class, name = "loJackFunctionAndID"),
@JsonSubTypes.Type(value = MDC1200ID.class, name = "mdc1200ID"),
@JsonSubTypes.Type(value = Min.class, name = "min"),
@JsonSubTypes.Type(value = MPT1327ID.class, name = "mpt1327ID"),
@JsonSubTypes.Type(value = NonRecordable.class, name = "nonRecordable"),
+ @JsonSubTypes.Type(value = Priority.class, name = "priority"),
@JsonSubTypes.Type(value = Radio.class, name = "radio"),
@JsonSubTypes.Type(value = RadioRange.class, name = "radioRange"),
- @JsonSubTypes.Type(value = Talkgroup.class, name = "talkgroup"),
- @JsonSubTypes.Type(value = TalkgroupRange.class, name = "talkgroupRange"),
- @JsonSubTypes.Type(value = Priority.class, name = "priority"),
@JsonSubTypes.Type(value = Record.class, name = "record"),
@JsonSubTypes.Type(value = SiteID.class, name = "siteID"),
- @JsonSubTypes.Type(value = StatusID.class, name = "statusID"),
- @JsonSubTypes.Type(value = LegacyTalkgroupID.class, name = "talkgroupID"),
+ @JsonSubTypes.Type(value = Talkgroup.class, name = "talkgroup"),
+ @JsonSubTypes.Type(value = TalkgroupRange.class, name = "talkgroupRange"),
+ @JsonSubTypes.Type(value = TonesID.class, name = "tones"),
+ @JsonSubTypes.Type(value = UserStatusID.class, name = "statusID"),
+ @JsonSubTypes.Type(value = UnitStatusID.class, name = "unitStatusID"),
@JsonSubTypes.Type(value = UniqueID.class, name = "uniqueID")
})
@JacksonXmlRootElement(localName = "id")
public abstract class AliasID
{
+ private SimpleStringProperty mValueProperty = new SimpleStringProperty();
+ private BooleanProperty mOverlapProperty = new SimpleBooleanProperty();
+
public AliasID()
{
}
+ /**
+ * String property representation of this alias ID
+ */
+ @JsonIgnore
+ public SimpleStringProperty valueProperty()
+ {
+ return mValueProperty;
+ }
+
+ /**
+ * Indicates if this alias identifier overlaps with any other alias identifier in the same alias list
+ */
+ @JsonIgnore
+ public BooleanProperty overlapProperty()
+ {
+ return mOverlapProperty;
+ }
+
+ /**
+ * Sets the overlap flag for this alias id. Overlap indicates that this identifier collides with another
+ * identifier within the same alias list.
+ */
+ public void setOverlap(boolean overlap)
+ {
+ mOverlapProperty.set(overlap);
+ updateValueProperty();
+ }
+
+ /**
+ * Updates the value property for this alias ID. Note: this method is intended to be invoked by all subclasses
+ * each time that any of the subclass member variable values change.
+ */
+ public void updateValueProperty()
+ {
+ if(overlapProperty().get())
+ {
+ valueProperty().set(toString() + " - Error: Overlap");
+ }
+ else
+ {
+ valueProperty().set(toString());
+ }
+
+ //Hack: harmless, but the list extractor does not consistently update unless we do this.
+ valueProperty().get();
+ }
+
@JsonIgnore
public abstract AliasIDType getType();
public abstract boolean matches(AliasID id);
+ /**
+ * Indicates if this alias ID overlaps with another alias ID.
+ * Note: this method is intended to be overridden by certain subclass implementations.
+ */
+ @JsonIgnore
+ public boolean overlaps(AliasID id)
+ {
+ return false;
+ }
+
@JsonIgnore
public abstract boolean isValid();
+
+ /**
+ * Indicates if the identifier is an audio identifier (monitor, record, stream)
+ */
+ @JsonIgnore
+ public abstract boolean isAudioIdentifier();
+
+ /**
+ * Creates an observable property extractor for use with observable lists to detect changes internal to this object.
+ */
+ public static Callback extractor()
+ {
+ return (AliasID aid) -> new Observable[] {aid.valueProperty(), aid.overlapProperty()};
+ }
}
diff --git a/src/main/java/io/github/dsheirer/alias/id/AliasIDType.java b/src/main/java/io/github/dsheirer/alias/id/AliasIDType.java
index 1ff9f356a..77a913378 100644
--- a/src/main/java/io/github/dsheirer/alias/id/AliasIDType.java
+++ b/src/main/java/io/github/dsheirer/alias/id/AliasIDType.java
@@ -21,6 +21,8 @@
*/
package io.github.dsheirer.alias.id;
+import java.util.EnumSet;
+
public enum AliasIDType
{
BROADCAST_CHANNEL("Audio Broadcast Channel"),
@@ -34,7 +36,9 @@ public enum AliasIDType
RADIO_ID_RANGE("Radio ID Range"),
RECORD("Record"),
SITE("Site"),
- STATUS("Status"),
+ STATUS("User Status"),
+ TONES("Tone Sequence"),
+ UNIT_STATUS("Unit Status"),
TALKGROUP("Talkgroup"),
TALKGROUP_RANGE("Talkgroup Range"),
@@ -52,6 +56,10 @@ public enum AliasIDType
mLabel = label;
}
+ //Values used by the View-By alias editor
+ public static EnumSet VIEW_BY_VALUES = EnumSet.of(TALKGROUP, TALKGROUP_RANGE, RADIO_ID, RADIO_ID_RANGE,
+ UNIT_STATUS, STATUS, TONES);
+
public String toString()
{
return mLabel;
diff --git a/src/main/java/io/github/dsheirer/alias/id/AliasIdentifierEditor.java b/src/main/java/io/github/dsheirer/alias/id/AliasIdentifierEditor.java
deleted file mode 100644
index 226871452..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/AliasIdentifierEditor.java
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- *
- * * ******************************************************************************
- * * Copyright (C) 2014-2019 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 io.github.dsheirer.alias.id;
-
-import io.github.dsheirer.alias.Alias;
-import io.github.dsheirer.alias.AliasEvent;
-import io.github.dsheirer.alias.AliasFactory;
-import io.github.dsheirer.alias.AliasModel;
-import io.github.dsheirer.audio.broadcast.BroadcastModel;
-import io.github.dsheirer.gui.editor.Editor;
-import io.github.dsheirer.gui.editor.EmptyEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.DefaultListModel;
-import javax.swing.JButton;
-import javax.swing.JList;
-import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JPopupMenu;
-import javax.swing.JScrollPane;
-import javax.swing.ListModel;
-import javax.swing.ListSelectionModel;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-import java.awt.EventQueue;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-public class AliasIdentifierEditor extends Editor
-{
- private static final long serialVersionUID = 1L;
-
- private static ListModel EMPTY_MODEL = new DefaultListModel<>();
- private JList mAliasIDList = new JList<>(EMPTY_MODEL);
- private JButton mNewIDButton;
- private JButton mCloneIDButton;
- private JButton mDeleteIDButton;
- private EditorContainer mEditorContainer = new EditorContainer();
-
- private AliasModel mAliasModel;
- private BroadcastModel mBroadcastModel;
-
- public AliasIdentifierEditor(AliasModel aliasModel, BroadcastModel broadcastModel)
- {
- mAliasModel = aliasModel;
- mBroadcastModel = broadcastModel;
-
- init();
- }
-
- private void init()
- {
- setLayout(new MigLayout("fill,wrap 3",
- "[grow,fill][grow,fill][grow,fill]", "[][grow,fill][]"));
-
- mAliasIDList.setVisibleRowCount(6);
- mAliasIDList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- mAliasIDList.setLayoutOrientation(JList.VERTICAL);
- mAliasIDList.addListSelectionListener(new ListSelectionListener()
- {
- @Override
- public void valueChanged(ListSelectionEvent event)
- {
- if(!event.getValueIsAdjusting())
- {
- JList> list = (JList>)event.getSource();
-
- Object selectedItem = list.getSelectedValue();
-
- if(selectedItem != null && selectedItem instanceof AliasID)
- {
- AliasID selected = (AliasID)selectedItem;
-
- mEditorContainer.setAliasID(selected);
-
- mCloneIDButton.setEnabled(true);
- mDeleteIDButton.setEnabled(true);
- }
- else
- {
- mCloneIDButton.setEnabled(false);
- mDeleteIDButton.setEnabled(false);
- }
- }
- }
- });
-
- JScrollPane scroller = new JScrollPane(mAliasIDList);
- add(scroller, "span,grow");
-
- add(mEditorContainer, "span,grow");
-
- mNewIDButton = new JButton("New ...");
- mNewIDButton.setToolTipText("Create a new Alias Identifier");
- mNewIDButton.addMouseListener(new MouseAdapter()
- {
- @Override
- public void mouseClicked(MouseEvent e)
- {
- JPopupMenu menu = new JPopupMenu();
-
- menu.add(new AddAliasIdentifierItem(AliasIDType.TALKGROUP));
- menu.add(new AddAliasIdentifierItem(AliasIDType.TALKGROUP_RANGE));
- menu.add(new AddAliasIdentifierItem(AliasIDType.RADIO_ID));
- menu.add(new AddAliasIdentifierItem(AliasIDType.RADIO_ID_RANGE));
- menu.add(new AddAliasIdentifierItem(AliasIDType.ESN));
-// menu.add(new AddAliasIdentifierItem(AliasIDType.LOJACK));
- menu.add(new AddAliasIdentifierItem(AliasIDType.STATUS));
-
- menu.addSeparator();
-
- menu.add(new AddAliasIdentifierItem(AliasIDType.BROADCAST_CHANNEL));
-
- if(hasItem())
- {
- Alias alias = getItem();
-
- if(!alias.isRecordable())
- {
- menu.add(new AddAliasIdentifierItem(AliasIDType.RECORD));
- }
-
- if(!alias.hasCallPriority())
- {
- menu.add(new AddAliasIdentifierItem(AliasIDType.PRIORITY));
- }
- }
-
- menu.show(e.getComponent(), e.getX(), e.getY());
- }
- });
-
- add(mNewIDButton);
-
- mCloneIDButton = new JButton("Clone");
- mCloneIDButton.setToolTipText("Create a copy of the currently selected identifier");
- mCloneIDButton.setEnabled(false);
- mCloneIDButton.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- AliasID selected = mAliasIDList.getSelectedValue();
-
- if(selected != null)
- {
- AliasID clone = AliasFactory.copyOf(selected);
-
- if(clone != null)
- {
- addAliasIDToList(clone);
- }
- }
- }
- });
- add(mCloneIDButton);
-
- mDeleteIDButton = new JButton("Delete");
- mDeleteIDButton.setToolTipText("Delete the currently selected identifier");
- mDeleteIDButton.setEnabled(false);
- mDeleteIDButton.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- final AliasID selected = mAliasIDList.getSelectedValue();
-
- if(selected != null)
- {
- int choice = JOptionPane.showConfirmDialog(mDeleteIDButton,
- "Do you want to delete [" + selected.toString() + "]",
- "Are you sure?", JOptionPane.YES_NO_OPTION);
-
- if(choice == JOptionPane.YES_OPTION && hasItem())
- {
- Alias alias = getItem();
-
- alias.removeAliasID(selected);
-
- mAliasModel.broadcast(new AliasEvent(alias, AliasEvent.Event.CHANGE));
-
- setItem(alias);
- }
- }
- }
- });
- add(mDeleteIDButton, "wrap");
- }
-
- @Override
- public void setItem(Alias alias)
- {
- super.setItem(alias);
-
- if(alias == null || alias.getId().isEmpty())
- {
- mAliasIDList.setModel(EMPTY_MODEL);
- }
- else
- {
- DefaultListModel model = new DefaultListModel();
-
- List ids = alias.getId();
-
- ids.sort(Comparator.comparing(Object::toString));
-
- for(AliasID id : ids)
- {
- model.addElement(id);
- }
-
- mAliasIDList.setModel(model);
- }
-
- mEditorContainer.setAliasID(null);
- }
-
- @Override
- public void save()
- {
- if(isModified() || mEditorContainer.isModified())
- {
- if(mEditorContainer.isModified())
- {
- mEditorContainer.save();
- }
-
- setModified(false);
-
- if(hasItem())
- {
- mAliasModel.broadcast(new AliasEvent(getItem(), AliasEvent.Event.CHANGE));
- }
- }
- }
-
- public class EditorContainer extends JPanel
- {
- private static final long serialVersionUID = 1L;
-
- private Editor mEditor = new EmptyEditor<>();
-
- public EditorContainer()
- {
- setLayout(new MigLayout("", "[grow,fill]", "[grow,fill]"));
-
- add(mEditor);
- }
-
- public boolean isModified()
- {
- if(mEditor != null)
- {
- return mEditor.isModified();
- }
-
- return false;
- }
-
- public void save()
- {
- if(mEditor != null)
- {
- mEditor.save();
- }
- }
-
- public void setAliasID(AliasID aliasID)
- {
- if(mEditor != null)
- {
- if(mEditor.isModified())
- {
- int option = JOptionPane.showConfirmDialog(
- EditorContainer.this,
- "Identifier settings have changed. Do you want to save these changes?",
- "Save Changes?",
- JOptionPane.YES_NO_OPTION,
- JOptionPane.QUESTION_MESSAGE);
-
- if(option == JOptionPane.YES_OPTION)
- {
- mEditor.save();
- }
- }
- }
- removeAll();
-
- //This will always give us an editor
- mEditor = AliasFactory.getEditor(aliasID, mBroadcastModel);
-
- add(mEditor);
-
- revalidate();
- }
- }
-
- private void addAliasIDToList(final AliasID id)
- {
- if(id != null && hasItem())
- {
- final Alias alias = getItem();
-
- alias.addAliasID(id);
-
- EventQueue.invokeLater(new Runnable()
- {
- @Override
- public void run()
- {
- setItem(alias);
-
- mAliasIDList.setSelectedValue(id, true);
-
- AliasIdentifierEditor.this.setModified(true);
- }
- });
- }
- }
-
- public class AddAliasIdentifierItem extends JMenuItem
- {
- private static final long serialVersionUID = 1L;
-
- private AliasIDType mAliasIDType;
-
- public AddAliasIdentifierItem(AliasIDType type)
- {
- super(type.toString());
-
- mAliasIDType = type;
-
- addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- final AliasID id = AliasFactory.getAliasID(mAliasIDType);
-
- addAliasIDToList(id);
- }
- });
- }
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/WildcardID.java b/src/main/java/io/github/dsheirer/alias/id/WildcardID.java
deleted file mode 100644
index 2b9b0afd6..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/WildcardID.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2016 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 io.github.dsheirer.alias.id;
-
-import org.apache.commons.lang3.Validate;
-import org.apache.commons.math3.util.FastMath;
-
-import java.util.regex.Pattern;
-
-public class WildcardID implements Comparable
-{
- public static final String WILDCARD = "*";
- public static final String REGEX_WILDCARD = ".";
-
- private String mValue;
- private Pattern mPattern;
- private int mWeight;
-
- /**
- * Wildcard identifier for matching to string identifiers containing single-character (*) wildcard values.
- *
- * Supports ordering from most-specific to least-specific using the build-in weighting calculation where identifier
- * patterns containing fewer wildcards closer to the least significant digit will be weighted more heavily than
- * identifier patterns containing more wildcards, or wildcard characters in the most significant digits.
- *
- * @param value is a string value containing one or more asterisk (*) single character wildcard with a maximum
- * length of 10 characters.
- *
- * @throws AssertionError if the value is null, longer than 10 characters, or doesn't contain at least 1 asterisk
- * @throws IllegalArgumentException if the value cannot be compiled as a regular expression after converting the
- * asterisk characters to the regex single-character wildcard value (.)
- */
- public WildcardID(String value)
- {
- Validate.isTrue(value != null && value.contains(WILDCARD) && value.length() < 10);
-
- mValue = value;
-
- try
- {
- mPattern = Pattern.compile(value.replace(WILDCARD, REGEX_WILDCARD));
- }
- catch(Exception e)
- {
- throw new IllegalArgumentException("Invalid regex pattern for alias ID value [" + value + "]", e);
- }
-
- mWeight = calculateWeight();
- }
-
- public String value()
- {
- return mValue;
- }
-
- /**
- * Indicates if the id matches the internal regex pattern for this wildcard alias ID
- * @param id
- * @return
- */
- public boolean matches(String id)
- {
- return id != null && mPattern.matcher(id).matches();
- }
-
- public int weight()
- {
- return mWeight;
- }
-
- /**
- * Calculates a weighting value for wildcard character quantity and significant digit location
- */
- private int calculateWeight()
- {
- int weight = 0;
- int characterCount = -1;
-
- for( int x = 0; x < mValue.length(); x++)
- {
- if(mValue.substring(x, x + 1).equals(WILDCARD))
- {
- weight += (int)(FastMath.pow(2, mValue.length() - x - 1)); //Position weight
- characterCount++;
- }
- }
-
- weight += (int)(FastMath.pow(2, characterCount)) * 1000; //Character count weight
-
- return weight;
- }
-
- @Override
- public int compareTo(WildcardID otherWildcardID)
- {
- return Integer.compare(this.weight(), otherWildcardID.weight());
- }
-
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof WildcardID)) return false;
- return compareTo((WildcardID) o) == 0;
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/broadcast/BroadcastChannel.java b/src/main/java/io/github/dsheirer/alias/id/broadcast/BroadcastChannel.java
index d3aec77c8..5f4911162 100644
--- a/src/main/java/io/github/dsheirer/alias/id/broadcast/BroadcastChannel.java
+++ b/src/main/java/io/github/dsheirer/alias/id/broadcast/BroadcastChannel.java
@@ -1,21 +1,24 @@
-/*******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2016 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.
+ * * ******************************************************************************
+ * * Copyright (C) 2014-2020 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
+ * * *****************************************************************************
*
- * 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 io.github.dsheirer.alias.id.broadcast;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
@@ -31,6 +34,12 @@ public BroadcastChannel()
//JAXB Constructor
}
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return true;
+ }
+
@Override
public int compareTo(BroadcastChannel other)
{
@@ -94,6 +103,7 @@ public String getChannelName()
public void setChannelName(String channel)
{
mChannelName = channel;
+ updateValueProperty();
}
@JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
@@ -118,13 +128,6 @@ public boolean matches(AliasID id)
@Override
public String toString()
{
- if(isValid())
- {
- return "Broadcast Channel: " + mChannelName;
- }
- else
- {
- return "Broadcast Channel: None Selected";
- }
+ return isValid() ? mChannelName : "(invalid)";
}
}
diff --git a/src/main/java/io/github/dsheirer/alias/id/broadcast/BroadcastChannelEditor.java b/src/main/java/io/github/dsheirer/alias/id/broadcast/BroadcastChannelEditor.java
deleted file mode 100644
index cd4ebc3d1..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/broadcast/BroadcastChannelEditor.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2016 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 io.github.dsheirer.alias.id.broadcast;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.audio.broadcast.BroadcastConfiguration;
-import io.github.dsheirer.audio.broadcast.BroadcastModel;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.util.List;
-
-public class BroadcastChannelEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private static final String HELP_TEXT = ""
- + "
Audio Broadcast Channel
"
- + "Name of a audio streaming broadcast configuration "
- + "to be used for streaming audio to an external "
- + "streaming server";
-
- private JComboBox mBroadcastConfigurations;
- private BroadcastModel mBroadcastModel;
-
- public BroadcastChannelEditor(AliasID aliasID, BroadcastModel broadcastModel)
- {
- mBroadcastModel = broadcastModel;
-
- initGUI();
- setItem( aliasID );
- }
-
- private void initGUI()
- {
- setLayout( new MigLayout( "fill,wrap 1", "[]", "[][]" ) );
-
- add( new JLabel( "Broadcast Channel" ), "grow" );
-
- List channelNames = mBroadcastModel.getBroadcastConfigurationNames();
-
- mBroadcastConfigurations = new JComboBox(channelNames.toArray(new String[0]));
- mBroadcastConfigurations.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- setModified(true);
- }
- });
-
- add(mBroadcastConfigurations, "grow");
-
- JLabel help = new JLabel( "Help ..." );
- help.setForeground( Color.BLUE.brighter() );
- help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
- help.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JOptionPane.showMessageDialog( BroadcastChannelEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
- }
- } );
-
- add( help, "align left" );
- }
-
- @Override
- public void setItem(AliasID item)
- {
- super.setItem(item);
-
- if(item instanceof BroadcastChannel)
- {
- BroadcastChannel channel = (BroadcastChannel)item;
-
- if(channel.isValid())
- {
- mBroadcastConfigurations.setSelectedItem(channel.getChannelName());
- }
- }
-
- setModified(false);
- }
-
- @Override
- public void save()
- {
- String channel = (String)mBroadcastConfigurations.getSelectedItem();
-
- BroadcastConfiguration selectedConfiguration = mBroadcastModel.getBroadcastConfiguration(channel);
-
-
- if(selectedConfiguration != null)
- {
- ((BroadcastChannel)getItem()).setChannelName(selectedConfiguration.getName());
- }
- else
- {
- ((BroadcastChannel)getItem()).setChannelName(null);
- }
- }
-
-
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/esn/ESNEditor.java b/src/main/java/io/github/dsheirer/alias/id/esn/ESNEditor.java
deleted file mode 100644
index 06675ffcc..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/esn/ESNEditor.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 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 io.github.dsheirer.alias.id.esn;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-public class ESNEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private static final String HELP_TEXT =
- "
Electronic Serial Number (ESN)
"
- + "ESN: hexadecimal 0-9, A-F (e.g. ABCD1234 ) "
- + "Wildcard: use an asterisk (*) to wildcard individual "
- + "digits (e.g. ABCD123* or AB**1**4)"
- + "";
-
- private JTextField mTextField;
-
- public ESNEditor( AliasID aliasID )
- {
- initGUI();
-
- setItem( aliasID );
- }
-
- private void initGUI()
- {
- setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][]" ) );
-
- add( new JLabel( "ESN:" ) );
- mTextField = new JTextField();
- mTextField.getDocument().addDocumentListener( this );
- mTextField.setToolTipText( HELP_TEXT );
- add( mTextField, "growx,push" );
-
- JLabel help = new JLabel( "Help ..." );
- help.setForeground( Color.BLUE.brighter() );
- help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
- help.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JOptionPane.showMessageDialog( ESNEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
- }
- } );
- add( help, "align left" );
- }
-
- public Esn getEsn()
- {
- if( getItem() instanceof Esn )
- {
- return (Esn)getItem();
- }
-
- return null;
- }
-
- @Override
- public void setItem( AliasID aliasID )
- {
- super.setItem( aliasID );
-
- Esn esn = getEsn();
-
- if( esn != null )
- {
- mTextField.setText( esn.getEsn() );
- }
-
- setModified( false );
-
- repaint();
- }
-
- @Override
- public void save()
- {
- Esn esn = getEsn();
-
- if( esn != null )
- {
- esn.setEsn( mTextField.getText() );
- }
-
- setModified( false );
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/esn/Esn.java b/src/main/java/io/github/dsheirer/alias/id/esn/Esn.java
index a2b660225..a3f73c77f 100644
--- a/src/main/java/io/github/dsheirer/alias/id/esn/Esn.java
+++ b/src/main/java/io/github/dsheirer/alias/id/esn/Esn.java
@@ -29,6 +29,12 @@ public Esn()
{
}
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return false;
+ }
+
@JacksonXmlProperty(isAttribute = true, localName = "esn")
public String getEsn()
{
@@ -44,6 +50,7 @@ public boolean isValid()
public void setEsn(String esn )
{
mEsn = esn;
+ updateValueProperty();
}
public String toString()
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/fleetsync/FleetsyncID.java b/src/main/java/io/github/dsheirer/alias/id/legacy/fleetsync/FleetsyncID.java
index 3076d3b72..970d96814 100644
--- a/src/main/java/io/github/dsheirer/alias/id/legacy/fleetsync/FleetsyncID.java
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/fleetsync/FleetsyncID.java
@@ -31,6 +31,12 @@ public FleetsyncID()
{
}
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return false;
+ }
+
@JacksonXmlProperty(isAttribute = true, localName = "ident")
public String getIdent()
{
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/fleetsync/FleetsyncIDEditor.java b/src/main/java/io/github/dsheirer/alias/id/legacy/fleetsync/FleetsyncIDEditor.java
deleted file mode 100644
index 85f7a2ba9..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/legacy/fleetsync/FleetsyncIDEditor.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * ******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2018 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 io.github.dsheirer.alias.id.legacy.fleetsync;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.swing.JFormattedTextField;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JTextField;
-import javax.swing.text.MaskFormatter;
-import java.awt.Color;
-import java.awt.Cursor;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-public class FleetsyncIDEditor extends DocumentListenerEditor
-{
- private final static Logger mLog = LoggerFactory.getLogger( FleetsyncIDEditor.class );
-
- private static final long serialVersionUID = 1L;
-
- private static final String HELP_TEXT = ""
- + "
Fleetsync Identifier
"
- + "Fleetsync: ggg-uuuu where g=Group and u=Unit (e.g. 001-0001) "
- + "Wildcard: use an asterisk (*) for each digit (e.g. 001-****)"
- + "";
-
- private JTextField mTextField;
-
- public FleetsyncIDEditor( AliasID aliasID )
- {
- initGUI();
-
- setItem( aliasID );
- }
-
- private void initGUI()
- {
- setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][]" ) );
-
- add( new JLabel( "Fleetsync ID:" ) );
-
- MaskFormatter formatter = null;
-
- try
- {
- //Mask: 3 digits - 4 digits
- formatter = new MaskFormatter( "###-####" );
- }
- catch( Exception e )
- {
- //Do nothing, the mask was invalid
- }
-
- mTextField = new JFormattedTextField( formatter );
- mTextField.getDocument().addDocumentListener( this );
- mTextField.setToolTipText( HELP_TEXT );
-
- add( mTextField, "growx,push" );
-
- JLabel help = new JLabel( "Help ..." );
- help.setForeground( Color.BLUE.brighter() );
- help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
- help.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JOptionPane.showMessageDialog( FleetsyncIDEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
- }
- } );
- add( help, "align left" );
- }
-
- public FleetsyncID getFleetsyncID()
- {
- if( getItem() instanceof FleetsyncID )
- {
- return (FleetsyncID)getItem();
- }
-
- return null;
- }
-
- @Override
- public void setItem( AliasID aliasID )
- {
- super.setItem( aliasID );
-
- FleetsyncID fleetsync = getFleetsyncID();
-
- if( fleetsync != null )
- {
- mTextField.setText( fleetsync.getIdent() );
- }
-
- setModified( false );
-
- repaint();
- }
-
- @Override
- public void save()
- {
- FleetsyncID fleetsync = getFleetsyncID();
-
- if( fleetsync != null )
- {
- fleetsync.setIdent( mTextField.getText() );
- }
-
- setModified( false );
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/mdc/MDC1200ID.java b/src/main/java/io/github/dsheirer/alias/id/legacy/mdc/MDC1200ID.java
index 85dc60d9c..b1a09062c 100644
--- a/src/main/java/io/github/dsheirer/alias/id/legacy/mdc/MDC1200ID.java
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/mdc/MDC1200ID.java
@@ -32,6 +32,12 @@ public MDC1200ID()
{
}
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return false;
+ }
+
@JacksonXmlProperty(isAttribute = true, localName = "ident")
public String getIdent()
{
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/mdc/MDC1200IDEditor.java b/src/main/java/io/github/dsheirer/alias/id/legacy/mdc/MDC1200IDEditor.java
deleted file mode 100644
index f472e6d54..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/legacy/mdc/MDC1200IDEditor.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * ******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2018 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 io.github.dsheirer.alias.id.legacy.mdc;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.JFormattedTextField;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JTextField;
-import javax.swing.text.MaskFormatter;
-import java.awt.Color;
-import java.awt.Cursor;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-public class MDC1200IDEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private static final String HELP_TEXT = ""
- + "
MDC-1200 Identifier
"
- + "MDC-1200: four digit [0-9] value (e.g. 1234) "
- + "Wildcard: use an asterisk (*) to wildcard individual "
- + "digits (e.g. 123* or **34)"
- + "";
-
- private JTextField mTextField;
-
- public MDC1200IDEditor(AliasID aliasID)
- {
- initGUI();
-
- setItem(aliasID);
- }
-
- private void initGUI()
- {
- setLayout(new MigLayout("fill,wrap 2", "[right][left]", "[][]"));
-
- add(new JLabel("MDC-1200 ID:"));
-
- MaskFormatter formatter = null;
-
- try
- {
- //Mask: 4 digits
- formatter = new MaskFormatter("####");
- }
- catch(Exception e)
- {
- //Do nothing, the mask was invalid
- }
-
- mTextField = new JFormattedTextField(formatter);
- mTextField.getDocument().addDocumentListener(this);
- mTextField.setToolTipText(HELP_TEXT);
- add(mTextField, "growx,push");
-
- JLabel help = new JLabel("Help ...");
- help.setForeground(Color.BLUE.brighter());
- help.setCursor(new Cursor(Cursor.HAND_CURSOR));
- help.addMouseListener(new MouseAdapter()
- {
- @Override
- public void mouseClicked(MouseEvent e)
- {
- JOptionPane.showMessageDialog(MDC1200IDEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE);
- }
- });
- add(help, "align left");
- }
-
- public MDC1200ID getMDC1200ID()
- {
- if(getItem() instanceof MDC1200ID)
- {
- return (MDC1200ID)getItem();
- }
-
- return null;
- }
-
- @Override
- public void setItem(AliasID aliasID)
- {
- super.setItem(aliasID);
-
- MDC1200ID mdc = getMDC1200ID();
-
- if(mdc != null)
- {
- mTextField.setText(mdc.getIdent());
- }
-
- setModified(false);
-
- repaint();
- }
-
- @Override
- public void save()
- {
- MDC1200ID mdc = getMDC1200ID();
-
- if(mdc != null)
- {
- mdc.setIdent(mTextField.getText());
- }
-
- setModified(false);
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/mobileID/MINEditor.java b/src/main/java/io/github/dsheirer/alias/id/legacy/mobileID/MINEditor.java
deleted file mode 100644
index f50b831a7..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/legacy/mobileID/MINEditor.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 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 io.github.dsheirer.alias.id.legacy.mobileID;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.*;
-import javax.swing.text.MaskFormatter;
-import java.awt.*;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-public class MINEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private static final String HELP_TEXT = ""
- + "
Passport Mobile ID (MIN)
"
- + "MIN: six character hex value (e.g. AB12CD) "
- + "Wildcard: use an asterisk (*) to wildcard individual "
- + "digits (e.g. AB**CD or AB12**)"
- + "";
-
- private JTextField mTextField;
-
- public MINEditor( AliasID aliasID )
- {
- initGUI();
-
- setItem( aliasID );
- }
-
- private void initGUI()
- {
- setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][]" ) );
-
- add( new JLabel( "MIN:" ) );
-
- MaskFormatter formatter = null;
-
- try
- {
- //Mask: 6 hex characters
- formatter = new MaskFormatter( "HHHHHH" );
- }
- catch( Exception e )
- {
- //Do nothing, the mask was invalid
- }
-
- mTextField = new JFormattedTextField( formatter );
- mTextField.getDocument().addDocumentListener( this );
- mTextField.setToolTipText( HELP_TEXT );
- add( mTextField, "growx,push" );
-
- JLabel help = new JLabel( "Help ..." );
- help.setForeground( Color.BLUE.brighter() );
- help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
- help.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JOptionPane.showMessageDialog( MINEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
- }
- } );
- add( help, "align left" );
- }
-
- public Min getMin()
- {
- if( getItem() instanceof Min )
- {
- return (Min)getItem();
- }
-
- return null;
- }
-
- @Override
- public void setItem( AliasID aliasID )
- {
- super.setItem( aliasID );
-
- Min min = getMin();
-
- if( min != null )
- {
- mTextField.setText( min.getMin() );
- }
-
- setModified( false );
-
- repaint();
- }
-
- @Override
- public void save()
- {
- Min min = getMin();
-
- if( min != null )
- {
- min.setMin( mTextField.getText() );
- }
-
- setModified( false );
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/mobileID/Min.java b/src/main/java/io/github/dsheirer/alias/id/legacy/mobileID/Min.java
index 4cd2e203a..c20fea890 100644
--- a/src/main/java/io/github/dsheirer/alias/id/legacy/mobileID/Min.java
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/mobileID/Min.java
@@ -33,6 +33,12 @@ public Min()
{
}
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return false;
+ }
+
@JacksonXmlProperty(isAttribute = true, localName = "min")
public String getMin()
{
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/mpt1327/MPT1327ID.java b/src/main/java/io/github/dsheirer/alias/id/legacy/mpt1327/MPT1327ID.java
index b27ad6ee4..e10bf3322 100644
--- a/src/main/java/io/github/dsheirer/alias/id/legacy/mpt1327/MPT1327ID.java
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/mpt1327/MPT1327ID.java
@@ -32,6 +32,12 @@ public MPT1327ID()
{
}
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return false;
+ }
+
@JacksonXmlProperty(isAttribute = true, localName = "ident")
public String getIdent()
{
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/mpt1327/MPT1327IDEditor.java b/src/main/java/io/github/dsheirer/alias/id/legacy/mpt1327/MPT1327IDEditor.java
deleted file mode 100644
index 36c38ecc9..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/legacy/mpt1327/MPT1327IDEditor.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * ******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2018 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 io.github.dsheirer.alias.id.legacy.mpt1327;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.JFormattedTextField;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JTextField;
-import javax.swing.text.MaskFormatter;
-import java.awt.Color;
-import java.awt.Cursor;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-public class MPT1327IDEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private static final String HELP_TEXT = ""
- + "
MPT-1327 Identifier
"
- + "MPT-1327: decimal (0-9) format ppp-iiii where "
- + "p=Prefix and i=Ident (e.g. 123-0001) "
- + "Wildcard: use an asterisk (*) to wildcard individual "
- + "digits (e.g. ABCD123* or AB**1**4)"
- + "";
-
- private JTextField mTextField;
-
- public MPT1327IDEditor( AliasID aliasID )
- {
- initGUI();
-
- setItem( aliasID );
- }
-
- private void initGUI()
- {
- setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][]" ) );
-
- add( new JLabel( "MPT-1327 ID:" ) );
-
- MaskFormatter formatter = null;
-
- try
- {
- //Mask: 3 digits - 4 digits
- formatter = new MaskFormatter( "***-****" );
- }
- catch( Exception e )
- {
- //Do nothing, the mask was invalid
- }
-
- mTextField = new JFormattedTextField( formatter );
- mTextField.getDocument().addDocumentListener( this );
- mTextField.setToolTipText( HELP_TEXT );
-
- add( mTextField, "growx,push" );
-
- JLabel help = new JLabel( "Help ..." );
- help.setForeground( Color.BLUE.brighter() );
- help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
- help.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JOptionPane.showMessageDialog( MPT1327IDEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
- }
- } );
- add( help, "align left" );
- }
-
- public MPT1327ID getMPT1327ID()
- {
- if( getItem() instanceof MPT1327ID )
- {
- return (MPT1327ID)getItem();
- }
-
- return null;
- }
-
- @Override
- public void setItem( AliasID aliasID )
- {
- super.setItem( aliasID );
-
- MPT1327ID mpt = getMPT1327ID();
-
- if( mpt != null )
- {
- mTextField.setText( mpt.getIdent() );
- }
-
- setModified( false );
-
- repaint();
- }
-
- @Override
- public void save()
- {
- MPT1327ID mpt = getMPT1327ID();
-
- if( mpt != null )
- {
- mpt.setIdent( mTextField.getText() );
- }
-
- setModified( false );
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/nonrecordable/NonRecordable.java b/src/main/java/io/github/dsheirer/alias/id/legacy/nonrecordable/NonRecordable.java
index b9d10706f..5d87682cc 100644
--- a/src/main/java/io/github/dsheirer/alias/id/legacy/nonrecordable/NonRecordable.java
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/nonrecordable/NonRecordable.java
@@ -33,6 +33,12 @@ public AliasIDType getType()
return AliasIDType.NON_RECORDABLE;
}
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return true;
+ }
+
@Override
public boolean isValid()
{
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/nonrecordable/NonRecordableEditor.java b/src/main/java/io/github/dsheirer/alias/id/legacy/nonrecordable/NonRecordableEditor.java
deleted file mode 100644
index 51a3438a3..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/legacy/nonrecordable/NonRecordableEditor.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * ******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2018 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 io.github.dsheirer.alias.id.legacy.nonrecordable;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import java.awt.Color;
-import java.awt.Cursor;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-public class NonRecordableEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private static final String HELP_TEXT = ""
- + "
Audio Non-Recordable
"
- + "This identifies an alias as non-recordable.
"
- + "The alias can still be monitored but associated audio will "
- + "not be recorded.
"
- + "The default behavior when audio recording is enabled for a "
- + "channel is to record all aliases except any alias with a "
- + "non-recordable identifier";
-
- public NonRecordableEditor(AliasID aliasID)
- {
- initGUI();
-
- setItem(aliasID);
- }
-
- private void initGUI()
- {
- setLayout(new MigLayout("fill,wrap 1", "[]", "[][]"));
-
- add(new JLabel("Non-Recordable"), "wrap");
-
- JLabel help = new JLabel("Help ...");
- help.setForeground(Color.BLUE.brighter());
- help.setCursor(new Cursor(Cursor.HAND_CURSOR));
- help.addMouseListener(new MouseAdapter()
- {
- @Override
- public void mouseClicked(MouseEvent e)
- {
- JOptionPane.showMessageDialog(NonRecordableEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE);
- }
- });
- add(help, "align left");
- }
-
- @Override
- public void save()
- {
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/siteID/SiteID.java b/src/main/java/io/github/dsheirer/alias/id/legacy/siteID/SiteID.java
index a7616e7eb..fddaa6d97 100644
--- a/src/main/java/io/github/dsheirer/alias/id/legacy/siteID/SiteID.java
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/siteID/SiteID.java
@@ -29,6 +29,12 @@ public SiteID()
{
}
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return false;
+ }
+
@JacksonXmlProperty(isAttribute = true, localName = "site")
public String getSite()
{
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/siteID/SiteIDEditor.java b/src/main/java/io/github/dsheirer/alias/id/legacy/siteID/SiteIDEditor.java
deleted file mode 100644
index e7184ba5f..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/legacy/siteID/SiteIDEditor.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 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 io.github.dsheirer.alias.id.legacy.siteID;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-public class SiteIDEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private static final String HELP_TEXT = ""
- + "
Site Identifier
"
- + "LTR-Net: decimal (0-9) (e.g. 019) "
- + "MPT-1327: 5 digits (0-9) (e.g. 23619) "
- + "Passport: 3 digits (0-9) (e.g. 019) "
- + "P25: hex (0-9, A-F) format RR-SS where RR = RF Subsystem "
- + "and SS = Site Number (e.g. RFSS 1 Site 1F: 01-1F)"
- + "";
-
- private JTextField mTextField;
-
- public SiteIDEditor( AliasID aliasID )
- {
- initGUI();
-
- setItem( aliasID );
- }
-
- private void initGUI()
- {
- setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][]" ) );
-
- add( new JLabel( "Site ID:" ) );
- mTextField = new JTextField();
- mTextField.getDocument().addDocumentListener( this );
- mTextField.setToolTipText( HELP_TEXT );
- add( mTextField, "growx,push" );
-
- JLabel help = new JLabel( "Help ..." );
- help.setForeground( Color.BLUE.brighter() );
- help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
- help.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JOptionPane.showMessageDialog( SiteIDEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
- }
- } );
-
- add( help, "align left" );
- }
-
- public SiteID getSiteID()
- {
- if( getItem() instanceof SiteID )
- {
- return (SiteID)getItem();
- }
-
- return null;
- }
-
- @Override
- public void setItem( AliasID aliasID )
- {
- super.setItem( aliasID );
-
- SiteID siteID = getSiteID();
-
- if( siteID != null )
- {
- mTextField.setText( siteID.getSite() );
- }
-
- setModified( false );
-
- repaint();
- }
-
- @Override
- public void save()
- {
- SiteID siteID = getSiteID();
-
- if( siteID != null )
- {
- siteID.setSite( mTextField.getText() );
- }
-
- setModified( false );
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/talkgroup/LegacyTalkgroupID.java b/src/main/java/io/github/dsheirer/alias/id/legacy/talkgroup/LegacyTalkgroupID.java
index 8eb9553fa..296cd1bbc 100644
--- a/src/main/java/io/github/dsheirer/alias/id/legacy/talkgroup/LegacyTalkgroupID.java
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/talkgroup/LegacyTalkgroupID.java
@@ -38,6 +38,12 @@ public LegacyTalkgroupID(String talkgroup)
mTalkgroup = talkgroup;
}
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return false;
+ }
+
@JacksonXmlProperty(isAttribute = true, localName = "talkgroup")
public String getTalkgroup()
{
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/talkgroup/LegacyTalkgroupIDEditor.java b/src/main/java/io/github/dsheirer/alias/id/legacy/talkgroup/LegacyTalkgroupIDEditor.java
deleted file mode 100644
index 7d88b5876..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/legacy/talkgroup/LegacyTalkgroupIDEditor.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * ******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2018 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 io.github.dsheirer.alias.id.legacy.talkgroup;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JTextField;
-import java.awt.Color;
-import java.awt.Cursor;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-public class LegacyTalkgroupIDEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private static final String HELP_TEXT =
- "
Talkgroup Identifier
"
- + "P25: 4 or 6 hex characters (e.g. AB12 or ABC123) "
- + "LTR: A-HH-TTT where A=Area H=Home T=Talkgroup (0-01-128) "
- + "Passport: 5-digit number (12345 or 00023) "
- + " "
- + "Wildcard: use an asterisk (*) in place of each talkgroup digit (e.g. 0*1*5)"
- + "";
-
- private JTextField mTextField;
-
- public LegacyTalkgroupIDEditor(AliasID aliasID)
- {
- initGUI();
-
- setItem(aliasID);
- }
-
- private void initGUI()
- {
- setLayout(new MigLayout("fill,wrap 2", "[right][left]", "[][]"));
-
- add(new JLabel("Talkgroup:"));
-
- mTextField = new JTextField();
- mTextField.getDocument().addDocumentListener(this);
- mTextField.setToolTipText(HELP_TEXT);
- add(mTextField, "growx,push");
-
- JLabel help = new JLabel("Help ...");
- help.setForeground(Color.BLUE.brighter());
- help.setCursor(new Cursor(Cursor.HAND_CURSOR));
- help.addMouseListener(new MouseAdapter()
- {
- @Override
- public void mouseClicked(MouseEvent e)
- {
- JOptionPane.showMessageDialog(LegacyTalkgroupIDEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE);
- }
- });
- add(help, "align left");
- }
-
- public LegacyTalkgroupID getTalkgroupID()
- {
- if(getItem() instanceof LegacyTalkgroupID)
- {
- return (LegacyTalkgroupID)getItem();
- }
-
- return null;
- }
-
- @Override
- public void setItem(AliasID aliasID)
- {
- super.setItem(aliasID);
-
- LegacyTalkgroupID talkgroup = getTalkgroupID();
-
- if(talkgroup != null)
- {
- mTextField.setText(talkgroup.getTalkgroup());
- }
-
- setModified(false);
-
- repaint();
- }
-
- @Override
- public void save()
- {
- LegacyTalkgroupID talkgroup = getTalkgroupID();
-
- if(talkgroup != null)
- {
- talkgroup.setTalkgroup(mTextField.getText());
- }
-
- setModified(false);
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/uniqueID/UniqueID.java b/src/main/java/io/github/dsheirer/alias/id/legacy/uniqueID/UniqueID.java
index 249a66eef..a1a41f821 100644
--- a/src/main/java/io/github/dsheirer/alias/id/legacy/uniqueID/UniqueID.java
+++ b/src/main/java/io/github/dsheirer/alias/id/legacy/uniqueID/UniqueID.java
@@ -29,6 +29,12 @@ public UniqueID()
{
}
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return false;
+ }
+
@JacksonXmlProperty(isAttribute = true, localName = "uid")
public int getUid()
{
diff --git a/src/main/java/io/github/dsheirer/alias/id/legacy/uniqueID/UniqueIDEditor.java b/src/main/java/io/github/dsheirer/alias/id/legacy/uniqueID/UniqueIDEditor.java
deleted file mode 100644
index 41dcb6fa6..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/legacy/uniqueID/UniqueIDEditor.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 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 io.github.dsheirer.alias.id.legacy.uniqueID;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-public class UniqueIDEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private static final String HELP_TEXT = ""
- + "
LTR-Net Unique ID (UID)
"
- + "UID: identifier assigned to each radio in "
- + "the range 1 - 2097152"
- + "";
-
- private JTextField mTextField;
-
- public UniqueIDEditor( AliasID aliasID )
- {
- initGUI();
-
- setItem( aliasID );
- }
-
- private void initGUI()
- {
- setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][]" ) );
-
- add( new JLabel( "Unique ID:" ) );
- mTextField = new JTextField();
- mTextField.getDocument().addDocumentListener( this );
- mTextField.setToolTipText( HELP_TEXT );
- add( mTextField, "growx,push" );
-
- JLabel help = new JLabel( "Help ..." );
- help.setForeground( Color.BLUE.brighter() );
- help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
- help.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JOptionPane.showMessageDialog( UniqueIDEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
- }
- } );
- add( help, "align left" );
- }
-
- public UniqueID getUniqueID()
- {
- if( getItem() instanceof UniqueID )
- {
- return (UniqueID)getItem();
- }
-
- return null;
- }
-
- @Override
- public void setItem( AliasID aliasID )
- {
- super.setItem( aliasID );
-
- UniqueID uid = getUniqueID();
-
- if( uid != null )
- {
- mTextField.setText( String.valueOf( uid.getUid() ) );
- }
-
- setModified( false );
-
- repaint();
- }
-
- @Override
- public void save()
- {
- UniqueID uid = getUniqueID();
-
- if( uid != null )
- {
- int id = 0;
-
- try
- {
- id = Integer.parseInt( mTextField.getText() );
- }
- catch( Exception e )
- {
- //Do nothing, we couldn't parse the value
- }
-
- uid.setUid( id );
- }
-
- setModified( false );
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/lojack/LoJackFunctionAndID.java b/src/main/java/io/github/dsheirer/alias/id/lojack/LoJackFunctionAndID.java
index 8ec2802ea..efd44446a 100644
--- a/src/main/java/io/github/dsheirer/alias/id/lojack/LoJackFunctionAndID.java
+++ b/src/main/java/io/github/dsheirer/alias/id/lojack/LoJackFunctionAndID.java
@@ -32,6 +32,12 @@ public LoJackFunctionAndID()
{
}
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return false;
+ }
+
@JacksonXmlProperty(isAttribute = true, localName = "id")
public String getID()
{
@@ -41,6 +47,7 @@ public String getID()
public void setID(String id)
{
mID = id;
+ updateValueProperty();
}
@JacksonXmlProperty(isAttribute = true, localName = "function")
@@ -52,6 +59,7 @@ public LJ1200Message.Function getFunction()
public void setFunction(LJ1200Message.Function function)
{
mFunction = function;
+ updateValueProperty();
}
@Override
diff --git a/src/main/java/io/github/dsheirer/alias/id/lojack/LoJackIDEditor.java b/src/main/java/io/github/dsheirer/alias/id/lojack/LoJackIDEditor.java
deleted file mode 100644
index 85e9fc8e9..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/lojack/LoJackIDEditor.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 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 io.github.dsheirer.alias.id.lojack;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import io.github.dsheirer.module.decode.lj1200.LJ1200Message;
-import io.github.dsheirer.module.decode.lj1200.LJ1200Message.Function;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.*;
-import javax.swing.text.MaskFormatter;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-public class LoJackIDEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private JTextField mTextField;
-
- private JComboBox mFunctionCombo;
-
- private static final String HELP_TEXT = ""
- + "
LoJack Function and Identifier
"
- + "Function Code:1Y-SITE ID "
- + "ID: 5 numbers or characters (e.g. 1BN47) "
- + " "
- + "Wildcard: use an asterisk (*) to wildcard ID "
- + "characters (e.g. AB*CD or ***12 or *****)
"
- + "The middle character in a reply ID code identifies the "
- + "entity. Valid ID middle characters are: "
- + "
Tower: X,Y
"
- + "
Transponder: 0-9,A,C-H,J-N,P-W
"
- + "
Not Used: B,I,O,Z
"
- + "";
-
- public LoJackIDEditor( AliasID aliasID )
- {
- initGUI();
-
- setItem( aliasID );
- }
-
- private void initGUI()
- {
- setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][]" ) );
-
- add( new JLabel( "Function:" ) );
- mFunctionCombo = new JComboBox( Function.values() );
- mFunctionCombo.addActionListener( new ActionListener()
- {
- @Override
- public void actionPerformed( ActionEvent e )
- {
- setModified( true );
- }
- } );
- mFunctionCombo.setToolTipText( HELP_TEXT );
- add( mFunctionCombo, "growx, push" );
-
- add( new JLabel( "ID:" ) );
-
- MaskFormatter formatter = null;
-
- try
- {
- //Mask: any character or number, 5 places
- formatter = new MaskFormatter( "AAAAA" );
- }
- catch( Exception e )
- {
- //Do nothing, the mask was invalid
- }
-
- mTextField = new JFormattedTextField( formatter );
- mTextField.getDocument().addDocumentListener( this );
- mTextField.setToolTipText( HELP_TEXT );
- add( mTextField, "growx,push" );
-
- JLabel help = new JLabel( "Help ..." );
- help.setForeground( Color.BLUE.brighter() );
- help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
- help.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JOptionPane.showMessageDialog( LoJackIDEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
- }
- } );
- add( help, "align left" );
- }
-
- public LoJackFunctionAndID getLoJackID()
- {
- if( getItem() instanceof LoJackFunctionAndID )
- {
- return (LoJackFunctionAndID)getItem();
- }
-
- return null;
- }
-
- @Override
- public void setItem( AliasID aliasID )
- {
- super.setItem( aliasID );
-
- LoJackFunctionAndID lojack = getLoJackID();
-
- if( lojack != null )
- {
- mFunctionCombo.setSelectedItem( lojack.getFunction() );
- mTextField.setText( lojack.getID() );
- }
- else
- {
- mFunctionCombo.setSelectedItem( null );
- mTextField.setText( null );
- }
-
- setModified( false );
-
- repaint();
- }
-
- @Override
- public void save()
- {
- LoJackFunctionAndID lojack = getLoJackID();
-
- if( lojack != null )
- {
- lojack.setID( mTextField.getText() );
- lojack.setFunction( (Function)mFunctionCombo.getSelectedItem() );
- }
-
- setModified( false );
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/priority/Priority.java b/src/main/java/io/github/dsheirer/alias/id/priority/Priority.java
index 6184c8ffe..3dff5c5a1 100644
--- a/src/main/java/io/github/dsheirer/alias/id/priority/Priority.java
+++ b/src/main/java/io/github/dsheirer/alias/id/priority/Priority.java
@@ -39,6 +39,17 @@ public Priority()
{
}
+ public Priority(int priority)
+ {
+ mPriority = priority;
+ }
+
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return true;
+ }
+
@Override
public boolean isValid()
{
@@ -63,6 +74,7 @@ public int getPriority()
public void setPriority(int priority)
{
mPriority = priority;
+ updateValueProperty();
}
public String toString()
diff --git a/src/main/java/io/github/dsheirer/alias/id/priority/PriorityEditor.java b/src/main/java/io/github/dsheirer/alias/id/priority/PriorityEditor.java
deleted file mode 100644
index 767625c5d..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/priority/PriorityEditor.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 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 io.github.dsheirer.alias.id.priority;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.*;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import java.awt.*;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-public class PriorityEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- public static final String DO_NOT_MONITOR = "Do Not Monitor";
-
- private static final String HELP_TEXT = ""
- + "
Call Audio Priority
"
- + "Priority determines which calls have priority for playback "
- + "over your computer speakers, or designates an alias for "
- + "no-monitoring if you don't want to hear calls from an alias.
"
- + "Do Not Monitor: slide priority all the way to the right"
- + "";
-
- private JSlider mPrioritySlider;
- private JLabel mPrioritySliderLabel;
-
- public PriorityEditor( AliasID aliasID )
- {
- initGUI();
-
- setItem( aliasID );
- }
-
- private void initGUI()
- {
- setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][]" ) );
-
- mPrioritySlider = new JSlider( JSlider.HORIZONTAL,
- Priority.MIN_PRIORITY,
- Priority.MAX_PRIORITY + 1,
- Priority.MIN_PRIORITY );
-
- mPrioritySlider.setMajorTickSpacing( 20 );
- mPrioritySlider.setMinorTickSpacing( 5 );
- mPrioritySlider.setPaintTicks( true );
- mPrioritySlider.setLabelTable( mPrioritySlider.createStandardLabels( 20, 20 ) );
- mPrioritySlider.setPaintLabels( true );
- mPrioritySlider.addChangeListener( new ChangeListener()
- {
- @Override
- public void stateChanged( ChangeEvent e )
- {
- int priority = mPrioritySlider.getValue();
-
- if( priority == Priority.MAX_PRIORITY + 1 )
- {
- mPrioritySliderLabel.setText( "Priority: Do Not Monitor" );
- }
- else
- {
- mPrioritySliderLabel.setText( "Priority: " + priority );
- }
-
- setModified( true );
- }
- } );
- mPrioritySlider.setToolTipText( HELP_TEXT );
-
- mPrioritySliderLabel = new JLabel( "Priority: " + mPrioritySlider.getValue() + " " );
- add( mPrioritySliderLabel, "span,align center" );
- add( mPrioritySlider, "span,grow" );
-
- JLabel help = new JLabel( "Help ..." );
- help.setForeground( Color.BLUE.brighter() );
- help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
- help.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JOptionPane.showMessageDialog( PriorityEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
- }
- } );
- add( help, "align left" );
- }
-
- public Priority getPriority()
- {
- if( getItem() instanceof Priority )
- {
- return (Priority)getItem();
- }
-
- return null;
- }
-
- @Override
- public void setItem( AliasID aliasID )
- {
- super.setItem( aliasID );
-
- Priority priority = getPriority();
-
- if( priority != null )
- {
- int value = priority.getPriority();
-
- if( value == Priority.DO_NOT_MONITOR )
- {
- value = Priority.MAX_PRIORITY + 1;
- }
-
- mPrioritySlider.setValue( value );
- }
-
- setModified( false );
-
- repaint();
- }
-
- @Override
- public void save()
- {
- Priority priority = getPriority();
-
- if( priority != null )
- {
- int value = mPrioritySlider.getValue();
-
- if( value == Priority.MAX_PRIORITY + 1 )
- {
- value = Priority.DO_NOT_MONITOR;
- }
-
- priority.setPriority( value );
- }
-
- setModified( false );
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/radio/Radio.java b/src/main/java/io/github/dsheirer/alias/id/radio/Radio.java
index f266faa30..ef29788fc 100644
--- a/src/main/java/io/github/dsheirer/alias/id/radio/Radio.java
+++ b/src/main/java/io/github/dsheirer/alias/id/radio/Radio.java
@@ -25,14 +25,13 @@
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import io.github.dsheirer.alias.id.AliasID;
import io.github.dsheirer.alias.id.AliasIDType;
-import io.github.dsheirer.alias.id.talkgroup.TalkgroupFormat;
import io.github.dsheirer.alias.id.talkgroup.TalkgroupFormatter;
import io.github.dsheirer.protocol.Protocol;
/**
* Integer radio identifier with protocol.
*/
-public class Radio extends AliasID
+public class Radio extends AliasID implements Comparable
{
private Protocol mProtocol = Protocol.UNKNOWN;
private int mValue;
@@ -48,6 +47,12 @@ public Radio(Protocol protocol, int value)
mValue = value;
}
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return false;
+ }
+
@JacksonXmlProperty(isAttribute = true, localName = "value")
public int getValue()
{
@@ -57,6 +62,7 @@ public int getValue()
public void setValue(int value)
{
mValue = value;
+ updateValueProperty();
}
@JacksonXmlProperty(isAttribute = true, localName = "protocol")
@@ -68,6 +74,7 @@ public Protocol getProtocol()
public void setProtocol(Protocol protocol)
{
mProtocol = protocol;
+ updateValueProperty();
}
@Override
@@ -115,4 +122,22 @@ public AliasIDType getType()
{
return AliasIDType.RADIO_ID;
}
+
+ @Override
+ public int compareTo(Radio other)
+ {
+ if(other == null)
+ {
+ return -1;
+ }
+
+ if(getProtocol().equals(other.getProtocol()))
+ {
+ return Integer.compare(getValue(), other.getValue());
+ }
+ else
+ {
+ return getProtocol().compareTo(other.getProtocol());
+ }
+ }
}
diff --git a/src/main/java/io/github/dsheirer/alias/id/radio/RadioEditor.java b/src/main/java/io/github/dsheirer/alias/id/radio/RadioEditor.java
deleted file mode 100644
index ebf29ada5..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/radio/RadioEditor.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- *
- * * ******************************************************************************
- * * Copyright (C) 2014-2019 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 io.github.dsheirer.alias.id.radio;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import io.github.dsheirer.protocol.Protocol;
-import net.miginfocom.swing.MigLayout;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.swing.DefaultComboBoxModel;
-import javax.swing.JComboBox;
-import javax.swing.JFormattedTextField;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.text.MaskFormatter;
-import java.awt.Color;
-import java.awt.Cursor;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.text.ParseException;
-
-public class RadioEditor extends DocumentListenerEditor
-{
- private final static Logger mLog = LoggerFactory.getLogger(RadioEditor.class);
- private static final long serialVersionUID = 1L;
-
- private static final String VALID_CHARACTERS_FOR_ASTERISK_MASKS = "0123456789 ";
- private MaskFormatter mMaskFormatter = new MaskFormatter();
- private JComboBox mComboProtocol;
- private JFormattedTextField mRadioIdField;
-
-
- public RadioEditor(AliasID aliasID)
- {
- initGUI();
- setItem(aliasID);
- }
-
- private void initGUI()
- {
- setLayout(new MigLayout("fill,wrap 2", "[right][left]", "[][]"));
-
- add(new JLabel("Protocol:"));
-
- mComboProtocol = new JComboBox<>();
-
- DefaultComboBoxModel model = new DefaultComboBoxModel<>();
-
- for(Protocol protocol : Protocol.RADIO_ID_PROTOCOLS)
- {
- model.addElement(protocol);
- }
-
- mComboProtocol.setModel(model);
- mComboProtocol.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- Protocol protocol = (Protocol)mComboProtocol.getSelectedItem();
- updateEditor(protocol);
- setModified(true);
- }
- });
-
- add(mComboProtocol);
-
- add(new JLabel("Value:"));
-
- mRadioIdField = new JFormattedTextField(mMaskFormatter);
- mRadioIdField.getDocument().addDocumentListener(this);
- add(mRadioIdField, "growx,push");
-
- JLabel help = new JLabel("Help ...");
- help.setForeground(Color.BLUE.brighter());
- help.setCursor(new Cursor(Cursor.HAND_CURSOR));
- help.addMouseListener(new MouseAdapter()
- {
- @Override
- public void mouseClicked(MouseEvent e)
- {
- RadioFormat radioFormat = RadioFormat.get(getCurrentProtocol());
- JOptionPane.showMessageDialog(RadioEditor.this,
- radioFormat.getValidRangeHelpText(), "Help", JOptionPane.INFORMATION_MESSAGE);
- }
- });
- add(help, "align left");
- }
-
- private void updateEditor(Protocol protocol)
- {
- RadioFormat mask = RadioFormat.get(protocol);
- int currentValue = 0;
- Radio radio = getRadio();
-
- if(radio != null)
- {
- currentValue = radio.getValue();
- }
-
- try
- {
- mRadioIdField.setValue(null);
- mRadioIdField.setToolTipText(mask.getValidRangeHelpText());
- mMaskFormatter.setMask(mask.getMask());
- if(mask.getMask().contains("*"))
- {
- mMaskFormatter.setValidCharacters(VALID_CHARACTERS_FOR_ASTERISK_MASKS);
- }
- mRadioIdField.setValue(RadioFormatter.format(protocol, currentValue));
- }
- catch(ParseException pe)
- {
- mLog.error("Error applying talkgroup editor mask to mask formatter [" + mask.getMask() + "]");
- }
- }
-
- private Protocol getCurrentProtocol()
- {
- return mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
- }
-
- /**
- * Current talkgroup alias id
- */
- public Radio getRadio()
- {
- if(getItem() instanceof Radio)
- {
- return (Radio)getItem();
- }
-
- return null;
- }
-
- @Override
- public void setItem(AliasID aliasID)
- {
- super.setItem(aliasID);
-
- Radio radio = getRadio();
-
- if(radio != null)
- {
- Protocol currentProtocol = getCurrentProtocol();
- if(currentProtocol == radio.getProtocol())
- {
- updateEditor(radio.getProtocol());
- }
- mComboProtocol.getModel().setSelectedItem(radio.getProtocol());
-
- String formatted = RadioFormatter.format(radio.getProtocol(), radio.getValue());
- mRadioIdField.setValue(formatted);
- }
- else
- {
- mComboProtocol.getModel().setSelectedItem(Protocol.UNKNOWN);
- mRadioIdField.setValue(RadioFormatter.format(getCurrentProtocol(), 0));
- }
-
- setModified(false);
-
- repaint();
- }
-
- @Override
- public void save()
- {
- Radio radio = getRadio();
-
- if(radio != null)
- {
- Protocol protocol = mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
-
- if(protocol == null)
- {
- protocol = Protocol.UNKNOWN;
- }
-
- int value = -1;
-
- try
- {
- value = RadioFormatter.parse(protocol, mRadioIdField.getText());
- }
- catch(ParseException pe)
- {
- //ignore ... value is still -1 and outside valid value range
- }
-
- RadioFormat mask = RadioFormat.get(protocol);
-
- //Check for valid value within range ... notify user but allow value to persist
- if(value < mask.getMinimumValidValue() || value > mask.getMaximumValidValue())
- {
- String message = "Invalid value [" + mRadioIdField.getText() + "]. " + protocol.name() +
- " valid range is [" + mask.getValidRangeDescription() + "]";
-
- JOptionPane.showMessageDialog(RadioEditor.this, message, "Invalid Radio ID Value",
- JOptionPane.ERROR_MESSAGE);
- }
- else
- {
- radio.setValue(value);
- }
-
- radio.setProtocol(protocol);
- }
-
- setModified(false);
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/radio/RadioFormat.java b/src/main/java/io/github/dsheirer/alias/id/radio/RadioFormat.java
index af347f96e..54233f64f 100644
--- a/src/main/java/io/github/dsheirer/alias/id/radio/RadioFormat.java
+++ b/src/main/java/io/github/dsheirer/alias/id/radio/RadioFormat.java
@@ -36,6 +36,8 @@ public enum RadioFormat
{
APCO25("********", 0, 0xFFFFFF, "0 to 16,777,215",
"APCO25 valid range is 0 to 16,777,215"),
+ PASSPORT("********", 0, 0x7FFFFF, "0 to 8,388,607",
+ "PASSPORT valid range is 0 to 8,388,607"),
UNKNOWN("********", 1, 0xFFFFFF, "1 to 16,777,215",
"Unknown protocol valid value range is 1-16,777,215");
@@ -110,6 +112,8 @@ public static RadioFormat get(Protocol protocol)
{
case APCO25:
return APCO25;
+ case PASSPORT:
+ return PASSPORT;
default:
return UNKNOWN;
}
diff --git a/src/main/java/io/github/dsheirer/alias/id/radio/RadioFormatter.java b/src/main/java/io/github/dsheirer/alias/id/radio/RadioFormatter.java
index 1d542e9e0..3dc8f3338 100644
--- a/src/main/java/io/github/dsheirer/alias/id/radio/RadioFormatter.java
+++ b/src/main/java/io/github/dsheirer/alias/id/radio/RadioFormatter.java
@@ -22,8 +22,10 @@
package io.github.dsheirer.alias.id.radio;
+import io.github.dsheirer.preference.identifier.IntegerFormat;
import io.github.dsheirer.preference.identifier.talkgroup.APCO25TalkgroupFormatter;
-import io.github.dsheirer.preference.identifier.talkgroup.IntegerFormatter;
+import io.github.dsheirer.preference.identifier.talkgroup.AbstractIntegerFormatter;
+import io.github.dsheirer.preference.identifier.talkgroup.UnknownTalkgroupFormatter;
import io.github.dsheirer.protocol.Protocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,12 +41,12 @@
public class RadioFormatter
{
private final static Logger mLog = LoggerFactory.getLogger(RadioFormatter.class);
- private static Map mFormatterMap = new EnumMap<>(Protocol.class);
+ private static Map mFormatterMap = new EnumMap<>(Protocol.class);
static
{
mFormatterMap.put(Protocol.APCO25, new APCO25TalkgroupFormatter());
- mFormatterMap.put(Protocol.UNKNOWN, new IntegerFormatter());
+ mFormatterMap.put(Protocol.UNKNOWN, new UnknownTalkgroupFormatter());
}
public RadioFormatter()
@@ -56,7 +58,7 @@ public RadioFormatter()
*/
public static int parse(Protocol protocol, String value) throws ParseException
{
- IntegerFormatter formatter = mFormatterMap.get(protocol);
+ AbstractIntegerFormatter formatter = mFormatterMap.get(protocol);
if(formatter == null)
{
@@ -71,7 +73,7 @@ public static int parse(Protocol protocol, String value) throws ParseException
*/
public static String format(Protocol protocol, int value)
{
- IntegerFormatter formatter = mFormatterMap.get(protocol);
+ AbstractIntegerFormatter formatter = mFormatterMap.get(protocol);
if(formatter == null)
{
@@ -80,4 +82,19 @@ public static String format(Protocol protocol, int value)
return formatter.format(value);
}
+
+ /**
+ * Formats the integer value to the specified integer format using the protocol specific formatter
+ */
+ public static String format(Protocol protocol, int value, IntegerFormat format)
+ {
+ AbstractIntegerFormatter formatter = mFormatterMap.get(protocol);
+
+ if(formatter == null)
+ {
+ formatter = mFormatterMap.get(Protocol.UNKNOWN);
+ }
+
+ return formatter.format(value, format);
+ }
}
diff --git a/src/main/java/io/github/dsheirer/alias/id/radio/RadioRange.java b/src/main/java/io/github/dsheirer/alias/id/radio/RadioRange.java
index 207ce6657..44724fdba 100644
--- a/src/main/java/io/github/dsheirer/alias/id/radio/RadioRange.java
+++ b/src/main/java/io/github/dsheirer/alias/id/radio/RadioRange.java
@@ -30,7 +30,7 @@
/**
* Integer radio identifier range of values with protocol.
*/
-public class RadioRange extends AliasID
+public class RadioRange extends AliasID implements Comparable
{
private Protocol mProtocol = Protocol.UNKNOWN;
private int mMinRadio;
@@ -41,6 +41,12 @@ public RadioRange()
//No arg JAXB constructor
}
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return false;
+ }
+
/**
* Creates a radio range of from - to radio values (inclusive) for the specified protocol
* @param protocol for the radio range
@@ -63,6 +69,7 @@ public int getMinRadio()
public void setMinRadio(int minRadio)
{
mMinRadio = minRadio;
+ updateValueProperty();
}
@JacksonXmlProperty(isAttribute = true, localName = "max")
@@ -74,6 +81,7 @@ public int getMaxRadio()
public void setMaxRadio(int maxRadio)
{
mMaxRadio = maxRadio;
+ updateValueProperty();
}
@JacksonXmlProperty(isAttribute = true, localName = "protocol")
@@ -99,7 +107,8 @@ public boolean isValid()
return radioFormat.getMinimumValidValue() <= mMinRadio &&
mMinRadio <= radioFormat.getMaximumValidValue() &&
radioFormat.getMinimumValidValue() <= mMaxRadio &&
- mMaxRadio <= radioFormat.getMaximumValidValue();
+ mMaxRadio <= radioFormat.getMaximumValidValue() &&
+ mMinRadio < mMaxRadio;
}
public String toString()
@@ -142,6 +151,13 @@ public boolean contains(int radioValue)
return getMinRadio() <= radioValue && radioValue <= getMaxRadio();
}
+ @Override
+ public boolean overlaps(AliasID other)
+ {
+ return other instanceof RadioRange && overlaps((RadioRange)other);
+ }
+
+
/**
* Indicates if this talkgroup range overlaps the talkgroup range argument.
* @param radioRange to check for overlap
@@ -163,4 +179,30 @@ public AliasIDType getType()
{
return AliasIDType.RADIO_ID_RANGE;
}
+
+
+ @Override
+ public int compareTo(RadioRange other)
+ {
+ if(other == null)
+ {
+ return -1;
+ }
+
+ if(getProtocol().equals(other.getProtocol()))
+ {
+ if(getMinRadio() == other.getMinRadio())
+ {
+ return Integer.compare(getMaxRadio(), other.getMaxRadio());
+ }
+ else
+ {
+ return Integer.compare(getMinRadio(), other.getMinRadio());
+ }
+ }
+ else
+ {
+ return getProtocol().compareTo(other.getProtocol());
+ }
+ }
}
diff --git a/src/main/java/io/github/dsheirer/alias/id/radio/RadioRangeEditor.java b/src/main/java/io/github/dsheirer/alias/id/radio/RadioRangeEditor.java
deleted file mode 100644
index 37c2b7773..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/radio/RadioRangeEditor.java
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- *
- * * ******************************************************************************
- * * Copyright (C) 2014-2019 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 io.github.dsheirer.alias.id.radio;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import io.github.dsheirer.protocol.Protocol;
-import net.miginfocom.swing.MigLayout;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.swing.DefaultComboBoxModel;
-import javax.swing.JComboBox;
-import javax.swing.JFormattedTextField;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.text.MaskFormatter;
-import java.awt.Color;
-import java.awt.Cursor;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.text.ParseException;
-
-public class RadioRangeEditor extends DocumentListenerEditor
-{
- private final static Logger mLog = LoggerFactory.getLogger(RadioRangeEditor.class);
- private static final long serialVersionUID = 1L;
-
- private static final String VALID_CHARACTERS_FOR_ASTERISK_MASKS = "0123456789 ";
- private MaskFormatter mMaskFormatter = new MaskFormatter();
- private JComboBox mComboProtocol;
- private JFormattedTextField mMinRadioField;
- private JFormattedTextField mMaxRadioField;
-
- public RadioRangeEditor(AliasID aliasID)
- {
- initGUI();
-
- setItem(aliasID);
- }
-
- private void initGUI()
- {
- setLayout(new MigLayout("fill,wrap 2", "[right][left]", "[][]"));
-
- add(new JLabel("Protocol:"));
-
- mComboProtocol = new JComboBox();
-
- DefaultComboBoxModel model = new DefaultComboBoxModel<>();
-
- for(Protocol protocol : Protocol.RADIO_ID_PROTOCOLS)
- {
- model.addElement(protocol);
- }
-
- mComboProtocol.setModel(model);
- mComboProtocol.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- Protocol protocol = (Protocol)mComboProtocol.getSelectedItem();
- updateEditor(protocol);
- setModified(true);
- }
- });
-
- add(mComboProtocol);
-
- add(new JLabel("Min:"));
-
- mMinRadioField = new JFormattedTextField(mMaskFormatter);
- mMinRadioField.getDocument().addDocumentListener(this);
- add(mMinRadioField, "growx,push");
-
- add(new JLabel("Max:"));
-
- mMaxRadioField = new JFormattedTextField(mMaskFormatter);
- mMaxRadioField.getDocument().addDocumentListener(this);
- add(mMaxRadioField, "growx,push");
-
- JLabel help = new JLabel("Help ...");
- help.setForeground(Color.BLUE.brighter());
- help.setCursor(new Cursor(Cursor.HAND_CURSOR));
- help.addMouseListener(new MouseAdapter()
- {
- @Override
- public void mouseClicked(MouseEvent e)
- {
- RadioFormat radioFormat = RadioFormat.get(getCurrentProtocol());
- JOptionPane.showMessageDialog(RadioRangeEditor.this,
- radioFormat.getValidRangeHelpText(), "Help", JOptionPane.INFORMATION_MESSAGE);
- }
- });
- add(help, "align left");
- }
-
- private void updateEditor(Protocol protocol)
- {
- RadioFormat mask = RadioFormat.get(protocol);
- int currentMinValue = 0;
- int currentMaxValue = 0;
- RadioRange radioRange = getRadioRange();
-
- if(radioRange != null)
- {
- currentMinValue = radioRange.getMinRadio();
- currentMaxValue = radioRange.getMaxRadio();
- }
-
- try
- {
- mMinRadioField.setValue(null);
- mMaxRadioField.setValue(null);
-
- mMinRadioField.setToolTipText(mask.getValidRangeHelpText());
- mMaxRadioField.setToolTipText(mask.getValidRangeHelpText());
- mMaskFormatter.setMask(mask.getMask());
- if(mask.getMask().contains("*"))
- {
- mMaskFormatter.setValidCharacters(VALID_CHARACTERS_FOR_ASTERISK_MASKS);
- }
-
- mMinRadioField.setValue(RadioFormatter.format(protocol, currentMinValue));
- mMaxRadioField.setValue(RadioFormatter.format(protocol, currentMaxValue));
- }
- catch(ParseException pe)
- {
- mLog.error("Error applying radio editor mask to mask formatter [" + mask.getMask() + "]");
- }
- }
-
- private Protocol getCurrentProtocol()
- {
- return mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
- }
-
-
-
- public RadioRange getRadioRange()
- {
- if(getItem() instanceof RadioRange)
- {
- return (RadioRange)getItem();
- }
-
- return null;
- }
-
- @Override
- public void setItem(AliasID aliasID)
- {
- super.setItem(aliasID);
-
- RadioRange radioRange = getRadioRange();
-
- updateEditor(radioRange.getProtocol());
-
- if(radioRange != null)
- {
- mComboProtocol.getModel().setSelectedItem(radioRange.getProtocol());
- String minFormatted = RadioFormatter.format(radioRange.getProtocol(), radioRange.getMinRadio());
- mMinRadioField.setValue(minFormatted);
- String maxFormatted = RadioFormatter.format(radioRange.getProtocol(), radioRange.getMaxRadio());
- mMaxRadioField.setValue(maxFormatted);
- }
- else
- {
- mComboProtocol.getModel().setSelectedItem(Protocol.UNKNOWN);
- mMinRadioField.setValue(RadioFormatter.format(getCurrentProtocol(), 0));
- mMaxRadioField.setValue(RadioFormatter.format(getCurrentProtocol(), 0));
- }
-
- setModified(false);
-
- repaint();
- }
-
- @Override
- public void save()
- {
- RadioRange radioRange = getRadioRange();
-
- if(radioRange != null)
- {
- Protocol protocol = mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
-
- if(protocol == null)
- {
- protocol = Protocol.UNKNOWN;
- }
-
- radioRange.setProtocol(protocol);
-
- int minValue = -1;
- int maxValue = -1;
-
- try
- {
- minValue = RadioFormatter.parse(protocol, mMinRadioField.getText());
- }
- catch(ParseException pe)
- {
- //ignore ... value is still -1 and outside valid value range
- }
-
- try
- {
- maxValue = RadioFormatter.parse(protocol, mMaxRadioField.getText());
- }
- catch(ParseException pe)
- {
- //ignore ... value is still -1 and outside valid value range
- }
-
- RadioFormat mask = RadioFormat.get(protocol);
-
- //Check for valid value within range ... notify user but allow value to persist
- if(minValue < mask.getMinimumValidValue() || minValue > mask.getMaximumValidValue())
- {
- String message = "Invalid minimum value [" + mMinRadioField.getText() + "]. " + protocol.name() +
- " valid range is [" + mask.getValidRangeDescription() + "]";
-
- JOptionPane.showMessageDialog(RadioRangeEditor.this, message,
- "Invalid Radio Value", JOptionPane.ERROR_MESSAGE);
- }
- else
- {
- radioRange.setMinRadio(minValue);
- }
-
- //Check for valid value within range ... notify user but allow value to persist
- if(maxValue < mask.getMinimumValidValue() || maxValue > mask.getMaximumValidValue())
- {
- String message = "Invalid maximum value [" + mMaxRadioField.getText() + "]. " + protocol.name() +
- " valid range is [" + mask.getValidRangeDescription() + "]";
-
- JOptionPane.showMessageDialog(RadioRangeEditor.this, message,
- "Invalid Radio Value", JOptionPane.ERROR_MESSAGE);
- }
- else
- {
- radioRange.setMaxRadio(maxValue);
- }
-
- radioRange.setProtocol(protocol);
- }
-
- setModified(false);
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/record/Record.java b/src/main/java/io/github/dsheirer/alias/id/record/Record.java
index 85ab55ca2..201f7d90e 100644
--- a/src/main/java/io/github/dsheirer/alias/id/record/Record.java
+++ b/src/main/java/io/github/dsheirer/alias/id/record/Record.java
@@ -36,6 +36,12 @@ public AliasIDType getType()
return AliasIDType.RECORD;
}
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return true;
+ }
+
@Override
public boolean isValid()
{
diff --git a/src/main/java/io/github/dsheirer/alias/id/record/RecordEditor.java b/src/main/java/io/github/dsheirer/alias/id/record/RecordEditor.java
deleted file mode 100644
index 91b8c8090..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/record/RecordEditor.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * ******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2018 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 io.github.dsheirer.alias.id.record;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import java.awt.Color;
-import java.awt.Cursor;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-public class RecordEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private static final String HELP_TEXT = ""
- + "
Record Audio
"
- + "Any audio associated with this alias will be recorded.
";
-
- public RecordEditor(AliasID aliasID )
- {
- initGUI();
-
- setItem( aliasID );
- }
-
- private void initGUI()
- {
- setLayout( new MigLayout( "fill,wrap 1", "[]", "[][]" ) );
-
- add( new JLabel( "Record Audio" ), "wrap" );
-
- JLabel help = new JLabel( "Help ..." );
- help.setForeground( Color.BLUE.brighter() );
- help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
- help.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JOptionPane.showMessageDialog( RecordEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
- }
- } );
- add( help, "align left" );
- }
-
- @Override
- public void save()
- {
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/status/StatusID.java b/src/main/java/io/github/dsheirer/alias/id/status/StatusID.java
deleted file mode 100644
index 24050b1a7..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/status/StatusID.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*******************************************************************************
- * 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 io.github.dsheirer.alias.id.status;
-
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.alias.id.AliasIDType;
-
-public class StatusID extends AliasID
-{
- private int mStatus;
-
- public StatusID()
- {
- }
-
- @JacksonXmlProperty(isAttribute = true, localName = "status")
- public int getStatus()
- {
- return mStatus;
- }
-
- public void setStatus(int status)
- {
- this.mStatus = status;
- }
-
- @Override
- public boolean isValid()
- {
- return true;
- }
-
- public String toString()
- {
- return "Status: " + String.format("%03d", mStatus);
- }
-
- @Override
- public boolean matches(AliasID id)
- {
- boolean retVal = false;
-
- if(id instanceof StatusID)
- {
- StatusID statusId = (StatusID)id;
-
- retVal = (mStatus == statusId.getStatus());
- }
-
- return retVal;
- }
-
- @JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
- @Override
- public AliasIDType getType()
- {
- return AliasIDType.STATUS;
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/status/StatusIDEditor.java b/src/main/java/io/github/dsheirer/alias/id/status/StatusIDEditor.java
deleted file mode 100644
index 69a4b9966..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/status/StatusIDEditor.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 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 io.github.dsheirer.alias.id.status;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import net.miginfocom.swing.MigLayout;
-
-import javax.swing.*;
-import javax.swing.text.MaskFormatter;
-import java.awt.*;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-public class StatusIDEditor extends DocumentListenerEditor
-{
- private static final long serialVersionUID = 1L;
-
- private static final String HELP_TEXT = ""
- + "
Status Identifier
"
- + "Status numbers are used in some protocols like Fleetsync.
"
- + "The status number is assigned a meaning in the radio. You "
- + "can assign a 3 digit status code (use leading zeros) to an "
- + "alias where the alias contains the status meaning.
"
- + "Status:001 engine start"
- + "";
-
- private JTextField mTextField;
-
- public StatusIDEditor( AliasID aliasID )
- {
- initGUI();
-
- setItem( aliasID );
- }
-
- private void initGUI()
- {
- setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][]" ) );
-
- add( new JLabel( "Status:" ) );
-
- MaskFormatter formatter = null;
-
- try
- {
- //Mask: 3 digits
- formatter = new MaskFormatter( "###" );
- }
- catch( Exception e )
- {
- //Do nothing, the mask was invalid
- }
-
- mTextField = new JFormattedTextField( formatter );
- mTextField.getDocument().addDocumentListener( this );
- mTextField.setToolTipText( HELP_TEXT );
- add( mTextField, "growx,push" );
-
- JLabel help = new JLabel( "Help ..." );
- help.setForeground( Color.BLUE.brighter() );
- help.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
- help.addMouseListener( new MouseAdapter()
- {
- @Override
- public void mouseClicked( MouseEvent e )
- {
- JOptionPane.showMessageDialog( StatusIDEditor.this,
- HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
- }
- } );
- add( help, "align left" );
- }
-
- public StatusID getStatusID()
- {
- if( getItem() instanceof StatusID )
- {
- return (StatusID)getItem();
- }
-
- return null;
- }
-
- @Override
- public void setItem( AliasID aliasID )
- {
- super.setItem( aliasID );
-
- StatusID statusID = getStatusID();
-
- if( statusID != null )
- {
- mTextField.setText( String.format( "%03d", statusID.getStatus() ) );
- }
-
- setModified( false );
-
- repaint();
- }
-
- @Override
- public void save()
- {
- StatusID statusID = getStatusID();
-
- if( statusID != null )
- {
- int status = 0;
-
- try
- {
- status = Integer.valueOf( mTextField.getText() );
- }
- catch( Exception e )
- {
- //Do nothing, we couldn't parse the value
- }
-
- statusID.setStatus( status );
- }
-
- setModified( false );
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/status/UnitStatusID.java b/src/main/java/io/github/dsheirer/alias/id/status/UnitStatusID.java
new file mode 100644
index 000000000..78f5f4c55
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/alias/id/status/UnitStatusID.java
@@ -0,0 +1,88 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2020 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 io.github.dsheirer.alias.id.status;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import io.github.dsheirer.alias.id.AliasID;
+import io.github.dsheirer.alias.id.AliasIDType;
+
+/**
+ * Unit Status
+ */
+public class UnitStatusID extends AliasID
+{
+ private int mStatus;
+
+ public UnitStatusID()
+ {
+ }
+
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return false;
+ }
+
+ @JacksonXmlProperty(isAttribute = true, localName = "status")
+ public int getStatus()
+ {
+ return mStatus;
+ }
+
+ public void setStatus(int status)
+ {
+ mStatus = status;
+ updateValueProperty();
+ }
+
+ @Override
+ public boolean isValid()
+ {
+ return true;
+ }
+
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Unit Status: ").append(String.format("%03d", mStatus));
+ return sb.toString();
+ }
+
+ @Override
+ public boolean matches(AliasID id)
+ {
+ boolean retVal = false;
+
+ if(id instanceof UnitStatusID)
+ {
+ UnitStatusID userStatusId = (UnitStatusID)id;
+
+ retVal = (mStatus == userStatusId.getStatus());
+ }
+
+ return retVal;
+ }
+
+ @JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
+ @Override
+ public AliasIDType getType()
+ {
+ return AliasIDType.UNIT_STATUS;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/alias/id/status/UserStatusID.java b/src/main/java/io/github/dsheirer/alias/id/status/UserStatusID.java
new file mode 100644
index 000000000..3794969e8
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/alias/id/status/UserStatusID.java
@@ -0,0 +1,88 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2020 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 io.github.dsheirer.alias.id.status;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import io.github.dsheirer.alias.id.AliasID;
+import io.github.dsheirer.alias.id.AliasIDType;
+
+/**
+ * User Status
+ */
+public class UserStatusID extends AliasID
+{
+ private int mStatus;
+
+ public UserStatusID()
+ {
+ }
+
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return false;
+ }
+
+ @JacksonXmlProperty(isAttribute = true, localName = "status")
+ public int getStatus()
+ {
+ return mStatus;
+ }
+
+ public void setStatus(int status)
+ {
+ mStatus = status;
+ updateValueProperty();
+ }
+
+ @Override
+ public boolean isValid()
+ {
+ return true;
+ }
+
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("User Status: ").append(String.format("%03d", mStatus));
+ return sb.toString();
+ }
+
+ @Override
+ public boolean matches(AliasID id)
+ {
+ boolean retVal = false;
+
+ if(id instanceof UserStatusID)
+ {
+ UserStatusID userStatusId = (UserStatusID)id;
+
+ retVal = (mStatus == userStatusId.getStatus());
+ }
+
+ return retVal;
+ }
+
+ @JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
+ @Override
+ public AliasIDType getType()
+ {
+ return AliasIDType.STATUS;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/alias/id/talkgroup/Talkgroup.java b/src/main/java/io/github/dsheirer/alias/id/talkgroup/Talkgroup.java
index a10a713c8..b38e67051 100644
--- a/src/main/java/io/github/dsheirer/alias/id/talkgroup/Talkgroup.java
+++ b/src/main/java/io/github/dsheirer/alias/id/talkgroup/Talkgroup.java
@@ -24,12 +24,15 @@
import io.github.dsheirer.alias.id.AliasID;
import io.github.dsheirer.alias.id.AliasIDType;
import io.github.dsheirer.protocol.Protocol;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Integer talkgroup identifier with protocol.
*/
-public class Talkgroup extends AliasID
+public class Talkgroup extends AliasID implements Comparable
{
+ private static final Logger mLog = LoggerFactory.getLogger(Talkgroup.class);
private Protocol mProtocol = Protocol.UNKNOWN;
private int mValue;
@@ -44,6 +47,12 @@ public Talkgroup(Protocol protocol, int value)
mValue = value;
}
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return false;
+ }
+
@JacksonXmlProperty(isAttribute = true, localName = "value")
public int getValue()
{
@@ -53,6 +62,7 @@ public int getValue()
public void setValue(int value)
{
mValue = value;
+ updateValueProperty();
}
@JacksonXmlProperty(isAttribute = true, localName = "protocol")
@@ -64,6 +74,7 @@ public Protocol getProtocol()
public void setProtocol(Protocol protocol)
{
mProtocol = protocol;
+ updateValueProperty();
}
@Override
@@ -82,7 +93,18 @@ public String toString()
{
StringBuilder sb = new StringBuilder();
- sb.append("Talkgroup:").append(TalkgroupFormatter.format(mProtocol, mValue));
+ String talkgroup = null;
+
+ try
+ {
+ talkgroup = TalkgroupFormatter.format(mProtocol, mValue);
+ }
+ catch(Exception e)
+ {
+ mLog.error("Error formatting Talkgroup Protocol [" + mProtocol + "] value [" + mValue + "]", e);
+ }
+
+ sb.append("Talkgroup:").append(talkgroup != null ? talkgroup : "error");
sb.append(" Protocol:").append((mProtocol));
if(!isValid())
@@ -111,4 +133,22 @@ public AliasIDType getType()
{
return AliasIDType.TALKGROUP;
}
+
+ @Override
+ public int compareTo(Talkgroup other)
+ {
+ if(other == null)
+ {
+ return -1;
+ }
+
+ if(getProtocol().equals(other.getProtocol()))
+ {
+ return Integer.compare(getValue(), other.getValue());
+ }
+ else
+ {
+ return getProtocol().compareTo(other.getProtocol());
+ }
+ }
}
diff --git a/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupEditor.java b/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupEditor.java
deleted file mode 100644
index 9d0a37c35..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupEditor.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * ******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2019 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 io.github.dsheirer.alias.id.talkgroup;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import io.github.dsheirer.protocol.Protocol;
-import net.miginfocom.swing.MigLayout;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.swing.DefaultComboBoxModel;
-import javax.swing.JComboBox;
-import javax.swing.JFormattedTextField;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.text.MaskFormatter;
-import java.awt.Color;
-import java.awt.Cursor;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.text.ParseException;
-
-public class TalkgroupEditor extends DocumentListenerEditor
-{
- private final static Logger mLog = LoggerFactory.getLogger(TalkgroupEditor.class);
- private static final long serialVersionUID = 1L;
-
- private static final String VALID_CHARACTERS_FOR_ASTERISK_MASKS = "0123456789 ";
- private MaskFormatter mMaskFormatter = new MaskFormatter();
- private JComboBox mComboProtocol;
- private JFormattedTextField mTalkgroupField;
-
-
- public TalkgroupEditor(AliasID aliasID)
- {
- initGUI();
- setItem(aliasID);
- }
-
- private void initGUI()
- {
- setLayout(new MigLayout("fill,wrap 2", "[right][left]", "[][]"));
-
- add(new JLabel("Protocol:"));
-
- mComboProtocol = new JComboBox<>();
-
- DefaultComboBoxModel model = new DefaultComboBoxModel<>();
-
- for(Protocol protocol : Protocol.TALKGROUP_PROTOCOLS)
- {
- model.addElement(protocol);
- }
-
- mComboProtocol.setModel(model);
- mComboProtocol.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- Protocol protocol = (Protocol)mComboProtocol.getSelectedItem();
- updateEditor(protocol);
- setModified(true);
- }
- });
-
- add(mComboProtocol);
-
- add(new JLabel("Value:"));
-
- mTalkgroupField = new JFormattedTextField(mMaskFormatter);
- mTalkgroupField.getDocument().addDocumentListener(this);
- add(mTalkgroupField, "growx,push");
-
- JLabel help = new JLabel("Help ...");
- help.setForeground(Color.BLUE.brighter());
- help.setCursor(new Cursor(Cursor.HAND_CURSOR));
- help.addMouseListener(new MouseAdapter()
- {
- @Override
- public void mouseClicked(MouseEvent e)
- {
- TalkgroupFormat talkgroupFormat = TalkgroupFormat.get(getCurrentProtocol());
- JOptionPane.showMessageDialog(TalkgroupEditor.this,
- talkgroupFormat.getValidRangeHelpText(), "Help", JOptionPane.INFORMATION_MESSAGE);
- }
- });
- add(help, "align left");
- }
-
- private void updateEditor(Protocol protocol)
- {
- TalkgroupFormat mask = TalkgroupFormat.get(protocol);
- int currentValue = 0;
- Talkgroup talkgroup = getTalkgroup();
-
- if(talkgroup != null)
- {
- currentValue = talkgroup.getValue();
- }
-
- try
- {
- mTalkgroupField.setValue(null);
- mTalkgroupField.setToolTipText(mask.getValidRangeHelpText());
- mMaskFormatter.setMask(mask.getMask());
- if(mask.getMask().contains("*"))
- {
- mMaskFormatter.setValidCharacters(VALID_CHARACTERS_FOR_ASTERISK_MASKS);
- }
- mTalkgroupField.setValue(TalkgroupFormatter.format(protocol, currentValue));
- }
- catch(ParseException pe)
- {
- mLog.error("Error applying talkgroup editor mask to mask formatter [" + mask.getMask() + "]");
- }
- }
-
- private Protocol getCurrentProtocol()
- {
- return mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
- }
-
- /**
- * Current talkgroup alias id
- */
- public Talkgroup getTalkgroup()
- {
- if(getItem() instanceof Talkgroup)
- {
- return (Talkgroup)getItem();
- }
-
- return null;
- }
-
- @Override
- public void setItem(AliasID aliasID)
- {
- super.setItem(aliasID);
-
- Talkgroup talkgroup = getTalkgroup();
-
- if(talkgroup != null)
- {
- Protocol currentProtocol = getCurrentProtocol();
- if(currentProtocol == talkgroup.getProtocol())
- {
- updateEditor(talkgroup.getProtocol());
- }
- mComboProtocol.getModel().setSelectedItem(talkgroup.getProtocol());
-
- String formatted = TalkgroupFormatter.format(talkgroup.getProtocol(), talkgroup.getValue());
- mTalkgroupField.setValue(formatted);
- }
- else
- {
- mComboProtocol.getModel().setSelectedItem(Protocol.UNKNOWN);
- mTalkgroupField.setValue(TalkgroupFormatter.format(getCurrentProtocol(), 0));
- }
-
- setModified(false);
-
- repaint();
- }
-
- @Override
- public void save()
- {
- Talkgroup talkgroup = getTalkgroup();
-
- if(talkgroup != null)
- {
- Protocol protocol = mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
-
- if(protocol == null)
- {
- protocol = Protocol.UNKNOWN;
- }
-
- int value = -1;
-
- try
- {
- value = TalkgroupFormatter.parse(protocol, mTalkgroupField.getText());
- }
- catch(ParseException pe)
- {
- //ignore ... value is still -1 and outside valid value range
- }
-
- TalkgroupFormat mask = TalkgroupFormat.get(protocol);
-
- //Check for valid value within range ... notify user but allow value to persist
- if(value < mask.getMinimumValidValue() || value > mask.getMaximumValidValue())
- {
- String message = "Invalid value [" + mTalkgroupField.getText() + "]. " + protocol.name() +
- " valid range is [" + mask.getValidRangeDescription() + "]";
-
- JOptionPane.showMessageDialog(TalkgroupEditor.this, message, "Invalid Talkgroup Value",
- JOptionPane.ERROR_MESSAGE);
- }
- else
- {
- talkgroup.setValue(value);
- }
-
- talkgroup.setProtocol(protocol);
- }
-
- setModified(false);
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupFormat.java b/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupFormat.java
index 236a35e30..3ecc3adf5 100644
--- a/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupFormat.java
+++ b/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupFormat.java
@@ -36,9 +36,9 @@ public enum TalkgroupFormat
{
APCO25("********", 0, 0xFFFFFF, "0 to 65,535",
"APCO25 talkgroup valid range is 0 to 65,535"),
- FLEETSYNC("###-####", 1, 0x7FFFFF, "001-0001 to 127-8192",
+ FLEETSYNC("###-####", 0, 0x7FFFFF, "001-0001 to 127-8192",
"Fleetsync valid ranges are 1-127(prefix) and 1-8192(ident) (ie. 001-0001 to 127-8192)"),
- LTR("##-###", 257, 5375, "01-001 to 20-255",
+ LTR("##-###", 0x101, 0x3FFF, "01-001 to 20-255",
"LTR valid ranges are 1-20(repeater) and 1-255(talkgroup) (ie. 01-001 to 20-255)"),
MDC1200("*****", 1, 0xFFFF, "1 to 65,535",
"MDC-1200 valid value range is 1-65,535"),
@@ -124,7 +124,6 @@ public static TalkgroupFormat get(Protocol protocol)
return FLEETSYNC;
case LTR:
case LTR_NET:
- case LTR_STANDARD:
return LTR;
case MDC1200:
return MDC1200;
diff --git a/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupFormatter.java b/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupFormatter.java
index 46c964e55..7e1b94d2d 100644
--- a/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupFormatter.java
+++ b/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupFormatter.java
@@ -20,13 +20,15 @@
package io.github.dsheirer.alias.id.talkgroup;
+import io.github.dsheirer.preference.identifier.IntegerFormat;
import io.github.dsheirer.preference.identifier.talkgroup.APCO25TalkgroupFormatter;
+import io.github.dsheirer.preference.identifier.talkgroup.AbstractIntegerFormatter;
import io.github.dsheirer.preference.identifier.talkgroup.FleetsyncTalkgroupFormatter;
-import io.github.dsheirer.preference.identifier.talkgroup.IntegerFormatter;
import io.github.dsheirer.preference.identifier.talkgroup.LTRTalkgroupFormatter;
import io.github.dsheirer.preference.identifier.talkgroup.MDC1200TalkgroupFormatter;
import io.github.dsheirer.preference.identifier.talkgroup.MPT1327TalkgroupFormatter;
import io.github.dsheirer.preference.identifier.talkgroup.PassportTalkgroupFormatter;
+import io.github.dsheirer.preference.identifier.talkgroup.UnknownTalkgroupFormatter;
import io.github.dsheirer.protocol.Protocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,7 +44,7 @@
public class TalkgroupFormatter
{
private final static Logger mLog = LoggerFactory.getLogger(TalkgroupFormatter.class);
- private static Map mFormatterMap = new EnumMap<>(Protocol.class);
+ private static Map mFormatterMap = new EnumMap<>(Protocol.class);
static
{
@@ -51,11 +53,10 @@ public class TalkgroupFormatter
LTRTalkgroupFormatter ltr = new LTRTalkgroupFormatter();
mFormatterMap.put(Protocol.LTR, ltr);
mFormatterMap.put(Protocol.LTR_NET, ltr);
- mFormatterMap.put(Protocol.LTR_STANDARD, ltr);
mFormatterMap.put(Protocol.MDC1200, new MDC1200TalkgroupFormatter());
mFormatterMap.put(Protocol.MPT1327, new MPT1327TalkgroupFormatter());
mFormatterMap.put(Protocol.PASSPORT, new PassportTalkgroupFormatter());
- mFormatterMap.put(Protocol.UNKNOWN, new IntegerFormatter());
+ mFormatterMap.put(Protocol.UNKNOWN, new UnknownTalkgroupFormatter());
}
public TalkgroupFormatter()
@@ -67,7 +68,7 @@ public TalkgroupFormatter()
*/
public static int parse(Protocol protocol, String value) throws ParseException
{
- IntegerFormatter formatter = mFormatterMap.get(protocol);
+ AbstractIntegerFormatter formatter = mFormatterMap.get(protocol);
if(formatter == null)
{
@@ -82,7 +83,7 @@ public static int parse(Protocol protocol, String value) throws ParseException
*/
public static String format(Protocol protocol, int value)
{
- IntegerFormatter formatter = mFormatterMap.get(protocol);
+ AbstractIntegerFormatter formatter = mFormatterMap.get(protocol);
if(formatter == null)
{
@@ -91,4 +92,19 @@ public static String format(Protocol protocol, int value)
return formatter.format(value);
}
+
+ /**
+ * Formats the integer value to the specified integer format using the protocol specific formatter
+ */
+ public static String format(Protocol protocol, int value, IntegerFormat format)
+ {
+ AbstractIntegerFormatter formatter = mFormatterMap.get(protocol);
+
+ if(formatter == null)
+ {
+ formatter = mFormatterMap.get(Protocol.UNKNOWN);
+ }
+
+ return formatter.format(value, format);
+ }
}
diff --git a/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupRange.java b/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupRange.java
index a0df981c0..01cf6c93b 100644
--- a/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupRange.java
+++ b/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupRange.java
@@ -28,7 +28,7 @@
/**
* Integer talkgroup identifier range of values with protocol.
*/
-public class TalkgroupRange extends AliasID
+public class TalkgroupRange extends AliasID implements Comparable
{
private Protocol mProtocol = Protocol.UNKNOWN;
private int mMinTalkgroup;
@@ -52,6 +52,12 @@ public TalkgroupRange(Protocol protocol, int minTalkgroup, int maxTalkgroup)
mMaxTalkgroup = maxTalkgroup;
}
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ return false;
+ }
+
@JacksonXmlProperty(isAttribute = true, localName = "min")
public int getMinTalkgroup()
{
@@ -61,6 +67,7 @@ public int getMinTalkgroup()
public void setMinTalkgroup(int minTalkgroup)
{
mMinTalkgroup = minTalkgroup;
+ updateValueProperty();
}
@JacksonXmlProperty(isAttribute = true, localName = "max")
@@ -72,6 +79,7 @@ public int getMaxTalkgroup()
public void setMaxTalkgroup(int maxTalkgroup)
{
mMaxTalkgroup = maxTalkgroup;
+ updateValueProperty();
}
@JacksonXmlProperty(isAttribute = true, localName = "protocol")
@@ -83,6 +91,7 @@ public Protocol getProtocol()
public void setProtocol(Protocol protocol)
{
mProtocol = protocol;
+ updateValueProperty();
}
@Override
@@ -97,7 +106,8 @@ public boolean isValid()
return talkgroupFormat.getMinimumValidValue() <= mMinTalkgroup &&
mMinTalkgroup <= talkgroupFormat.getMaximumValidValue() &&
talkgroupFormat.getMinimumValidValue() <= mMaxTalkgroup &&
- mMaxTalkgroup <= talkgroupFormat.getMaximumValidValue();
+ mMaxTalkgroup <= talkgroupFormat.getMaximumValidValue() &&
+ mMinTalkgroup < mMaxTalkgroup;
}
public String toString()
@@ -140,6 +150,12 @@ public boolean contains(int talkgroupValue)
return getMinTalkgroup() <= talkgroupValue && talkgroupValue <= getMaxTalkgroup();
}
+ @Override
+ public boolean overlaps(AliasID other)
+ {
+ return other instanceof TalkgroupRange && overlaps((TalkgroupRange)other);
+ }
+
/**
* Indicates if this talkgroup range overlaps the talkgroup range argument.
* @param talkgroupRange to check for overlap
@@ -161,4 +177,29 @@ public AliasIDType getType()
{
return AliasIDType.TALKGROUP_RANGE;
}
+
+ @Override
+ public int compareTo(TalkgroupRange other)
+ {
+ if(other == null)
+ {
+ return -1;
+ }
+
+ if(getProtocol().equals(other.getProtocol()))
+ {
+ if(getMinTalkgroup() == other.getMinTalkgroup())
+ {
+ return Integer.compare(getMaxTalkgroup(), other.getMaxTalkgroup());
+ }
+ else
+ {
+ return Integer.compare(getMinTalkgroup(), other.getMinTalkgroup());
+ }
+ }
+ else
+ {
+ return getProtocol().compareTo(other.getProtocol());
+ }
+ }
}
diff --git a/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupRangeEditor.java b/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupRangeEditor.java
deleted file mode 100644
index dca54176a..000000000
--- a/src/main/java/io/github/dsheirer/alias/id/talkgroup/TalkgroupRangeEditor.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * ******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2018 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 io.github.dsheirer.alias.id.talkgroup;
-
-import io.github.dsheirer.alias.id.AliasID;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import io.github.dsheirer.protocol.Protocol;
-import net.miginfocom.swing.MigLayout;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.swing.DefaultComboBoxModel;
-import javax.swing.JComboBox;
-import javax.swing.JFormattedTextField;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.text.MaskFormatter;
-import java.awt.Color;
-import java.awt.Cursor;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.text.ParseException;
-
-public class TalkgroupRangeEditor extends DocumentListenerEditor
-{
- private final static Logger mLog = LoggerFactory.getLogger(TalkgroupRangeEditor.class);
- private static final long serialVersionUID = 1L;
-
- private static final String VALID_CHARACTERS_FOR_ASTERISK_MASKS = "0123456789 ";
- private MaskFormatter mMaskFormatter = new MaskFormatter();
- private JComboBox mComboProtocol;
- private JFormattedTextField mMinTalkgroupField;
- private JFormattedTextField mMaxTalkgroupField;
-
- public TalkgroupRangeEditor(AliasID aliasID)
- {
- initGUI();
-
- setItem(aliasID);
- }
-
- private void initGUI()
- {
- setLayout(new MigLayout("fill,wrap 2", "[right][left]", "[][]"));
-
- add(new JLabel("Protocol:"));
-
- mComboProtocol = new JComboBox();
-
- DefaultComboBoxModel model = new DefaultComboBoxModel<>();
-
- for(Protocol protocol : Protocol.TALKGROUP_PROTOCOLS)
- {
- model.addElement(protocol);
- }
-
- mComboProtocol.setModel(model);
- mComboProtocol.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- Protocol protocol = (Protocol)mComboProtocol.getSelectedItem();
- updateEditor(protocol);
- setModified(true);
- }
- });
-
- add(mComboProtocol);
-
- add(new JLabel("Min:"));
-
- mMinTalkgroupField = new JFormattedTextField(mMaskFormatter);
- mMinTalkgroupField.getDocument().addDocumentListener(this);
- add(mMinTalkgroupField, "growx,push");
-
- add(new JLabel("Max:"));
-
- mMaxTalkgroupField = new JFormattedTextField(mMaskFormatter);
- mMaxTalkgroupField.getDocument().addDocumentListener(this);
- add(mMaxTalkgroupField, "growx,push");
-
- JLabel help = new JLabel("Help ...");
- help.setForeground(Color.BLUE.brighter());
- help.setCursor(new Cursor(Cursor.HAND_CURSOR));
- help.addMouseListener(new MouseAdapter()
- {
- @Override
- public void mouseClicked(MouseEvent e)
- {
- TalkgroupFormat talkgroupFormat = TalkgroupFormat.get(getCurrentProtocol());
- JOptionPane.showMessageDialog(TalkgroupRangeEditor.this,
- talkgroupFormat.getValidRangeHelpText(), "Help", JOptionPane.INFORMATION_MESSAGE);
- }
- });
- add(help, "align left");
- }
-
- private void updateEditor(Protocol protocol)
- {
- TalkgroupFormat mask = TalkgroupFormat.get(protocol);
- int currentMinValue = 0;
- int currentMaxValue = 0;
- TalkgroupRange talkgroupRange = getTalkgroupRange();
-
- if(talkgroupRange != null)
- {
- currentMinValue = talkgroupRange.getMinTalkgroup();
- currentMaxValue = talkgroupRange.getMaxTalkgroup();
- }
-
- try
- {
- mMinTalkgroupField.setValue(null);
- mMaxTalkgroupField.setValue(null);
-
- mMinTalkgroupField.setToolTipText(mask.getValidRangeHelpText());
- mMaxTalkgroupField.setToolTipText(mask.getValidRangeHelpText());
- mMaskFormatter.setMask(mask.getMask());
- if(mask.getMask().contains("*"))
- {
- mMaskFormatter.setValidCharacters(VALID_CHARACTERS_FOR_ASTERISK_MASKS);
- }
-
- mMinTalkgroupField.setValue(TalkgroupFormatter.format(protocol, currentMinValue));
- mMaxTalkgroupField.setValue(TalkgroupFormatter.format(protocol, currentMaxValue));
- }
- catch(ParseException pe)
- {
- mLog.error("Error applying talkgroup editor mask to mask formatter [" + mask.getMask() + "]");
- }
- }
-
- private Protocol getCurrentProtocol()
- {
- return mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
- }
-
-
-
- public TalkgroupRange getTalkgroupRange()
- {
- if(getItem() instanceof TalkgroupRange)
- {
- return (TalkgroupRange)getItem();
- }
-
- return null;
- }
-
- @Override
- public void setItem(AliasID aliasID)
- {
- super.setItem(aliasID);
-
- TalkgroupRange talkgroupRange = getTalkgroupRange();
-
- updateEditor(talkgroupRange.getProtocol());
-
- if(talkgroupRange != null)
- {
- mComboProtocol.getModel().setSelectedItem(talkgroupRange.getProtocol());
- String minFormatted = TalkgroupFormatter.format(talkgroupRange.getProtocol(), talkgroupRange.getMinTalkgroup());
- mMinTalkgroupField.setValue(minFormatted);
- String maxFormatted = TalkgroupFormatter.format(talkgroupRange.getProtocol(), talkgroupRange.getMaxTalkgroup());
- mMaxTalkgroupField.setValue(maxFormatted);
- }
- else
- {
- mComboProtocol.getModel().setSelectedItem(Protocol.UNKNOWN);
- mMinTalkgroupField.setValue(TalkgroupFormatter.format(getCurrentProtocol(), 0));
- mMaxTalkgroupField.setValue(TalkgroupFormatter.format(getCurrentProtocol(), 0));
- }
-
- setModified(false);
-
- repaint();
- }
-
- @Override
- public void save()
- {
- TalkgroupRange talkgroupRange = getTalkgroupRange();
-
- if(talkgroupRange != null)
- {
- Protocol protocol = mComboProtocol.getItemAt(mComboProtocol.getSelectedIndex());
-
- if(protocol == null)
- {
- protocol = Protocol.UNKNOWN;
- }
-
- talkgroupRange.setProtocol(protocol);
-
- int minValue = -1;
- int maxValue = -1;
-
- try
- {
- minValue = TalkgroupFormatter.parse(protocol, mMinTalkgroupField.getText());
- }
- catch(ParseException pe)
- {
- //ignore ... value is still -1 and outside valid value range
- }
-
- try
- {
- maxValue = TalkgroupFormatter.parse(protocol, mMaxTalkgroupField.getText());
- }
- catch(ParseException pe)
- {
- //ignore ... value is still -1 and outside valid value range
- }
-
- TalkgroupFormat mask = TalkgroupFormat.get(protocol);
-
- //Check for valid value within range ... notify user but allow value to persist
- if(minValue < mask.getMinimumValidValue() || minValue > mask.getMaximumValidValue())
- {
- String message = "Invalid minimum value [" + mMinTalkgroupField.getText() + "]. " + protocol.name() +
- " valid range is [" + mask.getValidRangeDescription() + "]";
-
- JOptionPane.showMessageDialog(TalkgroupRangeEditor.this, message,
- "Invalid Talkgroup Value", JOptionPane.ERROR_MESSAGE);
- }
- else
- {
- talkgroupRange.setMinTalkgroup(minValue);
- }
-
- //Check for valid value within range ... notify user but allow value to persist
- if(maxValue < mask.getMinimumValidValue() || maxValue > mask.getMaximumValidValue())
- {
- String message = "Invalid maximum value [" + mMaxTalkgroupField.getText() + "]. " + protocol.name() +
- " valid range is [" + mask.getValidRangeDescription() + "]";
-
- JOptionPane.showMessageDialog(TalkgroupRangeEditor.this, message,
- "Invalid Talkgroup Value", JOptionPane.ERROR_MESSAGE);
- }
- else
- {
- talkgroupRange.setMaxTalkgroup(maxValue);
- }
-
- talkgroupRange.setProtocol(protocol);
- }
-
- setModified(false);
- }
-}
diff --git a/src/main/java/io/github/dsheirer/alias/id/tone/TonesID.java b/src/main/java/io/github/dsheirer/alias/id/tone/TonesID.java
new file mode 100644
index 000000000..4d1937997
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/alias/id/tone/TonesID.java
@@ -0,0 +1,150 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2020 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 io.github.dsheirer.alias.id.tone;
+
+import io.github.dsheirer.alias.id.AliasID;
+import io.github.dsheirer.alias.id.AliasIDType;
+import io.github.dsheirer.identifier.tone.Tone;
+import io.github.dsheirer.identifier.tone.ToneSequence;
+import javafx.collections.ListChangeListener;
+
+import java.util.List;
+
+/**
+ * Tone sequence alias identifier. This is used for matching tone sequences produced by the AMBE audio CODEC. Some
+ * examples include DTMF dialed numbers, KNOX tones, 2-Tone, Tone-outs, etc.
+ */
+public class TonesID extends AliasID implements ListChangeListener
+{
+ private ToneSequence mToneSequence;
+
+ public TonesID()
+ {
+ setToneSequence(new ToneSequence());
+ //Empty serialization constructor
+ }
+
+ /**
+ * Constructs an instance with the specified tone sequence
+ */
+ public TonesID(ToneSequence toneSequence)
+ {
+ setToneSequence(toneSequence);
+ }
+
+ @Override
+ public AliasIDType getType()
+ {
+ return AliasIDType.TONES;
+ }
+
+ /**
+ * List of tones that define this identifier
+ */
+
+ public ToneSequence getToneSequence()
+ {
+ return mToneSequence;
+ }
+
+ /**
+ * Sets the tone sequence(s) for this ID
+ */
+ public void setToneSequence(ToneSequence toneSequence)
+ {
+ if(mToneSequence != null)
+ {
+ mToneSequence.tonesProperty().removeListener(this);
+ }
+
+ mToneSequence = toneSequence;
+ mToneSequence.tonesProperty().addListener(this);
+ }
+
+ /**
+ * Indicates if the other id is a tones identifier and has the exact same sequence of tones. However, it does not
+ * compare each of the tone duration value.
+ * @param id to check for match
+ * @return true if the identifiers match
+ */
+ @Override
+ public boolean matches(AliasID id)
+ {
+ boolean match = true;
+
+ if(mToneSequence.getTones().isEmpty() || !(id instanceof TonesID))
+ {
+ match = false;
+ }
+ else
+ {
+ List otherTones = ((TonesID)id).getToneSequence().getTones();
+ List thisTones = mToneSequence.getTones();
+
+ if(thisTones.size() == otherTones.size())
+ {
+ for(int x = 0; x < thisTones.size(); x++)
+ {
+ if(thisTones.get(x).getAmbeTone() != otherTones.get(x).getAmbeTone())
+ {
+ match = false;
+ continue;
+ }
+ }
+ }
+ else
+ {
+ match = false;
+ }
+ }
+
+ return match;
+ }
+
+ @Override
+ public boolean isValid()
+ {
+ return getToneSequence() != null && getToneSequence().hasTones();
+ }
+
+ @Override
+ public boolean isAudioIdentifier()
+ {
+ //This is not an audio identifier in the context that this method is used for.
+ return false;
+ }
+
+ @Override
+ public String toString()
+ {
+ if(getToneSequence() != null)
+ {
+ return "Tones: " + getToneSequence().toString();
+ }
+
+ return "Tones: (empty)";
+ }
+
+ @Override
+ public void onChanged(Change extends Tone> c)
+ {
+ updateValueProperty();
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/audio/AbstractAudioModule.java b/src/main/java/io/github/dsheirer/audio/AbstractAudioModule.java
index a253ff17e..5165a5917 100644
--- a/src/main/java/io/github/dsheirer/audio/AbstractAudioModule.java
+++ b/src/main/java/io/github/dsheirer/audio/AbstractAudioModule.java
@@ -125,8 +125,15 @@ protected void addAudio(float[] audioBuffer)
audioSegment.linkTo(previous);
}
- audioSegment.addAudio(audioBuffer);
- mAudioSampleCount += audioBuffer.length;
+ try
+ {
+ audioSegment.addAudio(audioBuffer);
+ mAudioSampleCount += audioBuffer.length;
+ }
+ catch(Exception e)
+ {
+ closeAudioSegment();
+ }
}
/**
diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/AudioBroadcaster.java b/src/main/java/io/github/dsheirer/audio/broadcast/AudioBroadcaster.java
index 59770cb52..341871a81 100644
--- a/src/main/java/io/github/dsheirer/audio/broadcast/AudioBroadcaster.java
+++ b/src/main/java/io/github/dsheirer/audio/broadcast/AudioBroadcaster.java
@@ -25,6 +25,8 @@
import io.github.dsheirer.identifier.IdentifierCollection;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.util.ThreadPool;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
import org.apache.commons.math3.util.FastMath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -52,7 +54,7 @@ public abstract class AudioBroadcaster implements Listener
private ISilenceGenerator mSilenceGenerator;
private Listener mBroadcastEventListener;
- private BroadcastState mBroadcastState = BroadcastState.READY;
+ private ObjectProperty mBroadcastState = new SimpleObjectProperty<>(BroadcastState.READY);
private int mStreamedAudioCount = 0;
private int mAgedOffAudioCount = 0;
@@ -90,6 +92,18 @@ public AudioBroadcaster(BroadcastConfiguration broadcastConfiguration)
mSilenceGenerator = BroadcastFactory.getSilenceGenerator(broadcastConfiguration.getBroadcastFormat());
}
+ /**
+ * Observable broadcast state property
+ */
+ public ObjectProperty broadcastStateProperty()
+ {
+ return mBroadcastState;
+ }
+
+ public void dispose()
+ {
+ }
+
/**
* Broadcast binary audio data frames or sequences.
*/
@@ -251,18 +265,18 @@ public void broadcast(BroadcastEvent event)
*/
protected void setBroadcastState(BroadcastState state)
{
- if(mBroadcastState != state)
+ if(mBroadcastState.get() != state)
{
if(state == BroadcastState.CONNECTED || state == BroadcastState.DISCONNECTED)
{
mLog.info("[" + getStreamName() + "] status: " + state);
}
- mBroadcastState = state;
+ mBroadcastState.setValue(state);
broadcast(new BroadcastEvent(this, BroadcastEvent.Event.BROADCASTER_STATE_CHANGE));
- if(mBroadcastState.isErrorState())
+ if(mBroadcastState.get().isErrorState())
{
stop();
}
@@ -291,7 +305,7 @@ protected void setBroadcastState(BroadcastState state)
*/
public BroadcastState getBroadcastState()
{
- return mBroadcastState;
+ return mBroadcastState.get();
}
/**
diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastConfiguration.java b/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastConfiguration.java
index 220416e57..33e463a6a 100644
--- a/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastConfiguration.java
+++ b/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastConfiguration.java
@@ -1,21 +1,24 @@
-/*******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2016 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.
+ * * ******************************************************************************
+ * * Copyright (C) 2014-2020 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
+ * * *****************************************************************************
*
- * 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 io.github.dsheirer.audio.broadcast;
import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -26,6 +29,17 @@
import io.github.dsheirer.audio.broadcast.icecast.IcecastConfiguration;
import io.github.dsheirer.audio.broadcast.shoutcast.v1.ShoutcastV1Configuration;
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ShoutcastV2Configuration;
+import javafx.beans.Observable;
+import javafx.beans.binding.Bindings;
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.IntegerProperty;
+import javafx.beans.property.LongProperty;
+import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.property.SimpleIntegerProperty;
+import javafx.beans.property.SimpleLongProperty;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+import javafx.util.Callback;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
@@ -39,18 +53,32 @@
@JacksonXmlRootElement(localName = "stream")
public abstract class BroadcastConfiguration
{
+ // Static unique channel identifier tracking
+ private static int UNIQUE_ID = 0;
+
private BroadcastFormat mBroadcastFormat = BroadcastFormat.MP3;
- private String mName;
- private String mHost;
- private int mPort;
- private String mPassword;
- private long mDelay;
- private long mMaximumRecordingAge = 10 * 60 * 1000; //10 minutes default
- private boolean mEnabled = true;
+ private StringProperty mName = new SimpleStringProperty();
+ private StringProperty mHost = new SimpleStringProperty();
+ private IntegerProperty mPort = new SimpleIntegerProperty(80);
+ private StringProperty mPassword = new SimpleStringProperty();
+ private LongProperty mDelay = new SimpleLongProperty();
+ private LongProperty mMaximumRecordingAge = new SimpleLongProperty(10 * 60 * 1000); //10 minutes default
+ private BooleanProperty mEnabled = new SimpleBooleanProperty(false);
+ private BooleanProperty mValid;
+ private int mId = ++UNIQUE_ID;
public BroadcastConfiguration()
{
- //No-arg constructor required for JAXB
+ }
+
+ /**
+ * Unique identifier for this configuration.
+ * Note: unique ids are generated at runtime and have no persistent context across sessions.
+ */
+ @JsonIgnore
+ public int getId()
+ {
+ return mId;
}
/**
@@ -66,6 +94,76 @@ public BroadcastConfiguration(BroadcastFormat format)
mBroadcastFormat = format;
}
+ /**
+ * Stream name
+ */
+ public StringProperty nameProperty()
+ {
+ return mName;
+ }
+
+ /**
+ * Server host name
+ */
+ public StringProperty hostProperty()
+ {
+ return mHost;
+ }
+
+ /**
+ * Feed port
+ */
+ public IntegerProperty portProperty()
+ {
+ return mPort;
+ }
+
+ /**
+ * Feed password
+ */
+ public StringProperty passwordProperty()
+ {
+ return mPassword;
+ }
+
+ /**
+ * Delay introduced for each recording before streaming
+ */
+ public LongProperty delayProperty()
+ {
+ return mDelay;
+ }
+
+ /**
+ * Maximum allowable age of a recording to stream. Recordings that exceed this threshold will be aged off.
+ */
+ public LongProperty maximumRecordingAgeProperty()
+ {
+ return mMaximumRecordingAge;
+ }
+
+ /**
+ * Stream enabled property
+ */
+ public BooleanProperty enabledProperty()
+ {
+ return mEnabled;
+ }
+
+ /**
+ * Configuration valid property
+ */
+ public BooleanProperty validProperty()
+ {
+ if(mValid == null)
+ {
+ mValid = new SimpleBooleanProperty();
+ mValid.bind(Bindings.and(Bindings.isNotNull(mHost), Bindings.greaterThan(mPort, 0)));
+ }
+
+ return mValid;
+ }
+
/**
* Broadcast server type
*/
@@ -83,7 +181,7 @@ private void setBroadcastServerType(BroadcastServerType type)
@JacksonXmlProperty(isAttribute = true, localName = "name")
public String getName()
{
- return mName;
+ return mName.get();
}
/**
@@ -93,7 +191,7 @@ public String getName()
*/
public void setName(String name)
{
- mName = name;
+ mName.set(name);
}
/**
@@ -110,7 +208,7 @@ public boolean hasName()
@JacksonXmlProperty(isAttribute = true, localName = "host")
public String getHost()
{
- return mHost;
+ return mHost.get();
}
/**
@@ -120,7 +218,7 @@ public String getHost()
*/
public void setHost(String host)
{
- mHost = host;
+ mHost.set(host);
}
/**
@@ -137,7 +235,7 @@ public boolean hasHost()
@JacksonXmlProperty(isAttribute = true, localName = "port")
public int getPort()
{
- return mPort;
+ return mPort.get();
}
/**
@@ -147,7 +245,7 @@ public int getPort()
*/
public void setPort(int port)
{
- mPort = port;
+ mPort.set(port);
}
/**
@@ -155,7 +253,7 @@ public void setPort(int port)
*/
public boolean hasPort()
{
- return mPort > 0;
+ return mPort.get() > 0;
}
@JsonIgnore
@@ -170,7 +268,7 @@ public SocketAddress getAddress()
@JacksonXmlProperty(isAttribute = true, localName = "password")
public String getPassword()
{
- return mPassword;
+ return mPassword.get();
}
/**
@@ -180,7 +278,7 @@ public String getPassword()
*/
public void setPassword(String password)
{
- mPassword = password;
+ mPassword.set(password);
}
/**
@@ -211,7 +309,7 @@ public void setBroadcastFormat(BroadcastFormat format)
@JacksonXmlProperty(isAttribute = true, localName = "delay")
public long getDelay()
{
- return mDelay;
+ return mDelay.get();
}
/**
@@ -220,7 +318,7 @@ public long getDelay()
*/
public void setDelay(long delay)
{
- mDelay = delay;
+ mDelay.set(delay);
}
/**
@@ -231,7 +329,7 @@ public void setDelay(long delay)
@JacksonXmlProperty(isAttribute = true, localName = "maximum_recording_age")
public long getMaximumRecordingAge()
{
- return mMaximumRecordingAge;
+ return mMaximumRecordingAge.get();
}
/**
@@ -241,7 +339,7 @@ public long getMaximumRecordingAge()
*/
public void setMaximumRecordingAge(long age)
{
- mMaximumRecordingAge = age;
+ mMaximumRecordingAge.set(age);
}
/**
@@ -250,12 +348,12 @@ public void setMaximumRecordingAge(long age)
@JacksonXmlProperty(isAttribute = true, localName = "enabled")
public boolean isEnabled()
{
- return mEnabled;
+ return mEnabled.get();
}
public void setEnabled(boolean enabled)
{
- mEnabled = enabled;
+ mEnabled.set(enabled);
}
@Override
@@ -302,6 +400,15 @@ public int hashCode()
@JsonIgnore
public boolean isValid()
{
- return mHost != null && mPort > 0;
+ return validProperty().get();
+ }
+
+ /**
+ * Creates an observable property extractor for use with observable lists to detect changes internal to this object.
+ */
+ public static Callback extractor()
+ {
+ return (BroadcastConfiguration b) -> new Observable[] {b.nameProperty(), b.hostProperty(), b.portProperty(),
+ b.passwordProperty(), b.maximumRecordingAgeProperty(), b.delayProperty(), b.enabledProperty()};
}
}
diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastConfigurationEditor.java b/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastConfigurationEditor.java
deleted file mode 100644
index bb5b9a182..000000000
--- a/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastConfigurationEditor.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2016 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 io.github.dsheirer.audio.broadcast;
-
-import io.github.dsheirer.alias.AliasModel;
-import io.github.dsheirer.gui.editor.DocumentListenerEditor;
-import io.github.dsheirer.icon.IconManager;
-
-import javax.swing.*;
-
-public abstract class BroadcastConfigurationEditor extends DocumentListenerEditor
-{
- protected IconManager mIconManager;
- protected BroadcastModel mBroadcastModel;
- protected AliasModel mAliasModel;
-
- public BroadcastConfigurationEditor(BroadcastModel broadcastModel, AliasModel aliasModel, IconManager iconManager)
- {
- mBroadcastModel = broadcastModel;
- mAliasModel = aliasModel;
- mIconManager = iconManager;
- }
-
- /**
- * Updates the configuration with the new name and prompts the user to update any aliases that have a broadcast
- * channel alias id with the old name to update to the new name.
- *
- * @param broadcastConfiguration to assign a new channel name
- * @param newName to assign to the broadcast configuration. Note: assumes that validateConfiguration() has been
- * invoked to verify that newName is non-null and non-empty
- */
- protected void updateConfigurationName(BroadcastConfiguration broadcastConfiguration, String newName)
- {
- String previousName = broadcastConfiguration.getName();
-
- if(previousName == null || previousName.isEmpty())
- {
- broadcastConfiguration.setName(newName);
- return;
- }
-
- if(!previousName.equals(newName))
- {
- mAliasModel.renameBroadcastChannel(previousName, newName);
- broadcastConfiguration.setName(newName);
- }
- }
-
- /**
- * Validates a text field control for a non-null, non-empty value
- * @param field to validate
- * @param title to use for error dialog
- * @param message to use for error dialog
- * @return true if field contains a non-null, non-empty value
- */
- protected boolean validateTextField(JTextField field, String title, String message)
- {
- String text = field.getText();
-
- if(text == null || text.isEmpty())
- {
- JOptionPane.showMessageDialog(BroadcastConfigurationEditor.this, message, title,
- JOptionPane.ERROR_MESSAGE);
-
- field.requestFocus();
- return false;
- }
-
- return true;
- }
-
- /**
- * Validates the text field control that contains an integer value for non-null, non-empty and within the
- * specified min/max valid range.
- * @param field to validate
- * @param title to use for error dialog
- * @param message to use for error dialog
- * @param minValid value
- * @param maxValid value
- * @return true if field contains a non-null, non-empty value within the valid min/max range
- */
- protected boolean validateIntegerTextField(JTextField field, String title, String message, int minValid, int maxValid)
- {
- if(validateTextField(field, title, message))
- {
- String text = field.getText();
-
- try
- {
- int value = Integer.parseInt(text);
-
- if(minValid <= value && value <= maxValid)
- {
- return true;
- }
- }
- catch(Exception e)
- {
- //Do nothing, we couldn't parse the number value
- }
-
- JOptionPane.showMessageDialog(BroadcastConfigurationEditor.this, message, title,
- JOptionPane.ERROR_MESSAGE);
-
- field.requestFocus();
- }
-
- return false;
- }
-}
diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastFactory.java b/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastFactory.java
index d41484820..85a55e90c 100644
--- a/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastFactory.java
+++ b/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastFactory.java
@@ -23,27 +23,18 @@
import io.github.dsheirer.alias.AliasModel;
import io.github.dsheirer.audio.broadcast.broadcastify.BroadcastifyConfiguration;
-import io.github.dsheirer.audio.broadcast.broadcastify.BroadcastifyConfigurationEditor;
import io.github.dsheirer.audio.broadcast.icecast.IcecastHTTPAudioBroadcaster;
import io.github.dsheirer.audio.broadcast.icecast.IcecastHTTPConfiguration;
-import io.github.dsheirer.audio.broadcast.icecast.IcecastHTTPConfigurationEditor;
import io.github.dsheirer.audio.broadcast.icecast.IcecastTCPAudioBroadcaster;
import io.github.dsheirer.audio.broadcast.icecast.IcecastTCPConfiguration;
-import io.github.dsheirer.audio.broadcast.icecast.IcecastTCPConfigurationEditor;
import io.github.dsheirer.audio.broadcast.shoutcast.v1.ShoutcastV1AudioBroadcaster;
import io.github.dsheirer.audio.broadcast.shoutcast.v1.ShoutcastV1Configuration;
-import io.github.dsheirer.audio.broadcast.shoutcast.v1.ShoutcastV1ConfigurationEditor;
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ShoutcastV2AudioBroadcaster;
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ShoutcastV2Configuration;
-import io.github.dsheirer.audio.broadcast.shoutcast.v2.ShoutcastV2ConfigurationEditor;
import io.github.dsheirer.audio.convert.IAudioConverter;
import io.github.dsheirer.audio.convert.ISilenceGenerator;
import io.github.dsheirer.audio.convert.MP3AudioConverter;
import io.github.dsheirer.audio.convert.MP3SilenceGenerator;
-import io.github.dsheirer.gui.editor.Editor;
-import io.github.dsheirer.gui.editor.EmptyEditor;
-import io.github.dsheirer.icon.IconManager;
-import io.github.dsheirer.preference.UserPreferences;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -140,48 +131,6 @@ public static BroadcastConfiguration getConfiguration(BroadcastServerType server
return null;
}
- /**
- * Constructs an editor for the specified broadcastAudio configuration
- *
- * @param configuration to modify or view
- * @param broadcastModel model for broadcastAudio configurations
- * @return an editor for the specified broadcastAudio configuration
- */
- public static Editor getEditor(UserPreferences userPreferences,
- BroadcastConfiguration configuration,
- BroadcastModel broadcastModel,
- AliasModel aliasModel,
- IconManager iconManager)
- {
- Editor editor;
-
- switch(configuration.getBroadcastServerType())
- {
- case BROADCASTIFY:
- editor = new BroadcastifyConfigurationEditor(userPreferences, broadcastModel, aliasModel, iconManager);
- break;
- case ICECAST_TCP:
- editor = new IcecastTCPConfigurationEditor(broadcastModel, aliasModel, iconManager);
- break;
- case ICECAST_HTTP:
- editor = new IcecastHTTPConfigurationEditor(broadcastModel, aliasModel, iconManager);
- break;
- case SHOUTCAST_V1:
- editor = new ShoutcastV1ConfigurationEditor(broadcastModel, aliasModel, iconManager);
- break;
- case SHOUTCAST_V2:
- editor = new ShoutcastV2ConfigurationEditor(broadcastModel, aliasModel, iconManager);
- break;
- default:
- editor = new EmptyEditor();
- break;
- }
-
- editor.setItem(configuration);
-
- return editor;
- }
-
public static ISilenceGenerator getSilenceGenerator(BroadcastFormat format)
{
switch(format)
diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastModel.java b/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastModel.java
index 0f9d11739..50be596b6 100644
--- a/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastModel.java
+++ b/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastModel.java
@@ -1,7 +1,7 @@
/*
*
* * ******************************************************************************
- * * Copyright (C) 2014-2019 Dennis Sheirer
+ * * Copyright (C) 2014-2020 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
@@ -29,6 +29,9 @@
import io.github.dsheirer.sample.Broadcaster;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.util.ThreadPool;
+import javafx.collections.FXCollections;
+import javafx.collections.ListChangeListener;
+import javafx.collections.ObservableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -68,11 +71,12 @@ public class BroadcastModel extends AbstractTableModel implements Listener