#2484 JMBE version 2 control in channel protocol editors. (#2485)

Co-authored-by: denny <dennis.sheirer@gmail.com>
This commit is contained in:
Denny Sheirer
2026-10-10 06:22:10 -04:00
committed by GitHub
parent c05328cd1e
commit 728a83a82d
6 changed files with 346 additions and 85 deletions

View File

@@ -52,6 +52,7 @@ import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.Spinner;
import javafx.scene.control.SpinnerValueFactory;
import javafx.scene.control.TableColumn;
@@ -61,6 +62,7 @@ import javafx.scene.control.Tooltip;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.util.Callback;
import org.controlsfx.control.ToggleSwitch;
@@ -87,10 +89,12 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
private TableView<TimeslotFrequency> mTimeslotFrequencyTable;
private IntegerTextField mLogicalChannelNumberField;
private FrequencyField mDownlinkFrequencyField;
// private FrequencyField mUplinkFrequencyField;
private Button mAddTimeslotFrequencyButton;
private Button mDeleteTimeslotFrequencyButton;
private Spinner<Integer> mChannelRotationDelaySpinner;
private ToggleSwitch mJmbeAGCButton;
private Slider mJmbeToneGainSlider;
private Slider mJmbeNoiseGainSlider;
/**
* Constructs an instance
@@ -204,6 +208,24 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
GridPane.setConstraints(editorBox, 0, row, 4, 1);
gridPane.getChildren().add(editorBox);
row++;
Label jmbeLabel = new Label("AMBE Audio");
GridPane.setHalignment(jmbeLabel, HPos.LEFT);
gridPane.add(jmbeLabel, 0, row);
GridPane.setHalignment(getJmbeAGCButton(), HPos.LEFT);
gridPane.add(getJmbeAGCButton(), 1, row);
gridPane.add(new Label("Tone Volume:"), 2, row);
GridPane.setHgrow(getJmbeToneGainSlider(), Priority.ALWAYS);
gridPane.add(getJmbeToneGainSlider(), 3, row);
gridPane.add(new Label("Comfort Noise Volume:"), 4, row);
GridPane.setHgrow(getJmbeNoiseGainSlider(), Priority.ALWAYS);
gridPane.add(getJmbeNoiseGainSlider(), 5, row);
mDecoderPane.setContent(gridPane);
}
@@ -554,6 +576,45 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
return mTrafficChannelPoolSizeSpinner;
}
public ToggleSwitch getJmbeAGCButton()
{
if(mJmbeAGCButton == null)
{
mJmbeAGCButton = new ToggleSwitch("AGC:");
mJmbeAGCButton.setTooltip(new Tooltip("Automatic Gain Control to automatically adjust call audio volume"));
mJmbeAGCButton.setDisable(true);
mJmbeAGCButton.selectedProperty().addListener((o, old, n) -> modifiedProperty().set(true));
}
return mJmbeAGCButton;
}
public Slider getJmbeToneGainSlider()
{
if(mJmbeToneGainSlider == null)
{
mJmbeToneGainSlider = new Slider(0.0, 1.0, 1.0);
mJmbeToneGainSlider.setTooltip(new Tooltip("Tone generation volume: 0.0 (no tones) to 1.0 (default)"));
mJmbeToneGainSlider.setDisable(true);
mJmbeToneGainSlider.valueProperty().addListener((observable, oldValue, newValue) -> modifiedProperty().set(true));
}
return mJmbeToneGainSlider;
}
public Slider getJmbeNoiseGainSlider()
{
if(mJmbeNoiseGainSlider == null)
{
mJmbeNoiseGainSlider = new Slider(0.0, 1.0, 1.0);
mJmbeNoiseGainSlider.setTooltip(new Tooltip("Comfort noise insertion volume: 0.0 (no noise) to 1.0 (default)"));
mJmbeNoiseGainSlider.setDisable(true);
mJmbeNoiseGainSlider.valueProperty().addListener((observable, oldValue, newValue) -> modifiedProperty().set(true));
}
return mJmbeNoiseGainSlider;
}
/**
* Channel rotation monitor delay value. This dictates how long the decoder will remain on each frequency before
* rotating to the next frequency in the list
@@ -600,21 +661,23 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
@Override
protected void setDecoderConfiguration(DecodeConfiguration config)
{
getIgnoreCRCChecksumsButton().setDisable(config == null);
getIgnoreDataCallsButton().setDisable(config == null);
getUseCompressedTalkgroupsToggle().setDisable(config == null);
getTrafficChannelPoolSizeSpinner().setDisable(config == null);
boolean disable = config == null;
getIgnoreCRCChecksumsButton().setDisable(disable);
getIgnoreDataCallsButton().setDisable(disable);
getUseCompressedTalkgroupsToggle().setDisable(disable);
getTrafficChannelPoolSizeSpinner().setDisable(disable);
getTimeslotTable().getItems().clear();
getTimeslotTable().setDisable(config == null);
getAddTimeslotFrequencyButton().setDisable(config == null);
getTimeslotTable().setDisable(disable);
getAddTimeslotFrequencyButton().setDisable(disable);
getDeleteTimeslotFrequencyButton().setDisable(true);
getLogicalChannelNumberField().set(0);
getLogicalChannelNumberField().setDisable(true);
getDownlinkFrequencyField().set(0);
getDownlinkFrequencyField().setDisable(true);
// getUplinkFrequencyField().set(0);
// getUplinkFrequencyField().setDisable(true);
getChannelRotationDelaySpinner().setDisable(config == null);
getChannelRotationDelaySpinner().setDisable(disable);
getJmbeAGCButton().setDisable(disable);
getJmbeNoiseGainSlider().setDisable(disable);
getJmbeToneGainSlider().setDisable(disable);
if(config instanceof DecodeConfigDMR)
{
@@ -629,6 +692,10 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
{
getTimeslotTable().getItems().add(timeslotFrequency.copy());
}
getJmbeAGCButton().setSelected(decodeConfig.isAGC());
getJmbeNoiseGainSlider().setValue(decodeConfig.getNoiseGain());
getJmbeToneGainSlider().setValue(decodeConfig.getToneGain());
}
else
{
@@ -637,6 +704,9 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
getUseCompressedTalkgroupsToggle().setSelected(false);
getTrafficChannelPoolSizeSpinner().getValueFactory().setValue(0);
getChannelRotationDelaySpinner().getValueFactory().setValue(200);
getJmbeAGCButton().setSelected(false);
getJmbeNoiseGainSlider().setValue(0);
getJmbeToneGainSlider().setValue(0);
}
}
@@ -659,6 +729,9 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
config.setTrafficChannelPoolSize(getTrafficChannelPoolSizeSpinner().getValue());
config.setUseCompressedTalkgroups(getUseCompressedTalkgroupsToggle().isSelected());
config.setTimeslotMap(new ArrayList<>(getTimeslotTable().getItems()));
config.setAGC(getJmbeAGCButton().selectedProperty().getValue());
config.setNoiseGain((float)getJmbeNoiseGainSlider().getValue());
config.setToneGain((float)getJmbeToneGainSlider().getValue());
getItem().setDecodeConfiguration(config);
}
@@ -723,61 +796,4 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
SourceConfiguration sourceConfiguration = getSourceConfigurationEditor().getSourceConfiguration();
getItem().setSourceConfiguration(sourceConfiguration);
}
/**
* Channel tuner channel source frequencies value factory
*/
public class FrequencyCellValueFactory implements Callback<TableColumn.CellDataFeatures<TimeslotFrequency, String>,
ObservableValue<String>>
{
private SimpleStringProperty mFrequency = new SimpleStringProperty();
private boolean mIsDownlink;
public FrequencyCellValueFactory(boolean isDownlink)
{
mIsDownlink = isDownlink;
}
@Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<TimeslotFrequency, String> param)
{
if(param.getValue() != null)
{
long frequency = (mIsDownlink ? param.getValue().getDownlinkFrequency() : param.getValue().getUplinkFrequency());
mFrequency.set(String.valueOf(frequency / 1E6));
}
else
{
mFrequency.set(null);
}
return mFrequency;
}
}
public class DownlinkPropertyValueFactory extends PropertyValueFactory<TimeslotFrequency,String>
{
private StringProperty mStringProperty = new SimpleStringProperty();
public DownlinkPropertyValueFactory()
{
super("downlinkFrequency");
}
@Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<TimeslotFrequency,String> param)
{
if(param.getValue() != null)
{
mStringProperty.set(String.valueOf(param.getValue().getDownlinkFrequency() / 1E6));
}
else
{
mStringProperty.setValue(null);
}
return mStringProperty;
}
}
}

View File

@@ -54,6 +54,7 @@ import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.Spinner;
import javafx.scene.control.SpinnerValueFactory;
import javafx.scene.control.TableColumn;
@@ -63,6 +64,7 @@ import javafx.scene.control.ToggleButton;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import org.controlsfx.control.SegmentedButton;
import org.controlsfx.control.ToggleSwitch;
@@ -93,6 +95,9 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor
private ComboBox<Encoding> mEncodingComboBox;
private ToggleSwitch mIgnoreDataCallsToggle;
private ToggleSwitch mIgnoreEncryptedCallsToggle;
private ToggleSwitch mJmbeAGCButton;
private Slider mJmbeToneGainSlider;
private Slider mJmbeNoiseGainSlider;
/**
* Constructs an instance
@@ -209,6 +214,24 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor
GridPane.setConstraints(editorBox, 0, row, 4, 1);
gridPane.getChildren().add(editorBox);
row++;
Label jmbeLabel = new Label("AMBE Audio");
GridPane.setHalignment(jmbeLabel, HPos.LEFT);
gridPane.add(jmbeLabel, 0, row);
GridPane.setHalignment(getJmbeAGCButton(), HPos.LEFT);
gridPane.add(getJmbeAGCButton(), 1, row);
gridPane.add(new Label("Tone Volume:"), 2, row);
GridPane.setHgrow(getJmbeToneGainSlider(), Priority.ALWAYS);
gridPane.add(getJmbeToneGainSlider(), 3, row);
gridPane.add(new Label("Comfort Noise Volume:"), 4, row);
GridPane.setHgrow(getJmbeNoiseGainSlider(), Priority.ALWAYS);
gridPane.add(getJmbeNoiseGainSlider(), 5, row);
mDecoderPane.setContent(gridPane);
}
@@ -533,6 +556,45 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor
return mIgnoreEncryptedCallsToggle;
}
public ToggleSwitch getJmbeAGCButton()
{
if(mJmbeAGCButton == null)
{
mJmbeAGCButton = new ToggleSwitch("AGC:");
mJmbeAGCButton.setTooltip(new Tooltip("Automatic Gain Control to automatically adjust call audio volume"));
mJmbeAGCButton.setDisable(true);
mJmbeAGCButton.selectedProperty().addListener((o, old, n) -> modifiedProperty().set(true));
}
return mJmbeAGCButton;
}
public Slider getJmbeToneGainSlider()
{
if(mJmbeToneGainSlider == null)
{
mJmbeToneGainSlider = new Slider(0.0, 1.0, 1.0);
mJmbeToneGainSlider.setTooltip(new Tooltip("Tone generation volume: 0.0 (no tones) to 1.0 (default)"));
mJmbeToneGainSlider.setDisable(true);
mJmbeToneGainSlider.valueProperty().addListener((observable, oldValue, newValue) -> modifiedProperty().set(true));
}
return mJmbeToneGainSlider;
}
public Slider getJmbeNoiseGainSlider()
{
if(mJmbeNoiseGainSlider == null)
{
mJmbeNoiseGainSlider = new Slider(0.0, 1.0, 1.0);
mJmbeNoiseGainSlider.setTooltip(new Tooltip("Comfort noise insertion volume: 0.0 (no noise) to 1.0 (default)"));
mJmbeNoiseGainSlider.setDisable(true);
mJmbeNoiseGainSlider.valueProperty().addListener((observable, oldValue, newValue) -> modifiedProperty().set(true));
}
return mJmbeNoiseGainSlider;
}
/**
* Channel rotation monitor delay value. This dictates how long the decoder will remain on each frequency before
* rotating to the next frequency in the list
@@ -579,19 +641,23 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor
@Override
protected void setDecoderConfiguration(DecodeConfiguration config)
{
getTransmissionModeButton().setDisable(config == null);
getTrafficChannelPoolSizeSpinner().setDisable(config == null);
boolean disable = config == null;
getTransmissionModeButton().setDisable(disable);
getTrafficChannelPoolSizeSpinner().setDisable(disable);
getChannelMapTable().getItems().clear();
getChannelMapTable().setDisable(config == null);
getAddTimeslotFrequencyButton().setDisable(config == null);
getChannelMapTable().setDisable(disable);
getAddTimeslotFrequencyButton().setDisable(disable);
getDeleteButton().setDisable(true);
getChannelField().set(0);
getChannelField().setDisable(true);
getDownlinkFrequencyField().set(0);
getDownlinkFrequencyField().setDisable(true);
getChannelRotationDelaySpinner().setDisable(config == null);
getIgnoreDataCallsToggle().setDisable(config == null);
getIgnoreEncryptedCallsToggle().setDisable(config == null);
getChannelRotationDelaySpinner().setDisable(disable);
getIgnoreDataCallsToggle().setDisable(disable);
getIgnoreEncryptedCallsToggle().setDisable(disable);
getJmbeAGCButton().setDisable(disable);
getJmbeNoiseGainSlider().setDisable(disable);
getJmbeToneGainSlider().setDisable(disable);
if(config instanceof DecodeConfigNXDN configNXDN)
{
@@ -612,6 +678,9 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor
getIgnoreDataCallsToggle().setSelected(configNXDN.isIgnoreDataCalls());
getIgnoreEncryptedCallsToggle().setSelected(configNXDN.isIgnoreEncryptedCalls());
getJmbeAGCButton().setSelected(configNXDN.isAGC());
getJmbeNoiseGainSlider().setValue(configNXDN.getNoiseGain());
getJmbeToneGainSlider().setValue(configNXDN.getToneGain());
}
else
{
@@ -619,6 +688,9 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor
getChannelRotationDelaySpinner().getValueFactory().setValue(200);
getIgnoreDataCallsToggle().setSelected(false);
getIgnoreEncryptedCallsToggle().setSelected(false);
getJmbeAGCButton().setSelected(false);
getJmbeNoiseGainSlider().setValue(0);
getJmbeToneGainSlider().setValue(0);
}
}
@@ -651,6 +723,9 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor
config.setChannelMap(channelFrequencies);
config.setIgnoreDataCalls(getIgnoreDataCallsToggle().isSelected());
config.setIgnoreEncryptedCalls(getIgnoreEncryptedCallsToggle().isSelected());
config.setAGC(getJmbeAGCButton().selectedProperty().getValue());
config.setNoiseGain((float)getJmbeNoiseGainSlider().getValue());
config.setToneGain((float)getJmbeToneGainSlider().getValue());
getItem().setDecodeConfiguration(config);
}

View File

@@ -43,6 +43,7 @@ import javafx.beans.value.ObservableValue;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.Spinner;
import javafx.scene.control.SpinnerValueFactory;
import javafx.scene.control.TitledPane;
@@ -50,6 +51,7 @@ import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import org.controlsfx.control.SegmentedButton;
import org.controlsfx.control.ToggleSwitch;
@@ -74,6 +76,9 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor
private SegmentedButton mModulationSegmentedButton;
private ToggleButton mC4FMToggleButton;
private ToggleButton mLSMToggleButton;
private ToggleSwitch mJmbeAGCButton;
private Slider mJmbeToneGainSlider;
private Slider mJmbeNoiseGainSlider;
/**
* Constructs an instance
@@ -121,34 +126,57 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor
gridPane.setHgap(10);
gridPane.setVgap(10);
int row = 0;
Label modulationLabel = new Label("Modulation");
GridPane.setHalignment(modulationLabel, HPos.RIGHT);
GridPane.setConstraints(modulationLabel, 0, 0);
GridPane.setConstraints(modulationLabel, 0, row);
gridPane.getChildren().add(modulationLabel);
GridPane.setConstraints(getModulationSegmentedButton(), 1, 0);
GridPane.setConstraints(getModulationSegmentedButton(), 1, row);
gridPane.getChildren().addAll(getModulationSegmentedButton());
Label poolSizeLabel = new Label("Max Traffic Channels");
GridPane.setHalignment(poolSizeLabel, HPos.RIGHT);
GridPane.setConstraints(poolSizeLabel, 2, 0);
GridPane.setConstraints(poolSizeLabel, 2, row);
gridPane.getChildren().add(poolSizeLabel);
GridPane.setConstraints(getTrafficChannelPoolSizeSpinner(), 3, 0);
GridPane.setConstraints(getTrafficChannelPoolSizeSpinner(), 3, row);
gridPane.getChildren().add(getTrafficChannelPoolSizeSpinner());
GridPane.setConstraints(getIgnoreDataCallsButton(), 4, 0);
GridPane.setConstraints(getIgnoreDataCallsButton(), 4, row);
gridPane.getChildren().add(getIgnoreDataCallsButton());
Label directionLabel = new Label("Ignore Data Calls");
GridPane.setHalignment(directionLabel, HPos.LEFT);
GridPane.setConstraints(directionLabel, 5, 0);
GridPane.setConstraints(directionLabel, 5, row);
gridPane.getChildren().add(directionLabel);
row++;
Label modulationHelpLabel = new Label("C4FM: repeaters and non-simulcast trunked systems. LSM: simulcast trunked systems.");
GridPane.setConstraints(modulationHelpLabel, 0, 1, 6, 1);
GridPane.setConstraints(modulationHelpLabel, 0, row, 6, 1);
gridPane.getChildren().add(modulationHelpLabel);
row++;
Label jmbeLabel = new Label("AMBE/IMBE Audio");
GridPane.setHalignment(jmbeLabel, HPos.LEFT);
gridPane.add(jmbeLabel, 0, row);
GridPane.setHalignment(getJmbeAGCButton(), HPos.LEFT);
gridPane.add(getJmbeAGCButton(), 1, row);
gridPane.add(new Label("Tone Volume:"), 2, row);
GridPane.setHgrow(getJmbeToneGainSlider(), Priority.ALWAYS);
gridPane.add(getJmbeToneGainSlider(), 3, row);
gridPane.add(new Label("Comfort Noise Volume:"), 4, row);
GridPane.setHgrow(getJmbeNoiseGainSlider(), Priority.ALWAYS);
gridPane.add(getJmbeNoiseGainSlider(), 5, row);
mDecoderPane.setContent(gridPane);
}
@@ -250,6 +278,45 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor
return mModulationSegmentedButton;
}
public ToggleSwitch getJmbeAGCButton()
{
if(mJmbeAGCButton == null)
{
mJmbeAGCButton = new ToggleSwitch("AGC:");
mJmbeAGCButton.setTooltip(new Tooltip("Automatic Gain Control to automatically adjust call audio volume"));
mJmbeAGCButton.setDisable(true);
mJmbeAGCButton.selectedProperty().addListener((o, old, n) -> modifiedProperty().set(true));
}
return mJmbeAGCButton;
}
public Slider getJmbeToneGainSlider()
{
if(mJmbeToneGainSlider == null)
{
mJmbeToneGainSlider = new Slider(0.0, 1.0, 1.0);
mJmbeToneGainSlider.setTooltip(new Tooltip("Tone generation volume: 0.0 (no tones) to 1.0 (default). Note: Phase 2 AMBE only"));
mJmbeToneGainSlider.setDisable(true);
mJmbeToneGainSlider.valueProperty().addListener((observable, oldValue, newValue) -> modifiedProperty().set(true));
}
return mJmbeToneGainSlider;
}
public Slider getJmbeNoiseGainSlider()
{
if(mJmbeNoiseGainSlider == null)
{
mJmbeNoiseGainSlider = new Slider(0.0, 1.0, 1.0);
mJmbeNoiseGainSlider.setTooltip(new Tooltip("Comfort noise insertion volume: 0.0 (no noise) to 1.0 (default)"));
mJmbeNoiseGainSlider.setDisable(true);
mJmbeNoiseGainSlider.valueProperty().addListener((observable, oldValue, newValue) -> modifiedProperty().set(true));
}
return mJmbeNoiseGainSlider;
}
private ToggleButton getC4FMToggleButton()
{
if(mC4FMToggleButton == null)
@@ -327,9 +394,8 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor
getIgnoreDataCallsButton().setDisable(config == null);
getTrafficChannelPoolSizeSpinner().setDisable(config == null);
if(config instanceof DecodeConfigP25Phase1)
if(config instanceof DecodeConfigP25Phase1 decodeConfig)
{
DecodeConfigP25Phase1 decodeConfig = (DecodeConfigP25Phase1)config;
getIgnoreDataCallsButton().setSelected(decodeConfig.getIgnoreDataCalls());
getTrafficChannelPoolSizeSpinner().getValueFactory().setValue(decodeConfig.getTrafficChannelPoolSize());
if(decodeConfig.getModulation() == Modulation.C4FM)
@@ -342,11 +408,24 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor
getC4FMToggleButton().setSelected(false);
getLSMToggleButton().setSelected(true);
}
getJmbeAGCButton().setDisable(false);
getJmbeNoiseGainSlider().setDisable(false);
getJmbeToneGainSlider().setDisable(false);
getJmbeAGCButton().setSelected(decodeConfig.isAGC());
getJmbeNoiseGainSlider().setValue(decodeConfig.getNoiseGain());
getJmbeToneGainSlider().setValue(decodeConfig.getToneGain());
}
else
{
getIgnoreDataCallsButton().setSelected(false);
getTrafficChannelPoolSizeSpinner().getValueFactory().setValue(0);
getJmbeAGCButton().setDisable(true);
getJmbeNoiseGainSlider().setDisable(true);
getJmbeToneGainSlider().setDisable(true);
getJmbeAGCButton().setSelected(false);
getJmbeNoiseGainSlider().setValue(0);
getJmbeToneGainSlider().setValue(0);
}
}
@@ -367,6 +446,9 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor
config.setIgnoreDataCalls(getIgnoreDataCallsButton().isSelected());
config.setTrafficChannelPoolSize(getTrafficChannelPoolSizeSpinner().getValue());
config.setModulation(getC4FMToggleButton().isSelected() ? Modulation.C4FM : Modulation.CQPSK);
config.setAGC(getJmbeAGCButton().selectedProperty().getValue());
config.setNoiseGain((float)getJmbeNoiseGainSlider().getValue());
config.setToneGain((float)getJmbeToneGainSlider().getValue());
getItem().setDecodeConfiguration(config);
}

View File

@@ -42,11 +42,13 @@ import java.util.List;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.Spinner;
import javafx.scene.control.SpinnerValueFactory;
import javafx.scene.control.TitledPane;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import org.controlsfx.control.ToggleSwitch;
import org.slf4j.Logger;
@@ -70,6 +72,9 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
private IntegerTextField mNacTextField;
private ToggleSwitch mIgnoreDataCallsButton;
private Spinner<Integer> mTrafficChannelPoolSizeSpinner;
private ToggleSwitch mJmbeAGCButton;
private Slider mJmbeToneGainSlider;
private Slider mJmbeNoiseGainSlider;
/**
* Constructs an instance
@@ -164,6 +169,24 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
GridPane.setConstraints(noteLabel, 1, ++row, 6, 1);
gridPane.getChildren().add(noteLabel);
row++;
Label jmbeLabel = new Label("AMBE Audio");
GridPane.setHalignment(jmbeLabel, HPos.LEFT);
gridPane.add(jmbeLabel, 0, row);
GridPane.setHalignment(getJmbeAGCButton(), HPos.LEFT);
gridPane.add(getJmbeAGCButton(), 1, row);
gridPane.add(new Label("Tone Volume:"), 2, row);
GridPane.setHgrow(getJmbeToneGainSlider(), Priority.ALWAYS);
gridPane.add(getJmbeToneGainSlider(), 3, row);
gridPane.add(new Label("Comfort Noise Volume:"), 4, row);
GridPane.setHgrow(getJmbeNoiseGainSlider(), Priority.ALWAYS);
gridPane.add(getJmbeNoiseGainSlider(), 5, row);
mDecoderPane.setContent(gridPane);
}
@@ -171,6 +194,45 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
return mDecoderPane;
}
public ToggleSwitch getJmbeAGCButton()
{
if(mJmbeAGCButton == null)
{
mJmbeAGCButton = new ToggleSwitch("AGC:");
mJmbeAGCButton.setTooltip(new Tooltip("Automatic Gain Control to automatically adjust call audio volume"));
mJmbeAGCButton.setDisable(true);
mJmbeAGCButton.selectedProperty().addListener((o, old, n) -> modifiedProperty().set(true));
}
return mJmbeAGCButton;
}
public Slider getJmbeToneGainSlider()
{
if(mJmbeToneGainSlider == null)
{
mJmbeToneGainSlider = new Slider(0.0, 1.0, 1.0);
mJmbeToneGainSlider.setTooltip(new Tooltip("Tone generation volume: 0.0 (no tones) to 1.0 (default)"));
mJmbeToneGainSlider.setDisable(true);
mJmbeToneGainSlider.valueProperty().addListener((observable, oldValue, newValue) -> modifiedProperty().set(true));
}
return mJmbeToneGainSlider;
}
public Slider getJmbeNoiseGainSlider()
{
if(mJmbeNoiseGainSlider == null)
{
mJmbeNoiseGainSlider = new Slider(0.0, 1.0, 1.0);
mJmbeNoiseGainSlider.setTooltip(new Tooltip("Comfort noise insertion volume: 0.0 (no noise) to 1.0 (default)"));
mJmbeNoiseGainSlider.setDisable(true);
mJmbeNoiseGainSlider.valueProperty().addListener((observable, oldValue, newValue) -> modifiedProperty().set(true));
}
return mJmbeNoiseGainSlider;
}
private TitledPane getEventLogPane()
{
if(mEventLogPane == null)
@@ -327,6 +389,9 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
getWacnTextField().setDisable(false);
getSystemTextField().setDisable(false);
getNacTextField().setDisable(false);
getJmbeAGCButton().setDisable(false);
getJmbeNoiseGainSlider().setDisable(false);
getJmbeToneGainSlider().setDisable(false);
ScrambleParameters scrambleParameters = decodeConfig.getScrambleParameters();
@@ -347,6 +412,9 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
getIgnoreDataCallsButton().setSelected(decodeConfig.getIgnoreDataCalls());
getTrafficChannelPoolSizeSpinner().setDisable(false);
getTrafficChannelPoolSizeSpinner().getValueFactory().setValue(decodeConfig.getTrafficChannelPoolSize());
getJmbeAGCButton().setSelected(decodeConfig.isAGC());
getJmbeNoiseGainSlider().setValue(decodeConfig.getNoiseGain());
getJmbeToneGainSlider().setValue(decodeConfig.getToneGain());
}
else
{
@@ -358,6 +426,12 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
getNacTextField().setDisable(true);
getIgnoreDataCallsButton().setDisable(true);
getTrafficChannelPoolSizeSpinner().setDisable(true);
getJmbeAGCButton().setDisable(true);
getJmbeNoiseGainSlider().setDisable(true);
getJmbeToneGainSlider().setDisable(true);
getJmbeAGCButton().setSelected(false);
getJmbeNoiseGainSlider().setValue(0);
getJmbeToneGainSlider().setValue(0);
}
}
@@ -382,7 +456,9 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
config.setScrambleParameters(new ScrambleParameters(wacn, system, nac));
config.setIgnoreDataCalls(getIgnoreDataCallsButton().isSelected());
config.setTrafficChannelPoolSize(getTrafficChannelPoolSizeSpinner().getValue());
config.setAGC(getJmbeAGCButton().selectedProperty().getValue());
config.setNoiseGain((float)getJmbeNoiseGainSlider().getValue());
config.setToneGain((float)getJmbeToneGainSlider().getValue());
getItem().setDecodeConfiguration(config);
}

View File

@@ -4,7 +4,7 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
public abstract class DecodeConfigJMBE extends DecodeConfiguration
{
private boolean mAGC;
private boolean mAGC = true;
private float mToneGain = 1.0f;
private float mNoiseGain = 1.0f;

View File

@@ -53,6 +53,18 @@
{
-fx-background-color: #3c3f41, #4a4d4f, #3c3f41, #3c3f41;
-fx-text-fill: #ececec;
-fx-thumb-color: #ececec;
}
.slider .thumb
{
-fx-base: #ececec;
-fx-background: #ececec;
}
.slider .track
{
-fx-background: #888888;
}
.button:hover, .toggle-button:hover, .menu-button:hover