From 9d4afb8c1f1438704d217f8535900de56ccb2c36 Mon Sep 17 00:00:00 2001 From: denny Date: Fri, 11 Mar 2016 07:16:29 -0500 Subject: [PATCH] WIP #34 - updates tuners and tuner model to provide details on frequency, sample rate, sourced channels, and spectral display in the tuner view tab. --- src/controller/ControllerPanel.java | 30 +++--- src/source/TunerModel.java | 126 ++++++++++++++++++++--- src/source/TunerViewPanel.java | 23 +++-- src/source/tuner/Tuner.java | 55 +++++++++- src/source/tuner/TunerChangeEvent.java | 33 ++++++ src/source/tuner/TunerController.java | 5 + src/source/tuner/TunerType.java | 2 +- src/source/tuner/airspy/AirspyTuner.java | 18 +++- src/source/tuner/ettus/B100Tuner.java | 7 ++ src/source/tuner/fcd/FCDTuner.java | 16 ++- src/source/tuner/hackrf/HackRFTuner.java | 16 ++- src/source/tuner/rtl/RTL2832Tuner.java | 13 +++ 12 files changed, 296 insertions(+), 48 deletions(-) create mode 100644 src/source/tuner/TunerChangeEvent.java diff --git a/src/controller/ControllerPanel.java b/src/controller/ControllerPanel.java index 79d24625..bcb21c13 100644 --- a/src/controller/ControllerPanel.java +++ b/src/controller/ControllerPanel.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 @@ -71,9 +71,9 @@ public class ControllerPanel extends JPanel private JideTabbedPane mTabbedPane; - protected ConfigurationTreePanel mSystemControlViewPanel; - protected OldConfigurationEditor mConfigurationEditor; - protected JideSplitPane mSystemControlSplitPane; +// protected ConfigurationTreePanel mSystemControlViewPanel; +// protected OldConfigurationEditor mConfigurationEditor; +// protected JideSplitPane mSystemControlSplitPane; protected JTable mChannelActivityTable = new JTable(); private AudioPanel mAudioPanel; @@ -128,25 +128,25 @@ public class ControllerPanel extends JPanel "[grow,fill]", "[grow,fill]") ); - //System Configuration View and Editor - mConfigurationEditor = new OldConfigurationEditor(); +// //System Configuration View and Editor +// mConfigurationEditor = new OldConfigurationEditor(); +// +// mSystemControlViewPanel = new ConfigurationTreePanel( mController ); +// mSystemControlViewPanel.addTreeSelectionListener( mConfigurationEditor ); - mSystemControlViewPanel = new ConfigurationTreePanel( mController ); - mSystemControlViewPanel.addTreeSelectionListener( mConfigurationEditor ); - - mSystemControlSplitPane = new JideSplitPane( JideSplitPane.HORIZONTAL_SPLIT ); - mSystemControlSplitPane.setDividerSize( 5 ); - mSystemControlSplitPane.add( mSystemControlViewPanel ); - mSystemControlSplitPane.add( mConfigurationEditor ); +// mSystemControlSplitPane = new JideSplitPane( JideSplitPane.HORIZONTAL_SPLIT ); +// mSystemControlSplitPane.setDividerSize( 5 ); +// mSystemControlSplitPane.add( mSystemControlViewPanel ); +// mSystemControlSplitPane.add( mConfigurationEditor ); //Tabbed View - configuration, calls, messages, map mTabbedPane = new JideTabbedPane(); mTabbedPane.setFont( this.getFont() ); mTabbedPane.setForeground( Color.BLACK ); + mTabbedPane.addTab( "Tuners", mTunerManagerPanel ); mTabbedPane.addTab( "Channels", mChannelController ); mTabbedPane.addTab( "Aliases", mAliasController ); - mTabbedPane.addTab( "Tuners", mTunerManagerPanel ); - mTabbedPane.addTab( "Configuration", mSystemControlSplitPane ); +// mTabbedPane.addTab( "Configuration", mSystemControlSplitPane ); mTabbedPane.addTab( "Channel Spectrum", mChannelSpectrumPanel ); mTabbedPane.addTab( "Events", mCallEventPanel ); mTabbedPane.addTab( "Messages", mMessageActivityPanel ); diff --git a/src/source/TunerModel.java b/src/source/TunerModel.java index dd51250e..4e5655a4 100644 --- a/src/source/TunerModel.java +++ b/src/source/TunerModel.java @@ -1,17 +1,34 @@ package source; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; -import javax.swing.AbstractListModel; +import javax.swing.table.AbstractTableModel; +import sample.Listener; import source.tuner.Tuner; +import source.tuner.TunerChangeEvent; -public class TunerModel extends AbstractListModel +public class TunerModel extends AbstractTableModel + implements Listener { private static final long serialVersionUID = 1L; + private static final int TUNER_CLASS = 0; + private static final int TUNER_TYPE = 1; + private static final int SAMPLE_RATE = 2; + private static final int FREQUENCY = 3; + private static final int CHANNEL_COUNT = 4; + private static final int SPECTRAL_DISPLAY = 5; + + private static final String MHZ = " MHz"; + private static final String[] COLUMNS = + { "Class", "Type", "Sample Rate", "Frequency", "Channels", "Spectrum" }; + private List mTuners = new ArrayList<>(); + private DecimalFormat mFrequencyFormat = new DecimalFormat( "0.00000" ); + private DecimalFormat mSampleRateFormat = new DecimalFormat( "0.000" ); public TunerModel() { @@ -24,6 +41,16 @@ public class TunerModel extends AbstractListModel { return mTuners; } + + public Tuner getTuner( int index ) + { + if( index < mTuners.size() ) + { + return mTuners.get( index ); + } + + return null; + } public void addTuners( List Tuners ) { @@ -44,7 +71,9 @@ public class TunerModel extends AbstractListModel int index = mTuners.indexOf( tuner ); - fireIntervalAdded( this, index, index ); + fireTableRowsInserted( index, index ); + + tuner.addTunerChangeListener( this ); } } @@ -55,34 +84,101 @@ public class TunerModel extends AbstractListModel { if( mTuners.contains( tuner ) ) { + tuner.removeTunerChangeListener( this ); + int index = mTuners.indexOf( tuner ); mTuners.remove( tuner ); - fireIntervalRemoved( this, index, index ); + fireTableRowsDeleted( index, index ); } } - /** - * Number of Tuners in this model - */ + @Override - public int getSize() + public void receive( TunerChangeEvent event ) + { + if( event.getTuner() != null ) + { + int index = mTuners.indexOf( event.getTuner() ); + + if( index >= 0 ) + { + switch( event.getEvent() ) + { + case CHANNEL_COUNT: + fireTableCellUpdated( index, CHANNEL_COUNT ); + break; + case FREQUENCY: + fireTableCellUpdated( index, FREQUENCY ); + break; + case SAMPLE_RATE: + fireTableCellUpdated( index, SAMPLE_RATE ); + break; + case SPECTRAL_DISPLAY: + fireTableCellUpdated( index, SPECTRAL_DISPLAY ); + default: + break; + } + } + } + } + + @Override + public int getRowCount() { return mTuners.size(); } - /** - * Returns the Tuner at the specified index - */ @Override - public Tuner getElementAt( int index ) + public int getColumnCount() { - if( index <= mTuners.size() ) + return 6; + } + + @Override + public Object getValueAt( int rowIndex, int columnIndex ) + { + if( rowIndex < mTuners.size() ) { - return mTuners.get( index ); + Tuner tuner = mTuners.get( rowIndex ); + + switch( columnIndex ) + { + case TUNER_CLASS: + return tuner.getTunerClass().getVendorDescription(); + case TUNER_TYPE: + return tuner.getTunerType().getLabel(); + case SAMPLE_RATE: + int sampleRate = tuner.getSampleRate(); + + return mSampleRateFormat.format( sampleRate / 1E6D ) + MHZ; + case FREQUENCY: + try + { + long frequency = tuner.getFrequency(); + + return mFrequencyFormat.format( frequency / 1E6D ) + MHZ; + } + catch( Exception e ) + { + return 0; + } + case CHANNEL_COUNT: + return tuner.getChannelCount(); + case SPECTRAL_DISPLAY: + return "TBD"; + default: + break; + } } - + return null; } + + @Override + public String getColumnName( int columnIndex ) + { + return COLUMNS[ columnIndex ]; + } } diff --git a/src/source/TunerViewPanel.java b/src/source/TunerViewPanel.java index e2b9ef57..5b577bfb 100644 --- a/src/source/TunerViewPanel.java +++ b/src/source/TunerViewPanel.java @@ -3,10 +3,11 @@ package source; import gui.editor.EmptyEditor; import java.awt.Component; +import java.awt.Dimension; -import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; +import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; @@ -30,7 +31,7 @@ public class TunerViewPanel extends JPanel private TunerModel mTunerModel; private SettingsManager mSettingsManager; private JideSplitPane mSplitPane; - private JList mTunerList; + private JTable mTunerTable; public TunerViewPanel( TunerModel tunerModel, SettingsManager settingsManager ) { @@ -44,17 +45,19 @@ public class TunerViewPanel extends JPanel { setLayout( new MigLayout( "insets 1 1 1 1", "[fill,grow]", "[fill,grow]" ) ); - mTunerList = new JList<>( mTunerModel ); - mTunerList.setLayoutOrientation( JList.VERTICAL ); - mTunerList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ); - mTunerList.addListSelectionListener( new ListSelectionListener() + mTunerTable = new JTable( mTunerModel ); + mTunerTable.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ); + mTunerTable.getSelectionModel().addListSelectionListener( new ListSelectionListener() { @Override public void valueChanged( ListSelectionEvent event ) { if( !event.getValueIsAdjusting() ) { - Tuner selected = mTunerList.getSelectedValue(); + int row = mTunerTable.getSelectedRow(); + int modelRow = mTunerTable.convertRowIndexToModel( row ); + + Tuner selected = mTunerModel.getTuner( modelRow ); Component component = null; @@ -80,12 +83,14 @@ public class TunerViewPanel extends JPanel } } ); - JScrollPane listScroller = new JScrollPane( mTunerList ); + JScrollPane listScroller = new JScrollPane( mTunerTable ); + listScroller.setPreferredSize( new Dimension( 400, 20 ) ); JScrollPane editorScroller = new JScrollPane( new EmptyEditor() ); + editorScroller.setPreferredSize( new Dimension( 400, 80 ) ); mSplitPane = new JideSplitPane(); - mSplitPane.setOrientation( JideSplitPane.HORIZONTAL_SPLIT ); + mSplitPane.setOrientation( JideSplitPane.VERTICAL_SPLIT ); mSplitPane.add( listScroller ); mSplitPane.add( editorScroller ); diff --git a/src/source/tuner/Tuner.java b/src/source/tuner/Tuner.java index e5769b54..cc4a8195 100644 --- a/src/source/tuner/Tuner.java +++ b/src/source/tuner/Tuner.java @@ -17,6 +17,8 @@ ******************************************************************************/ package source.tuner; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.RejectedExecutionException; @@ -32,7 +34,6 @@ import source.SourceException; import source.tuner.frequency.FrequencyChangeEvent; import source.tuner.frequency.FrequencyChangeEvent.Event; import source.tuner.frequency.IFrequencyChangeProcessor; -import controller.ThreadPoolManager; /** * Tuner - provides tuner channel sources, representing a channel frequency @@ -48,12 +49,15 @@ public abstract class Tuner implements IFrequencyChangeProcessor, * Sample Listeners - these will typically be the DFT processor for spectral * display, or it will be one or more tuner channel sources */ - protected CopyOnWriteArrayList> - mSampleListeners = new CopyOnWriteArrayList>(); + protected List> mSampleListeners = + new CopyOnWriteArrayList<>(); - protected CopyOnWriteArrayList - mFrequencyChangeProcessors = new CopyOnWriteArrayList(); + protected List mFrequencyChangeProcessors = + new CopyOnWriteArrayList<>(); + protected List> mTunerChangeListeners = + new ArrayList<>(); + public Tuner( String name ) { mName = name; @@ -148,6 +152,11 @@ public abstract class Tuner implements IFrequencyChangeProcessor, public abstract TunerChannelSource getChannel( TunerChannel channel ) throws RejectedExecutionException, SourceException; + /** + * Count of currently sourced channels (TunerChannel). + */ + public abstract int getChannelCount(); + /** * Releases the tuned channel resources * @@ -211,6 +220,33 @@ public abstract class Tuner implements IFrequencyChangeProcessor, new FrequencyChangeEvent( Event.NOTIFICATION_FREQUENCY_CHANGE, frequency ) ); } + /** + * Registers the listener + */ + public void addTunerChangeListener( Listener listener ) + { + mTunerChangeListeners.add( listener ); + } + + /** + * Removes the registered listener + */ + public void removeTunerChangeListener( Listener listener ) + { + mTunerChangeListeners.remove( listener ); + } + + /** + * Broadcasts the tuner change event + */ + public void broadcast( TunerChangeEvent event ) + { + for( Listener listener: mTunerChangeListeners ) + { + listener.receive( event ); + } + } + /** * Broadcasts a sample rate change event to all registered listeners */ @@ -238,6 +274,15 @@ public abstract class Tuner implements IFrequencyChangeProcessor, { processor.frequencyChanged( event ); } + + if( event.getEvent() == Event.NOTIFICATION_FREQUENCY_CHANGE ) + { + broadcast( new TunerChangeEvent( this, TunerChangeEvent.Event.FREQUENCY ) ); + } + else if( event.getEvent() == Event.NOTIFICATION_SAMPLE_RATE_CHANGE ) + { + broadcast( new TunerChangeEvent( this, TunerChangeEvent.Event.SAMPLE_RATE ) ); + } } /** diff --git a/src/source/tuner/TunerChangeEvent.java b/src/source/tuner/TunerChangeEvent.java new file mode 100644 index 00000000..72bf366c --- /dev/null +++ b/src/source/tuner/TunerChangeEvent.java @@ -0,0 +1,33 @@ +package source.tuner; + +public class TunerChangeEvent +{ + private Tuner mTuner; + private Event mEvent; + + public TunerChangeEvent( Tuner tuner, Event event ) + { + mTuner = tuner; + mEvent = event; + } + + public Tuner getTuner() + { + return mTuner; + } + + public Event getEvent() + { + return mEvent; + } + + public enum Event + { + ADD, + REMOVE, + CHANNEL_COUNT, + FREQUENCY, + SAMPLE_RATE, + SPECTRAL_DISPLAY; + } +} diff --git a/src/source/tuner/TunerController.java b/src/source/tuner/TunerController.java index 93c22339..65a6d859 100644 --- a/src/source/tuner/TunerController.java +++ b/src/source/tuner/TunerController.java @@ -221,6 +221,11 @@ public abstract class TunerController implements Tunable return source; } + + public int getChannelCount() + { + return mTunedChannels.size(); + } /** * Indicates if the tuner's LO frequency must be updated in order to diff --git a/src/source/tuner/TunerType.java b/src/source/tuner/TunerType.java index ea58a9a7..75dc06ca 100644 --- a/src/source/tuner/TunerType.java +++ b/src/source/tuner/TunerType.java @@ -19,7 +19,7 @@ package source.tuner; public enum TunerType { - AIRSPY_R820T( "R820T" ), + AIRSPY_R820T( "R820T/R820T2" ), ELONICS_E4000( "E4000" ), ETTUS_WBX( "WBX" ), ETTUS_VARIOUS( "Ettus Tuner" ), diff --git a/src/source/tuner/airspy/AirspyTuner.java b/src/source/tuner/airspy/AirspyTuner.java index 72fe4506..4637bfc8 100644 --- a/src/source/tuner/airspy/AirspyTuner.java +++ b/src/source/tuner/airspy/AirspyTuner.java @@ -29,6 +29,7 @@ import sample.complex.ComplexBuffer; import settings.SettingsManager; import source.SourceException; import source.tuner.Tuner; +import source.tuner.TunerChangeEvent; import source.tuner.TunerChannel; import source.tuner.TunerChannelSource; import source.tuner.TunerClass; @@ -137,8 +138,23 @@ public class AirspyTuner extends Tuner //Consider implementing a fractional resampler to get a correct 48 kHz //output sample rate - return mController.getChannel( this, channel ); + TunerChannelSource source = mController.getChannel( this, channel ); + + if( source != null ) + { + broadcast( new TunerChangeEvent( this, TunerChangeEvent.Event.CHANNEL_COUNT ) ); + } + + return source; } + + + + @Override + public int getChannelCount() + { + return mController.getChannelCount(); + } @Override public void releaseChannel( TunerChannelSource source ) diff --git a/src/source/tuner/ettus/B100Tuner.java b/src/source/tuner/ettus/B100Tuner.java index 51cc2ba3..b14e0e77 100644 --- a/src/source/tuner/ettus/B100Tuner.java +++ b/src/source/tuner/ettus/B100Tuner.java @@ -105,6 +105,13 @@ public class B100Tuner extends Tuner //TODO: pass this call to the tuner controller return null; } + + @Override + public int getChannelCount() + { + // TODO Auto-generated method stub + return 0; + } @Override public void releaseChannel( TunerChannelSource source ) diff --git a/src/source/tuner/fcd/FCDTuner.java b/src/source/tuner/fcd/FCDTuner.java index 7c304c61..e2a1bcfa 100644 --- a/src/source/tuner/fcd/FCDTuner.java +++ b/src/source/tuner/fcd/FCDTuner.java @@ -28,6 +28,7 @@ import settings.SettingsManager; import source.SourceException; import source.tuner.MixerTuner; import source.tuner.MixerTunerDataLine; +import source.tuner.TunerChangeEvent; import source.tuner.TunerChannel; import source.tuner.TunerChannelSource; import source.tuner.TunerClass; @@ -113,9 +114,22 @@ public class FCDTuner extends MixerTuner public TunerChannelSource getChannel( TunerChannel tunerChannel ) throws RejectedExecutionException, SourceException { - return mController.getChannel( this, tunerChannel ); + TunerChannelSource source = mController.getChannel( this, tunerChannel ); + + if( source != null ) + { + broadcast( new TunerChangeEvent( this, TunerChangeEvent.Event.CHANNEL_COUNT ) ); + } + + return source; } + @Override + public int getChannelCount() + { + return mController.getChannelCount(); + } + /** * Releases the tuned channel so that the tuner controller can tune to * other frequencies as needed. diff --git a/src/source/tuner/hackrf/HackRFTuner.java b/src/source/tuner/hackrf/HackRFTuner.java index 308e67c4..aee8570b 100644 --- a/src/source/tuner/hackrf/HackRFTuner.java +++ b/src/source/tuner/hackrf/HackRFTuner.java @@ -29,6 +29,7 @@ import sample.complex.ComplexBuffer; import settings.SettingsManager; import source.SourceException; import source.tuner.Tuner; +import source.tuner.TunerChangeEvent; import source.tuner.TunerChannel; import source.tuner.TunerChannelSource; import source.tuner.TunerClass; @@ -108,9 +109,22 @@ public class HackRFTuner extends Tuner public TunerChannelSource getChannel( TunerChannel channel ) throws RejectedExecutionException, SourceException { - return mController.getChannel( this, channel ); + TunerChannelSource source = mController.getChannel( this, channel ); + + if( source != null ) + { + broadcast( new TunerChangeEvent( this, TunerChangeEvent.Event.CHANNEL_COUNT ) ); + } + + return source; } + @Override + public int getChannelCount() + { + return mController.getChannelCount(); + } + @Override public void releaseChannel( TunerChannelSource source ) { diff --git a/src/source/tuner/rtl/RTL2832Tuner.java b/src/source/tuner/rtl/RTL2832Tuner.java index 39b6f0f1..55c7dfed 100644 --- a/src/source/tuner/rtl/RTL2832Tuner.java +++ b/src/source/tuner/rtl/RTL2832Tuner.java @@ -30,6 +30,7 @@ import sample.complex.ComplexBuffer; import settings.SettingsManager; import source.SourceException; import source.tuner.Tuner; +import source.tuner.TunerChangeEvent; import source.tuner.TunerChannel; import source.tuner.TunerChannelSource; import source.tuner.TunerClass; @@ -157,6 +158,11 @@ public class RTL2832Tuner extends Tuner try { source = mController.getChannel( this, channel ); + + if( source != null ) + { + broadcast( new TunerChangeEvent( this, TunerChangeEvent.Event.CHANNEL_COUNT ) ); + } } catch( Exception e ) { @@ -165,6 +171,13 @@ public class RTL2832Tuner extends Tuner return source; } + + @Override + public int getChannelCount() + { + return mController.getChannelCount(); + } + /** * Releases the tuned channel so that the tuner controller can tune to * other frequencies as needed.