diff --git a/src/main/java/io/github/dsheirer/settings/SettingsManager.java b/src/main/java/io/github/dsheirer/settings/SettingsManager.java index c8f26a5c..fe9ae675 100644 --- a/src/main/java/io/github/dsheirer/settings/SettingsManager.java +++ b/src/main/java/io/github/dsheirer/settings/SettingsManager.java @@ -18,6 +18,7 @@ */ package io.github.dsheirer.settings; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule; @@ -272,7 +273,8 @@ public class SettingsManager implements Listener JacksonXmlModule xmlModule = new JacksonXmlModule(); xmlModule.setDefaultUseWrapper(false); - ObjectMapper objectMapper = new XmlMapper(xmlModule); + ObjectMapper objectMapper = new XmlMapper(xmlModule) + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); try(InputStream in = Files.newInputStream(settingsPath)) { diff --git a/src/main/java/io/github/dsheirer/source/tuner/TunerFactory.java b/src/main/java/io/github/dsheirer/source/tuner/TunerFactory.java index 865ea53b..c4cfa2da 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/TunerFactory.java +++ b/src/main/java/io/github/dsheirer/source/tuner/TunerFactory.java @@ -19,21 +19,41 @@ package io.github.dsheirer.source.tuner; +import io.github.dsheirer.preference.UserPreferences; import io.github.dsheirer.preference.source.ChannelizerType; import io.github.dsheirer.source.SourceException; import io.github.dsheirer.source.mixer.MixerManager; import io.github.dsheirer.source.tuner.airspy.AirspyTuner; +import io.github.dsheirer.source.tuner.airspy.AirspyTunerConfiguration; import io.github.dsheirer.source.tuner.airspy.AirspyTunerController; +import io.github.dsheirer.source.tuner.airspy.AirspyTunerEditor; +import io.github.dsheirer.source.tuner.configuration.TunerConfiguration; import io.github.dsheirer.source.tuner.fcd.FCDTuner; +import io.github.dsheirer.source.tuner.fcd.proV1.FCD1TunerConfiguration; import io.github.dsheirer.source.tuner.fcd.proV1.FCD1TunerController; +import io.github.dsheirer.source.tuner.fcd.proV1.FCD1TunerEditor; +import io.github.dsheirer.source.tuner.fcd.proplusV2.FCD2TunerConfiguration; import io.github.dsheirer.source.tuner.fcd.proplusV2.FCD2TunerController; +import io.github.dsheirer.source.tuner.fcd.proplusV2.FCD2TunerEditor; import io.github.dsheirer.source.tuner.hackrf.HackRFTuner; +import io.github.dsheirer.source.tuner.hackrf.HackRFTunerConfiguration; import io.github.dsheirer.source.tuner.hackrf.HackRFTunerController; +import io.github.dsheirer.source.tuner.hackrf.HackRFTunerEditor; +import io.github.dsheirer.source.tuner.manager.DiscoveredTuner; +import io.github.dsheirer.source.tuner.manager.TunerManager; +import io.github.dsheirer.source.tuner.recording.RecordingTunerConfiguration; +import io.github.dsheirer.source.tuner.recording.RecordingTunerEditor; import io.github.dsheirer.source.tuner.rtl.EmbeddedTuner; import io.github.dsheirer.source.tuner.rtl.RTL2832Tuner; import io.github.dsheirer.source.tuner.rtl.RTL2832TunerController; +import io.github.dsheirer.source.tuner.rtl.RTL2832UnknownTunerEditor; import io.github.dsheirer.source.tuner.rtl.e4k.E4KEmbeddedTuner; +import io.github.dsheirer.source.tuner.rtl.e4k.E4KTunerConfiguration; +import io.github.dsheirer.source.tuner.rtl.e4k.E4KTunerEditor; import io.github.dsheirer.source.tuner.rtl.r820t.R820TEmbeddedTuner; +import io.github.dsheirer.source.tuner.rtl.r820t.R820TTunerConfiguration; +import io.github.dsheirer.source.tuner.rtl.r820t.R820TTunerEditor; +import io.github.dsheirer.source.tuner.ui.TunerEditor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -104,4 +124,69 @@ public class TunerFactory default -> throw new SourceException("Unsupported/Unrecognized Tuner Type"); }; } + + /** + * Creates a tuner configuration for the specified tuner type, unique ID and name + */ + public static TunerConfiguration getTunerConfiguration(TunerType type, String uniqueID) + { + switch(type) + { + case AIRSPY_R820T: + return new AirspyTunerConfiguration(uniqueID); + case ELONICS_E4000: + return new E4KTunerConfiguration(uniqueID); + case FUNCUBE_DONGLE_PRO: + return new FCD1TunerConfiguration(uniqueID); + case FUNCUBE_DONGLE_PRO_PLUS: + return new FCD2TunerConfiguration(uniqueID); + case HACKRF_JAWBREAKER: + case HACKRF_ONE: + case HACKRF_RAD1O: + return new HackRFTunerConfiguration(uniqueID); + case RAFAELMICRO_R820T: + return new R820TTunerConfiguration(uniqueID); + case RECORDING: + return new RecordingTunerConfiguration(uniqueID); + default: + throw new IllegalArgumentException("Unrecognized tuner type [" + type.name() + "]"); + } + } + + /** + * Creates a tuner editor gui for the specified tuner + */ + public static TunerEditor getEditor(UserPreferences userPreferences, DiscoveredTuner discoveredTuner, + TunerManager tunerManager) + { + switch(discoveredTuner.getTunerClass()) + { + case AIRSPY: + return new AirspyTunerEditor(userPreferences, tunerManager, discoveredTuner); + case FUNCUBE_DONGLE_PRO: + return new FCD1TunerEditor(userPreferences, tunerManager, discoveredTuner); + case FUNCUBE_DONGLE_PRO_PLUS: + return new FCD2TunerEditor(userPreferences, tunerManager, discoveredTuner); + case HACKRF: + return new HackRFTunerEditor(userPreferences, tunerManager, discoveredTuner); + case RTL2832: + if(discoveredTuner.hasTuner()) + { + switch(discoveredTuner.getTuner().getTunerType()) + { + case ELONICS_E4000: + return new E4KTunerEditor(userPreferences, tunerManager, discoveredTuner); + case RAFAELMICRO_R820T: + return new R820TTunerEditor(userPreferences, tunerManager, discoveredTuner); + } + } + return new RTL2832UnknownTunerEditor(userPreferences, tunerManager, discoveredTuner); + case RECORDING_TUNER: + return new RecordingTunerEditor(userPreferences, tunerManager, discoveredTuner); + case TEST_TUNER: + case UNKNOWN: + default: + throw new IllegalArgumentException("Unsupported tuner class: " + discoveredTuner.getTunerClass()); + } + } } diff --git a/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfigurationFactory.java b/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfigurationFactory.java deleted file mode 100644 index 4939f607..00000000 --- a/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfigurationFactory.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2022 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 - * **************************************************************************** - */ - -package io.github.dsheirer.source.tuner.configuration; - -import io.github.dsheirer.preference.UserPreferences; -import io.github.dsheirer.source.tuner.TunerType; -import io.github.dsheirer.source.tuner.airspy.AirspyTunerConfiguration; -import io.github.dsheirer.source.tuner.airspy.AirspyTunerEditor; -import io.github.dsheirer.source.tuner.fcd.proV1.FCD1TunerConfiguration; -import io.github.dsheirer.source.tuner.fcd.proV1.FCD1TunerEditor; -import io.github.dsheirer.source.tuner.fcd.proplusV2.FCD2TunerConfiguration; -import io.github.dsheirer.source.tuner.fcd.proplusV2.FCD2TunerEditor; -import io.github.dsheirer.source.tuner.hackrf.HackRFTunerConfiguration; -import io.github.dsheirer.source.tuner.hackrf.HackRFTunerEditor; -import io.github.dsheirer.source.tuner.manager.DiscoveredTuner; -import io.github.dsheirer.source.tuner.manager.TunerManager; -import io.github.dsheirer.source.tuner.recording.RecordingTunerConfiguration; -import io.github.dsheirer.source.tuner.recording.RecordingTunerEditor; -import io.github.dsheirer.source.tuner.rtl.RTL2832UnknownTunerEditor; -import io.github.dsheirer.source.tuner.rtl.e4k.E4KTunerConfiguration; -import io.github.dsheirer.source.tuner.rtl.e4k.E4KTunerEditor; -import io.github.dsheirer.source.tuner.rtl.r820t.R820TTunerConfiguration; -import io.github.dsheirer.source.tuner.rtl.r820t.R820TTunerEditor; -import io.github.dsheirer.source.tuner.ui.TunerEditor; - -/** - * Factory methods to support tuner configurations and configuration editors. - */ -public class TunerConfigurationFactory -{ - /** - * Creates a tuner configuration for the specified tuner type, unique ID and name - */ - public static TunerConfiguration getTunerConfiguration(TunerType type, String uniqueID) - { - switch(type) - { - case AIRSPY_R820T: - return new AirspyTunerConfiguration(uniqueID); - case ELONICS_E4000: - return new E4KTunerConfiguration(uniqueID); - case FUNCUBE_DONGLE_PRO: - return new FCD1TunerConfiguration(uniqueID); - case FUNCUBE_DONGLE_PRO_PLUS: - return new FCD2TunerConfiguration(uniqueID); - case HACKRF_JAWBREAKER: - case HACKRF_ONE: - case HACKRF_RAD1O: - return new HackRFTunerConfiguration(uniqueID); - case RAFAELMICRO_R820T: - return new R820TTunerConfiguration(uniqueID); - case RECORDING: - return new RecordingTunerConfiguration(uniqueID); - default: - throw new IllegalArgumentException("Unrecognized tuner type [" + type.name() + "]"); - } - } - - /** - * Creates a tuner editor gui for the specified tuner - */ - public static TunerEditor getEditor(UserPreferences userPreferences, DiscoveredTuner discoveredTuner, - TunerManager tunerManager) - { - switch(discoveredTuner.getTunerClass()) - { - case AIRSPY: - return new AirspyTunerEditor(userPreferences, tunerManager, discoveredTuner); - case FUNCUBE_DONGLE_PRO: - return new FCD1TunerEditor(userPreferences, tunerManager, discoveredTuner); - case FUNCUBE_DONGLE_PRO_PLUS: - return new FCD2TunerEditor(userPreferences, tunerManager, discoveredTuner); - case HACKRF: - return new HackRFTunerEditor(userPreferences, tunerManager, discoveredTuner); - case RTL2832: - if(discoveredTuner.hasTuner()) - { - switch(discoveredTuner.getTuner().getTunerType()) - { - case ELONICS_E4000: - return new E4KTunerEditor(userPreferences, tunerManager, discoveredTuner); - case RAFAELMICRO_R820T: - return new R820TTunerEditor(userPreferences, tunerManager, discoveredTuner); - } - } - return new RTL2832UnknownTunerEditor(userPreferences, tunerManager, discoveredTuner); - case RECORDING_TUNER: - return new RecordingTunerEditor(userPreferences, tunerManager, discoveredTuner); - case TEST_TUNER: - case UNKNOWN: - default: - throw new IllegalArgumentException("Unsupported tuner class: " + discoveredTuner.getTunerClass()); - } - } -} diff --git a/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfigurationManager.java b/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfigurationManager.java index 931b7fab..d4467166 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfigurationManager.java +++ b/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfigurationManager.java @@ -23,6 +23,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import io.github.dsheirer.preference.UserPreferences; +import io.github.dsheirer.source.tuner.TunerFactory; import io.github.dsheirer.source.tuner.TunerType; import io.github.dsheirer.source.tuner.manager.DiscoveredTuner; import io.github.dsheirer.source.tuner.manager.IDiscoveredTunerStatusListener; @@ -152,12 +153,10 @@ public class TunerConfigurationManager implements IDiscoveredTunerStatusListener { if(current == TunerStatus.DISABLED) { - mLog.info("Setting Tuner to Disabled: " + discoveredTuner.getId()); addDisabledTuner(discoveredTuner); } else if(current == TunerStatus.ENABLED) { - mLog.info("Setting Tuner to Enabled: " + discoveredTuner.getId()); removeDisabledTuner(discoveredTuner); } } @@ -287,7 +286,7 @@ public class TunerConfigurationManager implements IDiscoveredTunerStatusListener return optional.get(); } - TunerConfiguration config = TunerConfigurationFactory.getTunerConfiguration(type, uniqueID); + TunerConfiguration config = TunerFactory.getTunerConfiguration(type, uniqueID); addTunerConfiguration(config); return config; } diff --git a/src/main/java/io/github/dsheirer/source/tuner/manager/DiscoveredTuner.java b/src/main/java/io/github/dsheirer/source/tuner/manager/DiscoveredTuner.java index 2197cc9c..e57e347a 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/manager/DiscoveredTuner.java +++ b/src/main/java/io/github/dsheirer/source/tuner/manager/DiscoveredTuner.java @@ -83,6 +83,8 @@ public abstract class DiscoveredTuner implements ITunerErrorListener //If there was a change in state if(mEnabled ^ enabled) { + mErrorMessage = null; + mEnabled = enabled; if(mEnabled) diff --git a/src/main/java/io/github/dsheirer/source/tuner/manager/TunerManager.java b/src/main/java/io/github/dsheirer/source/tuner/manager/TunerManager.java index 5b0b0c4d..c1db18bc 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/manager/TunerManager.java +++ b/src/main/java/io/github/dsheirer/source/tuner/manager/TunerManager.java @@ -109,7 +109,6 @@ public class TunerManager implements IDiscoveredTunerStatusListener } discoverSdrPlayTuners(); - discoverSoundCardTuners(); discoverRecordingTuners(); } @@ -150,15 +149,39 @@ public class TunerManager implements IDiscoveredTunerStatusListener DeviceList deviceList = new DeviceList(); int deviceCount = LibUsb.getDeviceList(mLibUsbApplicationContext, deviceList); + mLog.info("LibUsb - discovered [" + deviceCount + "] potential usb devices"); + if(deviceCount >= 0) { for(Device device: deviceList) { - addUsbTuner(device); + int bus = LibUsb.getBusNumber(device); + int port = LibUsb.getPortNumber(device); + + DeviceDescriptor deviceDescriptor = new DeviceDescriptor(); + int status = LibUsb.getDeviceDescriptor(device, deviceDescriptor); + + //Unref the device - it will be rediscovered under the device context when it is started + LibUsb.unrefDevice(device); + + if(status == LibUsb.SUCCESS) + { + TunerClass tunerClass = TunerClass.lookup(deviceDescriptor.idVendor(), deviceDescriptor.idProduct()); + + if(tunerClass.isSupportedUsbTuner()) + { + addUsbTuner(bus, port, tunerClass); + } + } + else + { + mLog.error("LibUsb - unable to get device descriptor for device on bus [" + bus + + "] port [" + port + "] - status [" + status + "] - " + LibUsb.errorName(status)); + } } } - LibUsb.freeDeviceList(deviceList, true); + LibUsb.freeDeviceList(deviceList, false); } catch(Exception e) { @@ -169,63 +192,47 @@ public class TunerManager implements IDiscoveredTunerStatusListener /** * Determines if the USB device is a supported tuner and add if it has not already been added/discovered. - * @param device to inspect and optionally add as a discovered tuner + * @param bus usb + * @param port usb + * @param tunerClass of the device to add */ - private void addUsbTuner(Device device) + private void addUsbTuner(int bus, int port, TunerClass tunerClass) { - int bus = LibUsb.getBusNumber(device); - int port = LibUsb.getPortNumber(device); - - DeviceDescriptor deviceDescriptor = new DeviceDescriptor(); - int status = LibUsb.getDeviceDescriptor(device, deviceDescriptor); - - if(status == LibUsb.SUCCESS) + if(!mDiscoveredTunerModel.hasUsbTuner(bus, port)) { - TunerClass tunerClass = TunerClass.lookup(deviceDescriptor.idVendor(), deviceDescriptor.idProduct()); + mLog.info("Adding USB Bus [" + bus + "] Port [" + port + "] Tuner Class [" + tunerClass + "]"); + ChannelizerType channelizerType = mUserPreferences.getTunerPreference().getChannelizerType(); + DiscoveredUSBTuner discoveredUSBTuner = new DiscoveredUSBTuner(tunerClass, bus, port, channelizerType); + discoveredUSBTuner.addTunerStatusListener(this); - if(tunerClass.isSupportedUsbTuner() && !mDiscoveredTunerModel.hasUsbTuner(bus, port)) + //Set the tuner to disabled if the user has previously blacklisted the tuner + if(mTunerConfigurationManager.isDisabled(discoveredUSBTuner)) { - mLog.info("Adding USB Bus [" + bus + "] Port [" + port + "] ID [" + - String.format("%04X", deviceDescriptor.idVendor()) + ":" + - String.format("%04X", deviceDescriptor.idProduct()) + "] Tuner Class [" + tunerClass + "]"); - ChannelizerType channelizerType = mUserPreferences.getTunerPreference().getChannelizerType(); - DiscoveredUSBTuner discoveredUSBTuner = new DiscoveredUSBTuner(tunerClass, bus, port, channelizerType); - discoveredUSBTuner.addTunerStatusListener(this); + discoveredUSBTuner.setEnabled(false); + } + else + { + //Attempt to start the discovered tuner so we can determine the tuner type + discoveredUSBTuner.start(); - //Set the tuner to disabled if the user has previously blacklisted the tuner - if(mTunerConfigurationManager.isDisabled(discoveredUSBTuner)) + if(discoveredUSBTuner.hasTuner()) { - discoveredUSBTuner.setEnabled(false); - } - else - { - //Attempt to start the discovered tuner so we can determine the tuner type - discoveredUSBTuner.start(); + TunerType tunerType = discoveredUSBTuner.getTuner().getTunerType(); - if(discoveredUSBTuner.hasTuner()) + TunerConfiguration tunerConfiguration = mTunerConfigurationManager + .getTunerConfiguration(tunerType, discoveredUSBTuner.getId()); + + if(tunerConfiguration != null) { - TunerType tunerType = discoveredUSBTuner.getTuner().getTunerType(); - - TunerConfiguration tunerConfiguration = mTunerConfigurationManager - .getTunerConfiguration(tunerType, discoveredUSBTuner.getId()); - - if(tunerConfiguration != null) - { - mLog.info("Applying tuner configuration to " + discoveredUSBTuner.getId()); - discoveredUSBTuner.setTunerConfiguration(tunerConfiguration); - mTunerConfigurationManager.saveConfigurations(); - } + mLog.info("Applying tuner configuration to " + discoveredUSBTuner.getId()); + discoveredUSBTuner.setTunerConfiguration(tunerConfiguration); + mTunerConfigurationManager.saveConfigurations(); } } - - mDiscoveredTunerModel.addDiscoveredTuner(discoveredUSBTuner); - mLog.info("Tuner Added: " + discoveredUSBTuner); } - } - else - { - mLog.error("LibUsb - unable to get device descriptor for device on bus [" + bus + - "] port [" + port + "] - status [" + status + "] - " + LibUsb.errorName(status)); + + mDiscoveredTunerModel.addDiscoveredTuner(discoveredUSBTuner); + mLog.info("Tuner Added: " + discoveredUSBTuner); } } @@ -239,14 +246,6 @@ public class TunerManager implements IDiscoveredTunerStatusListener mDiscoveredTunerModel.removeUsbTuner(bus, port); } - /** - * Discover sound card tuners like the Funcube Dongle (Pro) - */ - private void discoverSoundCardTuners() - { - - } - /** * Discover SDRPlay RSP tuners */ @@ -481,7 +480,18 @@ public class TunerManager implements IDiscoveredTunerStatusListener switch(event) { case LibUsb.HOTPLUG_EVENT_DEVICE_ARRIVED: - addUsbTuner(device); + DeviceDescriptor deviceDescriptor = new DeviceDescriptor(); + int status = LibUsb.getDeviceDescriptor(device, deviceDescriptor); + + if(status == LibUsb.SUCCESS) + { + TunerClass tunerClass = TunerClass.lookup(deviceDescriptor.idVendor(), deviceDescriptor.idProduct()); + + if(tunerClass.isSupportedUsbTuner()) + { + addUsbTuner(bus, port, tunerClass); + } + } break; case LibUsb.HOTPLUG_EVENT_DEVICE_LEFT: removeUsbTuner(bus, port); @@ -513,7 +523,7 @@ public class TunerManager implements IDiscoveredTunerStatusListener { Runnable eventHandler = () -> LibUsb.handleEvents(mLibUsbApplicationContext); mEventProcessorFuture = ThreadPool.SCHEDULED.scheduleAtFixedRate(eventHandler, - 0, 100, TimeUnit.MILLISECONDS); + 0, 1, TimeUnit.SECONDS); } else { diff --git a/src/main/java/io/github/dsheirer/source/tuner/ui/DiscoveredTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/ui/DiscoveredTunerEditor.java index a3f6efb6..63da401a 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/ui/DiscoveredTunerEditor.java +++ b/src/main/java/io/github/dsheirer/source/tuner/ui/DiscoveredTunerEditor.java @@ -21,7 +21,7 @@ package io.github.dsheirer.source.tuner.ui; import io.github.dsheirer.gui.editor.Editor; import io.github.dsheirer.preference.UserPreferences; -import io.github.dsheirer.source.tuner.configuration.TunerConfigurationFactory; +import io.github.dsheirer.source.tuner.TunerFactory; import io.github.dsheirer.source.tuner.manager.DiscoveredTuner; import io.github.dsheirer.source.tuner.manager.IDiscoveredTunerStatusListener; import io.github.dsheirer.source.tuner.manager.TunerManager; @@ -101,7 +101,7 @@ public class DiscoveredTunerEditor extends Editor implements ID if(hasItem()) { - mEditor = TunerConfigurationFactory.getEditor(mUserPreferences, getItem(), mTunerManager); + mEditor = TunerFactory.getEditor(mUserPreferences, getItem(), mTunerManager); getItem().addTunerStatusListener(this); } else diff --git a/src/main/java/io/github/dsheirer/source/tuner/ui/TunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/ui/TunerEditor.java index 3a85ad31..0f40c673 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/ui/TunerEditor.java +++ b/src/main/java/io/github/dsheirer/source/tuner/ui/TunerEditor.java @@ -62,7 +62,6 @@ public abstract class TunerEditor private Logger mLog = LoggerFactory.getLogger(TunerEditor.class); private static final String BUTTON_STATUS_ENABLE = "Enable"; private static final String BUTTON_STATUS_DISABLE = "Disable"; - private static final String BUTTON_STATUS_RESET = "Reset Error"; private static final long serialVersionUID = 1L; private UserPreferences mUserPreferences; private TunerManager mTunerManager; @@ -71,9 +70,10 @@ public abstract class TunerEditor private FrequencyAndCorrectionChangeListener mFrequencyAndCorrectionChangeListener = new FrequencyAndCorrectionChangeListener(); private JFrequencyControl mFrequencyControl; private JSpinner mFrequencyCorrectionSpinner; - private JButton mChangeStatusButton; + private JButton mEnabledButton; private JButton mViewSpectrumButton; private JButton mNewSpectrumButton; + private JButton mRestartTunerButton; private JToggleButton mRecordButton; private ButtonPanel mButtonsPanel; private FrequencyPanel mFrequencyPanel; @@ -107,6 +107,11 @@ public abstract class TunerEditor if(mDiscoveredTuner.hasTuner()) { mDiscoveredTuner.getTuner().addTunerEventListener(this); + + if(!mDiscoveredTuner.hasTunerConfiguration()) + { + mLog.warn("Tuner does not have a tuner configuration ...."); + } } } } @@ -327,15 +332,15 @@ public abstract class TunerEditor /** * Button to change enable, disable, or error restart status. */ - protected JButton getChangeStatusButton() + protected JButton getEnabledButton() { - if(mChangeStatusButton == null) + if(mEnabledButton == null) { - mChangeStatusButton = new JButton(BUTTON_STATUS_ENABLE); - mChangeStatusButton.setToolTipText("Enable or disable the tuner for use by sdrtrunk, or attempt to reset a tuner error"); - mChangeStatusButton.addActionListener(e -> + mEnabledButton = new JButton(BUTTON_STATUS_ENABLE); + mEnabledButton.setToolTipText("Enable or disable the tuner for use by sdrtrunk, or attempt to reset a tuner error"); + mEnabledButton.addActionListener(e -> { - switch(getChangeStatusButton().getText()) + switch(getEnabledButton().getText()) { case BUTTON_STATUS_DISABLE: mLog.info("Disabling " + getDiscoveredTuner().getTunerClass() + " tuner"); @@ -345,17 +350,37 @@ public abstract class TunerEditor mLog.info("Enabling " + getDiscoveredTuner().getTunerClass() + " tuner"); getDiscoveredTuner().setEnabled(true); break; - case BUTTON_STATUS_RESET: - mLog.info("Resetting " + getDiscoveredTuner().getTunerClass() + " tuner"); - getDiscoveredTuner().reset(); - break; default: mLog.info("None matched"); } }); } - return mChangeStatusButton; + return mEnabledButton; + } + + protected JButton getRestartTunerButton() + { + if(mRestartTunerButton == null) + { + mRestartTunerButton = new JButton("Restart Tuner"); + mRestartTunerButton.setVisible(false); + mRestartTunerButton.setToolTipText("Attempt to restart this tuner to recover from error condition"); + mRestartTunerButton.addActionListener(e -> + { + if(!hasTuner() && getDiscoveredTuner().getTunerStatus() == TunerStatus.ERROR) + { + mLog.info("Resetting " + getDiscoveredTuner().getTunerClass() + " tuner"); + getDiscoveredTuner().reset(); + if(getDiscoveredTuner().isEnabled()) + { + getDiscoveredTuner().start(); + } + } + }); + } + + return mRestartTunerButton; } /** @@ -532,12 +557,12 @@ public abstract class TunerEditor */ public ButtonPanel() { - setLayout(new MigLayout("insets 0,fill", "[][][][][grow,fill]", "")); - add(getChangeStatusButton()); + setLayout(new MigLayout("insets 0,fill", "[][][][][][grow,fill]", "")); + add(getEnabledButton()); add(getRecordButton()); add(getViewSpectrumButton()); - add(getNewSpectrumButton(), "wrap"); -// add(new JLabel(""), "wrap"); //Spacer to allow recording status label to grow and not affect buttons + add(getNewSpectrumButton()); + add(getRestartTunerButton(), "wrap"); add(getRecordingStatusLabel(), "span"); } @@ -552,18 +577,15 @@ public abstract class TunerEditor getRecordingStatusLabel().setText(" "); getViewSpectrumButton().setEnabled(tunerStatus.isAvailable() && getDiscoveredTuner().hasTuner()); getNewSpectrumButton().setEnabled(tunerStatus.isAvailable() && getDiscoveredTuner().hasTuner()); + getRestartTunerButton().setVisible(tunerStatus == TunerStatus.ERROR); - switch(tunerStatus) + if(getDiscoveredTuner().isEnabled()) { - case ENABLED: - getChangeStatusButton().setText(BUTTON_STATUS_DISABLE); - break; - case DISABLED: - getChangeStatusButton().setText(BUTTON_STATUS_ENABLE); - break; - case ERROR: - getChangeStatusButton().setText(BUTTON_STATUS_RESET); - break; + getEnabledButton().setText(BUTTON_STATUS_DISABLE); + } + else + { + getEnabledButton().setText(BUTTON_STATUS_ENABLE); } } } diff --git a/src/main/java/io/github/dsheirer/source/tuner/usb/USBTunerController.java b/src/main/java/io/github/dsheirer/source/tuner/usb/USBTunerController.java index d2239d7b..c85e85e2 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/usb/USBTunerController.java +++ b/src/main/java/io/github/dsheirer/source/tuner/usb/USBTunerController.java @@ -329,6 +329,8 @@ public abstract class USBTunerController extends TunerController */ private Device findDevice() throws SourceException { + Device foundDevice = null; + DeviceList deviceList = new DeviceList(); int count = LibUsb.getDeviceList(mDeviceContext, deviceList); @@ -341,11 +343,23 @@ public abstract class USBTunerController extends TunerController if(mBus == bus && mPort == port) { - return device; + foundDevice = device; + } + else + { + LibUsb.unrefDevice(device); } } } + //Free the device list but don't auto-unref all the devices ... we already did that during iteration + LibUsb.freeDeviceList(deviceList, false); + + if(foundDevice != null) + { + return foundDevice; + } + throw new SourceException("LibUsb couldn't discover USB device [" + mBus + ":" + mPort + "] from device list" + (count < 0 ? " - error: " + LibUsb.errorName(count) : "")); } @@ -529,6 +543,7 @@ public abstract class USBTunerController extends TunerController else { mLog.error("Error submitting USB transfer - " + LibUsb.errorName(status)); + setErrorMessage("Usb I/O Error - Can't submit buffers to tuner - stopping tuner"); } }