Closes #71 - frequency controller throws exception when exceeding min/max tuning limits of a tuner.

Updated code to show dialog to user whenever the tuning limit has been exceeded.  Added new InvalidFrequencyException that includes the requested invalid frequency and the valid frequency limit that was exceeded
This commit is contained in:
Denny
2016-06-04 08:21:28 -04:00
parent bf5ded53e2
commit 078a6fddce
14 changed files with 516 additions and 391 deletions

View File

@@ -1,6 +1,6 @@
<component name="CopyrightManager"> <component name="CopyrightManager">
<copyright> <copyright>
<option name="myName" value="sdrtrunk" /> <option name="myName" value="sdrtrunk" />
<option name="notice" value="/*******************************************************************************&#10; * sdrtrunk &#10; * Copyright (C) 2014-&amp;#36;today.year Dennis Sheirer&#10; * &#10; * This program is free software: you can redistribute it and/or modify&#10; * it under the terms of the GNU General Public License as published by&#10; * the Free Software Foundation, either version 3 of the License, or&#10; * (at your option) any later version.&#10; * &#10; * This program is distributed in the hope that it will be useful,&#10; * but WITHOUT ANY WARRANTY; without even the implied warranty of&#10; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the&#10; * GNU General Public License for more details.&#10; * &#10; * You should have received a copy of the GNU General Public License&#10; * along with this program. If not, see &lt;http://www.gnu.org/licenses/&gt;&#10; ******************************************************************************/&#10;" /> <option name="notice" value="sdrtrunk &#10;Copyright (C) 2014-&amp;#36;today.year Dennis Sheirer&#10;&#10;This program is free software: you can redistribute it and/or modify&#10;it under the terms of the GNU General Public License as published by&#10;the Free Software Foundation, either version 3 of the License, or&#10;(at your option) any later version.&#10;&#10;This program is distributed in the hope that it will be useful,&#10;but WITHOUT ANY WARRANTY; without even the implied warranty of&#10;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the&#10;GNU General Public License for more details.&#10; &#10;You should have received a copy of the GNU General Public License&#10;along with this program. If not, see &lt;http://www.gnu.org/licenses/&gt;&#10;" />
</copyright> </copyright>
</component> </component>

View File

@@ -1,19 +1,19 @@
/******************************************************************************* /*******************************************************************************
* SDR Trunk * SDR Trunk
* Copyright (C) 2014 Dennis Sheirer * Copyright (C) 2014 Dennis Sheirer
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> * along with this program. If not, see <http://www.gnu.org/licenses/>
******************************************************************************/ ******************************************************************************/
package gui.control; package gui.control;
@@ -35,15 +35,15 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import javax.swing.JLabel; import javax.swing.*;
import javax.swing.JPanel;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout; import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import source.InvalidFrequencyException;
import source.SourceException;
import source.tuner.frequency.FrequencyChangeEvent; import source.tuner.frequency.FrequencyChangeEvent;
import source.tuner.frequency.FrequencyChangeEvent.Event; import source.tuner.frequency.FrequencyChangeEvent.Event;
import source.tuner.frequency.IFrequencyChangeProcessor; import source.tuner.frequency.IFrequencyChangeProcessor;
@@ -51,181 +51,181 @@ import source.tuner.frequency.IFrequencyChangeProcessor;
public class JFrequencyControl extends JPanel implements IFrequencyChangeProcessor public class JFrequencyControl extends JPanel implements IFrequencyChangeProcessor
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final static Logger mLog = private final static Logger mLog =
LoggerFactory.getLogger( JFrequencyControl.class ); LoggerFactory.getLogger(JFrequencyControl.class);
private List<IFrequencyChangeProcessor> mProcessors = new ArrayList<>(); private List<IFrequencyChangeProcessor> mProcessors = new ArrayList<>();
private Color mHighlightColor = Color.YELLOW; private Color mHighlightColor = Color.YELLOW;
private long mFrequency; private long mFrequency;
private Cursor mBlankCursor; private Cursor mBlankCursor;
private HashMap<Integer,Digit> mDigits = new HashMap<Integer,Digit>(); private HashMap<Integer, Digit> mDigits = new HashMap<Integer, Digit>();
public JFrequencyControl() public JFrequencyControl()
{
init();
}
public JFrequencyControl( long value )
{
this();
mFrequency = value;
}
private void init()
{
setLayout( new MigLayout( "insets 0 0 0 0", "[]0[]", "" ) );
Font font = new Font( Font.MONOSPACED, Font.BOLD, 30 );
for( int x = 9; x >= 0; x-- )
{
Digit digit = null;
try
{
digit = new Digit( x );
}
catch ( ParseException e )
{
mLog.error( "JFrequencyControl - parse exception "
+ "constructing a digit - " + e );
}
if( digit != null )
{
mDigits.put( x, digit );
add( digit );
digit.setFont( font );
if( x == 6 )
{
JLabel period = new JLabel( "." );
add( period );
}
}
}
add( new JLabel( " MHz" ) );
/**
* Create a blank cursor to use when the mouse is over the digits
*/
//Create an empty byte array
byte[] imageByte = new byte[ 0 ];
//Create image for cursor using empty array
Image cursorImage = Toolkit.getDefaultToolkit().createImage( imageByte );
mBlankCursor = Toolkit.getDefaultToolkit()
.createCustomCursor( cursorImage, new Point( 0, 0 ), "cursor" );
revalidate();
}
@Override
public void setEnabled( boolean enabled )
{
super.setEnabled( enabled );
for( Digit digit: mDigits.values() )
{
digit.setEnabled( enabled );
}
}
/**
* Receives a frequency change event invoked by another control. We don't
* rebroadcast this event, just set the control to indicate the new frequency.
*/
@Override
public void frequencyChanged( FrequencyChangeEvent event )
{ {
if( event.getEvent() == Event.NOTIFICATION_FREQUENCY_CHANGE ) init();
{
setFrequency( event.getValue().longValue(), false );
}
} }
/** public JFrequencyControl(long value)
* Loads the frequency into the display and optionally fires a change event {
* to all registered listeners this();
*/ mFrequency = value;
public void setFrequency( long frequency, boolean fireChangeEvent ) }
{
mFrequency = frequency;
for( Digit digit: mDigits.values() ) private void init()
{ {
digit.setFrequency( frequency, fireChangeEvent ); setLayout(new MigLayout("insets 0 0 0 0", "[]0[]", ""));
}
}
public long getFrequency() Font font = new Font(Font.MONOSPACED, Font.BOLD, 30);
{
return mFrequency;
}
private void updateFrequency() for (int x = 9; x >= 0; x--)
{ {
long frequency = 0; Digit digit = null;
for( Digit digit: mDigits.values() ) try
{ {
frequency += digit.getFrequency(); digit = new Digit(x);
} }
catch (ParseException e)
{
mLog.error("JFrequencyControl - parse exception "
+ "constructing a digit - " + e);
}
mFrequency = frequency; if (digit != null)
} {
mDigits.put(x, digit);
private void fireFrequencyChanged() add(digit);
{
updateFrequency();
Iterator<IFrequencyChangeProcessor> it = mProcessors.iterator(); digit.setFont(font);
FrequencyChangeEvent event = new FrequencyChangeEvent( if (x == 6)
Event.REQUEST_FREQUENCY_CHANGE, mFrequency ); {
JLabel period = new JLabel(".");
while( it.hasNext() ) add(period);
{ }
it.next().frequencyChanged( event ); }
} }
}
public void addListener( IFrequencyChangeProcessor processor ) add(new JLabel(" MHz"));
{
mProcessors.add( processor );
}
public void removeListener( IFrequencyChangeProcessor processor ) /**
{ * Create a blank cursor to use when the mouse is over the digits
mProcessors.remove( processor ); */
} //Create an empty byte array
byte[] imageByte = new byte[0];
//Create image for cursor using empty array
Image cursorImage = Toolkit.getDefaultToolkit().createImage(imageByte);
mBlankCursor = Toolkit.getDefaultToolkit()
.createCustomCursor(cursorImage, new Point(0, 0), "cursor");
revalidate();
}
@Override
public void setEnabled(boolean enabled)
{
super.setEnabled(enabled);
for (Digit digit : mDigits.values())
{
digit.setEnabled(enabled);
}
}
/**
* Receives a frequency change event invoked by another control. We don't
* rebroadcast this event, just set the control to indicate the new frequency.
*/
@Override
public void frequencyChanged(FrequencyChangeEvent event)
{
if (event.getEvent() == Event.NOTIFICATION_FREQUENCY_CHANGE)
{
setFrequency(event.getValue().longValue(), false);
}
}
/**
* Loads the frequency into the display and optionally fires a change event
* to all registered listeners
*/
public void setFrequency(long frequency, boolean fireChangeEvent)
{
mFrequency = frequency;
for (Digit digit : mDigits.values())
{
digit.setFrequency(frequency, fireChangeEvent);
}
}
public long getFrequency()
{
return mFrequency;
}
private void updateFrequency()
{
long frequency = 0;
for (Digit digit : mDigits.values())
{
frequency += digit.getFrequency();
}
mFrequency = frequency;
}
private void fireFrequencyChanged() throws SourceException
{
updateFrequency();
Iterator<IFrequencyChangeProcessor> it = mProcessors.iterator();
FrequencyChangeEvent event = new FrequencyChangeEvent(
Event.REQUEST_FREQUENCY_CHANGE, mFrequency);
while (it.hasNext())
{
it.next().frequencyChanged(event);
}
}
public void addListener(IFrequencyChangeProcessor processor)
{
mProcessors.add(processor);
}
public void removeListener(IFrequencyChangeProcessor processor)
{
mProcessors.remove(processor);
}
public class Digit extends JTextField public class Digit extends JTextField
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private int mPower = 0; private int mPower = 0;
private long mValue = 0; private long mValue = 0;
private Digit( int position ) throws ParseException private Digit(int position) throws ParseException
{ {
super( "0" ); super("0");
mPower = position; mPower = position;
Listener listener = new Listener(); Listener listener = new Listener();
this.addKeyListener( listener ); this.addKeyListener(listener);
this.addMouseListener( listener ); this.addMouseListener(listener);
this.addMouseWheelListener( listener ); this.addMouseWheelListener(listener);
} }
/** /**
@@ -233,231 +233,283 @@ public class JFrequencyControl extends JPanel implements IFrequencyChangeProcess
* to the power (ie column) set for this digit. Optionally, fires a * to the power (ie column) set for this digit. Optionally, fires a
* value change event to all listeners. * value change event to all listeners.
*/ */
public void setFrequency( long frequency, boolean fireChangeEvent ) public void setFrequency(long frequency, boolean fireChangeEvent)
{ {
//Strip the digits higher than this one //Strip the digits higher than this one
long lower = frequency % (long)( Math.pow( 10, mPower + 1) ); long lower = frequency % (long) (Math.pow(10, mPower + 1));
//Set the value to int value of dividing by 10 to this power //Set the value to int value of dividing by 10 to this power
long value = (long)( lower / (long)( Math.pow( 10, mPower ) ) ); long value = (long) (lower / (long) (Math.pow(10, mPower)));
set( value, fireChangeEvent ); set(value, fireChangeEvent);
} }
public long getFrequency() public long getFrequency()
{ {
return mValue * (long)Math.pow( 10, mPower ); return mValue * (long) Math.pow(10, mPower);
} }
public void increment() public void increment()
{ {
increment( true ); increment(true);
} }
public void increment( boolean fireChangeEvent ) public void increment(boolean fireChangeEvent)
{ {
if( isEnabled() ) if (isEnabled())
{ {
set( mValue + 1, fireChangeEvent ); set(mValue + 1, fireChangeEvent);
} }
} }
public void decrement() public void decrement()
{ {
decrement( true ); decrement(true);
} }
public void decrement( boolean fireChangeEvent ) public void decrement(boolean fireChangeEvent)
{ {
if( isEnabled() ) if (isEnabled())
{ {
set( mValue - 1, fireChangeEvent ); set(mValue - 1, fireChangeEvent);
} }
} }
/** /**
* Convenience wrapper to change amount and fire change event * Convenience wrapper to change amount and fire change event
*/ */
private void set( long amount ) private void set(long amount)
{ {
set( amount, true ); set(amount, true);
} }
/** /**
* Changes the value and optionally fires change event to listeners * Changes the value and optionally fires change event to listeners
*/ */
private void set( long amount, boolean fireChangeEvent ) private void set(long amount, boolean fireChangeEvent)
{ {
mValue = amount; long previous = mValue;
boolean higherDigitIncremented = false;
boolean higherDigitDecremented = false;
while( mValue < 0 ) mValue = amount;
{
mValue += 10;
Digit nextHigherDigit = mDigits.get( mPower + 1 );
if( nextHigherDigit != null ) while (mValue < 0)
{ {
nextHigherDigit.decrement( false ); mValue += 10;
}
} Digit nextHigherDigit = mDigits.get(mPower + 1);
while( mValue > 9 ) if (nextHigherDigit != null)
{ {
mValue -= 10; nextHigherDigit.decrement(false);
higherDigitDecremented = true;
}
Digit nextHigherDigit = mDigits.get( mPower + 1 ); }
if( nextHigherDigit != null ) while (mValue > 9)
{ {
nextHigherDigit.increment( false ); mValue -= 10;
}
}
setText( String.valueOf( mValue ) ); Digit nextHigherDigit = mDigits.get(mPower + 1);
repaint(); if (nextHigherDigit != null)
{
nextHigherDigit.increment(false);
higherDigitIncremented = true;
}
}
if( fireChangeEvent ) if (fireChangeEvent)
{ {
fireFrequencyChanged(); try
} {
fireFrequencyChanged();
}
catch (SourceException se)
{
mValue = previous;
if (higherDigitIncremented)
{
Digit nextHigherDigit = mDigits.get(mPower + 1);
if (nextHigherDigit != null)
{
nextHigherDigit.decrement(false);
}
}
if (higherDigitDecremented)
{
Digit nextHigherDigit = mDigits.get(mPower + 1);
if (nextHigherDigit != null)
{
nextHigherDigit.increment(false);
}
}
if (se instanceof InvalidFrequencyException)
{
InvalidFrequencyException ife = (InvalidFrequencyException) se;
JOptionPane.showMessageDialog(this, "Frequency [" + ife.getInvalidFrequency() +
"] exceeds the frequency limit [" + ife.getValidFrequency() + "] for this tuner.");
}
}
}
setText(String.valueOf(mValue));
repaint();
} }
private class Listener implements KeyListener, private class Listener implements KeyListener,
MouseListener, MouseListener,
MouseWheelListener MouseWheelListener
{ {
@Override @Override
public void keyReleased( KeyEvent e ) public void keyReleased(KeyEvent e)
{ {
int key = e.getKeyCode(); int key = e.getKeyCode();
switch( key ) switch (key)
{ {
case KeyEvent.VK_0: case KeyEvent.VK_0:
case KeyEvent.VK_NUMPAD0: case KeyEvent.VK_NUMPAD0:
set( 0 ); set(0);
Digit.this.transferFocus(); Digit.this.transferFocus();
break; break;
case KeyEvent.VK_1: case KeyEvent.VK_1:
case KeyEvent.VK_NUMPAD1: case KeyEvent.VK_NUMPAD1:
set( 1 ); set(1);
Digit.this.transferFocus(); Digit.this.transferFocus();
break; break;
case KeyEvent.VK_2: case KeyEvent.VK_2:
case KeyEvent.VK_NUMPAD2: case KeyEvent.VK_NUMPAD2:
set( 2 ); set(2);
Digit.this.transferFocus(); Digit.this.transferFocus();
break; break;
case KeyEvent.VK_3: case KeyEvent.VK_3:
case KeyEvent.VK_NUMPAD3: case KeyEvent.VK_NUMPAD3:
set( 3 ); set(3);
Digit.this.transferFocus(); Digit.this.transferFocus();
break; break;
case KeyEvent.VK_4: case KeyEvent.VK_4:
case KeyEvent.VK_NUMPAD4: case KeyEvent.VK_NUMPAD4:
set( 4 ); set(4);
Digit.this.transferFocus(); Digit.this.transferFocus();
break; break;
case KeyEvent.VK_5: case KeyEvent.VK_5:
case KeyEvent.VK_NUMPAD5: case KeyEvent.VK_NUMPAD5:
set( 5 ); set(5);
Digit.this.transferFocus(); Digit.this.transferFocus();
break; break;
case KeyEvent.VK_6: case KeyEvent.VK_6:
case KeyEvent.VK_NUMPAD6: case KeyEvent.VK_NUMPAD6:
set( 6 ); set(6);
Digit.this.transferFocus(); Digit.this.transferFocus();
break; break;
case KeyEvent.VK_7: case KeyEvent.VK_7:
case KeyEvent.VK_NUMPAD7: case KeyEvent.VK_NUMPAD7:
set( 7 ); set(7);
Digit.this.transferFocus(); Digit.this.transferFocus();
break; break;
case KeyEvent.VK_8: case KeyEvent.VK_8:
case KeyEvent.VK_NUMPAD8: case KeyEvent.VK_NUMPAD8:
set( 8 ); set(8);
Digit.this.transferFocus(); Digit.this.transferFocus();
break; break;
case KeyEvent.VK_9: case KeyEvent.VK_9:
case KeyEvent.VK_NUMPAD9: case KeyEvent.VK_NUMPAD9:
set( 9 ); set(9);
Digit.this.transferFocus(); Digit.this.transferFocus();
break; break;
case KeyEvent.VK_LEFT: case KeyEvent.VK_LEFT:
Digit.this.transferFocusBackward(); Digit.this.transferFocusBackward();
break; break;
case KeyEvent.VK_RIGHT: case KeyEvent.VK_RIGHT:
Digit.this.transferFocus(); Digit.this.transferFocus();
break; break;
case KeyEvent.VK_UP: case KeyEvent.VK_UP:
increment(); increment();
break; break;
case KeyEvent.VK_DOWN: case KeyEvent.VK_DOWN:
decrement(); decrement();
break; break;
case KeyEvent.VK_TAB: case KeyEvent.VK_TAB:
break; break;
default: default:
set( mValue ); set(mValue);
break; break;
} }
repaint(); repaint();
} }
@Override @Override
public void keyPressed( KeyEvent e ) {} public void keyPressed(KeyEvent e)
@Override
public void keyTyped( KeyEvent e ) {}
@Override
public void mouseClicked( MouseEvent e )
{ {
switch( e.getButton() )
{
case MouseEvent.BUTTON1:
increment();
break;
case MouseEvent.BUTTON2:
break;
case MouseEvent.BUTTON3:
decrement();
break;
}
} }
public void mousePressed( MouseEvent e ) {} @Override
public void mouseReleased( MouseEvent e ) {} public void keyTyped(KeyEvent e)
@Override
public void mouseEntered( MouseEvent e )
{ {
Digit.this.setBackground( mHighlightColor );
setCursor( mBlankCursor );
repaint();
} }
@Override @Override
public void mouseExited( MouseEvent e ) public void mouseClicked(MouseEvent e)
{ {
Digit.this.setBackground( Color.WHITE ); switch (e.getButton())
{
setCursor( Cursor.getDefaultCursor() ); case MouseEvent.BUTTON1:
increment();
repaint(); break;
case MouseEvent.BUTTON2:
break;
case MouseEvent.BUTTON3:
decrement();
break;
}
} }
@Override public void mousePressed(MouseEvent e)
public void mouseWheelMoved( MouseWheelEvent e )
{ {
set( mValue - e.getWheelRotation() ); }
public void mouseReleased(MouseEvent e)
{
}
@Override
public void mouseEntered(MouseEvent e)
{
Digit.this.setBackground(mHighlightColor);
setCursor(mBlankCursor);
repaint();
}
@Override
public void mouseExited(MouseEvent e)
{
Digit.this.setBackground(Color.WHITE);
setCursor(Cursor.getDefaultCursor());
repaint();
}
@Override
public void mouseWheelMoved(MouseWheelEvent e)
{
set(mValue - e.getWheelRotation());
} }
} }
} }
} }

View File

@@ -0,0 +1,57 @@
/*******************************************************************************
* sdrtrunk
* 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/>
*
******************************************************************************/
package source;
public class InvalidFrequencyException extends SourceException
{
private long mInvalidFrequency;
private long mValidFrequency;
/**
* Thrown when the user or the application requests to tune to an invalid frequency. Invalid means that the
* frequency is outside of the tunable range of the current tuner device. This class provides both the requested
* invalid frequency and the suggested valid frequency to use in lieu of the requested invalid frequency.
* @param message optional text
* @param invalidFrequency that was requested
* @param validFrequency that should be used instead
*/
public InvalidFrequencyException( String message, long invalidFrequency, long validFrequency )
{
super( message );
mInvalidFrequency = invalidFrequency;
mValidFrequency = validFrequency;
}
/**
* The invalid requested frequency
*/
public long getInvalidFrequency()
{
return mInvalidFrequency;
}
/**
* The valid frequency that should be used
*/
public long getValidFrequency()
{
return mValidFrequency;
}
}

View File

@@ -89,7 +89,7 @@ public class Recording implements Comparable<Recording>,
} }
@Override @Override
public void frequencyChanged( FrequencyChangeEvent event ) public void frequencyChanged( FrequencyChangeEvent event ) throws SourceException
{ {
if( event.getEvent() == Event.NOTIFICATION_FREQUENCY_CHANGE ) if( event.getEvent() == Event.NOTIFICATION_FREQUENCY_CHANGE )
{ {

View File

@@ -82,7 +82,6 @@ public class TunerChannelSource extends ComplexSource
* and thus the tuner might no longer be able to source this channel once it * and thus the tuner might no longer be able to source this channel once it
* has been stopped. * has been stopped.
* *
* @param threadPoolManager to use for decimation processing task
* @param tuner to obtain wideband IQ samples from * @param tuner to obtain wideband IQ samples from
* @param tunerChannel specifying the center frequency for the DDC * @param tunerChannel specifying the center frequency for the DDC
* @throws RejectedExecutionException if the thread pool manager cannot * @throws RejectedExecutionException if the thread pool manager cannot
@@ -229,7 +228,7 @@ public class TunerChannelSource extends ComplexSource
* frequency correction events received from the channel consumer/listener * frequency correction events received from the channel consumer/listener
*/ */
@Override @Override
public void frequencyChanged( FrequencyChangeEvent event ) public void frequencyChanged( FrequencyChangeEvent event ) throws SourceException
{ {
// Echo the event to the registered event listener // Echo the event to the registered event listener
if( mFrequencyChangeProcessor != null ) if( mFrequencyChangeProcessor != null )

View File

@@ -51,7 +51,7 @@ public abstract class TunerController implements Tunable, IFrequencyChangeProces
* @param minimumFrequency minimum uncorrected tunable frequency * @param minimumFrequency minimum uncorrected tunable frequency
* @param maximumFrequency maximum uncorrected tunable frequency * @param maximumFrequency maximum uncorrected tunable frequency
* @param middleUnusable is the +/- value center DC spike to avoid for channels * @param middleUnusable is the +/- value center DC spike to avoid for channels
* @param extantUnusable is the unusable space at the extreme ends of the spectrum * @param usableBandwidthPercentage is the unusable space at the extreme ends of the spectrum
* *
* @throws SourceException - for any issues related to constructing the * @throws SourceException - for any issues related to constructing the
* class, tuning a frequency, or setting the bandwidth * class, tuning a frequency, or setting the bandwidth
@@ -79,18 +79,11 @@ public abstract class TunerController implements Tunable, IFrequencyChangeProces
* Responds to requests to set the frequency * Responds to requests to set the frequency
*/ */
@Override @Override
public void frequencyChanged( FrequencyChangeEvent event ) public void frequencyChanged( FrequencyChangeEvent event ) throws SourceException
{ {
if( event.getEvent() == Event.REQUEST_FREQUENCY_CHANGE ) if( event.getEvent() == Event.REQUEST_FREQUENCY_CHANGE )
{ {
try setFrequency( event.getValue().longValue() );
{
setFrequency( event.getValue().longValue() );
}
catch ( SourceException e )
{
mLog.error( "Error setting frequency from external controller", e );
}
} }
} }
@@ -212,7 +205,6 @@ public abstract class TunerController implements Tunable, IFrequencyChangeProces
* ensure all of the channels can be accomodated and any defined central DC * ensure all of the channels can be accomodated and any defined central DC
* spike avoided. * spike avoided.
* *
* @param threadPoolManager for the channel to use for runnables
* @param tuner to source the channel from * @param tuner to source the channel from
* @param channel with defined center frequency and bandwidth * @param channel with defined center frequency and bandwidth
* *

View File

@@ -405,7 +405,7 @@ public class AirspyTunerController extends TunerController
* Sets the sample rate to the rate specified by the index value in the * Sets the sample rate to the rate specified by the index value in the
* available sample rates map * available sample rates map
* *
* @param index to a sample rate in the available samples rates map. * @param rate to a sample rate in the available samples rates map.
* *
* @throws IllegalArgumentException if index is not a valid rate index * @throws IllegalArgumentException if index is not a valid rate index
* @throws LibUsbException if there was a read error or if this operation * @throws LibUsbException if there was a read error or if this operation
@@ -414,7 +414,7 @@ public class AirspyTunerController extends TunerController
* @throws UsbException if there was a USB error * @throws UsbException if there was a USB error
*/ */
public void setSampleRate( AirspySampleRate rate ) throws public void setSampleRate( AirspySampleRate rate ) throws
LibUsbException, UsbException LibUsbException, UsbException, SourceException
{ {
if( rate.getRate() != mSampleRate ) if( rate.getRate() != mSampleRate )
{ {

View File

@@ -167,7 +167,7 @@ public class AirspyTunerEditor extends TunerConfigurationEditor
mController.setSampleRate( rate ); mController.setSampleRate( rate );
save(); save();
} }
catch ( LibUsbException | UsbException e1 ) catch ( LibUsbException | UsbException | SourceException e1 )
{ {
JOptionPane.showMessageDialog( AirspyTunerEditor.this, JOptionPane.showMessageDialog( AirspyTunerEditor.this,
"Couldn't set sample rate to " + rate.getLabel() ); "Couldn't set sample rate to " + rate.getLabel() );

View File

@@ -76,9 +76,17 @@ public abstract class FCDTunerController extends TunerController
maxTunableFrequency, maxTunableFrequency,
DC_SPIKE_AVOID_BUFFER, DC_SPIKE_AVOID_BUFFER,
USABLE_BANDWIDTH_PERCENT ); USABLE_BANDWIDTH_PERCENT );
mFrequencyController.setSampleRate( sampleRate );
mDevice = device; mDevice = device;
mDeviceDescriptor = descriptor; mDeviceDescriptor = descriptor;
try
{
mFrequencyController.setSampleRate( sampleRate );
}
catch( SourceException se )
{
mLog.error("Error setting sample rate to [" + sampleRate + "]", se );
}
} }
/** /**

View File

@@ -1,10 +1,16 @@
package source.tuner.frequency; package source.tuner.frequency;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sample.Listener; import sample.Listener;
import source.SourceException;
import source.tuner.hackrf.HackRFTunerEditor;
public class FrequencyChangeProcessorWrapper public class FrequencyChangeProcessorWrapper
implements IFrequencyChangeListener, Listener<FrequencyChangeEvent> implements IFrequencyChangeListener, Listener<FrequencyChangeEvent>
{ {
private final static Logger mLog = LoggerFactory.getLogger( FrequencyChangeProcessorWrapper.class );
private IFrequencyChangeProcessor mProcessor; private IFrequencyChangeProcessor mProcessor;
/** /**
@@ -26,7 +32,14 @@ public class FrequencyChangeProcessorWrapper
{ {
if( mProcessor != null ) if( mProcessor != null )
{ {
mProcessor.frequencyChanged( event ); try
{
mProcessor.frequencyChanged( event );
}
catch( SourceException se )
{
mLog.error("Error sending frequency change event to embedded processor", se);
}
} }
} }
} }

View File

@@ -22,6 +22,8 @@ import java.util.ArrayList;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import source.InvalidFrequencyException;
import source.Source;
import source.SourceException; import source.SourceException;
import source.tuner.frequency.FrequencyChangeEvent.Event; import source.tuner.frequency.FrequencyChangeEvent.Event;
@@ -61,7 +63,7 @@ public class FrequencyController
/** /**
* Set sample rate in hertz * Set sample rate in hertz
*/ */
public void setSampleRate( int sampleRate ) public void setSampleRate( int sampleRate ) throws SourceException
{ {
mSampleRate = sampleRate; mSampleRate = sampleRate;
@@ -92,21 +94,22 @@ public class FrequencyController
* method supports changing the frequency correction value without * method supports changing the frequency correction value without
* broadcasting a frequency change event. * broadcasting a frequency change event.
*/ */
private void setFrequency( long frequency, boolean broadcastChange ) private void setFrequency( long frequency, boolean broadcastChange ) throws SourceException
throws SourceException
{ {
long tunedFrequency = getTunedFrequency( frequency ); long tunedFrequency = getTunedFrequency( frequency );
if( tunedFrequency < mMinimumFrequency || if( tunedFrequency < mMinimumFrequency )
tunedFrequency > mMaximumFrequency )
{ {
//TODO: this should throw a frequency limit exception so that the frequency throw new InvalidFrequencyException( "Requested frequency not valid", frequency, mMinimumFrequency );
//controller can update its display to the last tuned frequency }
throw new SourceException( "Cannot tune frequency ( requested: " +
frequency + " actual:" + tunedFrequency + "]" ); if( tunedFrequency > mMaximumFrequency )
{
throw new InvalidFrequencyException( "Requested frequency not valid", frequency, mMaximumFrequency );
} }
mFrequency = frequency; mFrequency = frequency;
mTunedFrequency = tunedFrequency; mTunedFrequency = tunedFrequency;
if( mTunable != null ) if( mTunable != null )
@@ -164,8 +167,7 @@ public class FrequencyController
return mFrequencyCorrection; return mFrequencyCorrection;
} }
public void setFrequencyCorrection( double correction ) public void setFrequencyCorrection( double correction ) throws SourceException
throws SourceException
{ {
mFrequencyCorrection = correction; mFrequencyCorrection = correction;
@@ -202,7 +204,7 @@ public class FrequencyController
* Broadcasts a change/update to the current (uncorrected) frequency or the * Broadcasts a change/update to the current (uncorrected) frequency or the
* bandwidth/sample rate value. * bandwidth/sample rate value.
*/ */
protected void broadcastFrequencyChange() protected void broadcastFrequencyChange() throws SourceException
{ {
broadcastFrequencyChangeEvent( broadcastFrequencyChangeEvent(
new FrequencyChangeEvent( Event.NOTIFICATION_FREQUENCY_CHANGE, mFrequency ) ); new FrequencyChangeEvent( Event.NOTIFICATION_FREQUENCY_CHANGE, mFrequency ) );
@@ -211,7 +213,7 @@ public class FrequencyController
/** /**
* Broadcast a frequency error/correction value change * Broadcast a frequency error/correction value change
*/ */
protected void broadcastFrequencyErrorChange() protected void broadcastFrequencyErrorChange() throws SourceException
{ {
broadcastFrequencyChangeEvent( broadcastFrequencyChangeEvent(
new FrequencyChangeEvent( Event.NOTIFICATION_FREQUENCY_CORRECTION_CHANGE, mFrequencyCorrection ) ); new FrequencyChangeEvent( Event.NOTIFICATION_FREQUENCY_CORRECTION_CHANGE, mFrequencyCorrection ) );
@@ -220,13 +222,13 @@ public class FrequencyController
/** /**
* Broadcasts a sample rate change * Broadcasts a sample rate change
*/ */
protected void broadcastSampleRateChange() protected void broadcastSampleRateChange() throws SourceException
{ {
broadcastFrequencyChangeEvent( broadcastFrequencyChangeEvent(
new FrequencyChangeEvent( Event.NOTIFICATION_SAMPLE_RATE_CHANGE, mSampleRate ) ); new FrequencyChangeEvent( Event.NOTIFICATION_SAMPLE_RATE_CHANGE, mSampleRate ) );
} }
public void broadcastFrequencyChangeEvent( FrequencyChangeEvent event ) public void broadcastFrequencyChangeEvent( FrequencyChangeEvent event ) throws SourceException
{ {
for( IFrequencyChangeProcessor processor: mProcessors ) for( IFrequencyChangeProcessor processor: mProcessors )
{ {

View File

@@ -1,6 +1,8 @@
package source.tuner.frequency; package source.tuner.frequency;
import source.SourceException;
public interface IFrequencyChangeProcessor public interface IFrequencyChangeProcessor
{ {
public void frequencyChanged( FrequencyChangeEvent event ); public void frequencyChanged( FrequencyChangeEvent event ) throws SourceException;
} }

View File

@@ -515,7 +515,7 @@ public class HackRFTunerController extends TunerController
* sample rates. However, since we're only using integral sample rates, we * sample rates. However, since we're only using integral sample rates, we
* simply invoke the setSampleRateManual method directly. * simply invoke the setSampleRateManual method directly.
*/ */
public void setSampleRate( HackRFSampleRate rate ) throws UsbException public void setSampleRate( HackRFSampleRate rate ) throws UsbException, SourceException
{ {
setSampleRateManual( rate.getRate(), 1 ); setSampleRateManual( rate.getRate(), 1 );

View File

@@ -142,7 +142,7 @@ public class HackRFTunerEditor extends TunerConfigurationEditor
mController.setSampleRate( sampleRate ); mController.setSampleRate( sampleRate );
save(); save();
} }
catch ( UsbException e2 ) catch ( SourceException|UsbException e2 )
{ {
JOptionPane.showMessageDialog( HackRFTunerEditor.this, "HackRF Tuner Controller" JOptionPane.showMessageDialog( HackRFTunerEditor.this, "HackRF Tuner Controller"
+ " - couldn't apply the sample rate setting [" + sampleRate.getLabel() + + " - couldn't apply the sample rate setting [" + sampleRate.getLabel() +