diff --git a/src/alias/AliasModel.java b/src/alias/AliasModel.java index 3206a57e..b1168f79 100644 --- a/src/alias/AliasModel.java +++ b/src/alias/AliasModel.java @@ -24,20 +24,22 @@ import java.util.concurrent.CopyOnWriteArrayList; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; -import javax.swing.table.TableModel; +import javax.swing.table.AbstractTableModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import alias.AliasEvent.Event; import sample.Broadcaster; import sample.Listener; +import alias.AliasEvent.Event; /** * Alias Model */ -public class AliasModel implements TableModel +public class AliasModel extends AbstractTableModel { + private static final long serialVersionUID = 1L; + private final static Logger mLog = LoggerFactory.getLogger( AliasModel.class ); public static final int COLUMN_LIST = 0; @@ -47,7 +49,6 @@ public class AliasModel implements TableModel public static final int COLUMN_COLOR = 4; private List mAliases = new ArrayList<>(); - private List mTableModelListeners = new CopyOnWriteArrayList<>(); private Broadcaster mAliasEventBroadcaster = new Broadcaster<>(); public AliasModel() @@ -141,8 +142,7 @@ public class AliasModel implements TableModel int index = mAliases.size() - 1; - broadcast( new TableModelEvent( this, index, index, - TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT ) ); + fireTableRowsInserted( index, index ); broadcast( new AliasEvent( alias, Event.ADD ) ); @@ -163,8 +163,7 @@ public class AliasModel implements TableModel mAliases.remove( alias ); - broadcast( new TableModelEvent( this, index, index, - TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE ) ); + fireTableRowsDeleted( index, index ); broadcast( new AliasEvent( alias, Event.DELETE ) ); } @@ -247,26 +246,6 @@ public class AliasModel implements TableModel throw new IllegalArgumentException( "Not yet implemented" ); } - private void broadcast( TableModelEvent event ) - { - for( TableModelListener listener: mTableModelListeners ) - { - listener.tableChanged( event ); - } - } - - @Override - public void addTableModelListener( TableModelListener listener ) - { - mTableModelListeners.add( listener ); - } - - @Override - public void removeTableModelListener( TableModelListener listener ) - { - mTableModelListeners.remove( listener ); - } - public void broadcast( AliasEvent event ) { mAliasEventBroadcaster.broadcast( event ); @@ -275,7 +254,7 @@ public class AliasModel implements TableModel { int index = mAliases.indexOf( event.getAlias() ); - broadcast( new TableModelEvent( this, index ) ); + fireTableRowsUpdated( index, index ); } } diff --git a/src/controller/ControllerPanel.java b/src/controller/ControllerPanel.java index ef7d8619..8c58d145 100644 --- a/src/controller/ControllerPanel.java +++ b/src/controller/ControllerPanel.java @@ -99,8 +99,7 @@ public class ControllerPanel extends JPanel mMessageActivityPanel = new MessageActivityPanel( channelProcessingManager ); - mCallEventPanel = new CallEventPanel( mSettingsManager, - channelProcessingManager ); + mCallEventPanel = new CallEventPanel( mSettingsManager, channelProcessingManager ); mChannelSpectrumPanel = new ChannelSpectrumPanel( mSettingsManager, channelProcessingManager ); diff --git a/src/controller/channel/Channel.java b/src/controller/channel/Channel.java index be2bf97f..f9aca2c6 100644 --- a/src/controller/channel/Channel.java +++ b/src/controller/channel/Channel.java @@ -179,7 +179,16 @@ public class Channel extends Configuration implements IFrequencyChangeProcessor return mSelected; } - public void setSelected( boolean selected ) + /** + * Sets selection status of the channel. + * + * NOTE: this method is package private so that only the ChannelSelectionManager + * can toggle the selection state. Use the channel model to broadcast a + * request select/deselect channel event. + * + * @param selected + */ + void setSelected( boolean selected ) { mSelected = selected; } diff --git a/src/controller/channel/ChannelController.java b/src/controller/channel/ChannelController.java index 88b9fe9e..498fae64 100644 --- a/src/controller/channel/ChannelController.java +++ b/src/controller/channel/ChannelController.java @@ -1,5 +1,7 @@ package controller.channel; +import java.awt.Color; +import java.awt.Component; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -12,6 +14,7 @@ import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; +import javax.swing.table.DefaultTableCellRenderer; import net.coderazzi.filters.gui.AutoChoices; import net.coderazzi.filters.gui.TableFilterHeader; @@ -64,6 +67,7 @@ public class ChannelController extends JPanel //System Configuration View and Editor mChannelTable = new JTable( mChannelModel ); + mChannelTable.setDefaultRenderer( String.class, new ChannelTableCellRenderer() ); mChannelTable.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ); mChannelTable.getSelectionModel().addListSelectionListener( this ); mChannelTable.setAutoCreateRowSorter( true ); @@ -216,4 +220,52 @@ public class ChannelController extends JPanel break; } } + + public class ChannelTableCellRenderer extends DefaultTableCellRenderer + { + private static final long serialVersionUID = 1L; + + @Override + public Component getTableCellRendererComponent( JTable table, + Object value, boolean isSelected, boolean hasFocus, int row, + int column ) + { + Component component = super.getTableCellRendererComponent( + table, value, isSelected, hasFocus, row, column ); + + ChannelModel model = (ChannelModel)table.getModel(); + + int index = table.convertRowIndexToModel( row ); + + Channel channel = model.getChannelAtIndex( index ); + + boolean enabled = channel.getEnabled(); + + if( isSelected ) + { + if( enabled ) + { + component.setBackground( Color.YELLOW ); + } + else + { + component.setBackground( table.getSelectionBackground() ); + } + } + else + { + if( enabled ) + { + component.setBackground( Color.GREEN ); + } + else + { + component.setBackground( table.getBackground() ); + } + } + + return component; + } + + } } diff --git a/src/controller/channel/ChannelModel.java b/src/controller/channel/ChannelModel.java index 0ec88eb9..25240ec1 100644 --- a/src/controller/channel/ChannelModel.java +++ b/src/controller/channel/ChannelModel.java @@ -22,9 +22,7 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; -import javax.swing.event.TableModelEvent; -import javax.swing.event.TableModelListener; -import javax.swing.table.TableModel; +import javax.swing.table.AbstractTableModel; import module.decode.DecoderType; @@ -37,20 +35,18 @@ import controller.channel.ChannelEvent.Event; /** * Channel Model */ -public class ChannelModel implements IChannelEventBroadcaster, TableModel +public class ChannelModel extends AbstractTableModel implements IChannelEventBroadcaster { + private static final long serialVersionUID = 1L; + private final static Logger mLog = LoggerFactory.getLogger( ChannelModel.class ); - private ChannelSelectionManager mChannelSelectionManager; - private List mChannels = new ArrayList<>(); - private List mTrafficChannels = new ArrayList<>(); + private List mChannels = new CopyOnWriteArrayList<>(); + private List mTrafficChannels = new CopyOnWriteArrayList<>(); private List mListeners = new CopyOnWriteArrayList<>(); - private List mTableModelListeners = new CopyOnWriteArrayList<>(); public ChannelModel() { - mChannelSelectionManager = new ChannelSelectionManager( this ); - addListener( mChannelSelectionManager ); } /** @@ -138,7 +134,7 @@ public class ChannelModel implements IChannelEventBroadcaster, TableModel case NOTIFICATION_PROCESSING_STOP: case NOTIFICATION_SELECTION_CHANGE: int index = mChannels.indexOf( event.getChannel() ); - broadcast( new TableModelEvent( this, index ) ); + fireTableRowsUpdated( index, index ); break; default: break; @@ -177,8 +173,7 @@ public class ChannelModel implements IChannelEventBroadcaster, TableModel index = mChannels.size() - 1; - broadcast( new TableModelEvent( this, index, index, - TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT ) ); + fireTableRowsInserted( index, index ); break; case TRAFFIC: mTrafficChannels.add( channel ); @@ -214,8 +209,7 @@ public class ChannelModel implements IChannelEventBroadcaster, TableModel if( index >= 0 ) { - broadcast( new TableModelEvent( this, index, index, - TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE ) ); + fireTableRowsDeleted( index, index ); } break; case TRAFFIC: @@ -348,26 +342,6 @@ public class ChannelModel implements IChannelEventBroadcaster, TableModel throw new IllegalArgumentException( "Not yet implemented" ); } - private void broadcast( TableModelEvent event ) - { - for( TableModelListener listener: mTableModelListeners ) - { - listener.tableChanged( event ); - } - } - - @Override - public void addTableModelListener( TableModelListener listener ) - { - mTableModelListeners.add( listener ); - } - - @Override - public void removeTableModelListener( TableModelListener listener ) - { - mTableModelListeners.remove( listener ); - } - public void createChannel( DecoderType decoderType, long frequency ) { throw new UnsupportedOperationException( "Not yet implemented" ); diff --git a/src/controller/channel/ChannelProcessingManager.java b/src/controller/channel/ChannelProcessingManager.java index 610c4437..d1a5f423 100644 --- a/src/controller/channel/ChannelProcessingManager.java +++ b/src/controller/channel/ChannelProcessingManager.java @@ -77,8 +77,6 @@ public class ChannelProcessingManager implements ChannelEventListener mRecorderManager = recorderManager; mSourceManager = sourceManager; mThreadPoolManager = threadPoolManager; - - mChannelModel.addListener( this ); } /** @@ -184,7 +182,7 @@ public class ChannelProcessingManager implements ChannelEventListener return; } - + if( processingChain == null ) { processingChain = new ProcessingChain( mThreadPoolManager, @@ -258,6 +256,7 @@ public class ChannelProcessingManager implements ChannelEventListener } processingChain.setSource( source ); + processingChain.start(); channel.setEnabled( true ); diff --git a/src/gui/SDRTrunk.java b/src/gui/SDRTrunk.java index ef21d641..577c6593 100644 --- a/src/gui/SDRTrunk.java +++ b/src/gui/SDRTrunk.java @@ -119,10 +119,10 @@ public class SDRTrunk SourceManager sourceManager = new SourceManager( mSettingsManager, threadPoolManager ); - AliasModel aliasModel = new AliasModel(); - ChannelModel channelModel = new ChannelModel(); + AliasModel aliasModel = new AliasModel(); + PlaylistManager playlistManager = new PlaylistManager( threadPoolManager, aliasModel, channelModel ); @@ -137,7 +137,11 @@ public class SDRTrunk channelProcessingManager.addAudioPacketListener( recorderManager ); - AliasActionManager aliasActionManager = new AliasActionManager( threadPoolManager ); + ChannelSelectionManager channelSelectionManager = + new ChannelSelectionManager( channelModel ); + channelModel.addListener( channelSelectionManager ); + + AliasActionManager aliasActionManager = new AliasActionManager( threadPoolManager ); channelProcessingManager.addMessageListener( aliasActionManager ); AudioManager audioManager = new AudioManager( threadPoolManager, sourceManager.getMixerManager() ); @@ -145,16 +149,6 @@ public class SDRTrunk MapService mapService = new MapService( mSettingsManager ); channelProcessingManager.addMessageListener( mapService ); - - ChannelSelectionManager channelSelectionManager = - new ChannelSelectionManager( channelModel ); - channelModel.addListener( channelSelectionManager ); - -//TODO: move this to the end once we add the alias model, otherwise the -//configuration tree won't load correctly - - //Initialize the playlist manager to load the saved playlist - playlistManager.init(); ConfigurationControllerModel configurationControllerModel = new ConfigurationControllerModel( channelModel, channelProcessingManager, @@ -169,11 +163,16 @@ public class SDRTrunk mTitle = getTitle(); - //Initialize the GUI + //TODO: move this to the end once we add the alias model, otherwise the + //configuration tree won't load correctly + //Initialize the playlist manager to load the saved playlist + playlistManager.init(); + + mLog.info( "starting main application gui" ); + + //Initialize the GUI initGUI(); - mLog.info( "starting main application gui" ); - if( mLogChannelAndMemoryUsage ) { Runnable cml = new ChannelMemoryLogger(); diff --git a/src/module/ProcessingChain.java b/src/module/ProcessingChain.java index e48e644e..af501560 100644 --- a/src/module/ProcessingChain.java +++ b/src/module/ProcessingChain.java @@ -475,13 +475,15 @@ public class ProcessingChain implements IChannelEventListener } /* If this is a tuner source, broadcast the frequency to all - * of the decoder state's */ + * of the decoder state's and start the samples flowing */ if( mSource instanceof TunerChannelSource ) { + TunerChannelSource tcs = (TunerChannelSource)mSource; + try { - long frequency = ((TunerChannelSource)mSource).getFrequency(); - + long frequency = tcs.getFrequency(); + mDecoderStateEventBroadcaster.broadcast( new DecoderStateEvent( this, Event.SOURCE_FREQUENCY, State.IDLE, frequency ) ); @@ -490,6 +492,8 @@ public class ProcessingChain implements IChannelEventListener { mLog.error( "Error getting frequency from tuner channel source", e ); } + + tcs.start(); } } else @@ -603,6 +607,7 @@ public class ProcessingChain implements IChannelEventListener */ public void addMessageListener( Listener listener ) { + mLog.debug( "Registering Message Listener:" + listener.getClass() ); mMessageBroadcaster.addListener( listener ); } diff --git a/src/module/decode/event/MessageActivityModel.java b/src/module/decode/event/MessageActivityModel.java index 65850196..ddcf17a5 100644 --- a/src/module/decode/event/MessageActivityModel.java +++ b/src/module/decode/event/MessageActivityModel.java @@ -1,6 +1,6 @@ /******************************************************************************* * SDR Trunk - * Copyright (C) 2014 Dennis Sheirer + * 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 @@ -24,13 +24,19 @@ import java.util.LinkedList; import javax.swing.table.AbstractTableModel; import message.Message; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import sample.Listener; import filter.FilterSet; public class MessageActivityModel extends AbstractTableModel implements Listener { - private static final long serialVersionUID = 1L; + private final static Logger mLog = LoggerFactory.getLogger( MessageActivityModel.class ); + + private static final long serialVersionUID = 1L; private static final int sTIME = 0; private static final int sPROTOCOL = 1; private static final int sERROR_STATUS = 2; diff --git a/src/module/decode/event/MessageActivityPanel.java b/src/module/decode/event/MessageActivityPanel.java index 6cc4ac71..0ef6a5ee 100644 --- a/src/module/decode/event/MessageActivityPanel.java +++ b/src/module/decode/event/MessageActivityPanel.java @@ -1,6 +1,6 @@ /******************************************************************************* * SDR Trunk - * Copyright (C) 2014 Dennis Sheirer + * 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 diff --git a/src/module/decode/p25/P25MessageFramer.java b/src/module/decode/p25/P25MessageFramer.java index 84ed4154..39d9bb80 100644 --- a/src/module/decode/p25/P25MessageFramer.java +++ b/src/module/decode/p25/P25MessageFramer.java @@ -131,7 +131,7 @@ public class P25MessageFramer implements Listener if( demodulator != null ) { /* For CQPSK, we include 3 additional sync detectors to watch for and - * correction +/-90 and 180 degree costas loop phase lock errors */ + * correct +/-90 and 180 degree costas loop phase lock errors */ mMatcher.add( new CostasPhaseErrorDetector( FrameSync.P25_PHASE1_ERROR_90_CCW, demodulator, PHASE_CORRECTION_90_DEGREES ) ); @@ -291,6 +291,7 @@ public class P25MessageFramer implements Listener else { mComplete = true; + dispatch( new P25Message( mMessage.copy(), mDUID, mAliasList ) ); } } else diff --git a/src/module/decode/p25/P25_LSMDecoder.java b/src/module/decode/p25/P25_LSMDecoder.java index 0e72cba4..7614ac24 100644 --- a/src/module/decode/p25/P25_LSMDecoder.java +++ b/src/module/decode/p25/P25_LSMDecoder.java @@ -49,8 +49,8 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener /* Instrumentation Taps */ private static final String INSTRUMENT_BASEBAND_FILTER_OUTPUT = "Tap Point: Baseband Filter Output"; private static final String INSTRUMENT_AGC_OUTPUT = "Tap Point: AGC Output"; - private static final String INSTRUMENT_QPSK_DEMODULATOR_OUTPUT = "Tap Point: CQPSK Demodulator Output"; - private static final String INSTRUMENT_CQPSK_SLICER_OUTPUT = "Tap Point: CQPSK Slicer Output"; + private static final String INSTRUMENT_LSM_DEMODULATOR_OUTPUT = "Tap Point: LSM Demodulator Output"; + private static final String INSTRUMENT_QPSK_SLICER_OUTPUT = "Tap Point: QPSK Slicer Output"; private List mAvailableTaps; @@ -59,8 +59,8 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener new ComplexBufferToStreamConverter(); private ComplexFeedForwardGainControl mAGC = new ComplexFeedForwardGainControl( 32 ); - private LSMDemodulator mCQPSKDemodulator = new LSMDemodulator(); - private QPSKPolarSlicer mCQPSKSlicer = new QPSKPolarSlicer(); + private LSMDemodulator mLSMDemodulator = new LSMDemodulator(); + private QPSKPolarSlicer mQPSKSlicer = new QPSKPolarSlicer(); private P25MessageFramer mMessageFramer; public P25_LSMDecoder( AliasList aliasList ) @@ -74,12 +74,12 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener mStreamConverter.setListener( mAGC ); - mAGC.setListener( mCQPSKDemodulator ); + mAGC.setListener( mLSMDemodulator ); - mCQPSKDemodulator.setSymbolListener( mCQPSKSlicer ); + mLSMDemodulator.setSymbolListener( mQPSKSlicer ); - mMessageFramer = new P25MessageFramer( aliasList, mCQPSKDemodulator ); - mCQPSKSlicer.addListener( mMessageFramer ); + mMessageFramer = new P25MessageFramer( aliasList, mLSMDemodulator ); + mQPSKSlicer.addListener( mMessageFramer ); mMessageFramer.setListener( getMessageProcessor() ); } @@ -97,11 +97,11 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener mAGC.dispose(); mAGC = null; - mCQPSKDemodulator.dispose(); - mCQPSKDemodulator = null; + mLSMDemodulator.dispose(); + mLSMDemodulator = null; - mCQPSKSlicer.dispose(); - mCQPSKSlicer = null; + mQPSKSlicer.dispose(); + mQPSKSlicer = null; mMessageFramer.dispose(); mMessageFramer = null; @@ -132,14 +132,14 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener group.add( new ComplexTap( INSTRUMENT_BASEBAND_FILTER_OUTPUT, 0, 1.0f ) ); group.add( new ComplexTap( INSTRUMENT_AGC_OUTPUT, 0, 1.0f ) ); - group.add( new QPSKTap( INSTRUMENT_QPSK_DEMODULATOR_OUTPUT, 0, 1.0f ) ); - group.add( new DibitTap( INSTRUMENT_CQPSK_SLICER_OUTPUT, 0, 0.1f ) ); + group.add( new QPSKTap( INSTRUMENT_LSM_DEMODULATOR_OUTPUT, 0, 1.0f ) ); + group.add( new DibitTap( INSTRUMENT_QPSK_SLICER_OUTPUT, 0, 0.1f ) ); mAvailableTaps.add( group ); - if( mCQPSKDemodulator != null ) + if( mLSMDemodulator != null ) { - mAvailableTaps.addAll( mCQPSKDemodulator.getTapGroups() ); + mAvailableTaps.addAll( mLSMDemodulator.getTapGroups() ); } } @@ -152,9 +152,9 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener @Override public void registerTap( Tap tap ) { - if( mCQPSKDemodulator != null ) + if( mLSMDemodulator != null ) { - mCQPSKDemodulator.registerTap( tap ); + mLSMDemodulator.registerTap( tap ); } switch( tap.getName() ) @@ -167,15 +167,15 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener case INSTRUMENT_AGC_OUTPUT: ComplexSampleTap agcSymbol = (ComplexSampleTap)tap; mAGC.setListener( agcSymbol ); - agcSymbol.setListener( mCQPSKDemodulator ); + agcSymbol.setListener( mLSMDemodulator ); break; - case INSTRUMENT_QPSK_DEMODULATOR_OUTPUT: + case INSTRUMENT_LSM_DEMODULATOR_OUTPUT: QPSKTap qpsk = (QPSKTap)tap; - mCQPSKDemodulator.setSymbolListener( qpsk ); - qpsk.setListener( mCQPSKSlicer ); + mLSMDemodulator.setSymbolListener( qpsk ); + qpsk.setListener( mQPSKSlicer ); break; - case INSTRUMENT_CQPSK_SLICER_OUTPUT: - mCQPSKSlicer.addListener( (DibitTap)tap ); + case INSTRUMENT_QPSK_SLICER_OUTPUT: + mQPSKSlicer.addListener( (DibitTap)tap ); break; default: throw new IllegalArgumentException( "Unrecognized tap: " + @@ -189,9 +189,9 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener @Override public void unregisterTap( Tap tap ) { - if( mCQPSKDemodulator != null ) + if( mLSMDemodulator != null ) { - mCQPSKDemodulator.unregisterTap( tap ); + mLSMDemodulator.unregisterTap( tap ); } switch( tap.getName() ) @@ -200,13 +200,13 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener mStreamConverter.setListener( mAGC ); break; case INSTRUMENT_AGC_OUTPUT: - mAGC.setListener( mCQPSKDemodulator ); + mAGC.setListener( mLSMDemodulator ); break; - case INSTRUMENT_QPSK_DEMODULATOR_OUTPUT: - mCQPSKDemodulator.setSymbolListener( mCQPSKSlicer ); + case INSTRUMENT_LSM_DEMODULATOR_OUTPUT: + mLSMDemodulator.setSymbolListener( mQPSKSlicer ); break; - case INSTRUMENT_CQPSK_SLICER_OUTPUT: - mCQPSKSlicer.removeListener( (DibitTap)tap ); + case INSTRUMENT_QPSK_SLICER_OUTPUT: + mQPSKSlicer.removeListener( (DibitTap)tap ); break; default: throw new IllegalArgumentException( "Unrecognized tap: " + diff --git a/src/module/decode/p25/reference/DataUnitID.java b/src/module/decode/p25/reference/DataUnitID.java index c52e9af3..eba7fa42 100644 --- a/src/module/decode/p25/reference/DataUnitID.java +++ b/src/module/decode/p25/reference/DataUnitID.java @@ -14,7 +14,7 @@ public enum DataUnitID TSBK1( 7, 260, false, "TSBK1", "Trunking Signaling Block" ), TSBK2( 7, 260, false, "TSBK2", "Trunking Signaling Block" ), TSBK3( 7, 260, false, "TSBK3", "Trunking Signaling Block" ), - VSELP2( 9, 1680, false, "VSEL1", "Motorola VSELP Unit 1" ), + VSELP2( 9, 1680, false, "VSEL2", "Motorola VSELP Unit 2" ), LDU2 ( 10, 1632, true, "LDU2 ", "Logical Link Data Unit 2" ), PDU0 ( 12, 260, false, "PDU0 ", "Packet Header Data Unit" ), PDU1 ( 12, 356, false, "PDU1 ", "Packet Data Unit-Unconfirmed" ), @@ -75,8 +75,12 @@ public enum DataUnitID return TDU; case 5: return LDU1; + case 6: + return VSELP1; case 7: return TSBK1; + case 9: + return VSELP2; case 10: return LDU2; case 12: diff --git a/src/module/decode/state/ChangeChannelTimeoutEvent.java b/src/module/decode/state/ChangeChannelTimeoutEvent.java new file mode 100644 index 00000000..9119e4c9 --- /dev/null +++ b/src/module/decode/state/ChangeChannelTimeoutEvent.java @@ -0,0 +1,29 @@ +package module.decode.state; + +import controller.channel.Channel.ChannelType; + +/** + * Allows decoders to change the call timeout setting in the channel state + */ +public class ChangeChannelTimeoutEvent extends DecoderStateEvent +{ + private ChannelType mChannelType; + private long mCallTimeout; + + public ChangeChannelTimeoutEvent( Object source, ChannelType channelType, long timeout ) + { + super( source, Event.CHANGE_CALL_TIMEOUT, State.IDLE ); + mChannelType = channelType; + mCallTimeout = timeout; + } + + public ChannelType getChannelType() + { + return mChannelType; + } + + public long getCallTimeout() + { + return mCallTimeout; + } +} \ No newline at end of file diff --git a/src/module/decode/state/ChannelCollectionPanel.java b/src/module/decode/state/ChannelCollectionPanel.java deleted file mode 100644 index eae3db84..00000000 --- a/src/module/decode/state/ChannelCollectionPanel.java +++ /dev/null @@ -1,154 +0,0 @@ -package module.decode.state; - -import java.awt.Component; -import java.awt.Point; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.JMenu; -import javax.swing.JPanel; - -import net.miginfocom.swing.MigLayout; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import playlist.PlaylistManager; -import settings.SettingsManager; -import controller.channel.Channel; -import controller.channel.ChannelModel; -import controller.channel.ChannelProcessingManager; - -/** - * Channel Collection assembles a primary channel panel and any related decoder - * state panels, provides contextual access to the channel and supports channel - * selection. - */ -public class ChannelCollectionPanel extends JPanel -{ - private static final long serialVersionUID = 1L; - - private final static Logger mLog = LoggerFactory.getLogger( ChannelCollectionPanel.class ); - - private ChannelModel mChannelModel; - private ChannelProcessingManager mChannelProcessingManager; - private PlaylistManager mPlaylistManager; - private SettingsManager mSettingsManager; - - private List mChannelPanels = new ArrayList(); - - public ChannelCollectionPanel( ChannelModel channelModel, - ChannelProcessingManager channelProcessingManager, - PlaylistManager playlistManager, - SettingsManager settingsManager, - Channel channel ) - { - mChannelModel = channelModel; - mChannelProcessingManager = channelProcessingManager; - mPlaylistManager = playlistManager; - mSettingsManager = settingsManager; - - init( channel ); - } - - protected void init( Channel channel ) - { - setLayout( new MigLayout( "insets 0 0 0 0", "[grow,fill]", "[]0[]0[]") ); - - setOpaque( false ); - - ChannelStatePanel csp = new ChannelStatePanel( mChannelModel, - mChannelProcessingManager, mPlaylistManager, mSettingsManager, channel ); - - mChannelPanels.add( csp ); - - add( csp, "span,grow" ); - - } - - public Channel getChannel() - { - if( mChannelPanels.size() >= 1 ) - { - return mChannelPanels.get( 0 ).getChannel(); - } - - return null; - } - - public void dispose() - { - for( ChannelStatePanel panel: mChannelPanels ) - { - panel.dispose(); - } - - mChannelPanels.clear(); - - mPlaylistManager = null; - mSettingsManager = null; - } - - /** - * Toggles the selection state of the channel if it matches the channel - * argument. Otherwise, sets the selection state to false. - */ - public void setSelectedChannel( Channel channel ) - { - for( ChannelStatePanel panel: mChannelPanels ) - { - if( panel.getChannel() == channel ) - { - /* Toggle the selection state */ - panel.getChannel().setSelected( !panel.getChannel().isSelected() ); - panel.repaint(); - } - else - { - if( panel.getChannel().isSelected() ) - { - panel.getChannel().setSelected( false ); - panel.repaint(); - } - } - } - } - - /** - * Returns the channel represented by the channel panel at the gui point - * location, to selecting the channel - * - * @param point - current location of the mouse - * - * @return - channel or null - */ - public Channel getChannelAt( Point point ) - { - Component c = this.getComponentAt( point ); - - if( c instanceof ChannelCollectionPanel ) - { - return ((ChannelCollectionPanel)c).getChannel(); - } - else - { - return getChannel(); - } - } - - protected SettingsManager getSettingsManager() - { - return mSettingsManager; - } - - - public JMenu getContextMenu() - { - if( !mChannelPanels.isEmpty() ) - { - return mChannelPanels.get( 0 ).getContextMenu(); - } - - return null; - } -} diff --git a/src/module/decode/state/ChannelList.java b/src/module/decode/state/ChannelList.java index be9f9a89..16fe4e4e 100644 --- a/src/module/decode/state/ChannelList.java +++ b/src/module/decode/state/ChannelList.java @@ -23,6 +23,7 @@ import java.awt.Point; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.HashMap; +import java.util.Map; import javax.swing.JMenu; import javax.swing.JPanel; @@ -42,6 +43,7 @@ import settings.ColorSettingResetMenuItem; import settings.SettingsManager; import controller.channel.Channel; import controller.channel.ChannelEvent; +import controller.channel.ChannelEvent.Event; import controller.channel.ChannelEventListener; import controller.channel.ChannelModel; import controller.channel.ChannelProcessingManager; @@ -55,8 +57,7 @@ public class ChannelList extends JPanel implements ChannelEventListener private final static Logger mLog = LoggerFactory.getLogger( ChannelList.class ); - private HashMap mDisplayedPanels = - new HashMap(); + private Map mDisplayedPanels = new HashMap(); private ChannelModel mChannelModel; private ChannelProcessingManager mChannelProcessingManager; @@ -104,12 +105,12 @@ public class ChannelList extends JPanel implements ChannelEventListener { if( !mDisplayedPanels.containsKey( channel ) ) { - ChannelCollectionPanel panel = new ChannelCollectionPanel( mChannelModel, - mChannelProcessingManager, mPlaylistManager, mSettingsManager, channel ); + ChannelPanel channelPanel = new ChannelPanel( mChannelModel, + mChannelProcessingManager, mPlaylistManager, mSettingsManager, channel ); - add( panel, "wrap" ); + add( channelPanel, "wrap" ); - mDisplayedPanels.put( channel, panel ); + mDisplayedPanels.put( channel, channelPanel ); revalidate(); repaint(); @@ -120,7 +121,7 @@ public class ChannelList extends JPanel implements ChannelEventListener { if( mDisplayedPanels.containsKey( channel ) ) { - ChannelCollectionPanel panel = mDisplayedPanels.remove( channel ); + ChannelPanel panel = mDisplayedPanels.remove( channel ); if( panel != null ) { @@ -134,15 +135,6 @@ public class ChannelList extends JPanel implements ChannelEventListener } } - public void setSelectedChannel( Channel channel ) - { - /* Send channel selection to each channel panel */ - for( ChannelCollectionPanel panel: mDisplayedPanels.values() ) - { - panel.setSelectedChannel( channel ); - } - } - public class ListSelectionListener implements MouseListener { @Override @@ -150,18 +142,22 @@ public class ChannelList extends JPanel implements ChannelEventListener { Component component = getComponentAt( e.getPoint() ); - if( component instanceof ChannelCollectionPanel ) + if( component instanceof ChannelPanel ) { - ChannelCollectionPanel panel = (ChannelCollectionPanel)component; + ChannelPanel panel = (ChannelPanel)component; - Point translatedPoint = SwingUtilities - .convertPoint( e.getComponent(), e.getPoint(), panel ); - - Channel channel = panel.getChannelAt( translatedPoint ); + Channel channel = panel.getChannel(); if( e.getButton() == MouseEvent.BUTTON1 ) { - setSelectedChannel( channel ); + if( channel.isSelected() ) + { + mChannelModel.broadcast( new ChannelEvent( channel, Event.REQUEST_DESELECT ) ); + } + else + { + mChannelModel.broadcast( new ChannelEvent( channel, Event.REQUEST_SELECT ) ); + } } else if( e.getButton() == MouseEvent.BUTTON3 ) { diff --git a/src/module/decode/state/ChannelStatePanel.java b/src/module/decode/state/ChannelPanel.java similarity index 92% rename from src/module/decode/state/ChannelStatePanel.java rename to src/module/decode/state/ChannelPanel.java index 9b9dd7cb..0d88f826 100644 --- a/src/module/decode/state/ChannelStatePanel.java +++ b/src/module/decode/state/ChannelPanel.java @@ -15,13 +15,12 @@ import javax.swing.JMenu; import javax.swing.JPanel; import module.ProcessingChain; +import module.decode.DecoderFactory; +import net.miginfocom.swing.MigLayout; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import controller.channel.Channel; -import controller.channel.ChannelUtils; -import module.decode.DecoderFactory; -import net.miginfocom.swing.MigLayout; import playlist.PlaylistManager; import record.RecorderType; import record.config.RecordConfiguration; @@ -31,18 +30,22 @@ import settings.ColorSetting.ColorSettingName; import settings.Setting; import settings.SettingChangeListener; import settings.SettingsManager; - import controller.channel.Channel; +import controller.channel.ChannelEvent; +import controller.channel.ChannelEvent.Event; +import controller.channel.ChannelEventListener; import controller.channel.ChannelModel; import controller.channel.ChannelProcessingManager; import controller.channel.ChannelUtils; -public class ChannelStatePanel extends JPanel - implements Listener, SettingChangeListener +public class ChannelPanel extends JPanel + implements Listener, + SettingChangeListener, + ChannelEventListener { private static final long serialVersionUID = 1L; - private final static Logger mLog = LoggerFactory.getLogger( ChannelStatePanel.class ); + private final static Logger mLog = LoggerFactory.getLogger( ChannelPanel.class ); private Font mFontDetails = new Font( Font.MONOSPACED, Font.PLAIN, 12 ); private Font mFontDecoder = new Font( Font.MONOSPACED, Font.PLAIN, 12 ); @@ -88,19 +91,16 @@ public class ChannelStatePanel extends JPanel * * Updates color background according to current channel state. */ - public ChannelStatePanel( ChannelModel channelModel, - ChannelProcessingManager channelProcessingManager, - PlaylistManager playlistManager, - SettingsManager settingsManager, - Channel channel ) + public ChannelPanel( ChannelModel channelModel, + ChannelProcessingManager channelProcessingManager, + PlaylistManager playlistManager, + SettingsManager settingsManager, + Channel channel ) { mChannelModel = channelModel; mChannelProcessingManager = channelProcessingManager; mPlaylistManager = playlistManager; - mSettingsManager = settingsManager; - mSettingsManager.addListener( this ); - mChannel = channel; ProcessingChain processingChain = @@ -109,9 +109,7 @@ public class ChannelStatePanel extends JPanel if( processingChain != null ) { mChannelState = processingChain.getChannelState(); - - mChannelState.setChangedAttributeListener( this ); - + init(); for( DecoderState decoderState: processingChain.getDecoderStates() ) @@ -120,6 +118,10 @@ public class ChannelStatePanel extends JPanel mDecoderPanels.add( panel ); add( panel, "grow,span" ); } + + mChannelState.setChangedAttributeListener( this ); + mChannelModel.addListener( this ); + mSettingsManager.addListener( this ); } else { @@ -191,6 +193,11 @@ public class ChannelStatePanel extends JPanel public void dispose() { + mChannelModel.removeListener( this ); + mChannelModel = null; + + mChannelProcessingManager = null; + mPlaylistManager = null; mSettingsManager.removeListener( this ); @@ -426,6 +433,16 @@ public class ChannelStatePanel extends JPanel public JMenu getContextMenu() { return ChannelUtils.getContextMenu( mChannelModel, mChannelProcessingManager, - mPlaylistManager, mChannel, ChannelStatePanel.this ); + mPlaylistManager, mChannel, ChannelPanel.this ); + } + + @Override + public void channelChanged( ChannelEvent event ) + { + if( event.getEvent() == Event.NOTIFICATION_SELECTION_CHANGE && + event.getChannel() == mChannel ) + { + repaint(); + } } } diff --git a/src/playlist/PlaylistManager.java b/src/playlist/PlaylistManager.java index 167f5180..4fd5186f 100644 --- a/src/playlist/PlaylistManager.java +++ b/src/playlist/PlaylistManager.java @@ -103,11 +103,8 @@ public class PlaylistManager implements ChannelEventListener mPlaylistLoading = true; - mLog.debug( "Transferring aliases to model" ); mAliasModel.addAliases( mPlaylist.getAliases() ); - mLog.debug( "Transferring channels to model" ); mChannelModel.addChannels( mPlaylist.getChannels() ); - mLog.debug( "Transfer to models is complete" ); mPlaylistLoading = false; } @@ -175,13 +172,9 @@ public class PlaylistManager implements ChannelEventListener { //TODO: recreate the playlist and load values from each of the models - mLog.debug( "Aliases in model:" + mAliasModel.getAliases().size() ); mPlaylist.setAliases( mAliasModel.getAliases() ); - mLog.debug( "Aliases in playlist:" + mPlaylist.getAliases().size() ); - mLog.debug( "Channels in model:" + mChannelModel.getChannels().size() ); mPlaylist.setChannels( mChannelModel.getChannels() ); - mLog.debug( "Channels in playlist:" + mPlaylist.getChannels().size() ); JAXBContext context = null; diff --git a/src/sample/complex/ComplexBufferToStreamConverter.java b/src/sample/complex/ComplexBufferToStreamConverter.java index ecce6561..16062a1c 100644 --- a/src/sample/complex/ComplexBufferToStreamConverter.java +++ b/src/sample/complex/ComplexBufferToStreamConverter.java @@ -1,5 +1,10 @@ package sample.complex; +import module.decode.p25.P25_LSMDecoder; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import sample.Listener; /** @@ -7,9 +12,10 @@ import sample.Listener; */ public class ComplexBufferToStreamConverter implements Listener { + private final static Logger mLog = LoggerFactory.getLogger( ComplexBufferToStreamConverter.class ); + private ComplexSampleListener mListener; - public void dispose() { mListener = null;