Files
sdrtrunk/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataModel.java
Denny Sheirer 7eec82deee #6 DMR Decoder (#947)
* #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>
2020-10-12 04:57:59 -04:00

321 lines
11 KiB
Java

/*
*
* * ******************************************************************************
* * 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.channel.metadata;
import com.google.common.eventbus.Subscribe;
import io.github.dsheirer.alias.Alias;
import io.github.dsheirer.controller.channel.Channel;
import io.github.dsheirer.eventbus.MyEventBus;
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.identifier.decoder.DecoderLogicalChannelNameIdentifier;
import io.github.dsheirer.preference.PreferenceType;
import io.github.dsheirer.sample.Listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.table.AbstractTableModel;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ChannelMetadataModel extends AbstractTableModel implements IChannelMetadataUpdateListener
{
private final static Logger mLog = LoggerFactory.getLogger(ChannelMetadataModel.class);
public static final int COLUMN_DECODER_STATE = 0;
public static final int COLUMN_DECODER_TYPE = 1;
public static final int COLUMN_USER_FROM = 2;
public static final int COLUMN_USER_FROM_ALIAS = 3;
public static final int COLUMN_USER_TO = 4;
public static final int COLUMN_USER_TO_ALIAS = 5;
public static final int COLUMN_DECODER_LOGICAL_CHANNEL_NAME = 6;
public static final int COLUMN_CONFIGURATION_FREQUENCY = 7;
public static final int COLUMN_CONFIGURATION_CHANNEL = 8;
private static final String[] COLUMNS = {"Status", "Decoder", "From", "Alias", "To", "Alias", "Channel", "Frequency", "Channel Name"};
private List<ChannelMetadata> mChannelMetadata = new ArrayList();
private Map<ChannelMetadata,Channel> mMetadataChannelMap = new HashMap();
private Listener<ChannelAndMetadata> mChannelAddListener;
public ChannelMetadataModel()
{
MyEventBus.getGlobalEventBus().register(this);
}
/**
* Receives preference update notifications via the event bus
* @param preferenceType that was updated
*/
@Subscribe
public void preferenceUpdated(PreferenceType preferenceType)
{
if(preferenceType == PreferenceType.TALKGROUP_FORMAT)
{
EventQueue.invokeLater(() -> {
for(int row = 0; row < mChannelMetadata.size(); row++)
{
fireTableCellUpdated(row, COLUMN_USER_FROM);
fireTableCellUpdated(row, COLUMN_USER_TO);
}
});
}
}
public void dispose()
{
MyEventBus.getGlobalEventBus().unregister(this);
}
/**
* Lookup model row for the specified channel metadata
*/
public int getRow(ChannelMetadata channelMetadata)
{
if(mChannelMetadata.contains(channelMetadata))
{
return mChannelMetadata.indexOf(channelMetadata);
}
return -1;
}
/**
* Registers the listener to be notified when channel metadata(s) are added to the model.
* @param listener to receive channel associated with the channel metadata(s) that were added
*/
public void setChannelAddListener(Listener<ChannelAndMetadata> listener)
{
mChannelAddListener = listener;
}
public void add(ChannelAndMetadata channelAndMetadata)
{
//Execute on the swing thread to avoid threading issues
EventQueue.invokeLater(() -> {
for(ChannelMetadata channelMetadata: channelAndMetadata.getChannelMetadata())
{
mChannelMetadata.add(channelMetadata);
mMetadataChannelMap.put(channelMetadata, channelAndMetadata.getChannel());
int index = mChannelMetadata.indexOf(channelMetadata);
fireTableRowsInserted(index, index);
channelMetadata.setUpdateEventListener(ChannelMetadataModel.this);
}
if(mChannelAddListener != null)
{
mChannelAddListener.receive(channelAndMetadata);
}
});
}
/**
* Updates the mapping of channel metadata to the channel used to create the channel metadatas (and processing chain)
* @param channelMetadatas
* @param channel
*/
public void updateChannelMetadataToChannelMap(Collection<ChannelMetadata> channelMetadatas, Channel channel)
{
for(ChannelMetadata channelMetadata: channelMetadatas)
{
mMetadataChannelMap.put(channelMetadata, channel);
}
}
public void remove(ChannelMetadata channelMetadata)
{
//Execute on the swing thread to avoid threading issues
EventQueue.invokeLater(() -> {
channelMetadata.removeUpdateEventListener();
int index = mChannelMetadata.indexOf(channelMetadata);
mChannelMetadata.remove(channelMetadata);
mMetadataChannelMap.remove(channelMetadata);
if(index >= 0)
{
fireTableRowsDeleted(index, index);
}
});
}
/**
* Get the channel metadata at the specified model row index
*/
public ChannelMetadata getChannelMetadata(int row)
{
if(row < mChannelMetadata.size())
{
return mChannelMetadata.get(row);
}
return null;
}
/**
* Returns the channel that matches the metadata or null
*/
public Channel getChannelFromMetadata(ChannelMetadata channelMetadata)
{
return mMetadataChannelMap.get(channelMetadata);
}
@Override
public int getRowCount()
{
return mChannelMetadata.size();
}
@Override
public int getColumnCount()
{
return COLUMNS.length;
}
@Override
public String getColumnName(int column)
{
return COLUMNS[column];
}
@Override
public Class<?> getColumnClass(int columnIndex)
{
switch(columnIndex)
{
case COLUMN_USER_FROM:
case COLUMN_USER_TO:
return ChannelMetadata.class;
case COLUMN_USER_FROM_ALIAS:
case COLUMN_USER_TO_ALIAS:
return Alias.class;
case COLUMN_DECODER_LOGICAL_CHANNEL_NAME:
return String.class;
default:
return Identifier.class;
}
}
@Override
public Object getValueAt(int rowIndex, int columnIndex)
{
if(rowIndex <= mChannelMetadata.size())
{
ChannelMetadata channelMetadata = mChannelMetadata.get(rowIndex);
switch(columnIndex)
{
case COLUMN_DECODER_STATE:
return channelMetadata.getChannelStateIdentifier();
case COLUMN_DECODER_TYPE:
return channelMetadata.getDecoderTypeConfigurationIdentifier();
case COLUMN_DECODER_LOGICAL_CHANNEL_NAME:
DecoderLogicalChannelNameIdentifier id = channelMetadata.getDecoderLogicalChannelNameIdentifier();
if(channelMetadata.hasTimeslot())
{
if(id == null)
{
return "TS:" + channelMetadata.getTimeslot();
}
else
{
String value = id.getValue().replace(" TS0", "").replace(" TS1", "");
return value + " TS:" + channelMetadata.getTimeslot();
}
}
else
{
if(id == null)
{
return null;
}
else
{
return id.getValue();
}
}
case COLUMN_CONFIGURATION_FREQUENCY:
return channelMetadata.getFrequencyConfigurationIdentifier();
case COLUMN_CONFIGURATION_CHANNEL:
return channelMetadata.getChannelNameConfigurationIdentifier();
case COLUMN_USER_TO:
return channelMetadata;
case COLUMN_USER_FROM:
return channelMetadata;
case COLUMN_USER_FROM_ALIAS:
return channelMetadata.getFromIdentifierAliases();
case COLUMN_USER_TO_ALIAS:
return channelMetadata.getToIdentifierAliases();
}
}
return null;
}
@Override
public void updated(ChannelMetadata channelMetadata, ChannelMetadataField channelMetadataField)
{
final int rowIndex = mChannelMetadata.indexOf(channelMetadata);
if(rowIndex >= 0)
{
//Execute on the swing thread to avoid threading issues
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
switch(channelMetadataField)
{
case CONFIGURATION_CHANNEL:
fireTableCellUpdated(rowIndex, COLUMN_CONFIGURATION_CHANNEL);
break;
case CONFIGURATION_FREQUENCY:
fireTableCellUpdated(rowIndex, COLUMN_CONFIGURATION_FREQUENCY);
break;
case DECODER_CHANNEL_NAME:
fireTableCellUpdated(rowIndex, COLUMN_DECODER_LOGICAL_CHANNEL_NAME);
break;
case DECODER_TYPE:
fireTableCellUpdated(rowIndex, COLUMN_DECODER_TYPE);
break;
case DECODER_STATE:
fireTableCellUpdated(rowIndex, COLUMN_DECODER_STATE);
break;
case USER_FROM:
fireTableCellUpdated(rowIndex, COLUMN_USER_FROM);
fireTableCellUpdated(rowIndex, COLUMN_USER_FROM_ALIAS);
break;
case USER_TO:
fireTableCellUpdated(rowIndex, COLUMN_USER_TO);
fireTableCellUpdated(rowIndex, COLUMN_USER_TO_ALIAS);
break;
}
}
});
}
}
}