mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
Merge pull request #363 from DSheirer/170-airspy-mini-sample-rates
#170 Add Support for Airspy Mini tuner's 3 and 6 MHz
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