mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
Updates pull request from Roman Tsypuk to convert the build system from
ant to gradle. Removes linux and windows application launch scripts and produces an executable jar with all resources included.
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
/*******************************************************************************
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.module.decode.event;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
public class ActivitySummaryFrame extends JFrame
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ActivitySummaryFrame( String summary )
|
||||
{
|
||||
this( summary, null );
|
||||
}
|
||||
|
||||
public ActivitySummaryFrame( String summary, Component displayOver )
|
||||
{
|
||||
setTitle( "Activity Summary" );
|
||||
setLocationRelativeTo( displayOver );
|
||||
setSize( 400, 400 );
|
||||
setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
|
||||
setLayout( new MigLayout( "", "[grow,fill]", "[grow,fill][]" ) );
|
||||
|
||||
JTextArea summaryText = new JTextArea( summary );
|
||||
|
||||
JScrollPane scroller = new JScrollPane( summaryText );
|
||||
scroller.setViewportView( summaryText );
|
||||
|
||||
add( scroller, "wrap" );
|
||||
|
||||
JButton close = new JButton( "Close" );
|
||||
close.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
} );
|
||||
|
||||
add( close );
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
setVisible( true );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.module.decode.event;
|
||||
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
|
||||
public interface ActivitySummaryProvider extends Listener<Message>
|
||||
{
|
||||
public String getActivitySummary();
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
/*******************************************************************************
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.module.decode.event;
|
||||
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public abstract class CallEvent implements Comparable<CallEvent>
|
||||
{
|
||||
protected long mEventStart = System.currentTimeMillis();
|
||||
protected long mEventEnd;
|
||||
|
||||
private SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyyMMdd");
|
||||
private SimpleDateFormat TIME_FORMATTER = new SimpleDateFormat("HHmmss");
|
||||
|
||||
protected DecoderType mDecoderType;
|
||||
protected CallEventType mCallEventType;
|
||||
protected AliasList mAliasList;
|
||||
protected String mFromID;
|
||||
protected String mToID;
|
||||
protected String mDetails;
|
||||
|
||||
private boolean mValid = true;
|
||||
|
||||
public CallEvent(DecoderType decoder, CallEventType callEventType, AliasList aliasList, String fromID,
|
||||
String toID, String details)
|
||||
{
|
||||
mDecoderType = decoder;
|
||||
mCallEventType = callEventType;
|
||||
mAliasList = aliasList;
|
||||
mFromID = fromID;
|
||||
mToID = toID;
|
||||
mDetails = details;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this event is valid. Use this method to mark a previously
|
||||
* dispatched event as invalid and resend it so that any downstream
|
||||
* processing can remove the invalid event.
|
||||
*/
|
||||
public void setValid(boolean valid)
|
||||
{
|
||||
mValid = valid;
|
||||
}
|
||||
|
||||
public boolean isValid()
|
||||
{
|
||||
return mValid;
|
||||
}
|
||||
|
||||
public void setEnd(long end)
|
||||
{
|
||||
mEventEnd = end;
|
||||
}
|
||||
|
||||
public void end()
|
||||
{
|
||||
setEnd(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public DecoderType getDecoderType()
|
||||
{
|
||||
return mDecoderType;
|
||||
}
|
||||
|
||||
public CallEventType getCallEventType()
|
||||
{
|
||||
return mCallEventType;
|
||||
}
|
||||
|
||||
public void setCallEventType(CallEventType type)
|
||||
{
|
||||
mCallEventType = type;
|
||||
}
|
||||
|
||||
public AliasList getAliasList()
|
||||
{
|
||||
return mAliasList;
|
||||
}
|
||||
|
||||
public void setAliasList(AliasList aliasList)
|
||||
{
|
||||
mAliasList = aliasList;
|
||||
}
|
||||
|
||||
public boolean hasAliasList()
|
||||
{
|
||||
return mAliasList != null;
|
||||
}
|
||||
|
||||
public long getEventStartTime()
|
||||
{
|
||||
return mEventStart;
|
||||
}
|
||||
|
||||
public long getEventEndTime()
|
||||
{
|
||||
return mEventEnd;
|
||||
}
|
||||
|
||||
public String getFromID()
|
||||
{
|
||||
return mFromID;
|
||||
}
|
||||
|
||||
public boolean hasFromID()
|
||||
{
|
||||
return mFromID != null;
|
||||
}
|
||||
|
||||
public void setFromID(String id)
|
||||
{
|
||||
mFromID = id;
|
||||
}
|
||||
|
||||
public String getToID()
|
||||
{
|
||||
return mToID;
|
||||
}
|
||||
|
||||
public boolean hasToID()
|
||||
{
|
||||
return mToID != null;
|
||||
}
|
||||
|
||||
public void setToID(String id)
|
||||
{
|
||||
mToID = id;
|
||||
}
|
||||
|
||||
public String getDetails()
|
||||
{
|
||||
return mDetails;
|
||||
}
|
||||
|
||||
public void setDetails(String details)
|
||||
{
|
||||
mDetails = details;
|
||||
}
|
||||
|
||||
public abstract Alias getFromIDAlias();
|
||||
|
||||
public abstract Alias getToIDAlias();
|
||||
|
||||
public abstract String getChannel();
|
||||
|
||||
public abstract long getFrequency();
|
||||
|
||||
public static String getCSVHeader()
|
||||
{
|
||||
return "START_DATE,START_TIME,END_DATE,END_TIME,DECODER,EVENT,FROM,FROM_ALIAS,TO,TO_ALIAS,CHANNEL," +
|
||||
"FREQUENCY,DETAILS";
|
||||
}
|
||||
|
||||
public String toCSV()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("'");
|
||||
|
||||
Date eventStart = new Date(getEventStartTime());
|
||||
sb.append(DATE_FORMATTER.format(eventStart));
|
||||
sb.append("','");
|
||||
sb.append(TIME_FORMATTER.format(eventStart));
|
||||
sb.append("','");
|
||||
if(mEventEnd != 0)
|
||||
{
|
||||
Date eventEnd = new Date(getEventEndTime());
|
||||
sb.append(DATE_FORMATTER.format(eventEnd));
|
||||
sb.append("','");
|
||||
sb.append(TIME_FORMATTER.format(eventEnd));
|
||||
sb.append("','");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("','',");
|
||||
}
|
||||
sb.append("','");
|
||||
sb.append(getDecoderType().toString());
|
||||
sb.append("','");
|
||||
sb.append(getCallEventType().toString());
|
||||
sb.append("',");
|
||||
if(getFromID() != null)
|
||||
{
|
||||
sb.append("'");
|
||||
sb.append(getFromID());
|
||||
sb.append("'");
|
||||
}
|
||||
sb.append(",");
|
||||
|
||||
Alias fromAlias = getFromIDAlias();
|
||||
|
||||
if(fromAlias != null)
|
||||
{
|
||||
sb.append("'");
|
||||
sb.append(fromAlias.getName());
|
||||
sb.append("'");
|
||||
}
|
||||
sb.append(",");
|
||||
|
||||
if(getToID() != null)
|
||||
{
|
||||
sb.append("'");
|
||||
sb.append(getToID());
|
||||
sb.append("'");
|
||||
}
|
||||
sb.append(",");
|
||||
|
||||
Alias toAlias = getToIDAlias();
|
||||
|
||||
if(toAlias != null)
|
||||
{
|
||||
sb.append("'");
|
||||
sb.append(toAlias.getName());
|
||||
sb.append("'");
|
||||
}
|
||||
sb.append(",'");
|
||||
sb.append(getChannel());
|
||||
sb.append("','");
|
||||
sb.append(getFrequency());
|
||||
sb.append("',");
|
||||
if(getDetails() != null)
|
||||
{
|
||||
sb.append("'");
|
||||
sb.append(getDetails());
|
||||
sb.append("'");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public enum CallEventType
|
||||
{
|
||||
ANNOUNCEMENT("Announcement"),
|
||||
CALL("Call"),
|
||||
CALL_ALERT("Call Alert"),
|
||||
CALL_DETECT("Call Detect"),
|
||||
CALL_DO_NOT_MONITOR("Call-Do Not Monitor"),
|
||||
CALL_END("Call End"),
|
||||
CALL_UNIQUE_ID("UID Call"),
|
||||
CALL_NO_TUNER("Call - No Tuner"),
|
||||
CALL_TIMEOUT("Call Timeout"),
|
||||
COMMAND("Command"),
|
||||
DATA_CALL("Data Call"),
|
||||
DEREGISTER("Deregister"),
|
||||
EMERGENCY("EMERGENCY"),
|
||||
ENCRYPTED_CALL("Encrypted Call"),
|
||||
FUNCTION("Function"),
|
||||
GPS("GPS"),
|
||||
GROUP_CALL("Group Call"),
|
||||
ID_ANI("ANI"),
|
||||
ID_UNIQUE("Unique ID"),
|
||||
NOTIFICATION("Notification"),
|
||||
PAGE("Page"),
|
||||
PATCH_GROUP_ADD("Patch Group Add"),
|
||||
PATCH_GROUP_CALL("Patch Group Call"),
|
||||
PATCH_GROUP_DELETE("Patch Group Delete"),
|
||||
QUERY("Query"),
|
||||
REGISTER("Register"),
|
||||
REGISTER_ESN("ESN"),
|
||||
RESPONSE("Response"),
|
||||
SDM("Short Data Message"),
|
||||
STATION_ID("Station ID"),
|
||||
STATUS("Status"),
|
||||
TELEPHONE_INTERCONNECT("Telephone Interconnect"),
|
||||
UNIT_TO_UNIT_CALL("Unit To Unit Call"),
|
||||
UNKNOWN("Unknown"),
|
||||
INVALID("Invalid");
|
||||
|
||||
private String mLabel;
|
||||
|
||||
private CallEventType(String label)
|
||||
{
|
||||
mLabel = label;
|
||||
}
|
||||
|
||||
public String getLabel()
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(CallEvent other)
|
||||
{
|
||||
if(other != null && other == this)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Long.compare(mEventStart, other.getEventStartTime());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*******************************************************************************
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.module.decode.event;
|
||||
|
||||
import io.github.dsheirer.icon.IconManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* Custom renderer for JTable cells that contain Alias objects. Renders the
|
||||
* alias name, and if there is an icon name, attempts to get that icon from
|
||||
* the settings manager and render it.
|
||||
*/
|
||||
public class CallEventAliasCellRenderer extends DefaultTableCellRenderer
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog = LoggerFactory.getLogger(CallEventAliasCellRenderer.class);
|
||||
|
||||
private IconManager mIconManager;
|
||||
|
||||
public CallEventAliasCellRenderer(IconManager iconManager)
|
||||
{
|
||||
super();
|
||||
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);
|
||||
|
||||
if(value instanceof Alias)
|
||||
{
|
||||
Alias alias = (Alias)value;
|
||||
|
||||
label.setText(alias.getName());
|
||||
label.setForeground(alias.getDisplayColor());
|
||||
label.setIcon(mIconManager.getIcon(alias.getIconName(), IconManager.DEFAULT_ICON_SIZE));
|
||||
}
|
||||
else
|
||||
{
|
||||
label.setText("");
|
||||
label.setForeground(table.getForeground());
|
||||
label.setIcon(null);
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014,2015 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.module.decode.event;
|
||||
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CallEventModel extends AbstractTableModel implements Listener<CallEvent>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static DecimalFormat mFrequencyFormatter = new DecimalFormat("0.000000");
|
||||
|
||||
public static final int TIME = 0;
|
||||
public static final int EVENT = 1;
|
||||
public static final int FROM_ID = 2;
|
||||
public static final int FROM_ALIAS = 3;
|
||||
public static final int TO_ID = 4;
|
||||
public static final int TO_ALIAS = 5;
|
||||
public static final int CHANNEL = 6;
|
||||
public static final int FREQUENCY = 7;
|
||||
public static final int DETAILS = 8;
|
||||
|
||||
protected int mMaxMessages = 500;
|
||||
|
||||
protected List<CallEvent> mEvents = new ArrayList<CallEvent>();
|
||||
|
||||
protected String[] mHeaders = new String[]{"Time",
|
||||
"Event",
|
||||
"From",
|
||||
"Alias",
|
||||
"To",
|
||||
"Alias",
|
||||
"Channel",
|
||||
"Frequency",
|
||||
"Details"};
|
||||
|
||||
private SimpleDateFormat mSDFTime = new SimpleDateFormat("HH:mm:ss");
|
||||
|
||||
public CallEventModel()
|
||||
{
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
mEvents.clear();
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
mEvents.clear();
|
||||
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
public int getMaxMessageCount()
|
||||
{
|
||||
return mMaxMessages;
|
||||
}
|
||||
|
||||
public void setMaxMessageCount(int count)
|
||||
{
|
||||
mMaxMessages = count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds, updates or deletes the event from the model. Producers can send
|
||||
* the same call event multiple times to indicate that information in the
|
||||
* event is updated. Producers can also mark the event as invalid and the
|
||||
* event will be removed from the model.
|
||||
*/
|
||||
public void receive(final CallEvent event)
|
||||
{
|
||||
if(event.isValid())
|
||||
{
|
||||
if(!mEvents.contains(event))
|
||||
{
|
||||
mEvents.add(0, event);
|
||||
|
||||
fireTableRowsInserted(0, 0);
|
||||
|
||||
prune();
|
||||
}
|
||||
else
|
||||
{
|
||||
int row = mEvents.indexOf(event);
|
||||
|
||||
fireTableRowsUpdated(row, row);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mEvents.contains(event))
|
||||
{
|
||||
int row = mEvents.indexOf(event);
|
||||
|
||||
mEvents.remove(event);
|
||||
|
||||
fireTableRowsDeleted(row, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void prune()
|
||||
{
|
||||
while(mEvents.size() > mMaxMessages)
|
||||
{
|
||||
int index = mEvents.size() - 1;
|
||||
mEvents.remove(index);
|
||||
|
||||
fireTableRowsDeleted(index, index);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount()
|
||||
{
|
||||
return mEvents.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount()
|
||||
{
|
||||
return mHeaders.length;
|
||||
}
|
||||
|
||||
public String getColumnName(int column)
|
||||
{
|
||||
return mHeaders[column];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int rowIndex, int columnIndex)
|
||||
{
|
||||
synchronized(mEvents)
|
||||
{
|
||||
switch(columnIndex)
|
||||
{
|
||||
case TIME:
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append(mSDFTime.format(
|
||||
mEvents.get(rowIndex).getEventStartTime()));
|
||||
|
||||
if(mEvents.get(rowIndex).getEventEndTime() != 0)
|
||||
{
|
||||
sb.append(" - ");
|
||||
sb.append(mSDFTime.format(
|
||||
mEvents.get(rowIndex).getEventEndTime()));
|
||||
}
|
||||
else if(mEvents.get(rowIndex)
|
||||
.getCallEventType() == CallEvent.CallEventType.CALL)
|
||||
{
|
||||
sb.append(" - In Progress");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
case EVENT:
|
||||
return mEvents.get(rowIndex).getCallEventType();
|
||||
case FROM_ID:
|
||||
return mEvents.get(rowIndex).getFromID();
|
||||
case FROM_ALIAS:
|
||||
return mEvents.get(rowIndex).getFromIDAlias();
|
||||
case TO_ID:
|
||||
return mEvents.get(rowIndex).getToID();
|
||||
case TO_ALIAS:
|
||||
return mEvents.get(rowIndex).getToIDAlias();
|
||||
case CHANNEL:
|
||||
return mEvents.get(rowIndex).getChannel();
|
||||
case FREQUENCY:
|
||||
long frequency = mEvents.get(rowIndex).getFrequency();
|
||||
|
||||
if(frequency != 0)
|
||||
{
|
||||
return mFrequencyFormatter.format((double) frequency / 1E6d);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
case DETAILS:
|
||||
return mEvents.get(rowIndex).getDetails();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getColumnClass(int columnIndex)
|
||||
{
|
||||
if(columnIndex == FROM_ALIAS || columnIndex == TO_ALIAS)
|
||||
{
|
||||
return Alias.class;
|
||||
}
|
||||
|
||||
return super.getColumnClass(columnIndex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*******************************************************************************
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.module.decode.event;
|
||||
|
||||
import io.github.dsheirer.icon.IconManager;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import io.github.dsheirer.module.ProcessingChain;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class CallEventPanel extends JPanel implements Listener<ProcessingChain>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private JTable mTable;
|
||||
private CallEventModel mEmptyCallEventModel = new CallEventModel();
|
||||
private JScrollPane mEmptyScroller;
|
||||
private CallEventAliasCellRenderer mRenderer;
|
||||
|
||||
/**
|
||||
* View for call event table
|
||||
* @param iconManager to display alias icons in table rows
|
||||
*/
|
||||
public CallEventPanel(IconManager iconManager)
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill]"));
|
||||
|
||||
mTable = new JTable(mEmptyCallEventModel);
|
||||
mTable.setAutoCreateRowSorter(true);
|
||||
mTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
|
||||
|
||||
mRenderer = new CallEventAliasCellRenderer(iconManager);
|
||||
|
||||
|
||||
mEmptyScroller = new JScrollPane(mTable);
|
||||
|
||||
add(mEmptyScroller);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(ProcessingChain processingChain)
|
||||
{
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mTable.setModel(processingChain != null ? processingChain.getCallEventModel() : mEmptyCallEventModel);
|
||||
|
||||
if(processingChain != null)
|
||||
{
|
||||
mTable.getColumnModel().getColumn(CallEventModel.FROM_ALIAS).setCellRenderer(mRenderer);
|
||||
mTable.getColumnModel().getColumn(CallEventModel.TO_ALIAS).setCellRenderer(mRenderer);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package io.github.dsheirer.module.decode.event;
|
||||
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
|
||||
public interface ICallEventListener
|
||||
{
|
||||
public Listener<CallEvent> getCallEventListener();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package io.github.dsheirer.module.decode.event;
|
||||
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
|
||||
public interface ICallEventProvider
|
||||
{
|
||||
public void addCallEventListener( Listener<CallEvent> listener );
|
||||
public void removeCallEventListener( Listener<CallEvent> listener );
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
/*******************************************************************************
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.module.decode.event;
|
||||
|
||||
import io.github.dsheirer.filter.FilterSet;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import java.awt.*;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class MessageActivityModel extends AbstractTableModel
|
||||
implements Listener<Message>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final int TIME = 0;
|
||||
private static final int PROTOCOL = 1;
|
||||
private static final int ERROR_STATUS = 2;
|
||||
private static final int MESSAGE = 3;
|
||||
private static final int MESSAGE_BITS = 4;
|
||||
|
||||
protected int mMaxMessages = 500;
|
||||
protected LinkedList<Message> mMessages = new LinkedList<Message>();
|
||||
|
||||
protected int[] mColumnWidths = { 110, 110, 110, -1, -1 };
|
||||
|
||||
protected String[] mHeaders = new String[] { "Time",
|
||||
"Protocol",
|
||||
"Error Check",
|
||||
"Message",
|
||||
"Binary" };
|
||||
|
||||
private SimpleDateFormat mSDFTime = new SimpleDateFormat( "HH:mm:ss" );
|
||||
|
||||
private boolean mNewMessagesFirst = true;
|
||||
|
||||
private FilterSet<Message> mMessageFilter;
|
||||
|
||||
public MessageActivityModel( FilterSet<Message> messageFilter )
|
||||
{
|
||||
mMessageFilter = messageFilter;
|
||||
}
|
||||
|
||||
public MessageActivityModel()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all messages from history
|
||||
*/
|
||||
public void clear()
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
int messageCount = mMessages.size();
|
||||
|
||||
mMessages.clear();
|
||||
|
||||
fireTableRowsDeleted( 0, messageCount - 1 );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public FilterSet<Message> getMessageFilter()
|
||||
{
|
||||
return mMessageFilter;
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
mMessages.clear();
|
||||
}
|
||||
|
||||
public int[] getColumnWidths()
|
||||
{
|
||||
return mColumnWidths;
|
||||
}
|
||||
|
||||
public void setColumnWidths( int[] widths )
|
||||
{
|
||||
if( widths.length != 5 )
|
||||
{
|
||||
throw new IllegalArgumentException( "MessageActivityModel - "
|
||||
+ "column widths array should have 5 elements" );
|
||||
}
|
||||
else
|
||||
{
|
||||
mColumnWidths = widths;
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaxMessageCount()
|
||||
{
|
||||
return mMaxMessages;
|
||||
}
|
||||
|
||||
public void setMaxMessageCount( int count )
|
||||
{
|
||||
mMaxMessages = count;
|
||||
}
|
||||
|
||||
public void receive( final Message message )
|
||||
{
|
||||
if( message.isValid() && mMessageFilter.passes( message ) )
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mMessages.addFirst( message );
|
||||
|
||||
MessageActivityModel.this.fireTableRowsInserted( 0, 0 );
|
||||
|
||||
prune();
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
private void prune()
|
||||
{
|
||||
while( mMessages.size() > mMaxMessages )
|
||||
{
|
||||
mMessages.removeLast();
|
||||
|
||||
super.fireTableRowsDeleted( mMessages.size() - 1, mMessages.size() - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount()
|
||||
{
|
||||
return mMessages.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount()
|
||||
{
|
||||
return mHeaders.length;
|
||||
}
|
||||
|
||||
public String getColumnName( int column )
|
||||
{
|
||||
return mHeaders[ column ];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt( int rowIndex, int columnIndex )
|
||||
{
|
||||
if( 0 <= rowIndex && rowIndex < mMessages.size() )
|
||||
{
|
||||
Message message = mMessages.get( rowIndex );
|
||||
|
||||
switch( columnIndex )
|
||||
{
|
||||
case TIME:
|
||||
return mSDFTime.format( new Date( message.getTimeReceived() ) );
|
||||
case PROTOCOL:
|
||||
return message.getProtocol();
|
||||
case ERROR_STATUS:
|
||||
return message.getErrorStatus();
|
||||
case MESSAGE:
|
||||
return message.getMessage();
|
||||
case MESSAGE_BITS:
|
||||
return message.getBinaryMessage();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
/*******************************************************************************
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.module.decode.event;
|
||||
|
||||
import com.jidesoft.swing.JideButton;
|
||||
import com.jidesoft.swing.JideSplitButton;
|
||||
import io.github.dsheirer.controller.channel.ChannelProcessingManager;
|
||||
import io.github.dsheirer.filter.FilterEditorPanel;
|
||||
import io.github.dsheirer.filter.FilterSet;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.module.ProcessingChain;
|
||||
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 java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
|
||||
public class MessageActivityPanel extends JPanel implements Listener<ProcessingChain>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static Logger mLog = LoggerFactory.getLogger(MessageActivityPanel.class);
|
||||
|
||||
private static MessageActivityModel EMPTY_MODEL = new MessageActivityModel();
|
||||
|
||||
private JTable mTable = new JTable(EMPTY_MODEL);
|
||||
|
||||
private MessageManagementPanel mManagementPanel = new MessageManagementPanel();
|
||||
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
|
||||
public MessageActivityPanel(ChannelProcessingManager channelProcessingManager)
|
||||
{
|
||||
mChannelProcessingManager = channelProcessingManager;
|
||||
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[][grow,fill]", "[]0[grow,fill]"));
|
||||
|
||||
add(mManagementPanel, "span,growx");
|
||||
|
||||
add(new JScrollPane(mTable), "span,grow");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(ProcessingChain processingChain)
|
||||
{
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mTable.setModel(processingChain != null ? processingChain.getMessageActivityModel() : EMPTY_MODEL);
|
||||
|
||||
if(processingChain != null)
|
||||
{
|
||||
mManagementPanel.enableButtons();
|
||||
}
|
||||
else
|
||||
{
|
||||
mManagementPanel.disableButtons();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void channelChanged(ChannelEvent event)
|
||||
// {
|
||||
// boolean changed = false;
|
||||
//
|
||||
// if(event.getEvent() == Event.NOTIFICATION_SELECTION_CHANGE &&
|
||||
// event.getChannel().isSelected())
|
||||
// {
|
||||
// if(mDisplayedChannel == null || (mDisplayedChannel != null && mDisplayedChannel != event.getChannel()))
|
||||
// {
|
||||
// mDisplayedChannel = event.getChannel();
|
||||
//
|
||||
// ProcessingChain chain = mChannelProcessingManager.getProcessingChain(mDisplayedChannel);
|
||||
//
|
||||
// if(chain != null)
|
||||
// {
|
||||
// mDisplayedModel = chain.getMessageActivityModel();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// mDisplayedModel = EMPTY_MODEL;
|
||||
// }
|
||||
//
|
||||
// mMessageTable.setModel(mDisplayedModel);
|
||||
//
|
||||
// if(mDisplayedChannel != null)
|
||||
// {
|
||||
// mManagementPanel.enableButtons();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// mManagementPanel.disableButtons();
|
||||
// }
|
||||
//
|
||||
// changed = true;
|
||||
// }
|
||||
// }
|
||||
// else if(event.getEvent() == Event.NOTIFICATION_PROCESSING_STOP || event.getEvent() == Event.REQUEST_DISABLE)
|
||||
// {
|
||||
// if(mDisplayedChannel != null && mDisplayedChannel == event.getChannel())
|
||||
// {
|
||||
// mDisplayedChannel = null;
|
||||
//
|
||||
// mMessageTable.setModel(EMPTY_MODEL);
|
||||
//
|
||||
// mManagementPanel.disableButtons();
|
||||
//
|
||||
// changed = true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if(changed)
|
||||
// {
|
||||
// revalidate();
|
||||
// repaint();
|
||||
// }
|
||||
// }
|
||||
|
||||
public class MessageManagementPanel extends JPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private MessageHistoryButton mHistoryButton = new MessageHistoryButton();
|
||||
private MessageFilterButton mFilterButton = new MessageFilterButton();
|
||||
|
||||
public MessageManagementPanel()
|
||||
{
|
||||
setLayout(new MigLayout("insets 2 2 5 5", "[]5[left,grow]", ""));
|
||||
|
||||
disableButtons();
|
||||
|
||||
add(mFilterButton);
|
||||
add(mHistoryButton);
|
||||
}
|
||||
|
||||
public void enableButtons()
|
||||
{
|
||||
mHistoryButton.setEnabled(true);
|
||||
mFilterButton.setEnabled(true);
|
||||
}
|
||||
|
||||
public void disableButtons()
|
||||
{
|
||||
mHistoryButton.setEnabled(false);
|
||||
mFilterButton.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
public class MessageHistoryButton extends JideSplitButton
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public MessageHistoryButton()
|
||||
{
|
||||
super("Clear");
|
||||
|
||||
JPanel historyPanel = new JPanel();
|
||||
|
||||
historyPanel.add(new JLabel("Message History:"));
|
||||
|
||||
final JSlider slider = new JSlider();
|
||||
slider.setMinimum(0);
|
||||
slider.setMaximum(2000);
|
||||
slider.setMajorTickSpacing(500);
|
||||
slider.setPaintTicks(true);
|
||||
slider.setPaintLabels(true);
|
||||
|
||||
slider.addMouseListener(new MouseListener()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent arg0)
|
||||
{
|
||||
if(SwingUtilities.isLeftMouseButton(arg0) && arg0.getClickCount() == 2)
|
||||
{
|
||||
slider.setValue(500); //default
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseEntered(MouseEvent arg0)
|
||||
{
|
||||
}
|
||||
|
||||
public void mouseExited(MouseEvent arg0)
|
||||
{
|
||||
}
|
||||
|
||||
public void mousePressed(MouseEvent arg0)
|
||||
{
|
||||
}
|
||||
|
||||
public void mouseReleased(MouseEvent arg0)
|
||||
{
|
||||
}
|
||||
});
|
||||
|
||||
slider.setValue(((MessageActivityModel)mTable.getModel()).getMaxMessageCount());
|
||||
slider.addChangeListener(new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent arg0)
|
||||
{
|
||||
((MessageActivityModel)mTable.getModel()).setMaxMessageCount(slider.getValue());
|
||||
}
|
||||
});
|
||||
|
||||
historyPanel.add(slider);
|
||||
|
||||
add(historyPanel);
|
||||
|
||||
/* Clear messages */
|
||||
addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
((MessageActivityModel)mTable.getModel()).clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class MessageFilterButton extends JideButton
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public MessageFilterButton()
|
||||
{
|
||||
super("Filter");
|
||||
|
||||
addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
final JFrame editor = new JFrame();
|
||||
|
||||
editor.setTitle("Message Filter Editor");
|
||||
editor.setSize(600, 400);
|
||||
editor.setLocationRelativeTo(MessageFilterButton.this);
|
||||
editor.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||
editor.setLayout(new MigLayout("", "[grow,fill]",
|
||||
"[grow,fill][][]"));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
FilterSet<Message> filter = (FilterSet<Message>) ((MessageActivityModel)mTable.getModel()).getMessageFilter();
|
||||
|
||||
FilterEditorPanel<Message> panel = new FilterEditorPanel<Message>(filter);
|
||||
|
||||
JScrollPane scroller = new JScrollPane(panel);
|
||||
scroller.setViewportView(panel);
|
||||
|
||||
editor.add(scroller, "wrap");
|
||||
|
||||
editor.add(new JLabel("Right-click to select/deselect all nodes"), "wrap");
|
||||
|
||||
JButton close = new JButton("Close");
|
||||
close.addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
editor.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
editor.add(close);
|
||||
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
editor.setVisible(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user