wip #34 - finished updating all channel configuration editors and

completed preliminary functional testing.
This commit is contained in:
denny
2016-03-25 14:26:08 -04:00
parent e89e7bd361
commit 112083a22f
32 changed files with 1328 additions and 946 deletions

View File

@@ -4,11 +4,11 @@ import gui.editor.Editor;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.ImageIcon;
@@ -148,6 +148,7 @@ public class AliasController extends JPanel
((Editor<?>)component).setItem( null );
mSplitPane.remove( component );
editor.setPreferredSize( new Dimension( 100, 100 ) );
mSplitPane.add( editor );
mSplitPane.validate();

View File

@@ -183,7 +183,7 @@ public class MultipleAliasEditor extends Editor<List<Alias>>
mPrioritySlider.setMajorTickSpacing( 20 );
mPrioritySlider.setMinorTickSpacing( 5 );
mPrioritySlider.setPaintTicks( true );
mPrioritySlider.setLabelTable( mPrioritySlider.createStandardLabels( 20, 20 ) );
mPrioritySlider.setLabelTable( mPrioritySlider.createStandardLabels( 25, 25 ) );
mPrioritySlider.setPaintLabels( true );
mPrioritySlider.addChangeListener( new ChangeListener()
{

View File

@@ -1,41 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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 controller.channel;
public abstract class AbstractChannelEditor extends ChannelConfigurationEditor
{
private static final long serialVersionUID = 1L;
protected Channel mChannel;
public AbstractChannelEditor( Channel channel )
{
super();
mChannel = channel;
}
public Channel getChannel()
{
return mChannel;
}
public abstract void save();
public abstract void reset();
}

View File

@@ -1,44 +0,0 @@
/*******************************************************************************
* 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/>
******************************************************************************/
package controller.channel;
import javax.swing.JPanel;
public abstract class ChannelConfigurationEditor extends JPanel
{
private static final long serialVersionUID = 1L;
/**
* Sets or resets the configuration editor components
*/
public abstract void setConfiguration( Channel channel );
/**
* Saves the contents of the editor components to the configuration
*/
public abstract void save();
/**
* Validates the contents of the editor components prior to saving the
* content to the configuration.
*
* @throws ConfigurationValidationException if the content is invalid
*/
public abstract void validateConfiguration() throws ConfigurationValidationException;
}

View File

@@ -85,17 +85,17 @@ public class ChannelController extends JPanel
new MigLayout( "insets 0 0 0 0", "[grow,fill][grow,fill][grow,fill]", "[]") );
mNewChannelButton.addActionListener( this );
mNewChannelButton.setToolTipText( "Adds a new default channel" );
mNewChannelButton.setToolTipText( "Create a new channel configuration" );
buttonsPanel.add( mNewChannelButton );
mCopyChannelButton.addActionListener( this );
mCopyChannelButton.setEnabled( false );
mCopyChannelButton.setToolTipText( "Creates a copy of the currently selected channel and adds it" );
mCopyChannelButton.setToolTipText( "Create a copy of the currently selected channel configuration" );
buttonsPanel.add( mCopyChannelButton );
mDeleteChannelButton.addActionListener( this );
mDeleteChannelButton.setEnabled( false );
mDeleteChannelButton.setToolTipText( "Deletes the currently selected channel" );
mDeleteChannelButton.setToolTipText( "Delete the currently selected channel configuration" );
buttonsPanel.add( mDeleteChannelButton );
JPanel listAndButtonsPanel = new JPanel();
@@ -115,10 +115,10 @@ public class ChannelController extends JPanel
//Attempt to get a 60:40 vertical sizing preference
JScrollPane listScroller = new JScrollPane( listAndButtonsPanel );
listScroller.setPreferredSize( new Dimension( 800, 60 ) );
listScroller.setPreferredSize( new Dimension( 800, 58 ) );
JScrollPane editorScroller = new JScrollPane( mEditor );
editorScroller.setPreferredSize( new Dimension( 800, 40 ) );
editorScroller.setPreferredSize( new Dimension( 800, 42 ) );
splitPane.add( listScroller );
splitPane.add( editorScroller );

View File

@@ -81,51 +81,6 @@ public class ChannelEditor extends Editor<Channel> implements ActionListener, Ch
init();
}
/**
* Sets the channel configuration in each of the channel editor components
* Note: this method must be invoked on the swing event dispatch thread
*/
public void setItem( final Channel channel )
{
//Check if the current channel configuration has changed
if( hasItem() &&
( mNameConfigurationEditor.isModified() ) )
{
int option = JOptionPane.showConfirmDialog( ChannelEditor.this,
"This channel configuration has changed. Do you want to save these changes?",
"Save Changes?", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE );
if( option == JOptionPane.YES_OPTION )
{
save();
}
setModified( false );
}
mNameConfigurationEditor.setItem( channel );
mSourceConfigurationEditor.setItem( channel );
mDecodeConfigurationEditor.setItem( channel );
mAuxDecodeConfigurationEditor.setItem( channel );
mEventLogConfigurationEditor.setItem( channel );
mRecordConfigurationEditor.setItem( channel );
if( channel != null )
{
mChannelName.setText( "Channel: " + channel.getName() );
mEnableButton.setText( channel.getEnabled() ? "Disable" : "Enable" );
mEnableButton.setEnabled( true );
mEnableButton.setBackground( channel.getEnabled() ? Color.GREEN : getBackground() );
}
else
{
mChannelName.setText( "Channel: " );
mEnableButton.setText( "Enable" );
mEnableButton.setEnabled( false );
mEnableButton.setBackground( getBackground() );
}
}
private void init()
{
setLayout( new MigLayout( "fill,wrap 3", "[grow,fill][grow,fill][grow,fill]", "[grow,fill][]" ) );
@@ -135,38 +90,48 @@ public class ChannelEditor extends Editor<Channel> implements ActionListener, Ch
tabs.setForeground( Color.BLACK );
tabs.setTabTrailingComponent( mChannelName );
mNameConfigurationEditor.setSaveRequestListener( this );
tabs.addTab( "Name/Alias", mNameConfigurationEditor );
mSourceConfigurationEditor = new SourceConfigurationEditor( mSourceManager );
mSourceConfigurationEditor.setSaveRequestListener( this );
tabs.addTab( "Source", mSourceConfigurationEditor );
mDecodeConfigurationEditor = new DecodeConfigurationEditor( mChannelMapModel );
mDecodeConfigurationEditor.setSaveRequestListener( this );
tabs.addTab( "Decoder", mDecodeConfigurationEditor );
mAuxDecodeConfigurationEditor = new AuxDecodeConfigurationEditor();
mAuxDecodeConfigurationEditor.setSaveRequestListener( this );
tabs.addTab( "Aux Decoders", mAuxDecodeConfigurationEditor );
mEventLogConfigurationEditor = new EventLogConfigurationEditor();
mEventLogConfigurationEditor.setSaveRequestListener( this );
tabs.addTab( "Logging", mEventLogConfigurationEditor );
mRecordConfigurationEditor = new RecordConfigurationEditor();
mRecordConfigurationEditor.setSaveRequestListener( this );
tabs.addTab( "Recording", mRecordConfigurationEditor );
add( tabs, "span" );
mEnableButton.addActionListener( this );
mEnableButton.setEnabled( false );
mEnableButton.setToolTipText( "Start the currently selected channel running/decoding" );
add( mEnableButton );
JButton btnSave = new JButton( "Save" );
btnSave.setToolTipText( "Save changes to the currently selected channel" );
btnSave.addActionListener( ChannelEditor.this );
add( btnSave );
JButton btnReset = new JButton( "Reset" );
btnReset.setToolTipText( "Reload the currently selected channel" );
btnReset.addActionListener( ChannelEditor.this );
add( btnReset );
}
@Override
public void channelChanged( ChannelEvent event )
{
@@ -229,10 +194,48 @@ public class ChannelEditor extends Editor<Channel> implements ActionListener, Ch
}
}
/**
* Sets the channel configuration in each of the channel editor components
* Note: this method must be invoked on the swing event dispatch thread
*/
public void setItem( final Channel channel )
{
super.setItem( channel );
mNameConfigurationEditor.setItem( channel );
mSourceConfigurationEditor.setItem( channel );
mDecodeConfigurationEditor.setItem( channel );
mAuxDecodeConfigurationEditor.setItem( channel );
mEventLogConfigurationEditor.setItem( channel );
mRecordConfigurationEditor.setItem( channel );
if( channel != null )
{
mChannelName.setText( "Channel: " + channel.getName() );
mEnableButton.setText( channel.getEnabled() ? "Disable" : "Enable" );
mEnableButton.setEnabled( true );
mEnableButton.setBackground( channel.getEnabled() ? Color.GREEN : getBackground() );
}
else
{
mChannelName.setText( "Channel: " );
mEnableButton.setText( "Enable" );
mEnableButton.setEnabled( false );
mEnableButton.setBackground( getBackground() );
}
}
public void save()
{
if( hasItem() )
{
mNameConfigurationEditor.save();
mSourceConfigurationEditor.save();
mDecodeConfigurationEditor.save();
mAuxDecodeConfigurationEditor.save();
mEventLogConfigurationEditor.save();
mRecordConfigurationEditor.save();
try
{
mDecodeConfigurationEditor.validate( mSourceConfigurationEditor );
@@ -240,33 +243,17 @@ public class ChannelEditor extends Editor<Channel> implements ActionListener, Ch
}
catch( EditorValidationException e )
{
JOptionPane.showMessageDialog( ChannelEditor.this, e.getReason(),
"Configuration Error", JOptionPane.ERROR_MESSAGE );
e.getEditor().requestFocus();
JOptionPane.showMessageDialog( e.getEditor(), e.getReason(),
"Configuration Error", JOptionPane.ERROR_MESSAGE );
return;
}
boolean changed = mNameConfigurationEditor.isModified() ||
mSourceConfigurationEditor.isModified() ||
mDecodeConfigurationEditor.isModified() ||
mAuxDecodeConfigurationEditor.isModified() ||
mEventLogConfigurationEditor.isModified() ||
mRecordConfigurationEditor.isModified();
mNameConfigurationEditor.save();
mSourceConfigurationEditor.save();
mDecodeConfigurationEditor.save();
mAuxDecodeConfigurationEditor.save();
mEventLogConfigurationEditor.save();
mRecordConfigurationEditor.save();
if( changed )
{
mChannelModel.broadcast( new ChannelEvent( getItem(),
mChannelModel.broadcast( new ChannelEvent( getItem(),
Event.NOTIFICATION_CONFIGURATION_CHANGE ) );
}
}
setModified( false );

View File

@@ -262,5 +262,8 @@ public class NameConfigurationEditor extends Editor<Channel> implements Document
}
@Override
public void removeUpdate( DocumentEvent e ) {}
public void removeUpdate( DocumentEvent e )
{
setModified( true );
}
}

View File

@@ -78,7 +78,7 @@ public class JFrequencyControl extends JPanel implements IFrequencyChangeProcess
private void init()
{
setLayout( new MigLayout( "", "[]0[]", "" ) );
setLayout( new MigLayout( "insets 0 0 0 0", "[]0[]", "" ) );
Font font = new Font( Font.MONOSPACED, Font.BOLD, 30 );

View File

@@ -6,10 +6,19 @@ import javax.swing.JPanel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import alias.id.AliasIdentifierEditor;
/**
* Generic editor with change detection, save and reset functions.
*
* This editor supports hierarchical nesting of sub-component editors where changes are detected
* at the lowest editor in the tree and percolated up to the top-level editor for managing the
* configuration set as a whole.
*
* To configure this editor as a collective, register each parent editor as a saveRequestListener
* on each child editor. If no save request listener is registered, the editor will simply invoke
* save when a change is detected and the user opts to save the contents.
*
* The top-level editor can override the saveRequest() method to perform custom save operations
* and validation.
*/
public abstract class Editor<T> extends JPanel
{
@@ -19,19 +28,51 @@ public abstract class Editor<T> extends JPanel
protected T mItem;
protected boolean mModified = false;
protected Editor<?> mSaveRequestListener;
public Editor()
{
}
/**
* Requests to save the contents of this editor.
*
* If a save request listener is registered, the listener is notified that a save is requested,
* otherwise the save is request is processed by the instance.
*
* This allows for a save event to be percolated up the hierarchical set of editors so that
* a top-level editor can invoke custom operations such as configuration validation.
*/
protected void saveRequest()
{
if( mSaveRequestListener != null )
{
mSaveRequestListener.saveRequest();
}
else
{
save();
}
}
/**
* Registers the editor to be notified when this editor contents have been saved.
*/
public void setSaveRequestListener( Editor<?> listener )
{
mSaveRequestListener = listener;
}
/**
* Sets the object to be edited
* Sets the object to be edited. If the contents from the previous object have changed, this
* prompts the user to save these changes. A saveRequest() is issued and either this editor
* or the parent editor will respond to the save request and invoke the save() method.
*/
public void setItem( T item )
{
if( isModified() )
{
mLog.debug( "Editor that is modified: " + getClass() );
int option = JOptionPane.showConfirmDialog(
Editor.this,
"This item has changed. Do you want to save these changes?",
@@ -41,7 +82,7 @@ public abstract class Editor<T> extends JPanel
if( option == JOptionPane.YES_OPTION )
{
save();
saveRequest();
}
setModified( false );

View File

@@ -10,7 +10,7 @@ public class EmptyValidatingEditor<T> extends ValidatingEditor<T>
public EmptyValidatingEditor( String descriptor )
{
setLayout( new MigLayout( "insets 0 0 0 0", "[center]", "[grow]" ) );
setLayout( new MigLayout( "insets 0 0 0 0", "", "" ) );
add( new JLabel( "Please select " + descriptor ), "wrap" );
}

View File

@@ -42,6 +42,11 @@ public class AuxDecodeConfigurationEditor extends Editor<Channel>
init();
}
public AuxDecodeConfiguration getConfiguration()
{
return hasItem() ? getItem().getAuxDecodeConfiguration() : null;
}
private void init()
{
setLayout( new MigLayout( "fill,wrap 4", "", "[][grow]" ) );

View File

@@ -27,7 +27,6 @@ import java.awt.event.ActionListener;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import net.miginfocom.swing.MigLayout;
@@ -39,21 +38,21 @@ import controller.channel.map.ChannelMapModel;
public class DecodeConfigurationEditor extends ValidatingEditor<Channel>
{
private final static Logger mLog = LoggerFactory.getLogger( DecodeConfigurationEditor.class );
private static final long serialVersionUID = 1L;
private JComboBox<DecoderType> mComboDecoders;
private ValidatingEditor<Channel> mCurrentEditor = new EmptyValidatingEditor<>();
private ValidatingEditor<Channel> mCurrentEditor = new EmptyValidatingEditor<>( "a decoder" );
private ChannelMapModel mChannelMapModel;
public DecodeConfigurationEditor( final ChannelMapModel channelMapModel )
{
mChannelMapModel = channelMapModel;
init();
}
private void init()
{
setLayout( new MigLayout( "fill,wrap 3", "[right][left][grow,fill]", "[][grow]" ) );
setLayout( new MigLayout( "wrap 2", "[][grow,fill]", "[align top][grow,fill]" ) );
mComboDecoders = new JComboBox<DecoderType>();
mComboDecoders.setEnabled( false );
@@ -72,11 +71,11 @@ public class DecodeConfigurationEditor extends ValidatingEditor<Channel>
public void actionPerformed( ActionEvent e )
{
DecoderType selected = mComboDecoders.getItemAt( mComboDecoders.getSelectedIndex() );
setEditor( DecoderFactory.getEditor( selected ) );
ValidatingEditor<Channel> editor = DecoderFactory.getEditor( selected, mChannelMapModel );
setEditor( editor );
}
});
add( new JLabel( "Decoder:" ) );
add( mComboDecoders );
add( mCurrentEditor );
}
@@ -85,9 +84,18 @@ public class DecodeConfigurationEditor extends ValidatingEditor<Channel>
{
if( mCurrentEditor != editor )
{
//Set channel to null in current editor to force a save prompt as required
if( mCurrentEditor.isModified() )
{
mCurrentEditor.setItem( null );
}
remove( mCurrentEditor );
mCurrentEditor = editor;
mCurrentEditor.setSaveRequestListener( this );
mCurrentEditor.setItem( getItem() );
add( mCurrentEditor );
revalidate();
@@ -98,7 +106,7 @@ public class DecodeConfigurationEditor extends ValidatingEditor<Channel>
@Override
public void save()
{
if( hasItem() && mCurrentEditor != null )
if( hasItem() )
{
mCurrentEditor.save();
}
@@ -114,6 +122,7 @@ public class DecodeConfigurationEditor extends ValidatingEditor<Channel>
if( hasItem() )
{
mComboDecoders.setEnabled( true );
mComboDecoders.setSelectedItem( channel.getDecodeConfiguration().getDecoderType() );
mCurrentEditor.setItem( channel );
}
else

View File

@@ -1,127 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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 module.decode;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import module.decode.config.DecodeConfiguration;
import net.miginfocom.swing.MigLayout;
import controller.channel.Channel;
import controller.channel.ChannelConfigurationEditor;
import controller.channel.ConfigurationValidationException;
public class DecodeEditor extends ChannelConfigurationEditor
{
private static final long serialVersionUID = 1L;
protected DecodeConfiguration mConfig;
protected JCheckBox mAFC;
protected JSpinner mAFCMaximumCorrection;
public DecodeEditor( DecodeConfiguration config )
{
setLayout( new MigLayout( "fill,wrap 2", "[right,grow][grow]", "[][][][][grow]" ) );
mConfig = config;
if( config.supportsAFC() )
{
mAFC = new JCheckBox( "Automatic Frequency Control" );
mAFC.setSelected( mConfig.isAFCEnabled() );
mAFC.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent arg0 )
{
mConfig.setAFC( mAFC.isSelected() );
}
} );
mAFC.setToolTipText( "AFC automatically adjusts the center "
+ "frequency of the channel to correct/compensate for "
+ "inaccuracies and frequency drift in the tuner" );
add( mAFC, "span" );
int initial = mConfig.getAFCMaximumCorrection();
SpinnerModel model = new SpinnerNumberModel( initial, 0, 15000, 1 );
mAFCMaximumCorrection = new JSpinner( model );
JSpinner.NumberEditor editor =
(JSpinner.NumberEditor)mAFCMaximumCorrection.getEditor();
editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER );
mAFCMaximumCorrection.setToolTipText( "Sets the maximum frequency "
+ "correction value in hertz, 0 - 15kHz" );
mAFCMaximumCorrection.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
int value = ((SpinnerNumberModel)mAFCMaximumCorrection
.getModel()).getNumber().intValue();
mConfig.setAFCMaximumCorrection( value );
save();
}
} );
add( new JLabel( "Correction Limit Hz:" ) );
add( mAFCMaximumCorrection, "wrap" );
}
}
public DecodeConfiguration getConfig()
{
return mConfig;
}
@Override
public void save()
{
}
@Override
public void setConfiguration( Channel channel )
{
// TODO Auto-generated method stub
}
@Override
public void validateConfiguration() throws ConfigurationValidationException
{
// TODO Auto-generated method stub
}
}

View File

@@ -48,6 +48,7 @@ import module.decode.ltrstandard.DecodeConfigLTRStandard;
import module.decode.ltrstandard.LTRStandardDecoder;
import module.decode.ltrstandard.LTRStandardDecoderPanel;
import module.decode.ltrstandard.LTRStandardDecoderState;
import module.decode.ltrstandard.LTRStandardDecoderEditor;
import module.decode.ltrstandard.LTRStandardMessageFilter;
import module.decode.mdc1200.MDCDecoder;
import module.decode.mdc1200.MDCDecoderPanel;
@@ -56,14 +57,17 @@ import module.decode.mdc1200.MDCMessageFilter;
import module.decode.mpt1327.DecodeConfigMPT1327;
import module.decode.mpt1327.MPT1327Decoder;
import module.decode.mpt1327.MPT1327Decoder.Sync;
import module.decode.mpt1327.MPT1327DecoderEditor;
import module.decode.mpt1327.MPT1327DecoderPanel;
import module.decode.mpt1327.MPT1327DecoderState;
import module.decode.mpt1327.MPT1327MessageFilter;
import module.decode.nbfm.DecodeConfigNBFM;
import module.decode.nbfm.NBFMDecoder;
import module.decode.nbfm.NBFMDecoderPanel;
import module.decode.nbfm.NBFMDecoderEditor;
import module.decode.p25.DecodeConfigP25Phase1;
import module.decode.p25.P25Decoder.Modulation;
import module.decode.p25.P25DecoderEditor;
import module.decode.p25.P25DecoderPanel;
import module.decode.p25.P25DecoderState;
import module.decode.p25.P25_C4FMDecoder;
@@ -74,6 +78,7 @@ import module.decode.passport.DecodeConfigPassport;
import module.decode.passport.PassportDecoder;
import module.decode.passport.PassportDecoderPanel;
import module.decode.passport.PassportDecoderState;
import module.decode.passport.PassportDecoderEditor;
import module.decode.passport.PassportMessageFilter;
import module.decode.state.AlwaysUnsquelchedDecoderState;
import module.decode.state.DecoderPanel;
@@ -464,7 +469,7 @@ public class DecoderFactory
}
}
public static ValidatingEditor<Channel> getEditor( DecoderType type )
public static ValidatingEditor<Channel> getEditor( DecoderType type, ChannelMapModel model )
{
switch( type )
{
@@ -473,20 +478,20 @@ public class DecoderFactory
case LTR_NET:
return new LTRNetDecoderEditor();
case LTR_STANDARD:
break;
return new LTRStandardDecoderEditor();
case MPT1327:
break;
return new MPT1327DecoderEditor( model );
case NBFM:
break;
return new NBFMDecoderEditor();
case P25_PHASE1:
break;
return new P25DecoderEditor();
case PASSPORT:
break;
return new PassportDecoderEditor();
default:
break;
}
return new EmptyValidatingEditor<Channel>();
return new EmptyValidatingEditor<Channel>( "a decoder" );
}
/**

View File

@@ -1,6 +1,6 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 Dennis Sheirer
* Copyright (C) 2014-2016 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,6 +20,10 @@ package module.decode.am;
import gui.editor.Editor;
import gui.editor.EditorValidationException;
import gui.editor.ValidatingEditor;
import javax.swing.JLabel;
import net.miginfocom.swing.MigLayout;
import controller.channel.Channel;
public class AMDecoderEditor extends ValidatingEditor<Channel>
@@ -28,6 +32,8 @@ public class AMDecoderEditor extends ValidatingEditor<Channel>
public AMDecoderEditor()
{
setLayout( new MigLayout( "insets 0 0 0 0", "", "" ) );
add( new JLabel( "AM Decoder" ) );
}
@Override
@@ -35,6 +41,28 @@ public class AMDecoderEditor extends ValidatingEditor<Channel>
{
}
@Override
public void setItem( Channel item )
{
super.setItem( item );
if( hasItem() )
{
if( getItem().getDecodeConfiguration() instanceof DecodeConfigAM )
{
setModified( false );
}
else
{
setModified( true );
}
}
else
{
setModified( false );
}
}
@Override
public void save()
{

View File

@@ -17,7 +17,7 @@
******************************************************************************/
package module.decode.config;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
@@ -48,10 +48,12 @@ public abstract class DecodeConfiguration extends Configuration
public static final int TRAFFIC_CHANNEL_LIMIT_DEFAULT = 3;
public static final int TRAFFIC_CHANNEL_LIMIT_MINIMUM = 0;
public static final int TRAFFIC_CHANNEL_LIMIT_MAXIMUM = 30;
public static final int DEFAULT_AFC_MAX_CORRECTION = 1000;
private DecoderType mDecoderType = DecoderType.NBFM;
private boolean mAFCEnabled = true;
private int mAFCMaxCorrection = 3000;
private int mAFCMaxCorrection = DEFAULT_AFC_MAX_CORRECTION;
public DecodeConfiguration()
{
@@ -68,7 +70,7 @@ public abstract class DecodeConfiguration extends Configuration
return mDecoderType;
}
@XmlElement( name = "afc" )
@XmlAttribute( name = "afc" )
public boolean getAFC()
{
return mAFCEnabled;
@@ -84,6 +86,7 @@ public abstract class DecodeConfiguration extends Configuration
mAFCEnabled = enabled;
}
@XmlAttribute( name = "AFCMaximumCorrection" )
public int getAFCMaximumCorrection()
{
return mAFCMaxCorrection;

View File

@@ -28,9 +28,7 @@ import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@@ -43,8 +41,8 @@ public class LTRNetDecoderEditor extends ValidatingEditor<Channel>
{
private static final long serialVersionUID = 1L;
protected JCheckBox mAFC;
protected JSpinner mAFCMaximumCorrection;
private JCheckBox mAFC;
private JSlider mAFCMaximumCorrection;
private JComboBox<MessageDirection> mComboDirection;
public LTRNetDecoderEditor()
@@ -54,10 +52,9 @@ public class LTRNetDecoderEditor extends ValidatingEditor<Channel>
private void init()
{
setLayout( new MigLayout( "fill,wrap 5", "[left][right][grow,fill][right][grow,fill]",
"[][grow]" ) );
setLayout( new MigLayout( "insets 0 0 0 0,wrap 4", "[right][grow,fill][right][grow,fill]", "" ) );
mAFC = new JCheckBox( "AFC" );
mAFC = new JCheckBox( "AFC: 3000 Hz" );
mAFC.setEnabled( false );
mAFC.setToolTipText( "AFC automatically adjusts the center frequency of the channel to "
+ "correct/compensate for inaccuracies and frequency drift in the tuner" );
@@ -67,26 +64,36 @@ public class LTRNetDecoderEditor extends ValidatingEditor<Channel>
public void actionPerformed( ActionEvent arg0 )
{
setModified( true );
if( mAFC.isSelected() && !mAFCMaximumCorrection.isEnabled() )
{
mAFCMaximumCorrection.setEnabled( true );
}
else if( !mAFC.isSelected() && mAFCMaximumCorrection.isEnabled() )
{
mAFCMaximumCorrection.setEnabled( false );
}
}
} );
add( mAFC );
mAFCMaximumCorrection = new JSpinner( new SpinnerNumberModel( 3000, 0, 15000, 1 ) );
mAFCMaximumCorrection = new JSlider( 0, 7000, 3000 );
mAFCMaximumCorrection.setEnabled( false );
JSpinner.NumberEditor editor = (JSpinner.NumberEditor)mAFCMaximumCorrection.getEditor();
editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER );
mAFCMaximumCorrection.setToolTipText( "Sets the maximum frequency correction value in hertz, 0 - 15kHz" );
mAFCMaximumCorrection.addChangeListener( new ChangeListener()
{
mAFCMaximumCorrection.setToolTipText( "Maximum AFC frequency correction (0 - 15kHz)" );
mAFCMaximumCorrection.setMajorTickSpacing( 2000 );
mAFCMaximumCorrection.setMinorTickSpacing( 1000 );
mAFCMaximumCorrection.setPaintTicks( true );
mAFCMaximumCorrection.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
public void stateChanged( ChangeEvent e )
{
mAFC.setText( "AFC: " + mAFCMaximumCorrection.getValue() + " Hz" );
setModified( true );
}
} );
add( new JLabel( "Correction Limit Hz:" ) );
}
} );
add( mAFCMaximumCorrection );
mComboDirection = new JComboBox<MessageDirection>();
@@ -109,6 +116,7 @@ public class LTRNetDecoderEditor extends ValidatingEditor<Channel>
@Override
public void validate( Editor<Channel> editor ) throws EditorValidationException
{
//No validation
}
@@ -120,7 +128,6 @@ public class LTRNetDecoderEditor extends ValidatingEditor<Channel>
if( hasItem() )
{
mAFC.setEnabled( true );
mAFCMaximumCorrection.setEnabled( true );
mComboDirection.setEnabled( true );
DecodeConfiguration config = getItem().getDecodeConfiguration();
@@ -131,13 +138,25 @@ public class LTRNetDecoderEditor extends ValidatingEditor<Channel>
mComboDirection.setSelectedItem( ltr.getMessageDirection() );
mAFC.setSelected( ltr.isAFCEnabled() );
mAFCMaximumCorrection.setValue( ltr.getAFCMaximumCorrection() );
mAFCMaximumCorrection.setEnabled( ltr.isAFCEnabled() );
setModified( false );
}
else
{
mComboDirection.setSelectedItem( MessageDirection.OSW );
mAFC.setSelected( false );
mAFCMaximumCorrection.setValue( DecodeConfiguration.DEFAULT_AFC_MAX_CORRECTION );
mAFCMaximumCorrection.setEnabled( false );
setModified( true );
}
}
else
{
mAFC.setEnabled( false );
mAFCMaximumCorrection.setEnabled( false );
mComboDirection.setEnabled( false );
setModified( false );
}
}
@@ -147,12 +166,12 @@ public class LTRNetDecoderEditor extends ValidatingEditor<Channel>
if( hasItem() && isModified() )
{
DecodeConfigLTRNet ltr = new DecodeConfigLTRNet();
ltr.setAFC( mAFC.isSelected() );
int value = ((SpinnerNumberModel)mAFCMaximumCorrection.getModel()).getNumber().intValue();
ltr.setAFCMaximumCorrection( value );
ltr.setAFCMaximumCorrection( mAFCMaximumCorrection.getValue() );
ltr.setMessageDirection( (MessageDirection)mComboDirection.getSelectedItem() );
getItem().setDecodeConfiguration( ltr );
}
setModified( false );

View File

@@ -0,0 +1,177 @@
/*******************************************************************************
* 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/>
******************************************************************************/
package module.decode.ltrstandard;
import gui.editor.Editor;
import gui.editor.EditorValidationException;
import gui.editor.ValidatingEditor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import message.MessageDirection;
import module.decode.config.DecodeConfiguration;
import module.decode.ltrnet.DecodeConfigLTRNet;
import net.miginfocom.swing.MigLayout;
import controller.channel.Channel;
public class LTRStandardDecoderEditor extends ValidatingEditor<Channel>
{
private static final long serialVersionUID = 1L;
private JCheckBox mAFC;
private JSlider mAFCMaximumCorrection;
private JComboBox<MessageDirection> mComboDirection;
public LTRStandardDecoderEditor()
{
init();
}
private void init()
{
setLayout( new MigLayout( "insets 0 0 0 0,wrap 4", "[right][grow,fill][right][grow,fill]", "" ) );
mAFC = new JCheckBox( "AFC: 3000 Hz" );
mAFC.setEnabled( false );
mAFC.setToolTipText( "AFC automatically adjusts the center frequency of the channel to "
+ "correct/compensate for inaccuracies and frequency drift in the tuner" );
mAFC.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent arg0 )
{
setModified( true );
if( mAFC.isSelected() && !mAFCMaximumCorrection.isEnabled() )
{
mAFCMaximumCorrection.setEnabled( true );
}
else if( !mAFC.isSelected() && mAFCMaximumCorrection.isEnabled() )
{
mAFCMaximumCorrection.setEnabled( false );
}
}
} );
add( mAFC );
mAFCMaximumCorrection = new JSlider( 0, 7000, 3000 );
mAFCMaximumCorrection.setEnabled( false );
mAFCMaximumCorrection.setToolTipText( "Maximum AFC frequency correction (0 - 15kHz)" );
mAFCMaximumCorrection.setMajorTickSpacing( 2000 );
mAFCMaximumCorrection.setMinorTickSpacing( 1000 );
mAFCMaximumCorrection.setPaintTicks( true );
mAFCMaximumCorrection.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
mAFC.setText( "AFC: " + mAFCMaximumCorrection.getValue() + " Hz" );
setModified( true );
}
} );
add( mAFCMaximumCorrection );
mComboDirection = new JComboBox<MessageDirection>();
mComboDirection.setModel( new DefaultComboBoxModel<MessageDirection>( MessageDirection.values() ) );
mComboDirection.setSelectedItem( MessageDirection.OSW );
mComboDirection.setEnabled( false );
mComboDirection.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{
setModified( true );
}
} );
add( new JLabel( "Format:" ) );
add( mComboDirection );
}
@Override
public void validate( Editor<Channel> editor ) throws EditorValidationException
{
}
@Override
public void setItem( Channel item )
{
super.setItem( item );
if( hasItem() )
{
mAFC.setEnabled( true );
mComboDirection.setEnabled( true );
DecodeConfiguration config = getItem().getDecodeConfiguration();
if( config instanceof DecodeConfigLTRStandard )
{
DecodeConfigLTRStandard ltr = (DecodeConfigLTRStandard)config;
mComboDirection.setSelectedItem( ltr.getMessageDirection() );
mAFC.setSelected( ltr.isAFCEnabled() );
mAFCMaximumCorrection.setValue( ltr.getAFCMaximumCorrection() );
mAFCMaximumCorrection.setEnabled( ltr.isAFCEnabled() );
setModified( false );
}
else
{
mComboDirection.setSelectedItem( MessageDirection.OSW );
mAFC.setSelected( false );
mAFCMaximumCorrection.setValue( DecodeConfiguration.DEFAULT_AFC_MAX_CORRECTION );
mAFCMaximumCorrection.setEnabled( false );
setModified( true );
}
}
else
{
mAFC.setEnabled( false );
mComboDirection.setEnabled( false );
setModified( false );
}
}
@Override
public void save()
{
if( hasItem() && isModified() )
{
DecodeConfigLTRStandard ltr = new DecodeConfigLTRStandard();
ltr.setAFC( mAFC.isSelected() );
ltr.setAFCMaximumCorrection( mAFCMaximumCorrection.getValue() );
ltr.setMessageDirection( (MessageDirection)mComboDirection.getSelectedItem() );
getItem().setDecodeConfiguration( ltr );
}
setModified( false );
}
}

View File

@@ -1,71 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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 module.decode.ltrstandard;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import message.MessageDirection;
import module.decode.DecodeEditor;
import module.decode.config.DecodeConfiguration;
public class LTRStandardEditor extends DecodeEditor
{
private static final long serialVersionUID = 1L;
private JComboBox<MessageDirection> mComboDirection;
public LTRStandardEditor( DecodeConfiguration config )
{
super( config );
initGUI();
}
private void initGUI()
{
mComboDirection = new JComboBox<MessageDirection>();
mComboDirection.setModel(
new DefaultComboBoxModel<MessageDirection>( MessageDirection.values() ) );
mComboDirection.setSelectedItem( ((DecodeConfigLTRStandard)mConfig).getMessageDirection() );
mComboDirection.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{
MessageDirection selected = mComboDirection
.getItemAt( mComboDirection.getSelectedIndex() );
if( selected != null )
{
((DecodeConfigLTRStandard)mConfig).setMessageDirection( selected );
}
}
} );
add( new JLabel( "Format:" ) );
add( mComboDirection, "wrap" );
}
}

View File

@@ -1,219 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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 module.decode.mpt1327;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import module.decode.DecodeEditor;
import module.decode.config.DecodeConfiguration;
import module.decode.mpt1327.MPT1327Decoder.Sync;
import controller.channel.map.ChannelMap;
import controller.channel.map.ChannelMapManagerFrame;
import controller.channel.map.ChannelMapModel;
public class MPT1327ConfigEditor extends DecodeEditor
{
private static final long serialVersionUID = 1L;
private JComboBox<ChannelMap> mComboChannelMaps;
private JComboBox<Sync> mComboSync;
private JLabel mCallTimeoutLabel;
private JSlider mCallTimeout;
private JLabel mTrafficChannelPoolSizeLabel;
private JSlider mTrafficChannelPoolSize;
private ChannelMapModel mChannelMapModel;
public MPT1327ConfigEditor( DecodeConfiguration config,
ChannelMapModel channelMapModel )
{
super( config );
mChannelMapModel = channelMapModel;
initGUI();
}
private DecodeConfigMPT1327 getMPTConfig()
{
return (DecodeConfigMPT1327)mConfig;
}
private void initGUI()
{
/**
* ComboBox: Alias Lists
*/
List<ChannelMap> maps = mChannelMapModel.getChannelMaps();
ChannelMap[] mapArray = maps.toArray( new ChannelMap[ maps.size() ] );
mComboChannelMaps = new JComboBox<ChannelMap>();
mComboChannelMaps.setModel(
new DefaultComboBoxModel<ChannelMap>( mapArray ) );
add( new JLabel( "Channel Map:" ) );
add( mComboChannelMaps, "wrap" );
JButton channelMapManager = new JButton( "Channel Map Manager ..." );
channelMapManager.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{
final ChannelMapManagerFrame manager =
new ChannelMapManagerFrame( mChannelMapModel );
EventQueue.invokeLater( new Runnable()
{
@Override
public void run()
{
manager.setVisible( true );
}
} );
}
} );
add( channelMapManager, "wrap" );
mComboSync = new JComboBox<Sync>();
mComboSync.setModel( new DefaultComboBoxModel<Sync>( Sync.values() ) );
add( new JLabel( "Sync:" ) );
add( mComboSync, "wrap" );
mCallTimeout = new JSlider( JSlider.HORIZONTAL,
DecodeConfiguration.CALL_TIMEOUT_MINIMUM,
DecodeConfiguration.CALL_TIMEOUT_MAXIMUM,
DecodeConfiguration.DEFAULT_CALL_TIMEOUT_SECONDS );
mCallTimeout.setMajorTickSpacing( 90 );
mCallTimeout.setMinorTickSpacing( 10 );
mCallTimeout.setPaintTicks( true );
mCallTimeout.setLabelTable( mCallTimeout.createStandardLabels( 100, 100 ) );
mCallTimeout.setPaintLabels( true );
mCallTimeoutLabel = new JLabel( "Call Timeout: " + mCallTimeout.getValue() + " " );
mCallTimeout.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
mCallTimeoutLabel.setText( "Call Timeout: " + mCallTimeout.getValue() );
}
} );
add( mCallTimeoutLabel );
add( mCallTimeout, "wrap,grow" );
mTrafficChannelPoolSize = new JSlider( JSlider.HORIZONTAL,
DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MINIMUM,
DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MAXIMUM,
DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_DEFAULT );
mTrafficChannelPoolSize.setMajorTickSpacing( 10 );
mTrafficChannelPoolSize.setMinorTickSpacing( 1 );
mTrafficChannelPoolSize.setPaintTicks( true );
mTrafficChannelPoolSize.setLabelTable( mTrafficChannelPoolSize.createStandardLabels( 10, 10 ) );
mTrafficChannelPoolSize.setPaintLabels( true );
mTrafficChannelPoolSizeLabel = new JLabel( "Traffic Channel Pool: " + mTrafficChannelPoolSize.getValue() + " " );
mTrafficChannelPoolSize.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
mTrafficChannelPoolSizeLabel.setText( "Traffic Channel Pool: " + mTrafficChannelPoolSize.getValue() );
}
} );
add( mTrafficChannelPoolSizeLabel );
add( mTrafficChannelPoolSize, "wrap,grow" );
// reset();
}
@Override
public void save()
{
DecodeConfigMPT1327 config = getMPTConfig();
ChannelMap selected = (ChannelMap)mComboChannelMaps.getSelectedItem();
if( selected != null )
{
config.setChannelMapName( selected.getName() );
}
Sync selectedSync = (Sync)mComboSync.getSelectedItem();
if( selectedSync != null )
{
config.setSync( selectedSync );
}
config.setCallTimeout( mCallTimeout.getValue() );
config.setTrafficChannelPoolSize( mTrafficChannelPoolSize.getValue() );
}
// @Override
// public void reset()
// {
// DecodeConfigMPT1327 config = (DecodeConfigMPT1327)mConfig;
//
// String name = config.getChannelMapName();
//
// ChannelMap selected = null;
//
// if( name != null )
// {
// for( ChannelMap map: mPlaylistManager.getPlayist().getChannelMapList()
// .getChannelMap() )
// {
// if( map.getName().equalsIgnoreCase( name ) )
// {
// selected = map;
// }
// }
// }
//
// mComboChannelMaps.setSelectedItem( selected );
// mComboChannelMaps.requestFocus();
// mComboChannelMaps.requestFocusInWindow();
//
// mComboSync.setSelectedItem( config.getSync() );
//
// mCallTimeout.setValue( config.getCallTimeout() );
//
// mTrafficChannelPoolSize.setValue( config.getTrafficChannelPoolSize() );
// }
}

View File

@@ -0,0 +1,287 @@
/*******************************************************************************
* 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/>
******************************************************************************/
package module.decode.mpt1327;
import gui.editor.Editor;
import gui.editor.EditorValidationException;
import gui.editor.ValidatingEditor;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import module.decode.config.DecodeConfiguration;
import module.decode.ltrnet.DecodeConfigLTRNet;
import net.miginfocom.swing.MigLayout;
import controller.channel.Channel;
import controller.channel.map.ChannelMap;
import controller.channel.map.ChannelMapManagerFrame;
import controller.channel.map.ChannelMapModel;
public class MPT1327DecoderEditor extends ValidatingEditor<Channel>
{
private static final long serialVersionUID = 1L;
private JCheckBox mAFC;
private JSlider mAFCMaximumCorrection;
private JComboBox<ChannelMap> mComboChannelMaps;
private JLabel mCallTimeoutLabel;
private JSlider mCallTimeout;
private JLabel mTrafficChannelPoolSizeLabel;
private JSlider mTrafficChannelPoolSize;
private ChannelMapModel mChannelMapModel;
public MPT1327DecoderEditor( ChannelMapModel channelMapModel )
{
mChannelMapModel = channelMapModel;
init();
}
private void init()
{
setLayout( new MigLayout( "insets 0 0 0 0,wrap 4", "[right][grow,fill][right][grow,fill]", "" ) );
mAFC = new JCheckBox( "AFC: 3000 Hz" );
mAFC.setEnabled( false );
mAFC.setToolTipText( "AFC automatically adjusts the center frequency of the channel to "
+ "correct/compensate for inaccuracies and frequency drift in the tuner" );
mAFC.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent arg0 )
{
setModified( true );
if( mAFC.isSelected() && !mAFCMaximumCorrection.isEnabled() )
{
mAFCMaximumCorrection.setEnabled( true );
}
else if( !mAFC.isSelected() && mAFCMaximumCorrection.isEnabled() )
{
mAFCMaximumCorrection.setEnabled( false );
}
}
} );
add( mAFC );
mAFCMaximumCorrection = new JSlider( 0, 7000, 3000 );
mAFCMaximumCorrection.setEnabled( false );
mAFCMaximumCorrection.setToolTipText( "Maximum AFC frequency correction (0 - 15kHz)" );
mAFCMaximumCorrection.setMajorTickSpacing( 2000 );
mAFCMaximumCorrection.setMinorTickSpacing( 1000 );
mAFCMaximumCorrection.setPaintTicks( true );
mAFCMaximumCorrection.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
mAFC.setText( "AFC: " + mAFCMaximumCorrection.getValue() + " Hz" );
setModified( true );
}
} );
add( mAFCMaximumCorrection );
JButton channelMaps = new JButton( "Channel Maps" );
channelMaps.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{
final ChannelMapManagerFrame manager =
new ChannelMapManagerFrame( mChannelMapModel );
EventQueue.invokeLater( new Runnable()
{
@Override
public void run()
{
manager.setVisible( true );
}
} );
}
} );
add( channelMaps, "span 2" );
List<ChannelMap> maps = mChannelMapModel.getChannelMaps();
ChannelMap[] mapArray = maps.toArray( new ChannelMap[ maps.size() ] );
mComboChannelMaps = new JComboBox<ChannelMap>();
mComboChannelMaps.setModel( new DefaultComboBoxModel<ChannelMap>( mapArray ) );
mComboChannelMaps.setEnabled( false );
add( new JLabel( "Channel Map:" ) );
add( mComboChannelMaps, "span 3,grow" );
mTrafficChannelPoolSize = new JSlider( JSlider.HORIZONTAL, DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MINIMUM,
DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MAXIMUM, DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_DEFAULT );
mTrafficChannelPoolSize.setEnabled( false );
mTrafficChannelPoolSize.setMajorTickSpacing( 10 );
mTrafficChannelPoolSize.setMinorTickSpacing( 5 );
mTrafficChannelPoolSize.setPaintTicks( true );
mTrafficChannelPoolSizeLabel = new JLabel( "Traffic Pool: " +
mTrafficChannelPoolSize.getValue() + " " );
mTrafficChannelPoolSize.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
mTrafficChannelPoolSizeLabel.setText( "Traffic Pool: " +
mTrafficChannelPoolSize.getValue() );
}
} );
add( mTrafficChannelPoolSizeLabel );
add( mTrafficChannelPoolSize );
mCallTimeout = new JSlider( JSlider.HORIZONTAL, DecodeConfiguration.CALL_TIMEOUT_MINIMUM,
DecodeConfiguration.CALL_TIMEOUT_MAXIMUM, DecodeConfiguration.DEFAULT_CALL_TIMEOUT_SECONDS );
mCallTimeout.setEnabled( false );
mCallTimeout.setMajorTickSpacing( 100 );
mCallTimeout.setMinorTickSpacing( 50 );
mCallTimeout.setPaintTicks( true );
mCallTimeoutLabel = new JLabel( "Timeout: " + mCallTimeout.getValue() + " " );
mCallTimeout.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
mCallTimeoutLabel.setText( "Timeout: " + mCallTimeout.getValue() );
}
} );
add( mCallTimeoutLabel );
add( mCallTimeout );
}
@Override
public void save()
{
if( hasItem() && isModified() )
{
DecodeConfigMPT1327 mpt = new DecodeConfigMPT1327();
mpt.setAFC( mAFC.isSelected() );
mpt.setAFCMaximumCorrection( mAFCMaximumCorrection.getValue() );
mpt.setTrafficChannelPoolSize( mTrafficChannelPoolSize.getValue() );
mpt.setCallTimeout( mCallTimeout.getValue() );
if( mComboChannelMaps.getSelectedItem() != null )
{
ChannelMap map = (ChannelMap)mComboChannelMaps.getSelectedItem();
mpt.setChannelMapName( map.getName() );
}
getItem().setDecodeConfiguration( mpt );
}
setModified( false );
}
@Override
public void validate( Editor<Channel> editor ) throws EditorValidationException
{
//No validation required
}
private void setControlsEnabled( boolean enabled )
{
if( mAFC.isEnabled() != enabled )
{
mAFC.setEnabled( enabled );
}
if( mComboChannelMaps.isEnabled() != enabled )
{
mComboChannelMaps.setEnabled( enabled );
}
if( mTrafficChannelPoolSize.isEnabled() != enabled )
{
mTrafficChannelPoolSize.setEnabled( enabled );
}
if( mCallTimeout.isEnabled() != enabled )
{
mCallTimeout.setEnabled( enabled );
}
}
@Override
public void setItem( Channel item )
{
super.setItem( item );
if( hasItem() )
{
setControlsEnabled( true );
DecodeConfiguration config = getItem().getDecodeConfiguration();
if( config instanceof DecodeConfigMPT1327 )
{
DecodeConfigMPT1327 mpt = (DecodeConfigMPT1327)config;
mAFC.setSelected( mpt.isAFCEnabled() );
mAFCMaximumCorrection.setValue( mpt.getAFCMaximumCorrection() );
mAFCMaximumCorrection.setEnabled( mpt.isAFCEnabled() );
ChannelMap map = mChannelMapModel.getChannelMap( mpt.getChannelMapName() );
if( map != null )
{
mComboChannelMaps.setSelectedItem( map );
}
mTrafficChannelPoolSize.setValue( mpt.getTrafficChannelPoolSize() );
mCallTimeout.setValue( mpt.getCallTimeout() );
setModified( false );
}
else
{
mAFC.setSelected( false );
mAFCMaximumCorrection.setValue( DecodeConfiguration.DEFAULT_AFC_MAX_CORRECTION );
mAFCMaximumCorrection.setEnabled( false );
mTrafficChannelPoolSize.setValue( DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_DEFAULT );
mCallTimeout.setValue( DecodeConfiguration.DEFAULT_CALL_TIMEOUT_SECONDS );
setModified( true );
}
}
else
{
setControlsEnabled( false );
setModified( false );
}
}
}

View File

@@ -0,0 +1,161 @@
/*******************************************************************************
* 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/>
******************************************************************************/
package module.decode.nbfm;
import gui.editor.Editor;
import gui.editor.EditorValidationException;
import gui.editor.ValidatingEditor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JCheckBox;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import module.decode.config.DecodeConfiguration;
import net.miginfocom.swing.MigLayout;
import controller.channel.Channel;
public class NBFMDecoderEditor extends ValidatingEditor<Channel>
{
private static final long serialVersionUID = 1L;
private JCheckBox mAFC;
private JSlider mAFCMaximumCorrection;
public NBFMDecoderEditor()
{
init();
}
private void init()
{
setLayout( new MigLayout( "insets 0 0 0 0,wrap 2", "[right][grow,fill]", "" ) );
mAFC = new JCheckBox( "AFC: 3000 Hz" );
mAFC.setEnabled( false );
mAFC.setToolTipText( "AFC automatically adjusts the center frequency of the channel to "
+ "correct/compensate for inaccuracies and frequency drift in the tuner" );
mAFC.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent arg0 )
{
setModified( true );
if( mAFC.isSelected() && !mAFCMaximumCorrection.isEnabled() )
{
mAFCMaximumCorrection.setEnabled( true );
}
else if( !mAFC.isSelected() && mAFCMaximumCorrection.isEnabled() )
{
mAFCMaximumCorrection.setEnabled( false );
}
}
} );
add( mAFC );
mAFCMaximumCorrection = new JSlider( 0, 7000, 3000 );
mAFCMaximumCorrection.setEnabled( false );
mAFCMaximumCorrection.setToolTipText( "Maximum AFC frequency correction (0 - 15kHz)" );
mAFCMaximumCorrection.setMajorTickSpacing( 2000 );
mAFCMaximumCorrection.setMinorTickSpacing( 1000 );
mAFCMaximumCorrection.setPaintTicks( true );
mAFCMaximumCorrection.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
mAFC.setText( "AFC: " + mAFCMaximumCorrection.getValue() + " Hz" );
setModified( true );
}
} );
add( mAFCMaximumCorrection );
}
@Override
public void validate( Editor<Channel> editor ) throws EditorValidationException
{
//No validation
}
@Override
public void save()
{
if( hasItem() && isModified() )
{
DecodeConfigNBFM nbfm = new DecodeConfigNBFM();
nbfm.setAFC( mAFC.isSelected() );
nbfm.setAFCMaximumCorrection( mAFCMaximumCorrection.getValue() );
getItem().setDecodeConfiguration( nbfm );
}
setModified( false );
}
private void setControlsEnabled( boolean enabled )
{
if( mAFC.isEnabled() != enabled )
{
mAFC.setEnabled( enabled );
}
}
@Override
public void setItem( Channel item )
{
super.setItem( item );
if( hasItem() )
{
setControlsEnabled( true );
DecodeConfiguration config = getItem().getDecodeConfiguration();
if( config instanceof DecodeConfigNBFM )
{
DecodeConfigNBFM nbfm = (DecodeConfigNBFM)config;
mAFC.setSelected( nbfm.isAFCEnabled() );
mAFCMaximumCorrection.setValue( nbfm.getAFCMaximumCorrection() );
mAFCMaximumCorrection.setEnabled( nbfm.isAFCEnabled() );
setModified( false );
}
else
{
mAFC.setSelected( false );
mAFCMaximumCorrection.setValue( DecodeConfiguration.DEFAULT_AFC_MAX_CORRECTION );
mAFCMaximumCorrection.setEnabled( false );
setModified( true );
}
}
else
{
setControlsEnabled( false );
setModified( false );
}
}
}

View File

@@ -1,35 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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 module.decode.nbfm;
import javax.swing.JCheckBox;
import module.decode.DecodeEditor;
import module.decode.config.DecodeConfiguration;
public class NBFMEditor extends DecodeEditor
{
private static final long serialVersionUID = 1L;
private JCheckBox mAFC;
public NBFMEditor( DecodeConfiguration config )
{
super( config );
}
}

View File

@@ -1,147 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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 module.decode.p25;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import module.decode.DecodeEditor;
import module.decode.config.DecodeConfiguration;
import module.decode.p25.P25Decoder.Modulation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import source.SourceConfigurationEditor;
import source.tuner.TunerSourceEditor;
import controller.channel.ChannelConfigurationEditor;
import controller.channel.ConfigurationValidationException;
public class P25DecodeEditor extends DecodeEditor
{
private final static Logger mLog = LoggerFactory.getLogger( P25DecodeEditor.class );
private static final long serialVersionUID = 1L;
private JComboBox<P25_LSMDecoder.Modulation> mComboModulation;
private JCheckBox mIgnoreDataCalls;
private JLabel mTrafficChannelPoolSizeLabel;
private JSlider mTrafficChannelPoolSize;
public P25DecodeEditor( DecodeConfiguration config )
{
super( config );
initGUI();
}
private void initGUI()
{
final DecodeConfigP25Phase1 config = (DecodeConfigP25Phase1)mConfig;
mComboModulation = new JComboBox<P25_LSMDecoder.Modulation>();
mComboModulation.setModel( new DefaultComboBoxModel<P25_LSMDecoder.Modulation>(
P25_LSMDecoder.Modulation.values() ) );
mComboModulation.setSelectedItem( config.getModulation() );
add( new JLabel( "Modulation:" ) );
add( mComboModulation, "wrap" );
mTrafficChannelPoolSize = new JSlider( JSlider.HORIZONTAL,
DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MINIMUM,
DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MAXIMUM,
config.getTrafficChannelPoolSize() );
mTrafficChannelPoolSize.setMajorTickSpacing( 10 );
mTrafficChannelPoolSize.setMinorTickSpacing( 1 );
mTrafficChannelPoolSize.setPaintTicks( true );
mTrafficChannelPoolSize.setLabelTable( mTrafficChannelPoolSize.createStandardLabels( 10, 10 ) );
mTrafficChannelPoolSize.setPaintLabels( true );
mTrafficChannelPoolSizeLabel = new JLabel( "Traffic Channel Pool: " + mTrafficChannelPoolSize.getValue() + " " );
mTrafficChannelPoolSize.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
mTrafficChannelPoolSizeLabel.setText( "Traffic Channel Pool: " + mTrafficChannelPoolSize.getValue() );
}
} );
add( mTrafficChannelPoolSizeLabel );
add( mTrafficChannelPoolSize, "wrap,grow" );
mIgnoreDataCalls = new JCheckBox();
mIgnoreDataCalls.setSelected( config.getIgnoreDataCalls() );
add( new JLabel( "Ignore Data Calls" ) );
add( mIgnoreDataCalls, "wrap,grow" );
// reset();
}
// /**
// * Enforce source=tuner for CQPSK modulation
// */
// @Override
// public void validate( ChannelConfigurationEditor editor ) throws ConfigurationValidationException
// {
// if( editor instanceof SourceEditor &&
// ((DecodeConfigP25Phase1)mConfig).getModulation() == Modulation.CQPSK )
// {
// if( !( editor instanceof TunerEditor ) )
// {
// throw new ConfigurationValidationException(
// "<html><body width='175'><h1>LSM Simulcast</h1>"
// + "<p>P25 LSM Simulcast decoder can only be used with "
// + "a tuner source. Please change the Source to use a tuner"
// + " or change the P25 Decoder to C4FM modulation" );
//
// }
// }
// }
@Override
public void save()
{
DecodeConfigP25Phase1 config = (DecodeConfigP25Phase1)mConfig;
config.setModulation( (Modulation)mComboModulation.getSelectedItem() );
config.setIgnoreDataCalls( mIgnoreDataCalls.isSelected() );
config.setTrafficChannelPoolSize( mTrafficChannelPoolSize.getValue() );
}
// @Override
// public void reset()
// {
// DecodeConfigP25Phase1 config = (DecodeConfigP25Phase1)mConfig;
//
// mComboModulation.setSelectedItem( config.getModulation() );
// mIgnoreDataCalls.setSelected( config.getIgnoreDataCalls() );
// mTrafficChannelPoolSize.setValue( config.getTrafficChannelPoolSize() );
// }
}

View File

@@ -0,0 +1,226 @@
/*******************************************************************************
* 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/>
******************************************************************************/
package module.decode.p25;
import gui.editor.Editor;
import gui.editor.EditorValidationException;
import gui.editor.ValidatingEditor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import module.decode.AuxDecodeConfigurationEditor;
import module.decode.config.AuxDecodeConfiguration;
import module.decode.config.DecodeConfiguration;
import module.decode.p25.P25Decoder.Modulation;
import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import source.SourceConfigurationEditor;
import source.config.SourceConfigTuner;
import source.config.SourceConfiguration;
import controller.channel.Channel;
public class P25DecoderEditor extends ValidatingEditor<Channel>
{
private final static Logger mLog = LoggerFactory.getLogger( P25DecoderEditor.class );
private static final long serialVersionUID = 1L;
private JComboBox<P25_LSMDecoder.Modulation> mComboModulation;
private JCheckBox mIgnoreDataCalls;
private JLabel mTrafficChannelPoolSizeLabel;
private JSlider mTrafficChannelPoolSize;
public P25DecoderEditor()
{
init();
}
private void init()
{
setLayout( new MigLayout( "insets 0 0 0 0,wrap 3", "[right][grow,fill][]", "" ) );
mComboModulation = new JComboBox<P25_LSMDecoder.Modulation>();
mComboModulation.setModel( new DefaultComboBoxModel<P25_LSMDecoder.Modulation>(
P25_LSMDecoder.Modulation.values() ) );
mComboModulation.setEnabled( false );
mComboModulation.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{
setModified( true );
}
} );
add( new JLabel( "Modulation:" ) );
add( mComboModulation );
mIgnoreDataCalls = new JCheckBox( "Ignore Data Calls" );
mIgnoreDataCalls.setEnabled( false );
mIgnoreDataCalls.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{
setModified( true );
}
} );
add( mIgnoreDataCalls );
mTrafficChannelPoolSize = new JSlider( JSlider.HORIZONTAL, DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MINIMUM,
DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MAXIMUM, DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_DEFAULT );
mTrafficChannelPoolSize.setEnabled( false );
mTrafficChannelPoolSize.setMajorTickSpacing( 10 );
mTrafficChannelPoolSize.setMinorTickSpacing( 5 );
mTrafficChannelPoolSize.setPaintTicks( true );
mTrafficChannelPoolSize.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
mTrafficChannelPoolSizeLabel.setText( "Traffic Pool: " + mTrafficChannelPoolSize.getValue() );
setModified( true );
}
} );
mTrafficChannelPoolSizeLabel = new JLabel( "Traffic Pool: " + mTrafficChannelPoolSize.getValue() + " " );
add( mTrafficChannelPoolSizeLabel );
add( mTrafficChannelPoolSize );
}
@Override
public void save()
{
if( hasItem() && isModified() )
{
DecodeConfigP25Phase1 p25 = new DecodeConfigP25Phase1();
p25.setModulation( (Modulation)mComboModulation.getSelectedItem() );
p25.setIgnoreDataCalls( mIgnoreDataCalls.isSelected() );
p25.setTrafficChannelPoolSize( mTrafficChannelPoolSize.getValue() );
getItem().setDecodeConfiguration( p25 );
}
setModified( false );
}
@Override
public void validate( Editor<Channel> editor ) throws EditorValidationException
{
mLog.debug( "Validating editor:" + editor.getClass() );
/**
* Enforce CQPSK modulation uses a Tuner Source for I/Q sample data
*/
if( editor instanceof SourceConfigurationEditor &&
((Modulation)mComboModulation.getSelectedItem()) == Modulation.CQPSK )
{
SourceConfiguration config = ((SourceConfigurationEditor)editor).getSourceConfiguration();
if( config != null && !( config instanceof SourceConfigTuner ) )
{
throw new EditorValidationException( editor,
"<html><body width='175'><h3>LSM Simulcast</h3>"
+ "<p>P25 LSM Simulcast decoder can only be used with "
+ "a tuner source. Please change the Source to use a tuner"
+ " or change the P25 Decoder to C4FM modulation</p>" );
}
}
if( editor instanceof AuxDecodeConfigurationEditor )
{
AuxDecodeConfiguration config = ((AuxDecodeConfigurationEditor)editor).getConfiguration();
if( config != null && !config.getAuxDecoders().isEmpty() )
{
throw new EditorValidationException( editor,
"<html><body width='175'><h3>Auxilary Decoders</h3>"
+ "<p>The auxiliary decoders work with analog audio and are not "
+ "compatible with the P25 Decoder. Please uncheck any auxiliary "
+ "decoders that you have selected for this channel</p>" );
}
}
}
private void setControlsEnabled( boolean enabled )
{
if( mComboModulation.isEnabled() != enabled )
{
mComboModulation.setEnabled( enabled );
}
if( mTrafficChannelPoolSize.isEnabled() != enabled )
{
mTrafficChannelPoolSize.setEnabled( enabled );
}
if( mIgnoreDataCalls.isEnabled() != enabled )
{
mIgnoreDataCalls.setEnabled( enabled );
}
}
@Override
public void setItem( Channel item )
{
super.setItem( item );
if( hasItem() )
{
setControlsEnabled( true );
DecodeConfiguration config = getItem().getDecodeConfiguration();
if( config instanceof DecodeConfigP25Phase1 )
{
DecodeConfigP25Phase1 p25 = (DecodeConfigP25Phase1)config;
mComboModulation.setSelectedItem( p25.getModulation() );
mIgnoreDataCalls.setSelected( p25.getIgnoreDataCalls() );
mTrafficChannelPoolSize.setValue( p25.getTrafficChannelPoolSize() );
setModified( false );
}
else
{
mComboModulation.setSelectedItem( Modulation.C4FM );
mIgnoreDataCalls.setSelected( false );
mTrafficChannelPoolSize.setValue( DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_DEFAULT );
setModified( true );
}
}
else
{
setControlsEnabled( false );
setModified( false );
}
}
}

View File

@@ -0,0 +1,159 @@
/*******************************************************************************
* 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/>
******************************************************************************/
package module.decode.passport;
import gui.editor.Editor;
import gui.editor.EditorValidationException;
import gui.editor.ValidatingEditor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JCheckBox;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import module.decode.config.DecodeConfiguration;
import net.miginfocom.swing.MigLayout;
import controller.channel.Channel;
public class PassportDecoderEditor extends ValidatingEditor<Channel>
{
private static final long serialVersionUID = 1L;
private JCheckBox mAFC;
private JSlider mAFCMaximumCorrection;
public PassportDecoderEditor()
{
init();
}
private void init()
{
setLayout( new MigLayout( "insets 0 0 0 0,wrap 2", "[right][grow,fill]", "" ) );
mAFC = new JCheckBox( "AFC: 3000 Hz" );
mAFC.setEnabled( false );
mAFC.setToolTipText( "AFC automatically adjusts the center frequency of the channel to "
+ "correct/compensate for inaccuracies and frequency drift in the tuner" );
mAFC.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent arg0 )
{
setModified( true );
if( mAFC.isSelected() && !mAFCMaximumCorrection.isEnabled() )
{
mAFCMaximumCorrection.setEnabled( true );
}
else if( !mAFC.isSelected() && mAFCMaximumCorrection.isEnabled() )
{
mAFCMaximumCorrection.setEnabled( false );
}
}
} );
add( mAFC );
mAFCMaximumCorrection = new JSlider( 0, 7000, 3000 );
mAFCMaximumCorrection.setEnabled( false );
mAFCMaximumCorrection.setToolTipText( "Maximum AFC frequency correction (0 - 15kHz)" );
mAFCMaximumCorrection.setMajorTickSpacing( 2000 );
mAFCMaximumCorrection.setMinorTickSpacing( 1000 );
mAFCMaximumCorrection.setPaintTicks( true );
mAFCMaximumCorrection.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
mAFC.setText( "AFC: " + mAFCMaximumCorrection.getValue() + " Hz" );
setModified( true );
}
} );
add( mAFCMaximumCorrection );
}
@Override
public void validate( Editor<Channel> editor ) throws EditorValidationException
{
//No validation
}
@Override
public void save()
{
if( hasItem() && isModified() )
{
DecodeConfigPassport passport = new DecodeConfigPassport();
passport.setAFC( mAFC.isSelected() );
passport.setAFCMaximumCorrection( mAFCMaximumCorrection.getValue() );
getItem().setDecodeConfiguration( passport );
}
setModified( false );
}
private void setControlsEnabled( boolean enabled )
{
if( mAFC.isEnabled() != enabled )
{
mAFC.setEnabled( enabled );
}
}
@Override
public void setItem( Channel item )
{
super.setItem( item );
if( hasItem() )
{
setControlsEnabled( true );
DecodeConfiguration config = getItem().getDecodeConfiguration();
if( config instanceof DecodeConfigPassport )
{
DecodeConfigPassport passport = (DecodeConfigPassport)config;
mAFC.setSelected( passport.isAFCEnabled() );
mAFCMaximumCorrection.setValue( passport.getAFCMaximumCorrection() );
mAFCMaximumCorrection.setEnabled( passport.isAFCEnabled() );
setModified( false );
}
else
{
mAFC.setSelected( false );
mAFCMaximumCorrection.setValue( DecodeConfiguration.DEFAULT_AFC_MAX_CORRECTION );
mAFCMaximumCorrection.setEnabled( false );
setModified( true );
}
}
else
{
setControlsEnabled( false );
setModified( false );
}
}
}

View File

@@ -1,31 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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 module.decode.passport;
import module.decode.DecodeEditor;
import module.decode.config.DecodeConfiguration;
public class PassportEditor extends DecodeEditor
{
private static final long serialVersionUID = 1L;
public PassportEditor( DecodeConfiguration config )
{
super( config );
}
}

View File

@@ -1,59 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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 record;
import record.config.RecordConfiguration;
import controller.channel.Channel;
import controller.channel.ChannelConfigurationEditor;
import controller.channel.ConfigurationValidationException;
public class RecordEditor extends ChannelConfigurationEditor
{
private static final long serialVersionUID = 1L;
protected RecordConfiguration mConfig;
public RecordEditor( RecordConfiguration config )
{
mConfig = config;
}
public RecordConfiguration getConfig()
{
return mConfig;
}
@Override
public void save()
{
}
@Override
public void setConfiguration( Channel channel )
{
// TODO Auto-generated method stub
}
@Override
public void validateConfiguration() throws ConfigurationValidationException
{
// TODO Auto-generated method stub
}
}

View File

@@ -25,9 +25,9 @@ import java.awt.event.ActionListener;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import net.miginfocom.swing.MigLayout;
import source.config.SourceConfiguration;
import source.mixer.MixerSourceEditor;
import source.tuner.TunerSourceEditor;
import controller.channel.Channel;
@@ -44,13 +44,22 @@ public class SourceConfigurationEditor extends Editor<Channel>
public SourceConfigurationEditor( SourceManager sourceManager )
{
mMixerSourceEditor = new MixerSourceEditor( sourceManager );
mMixerSourceEditor.setSaveRequestListener( this );
mTunerSourceEditor = new TunerSourceEditor();
mTunerSourceEditor.setSaveRequestListener( this );
init();
}
public SourceConfiguration getSourceConfiguration()
{
return hasItem() ? getItem().getSourceConfiguration() : null;
}
private void init()
{
setLayout( new MigLayout( "fill,wrap 3", "[right][left][grow,fill]", "[][grow]" ) );
setLayout( new MigLayout( "wrap 2", "[][grow,fill]", "[align top][grow]" ) );
mComboSources = new JComboBox<SourceType>();
mComboSources.setModel( new DefaultComboBoxModel<SourceType>( SourceType.getTypes() ) );
@@ -76,7 +85,6 @@ public class SourceConfigurationEditor extends Editor<Channel>
}
});
add( new JLabel( "Source:" ) );
add( mComboSources );
mCurrentEditor = mTunerSourceEditor;
@@ -87,10 +95,16 @@ public class SourceConfigurationEditor extends Editor<Channel>
{
if( mCurrentEditor != editor )
{
//Set channel to null to force a save prompt as required
mCurrentEditor.setItem( null );
remove( mCurrentEditor );
mCurrentEditor = editor;
mCurrentEditor.setSaveRequestListener( this );
add( mCurrentEditor );
mCurrentEditor.setItem( getItem() );
revalidate();
}
}
@@ -98,18 +112,12 @@ public class SourceConfigurationEditor extends Editor<Channel>
@Override
public void save()
{
if( hasItem() && mCurrentEditor.isModified() )
if( hasItem() )
{
mCurrentEditor.save();
}
}
@Override
public boolean isModified()
{
return super.isModified() || mCurrentEditor.isModified();
}
/**
* Sets the channel configuration. Note: this method must be invoked from
* the swing event dispatch thread.
@@ -121,8 +129,9 @@ public class SourceConfigurationEditor extends Editor<Channel>
if( hasItem() )
{
mMixerSourceEditor.setItem( channel );
mTunerSourceEditor.setItem( channel );
mComboSources.setSelectedItem( getItem().getSourceConfiguration().getSourceType() );
repaint();
mCurrentEditor.setItem( channel );
}
}
}

View File

@@ -50,7 +50,7 @@ public class MixerSourceEditor extends Editor<Channel>
private void init()
{
setLayout( new MigLayout( "fill,wrap 4", "[right][grow,fill][right][grow,fill]", "[][grow]" ) );
setLayout( new MigLayout( "insets 0 0 0 0,wrap 4", "[right][grow,fill][right][grow,fill]", "" ) );
mComboMixers = new JComboBox<InputMixerConfiguration>();
InputMixerConfiguration[] inputMixers = mSourceManager.getMixerManager().getInputMixers();
@@ -68,6 +68,8 @@ public class MixerSourceEditor extends Editor<Channel>
mComboChannels.setModel( new DefaultComboBoxModel<MixerChannel>(
channels.toArray( new MixerChannel[ channels.size() ] ) ) );
repaint();
setModified( true );
}
} );
@@ -76,6 +78,17 @@ public class MixerSourceEditor extends Editor<Channel>
add( mComboMixers );
mComboChannels = new JComboBox<MixerChannel>();
InputMixerConfiguration selected = (InputMixerConfiguration)mComboMixers.getSelectedItem();
if( selected != null )
{
EnumSet<MixerChannel> channels = selected.getChannels();
mComboChannels.setModel( new DefaultComboBoxModel<MixerChannel>(
channels.toArray( new MixerChannel[ channels.size() ] ) ) );
}
mComboChannels.setEnabled( false );
mComboChannels.addActionListener( new ActionListener()
{
@@ -114,24 +127,33 @@ public class MixerSourceEditor extends Editor<Channel>
for( MixerChannel channel: inputMixer.getChannels() )
{
if( channel.getLabel().equalsIgnoreCase( mixer.getChannel().getLabel() ) )
if( channel.getLabel() != null && mixer.getChannel() != null )
{
mComboChannels.setSelectedItem( channel );
if( channel.getLabel().equalsIgnoreCase( mixer.getChannel().getLabel() ) )
{
mComboChannels.setSelectedItem( channel );
}
}
}
continue;
}
}
setModified( false );
}
else
{
setModified( true );
}
}
else
{
mComboMixers.setEnabled( false );
mComboChannels.setEnabled( false );
setModified( false );
}
setModified( false );
}
public void save()

View File

@@ -38,7 +38,7 @@ public class TunerSourceEditor extends Editor<Channel>
private void init()
{
setLayout( new MigLayout( "fill", "[left]", "[][grow]" ) );
setLayout( new MigLayout( "insets 0 0 0 0", "[left]", "" ) );
mFrequencyControl = new JFrequencyControl();
mFrequencyControl.setEnabled( false );
mFrequencyControl.addListener( new IFrequencyChangeProcessor()
@@ -73,18 +73,23 @@ public class TunerSourceEditor extends Editor<Channel>
{
SourceConfiguration config = getItem().getSourceConfiguration();
mFrequencyControl.setEnabled( true );
if( config instanceof SourceConfigTuner )
{
mFrequencyControl.setFrequency( ((SourceConfigTuner)config).getFrequency(), false );
setModified( false );
}
else
{
mFrequencyControl.setFrequency( 101000000, false );
setModified( true );
}
mFrequencyControl.setEnabled( true );
}
else
{
mFrequencyControl.setEnabled( false );
setModified( false );
}
setModified( false );
}
}

View File

@@ -100,8 +100,7 @@ public class OverlayPanel extends JPanel
// private List<Channel> mChannels = new ArrayList<Channel>();
//
//Currently visible/displayable channels
private CopyOnWriteArrayList<Channel> mVisibleChannels =
new CopyOnWriteArrayList<Channel>();
private CopyOnWriteArrayList<Channel> mVisibleChannels = new CopyOnWriteArrayList<Channel>();
private ChannelDisplay mChannelDisplay = ChannelDisplay.ALL;
//Defines the offset at the bottom of the spectral display to account for
@@ -597,29 +596,24 @@ public class OverlayPanel extends JPanel
width );
//Draw the decoder label
drawLabel( graphics,
channel.getDecodeConfiguration().getDecoderType()
.getShortDisplayString(),
this.getFont(),
xAxis,
yAxis,
width );
}
long frequency = tunerChannel.getFrequency();
double frequencyAxis = getAxisFromFrequency( frequency );
drawChannelCenterLine( graphics, frequencyAxis );
/* Draw Automatic Frequency Control line */
int correction = channel.getChannelFrequencyCorrection();
if( correction != 0 )
{
long error = frequency + correction;
drawLabel( graphics, channel.getDecodeConfiguration().getDecoderType().getShortDisplayString(),
this.getFont(), xAxis, yAxis, width );
long frequency = tunerChannel.getFrequency();
drawAFC( graphics, frequencyAxis, getAxisFromFrequency( error ) );
double frequencyAxis = getAxisFromFrequency( frequency );
drawChannelCenterLine( graphics, frequencyAxis );
/* Draw Automatic Frequency Control line */
int correction = channel.getChannelFrequencyCorrection();
if( correction != 0 )
{
long error = frequency + correction;
drawAFC( graphics, frequencyAxis, getAxisFromFrequency( error ) );
}
}
}
}
@@ -725,6 +719,21 @@ public class OverlayPanel extends JPanel
mVisibleChannels.remove( channel );
}
break;
case NOTIFICATION_CONFIGURATION_CHANGE:
if( mVisibleChannels.contains( channel ) &&
!channel.isWithin( getMinFrequency(), getMaxFrequency() ) )
{
mVisibleChannels.remove( channel );
}
if( !mVisibleChannels.contains( channel ) &&
channel.isWithin( getMinFrequency(), getMaxFrequency() ) )
{
mVisibleChannels.add( channel );
}
break;
default:
break;
}
repaint();