From d83e6379a3b32dea282129db126925b5e191f9bc Mon Sep 17 00:00:00 2001 From: "dennis.sheirer" Date: Sat, 14 Feb 2015 19:24:25 +0000 Subject: [PATCH] Alias actions. Adds capability to alert when an alias is active in one of the decoded messages. Alias actions include: beep, play an audio clip, or run a script. Additional actions can easily be added. --- images/action.png | Bin 0 -> 522 bytes src/alias/Alias.java | 28 +++ src/alias/AliasList.java | 14 +- src/alias/AliasNode.java | 102 +++++++- src/alias/action/AliasAction.java | 30 +++ src/alias/action/AliasActionManager.java | 59 +++++ src/alias/action/AliasActionNode.java | 40 ++++ src/alias/action/RecurringAction.java | 188 +++++++++++++++ src/alias/action/beep/BeepAction.java | 14 ++ src/alias/action/beep/BeepActionEditor.java | 151 ++++++++++++ src/alias/action/beep/BeepActionNode.java | 88 +++++++ src/alias/action/clip/ClipAction.java | 90 +++++++ src/alias/action/clip/ClipActionEditor.java | 220 ++++++++++++++++++ src/alias/action/clip/ClipActionNode.java | 88 +++++++ src/alias/action/script/ScriptAction.java | 80 +++++++ .../action/script/ScriptActionEditor.java | 218 +++++++++++++++++ src/alias/action/script/ScriptActionNode.java | 88 +++++++ src/controller/ControllerPanel.java | 2 +- src/controller/ResourceManager.java | 1 + src/controller/channel/ChannelManager.java | 8 + src/decode/fleetsync1/Fleetsync1Message.java | 27 +++ src/decode/fleetsync2/FleetsyncMessage.java | 33 +++ src/decode/lj1200/LJ1200Message.java | 33 +++ src/decode/ltrnet/LTRNetISWMessage.java | 33 +++ src/decode/ltrnet/LTRNetOSWMessage.java | 46 ++++ .../ltrstandard/LTRStandardISWMessage.java | 26 +++ .../ltrstandard/LTRStandardOSWMessage.java | 26 +++ src/decode/mdc1200/MDCMessage.java | 26 +++ src/decode/mpt1327/MPT1327Message.java | 26 +++ src/decode/passport/PassportMessage.java | 25 ++ src/decode/tait/Tait1200ANIMessage.java | 26 +++ src/decode/tait/Tait1200GPSMessage.java | 26 +++ src/message/Message.java | 12 +- 33 files changed, 1868 insertions(+), 6 deletions(-) create mode 100644 images/action.png create mode 100644 src/alias/action/AliasAction.java create mode 100644 src/alias/action/AliasActionManager.java create mode 100644 src/alias/action/AliasActionNode.java create mode 100644 src/alias/action/RecurringAction.java create mode 100644 src/alias/action/beep/BeepAction.java create mode 100644 src/alias/action/beep/BeepActionEditor.java create mode 100644 src/alias/action/beep/BeepActionNode.java create mode 100644 src/alias/action/clip/ClipAction.java create mode 100644 src/alias/action/clip/ClipActionEditor.java create mode 100644 src/alias/action/clip/ClipActionNode.java create mode 100644 src/alias/action/script/ScriptAction.java create mode 100644 src/alias/action/script/ScriptActionEditor.java create mode 100644 src/alias/action/script/ScriptActionNode.java diff --git a/images/action.png b/images/action.png new file mode 100644 index 0000000000000000000000000000000000000000..6e53a7851de60b98de423a9e25e24ce038bfb365 GIT binary patch literal 522 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyKLdP1Tst~C8jwJJeLaK+VZga) zf3p^r=85qQcK$tOo z{v}W#vX^-Jy0YJA;^P)IygyeH6pUS-E{-76!x@*Pm%cr5$-P@i|%{le@2{u`zh z2XanH^W|~jUJg$vAoHr`WZ~ND=d*t7ZJKa#^V|ay zSZdjiYs4S?=P0x)t|rxAitj2%QB6tP>;8!!UQY0wQRcJff5Y{>&!LGTbI&e$G}p;z l`_!t(U3Wzf24w7G+?KjP^7}ohpFmeJc)I$ztaD0e0syc!;3xn9 literal 0 HcmV?d00001 diff --git a/src/alias/Alias.java b/src/alias/Alias.java index 333a8495..26404dc9 100644 --- a/src/alias/Alias.java +++ b/src/alias/Alias.java @@ -19,9 +19,11 @@ package alias; import java.awt.Color; import java.util.ArrayList; +import java.util.List; import javax.xml.bind.annotation.XmlAttribute; +import alias.action.AliasAction; import audio.AudioType; public class Alias @@ -30,6 +32,7 @@ public class Alias private int mColor; private String mIconName; private ArrayList mAliasIDs = new ArrayList(); + private List mAliasActions = new ArrayList(); public Alias() { @@ -98,6 +101,31 @@ public class Alias mAliasIDs.remove( id ); } + public List getAction() + { + return mAliasActions; + } + + public void setAction( List actions ) + { + mAliasActions = actions; + } + + public void addAliasAction( AliasAction action ) + { + mAliasActions.add( action ); + } + + public void removeAliasAction( AliasAction action ) + { + mAliasActions.remove( action ); + } + + public boolean hasActions() + { + return !mAliasActions.isEmpty(); + } + public boolean hasAudioType() { for( AliasID id: mAliasIDs ) diff --git a/src/alias/AliasList.java b/src/alias/AliasList.java index f1cce1d1..de387a4e 100644 --- a/src/alias/AliasList.java +++ b/src/alias/AliasList.java @@ -27,7 +27,10 @@ import javax.xml.bind.annotation.XmlSeeAlso; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import decode.p25.P25ActivitySummary; +import alias.action.AliasAction; +import alias.action.beep.BeepAction; +import alias.action.clip.ClipAction; +import alias.action.script.ScriptAction; import alias.esn.Esn; import alias.fleetsync.FleetsyncID; import alias.fleetsync.StatusID; @@ -49,7 +52,14 @@ import alias.uniqueID.UniqueID; UniqueID.class, SiteID.class, StatusID.class, - TalkgroupID.class } ) + TalkgroupID.class, + + /* Alias Actions */ + AliasAction.class, + BeepAction.class, + ClipAction.class, + ScriptAction.class } ) + @XmlRootElement( name = "alias_list" ) public class AliasList implements Comparable { diff --git a/src/alias/AliasNode.java b/src/alias/AliasNode.java index a2520303..ceb5e6fb 100644 --- a/src/alias/AliasNode.java +++ b/src/alias/AliasNode.java @@ -25,9 +25,15 @@ import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; -import javax.swing.JSeparator; import map.MapIcon; +import alias.action.AliasAction; +import alias.action.beep.BeepAction; +import alias.action.beep.BeepActionNode; +import alias.action.clip.ClipAction; +import alias.action.clip.ClipActionNode; +import alias.action.script.ScriptAction; +import alias.action.script.ScriptActionNode; import alias.esn.ESNNode; import alias.esn.Esn; import alias.fleetsync.FleetsyncID; @@ -136,6 +142,25 @@ public class AliasNode extends ConfigurableNode } } + for( AliasAction action: getAlias().getAction() ) + { + if( action instanceof BeepAction ) + { + getModel().addNode( new BeepActionNode( (BeepAction)action ), + AliasNode.this, getChildCount() ); + } + else if( action instanceof ClipAction ) + { + getModel().addNode( new ClipActionNode( (ClipAction)action ), + AliasNode.this, getChildCount() ); + } + else if( action instanceof ScriptAction ) + { + getModel().addNode( new ScriptActionNode( (ScriptAction)action ), + AliasNode.this, getChildCount() ); + } + } + sort(); } @@ -342,7 +367,80 @@ public class AliasNode extends ConfigurableNode retVal.add( addIDMenu ); - retVal.add( new JSeparator() ); + JMenu addActionMenu = new JMenu( "Add Action" ); + + JMenuItem addClipItem = new JMenuItem( "Audio Clip" ); + + addClipItem.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent e ) + { + ClipAction clipAction = new ClipAction(); + + getAlias().addAliasAction( clipAction ); + + ClipActionNode node = new ClipActionNode( clipAction ); + + getModel().addNode( node, + AliasNode.this, + AliasNode.this.getChildCount() ); + + node.show(); + } + } ); + + addActionMenu.add( addClipItem ); + + JMenuItem addBeepItem = new JMenuItem( "Beep" ); + + addBeepItem.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent e ) + { + BeepAction beepAction = new BeepAction(); + + getAlias().addAliasAction( beepAction ); + + BeepActionNode node = new BeepActionNode( beepAction ); + + getModel().addNode( node, + AliasNode.this, + AliasNode.this.getChildCount() ); + + node.show(); + } + } ); + + addActionMenu.add( addBeepItem ); + + JMenuItem addScriptItem = new JMenuItem( "Script" ); + + addScriptItem.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent e ) + { + ScriptAction scriptAction = new ScriptAction(); + + getAlias().addAliasAction( scriptAction ); + + ScriptActionNode node = new ScriptActionNode( scriptAction ); + + getModel().addNode( node, + AliasNode.this, + AliasNode.this.getChildCount() ); + + node.show(); + } + } ); + + addActionMenu.add( addScriptItem ); + + retVal.add( addActionMenu ); + + retVal.addSeparator(); JMenuItem deleteItem = new JMenuItem( "Delete" ); deleteItem.addActionListener( new ActionListener() diff --git a/src/alias/action/AliasAction.java b/src/alias/action/AliasAction.java new file mode 100644 index 00000000..08308c82 --- /dev/null +++ b/src/alias/action/AliasAction.java @@ -0,0 +1,30 @@ +package alias.action; + +import message.Message; +import alias.Alias; +import controller.ThreadPoolManager; + +/** + * Alias action defines an action to execute when an alias is detected active. + */ +public abstract class AliasAction +{ + public AliasAction() + { + } + + /** + * Task to execute when an alias action is defined. The message argument is + * the original message containing one or more aliases that have an alias + * action attached. The alias argument is the parent alias containing the + * alias action. + */ + public abstract void execute( ThreadPoolManager threadPoolManager, + Alias alias, + Message message ); + + /** + * Dismiss a persistent alias action + */ + public abstract void dismiss( boolean reset ); +} diff --git a/src/alias/action/AliasActionManager.java b/src/alias/action/AliasActionManager.java new file mode 100644 index 00000000..dca4633f --- /dev/null +++ b/src/alias/action/AliasActionManager.java @@ -0,0 +1,59 @@ +package alias.action; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import message.Message; +import sample.Listener; +import alias.Alias; +import controller.ResourceManager; +import decode.p25.P25Decoder; + +/** + * Manages all alias action events. Each received message is interrogated for + * any alias entries and then each alias is interrogated for any alias actions. + * + * Each alias action is executed and provided a copy of the source message so + * that the contents of the message can be used as part of the action. + */ +public class AliasActionManager implements Listener +{ + private final static Logger mLog = + LoggerFactory.getLogger( AliasActionManager.class ); + + private ResourceManager mResourceManager; + + public AliasActionManager( ResourceManager resourceManager ) + { + mResourceManager = resourceManager; + } + + @Override + public void receive( Message message ) + { + List aliases = message.getAliases(); + + if( aliases != null ) + { + for( Alias alias: aliases ) + { + if( alias.hasActions() ) + { + List actions = alias.getAction(); + + for( AliasAction action: actions ) + { + /* Provide access to the thread pool manager in case the + * action needs to setup a timer, and provide the original + * message to be used as part of the action (e.g. sending + * the message as a text message to a cell phone */ + action.execute( mResourceManager.getThreadPoolManager(), + alias, message ); + } + } + } + } + } +} diff --git a/src/alias/action/AliasActionNode.java b/src/alias/action/AliasActionNode.java new file mode 100644 index 00000000..79ee2484 --- /dev/null +++ b/src/alias/action/AliasActionNode.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * 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 alias.action; + +import controller.ConfigurableNode; + +public class AliasActionNode extends ConfigurableNode +{ + private static final long serialVersionUID = 1L; + + public AliasActionNode( AliasAction action ) + { + super( action ); + } + + public void save() + { + getModel().getResourceManager().getPlaylistManager().save(); + } + + public String getIconPath() + { + return "images/action.png"; + } +} diff --git a/src/alias/action/RecurringAction.java b/src/alias/action/RecurringAction.java new file mode 100644 index 00000000..8d6298c2 --- /dev/null +++ b/src/alias/action/RecurringAction.java @@ -0,0 +1,188 @@ +package alias.action; + +import java.awt.EventQueue; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.swing.JOptionPane; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlTransient; + +import message.Message; +import alias.Alias; +import controller.ThreadPoolManager; +import controller.ThreadPoolManager.ThreadType; + +public abstract class RecurringAction extends AliasAction +{ + @XmlTransient + protected AtomicBoolean mRunning = new AtomicBoolean( false ); + @XmlTransient + private ScheduledFuture mPerpetualAction; + + protected Interval mInterval = Interval.ONCE; + protected int mPeriod = 5; + + protected ThreadPoolManager mThreadPoolManager; + + public abstract void performAction( Alias alias, Message message ); + + @Override + public void execute( ThreadPoolManager threadPoolManager, + Alias alias, + Message message ) + { + mThreadPoolManager = threadPoolManager; + + if( mRunning.compareAndSet( false, true ) ) + { + switch( mInterval ) + { + case ONCE: + performThreadedAction( alias, message ); + /* Don't reset */ + break; + case DELAYED_RESET: + performThreadedAction( alias, message ); + mThreadPoolManager.scheduleOnce( new ResetTask(), + mPeriod, TimeUnit.SECONDS ); + break; + case UNTIL_DISMISSED: + mPerpetualAction = mThreadPoolManager + .scheduleFixedRate( ThreadType.DECODER, + new PerformActionTask( alias, message ), + mPeriod, TimeUnit.SECONDS ); + + StringBuilder sb = new StringBuilder(); + sb.append( "
Alias [" ); + sb.append( alias.getName() ); + sb.append( "] is active in message [" ); + sb.append( message.toString() ); + sb.append( "]
" ); + + final String text = sb.toString(); + + EventQueue.invokeLater( new Runnable() + { + @Override + public void run() + { + JOptionPane.showMessageDialog( null, text, + "Alias Alert", JOptionPane.INFORMATION_MESSAGE ); + + dismiss( false ); + + mThreadPoolManager.scheduleOnce( new ResetTask(), + 15, TimeUnit.SECONDS ); + } + } ); + break; + default: + } + } + } + + /** + * Spawns the performAction() event into a new thread so that it doesn't + * delay any decoder actions. + */ + private void performThreadedAction( final Alias alias, final Message message ) + { + mThreadPoolManager.scheduleOnce( new Runnable() { + + @Override + public void run() + { + performAction( alias, message ); + }}, 0, TimeUnit.SECONDS ); + } + + @Override + public void dismiss( boolean reset ) + { + if( mPerpetualAction != null ) + { + mPerpetualAction.cancel( true ); + + mPerpetualAction = null; + } + + if( reset ) + { + mRunning.set( false ); + } + } + + @XmlAttribute + public int getPeriod() + { + return mPeriod; + } + + public void setPeriod( int period ) + { + mPeriod = period; + } + + @XmlAttribute + public Interval getInterval() + { + return mInterval; + } + + public void setInterval( Interval interval ) + { + mInterval = interval; + + mRunning.set( false ); + } + + public enum Interval + { + ONCE( "Once" ), + DELAYED_RESET( "Once, Reset After Delay" ), + UNTIL_DISMISSED( "Until Dismissed" ); + + private String mLabel; + + private Interval( String label ) + { + mLabel = label; + } + + public String toString() + { + return mLabel; + } + } + + public class PerformActionTask implements Runnable + { + private Alias mAlias; + private Message mMessage; + + public PerformActionTask( Alias alias, Message message ) + { + mAlias = alias; + mMessage = message; + } + + @Override + public void run() + { + /* Don't use the performThreadedAction() method, since this is + * already running in a separate thread */ + performAction( mAlias, mMessage ); + } + } + + public class ResetTask implements Runnable + { + @Override + public void run() + { + mRunning.set( false ); + } + } +} diff --git a/src/alias/action/beep/BeepAction.java b/src/alias/action/beep/BeepAction.java new file mode 100644 index 00000000..b260adbb --- /dev/null +++ b/src/alias/action/beep/BeepAction.java @@ -0,0 +1,14 @@ +package alias.action.beep; + +import message.Message; +import alias.Alias; +import alias.action.RecurringAction; + +public class BeepAction extends RecurringAction +{ + @Override + public void performAction( Alias alias, Message message ) + { + System.out.println( "\007" ); + } +} diff --git a/src/alias/action/beep/BeepActionEditor.java b/src/alias/action/beep/BeepActionEditor.java new file mode 100644 index 00000000..7b5844f9 --- /dev/null +++ b/src/alias/action/beep/BeepActionEditor.java @@ -0,0 +1,151 @@ +/******************************************************************************* + * 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 alias.action.beep; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSpinner; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.SpinnerModel; +import javax.swing.SpinnerNumberModel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import net.miginfocom.swing.MigLayout; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import alias.action.RecurringAction.Interval; + +public class BeepActionEditor extends JPanel implements ActionListener +{ + private static final long serialVersionUID = 1L; + + private final static Logger mLog = + LoggerFactory.getLogger( BeepActionEditor.class ); + + private BeepActionNode mBeepActionNode; + private JTextField mTextSiteID; + private JComboBox mComboInterval; + private JSpinner mSpinnerPeriod; + + public BeepActionEditor( BeepActionNode beepActionNode ) + { + mBeepActionNode = beepActionNode; + + initGUI(); + } + + private void initGUI() + { + setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][][][][grow]" ) ); + + add( new JLabel( "Action: Beep" ), "span,align center" ); + + add( new JLabel( "Interval:" ) ); + + mComboInterval = new JComboBox( Interval.values() ); + + mComboInterval.setSelectedItem( mBeepActionNode.getBeepAction().getInterval() ); + + mComboInterval.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent e ) + { + Interval selected = mComboInterval + .getItemAt( mComboInterval.getSelectedIndex() ); + + if( selected != null ) + { + /* Enable/disable period spinner based on selection */ + mSpinnerPeriod.setEnabled( selected != Interval.ONCE ); + + mBeepActionNode.getBeepAction().setInterval( selected ); + } + } + }); + + add( mComboInterval, "wrap" ); + + final SpinnerModel model = new SpinnerNumberModel( + mBeepActionNode.getBeepAction().getPeriod(), 1, 30, 1 ); + + model.addChangeListener( new ChangeListener() + { + @Override + public void stateChanged( ChangeEvent e ) + { + mBeepActionNode.getBeepAction().setPeriod( (int)model.getValue() ); + } + } ); + + mSpinnerPeriod = new JSpinner( model ); + + if( mBeepActionNode.getBeepAction().getInterval() == Interval.ONCE ) + { + mSpinnerPeriod.setEnabled( false ); + } + + add( new JLabel( "Period:" ) ); + add( mSpinnerPeriod, "wrap" ); + + StringBuilder sb = new StringBuilder(); + + sb.append( "This action will sound a beep according to the interval that you select.\n\n" ); + sb.append( "Once - Beep the first time the alias is active and never again.\n\n" ); + sb.append( "Once, Reset After Delay - Beep once and suppress subsequent beeps for the specified period in seconds. After the reset period, it will beep again when the alias is active.\n\n" ); + sb.append( "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." ); + + JTextArea description = new JTextArea( sb.toString() ); + + description.setLineWrap( true ); + description.setBackground( getBackground() ); + + add( description, "growx,span" ); + + JButton btnSave = new JButton( "Save" ); + btnSave.addActionListener( BeepActionEditor.this ); + add( btnSave, "growx,push" ); + + JButton btnReset = new JButton( "Reset" ); + btnReset.addActionListener( BeepActionEditor.this ); + add( btnReset, "growx,push" ); + } + + @Override + public void actionPerformed( ActionEvent e ) + { + String command = e.getActionCommand(); + + if( command.contentEquals( "Save" ) ) + { + mBeepActionNode.save(); + mBeepActionNode.show(); + } + + mBeepActionNode.refresh(); + } +} diff --git a/src/alias/action/beep/BeepActionNode.java b/src/alias/action/beep/BeepActionNode.java new file mode 100644 index 00000000..817e3949 --- /dev/null +++ b/src/alias/action/beep/BeepActionNode.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * 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 alias.action.beep; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; + +import alias.AliasNode; +import alias.action.AliasActionNode; + +public class BeepActionNode extends AliasActionNode +{ + private static final long serialVersionUID = 1L; + + public BeepActionNode( BeepAction beepAction ) + { + super( beepAction ); + } + + @Override + public JPanel getEditor() + { + return new BeepActionEditor( this ); + } + + public BeepAction getBeepAction() + { + return (BeepAction)getUserObject(); + } + + public String toString() + { + return "Action: Beep"; + } + + public JPopupMenu getContextMenu() + { + JPopupMenu retVal = new JPopupMenu(); + + JMenuItem deleteItem = new JMenuItem( "Delete" ); + deleteItem.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent e ) + { + int n = JOptionPane.showConfirmDialog( getModel().getTree(), + "Are you sure you want to permanently delete this node?" ); + + if( n == JOptionPane.YES_OPTION ) + { + AliasNode parent = (AliasNode)getParent(); + + parent.getAlias().removeAliasAction( getBeepAction() ); + + /* Save before removing the node ... so that we still have + * a reference to the parent's resources */ + save(); + + getModel().removeNodeFromParent( BeepActionNode.this ); + } + } + } ); + + retVal.add( deleteItem ); + + return retVal; + } +} diff --git a/src/alias/action/clip/ClipAction.java b/src/alias/action/clip/ClipAction.java new file mode 100644 index 00000000..a55b12e1 --- /dev/null +++ b/src/alias/action/clip/ClipAction.java @@ -0,0 +1,90 @@ +package alias.action.clip; + +import java.io.File; + +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.xml.bind.annotation.XmlTransient; + +import message.Message; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import alias.Alias; +import alias.action.RecurringAction; + +public class ClipAction extends RecurringAction +{ + private final static Logger mLog = LoggerFactory.getLogger( ClipAction.class ); + + private String mFilePath; + + @XmlTransient + private Clip mClip; + + public ClipAction() + { + } + + public String getPath() + { + + return mFilePath; + } + + public void setPath( String path ) + { + mFilePath = path; + } + + @Override + public void performAction( Alias alias, Message message ) + { + try + { + play(); + } + catch( Exception e ) + { + mLog.debug( "Couldn't play audio clip", e ); + } + } + + public void play() throws Exception + { + try + { + if( mFilePath != null ) + { + if( mClip == null ) + { + mClip = AudioSystem.getClip(); + + AudioInputStream ais = + AudioSystem.getAudioInputStream( new File( mFilePath ) ); + + mClip.open( ais ); + } + + if( mClip.isRunning() ) + { + mClip.stop(); + } + + mClip.setFramePosition( 0 ); + + mClip.start(); + } + } + catch( Exception e ) + { + mClip = null; + + mLog.error( "Error playing sound clip [" + mFilePath + "] - " + e.getMessage() ); + + throw e; + } + } +} diff --git a/src/alias/action/clip/ClipActionEditor.java b/src/alias/action/clip/ClipActionEditor.java new file mode 100644 index 00000000..07bcceba --- /dev/null +++ b/src/alias/action/clip/ClipActionEditor.java @@ -0,0 +1,220 @@ +/******************************************************************************* + * 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 alias.action.clip; + +import java.awt.EventQueue; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JSpinner; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.SpinnerModel; +import javax.swing.SpinnerNumberModel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import net.miginfocom.swing.MigLayout; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import alias.action.RecurringAction.Interval; +import alias.action.script.ScriptActionEditor; + +public class ClipActionEditor extends JPanel implements ActionListener +{ + private static final long serialVersionUID = 1L; + + private final static Logger mLog = + LoggerFactory.getLogger( ClipActionEditor.class ); + + private ClipActionNode mClipActionNode; + private JTextField mTextSiteID; + private JComboBox mComboInterval; + private JSpinner mSpinnerPeriod; + private JTextField mTextFilePath; + + public ClipActionEditor( ClipActionNode clipActionNode ) + { + mClipActionNode = clipActionNode; + + initGUI(); + } + + private void initGUI() + { + setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][][][][grow]" ) ); + + add( new JLabel( "Action: Audio Clip" ), "span,align center" ); + + add( new JLabel( "Interval:" ) ); + + mComboInterval = new JComboBox( Interval.values() ); + + mComboInterval.setSelectedItem( mClipActionNode.getClipAction().getInterval() ); + + mComboInterval.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent e ) + { + Interval selected = mComboInterval + .getItemAt( mComboInterval.getSelectedIndex() ); + + if( selected != null ) + { + /* Enable/disable period spinner based on selection */ + mSpinnerPeriod.setEnabled( selected != Interval.ONCE ); + + mClipActionNode.getClipAction().setInterval( selected ); + } + } + }); + + add( mComboInterval, "wrap" ); + + final SpinnerModel model = new SpinnerNumberModel( + mClipActionNode.getClipAction().getPeriod(), 1, 30, 1 ); + + model.addChangeListener( new ChangeListener() + { + @Override + public void stateChanged( ChangeEvent e ) + { + mClipActionNode.getClipAction().setPeriod( (int)model.getValue() ); + } + } ); + + mSpinnerPeriod = new JSpinner( model ); + + if( mClipActionNode.getClipAction().getInterval() == Interval.ONCE ) + { + mSpinnerPeriod.setEnabled( false ); + } + + add( new JLabel( "Period:" ) ); + add( mSpinnerPeriod, "wrap" ); + + 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(); + + mClipActionNode.getClipAction().setPath( file.getAbsolutePath() ); + mTextFilePath.setText( file.getAbsolutePath() ); + } + } + } ); + + add( fileButton ); + + JButton testButton = new JButton( "Test" ); + testButton.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent actionEvent ) + { + String path = mClipActionNode.getClipAction().getPath(); + + if( path == null || path.trim().isEmpty() ) + { + JOptionPane.showMessageDialog( ClipActionEditor.this, + "Please select an audio file", "Please select file", + JOptionPane.ERROR_MESSAGE ); + } + + EventQueue.invokeLater( new Runnable() + { + @Override + public void run() + { + try + { + mClipActionNode.getClipAction().play(); + } + catch( Exception e ) + { + JOptionPane.showMessageDialog( ClipActionEditor.this, + "Couldn't play audio clip [" + e.getMessage() + "]", + "Error", JOptionPane.ERROR_MESSAGE ); + } + } + } ); + } + } ); + + add( testButton, "wrap" ); + + mTextFilePath = new JTextField( mClipActionNode.getClipAction().getPath() ); + add( mTextFilePath, "growx,span" ); + + StringBuilder sb = new StringBuilder(); + + sb.append( "This action will play the audio clip according to the interval that you select.\n\n" ); + sb.append( "Once - Play the first time the alias is active and never again.\n\n" ); + sb.append( "Once, Reset After Delay - Play once and suppress subsequent plays for the specified period in seconds. After the reset period, it will play again when the alias is active.\n\n" ); + sb.append( "Until Dismissed - Play audio clip every period seconds until you click OK on the dialog that appears. Alerting is suppressed for 15 seconds after you click OK." ); + + JTextArea description = new JTextArea( sb.toString() ); + + description.setLineWrap( true ); + description.setBackground( getBackground() ); + + add( description, "growx,span" ); + + JButton btnSave = new JButton( "Save" ); + btnSave.addActionListener( ClipActionEditor.this ); + add( btnSave, "growx,push" ); + + JButton btnReset = new JButton( "Reset" ); + btnReset.addActionListener( ClipActionEditor.this ); + add( btnReset, "growx,push" ); + } + + @Override + public void actionPerformed( ActionEvent e ) + { + String command = e.getActionCommand(); + + if( command.contentEquals( "Save" ) ) + { + mClipActionNode.save(); + mClipActionNode.show(); + } + + mClipActionNode.refresh(); + } +} diff --git a/src/alias/action/clip/ClipActionNode.java b/src/alias/action/clip/ClipActionNode.java new file mode 100644 index 00000000..e3255cd0 --- /dev/null +++ b/src/alias/action/clip/ClipActionNode.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * 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 alias.action.clip; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; + +import alias.AliasNode; +import alias.action.AliasActionNode; + +public class ClipActionNode extends AliasActionNode +{ + private static final long serialVersionUID = 1L; + + public ClipActionNode( ClipAction clipAction ) + { + super( clipAction ); + } + + @Override + public JPanel getEditor() + { + return new ClipActionEditor( this ); + } + + public ClipAction getClipAction() + { + return (ClipAction)getUserObject(); + } + + public String toString() + { + return "Action: Audio Clip"; + } + + public JPopupMenu getContextMenu() + { + JPopupMenu retVal = new JPopupMenu(); + + JMenuItem deleteItem = new JMenuItem( "Delete" ); + deleteItem.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent e ) + { + int n = JOptionPane.showConfirmDialog( getModel().getTree(), + "Are you sure you want to permanently delete this node?" ); + + if( n == JOptionPane.YES_OPTION ) + { + AliasNode parent = (AliasNode)getParent(); + + parent.getAlias().removeAliasAction( getClipAction() ); + + /* Save before removing the node ... so that we still have + * a reference to the parent's resources */ + save(); + + getModel().removeNodeFromParent( ClipActionNode.this ); + } + } + } ); + + retVal.add( deleteItem ); + + return retVal; + } +} diff --git a/src/alias/action/script/ScriptAction.java b/src/alias/action/script/ScriptAction.java new file mode 100644 index 00000000..a32e32fb --- /dev/null +++ b/src/alias/action/script/ScriptAction.java @@ -0,0 +1,80 @@ +package alias.action.script; + +import java.io.BufferedReader; +import java.io.InputStreamReader; + +import message.Message; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import alias.Alias; +import alias.action.RecurringAction; + +public class ScriptAction extends RecurringAction +{ + private final static Logger mLog = LoggerFactory.getLogger( ScriptAction.class ); + + private String mScript; + + public ScriptAction() + { + } + + public String getScript() + { + return mScript; + } + + public void setScript( String script ) + { + mScript = script; + } + + @Override + public void performAction( Alias alias, Message message ) + { + try + { + play(); + } + catch( Exception e ) + { + mLog.debug( "Couldn't execute script [" + mScript + "]", e ); + } + } + + public void play() throws Exception + { + if( mScript != null ) + { + mLog.debug( "Running Script ..." ); + + ProcessBuilder pb = new ProcessBuilder( mScript ); + + pb.redirectErrorStream( true ); + + Process p = pb.start(); + + int exitCode = p.waitFor(); + + BufferedReader reader = new BufferedReader( + new InputStreamReader( p.getInputStream() ) ); + + String line = ""; + + StringBuilder sb = new StringBuilder(); + + while( ( line = reader.readLine() ) != null ) + { + sb.append(line + "\n"); + } + + if( exitCode != 0 ) + { + throw new RuntimeException( "Exit Code: " + exitCode + + " Console:" + sb.toString() ); + } + } + } +} diff --git a/src/alias/action/script/ScriptActionEditor.java b/src/alias/action/script/ScriptActionEditor.java new file mode 100644 index 00000000..22f2c77d --- /dev/null +++ b/src/alias/action/script/ScriptActionEditor.java @@ -0,0 +1,218 @@ +/******************************************************************************* + * 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 alias.action.script; + +import java.awt.EventQueue; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JSpinner; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.SpinnerModel; +import javax.swing.SpinnerNumberModel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import net.miginfocom.swing.MigLayout; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import alias.action.RecurringAction.Interval; + +public class ScriptActionEditor extends JPanel implements ActionListener +{ + private static final long serialVersionUID = 1L; + + private final static Logger mLog = + LoggerFactory.getLogger( ScriptActionEditor.class ); + + private ScriptActionNode mScriptActionNode; + private JComboBox mComboInterval; + private JSpinner mSpinnerPeriod; + private JTextField mTextFilePath; + + public ScriptActionEditor( ScriptActionNode clipActionNode ) + { + mScriptActionNode = clipActionNode; + + initGUI(); + } + + private void initGUI() + { + setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][][][][grow]" ) ); + + add( new JLabel( "Action: Script" ), "span,align center" ); + + add( new JLabel( "Interval:" ) ); + + mComboInterval = new JComboBox( Interval.values() ); + + mComboInterval.setSelectedItem( mScriptActionNode.getScriptAction().getInterval() ); + + mComboInterval.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent e ) + { + Interval selected = mComboInterval + .getItemAt( mComboInterval.getSelectedIndex() ); + + if( selected != null ) + { + /* Enable/disable period spinner based on selection */ + mSpinnerPeriod.setEnabled( selected != Interval.ONCE ); + + mScriptActionNode.getScriptAction().setInterval( selected ); + } + } + }); + + add( mComboInterval, "wrap" ); + + final SpinnerModel model = new SpinnerNumberModel( + mScriptActionNode.getScriptAction().getPeriod(), 1, 30, 1 ); + + model.addChangeListener( new ChangeListener() + { + @Override + public void stateChanged( ChangeEvent e ) + { + mScriptActionNode.getScriptAction().setPeriod( (int)model.getValue() ); + } + } ); + + mSpinnerPeriod = new JSpinner( model ); + + if( mScriptActionNode.getScriptAction().getInterval() == Interval.ONCE ) + { + mSpinnerPeriod.setEnabled( false ); + } + + add( new JLabel( "Period:" ) ); + add( mSpinnerPeriod, "wrap" ); + + 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(); + + mScriptActionNode.getScriptAction().setScript( file.getAbsolutePath() ); + mTextFilePath.setText( file.getAbsolutePath() ); + } + } + } ); + + add( fileButton ); + + JButton testButton = new JButton( "Test" ); + testButton.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent actionEvent ) + { + String script = mScriptActionNode.getScriptAction().getScript(); + + if( script == null || script.trim().isEmpty() ) + { + JOptionPane.showMessageDialog( ScriptActionEditor.this, + "Please select a script file", "Please select file", + JOptionPane.ERROR_MESSAGE ); + } + + EventQueue.invokeLater( new Runnable() + { + @Override + public void run() + { + try + { + mScriptActionNode.getScriptAction().play(); + } + catch( Exception e ) + { + JOptionPane.showMessageDialog( ScriptActionEditor.this, + "Couldn't run script [" + e.getMessage() + "]", + "Error", JOptionPane.ERROR_MESSAGE ); + } + } + } ); + } + } ); + + add( testButton, "wrap" ); + + mTextFilePath = new JTextField( mScriptActionNode.getScriptAction().getScript() ); + add( mTextFilePath, "growx,span" ); + + StringBuilder sb = new StringBuilder(); + + sb.append( "This action will run the script according to the interval that you select.\n\n" ); + sb.append( "Once - Run script the first time the alias is active and never again.\n\n" ); + sb.append( "Once, Reset After Delay - Run once and suppress subsequent runs for the specified period in seconds. After the reset period, it will play again when the alias is active.\n\n" ); + sb.append( "Until Dismissed - Run script every period seconds until you click OK on the dialog that appears. Alerting is suppressed for 15 seconds after you click OK." ); + + JTextArea description = new JTextArea( sb.toString() ); + + description.setLineWrap( true ); + description.setBackground( getBackground() ); + + add( description, "growx,span" ); + + JButton btnSave = new JButton( "Save" ); + btnSave.addActionListener( ScriptActionEditor.this ); + add( btnSave, "growx,push" ); + + JButton btnReset = new JButton( "Reset" ); + btnReset.addActionListener( ScriptActionEditor.this ); + add( btnReset, "growx,push" ); + } + + @Override + public void actionPerformed( ActionEvent e ) + { + String command = e.getActionCommand(); + + if( command.contentEquals( "Save" ) ) + { + mScriptActionNode.save(); + mScriptActionNode.show(); + } + + mScriptActionNode.refresh(); + } +} diff --git a/src/alias/action/script/ScriptActionNode.java b/src/alias/action/script/ScriptActionNode.java new file mode 100644 index 00000000..b0385e3f --- /dev/null +++ b/src/alias/action/script/ScriptActionNode.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * 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 alias.action.script; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; + +import alias.AliasNode; +import alias.action.AliasActionNode; + +public class ScriptActionNode extends AliasActionNode +{ + private static final long serialVersionUID = 1L; + + public ScriptActionNode( ScriptAction scriptAction ) + { + super( scriptAction ); + } + + @Override + public JPanel getEditor() + { + return new ScriptActionEditor( this ); + } + + public ScriptAction getScriptAction() + { + return (ScriptAction)getUserObject(); + } + + public String toString() + { + return "Action: Script"; + } + + public JPopupMenu getContextMenu() + { + JPopupMenu retVal = new JPopupMenu(); + + JMenuItem deleteItem = new JMenuItem( "Delete" ); + deleteItem.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent e ) + { + int n = JOptionPane.showConfirmDialog( getModel().getTree(), + "Are you sure you want to permanently delete this node?" ); + + if( n == JOptionPane.YES_OPTION ) + { + AliasNode parent = (AliasNode)getParent(); + + parent.getAlias().removeAliasAction( getScriptAction() ); + + /* Save before removing the node ... so that we still have + * a reference to the parent's resources */ + save(); + + getModel().removeNodeFromParent( ScriptActionNode.this ); + } + } + } ); + + retVal.add( deleteItem ); + + return retVal; + } +} diff --git a/src/controller/ControllerPanel.java b/src/controller/ControllerPanel.java index 145e5271..a68cb667 100644 --- a/src/controller/ControllerPanel.java +++ b/src/controller/ControllerPanel.java @@ -121,7 +121,7 @@ public class ControllerPanel extends JPanel } } } ); - + /** * Add mapping services and map panel to a new tab */ diff --git a/src/controller/ResourceManager.java b/src/controller/ResourceManager.java index 33caf291..ee5c1b6f 100644 --- a/src/controller/ResourceManager.java +++ b/src/controller/ResourceManager.java @@ -17,6 +17,7 @@ ******************************************************************************/ package controller; +import alias.action.AliasActionManager; import map.MapService; import playlist.PlaylistManager; import record.RecorderManager; diff --git a/src/controller/channel/ChannelManager.java b/src/controller/channel/ChannelManager.java index 96dfbeb0..ca475413 100644 --- a/src/controller/channel/ChannelManager.java +++ b/src/controller/channel/ChannelManager.java @@ -19,6 +19,7 @@ package controller.channel; import java.util.ArrayList; +import alias.action.AliasActionManager; import message.Message; import sample.Listener; import controller.ResourceManager; @@ -31,10 +32,17 @@ public class ChannelManager implements ChannelEventListener new ArrayList(); private ArrayList> mMessageListeners = new ArrayList>(); + + private AliasActionManager mAliasActionManager; public ChannelManager( ResourceManager resourceManager ) { + mAliasActionManager = new AliasActionManager( resourceManager ); + mChannelListeners.add( this ); + + /* Add alias action manager as listener to all channels/messages */ + mMessageListeners.add( mAliasActionManager ); } /** diff --git a/src/decode/fleetsync1/Fleetsync1Message.java b/src/decode/fleetsync1/Fleetsync1Message.java index e218ec26..80826562 100644 --- a/src/decode/fleetsync1/Fleetsync1Message.java +++ b/src/decode/fleetsync1/Fleetsync1Message.java @@ -18,7 +18,10 @@ package decode.fleetsync1; import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; import java.util.Date; +import java.util.List; import map.Plottable; import message.Message; @@ -172,4 +175,28 @@ public class Fleetsync1Message extends Message { return null; } + + /** + * Provides a listing of aliases contained in the message. + */ + public List getAliases() + { + List aliases = new ArrayList(); + + Alias from = getFromIDAlias(); + + if( from != null ) + { + aliases.add( from ); + } + + Alias to = getToIDAlias(); + + if( to != null ) + { + aliases.add( to ); + } + + return aliases; + } } diff --git a/src/decode/fleetsync2/FleetsyncMessage.java b/src/decode/fleetsync2/FleetsyncMessage.java index 998d4242..190e0a1c 100644 --- a/src/decode/fleetsync2/FleetsyncMessage.java +++ b/src/decode/fleetsync2/FleetsyncMessage.java @@ -19,10 +19,12 @@ package decode.fleetsync2; import java.text.DecimalFormat; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.BitSet; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; +import java.util.List; import map.Plottable; import message.Message; @@ -860,4 +862,35 @@ public class FleetsyncMessage extends Message return null; } } + + /** + * Provides a listing of aliases contained in the message. + */ + public List getAliases() + { + List aliases = new ArrayList(); + + Alias from = getFromIDAlias(); + + if( from != null ) + { + aliases.add( from ); + } + + Alias to = getToIDAlias(); + + if( to != null ) + { + aliases.add( to ); + } + + Alias status = getStatusAlias(); + + if( status != null ) + { + aliases.add( status ); + } + + return aliases; + } } diff --git a/src/decode/lj1200/LJ1200Message.java b/src/decode/lj1200/LJ1200Message.java index 7a3d4b14..4198d947 100644 --- a/src/decode/lj1200/LJ1200Message.java +++ b/src/decode/lj1200/LJ1200Message.java @@ -18,6 +18,8 @@ package decode.lj1200; import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; import map.Plottable; import message.Message; @@ -364,4 +366,35 @@ public class LJ1200Message extends Message return UNKNOWN; } } + + /** + * Provides a listing of aliases contained in the message. + */ + public List getAliases() + { + List aliases = new ArrayList(); + + Alias from = getFromIDAlias(); + + if( from != null ) + { + aliases.add( from ); + } + + Alias to = getToIDAlias(); + + if( to != null ) + { + aliases.add( to ); + } + + Alias site = getSiteIDAlias(); + + if( site != null ) + { + aliases.add( site ); + } + + return aliases; + } } diff --git a/src/decode/ltrnet/LTRNetISWMessage.java b/src/decode/ltrnet/LTRNetISWMessage.java index 119a810a..d643bc4e 100644 --- a/src/decode/ltrnet/LTRNetISWMessage.java +++ b/src/decode/ltrnet/LTRNetISWMessage.java @@ -17,7 +17,9 @@ ******************************************************************************/ package decode.ltrnet; +import java.util.ArrayList; import java.util.Date; +import java.util.List; import map.Plottable; import message.MessageDirection; @@ -309,4 +311,35 @@ public class LTRNetISWMessage extends LTRNetMessage // TODO Auto-generated method stub return null; } + + /** + * Provides a listing of aliases contained in the message. + */ + public List getAliases() + { + List aliases = new ArrayList(); + + Alias from = getFromIDAlias(); + + if( from != null ) + { + aliases.add( from ); + } + + Alias to = getToIDAlias(); + + if( to != null ) + { + aliases.add( to ); + } + + Alias esn = getESNAlias(); + + if( esn != null ) + { + aliases.add( esn ); + } + + return aliases; + } } diff --git a/src/decode/ltrnet/LTRNetOSWMessage.java b/src/decode/ltrnet/LTRNetOSWMessage.java index abb752f1..93e276da 100644 --- a/src/decode/ltrnet/LTRNetOSWMessage.java +++ b/src/decode/ltrnet/LTRNetOSWMessage.java @@ -19,6 +19,7 @@ package decode.ltrnet; import java.util.ArrayList; import java.util.Date; +import java.util.List; import map.Plottable; import message.MessageDirection; @@ -590,4 +591,49 @@ public class LTRNetOSWMessage extends LTRNetMessage // TODO Auto-generated method stub return null; } + + /** + * Provides a listing of aliases contained in the message. + */ + public List getAliases() + { + List aliases = new ArrayList(); + + Alias from = getFromIDAlias(); + + if( from != null ) + { + aliases.add( from ); + } + + Alias to = getToIDAlias(); + + if( to != null ) + { + aliases.add( to ); + } + + Alias neighbor = getNeighborIDAlias(); + + if( neighbor != null ) + { + aliases.add( neighbor ); + } + + Alias uid = getRadioUniqueIDAlias(); + + if( uid != null ) + { + aliases.add( uid ); + } + + Alias site = getSiteIDAlias(); + + if( site != null ) + { + aliases.add( site ); + } + + return aliases; + } } diff --git a/src/decode/ltrstandard/LTRStandardISWMessage.java b/src/decode/ltrstandard/LTRStandardISWMessage.java index f3f08737..44d44385 100644 --- a/src/decode/ltrstandard/LTRStandardISWMessage.java +++ b/src/decode/ltrstandard/LTRStandardISWMessage.java @@ -17,7 +17,9 @@ ******************************************************************************/ package decode.ltrstandard; +import java.util.ArrayList; import java.util.Date; +import java.util.List; import map.Plottable; import message.MessageDirection; @@ -209,4 +211,28 @@ public class LTRStandardISWMessage extends LTRStandardMessage // TODO Auto-generated method stub return null; } + + /** + * Provides a listing of aliases contained in the message. + */ + public List getAliases() + { + List aliases = new ArrayList(); + + Alias from = getFromIDAlias(); + + if( from != null ) + { + aliases.add( from ); + } + + Alias to = getToIDAlias(); + + if( to != null ) + { + aliases.add( to ); + } + + return aliases; + } } diff --git a/src/decode/ltrstandard/LTRStandardOSWMessage.java b/src/decode/ltrstandard/LTRStandardOSWMessage.java index 06b897e1..e29bb9d1 100644 --- a/src/decode/ltrstandard/LTRStandardOSWMessage.java +++ b/src/decode/ltrstandard/LTRStandardOSWMessage.java @@ -17,7 +17,9 @@ ******************************************************************************/ package decode.ltrstandard; +import java.util.ArrayList; import java.util.Date; +import java.util.List; import map.Plottable; import message.MessageDirection; @@ -219,4 +221,28 @@ public class LTRStandardOSWMessage extends LTRStandardMessage // TODO Auto-generated method stub return null; } + + /** + * Provides a listing of aliases contained in the message. + */ + public List getAliases() + { + List aliases = new ArrayList(); + + Alias from = getFromIDAlias(); + + if( from != null ) + { + aliases.add( from ); + } + + Alias to = getToIDAlias(); + + if( to != null ) + { + aliases.add( to ); + } + + return aliases; + } } diff --git a/src/decode/mdc1200/MDCMessage.java b/src/decode/mdc1200/MDCMessage.java index 3e83fa3e..4ba2738b 100644 --- a/src/decode/mdc1200/MDCMessage.java +++ b/src/decode/mdc1200/MDCMessage.java @@ -18,7 +18,9 @@ package decode.mdc1200; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Date; +import java.util.List; import map.Plottable; import message.Message; @@ -313,6 +315,30 @@ public class MDCMessage extends Message return null; } + /** + * Provides a listing of aliases contained in the message. + */ + public List getAliases() + { + List aliases = new ArrayList(); + + Alias from = getFromIDAlias(); + + if( from != null ) + { + aliases.add( from ); + } + + Alias to = getToIDAlias(); + + if( to != null ) + { + aliases.add( to ); + } + + return aliases; + } + private enum PacketType { CMND, DATA }; private enum Acknowledge { YES, NO }; private enum Direction { IN, OUT }; diff --git a/src/decode/mpt1327/MPT1327Message.java b/src/decode/mpt1327/MPT1327Message.java index 27bacd1b..6038cef5 100644 --- a/src/decode/mpt1327/MPT1327Message.java +++ b/src/decode/mpt1327/MPT1327Message.java @@ -24,6 +24,7 @@ import java.util.BitSet; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; +import java.util.List; import map.Plottable; import message.Message; @@ -1535,6 +1536,31 @@ public class MPT1327Message extends Message return sb.toString(); } + /** + * Provides a listing of aliases contained in the message. + */ + public List getAliases() + { + List aliases = new ArrayList(); + + Alias from = getFromIDAlias(); + + if( from != null ) + { + aliases.add( from ); + } + + Alias to = getToIDAlias(); + + if( to != null ) + { + aliases.add( to ); + } + + return aliases; + } + + /** * SDM Message format ICDs */ diff --git a/src/decode/passport/PassportMessage.java b/src/decode/passport/PassportMessage.java index b1f9c282..59d156e1 100644 --- a/src/decode/passport/PassportMessage.java +++ b/src/decode/passport/PassportMessage.java @@ -20,6 +20,8 @@ package decode.passport; import java.text.DecimalFormat; import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; import map.Plottable; import message.Message; @@ -621,4 +623,27 @@ public class PassportMessage extends Message return null; } + /** + * Provides a listing of aliases contained in the message. + */ + public List getAliases() + { + List aliases = new ArrayList(); + + Alias talkgroup = getTalkgroupIDAlias(); + + if( talkgroup != null ) + { + aliases.add( talkgroup ); + } + + Alias mid = getMobileIDAlias(); + + if( mid != null ) + { + aliases.add( mid ); + } + + return aliases; + } } diff --git a/src/decode/tait/Tait1200ANIMessage.java b/src/decode/tait/Tait1200ANIMessage.java index 1c472a72..968ef2ad 100644 --- a/src/decode/tait/Tait1200ANIMessage.java +++ b/src/decode/tait/Tait1200ANIMessage.java @@ -18,6 +18,8 @@ package decode.tait; import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; import map.Plottable; import message.Message; @@ -250,4 +252,28 @@ public class Tait1200ANIMessage extends Message { return null; } + + /** + * Provides a listing of aliases contained in the message. + */ + public List getAliases() + { + List aliases = new ArrayList(); + + Alias from = getFromIDAlias(); + + if( from != null ) + { + aliases.add( from ); + } + + Alias to = getToIDAlias(); + + if( to != null ) + { + aliases.add( to ); + } + + return aliases; + } } diff --git a/src/decode/tait/Tait1200GPSMessage.java b/src/decode/tait/Tait1200GPSMessage.java index 59a899d8..f68e8207 100644 --- a/src/decode/tait/Tait1200GPSMessage.java +++ b/src/decode/tait/Tait1200GPSMessage.java @@ -18,9 +18,11 @@ package decode.tait; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; +import java.util.List; import java.util.TimeZone; import map.Plottable; @@ -386,4 +388,28 @@ public class Tait1200GPSMessage extends Message return new Plottable( getGPSTime(), getGPSLocation(), getFromID(), getFromIDAlias() ); } + + /** + * Provides a listing of aliases contained in the message. + */ + public List getAliases() + { + List aliases = new ArrayList(); + + Alias from = getFromIDAlias(); + + if( from != null ) + { + aliases.add( from ); + } + + Alias to = getToIDAlias(); + + if( to != null ) + { + aliases.add( to ); + } + + return aliases; + } } diff --git a/src/message/Message.java b/src/message/Message.java index 9783b8f5..0defd5ec 100644 --- a/src/message/Message.java +++ b/src/message/Message.java @@ -18,9 +18,12 @@ package message; +import java.util.Collections; import java.util.Date; +import java.util.List; import map.Plottable; +import alias.Alias; import controller.activity.MessageDetailsProvider; public abstract class Message implements MessageDetailsProvider @@ -59,5 +62,12 @@ public abstract class Message implements MessageDetailsProvider { return mType; } - + + /** + * Provides a listing of aliases contained in the message. + */ + public List getAliases() + { + return Collections.EMPTY_LIST; + } }