mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
* #6 DMR decoder feature - work in progress * #6 DMR Decoder. * #6 DMR Decoder. Code review updates. Co-authored-by: Zhenyu Mao <maozhenyu@foxmail.com> Co-authored-by: Denny <denny@denny-desktop>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.event;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import io.github.dsheirer.module.HistoryModule;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
|
||||
/**
|
||||
* Decode event history module. Maintains a history of decode events and constrains the total history size.
|
||||
*/
|
||||
public class DecodeEventHistory extends HistoryModule<IDecodeEvent> implements IDecodeEventListener
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
*/
|
||||
public DecodeEventHistory(int historySize)
|
||||
{
|
||||
super(historySize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the IDecodeEventListener interface - delegates to receive(event) method.
|
||||
*/
|
||||
@Override
|
||||
public Listener<IDecodeEvent> getDecodeEventListener()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process preload data
|
||||
*/
|
||||
@Subscribe
|
||||
public void process(DecodeEventHistoryPreloadData preloadData)
|
||||
{
|
||||
for(IDecodeEvent decodeEvent: preloadData.getData())
|
||||
{
|
||||
receive(decodeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a request for decode event history and posts the response back
|
||||
* to the processing chain event bus so that any of the modules can receive that history.
|
||||
*
|
||||
* Note: this is principally used by the DMR decoder for Capacity+ REST channel rotation to transfer the decode
|
||||
* event history from a traffic channel conversion to the new rest channel.
|
||||
*
|
||||
* @param request for decode event history
|
||||
*/
|
||||
@Subscribe
|
||||
public void process(DecodeEventHistoryRequest request)
|
||||
{
|
||||
getInterModuleEventBus().post(new DecodeEventHistoryResponse(this));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.event;
|
||||
|
||||
import io.github.dsheirer.controller.channel.event.PreloadDataContent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Decode event history for pre-loading into a processing chain.
|
||||
*/
|
||||
public class DecodeEventHistoryPreloadData extends PreloadDataContent<List<IDecodeEvent>>
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
*
|
||||
* @param data to preload
|
||||
*/
|
||||
public DecodeEventHistoryPreloadData(List<IDecodeEvent> data)
|
||||
{
|
||||
super(data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.event;
|
||||
|
||||
import io.github.dsheirer.module.ModuleEventBusMessage;
|
||||
|
||||
/**
|
||||
* Request for decode event history from a processing chain for the specified channel.
|
||||
*/
|
||||
public class DecodeEventHistoryRequest extends ModuleEventBusMessage
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
*/
|
||||
public DecodeEventHistoryRequest()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.module.decode.event;
|
||||
|
||||
import io.github.dsheirer.module.ModuleEventBusMessage;
|
||||
|
||||
/**
|
||||
* Response to decode event history request from a processing chain for the specified channel.
|
||||
*/
|
||||
public class DecodeEventHistoryResponse extends ModuleEventBusMessage
|
||||
{
|
||||
private DecodeEventHistory mDecodeEventHistory;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param history that has a decode event history
|
||||
*/
|
||||
public DecodeEventHistoryResponse(DecodeEventHistory history)
|
||||
{
|
||||
mDecodeEventHistory = history;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode event history module
|
||||
*/
|
||||
public DecodeEventHistory getDecodeEventHistory()
|
||||
{
|
||||
return mDecodeEventHistory;
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,7 @@ public class DecodeEventModel extends AbstractTableModel implements Listener<IDe
|
||||
|
||||
public DecodeEventModel()
|
||||
{
|
||||
MyEventBus.getEventBus().register(this);
|
||||
MyEventBus.getGlobalEventBus().register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,10 +86,17 @@ public class DecodeEventModel extends AbstractTableModel implements Listener<IDe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the complete list of events managed by this model.
|
||||
*/
|
||||
public List<IDecodeEvent> getEvents()
|
||||
{
|
||||
return new ArrayList<>(mEvents);
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
MyEventBus.getEventBus().unregister(this);
|
||||
MyEventBus.getGlobalEventBus().unregister(this);
|
||||
Iterator<IDecodeEvent> it = mEvents.iterator();
|
||||
|
||||
while(it.hasNext())
|
||||
@@ -98,6 +105,16 @@ public class DecodeEventModel extends AbstractTableModel implements Listener<IDe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all events from this model and loads the events argument
|
||||
*/
|
||||
public void clearAndSet(List<IDecodeEvent> events)
|
||||
{
|
||||
mEvents.clear();
|
||||
mEvents.addAll(events);
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
dispose();
|
||||
|
||||
@@ -53,6 +53,7 @@ import java.awt.Component;
|
||||
import java.awt.EventQueue;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@@ -64,7 +65,8 @@ public class DecodeEventPanel extends JPanel implements Listener<ProcessingChain
|
||||
|
||||
private JTable mTable;
|
||||
private JTableColumnWidthMonitor mTableColumnWidthMonitor;
|
||||
private DecodeEventModel mEmptyDecodeEventModel;
|
||||
private DecodeEventModel mEventModel = new DecodeEventModel();
|
||||
private DecodeEventHistory mCurrentEventHistory;
|
||||
private JScrollPane mEmptyScroller;
|
||||
private IconModel mIconModel;
|
||||
private AliasModel mAliasModel;
|
||||
@@ -77,15 +79,14 @@ public class DecodeEventPanel extends JPanel implements Listener<ProcessingChain
|
||||
*/
|
||||
public DecodeEventPanel(IconModel iconModel, UserPreferences userPreferences, AliasModel aliasModel)
|
||||
{
|
||||
MyEventBus.getEventBus().register(this);
|
||||
MyEventBus.getGlobalEventBus().register(this);
|
||||
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill]"));
|
||||
mIconModel = iconModel;
|
||||
mAliasModel = aliasModel;
|
||||
mUserPreferences = userPreferences;
|
||||
mTimestampCellRenderer = new TimestampCellRenderer();
|
||||
mEmptyDecodeEventModel = new DecodeEventModel();
|
||||
mTable = new JTable(mEmptyDecodeEventModel);
|
||||
mTable = new JTable(mEventModel);
|
||||
mTable.setAutoCreateRowSorter(true);
|
||||
mTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
|
||||
mTableColumnWidthMonitor = new JTableColumnWidthMonitor(mUserPreferences, mTable, TABLE_PREFERENCE_KEY);
|
||||
@@ -95,6 +96,11 @@ public class DecodeEventPanel extends JPanel implements Listener<ProcessingChain
|
||||
add(mEmptyScroller);
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
MyEventBus.getGlobalEventBus().unregister(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives preference update notifications via the event bus
|
||||
* @param preferenceType that was updated
|
||||
@@ -129,20 +135,25 @@ public class DecodeEventPanel extends JPanel implements Listener<ProcessingChain
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(ProcessingChain processingChain)
|
||||
public void receive(final ProcessingChain processingChain)
|
||||
{
|
||||
if(mCurrentEventHistory != null)
|
||||
{
|
||||
mCurrentEventHistory.addListener(null);
|
||||
}
|
||||
|
||||
EventQueue.invokeLater(() -> {
|
||||
|
||||
//Dispose the current column width monitor and recreate after we swap out the table model
|
||||
mTableColumnWidthMonitor.dispose();
|
||||
mTable.setModel(processingChain != null ? processingChain.getDecodeEventModel() : mEmptyDecodeEventModel);
|
||||
|
||||
if(processingChain != null)
|
||||
{
|
||||
updateCellRenderers();
|
||||
mCurrentEventHistory = processingChain.getDecodeEventHistory();
|
||||
mEventModel.clearAndSet(mCurrentEventHistory.getItems());
|
||||
processingChain.getDecodeEventHistory().addListener(mEventModel);
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentEventHistory = null;
|
||||
mEventModel.clearAndSet(Collections.emptyList());
|
||||
}
|
||||
|
||||
mTableColumnWidthMonitor = new JTableColumnWidthMonitor(mUserPreferences, mTable, TABLE_PREFERENCE_KEY);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ package io.github.dsheirer.module.decode.event;
|
||||
|
||||
public enum DecodeEventType
|
||||
{
|
||||
AFFILIATE("Affiliate"),
|
||||
ANNOUNCEMENT("Announcement"),
|
||||
AUTOMATIC_REGISTRATION_SERVICE("Motorola ARS"),
|
||||
CALL("Call"),
|
||||
@@ -55,6 +56,7 @@ public enum DecodeEventType
|
||||
NOTIFICATION("Notification"),
|
||||
PAGE("Page"),
|
||||
QUERY("Query"),
|
||||
RADIO_CHECK("Radio Check"),
|
||||
REGISTER("Register"),
|
||||
REGISTER_ESN("ESN"),
|
||||
REQUEST("Request"),
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
package io.github.dsheirer.module.decode.event;
|
||||
|
||||
import io.github.dsheirer.filter.AllPassFilter;
|
||||
import io.github.dsheirer.filter.FilterSet;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.message.StuffBitsMessage;
|
||||
@@ -30,6 +31,7 @@ import javax.swing.table.AbstractTableModel;
|
||||
import java.awt.EventQueue;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class MessageActivityModel extends AbstractTableModel implements Listener<IMessage>
|
||||
{
|
||||
@@ -46,39 +48,49 @@ public class MessageActivityModel extends AbstractTableModel implements Listener
|
||||
|
||||
private SimpleDateFormat mSDFTime = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
|
||||
|
||||
private FilterSet<IMessage> mMessageFilter;
|
||||
|
||||
public MessageActivityModel(FilterSet<IMessage> messageFilter)
|
||||
{
|
||||
mMessageFilter = messageFilter;
|
||||
}
|
||||
private FilterSet<IMessage> mMessageFilterSet = new FilterSet<>(new AllPassFilter<>());
|
||||
|
||||
public MessageActivityModel()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the filter set
|
||||
*/
|
||||
public void setFilters(FilterSet filterSet)
|
||||
{
|
||||
mMessageFilterSet = filterSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all messages from history
|
||||
*/
|
||||
public void clear()
|
||||
{
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
EventQueue.invokeLater(() -> {
|
||||
mMessageItems.clear();
|
||||
fireTableDataChanged();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the current messages and loads the messages argument
|
||||
*/
|
||||
public void clearAndSet(List<IMessage> messages)
|
||||
{
|
||||
EventQueue.invokeLater(() -> {
|
||||
mMessageItems.clear();
|
||||
fireTableDataChanged();
|
||||
for(IMessage message: messages)
|
||||
{
|
||||
int messageCount = mMessageItems.size();
|
||||
|
||||
mMessageItems.clear();
|
||||
|
||||
fireTableRowsDeleted(0, messageCount - 1);
|
||||
receive(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public FilterSet<IMessage> getMessageFilter()
|
||||
public FilterSet<IMessage> getMessageFilterSet()
|
||||
{
|
||||
return mMessageFilter;
|
||||
return mMessageFilterSet;
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
@@ -121,7 +133,7 @@ public class MessageActivityModel extends AbstractTableModel implements Listener
|
||||
return;
|
||||
}
|
||||
|
||||
if(mMessageFilter.passes(message))
|
||||
if(mMessageFilterSet.passes(message))
|
||||
{
|
||||
final MessageItem messageItem = new MessageItem(message);
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.jidesoft.swing.JideSplitButton;
|
||||
import io.github.dsheirer.filter.FilterEditorPanel;
|
||||
import io.github.dsheirer.filter.FilterSet;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.message.MessageHistory;
|
||||
import io.github.dsheirer.module.ProcessingChain;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.swing.JTableColumnWidthMonitor;
|
||||
@@ -53,12 +54,17 @@ public class MessageActivityPanel extends JPanel implements Listener<ProcessingC
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog = LoggerFactory.getLogger(MessageActivityPanel.class);
|
||||
private static final String TABLE_PREFERENCE_KEY = "message.activity.panel";
|
||||
private static MessageActivityModel EMPTY_MODEL = new MessageActivityModel();
|
||||
private JTable mTable = new JTable(EMPTY_MODEL);
|
||||
private static MessageActivityModel mMessageModel = new MessageActivityModel();
|
||||
private MessageHistory mCurrentMessageHistory;
|
||||
private JTable mTable = new JTable(mMessageModel);
|
||||
private JTableColumnWidthMonitor mTableColumnWidthMonitor;
|
||||
private UserPreferences mUserPreferences;
|
||||
private MessageManagementPanel mManagementPanel = new MessageManagementPanel();
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param userPreferences
|
||||
*/
|
||||
public MessageActivityPanel(UserPreferences userPreferences)
|
||||
{
|
||||
mUserPreferences = userPreferences;
|
||||
@@ -71,33 +77,30 @@ public class MessageActivityPanel extends JPanel implements Listener<ProcessingC
|
||||
mTableColumnWidthMonitor = new JTableColumnWidthMonitor(mUserPreferences, mTable, TABLE_PREFERENCE_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the message activity model with message history from the specified processing chain
|
||||
*/
|
||||
@Override
|
||||
public void receive(ProcessingChain processingChain)
|
||||
{
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
if(mCurrentMessageHistory != null)
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
//Remove the existing table column width monitor and replace after swapping the table model
|
||||
mTableColumnWidthMonitor.dispose();
|
||||
mTable.setModel(processingChain != null ? processingChain.getMessageActivityModel() : EMPTY_MODEL);
|
||||
mCurrentMessageHistory.addListener(null);
|
||||
}
|
||||
|
||||
mTable.getColumnModel().getColumn(0).setPreferredWidth(18);
|
||||
mTable.getColumnModel().getColumn(1).setPreferredWidth(15);
|
||||
mTable.getColumnModel().getColumn(2).setPreferredWidth(600);
|
||||
|
||||
if(processingChain != null)
|
||||
{
|
||||
mManagementPanel.enableButtons();
|
||||
}
|
||||
else
|
||||
{
|
||||
mManagementPanel.disableButtons();
|
||||
}
|
||||
mTableColumnWidthMonitor = new JTableColumnWidthMonitor(mUserPreferences, mTable, TABLE_PREFERENCE_KEY);
|
||||
}
|
||||
});
|
||||
if(processingChain != null)
|
||||
{
|
||||
mCurrentMessageHistory = processingChain.getMessageHistory();
|
||||
mMessageModel.clearAndSet(mCurrentMessageHistory.getItems());
|
||||
mCurrentMessageHistory.addListener(mMessageModel);
|
||||
mManagementPanel.enableButtons();
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentMessageHistory = null;
|
||||
mMessageModel.clear();
|
||||
mManagementPanel.disableButtons();
|
||||
}
|
||||
}
|
||||
|
||||
public class MessageManagementPanel extends JPanel
|
||||
@@ -227,7 +230,7 @@ public class MessageActivityPanel extends JPanel implements Listener<ProcessingC
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
FilterSet<IMessage> filter = (FilterSet<IMessage>) ((MessageActivityModel) mTable.getModel())
|
||||
.getMessageFilter();
|
||||
.getMessageFilterSet();
|
||||
|
||||
FilterEditorPanel<IMessage> panel = new FilterEditorPanel<>(filter);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user