mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
Resolves #170 adding support for Airspy Mini tuner's 3 and 6 MHz
sample rates. Resolves issue in PolyphaseChannelManager responding to sample rate changes in the tuner. The manager now recreates the channelizer when needed if the tuner's sample rate has changed since the last time the channelizer was used. Updates the Tuner selection view to reflect tuner lock state. Updates the tuner editors to enable/disable frequency controller and sample rate controls according to the tuner's lock state.
This commit is contained in:
@@ -68,9 +68,10 @@ public abstract class AbstractComplexPolyphaseChannelizer implements Listener<Re
|
||||
* Sets the input sample rate for for this channelizer
|
||||
* @param sampleRate in hertz
|
||||
*/
|
||||
public void setSampleRate(double sampleRate)
|
||||
public void setRates(double sampleRate, int channelCount)
|
||||
{
|
||||
mSampleRate = sampleRate;
|
||||
mChannelCount = channelCount;
|
||||
mChannelSampleRate = mSampleRate / (double)mChannelCount;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ import io.github.dsheirer.source.tuner.channel.TunerChannel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -43,7 +42,7 @@ public class ChannelCalculator
|
||||
private int mChannelCount;
|
||||
private double mCenterFrequency;
|
||||
private double mChannelBandwidth;
|
||||
private double mOversampling = 1.0;
|
||||
private double mOversampling = 2.0;
|
||||
|
||||
/**
|
||||
* Calculates channel index(es) from a polyphase channelizer output to source a DDC polyphase channel source
|
||||
@@ -137,9 +136,11 @@ public class ChannelCalculator
|
||||
*
|
||||
* @param sampleRate to use for channel count
|
||||
*/
|
||||
public void setSampleRate(double sampleRate)
|
||||
public void setRates(double sampleRate, int channelCount)
|
||||
{
|
||||
setChannelCount((int)(sampleRate / getChannelBandwidth()));
|
||||
mSampleRate = sampleRate;
|
||||
mChannelCount = channelCount;
|
||||
updateChannelBandwidth();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -544,7 +545,8 @@ public class ChannelCalculator
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Channels:").append(getChannelCount());
|
||||
sb.append("Channel Calculator Settings");
|
||||
sb.append(" Channels:").append(getChannelCount());
|
||||
sb.append(" Sample Rate:").append(getSampleRate());
|
||||
sb.append(" Channel Bandwidth:").append(getChannelBandwidth());
|
||||
sb.append(" Channel Rate:").append(getChannelSampleRate());
|
||||
@@ -552,43 +554,4 @@ public class ChannelCalculator
|
||||
sb.append(" Max:").append(getMaximumFrequency());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
mLog.debug("Starting ....");
|
||||
|
||||
double channelBandwidth = 12500.0;
|
||||
double sampleRate = 100000.0; //Airspy
|
||||
int channelCount = (int)(sampleRate / channelBandwidth);
|
||||
double centerFrequency = 455000000;
|
||||
|
||||
ChannelCalculator calculator = new ChannelCalculator(sampleRate, channelCount, centerFrequency, 2.0);
|
||||
|
||||
mLog.debug(calculator.toString());
|
||||
|
||||
DecimalFormat decimalFormat = new DecimalFormat("000,000,000.0");
|
||||
|
||||
int wrapAroundIndex = calculator.getWrapAroundIndex();
|
||||
|
||||
IndexBoundaryPolicy indexBoundaryPolicy = IndexBoundaryPolicy.ADJUST_NEGATIVE;
|
||||
|
||||
for(int index = wrapAroundIndex; index < calculator.getChannelCount(); index++)
|
||||
{
|
||||
mLog.debug("Index:" + index + " Min:" + decimalFormat.format(calculator.getIndexMinimumFrequency(index, indexBoundaryPolicy)) +
|
||||
" Center:" + decimalFormat.format(calculator.getIndexCenterFrequency(index, indexBoundaryPolicy)) +
|
||||
" Max:" + decimalFormat.format(calculator.getIndexMaximumFrequency(index, indexBoundaryPolicy)));
|
||||
}
|
||||
|
||||
indexBoundaryPolicy = IndexBoundaryPolicy.ADJUST_POSITIVE;
|
||||
|
||||
for(int index = 0; index <= wrapAroundIndex; index++)
|
||||
{
|
||||
mLog.debug("Index:" + index + " Min:" + decimalFormat.format(calculator.getIndexMinimumFrequency(index, indexBoundaryPolicy)) +
|
||||
" Center:" + decimalFormat.format(calculator.getIndexCenterFrequency(index, indexBoundaryPolicy)) +
|
||||
" Max:" + decimalFormat.format(calculator.getIndexMaximumFrequency(index, indexBoundaryPolicy)));
|
||||
}
|
||||
|
||||
mLog.debug("Finished");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
||||
* @param sampleRate to channelize
|
||||
* @return number of multiple of two channels that can be channelized.
|
||||
*/
|
||||
private static int getChannelCount(double sampleRate)
|
||||
public static int getChannelCount(double sampleRate)
|
||||
{
|
||||
int channels = (int)(sampleRate / DEFAULT_MINIMUM_CHANNEL_BANDWIDTH);
|
||||
|
||||
@@ -164,12 +164,11 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
||||
* @param sampleRate in hertz
|
||||
*/
|
||||
@Override
|
||||
public void setSampleRate(double sampleRate)
|
||||
public void setRates(double sampleRate, int channelCount)
|
||||
{
|
||||
try
|
||||
{
|
||||
super.setSampleRate(sampleRate);
|
||||
|
||||
super.setRates(sampleRate, channelCount);
|
||||
float[] filterTaps = FilterFactory.getSincM2Channelizer(getChannelSampleRate(), getChannelCount(),
|
||||
mTapsPerChannel, false);
|
||||
|
||||
|
||||
@@ -108,8 +108,6 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
||||
|
||||
mBufferProcessor = new ContinuousBufferProcessor(200, 50);
|
||||
mBufferProcessor.setListener(mBufferSourceEventMonitor);
|
||||
|
||||
updateChannelizerSampleRate(sampleRate);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,6 +227,7 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
||||
default:
|
||||
//TODO: create output processor for greater than 2 input channels
|
||||
mLog.error("Request to create an output processor for unexpected channel index size:" + indexes.size());
|
||||
mLog.info(mChannelCalculator.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -245,6 +244,8 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
||||
{
|
||||
//Note: the polyphase channel source has already been added to the mChannelSources in getChannel() method
|
||||
|
||||
checkChannelizerConfiguration();
|
||||
|
||||
mPolyphaseChannelizer.addChannel(channelSource);
|
||||
mSourceEventBroadcaster.broadcast(SourceEvent.channelCountChange(getTunerChannelCount()));
|
||||
|
||||
@@ -312,10 +313,9 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
||||
break;
|
||||
case NOTIFICATION_SAMPLE_RATE_CHANGE:
|
||||
//Update channel calculator immediately so that channels can be allocated
|
||||
mChannelCalculator.setSampleRate(sourceEvent.getValue().doubleValue());
|
||||
|
||||
//Defer channelizer configuration changes to be handled on the buffer processor thread
|
||||
mBufferSourceEventMonitor.receive(sourceEvent);
|
||||
double sampleRate = sourceEvent.getValue().doubleValue();
|
||||
int channelCount = (int)Math.ceil(sampleRate / MINIMUM_CHANNEL_BANDWIDTH);
|
||||
mChannelCalculator.setRates(sampleRate, channelCount);
|
||||
break;
|
||||
case NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_LOCKED:
|
||||
case NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_UNLOCKED:
|
||||
@@ -325,7 +325,6 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
||||
default:
|
||||
mLog.info("Unrecognized source event: " + sourceEvent.toString());
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,40 +334,39 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
||||
* Note: this method should only be invoked on the mBufferProcessor thread or prior to starting the mBufferProcessor.
|
||||
* Sample rate source events will normally arrive via the incoming complex buffer stream from the mBufferProcessor
|
||||
* and will be handled as they arrive.
|
||||
*
|
||||
* @param sampleRate to use for the channelizer
|
||||
*/
|
||||
private void updateChannelizerSampleRate(double sampleRate)
|
||||
private void checkChannelizerConfiguration()
|
||||
{
|
||||
if(mPolyphaseChannelizer == null || Math.abs(mPolyphaseChannelizer.getSampleRate() - sampleRate) > 0.5)
|
||||
//Channel calculator is always in sync with the tuner's current sample rate
|
||||
double tunerSampleRate = mChannelCalculator.getSampleRate();
|
||||
|
||||
//If the channelizer is not setup, or setup to the wrong sample rate, recreate it
|
||||
if(mPolyphaseChannelizer == null || Math.abs(mPolyphaseChannelizer.getSampleRate() - tunerSampleRate) > 0.5)
|
||||
{
|
||||
if(mPolyphaseChannelizer != null && mPolyphaseChannelizer.getRegisteredChannelCount() > 0)
|
||||
{
|
||||
throw new IllegalStateException("Polyphase Channelizer cannot be changed to a new sample rate while " +
|
||||
"channels are currently sourced. Ensure you remove all tuner channels before changing tuner " +
|
||||
"sample rate. Current channel count:" +
|
||||
(mPolyphaseChannelizer != null ? mPolyphaseChannelizer.getRegisteredChannelCount() : "0"));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if(mPolyphaseChannelizer == null)
|
||||
{
|
||||
mPolyphaseChannelizer = new ComplexPolyphaseChannelizerM2(sampleRate,
|
||||
POLYPHASE_CHANNELIZER_TAPS_PER_CHANNEL);
|
||||
}
|
||||
else
|
||||
{
|
||||
mPolyphaseChannelizer.setSampleRate(sampleRate);
|
||||
}
|
||||
mPolyphaseChannelizer = new ComplexPolyphaseChannelizerM2(tunerSampleRate,
|
||||
POLYPHASE_CHANNELIZER_TAPS_PER_CHANNEL);
|
||||
}
|
||||
catch(IllegalArgumentException iae)
|
||||
{
|
||||
mLog.error("Could not create polyphase channelizer for sample rate [" + sampleRate + "]", iae);
|
||||
mLog.error("Could not create polyphase channelizer for sample rate [" + tunerSampleRate + "]", iae);
|
||||
}
|
||||
catch(FilterDesignException fde)
|
||||
{
|
||||
mLog.error("Could not create filter for polyphase channelizer for sample rate [" + sampleRate + "]", fde);
|
||||
mLog.error("Could not create filter for polyphase channelizer for sample rate [" + tunerSampleRate + "]", fde);
|
||||
}
|
||||
|
||||
//Clear the previous channel synthesis filters so they can be recreated for the new channel sample rate
|
||||
//Clear any previous channel synthesis filters so they can be recreated for the new channel sample rate
|
||||
mOutputProcessorFilters.clear();
|
||||
|
||||
//Broadcast the new channel sample rate
|
||||
double updatedChannelSampleRate = mChannelCalculator.getChannelSampleRate();
|
||||
updateOutputProcessors(SourceEvent.sampleRateChange(updatedChannelSampleRate, "Channelizer Sample Rate Update"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -600,9 +598,6 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
||||
//Don't send the tuner's frequency change event down to the channels - it would cause chaos
|
||||
updateOutputProcessors(null);
|
||||
break;
|
||||
case NOTIFICATION_SAMPLE_RATE_CHANGE:
|
||||
updateChannelizerSampleRate(queuedSourceEvent.getValue().intValue());
|
||||
break;
|
||||
}
|
||||
|
||||
queuedSourceEvent = mQueuedSourceEvents.poll();
|
||||
|
||||
@@ -125,6 +125,8 @@ public class JFrequencyControl extends JPanel implements ISourceEventProcessor
|
||||
mBlankCursor = Toolkit.getDefaultToolkit()
|
||||
.createCustomCursor(cursorImage, new Point(0, 0), "cursor");
|
||||
|
||||
setTooltip(false);
|
||||
|
||||
revalidate();
|
||||
}
|
||||
|
||||
@@ -139,6 +141,26 @@ public class JFrequencyControl extends JPanel implements ISourceEventProcessor
|
||||
}
|
||||
}
|
||||
|
||||
private void setTooltip(boolean locked)
|
||||
{
|
||||
String tooltip = null;
|
||||
|
||||
if(locked)
|
||||
{
|
||||
tooltip = "Frequency control is locked. Disable decoding channels to unlock.";
|
||||
}
|
||||
else
|
||||
{
|
||||
tooltip = "Click on a frequency digit and type a frequency value, or click the upper/lower digits to " +
|
||||
"change the value";
|
||||
}
|
||||
|
||||
for(Digit digit: mDigits.values())
|
||||
{
|
||||
digit.setToolTipText(tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives a frequency change event invoked by another control. We don't
|
||||
* rebroadcast this event, just set the control to indicate the new frequency.
|
||||
@@ -165,6 +187,7 @@ public class JFrequencyControl extends JPanel implements ISourceEventProcessor
|
||||
public void run()
|
||||
{
|
||||
setEnabled(false);
|
||||
setTooltip(true);
|
||||
}
|
||||
});
|
||||
break;
|
||||
@@ -175,6 +198,7 @@ public class JFrequencyControl extends JPanel implements ISourceEventProcessor
|
||||
public void run()
|
||||
{
|
||||
setEnabled(true);
|
||||
setTooltip(false);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
@@ -65,6 +65,10 @@ public abstract class Tuner implements ISourceEventProcessor
|
||||
case NOTIFICATION_SAMPLE_RATE_CHANGE:
|
||||
broadcast(new TunerEvent(Tuner.this, Event.SAMPLE_RATE));
|
||||
break;
|
||||
case NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_LOCKED:
|
||||
case NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_UNLOCKED:
|
||||
broadcast(new TunerEvent(Tuner.this, Event.LOCK_STATE_CHANGE));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2,33 +2,34 @@ package io.github.dsheirer.source.tuner;
|
||||
|
||||
public class TunerEvent
|
||||
{
|
||||
private Tuner mTuner;
|
||||
private Event mEvent;
|
||||
|
||||
public TunerEvent( Tuner tuner, Event event )
|
||||
{
|
||||
mTuner = tuner;
|
||||
mEvent = event;
|
||||
}
|
||||
|
||||
public Tuner getTuner()
|
||||
{
|
||||
return mTuner;
|
||||
}
|
||||
private Tuner mTuner;
|
||||
private Event mEvent;
|
||||
|
||||
public Event getEvent()
|
||||
{
|
||||
return mEvent;
|
||||
}
|
||||
|
||||
public enum Event
|
||||
{
|
||||
ADD,
|
||||
REMOVE,
|
||||
CHANNEL_COUNT,
|
||||
FREQUENCY,
|
||||
SAMPLE_RATE,
|
||||
REQUEST_MAIN_SPECTRAL_DISPLAY,
|
||||
REQUEST_NEW_SPECTRAL_DISPLAY;
|
||||
}
|
||||
public TunerEvent(Tuner tuner, Event event)
|
||||
{
|
||||
mTuner = tuner;
|
||||
mEvent = event;
|
||||
}
|
||||
|
||||
public Tuner getTuner()
|
||||
{
|
||||
return mTuner;
|
||||
}
|
||||
|
||||
public Event getEvent()
|
||||
{
|
||||
return mEvent;
|
||||
}
|
||||
|
||||
public enum Event
|
||||
{
|
||||
ADD,
|
||||
LOCK_STATE_CHANGE,
|
||||
REMOVE,
|
||||
CHANNEL_COUNT,
|
||||
FREQUENCY,
|
||||
SAMPLE_RATE,
|
||||
REQUEST_MAIN_SPECTRAL_DISPLAY,
|
||||
REQUEST_NEW_SPECTRAL_DISPLAY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,7 +257,16 @@ public class TunerModel extends AbstractTableModel implements Listener<TunerEven
|
||||
return 0;
|
||||
}
|
||||
case CHANNEL_COUNT:
|
||||
return tuner.getChannelSourceManager().getTunerChannelCount();
|
||||
int channelCount = tuner.getChannelSourceManager().getTunerChannelCount();
|
||||
|
||||
if(channelCount > 0)
|
||||
{
|
||||
return channelCount + " (LOCKED)";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "0";
|
||||
}
|
||||
case SPECTRAL_DISPLAY_MAIN:
|
||||
return "Main";
|
||||
case SPECTRAL_DISPLAY_NEW:
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*******************************************************************************
|
||||
* 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/>
|
||||
******************************************************************************/
|
||||
@@ -19,18 +19,27 @@
|
||||
package io.github.dsheirer.source.tuner;
|
||||
|
||||
import com.jidesoft.swing.JideSplitPane;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.source.tuner.TunerEvent.Event;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.RowSorter;
|
||||
import javax.swing.SortOrder;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import javax.swing.table.TableRowSorter;
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
@@ -38,129 +47,150 @@ import java.util.List;
|
||||
|
||||
public class TunerViewPanel extends JPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog = LoggerFactory.getLogger( TunerViewPanel.class );
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog = LoggerFactory.getLogger(TunerViewPanel.class);
|
||||
|
||||
private TunerModel mTunerModel;
|
||||
private JTable mTunerTable;
|
||||
private TableRowSorter<TunerModel> mRowSorter;
|
||||
private JideSplitPane mSplitPane;
|
||||
private TunerEditor mTunerEditor;
|
||||
|
||||
public TunerViewPanel( TunerModel tunerModel )
|
||||
{
|
||||
mTunerModel = tunerModel;
|
||||
mTunerEditor = new TunerEditor( mTunerModel.getTunerConfigurationModel() );
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0", "[fill,grow]", "[fill,grow]" ) );
|
||||
private TunerModel mTunerModel;
|
||||
private JTable mTunerTable;
|
||||
private TableRowSorter<TunerModel> mRowSorter;
|
||||
private JideSplitPane mSplitPane;
|
||||
private TunerEditor mTunerEditor;
|
||||
|
||||
mRowSorter = new TableRowSorter<>( mTunerModel );
|
||||
List<RowSorter.SortKey> sortKeys = new ArrayList<>();
|
||||
sortKeys.add( new RowSorter.SortKey( TunerModel.TUNER_TYPE, SortOrder.ASCENDING ) );
|
||||
sortKeys.add( new RowSorter.SortKey( TunerModel.TUNER_ID, SortOrder.ASCENDING ) );
|
||||
mRowSorter.setSortKeys( sortKeys );
|
||||
|
||||
mTunerTable = new JTable( mTunerModel );
|
||||
mTunerTable.setRowSorter( mRowSorter );
|
||||
mTunerTable.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
|
||||
mTunerTable.getSelectionModel().addListSelectionListener( new ListSelectionListener()
|
||||
{
|
||||
@Override
|
||||
public void valueChanged( ListSelectionEvent event )
|
||||
{
|
||||
if( !event.getValueIsAdjusting() )
|
||||
{
|
||||
int row = mTunerTable.getSelectedRow();
|
||||
int modelRow = mTunerTable.convertRowIndexToModel( row );
|
||||
public TunerViewPanel(TunerModel tunerModel)
|
||||
{
|
||||
mTunerModel = tunerModel;
|
||||
mTunerEditor = new TunerEditor(mTunerModel.getTunerConfigurationModel());
|
||||
|
||||
mTunerEditor.setItem( mTunerModel.getTuner( modelRow ) );
|
||||
}
|
||||
}
|
||||
} );
|
||||
mTunerTable.addMouseListener( new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked( MouseEvent e )
|
||||
{
|
||||
int column = mTunerTable.columnAtPoint( e.getPoint() );
|
||||
init();
|
||||
}
|
||||
|
||||
if( column == TunerModel.SPECTRAL_DISPLAY_MAIN )
|
||||
{
|
||||
int tableRow = mTunerTable.rowAtPoint( e.getPoint() );
|
||||
int modelRow = mTunerTable.convertRowIndexToModel( tableRow );
|
||||
|
||||
Tuner tuner = mTunerModel.getTuner( modelRow );
|
||||
|
||||
if( tuner != null )
|
||||
{
|
||||
mTunerModel.broadcast( new TunerEvent( tuner,
|
||||
Event.REQUEST_MAIN_SPECTRAL_DISPLAY ) );
|
||||
}
|
||||
}
|
||||
else if( column == TunerModel.SPECTRAL_DISPLAY_NEW )
|
||||
{
|
||||
int tableRow = mTunerTable.rowAtPoint( e.getPoint() );
|
||||
int modelRow = mTunerTable.convertRowIndexToModel( tableRow );
|
||||
|
||||
Tuner tuner = mTunerModel.getTuner( modelRow );
|
||||
|
||||
if( tuner != null )
|
||||
{
|
||||
mTunerModel.broadcast( new TunerEvent( tuner,
|
||||
Event.REQUEST_NEW_SPECTRAL_DISPLAY ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
TableCellRenderer renderer = new LinkCellRenderer();
|
||||
|
||||
mTunerTable.getColumnModel().getColumn( 5 ).setCellRenderer( renderer );
|
||||
mTunerTable.getColumnModel().getColumn( 6 ).setCellRenderer( renderer );
|
||||
|
||||
JScrollPane listScroller = new JScrollPane( mTunerTable );
|
||||
listScroller.setPreferredSize( new Dimension( 400, 20 ) );
|
||||
private void init()
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[fill,grow]", "[fill,grow]"));
|
||||
|
||||
JScrollPane editorScroller = new JScrollPane( mTunerEditor );
|
||||
editorScroller.setPreferredSize( new Dimension( 400, 80 ) );
|
||||
|
||||
mSplitPane = new JideSplitPane();
|
||||
mSplitPane.setOrientation( JideSplitPane.VERTICAL_SPLIT );
|
||||
mSplitPane.add( listScroller );
|
||||
mSplitPane.add( editorScroller );
|
||||
|
||||
add( mSplitPane );
|
||||
}
|
||||
|
||||
public class LinkCellRenderer extends DefaultTableCellRenderer
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
mRowSorter = new TableRowSorter<>(mTunerModel);
|
||||
List<RowSorter.SortKey> sortKeys = new ArrayList<>();
|
||||
sortKeys.add(new RowSorter.SortKey(TunerModel.TUNER_TYPE, SortOrder.ASCENDING));
|
||||
sortKeys.add(new RowSorter.SortKey(TunerModel.TUNER_ID, SortOrder.ASCENDING));
|
||||
mRowSorter.setSortKeys(sortKeys);
|
||||
|
||||
@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 );
|
||||
|
||||
label.setForeground( Color.BLUE.brighter() );
|
||||
|
||||
if( column == TunerModel.SPECTRAL_DISPLAY_MAIN )
|
||||
{
|
||||
label.setToolTipText( "Show this tuner in the main spectral display" );
|
||||
}
|
||||
else if( column == TunerModel.SPECTRAL_DISPLAY_NEW )
|
||||
{
|
||||
label.setToolTipText( "Show this tuner in a new spectral display" );
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
}
|
||||
mTunerTable = new JTable(mTunerModel);
|
||||
mTunerTable.setRowSorter(mRowSorter);
|
||||
mTunerTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
mTunerTable.getSelectionModel().addListSelectionListener(new ListSelectionListener()
|
||||
{
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent event)
|
||||
{
|
||||
if(!event.getValueIsAdjusting())
|
||||
{
|
||||
int row = mTunerTable.getSelectedRow();
|
||||
int modelRow = mTunerTable.convertRowIndexToModel(row);
|
||||
|
||||
mTunerEditor.setItem(mTunerModel.getTuner(modelRow));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mTunerModel.addListener(new Listener<TunerEvent>()
|
||||
{
|
||||
@Override
|
||||
public void receive(TunerEvent tunerEvent)
|
||||
{
|
||||
switch(tunerEvent.getEvent())
|
||||
{
|
||||
case LOCK_STATE_CHANGE:
|
||||
int row = mTunerTable.getSelectedRow();
|
||||
|
||||
if(row >= 0)
|
||||
{
|
||||
int modelRow = mTunerTable.convertRowIndexToModel(row);
|
||||
mTunerEditor.setItem(mTunerModel.getTuner(modelRow));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mTunerTable.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
int column = mTunerTable.columnAtPoint(e.getPoint());
|
||||
|
||||
if(column == TunerModel.SPECTRAL_DISPLAY_MAIN)
|
||||
{
|
||||
int tableRow = mTunerTable.rowAtPoint(e.getPoint());
|
||||
int modelRow = mTunerTable.convertRowIndexToModel(tableRow);
|
||||
|
||||
Tuner tuner = mTunerModel.getTuner(modelRow);
|
||||
|
||||
if(tuner != null)
|
||||
{
|
||||
mTunerModel.broadcast(new TunerEvent(tuner,
|
||||
Event.REQUEST_MAIN_SPECTRAL_DISPLAY));
|
||||
}
|
||||
}
|
||||
else if(column == TunerModel.SPECTRAL_DISPLAY_NEW)
|
||||
{
|
||||
int tableRow = mTunerTable.rowAtPoint(e.getPoint());
|
||||
int modelRow = mTunerTable.convertRowIndexToModel(tableRow);
|
||||
|
||||
Tuner tuner = mTunerModel.getTuner(modelRow);
|
||||
|
||||
if(tuner != null)
|
||||
{
|
||||
mTunerModel.broadcast(new TunerEvent(tuner,
|
||||
Event.REQUEST_NEW_SPECTRAL_DISPLAY));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
TableCellRenderer renderer = new LinkCellRenderer();
|
||||
|
||||
mTunerTable.getColumnModel().getColumn(5).setCellRenderer(renderer);
|
||||
mTunerTable.getColumnModel().getColumn(6).setCellRenderer(renderer);
|
||||
|
||||
JScrollPane listScroller = new JScrollPane(mTunerTable);
|
||||
listScroller.setPreferredSize(new Dimension(400, 20));
|
||||
|
||||
JScrollPane editorScroller = new JScrollPane(mTunerEditor);
|
||||
editorScroller.setPreferredSize(new Dimension(400, 80));
|
||||
|
||||
mSplitPane = new JideSplitPane();
|
||||
mSplitPane.setOrientation(JideSplitPane.VERTICAL_SPLIT);
|
||||
mSplitPane.add(listScroller);
|
||||
mSplitPane.add(editorScroller);
|
||||
|
||||
add(mSplitPane);
|
||||
}
|
||||
|
||||
public class LinkCellRenderer extends DefaultTableCellRenderer
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@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);
|
||||
|
||||
label.setForeground(Color.BLUE.brighter());
|
||||
|
||||
if(column == TunerModel.SPECTRAL_DISPLAY_MAIN)
|
||||
{
|
||||
label.setToolTipText("Show this tuner in the main spectral display");
|
||||
}
|
||||
else if(column == TunerModel.SPECTRAL_DISPLAY_NEW)
|
||||
{
|
||||
label.setToolTipText("Show this tuner in a new spectral display");
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,8 +80,7 @@ public class AirspyTunerController extends USBTunerController
|
||||
public static final long FREQUENCY_MAX = 1800000000l;
|
||||
public static final long FREQUENCY_DEFAULT = 101100000;
|
||||
public static final double USABLE_BANDWIDTH_PERCENT = 0.90;
|
||||
public static final AirspySampleRate DEFAULT_SAMPLE_RATE =
|
||||
new AirspySampleRate(0, 10000000, "10.00 MHz");
|
||||
public static final AirspySampleRate DEFAULT_SAMPLE_RATE = new AirspySampleRate(0, 10000000, "10.00 MHz");
|
||||
|
||||
private static final long USB_TIMEOUT_MS = 2000l; //milliseconds
|
||||
private static final byte USB_INTERFACE = (byte) 0x0;
|
||||
@@ -168,7 +167,7 @@ public class AirspyTunerController extends USBTunerController
|
||||
|
||||
try
|
||||
{
|
||||
setSampleRate(DEFAULT_SAMPLE_RATE);
|
||||
setSampleRate(mSampleRates.get(0));
|
||||
}
|
||||
catch(IllegalArgumentException | LibUsbException | UsbException e)
|
||||
{
|
||||
@@ -292,8 +291,7 @@ public class AirspyTunerController extends USBTunerController
|
||||
}
|
||||
catch(UsbException e)
|
||||
{
|
||||
throw new SourceException("Couldn't set sample rate [" +
|
||||
rate.toString() + "]", e);
|
||||
throw new SourceException("Couldn't set sample rate [" + rate.toString() + "]", e);
|
||||
}
|
||||
|
||||
try
|
||||
@@ -314,8 +312,7 @@ public class AirspyTunerController extends USBTunerController
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new SourceException("Couldn't apply gain settings from "
|
||||
+ "airspy config", e);
|
||||
throw new SourceException("Couldn't apply gain settings from airspy config", e);
|
||||
}
|
||||
|
||||
try
|
||||
@@ -389,8 +386,7 @@ public class AirspyTunerController extends USBTunerController
|
||||
* is not supported by the current firmware
|
||||
* @throws UsbException if there was a USB error
|
||||
*/
|
||||
public void setSampleRate(AirspySampleRate rate) throws
|
||||
LibUsbException, UsbException, SourceException
|
||||
public void setSampleRate(AirspySampleRate rate) throws LibUsbException, UsbException, SourceException
|
||||
{
|
||||
if(rate.getRate() != mSampleRate)
|
||||
{
|
||||
@@ -398,8 +394,7 @@ public class AirspyTunerController extends USBTunerController
|
||||
|
||||
if(result != 1)
|
||||
{
|
||||
throw new UsbException("Error setting sample rate [" +
|
||||
rate + "] rate - return value [" + result + "]");
|
||||
throw new UsbException("Error setting sample rate [" + rate + "] rate - return value [" + result + "]");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -607,8 +602,7 @@ public class AirspyTunerController extends USBTunerController
|
||||
* Queries the device for available sample rates. Will always provide at
|
||||
* least the default 10 MHz sample rate.
|
||||
*/
|
||||
private void determineAvailableSampleRates()
|
||||
throws LibUsbException, UsbException
|
||||
private void determineAvailableSampleRates() throws LibUsbException, UsbException
|
||||
{
|
||||
mSampleRates.clear();
|
||||
|
||||
@@ -629,7 +623,6 @@ public class AirspyTunerController extends USBTunerController
|
||||
for(int x = 0; x < count; x++)
|
||||
{
|
||||
int rate = EndianUtils.readSwappedInteger(rawRates, (x * 4));
|
||||
|
||||
mSampleRates.add(new AirspySampleRate(x, rate, formatSampleRate(rate)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ import javax.swing.SwingConstants;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.usb.UsbException;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
@@ -55,8 +54,7 @@ public class AirspyTunerEditor extends TunerConfigurationEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger(AirspyTunerEditor.class);
|
||||
private final static Logger mLog = LoggerFactory.getLogger(AirspyTunerEditor.class);
|
||||
|
||||
private JTextField mConfigurationName;
|
||||
private JButton mTunerInfo;
|
||||
@@ -103,24 +101,6 @@ public class AirspyTunerEditor extends TunerConfigurationEditor
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the enabled state of the sample rate combo control.
|
||||
*
|
||||
* @param enabled state for the sample rate control
|
||||
*/
|
||||
@Override
|
||||
public void setSampleRateControl(boolean enabled)
|
||||
{
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mSampleRateCombo.setEnabled(enabled);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout(new MigLayout("fill,wrap 4", "[right][grow,fill][right][grow,fill]",
|
||||
@@ -616,6 +596,21 @@ public class AirspyTunerEditor extends TunerConfigurationEditor
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the sample rate tooltip according to the tuner controller's lock state.
|
||||
*/
|
||||
private void updateSampleRateToolTip()
|
||||
{
|
||||
if(mController.isLocked())
|
||||
{
|
||||
mSampleRateCombo.setToolTipText("Sample Rate is locked. Disable decoding channels to unlock.");
|
||||
}
|
||||
else
|
||||
{
|
||||
mSampleRateCombo.setToolTipText("Select a sample rate for the tuner");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all controls to the argument enabled state
|
||||
*/
|
||||
@@ -631,7 +626,13 @@ public class AirspyTunerEditor extends TunerConfigurationEditor
|
||||
mTunerInfo.setEnabled(enabled);
|
||||
}
|
||||
|
||||
if(mSampleRateCombo.isEnabled() != enabled)
|
||||
updateSampleRateToolTip();
|
||||
|
||||
if(mController.isLocked())
|
||||
{
|
||||
mSampleRateCombo.setEnabled(false);
|
||||
}
|
||||
else if(mSampleRateCombo.isEnabled() != enabled)
|
||||
{
|
||||
mSampleRateCombo.setEnabled(enabled);
|
||||
}
|
||||
|
||||
@@ -32,12 +32,4 @@ public abstract class TunerConfigurationEditor extends Editor<TunerConfiguration
|
||||
{
|
||||
return mTunerConfigurationModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state of the sample rate editor control. When enabled, users are allowed to change the sample rate
|
||||
* of the tuner. When disabled, user controls should NOT allow sample rate changes.
|
||||
*
|
||||
* @param enabled state for the sample rate control
|
||||
*/
|
||||
public abstract void setSampleRateControl(boolean enabled);
|
||||
}
|
||||
|
||||
@@ -86,12 +86,6 @@ public class FCD1TunerEditor extends TunerConfigurationEditor
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSampleRateControl(boolean enabled)
|
||||
{
|
||||
//no-op
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout(new MigLayout("fill,wrap 4", "[right][grow,fill][right][grow,fill]",
|
||||
|
||||
@@ -76,12 +76,6 @@ public class FCD2TunerEditor extends TunerConfigurationEditor
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSampleRateControl(boolean enabled)
|
||||
{
|
||||
//no-op
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout(new MigLayout("fill,wrap 4", "[right][grow,fill][right][grow,fill]",
|
||||
|
||||
@@ -22,8 +22,8 @@ import io.github.dsheirer.source.SourceException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public class FrequencyController
|
||||
{
|
||||
@@ -38,7 +38,7 @@ public class FrequencyController
|
||||
private double mSampleRate = 0.0d;
|
||||
private boolean mLocked = false;
|
||||
|
||||
private List<ISourceEventProcessor> mProcessors = new ArrayList<>();
|
||||
private List<ISourceEventProcessor> mProcessors = new CopyOnWriteArrayList<>();
|
||||
|
||||
public FrequencyController(Tunable tunable, long minFrequency, long maxFrequency, double frequencyCorrection)
|
||||
{
|
||||
@@ -95,9 +95,16 @@ public class FrequencyController
|
||||
*/
|
||||
public void setSampleRate(int sampleRate) throws SourceException
|
||||
{
|
||||
mSampleRate = sampleRate;
|
||||
if(!mLocked)
|
||||
{
|
||||
mSampleRate = sampleRate;
|
||||
|
||||
broadcastSampleRateChange();
|
||||
broadcastSampleRateChange();
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.warn("Cannot change sample rate while tuner is is LOCKED state.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,6 +115,17 @@ public class FrequencyController
|
||||
return mSampleRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the specified frequency can be tuned (ie is within min/max frequency) by this controller.
|
||||
*
|
||||
* @param frequency to evaluate
|
||||
* @return true if the frequency falls within the tuning range of this controller
|
||||
*/
|
||||
public boolean canTune(long frequency)
|
||||
{
|
||||
return getMinimumFrequency() <= frequency && frequency <= getMaximumFrequency();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get frequency in hertz
|
||||
*/
|
||||
@@ -128,17 +146,6 @@ public class FrequencyController
|
||||
setFrequency(frequency, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the specified frequency can be tuned (ie is within min/max frequency) by this controller.
|
||||
*
|
||||
* @param frequency to evaluate
|
||||
* @return true if the frequency falls within the tuning range of this controller
|
||||
*/
|
||||
public boolean canTune(long frequency)
|
||||
{
|
||||
return getMinimumFrequency() <= frequency && frequency <= getMaximumFrequency();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set frequency with optional broadcast of frequency change event. This
|
||||
* method supports changing the frequency correction value without
|
||||
|
||||
@@ -41,7 +41,6 @@ import javax.swing.SwingConstants;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.usb.UsbException;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
@@ -84,19 +83,6 @@ public class HackRFTunerEditor extends TunerConfigurationEditor
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSampleRateControl(boolean enabled)
|
||||
{
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mComboSampleRate.setEnabled(enabled);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout(new MigLayout("fill,wrap 4", "[right][grow,fill][right][grow,fill]",
|
||||
@@ -297,6 +283,21 @@ public class HackRFTunerEditor extends TunerConfigurationEditor
|
||||
add(mComboVGAGain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the sample rate tooltip according to the tuner controller's lock state.
|
||||
*/
|
||||
private void updateSampleRateToolTip()
|
||||
{
|
||||
if(mController.isLocked())
|
||||
{
|
||||
mComboSampleRate.setToolTipText("Sample Rate is locked. Disable decoding channels to unlock.");
|
||||
}
|
||||
else
|
||||
{
|
||||
mComboSampleRate.setToolTipText("Select a sample rate for the tuner");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets each of the tuner configuration controls to the enabled argument state
|
||||
*/
|
||||
@@ -317,7 +318,13 @@ public class HackRFTunerEditor extends TunerConfigurationEditor
|
||||
mFrequencyCorrection.setEnabled(enabled);
|
||||
}
|
||||
|
||||
if(mComboSampleRate.isEnabled() != enabled)
|
||||
updateSampleRateToolTip();
|
||||
|
||||
if(mController.isLocked())
|
||||
{
|
||||
mComboSampleRate.setEnabled(false);
|
||||
}
|
||||
else if(mComboSampleRate.isEnabled() != enabled)
|
||||
{
|
||||
mComboSampleRate.setEnabled(enabled);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ import javax.swing.SwingConstants;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.usb.UsbException;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
@@ -88,19 +87,6 @@ public class E4KTunerEditor extends TunerConfigurationEditor
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSampleRateControl(boolean enabled)
|
||||
{
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mComboSampleRate.setEnabled(enabled);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout(new MigLayout("fill,wrap 4", "[right][grow,fill][right][grow,fill]",
|
||||
@@ -354,6 +340,21 @@ public class E4KTunerEditor extends TunerConfigurationEditor
|
||||
add(mComboEnhanceGain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the sample rate tooltip according to the tuner controller's lock state.
|
||||
*/
|
||||
private void updateSampleRateToolTip()
|
||||
{
|
||||
if(mController.isLocked())
|
||||
{
|
||||
mComboSampleRate.setToolTipText("Sample Rate is locked. Disable decoding channels to unlock.");
|
||||
}
|
||||
else
|
||||
{
|
||||
mComboSampleRate.setToolTipText("Select a sample rate for the tuner");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets each of the tuner configuration controls to the enabled argument state
|
||||
*/
|
||||
@@ -374,7 +375,13 @@ public class E4KTunerEditor extends TunerConfigurationEditor
|
||||
mFrequencyCorrection.setEnabled(enabled);
|
||||
}
|
||||
|
||||
if(mComboSampleRate.isEnabled() != enabled)
|
||||
updateSampleRateToolTip();
|
||||
|
||||
if(mController.isLocked())
|
||||
{
|
||||
mComboSampleRate.setEnabled(false);
|
||||
}
|
||||
else if(mComboSampleRate.isEnabled() != enabled)
|
||||
{
|
||||
mComboSampleRate.setEnabled(enabled);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ import javax.swing.SwingConstants;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.usb.UsbException;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
@@ -89,19 +88,6 @@ public class R820TTunerEditor extends TunerConfigurationEditor
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSampleRateControl(boolean enabled)
|
||||
{
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mComboSampleRate.setEnabled(enabled);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout(new MigLayout("fill,wrap 4", "[right][grow,fill][right][grow,fill]",
|
||||
@@ -408,6 +394,21 @@ public class R820TTunerEditor extends TunerConfigurationEditor
|
||||
add(mComboVGAGain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the sample rate tooltip according to the tuner controller's lock state.
|
||||
*/
|
||||
private void updateSampleRateToolTip()
|
||||
{
|
||||
if(mController.isLocked())
|
||||
{
|
||||
mComboSampleRate.setToolTipText("Sample Rate is locked. Disable decoding channels to unlock.");
|
||||
}
|
||||
else
|
||||
{
|
||||
mComboSampleRate.setToolTipText("Select a sample rate for the tuner");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets each of the tuner configuration controls to the enabled argument state
|
||||
*/
|
||||
@@ -428,7 +429,13 @@ public class R820TTunerEditor extends TunerConfigurationEditor
|
||||
mFrequencyCorrection.setEnabled(enabled);
|
||||
}
|
||||
|
||||
if(mComboSampleRate.isEnabled() != enabled)
|
||||
updateSampleRateToolTip();
|
||||
|
||||
if(mController.isLocked())
|
||||
{
|
||||
mComboSampleRate.setEnabled(false);
|
||||
}
|
||||
else if(mComboSampleRate.isEnabled() != enabled)
|
||||
{
|
||||
mComboSampleRate.setEnabled(enabled);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user