diff --git a/src/main/java/io/github/dsheirer/gui/playlist/channel/DMRConfigurationEditor.java b/src/main/java/io/github/dsheirer/gui/playlist/channel/DMRConfigurationEditor.java index 4237db6c..303b0c5b 100644 --- a/src/main/java/io/github/dsheirer/gui/playlist/channel/DMRConfigurationEditor.java +++ b/src/main/java/io/github/dsheirer/gui/playlist/channel/DMRConfigurationEditor.java @@ -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 mTimeslotFrequencyTable; private IntegerTextField mLogicalChannelNumberField; private FrequencyField mDownlinkFrequencyField; -// private FrequencyField mUplinkFrequencyField; private Button mAddTimeslotFrequencyButton; private Button mDeleteTimeslotFrequencyButton; private Spinner 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, - ObservableValue> - { - private SimpleStringProperty mFrequency = new SimpleStringProperty(); - private boolean mIsDownlink; - - public FrequencyCellValueFactory(boolean isDownlink) - { - mIsDownlink = isDownlink; - } - - @Override - public ObservableValue call(TableColumn.CellDataFeatures 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 - { - private StringProperty mStringProperty = new SimpleStringProperty(); - - public DownlinkPropertyValueFactory() - { - super("downlinkFrequency"); - } - - @Override - public ObservableValue call(TableColumn.CellDataFeatures param) - { - if(param.getValue() != null) - { - mStringProperty.set(String.valueOf(param.getValue().getDownlinkFrequency() / 1E6)); - } - else - { - mStringProperty.setValue(null); - } - - return mStringProperty; - } - } - } diff --git a/src/main/java/io/github/dsheirer/gui/playlist/channel/NXDNConfigurationEditor.java b/src/main/java/io/github/dsheirer/gui/playlist/channel/NXDNConfigurationEditor.java index f735e180..a362d22d 100644 --- a/src/main/java/io/github/dsheirer/gui/playlist/channel/NXDNConfigurationEditor.java +++ b/src/main/java/io/github/dsheirer/gui/playlist/channel/NXDNConfigurationEditor.java @@ -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 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); } diff --git a/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P1ConfigurationEditor.java b/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P1ConfigurationEditor.java index c8e97e86..1b3e79e1 100644 --- a/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P1ConfigurationEditor.java +++ b/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P1ConfigurationEditor.java @@ -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); } diff --git a/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P2ConfigurationEditor.java b/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P2ConfigurationEditor.java index 1201b461..51a516d3 100644 --- a/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P2ConfigurationEditor.java +++ b/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P2ConfigurationEditor.java @@ -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 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); } diff --git a/src/main/java/io/github/dsheirer/module/decode/config/DecodeConfigJMBE.java b/src/main/java/io/github/dsheirer/module/decode/config/DecodeConfigJMBE.java index edacb468..aeefeffd 100644 --- a/src/main/java/io/github/dsheirer/module/decode/config/DecodeConfigJMBE.java +++ b/src/main/java/io/github/dsheirer/module/decode/config/DecodeConfigJMBE.java @@ -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; diff --git a/src/main/resources/sdrtrunk_dark.css b/src/main/resources/sdrtrunk_dark.css index 2172bb05..6a00b17e 100644 --- a/src/main/resources/sdrtrunk_dark.css +++ b/src/main/resources/sdrtrunk_dark.css @@ -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