deviceStructs = getDeviceStructures();
+
+ for(IDeviceStruct deviceStruct: deviceStructs)
+ {
+ if(deviceInfo.matches(deviceStruct))
+ {
+ device = DeviceFactory.createDevice(this, deviceStruct);
+ break;
+ }
+ }
+ }
+
+ if(device == null)
+ {
+ throw new SDRPlayException("Unable to find RSP device");
+ }
+
+ return device;
+ }
+
+
+ /**
+ * Finds the first device that matches the specified device type.
+ *
+ * @param deviceType to find
+ * @return the specified device type or null.
+ */
+ public DeviceInfo getDeviceInfo(DeviceType deviceType) throws SDRPlayException
+ {
+ for(DeviceInfo deviceInfo : getDeviceInfos())
+ {
+ if(deviceInfo.getDeviceType() == deviceType)
+ {
+ return deviceInfo;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Selects the device for exclusive use. This method is invoked by the device instance.
+ *
+ * @param memorySegment of the device in foreign memory
+ * @throws SDRPlayException if the device argument was not created by this API instance or if unable to lock or
+ * unlock the device API for exclusive use, or if unable to select the device.
+ */
+ public void select(MemorySegment memorySegment) throws SDRPlayException
+ {
+ lockDeviceApi();
+ Status selectStatus = Status.fromValue(sdrplay_api_h.sdrplay_api_SelectDevice(memorySegment));
+ unlockDeviceApi();
+
+ if(selectStatus.fail())
+ {
+ throw new SDRPlayException("Unable to select the device", selectStatus);
+ }
+ }
+
+ /**
+ * Releases the device from exclusive use. This method is invoked by the device instance.
+ *
+ * @param memorySegment of the device in foreign memory
+ * @throws SDRPlayException if the device argument was not created by this API instance or if unable to release
+ * the device
+ */
+ public void release(MemorySegment memorySegment) throws SDRPlayException
+ {
+ Status status = Status.fromValue(sdrplay_api_h.sdrplay_api_ReleaseDevice(memorySegment));
+
+ if(status.fail())
+ {
+ mLog.info("API call to release device failed, however device is effectively released now.");
+ }
+ }
+
+ /**
+ * Retrieves the initial composite parameters for each device. This should only be invoked once, on
+ * startup, for each device. Changes made to the device parameters should invoke update() method to apply changes.
+ *
+ * @param deviceType to load parameters
+ * @param deviceHandle to device
+ * @return constructed device composite paramaters
+ */
+ public CompositeParameters getCompositeParameters(DeviceType deviceType, MemoryAddress deviceHandle) throws SDRPlayException
+ {
+ //Allocate a pointer that the api will fill with the memory address of the device parameters in memory.
+ MemorySegment pointer = getGlobalMemorySession().allocate(ValueLayout.ADDRESS);
+ Status status = Status.fromValue(sdrplay_api_h.sdrplay_api_GetDeviceParams(deviceHandle, pointer));
+
+ if(status.success())
+ {
+ //Get the memory address from the pointer's memory segment to where the structure is located
+ MemoryAddress memoryAddress = pointer.get(ValueLayout.ADDRESS, 0);
+
+ //The structure's memory is already allocated ... wrap a memory segment around it
+ MemorySegment memorySegment = sdrplay_api_DeviceT.ofAddress(memoryAddress, mGlobalMemorySession);
+ return CompositeParametersFactory.create(deviceType, memorySegment, mGlobalMemorySession);
+ }
+ else
+ {
+ throw new SDRPlayException("Error retrieving device composite parameters", status);
+ }
+ }
+
+ /**
+ * Initializes a device for use.
+ *
+ * @param deviceHandle to the device
+ * @param callbackFunctions to receive stream data from A and (optionally) B channels and events.
+ * @throws SDRPlayException if the device is not selected of if unable to init the device
+ */
+ private void init(MemoryAddress deviceHandle, MemorySegment callbackFunctions) throws SDRPlayException
+ {
+ //Since we don't need/use the callback context ... setup as a pointer to the callback functions
+ MemorySegment contextPointer = getGlobalMemorySession().allocate(ValueLayout.ADDRESS, callbackFunctions);
+ Status status = Status.fromValue(sdrplay_api_h.sdrplay_api_Init(deviceHandle, callbackFunctions, contextPointer));
+
+ if(!status.success())
+ {
+ throw new SDRPlayException("Error while initializing device", status);
+ }
+ }
+
+ /**
+ * Initializes a device for single-tuner use or for dual-tuner use as stream A
+ *
+ * @param device to initialize
+ * @param deviceHandle to the device
+ * @param eventListener to receive events for this device
+ * @param streamListener to receive samples for stream A
+ * @throws SDRPlayException if the device is not selected of if unable to init the device
+ */
+ public void initA(Device device, MemoryAddress deviceHandle, IDeviceEventListener eventListener,
+ IStreamListener streamListener) throws SDRPlayException
+ {
+ CallbackFunctions callbackFunctions = mDeviceCallbackFunctionsMap.get(deviceHandle);
+
+ if(callbackFunctions == null)
+ {
+ callbackFunctions = new CallbackFunctions(getGlobalMemorySession(), eventListener, streamListener,
+ device.getStreamCallbackListener());
+ mDeviceCallbackFunctionsMap.put(deviceHandle, callbackFunctions);
+ }
+ else
+ {
+ callbackFunctions.setDeviceEventListener(eventListener);
+ callbackFunctions.setStreamAListener(streamListener);
+ }
+
+ init(deviceHandle, callbackFunctions.getCallbackFunctionsMemorySegment());
+ }
+
+ /**
+ * Initializes a device for dual-tuner use as stream B
+ *
+ * @param device to initialize
+ * @param deviceHandle to the device
+ * @param eventListener to receive events for this device
+ * @param streamListener to receive samples for stream B
+ * @throws SDRPlayException if the device is not selected of if unable to init the device
+ */
+ public void initB(Device device, MemoryAddress deviceHandle, IDeviceEventListener eventListener,
+ IStreamListener streamListener) throws SDRPlayException
+ {
+ CallbackFunctions callbackFunctions = mDeviceCallbackFunctionsMap.get(deviceHandle);
+
+ if(callbackFunctions == null)
+ {
+ callbackFunctions = new CallbackFunctions(getGlobalMemorySession(), eventListener, streamListener, streamListener,
+ device.getStreamCallbackListener());
+ mDeviceCallbackFunctionsMap.put(deviceHandle, callbackFunctions);
+ }
+ else
+ {
+ callbackFunctions.setDeviceEventListener(eventListener);
+ callbackFunctions.setStreamAListener(streamListener);
+ }
+
+ init(deviceHandle, callbackFunctions.getCallbackFunctionsMemorySegment());
+ }
+
+ /**
+ * Un-Initializes a device from use.
+ *
+ * @param deviceHandle to the device
+ * @throws SDRPlayException if error during uninit or if device is not selected
+ */
+ public void uninit(MemoryAddress deviceHandle) throws SDRPlayException
+ {
+ Status status = Status.fromValue(sdrplay_api_h.sdrplay_api_Uninit(deviceHandle));
+
+ if(status.fail() && status != Status.NOT_INITIALIZED)
+ {
+ throw new SDRPlayException("Error while un-initializing device", status);
+ }
+ }
+
+ /**
+ * Applies updates made to the device parameters. The device parameter that was updated is specified in the
+ * update reason.
+ *
+ * Note: this method is synchronized to prevent multiple threads from attempting to send update requests
+ * concurrently, which will cause a failed request.
+ *
+ * @param device to update
+ * @param deviceHandle for the device
+ * @param tunerSelect identifies which tuner to apply the updates
+ * @param updateReasons identifying what was updated
+ * @throws SDRPlayException if the device is not selected, or if unable to update the device parameters
+ */
+ public synchronized void update(Device device, MemoryAddress deviceHandle, TunerSelect tunerSelect,
+ UpdateReason... updateReasons) throws SDRPlayException
+ {
+ int reasons = UpdateReason.getReasons(updateReasons);
+ int extendedReasons = UpdateReason.getExtendedReasons(updateReasons);
+
+ Status status = Status.fromValue(sdrplay_api_h.sdrplay_api_Update(deviceHandle, tunerSelect.getValue(),
+ reasons, extendedReasons));
+
+ if(status.fail())
+ {
+ throw new SDRPlayUpdateException(status, Arrays.stream(updateReasons).toList());
+ }
+ }
+
+ /**
+ * Retrieve error information for the last error for the specified device.
+ *
+ * @param deviceSegment for the device
+ * @return error information
+ */
+ private ErrorInformation getLastError(MemorySegment deviceSegment)
+ {
+ MemoryAddress errorAddress = sdrplay_api_h.sdrplay_api_GetLastError(deviceSegment);
+ MemorySegment errorSegment = sdrplay_api_ErrorInfoT.ofAddress(errorAddress, mGlobalMemorySession);
+ return new ErrorInformation(errorSegment);
+ }
+
+ /**
+ * Sets the debug level logging for the specified device
+ *
+ * @param deviceHandle for the device
+ * @param debugLevel to set
+ * @throws SDRPlayException if the device is not selected or if unable to set/change the debug level.
+ */
+ public void setDebugLevel(MemoryAddress deviceHandle, DebugLevel debugLevel) throws SDRPlayException
+ {
+ Status status = Status.UNKNOWN;
+
+ if(getVersion() == Version.V3_07)
+ {
+ //V3.07 used a debug level argument
+ status = Status.fromValue(sdrplay_api_h.sdrplay_api_DebugEnable(deviceHandle, debugLevel.getValue()));
+ }
+ else if(getVersion().gte(Version.V3_08))
+ {
+ //V3.08+ uses a 0:1 flag to enable debug logging. The method signature didn't change -- still takes an integer
+ boolean enable = debugLevel != DebugLevel.DISABLE;
+ status = Status.fromValue(sdrplay_api_h.sdrplay_api_DebugEnable(deviceHandle, Flag.of(enable)));
+ }
+
+ if(status.fail())
+ {
+ throw new SDRPlayException("Unable to set debug level", status);
+ }
+ }
+
+ /**
+ * Indicates if the SDRplay API is available and that the API library has been located and loaded for use and
+ * it the API version is supported by this jsdrplay library.
+ */
+ public boolean isAvailable()
+ {
+ return mAvailable;
+ }
+
+ /**
+ * Opens the API service. MUST be invoked before accessing any of the API functions/methods.
+ */
+ private Status open()
+ {
+ return Status.fromValue(sdrplay_api_h.sdrplay_api_Open());
+ }
+
+ /**
+ * Closes the API service. MUST be invoked before shutdown, after all SDRPlay API operations are completed.
+ *
+ * Note: when using multiple instances of this class, only invoke close() on a single instance. With linux API
+ * version 3.07, if you invoked close() on one instance, then all of the other instances become unusable for
+ * performing device operations (e.g. release(), etc). This may be an artifact of the way that the Java
+ * Foreign Function support is implemented, but not sure. dls 1-Jan-2023
+ */
+ public Status close()
+ {
+ Status closeStatus;
+
+ try
+ {
+ closeStatus = Status.fromValue(sdrplay_api_h.sdrplay_api_Close());
+ }
+ catch(Exception e)
+ {
+ closeStatus = Status.FAIL;
+ mLog.error("Error closing SDRPlay API", e);
+ }
+
+ mSdrplayLibraryLoaded = false;
+ mAvailable = false;
+ return closeStatus;
+ }
+
+ /**
+ * Identifies the API version.
+ * Note: if the library is not found or loaded, or if the API version is not a supported version, this method
+ * returns UNKNOWN
+ *
+ * @return version.
+ */
+ public Version getVersion()
+ {
+ if(mVersion == null)
+ {
+ if(mSdrplayLibraryLoaded)
+ {
+ MemorySegment apiVersion = getGlobalMemorySession().allocate(ValueLayout.JAVA_FLOAT, 0);
+ Status status = Status.fromValue(sdrplay_api_h.sdrplay_api_ApiVersion(apiVersion));
+ if(status.success())
+ {
+ float version = apiVersion.get(ValueLayout.JAVA_FLOAT, 0);
+ mVersion = Version.fromValue(version);
+ }
+ }
+
+ if(mVersion == null)
+ {
+ mVersion = Version.UNKNOWN;
+ }
+ }
+
+ return mVersion;
+ }
+
+ /**
+ * Attempts to lock the API for exclusive use of the current application. Once locked, no other applications
+ * will be able to use the API. Typically used to lock the API prior to calling sdrplay_api_GetDevices() to
+ * ensure only one application can select a given device. After completing device selection using
+ * sdrplay_api_SelectDevice(), sdrplay_api_UnlockDeviceApi() can be used to release the API. May also
+ * be used prior to calling sdrplay_api_ReleaseDevice() if it is necessary to reselect the same device.
+ */
+ private void lockDeviceApi() throws SDRPlayException
+ {
+ if(isAvailable())
+ {
+ Status status = Status.fromValue(sdrplay_api_h.sdrplay_api_LockDeviceApi());
+ if(status.fail())
+ {
+ throw new SDRPlayException("Unable to lock Device API for exclusive use", status);
+ }
+ }
+ else
+ {
+ throw new SDRPlayException("API is unavailable", Status.API_UNAVAILABLE);
+ }
+ }
+
+ /**
+ * Unlocks the device from exclusive access.
+ *
+ * @throws SDRPlayException if unable to unlock the Device API
+ */
+ private void unlockDeviceApi() throws SDRPlayException
+ {
+ if(isAvailable())
+ {
+ Status status = Status.fromValue(sdrplay_api_h.sdrplay_api_UnlockDeviceApi());
+
+ if(status.fail())
+ {
+ throw new SDRPlayException("Unable to unlock Device API", status);
+ }
+ }
+ else
+ {
+ throw new SDRPlayException("API is unavailable", Status.API_UNAVAILABLE);
+ }
+ }
+
+ /**
+ * Identifies the java library path for the sdrplay api library at runtime.
+ */
+ public static String getSDRplayLibraryPath()
+ {
+ if(SystemUtils.IS_OS_WINDOWS)
+ {
+ return SDRPLAY_API_PATH_WINDOWS;
+ }
+ else if(SystemUtils.IS_OS_LINUX)
+ {
+ return SDRPLAY_API_PATH_LINUX;
+ }
+ else if(SystemUtils.IS_OS_MAC_OSX)
+ {
+ return SDRPLAY_API_PATH_MAC_OS;
+ }
+
+ mLog.error("Unrecognized operating system. Cannot identify sdrplay api library path");
+ return "";
+ }
+
+ public static void main(String[] args)
+ {
+ /**
+ * Note: on windows, add the following environment variable to the IntelliJ launcher:
+ * -Djava.library.path="C:\Program Files\SDRplay\API\x64"
+ *
+ * Alternately, we can add this location to the Windows PATH environment variable and
+ * Java will look there for the library, without having to specify it as a launcher
+ * option. This would allow for users that have installed the API to an alternate location.
+ */
+ SDRplay sdrplay = new SDRplay();
+ Status status = sdrplay.open();
+ mLog.info("Open Status: " + status);
+
+ try
+ {
+ for(DeviceInfo deviceInfo: sdrplay.getDeviceInfos())
+ {
+ mLog.info("Found: " + deviceInfo);
+ }
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.info("Error", se);
+ }
+
+ Status closeStatus = sdrplay.close();
+ mLog.info("Close Status: " + closeStatus);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/Status.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/Status.java
new file mode 100644
index 000000000..e09b6d13a
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/Status.java
@@ -0,0 +1,109 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+public enum Status
+{
+ SUCCESS(sdrplay_api_h.sdrplay_api_Success(), "Success"),
+ FAIL(sdrplay_api_h.sdrplay_api_Fail(), "Fail"),
+ INVALID_PARAMETER(sdrplay_api_h.sdrplay_api_InvalidParam(), "Invalid Parameter. Null pointer or invalid operating mode"),
+ OUT_OF_RANGE(sdrplay_api_h.sdrplay_api_OutOfRange(), "Out of Range. One or more parameters are set incorrectly"),
+ GAIN_UPDATE_ERROR(sdrplay_api_h.sdrplay_api_GainUpdateError(), "Gain Update Error"),
+ RF_UPDATE_ERROR(sdrplay_api_h.sdrplay_api_RfUpdateError(), "Frequency Update Error"),
+ FS_UPDATE_ERROR(sdrplay_api_h.sdrplay_api_FsUpdateError(), "Sample Rate Update Error"),
+ HARDWARE_ERROR(sdrplay_api_h.sdrplay_api_HwError(), "Hardware Error during tuner initialization"),
+ ALIASING_ERROR(sdrplay_api_h.sdrplay_api_AliasingError(), "Aliasing Error"),
+ ALREADY_INITIALIZED(sdrplay_api_h.sdrplay_api_AlreadyInitialised(), "Already Initialized"),
+ NOT_INITIALIZED(sdrplay_api_h.sdrplay_api_NotInitialised(), "Not Initialized"),
+ NOT_ENABLED(sdrplay_api_h.sdrplay_api_NotEnabled(), "Not Enabled"),
+ HARDWARE_VERSION_ERROR(sdrplay_api_h.sdrplay_api_HwVerError(), "Hardware Version Error"),
+ OUT_OF_MEMORY(sdrplay_api_h.sdrplay_api_OutOfMemError(), "Out Of Memory"),
+ SERVICE_NOT_RESPONDING(sdrplay_api_h.sdrplay_api_ServiceNotResponding(), "Service Not Responding"),
+ START_PENDING(sdrplay_api_h.sdrplay_api_StartPending(), "Start Pending"),
+ STOP_PENDING(sdrplay_api_h.sdrplay_api_StopPending(), "Stop Pending"),
+ INVALID_MODE(sdrplay_api_h.sdrplay_api_InvalidMode(), "Invalid Mode"),
+ FAILED_VERIFICATION_1(sdrplay_api_h.sdrplay_api_FailedVerification1(), "Failed Verification 1"),
+ FAILED_VERIFICATION_2(sdrplay_api_h.sdrplay_api_FailedVerification2(), "Failed Verification 2"),
+ FAILED_VERIFICATION_3(sdrplay_api_h.sdrplay_api_FailedVerification3(), "Failed Verification 3"),
+ FAILED_VERIFICATION_4(sdrplay_api_h.sdrplay_api_FailedVerification4(), "Failed Verification 4"),
+ FAILED_VERIFICATION_5(sdrplay_api_h.sdrplay_api_FailedVerification5(), "Failed Verification 5"),
+ FAILED_VERIFICATION_6(sdrplay_api_h.sdrplay_api_FailedVerification6(), "Failed Verification 6"),
+ INVALID_SERVICE_VERSION(sdrplay_api_h.sdrplay_api_InvalidServiceVersion(), "Invalid Service Version"),
+
+ //Custom status codes
+ API_UNAVAILABLE(-2, "SDRplay API is not installed or it has an unsupported version"),
+ UNKNOWN(-1, "Unknown");
+
+ private int mValue;
+ private String mDescription;
+
+ Status(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Status code value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Indicates if this is a SUCCESS status.
+ */
+ public boolean success()
+ {
+ return this == Status.SUCCESS;
+ }
+
+ public boolean fail()
+ {
+ return this != Status.SUCCESS;
+ }
+
+ /**
+ * Lookup the status from a return code
+ * @param value to lookup
+ * @return status or UKNOWN if the code is not recognized
+ */
+ public static Status fromValue(int value)
+ {
+ for(Status status: Status.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return UNKNOWN;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/UpdateReason.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/UpdateReason.java
new file mode 100644
index 000000000..a1ad61749
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/UpdateReason.java
@@ -0,0 +1,196 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+import java.util.EnumSet;
+
+/**
+ * Update reason.
+ *
+ * These entries are used to notify the SDRplay API once settings are updated on the device.
+ */
+public enum UpdateReason
+{
+ //Master Only mode
+ DEVICE_SAMPLE_RATE(sdrplay_api_h.sdrplay_api_Update_Dev_Fs(), "Sample Rate"),
+ DEVICE_PPM(sdrplay_api_h.sdrplay_api_Update_Dev_Ppm(), "PPM"),
+ DEVICE_SYNC_UPDATE(sdrplay_api_h.sdrplay_api_Update_Dev_SyncUpdate(), "Sync Update"),
+ DEVICE_RESET_FLAGS(sdrplay_api_h.sdrplay_api_Update_Dev_ResetFlags(), "Reset Flags"),
+
+ RSP1A_BIAS_T_CONTROL(sdrplay_api_h.sdrplay_api_Update_Rsp1a_BiasTControl(), "RSP1A Bias-T Control"),
+ RSP1A_RF_NOTCH_CONTROL(sdrplay_api_h.sdrplay_api_Update_Rsp1a_RfNotchControl(), "RSP1A RF Notch Control"),
+ RSP1A_RF_DAB_NOTCH_CONTROL(sdrplay_api_h.sdrplay_api_Update_Rsp1a_RfDabNotchControl(), "RSP1A RF DAB Notch Control"),
+
+ RSP2_BIAS_T_CONTROL(sdrplay_api_h.sdrplay_api_Update_Rsp2_BiasTControl(), "RSP2 Bias-T Control"),
+ RSP2_AM_PORT_SELECT(sdrplay_api_h.sdrplay_api_Update_Rsp2_AmPortSelect(), "RSP2 AM Port Select"),
+ RSP2_ANTENNA_CONTROL(sdrplay_api_h.sdrplay_api_Update_Rsp2_AntennaControl(), "RSP2 Antenna Control"),
+ RSP2_RF_NOTCH_CONTROL(sdrplay_api_h.sdrplay_api_Update_Rsp2_RfNotchControl(), "RSP2 RF Notch Control"),
+ RSP2_EXT_REF_CONTROL(sdrplay_api_h.sdrplay_api_Update_Rsp2_ExtRefControl(), "RSP2 External Reference Control"),
+
+ RSP_DUO_EXT_REF_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDuo_ExtRefControl(), "RSPduo External Reference Control"),
+
+ SPARE_1(sdrplay_api_h.sdrplay_api_Update_Master_Spare_1(), "Spare 1"),
+ SPARE_2(sdrplay_api_h.sdrplay_api_Update_Master_Spare_2(), "Spare 2"),
+
+ //Master and Slave mode
+ TUNER_GAIN_REDUCTION(sdrplay_api_h.sdrplay_api_Update_Tuner_Gr(), "Tuner Gain Reduction"),
+ TUNER_GAIN_REDUCTION_LIMITS(sdrplay_api_h.sdrplay_api_Update_Tuner_GrLimits(), "Tuner Gain Reduction Limits"),
+ TUNER_FREQUENCY_RF(sdrplay_api_h.sdrplay_api_Update_Tuner_Frf(), "Tuner Frequency RF"),
+ TUNER_BANDWIDTH_TYPE(sdrplay_api_h.sdrplay_api_Update_Tuner_BwType(), "Tuner Bandwidth Type"),
+ TUNER_IF_TYPE(sdrplay_api_h.sdrplay_api_Update_Tuner_IfType(), "Tuner IF Type"),
+ TUNER_DC_OFFSET(sdrplay_api_h.sdrplay_api_Update_Tuner_DcOffset(), "Tuner DC Offset"),
+ TUNER_LO_MODE(sdrplay_api_h.sdrplay_api_Update_Tuner_LoMode(), "Tuner LO Mode"),
+
+ CONTROL_DC_OFFSET_IQ_IMBALANCE(sdrplay_api_h.sdrplay_api_Update_Ctrl_DCoffsetIQimbalance(), "Control DC Offset IQ Imbalance"),
+ CONTROL_DECIMATION(sdrplay_api_h.sdrplay_api_Update_Ctrl_Decimation(), "Control Decimation"),
+ CONTROL_AGC(sdrplay_api_h.sdrplay_api_Update_Ctrl_Agc(), "Control AGC"),
+ CONTROL_ADSB_MODE(sdrplay_api_h.sdrplay_api_Update_Ctrl_AdsbMode(), "Control ADSB Mode"),
+ CONTROL_OVERLOAD_MESSAGE_ACK(sdrplay_api_h.sdrplay_api_Update_Ctrl_OverloadMsgAck(), "Control Overload Message Ack"),
+
+ RSP_DUO_BIAS_T_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDuo_BiasTControl(), "RSPduo Bias-T Control"),
+ RSP_DUO_AM_PORT_SELECT(sdrplay_api_h.sdrplay_api_Update_RspDuo_AmPortSelect(), "RSPduo AM Port Select"),
+ RSP_DUO_TUNER_1_AM_NOTCH_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDuo_Tuner1AmNotchControl(), "RSPduo Tuner 1 AM Notch Control"),
+ RSP_DUO_RF_NOTCH_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDuo_RfNotchControl(), "RSPduo RF Notch Control"),
+ RSP_DUO_RF_DAB_NOTCH_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDuo_RfDabNotchControl(), "RSPduo RF DAB Notch Control"),
+
+ //Extension 1
+ EXTENSION_RSP_DX_HDR_ENABLE(sdrplay_api_h.sdrplay_api_Update_RspDx_HdrEnable(), "RSPdx HDR Enable"),
+ EXTENSION_RSP_DX_BIAS_T_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDx_BiasTControl(), "RSPdx Bias-T Control"),
+ EXTENSION_RSP_DX_ANTENNA_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDx_AntennaControl(), "RSPdx Antenna Control"),
+ EXTENSION_RSP_DX_RF_NOTCH_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDx_RfNotchControl(), "RSPdx RF Notch Control"),
+ EXTENSION_RSP_DX_RF_DAB_NOTCH_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDx_RfDabNotchControl(), "RSPdx RF DAB Notch Control"),
+ EXTENSION_RSP_DX_HDR_BANDWIDTH(sdrplay_api_h.sdrplay_api_Update_RspDx_HdrBw(), "RSPdx HDR Bandwidth"),
+ EXTENSION_NONE(sdrplay_api_h.sdrplay_api_Update_Ext1_None(), "NONE"),
+
+
+ NONE(sdrplay_api_h.sdrplay_api_Update_None(), "NONE");
+
+ private int mValue;
+ private String mDescription;
+
+ UpdateReason(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ public static EnumSet EXTENSIONS = EnumSet.range(EXTENSION_RSP_DX_HDR_ENABLE, EXTENSION_NONE);
+
+
+ /**
+ * Many of the update reasons described in this enumeration are submitted asynchronously, since the API is
+ * non-blocking. However, the device event listener responses are limited to just three events: Frequency, Gain,
+ * and Sample Rate. This constant describes the three update reasons that correspond to the device events.
+ */
+ public static EnumSet ASYNC_UPDATE_RESPONSES = EnumSet.of(DEVICE_SAMPLE_RATE, TUNER_FREQUENCY_RF, TUNER_GAIN_REDUCTION);
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Indicates if this is an extended update reason entry.
+ */
+ public boolean isExtended()
+ {
+ return EXTENSIONS.contains(this);
+ }
+
+ /**
+ * Indicates if this update reason is one of the limited set of asynchronous update operation response types.
+ */
+ public boolean isAsyncUpdateResponse()
+ {
+ return ASYNC_UPDATE_RESPONSES.contains(this);
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or UNKNOWN if the code is not recognized
+ */
+ public static UpdateReason fromValue(int value)
+ {
+ for(UpdateReason status: UpdateReason.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return NONE;
+ }
+
+ /**
+ * Calculates a combined logical OR value of the non-extended update reasons. Extended reason values will
+ * be ignored for this calculation.
+ *
+ * @param reasons to combine
+ * @return combined (logical OR) value.
+ */
+ public static int getReasons(UpdateReason ... reasons)
+ {
+ int combined = UpdateReason.NONE.getValue();
+
+ for(UpdateReason reason: reasons)
+ {
+ if(!reason.isExtended())
+ {
+ combined += reason.getValue();
+ }
+ }
+
+ return combined;
+ }
+
+ /**
+ * Calculates a combined logical OR value of the extended update reasons. Non-extended reason values will
+ * be ignored for this calculation.
+ *
+ * @param reasons to combine
+ * @return combined (logical OR) value.
+ */
+ public static int getExtendedReasons(UpdateReason ... reasons)
+ {
+ int combined = UpdateReason.EXTENSION_NONE.getValue();
+
+ for(UpdateReason reason: reasons)
+ {
+ if(reason.isExtended())
+ {
+ combined += reason.getValue();
+ }
+ }
+
+ return combined;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/Version.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/Version.java
new file mode 100644
index 000000000..5a2ca8fde
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/Version.java
@@ -0,0 +1,99 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * SDRPlay API Versions
+ */
+public enum Version
+{
+ UNKNOWN(0.0f, false),
+ V3_07(3.07f, true),
+ V3_08(3.08f, true),
+ V3_09(3.09f, true),
+ V3_10(3.10f, true),
+ V3_11(3.11f, true);
+
+ private float mValue;
+ private boolean mSupported;
+ private static final Logger mLog = LoggerFactory.getLogger(Version.class);
+
+ Version(float value, boolean supported)
+ {
+ mValue = value;
+ mSupported = supported;
+ }
+
+ /**
+ * Indicates if the API version is supported by the jsdrplay library
+ */
+ public boolean isSupported()
+ {
+ return mSupported;
+ }
+
+ /**
+ * Indicates if this version is greater than or equal to the specified version.
+ * @param version to compare
+ * @return true if this version is greater than or equal to
+ */
+ public boolean gte(Version version)
+ {
+ return this.ordinal() >= version.ordinal();
+ }
+
+ /**
+ * Numeric API version/value
+ */
+ public float getVersion()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the version from the specified value.
+ * @param value to lookup
+ * @return version or UNKNOWN
+ */
+ public static Version fromValue(float value)
+ {
+
+ for(Version version: values())
+ {
+ if(version.mValue == value)
+ {
+ return version;
+ }
+ }
+
+ mLog.warn("Unrecognized SDRplay API version [" + value + "]");
+ return UNKNOWN;
+ }
+
+
+ @Override
+ public String toString()
+ {
+ return String.valueOf(mValue);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/async/AsyncFuture.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/async/AsyncFuture.java
new file mode 100644
index 000000000..4696149bd
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/async/AsyncFuture.java
@@ -0,0 +1,227 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.async;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Asynchronous operation that implements the Future interface with utility methods for callback on completion, or
+ * converting to a synchronous (ie blocking) operation.
+ * @param expected return type upon completion of the operation
+ */
+public class AsyncFuture implements Future
+{
+ private R mResult;
+ private Throwable mError;
+ private boolean mCancelled;
+ private boolean mCompleted = false;
+ private ReentrantLock mLock = new ReentrantLock();
+ private IAsyncCallback mCallback;
+
+ /**
+ * Sets the result and completes this future.
+ * @param result to apply.
+ */
+ public synchronized void setResult(R result)
+ {
+ if(mCompleted)
+ {
+ throw new IllegalStateException("Future is already completed.");
+ }
+
+ mResult = result;
+ finish();
+ }
+
+ /**
+ * Sets an error resulting from the operation and completes this future.
+ * @param error produced from the operation
+ */
+ public synchronized void setError(Throwable error)
+ {
+ if(mCompleted)
+ {
+ throw new IllegalStateException("Future is already completed.");
+ }
+
+ mError = error;
+ finish();
+ }
+
+ /**
+ * (Optional) error produced from the operation.
+ */
+ public Throwable getError()
+ {
+ return mError;
+ }
+
+ /**
+ * Indicates if this future had an error during the operation
+ */
+ public boolean hasError()
+ {
+ return mError != null;
+ }
+
+ /**
+ * Cleanup task that completes the future and notifies an optional registered callback.
+ */
+ private void finish()
+ {
+ mLock.lock();
+
+ try
+ {
+ mCompleted = true;
+
+ if(mCallback != null)
+ {
+ mCallback.complete(this);
+ mCallback = null;
+ }
+ }
+ finally
+ {
+ mLock.unlock();
+ }
+
+ notifyAll();
+ }
+
+ /**
+ * Signals a desire to cancel this future operation.
+ *
+ * Note: it is up to the implementer to monitor this cancel state.
+ * @param mayInterruptIfRunning not implemented.
+ * @return true always.
+ */
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning)
+ {
+ mCancelled = true;
+ return true;
+ }
+
+ /**
+ * Indicates if this future has been cancelled.
+ */
+ @Override
+ public boolean isCancelled()
+ {
+ return mCancelled;
+ }
+
+ /**
+ * Indicates if this future has completed.
+ */
+ @Override
+ public boolean isDone()
+ {
+ return mCompleted;
+ }
+
+ /**
+ * Blocking call to wait indefinitely for the result of the operation.
+ * @return result of the operation
+ * @throws InterruptedException if the calling thread is interrupted while waiting
+ * @throws ExecutionException if there is an error produced from the operation
+ */
+ @Override
+ public synchronized R get() throws InterruptedException, ExecutionException
+ {
+ while(!mCompleted)
+ {
+ wait();
+ }
+
+ if(mError != null)
+ {
+ throw new ExecutionException(mError);
+ }
+
+ return mResult;
+ }
+
+ /**
+ * Blocking call to synchronously get the result of the operation.
+ * @param timeout to wait
+ * @param unit for the timeout
+ * @return result once completed
+ * @throws InterruptedException if the calling thread is interrupted while waiting
+ * @throws ExecutionException if there is an error produced from the operation
+ * @throws TimeoutException if the timeout is exceeded while waiting.
+ */
+ @Override
+ public synchronized R get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
+ {
+ if(!mCompleted)
+ {
+ wait(unit.toMillis(timeout));
+ }
+
+ if(!mCompleted)
+ {
+ throw new TimeoutException("Get timeout [" + timeout + " " + unit + "] exceeded without completion");
+ }
+
+ if(mError != null)
+ {
+ throw new ExecutionException(mError);
+ }
+
+ return mResult;
+ }
+
+ /**
+ * Registers the callback to receive the result once the operation completes. If the operation is completed, the
+ * callback is immediately notified, otherwise the callback will be notified later.
+ * @param callback to be notified once the operation is completed.
+ */
+ public synchronized void callback(IAsyncCallback callback)
+ {
+ if(mCallback != null)
+ {
+ throw new IllegalArgumentException("Callback has been registered - only one callback is supported.");
+ }
+
+ mLock.lock();
+
+ try
+ {
+ if(mCompleted)
+ {
+ callback.complete(this);
+ }
+ else
+ {
+ mCallback = callback;
+ }
+ }
+ finally
+ {
+ mLock.unlock();
+ }
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/async/AsyncUpdateFuture.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/async/AsyncUpdateFuture.java
new file mode 100644
index 000000000..93ee0856d
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/async/AsyncUpdateFuture.java
@@ -0,0 +1,100 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.async;
+
+import com.github.dsheirer.sdrplay.Status;
+import com.github.dsheirer.sdrplay.UpdateReason;
+import com.github.dsheirer.sdrplay.device.TunerSelect;
+
+/**
+ * Asynchronous future for an SDRplay API update operation.
+ */
+public class AsyncUpdateFuture extends AsyncFuture
+{
+ private TunerSelect mTunerSelect;
+ private UpdateReason mUpdateReason;
+ private UpdateReason mExpectedResponse;
+ private boolean mSubmitted;
+
+ /**
+ * Creates a to-be completed future where a successful update with return success or an unsuccessful update will
+ * return an exception.
+ * @param tunerSelect for the tuner to be updated
+ * @param updateReason of what is to be updated
+ * @param expectedResponse to be received to indicate the async operation is completed
+ */
+ public AsyncUpdateFuture(TunerSelect tunerSelect, UpdateReason updateReason, UpdateReason expectedResponse)
+ {
+ mTunerSelect = tunerSelect;
+ mUpdateReason = updateReason;
+ mExpectedResponse = expectedResponse;
+ }
+
+ /**
+ * Tuner(s) for the update
+ */
+ public TunerSelect getTunerSelect()
+ {
+ return mTunerSelect;
+ }
+
+ /**
+ * UpdateReason that is being updated
+ */
+ public UpdateReason getUpdateReason()
+ {
+ return mUpdateReason;
+ }
+
+ /**
+ * Expected response to this update operation
+ */
+ public UpdateReason getExpectedResponse()
+ {
+ return mExpectedResponse;
+ }
+
+ /**
+ * Flag to indicate if this update has been submitted and is currently awaiting results.
+ */
+ public boolean isSubmitted()
+ {
+ return mSubmitted;
+ }
+
+ /**
+ * Sets flag to indicate that this update has been submitted.
+ */
+ public void setSubmitted(boolean submitted)
+ {
+ mSubmitted = submitted;
+ }
+
+ /**
+ * Indicates if the completed async operation matches this submitted async update future
+ * @param completedAsyncUpdate to compare
+ * @return true if there is a match
+ */
+ public boolean matches(CompletedAsyncUpdate completedAsyncUpdate)
+ {
+ return getTunerSelect().equals(completedAsyncUpdate.getTunerSelect()) &&
+ getExpectedResponse().equals(completedAsyncUpdate.getUpdateReason());
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/async/CompletedAsyncUpdate.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/async/CompletedAsyncUpdate.java
new file mode 100644
index 000000000..a1e896561
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/async/CompletedAsyncUpdate.java
@@ -0,0 +1,57 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.async;
+
+import com.github.dsheirer.sdrplay.UpdateReason;
+import com.github.dsheirer.sdrplay.device.TunerSelect;
+
+/**
+ * Completed asynchronous update operation
+ */
+public class CompletedAsyncUpdate
+{
+ private TunerSelect mTunerSelect;
+ private UpdateReason mUpdateReason;
+
+ /**
+ * Creates a completed update.
+ */
+ public CompletedAsyncUpdate(TunerSelect tunerSelect, UpdateReason updateReason)
+ {
+ mTunerSelect = tunerSelect;
+ mUpdateReason = updateReason;
+ }
+
+ /**
+ * Tuner(s) for the update
+ */
+ public TunerSelect getTunerSelect()
+ {
+ return mTunerSelect;
+ }
+
+ /**
+ * UpdateReason that is being updated
+ */
+ public UpdateReason getUpdateReason()
+ {
+ return mUpdateReason;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/async/IAsyncCallback.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/async/IAsyncCallback.java
new file mode 100644
index 000000000..bc722eef9
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/async/IAsyncCallback.java
@@ -0,0 +1,32 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.async;
+
+/**
+ * Callback interface to be notified when an async future has completed or has resulted in an error
+ */
+public interface IAsyncCallback
+{
+ /**
+ * Callback method once the future is completed or produces an error.
+ * @param future that is being monitored
+ */
+ void complete(AsyncFuture future);
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/CallbackFunctions.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/CallbackFunctions.java
new file mode 100644
index 000000000..a3d3b9d35
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/CallbackFunctions.java
@@ -0,0 +1,128 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.callback;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_CallbackFnsT;
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_EventCallback_t;
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_StreamCallback_t;
+
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+
+/**
+ * Callback functions (sdrplay_api_CallbackFnsT) factory
+ */
+public class CallbackFunctions
+{
+ private DeviceEventAdapter mDeviceEventAdapter;
+ private StreamCallbackAdapter mStreamACallbackAdapter;
+ private StreamCallbackAdapter mStreamBCallbackAdapter;
+ private MemorySegment mCallbackFunctionsMemorySegment;
+
+ /**
+ * Constructs a callback functions for single-tuner use.
+ * @param memorySession for native memory allocation
+ * @param deviceEventListener for device events
+ * @param streamListener for streaming samples
+ * @param streamCallbackListener for streaming events
+ */
+ public CallbackFunctions(MemorySession memorySession, IDeviceEventListener deviceEventListener,
+ IStreamListener streamListener, IStreamCallbackListener streamCallbackListener)
+ {
+ //Create the event callback function
+ mDeviceEventAdapter = new DeviceEventAdapter(memorySession, deviceEventListener);
+ MemorySegment eventFunction = sdrplay_api_EventCallback_t.allocate(mDeviceEventAdapter, memorySession);
+
+ //Create the stream A callback function
+ mStreamACallbackAdapter = new StreamCallbackAdapter(memorySession, streamListener, streamCallbackListener);
+ MemorySegment streamAFunction = sdrplay_api_StreamCallback_t.allocate(mStreamACallbackAdapter, memorySession);
+
+ //Create the callback functions union and populate the callback functions
+ mCallbackFunctionsMemorySegment = sdrplay_api_CallbackFnsT.allocate(memorySession);
+ sdrplay_api_CallbackFnsT.EventCbFn$set(mCallbackFunctionsMemorySegment, eventFunction.address());
+ sdrplay_api_CallbackFnsT.StreamACbFn$set(mCallbackFunctionsMemorySegment, streamAFunction.address());
+ }
+
+ /**
+ * Constructs a callback functions for dual-tuner use.
+ * @param memorySession for native memory allocation
+ * @param deviceEventListener for device events
+ * @param streamAListener for streaming samples from the master tuner
+ * @param streamBListener for streaming samples from the slave tuner
+ * @param streamCallbackListener for streaming events
+ */
+ public CallbackFunctions(MemorySession memorySession, IDeviceEventListener deviceEventListener,
+ IStreamListener streamAListener, IStreamListener streamBListener,
+ IStreamCallbackListener streamCallbackListener)
+ {
+ //Create the event callback function
+ mDeviceEventAdapter = new DeviceEventAdapter(memorySession, deviceEventListener);
+ MemorySegment eventFunction = sdrplay_api_EventCallback_t.allocate(mDeviceEventAdapter, memorySession);
+
+ //Create the stream A callback function
+ mStreamACallbackAdapter = new StreamCallbackAdapter(memorySession, streamAListener, streamCallbackListener);
+ MemorySegment streamAFunction = sdrplay_api_StreamCallback_t.allocate(mStreamACallbackAdapter, memorySession);
+
+ //Create the stream B callback function
+ mStreamBCallbackAdapter = new StreamCallbackAdapter(memorySession, streamBListener, streamCallbackListener);
+ MemorySegment streamBFunction = sdrplay_api_StreamCallback_t.allocate(mStreamBCallbackAdapter, memorySession);
+
+ //Create the callback functions union and populate the callback functions
+ mCallbackFunctionsMemorySegment = sdrplay_api_CallbackFnsT.allocate(memorySession);
+ sdrplay_api_CallbackFnsT.EventCbFn$set(mCallbackFunctionsMemorySegment, eventFunction.address());
+ sdrplay_api_CallbackFnsT.StreamACbFn$set(mCallbackFunctionsMemorySegment, streamAFunction.address());
+ sdrplay_api_CallbackFnsT.StreamBCbFn$set(mCallbackFunctionsMemorySegment, streamBFunction.address());
+ }
+
+ /**
+ * Foreign memory segment for the callback functions.
+ */
+ public MemorySegment getCallbackFunctionsMemorySegment()
+ {
+ return mCallbackFunctionsMemorySegment;
+ }
+
+ /**
+ * Updates the device event listener
+ * @param listener to receive device events
+ */
+ public void setDeviceEventListener(IDeviceEventListener listener)
+ {
+ mDeviceEventAdapter.setListener(listener);
+ }
+
+ /**
+ * Updates the stream A listener
+ * @param listener to receive samples for stream A
+ */
+ public void setStreamAListener(IStreamListener listener)
+ {
+ mStreamACallbackAdapter.setListener(listener);
+ }
+
+ /**
+ * Updates the stream B listener
+ * @param listener to receive samples for stream B
+ */
+ public void setStreamBListener(IStreamListener listener)
+ {
+ mStreamBCallbackAdapter.setListener(listener);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/DeviceEventAdapter.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/DeviceEventAdapter.java
new file mode 100644
index 000000000..8a201d4c3
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/DeviceEventAdapter.java
@@ -0,0 +1,112 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.callback;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_EventCallback_t;
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_EventParamsT;
+import com.github.dsheirer.sdrplay.device.TunerSelect;
+import com.github.dsheirer.sdrplay.parameter.event.EventParametersFactory;
+import com.github.dsheirer.sdrplay.parameter.event.EventType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+
+/**
+ * Adapter for Device Event callbacks. Implements foreign interface and transfers foreign memory event details to
+ * native Java and invokes the appropriate interface methods for an event listener.
+ */
+public class DeviceEventAdapter implements sdrplay_api_EventCallback_t
+{
+ private static final Logger mLog = LoggerFactory.getLogger(DeviceEventAdapter.class);
+
+ private MemorySession mMemorySession;
+ private IDeviceEventListener mDeviceEventListener;
+
+ /**
+ * Constructs an instance.
+ * @param memorySession to use in creating foreign memory segments to access foreign structures.
+ * @param listener to receive translated device events.
+ */
+ public DeviceEventAdapter(MemorySession memorySession, IDeviceEventListener listener)
+ {
+ if(memorySession == null)
+ {
+ throw new IllegalArgumentException("Resource scope must be non-null");
+ }
+
+ mMemorySession = memorySession;
+
+ setListener(listener);
+ }
+
+ /**
+ * Updates the device event listener
+ * @param listener to receive device events
+ */
+ public void setListener(IDeviceEventListener listener)
+ {
+ if(listener == null)
+ {
+ throw new IllegalArgumentException("Device event listener must be non-null");
+ }
+
+ mDeviceEventListener = listener;
+ }
+
+ @Override
+ public void apply(int eventTypeId, int tunerSelectId, MemoryAddress eventParametersPointer,
+ MemoryAddress callbackContext)
+ {
+ MemorySegment memorySegment = sdrplay_api_EventParamsT.ofAddress(eventParametersPointer, mMemorySession);
+ EventType eventType = EventType.fromValue(eventTypeId);
+ TunerSelect tunerSelect = TunerSelect.fromValue(tunerSelectId);
+
+ switch(eventType)
+ {
+ case GAIN_CHANGE -> {
+ mDeviceEventListener.processGainChange(tunerSelect,
+ EventParametersFactory.createGainCallbackParameters(memorySegment));
+ }
+ case POWER_OVERLOAD_CHANGE -> {
+ mDeviceEventListener.processPowerOverload(tunerSelect,
+ EventParametersFactory.createPowerOverloadCallbackParameters(memorySegment));
+ }
+ case DEVICE_REMOVED -> {
+ mDeviceEventListener.processDeviceRemoval(tunerSelect);
+ }
+ case RSP_DUO_MODE_CHANGE -> {
+ mDeviceEventListener.processRspDuoModeChange(tunerSelect,
+ EventParametersFactory.createRspDuoModeCallbackParameters(memorySegment));
+ }
+ case UNKNOWN -> {
+ mLog.warn("Unknown device event callback ignored. Please contact the library developer as this may " +
+ "indicate a change to the SDRPlay API change. Tuner:" + tunerSelect + " Event Type ID:" +
+ eventTypeId);
+ mDeviceEventListener.processEvent(eventType, tunerSelect);
+ }
+ default -> {
+ throw new IllegalStateException("DeviceEventAdapter must be updated handle EventType." + eventType);
+ }
+ }
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/IDeviceEventListener.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/IDeviceEventListener.java
new file mode 100644
index 000000000..0c0d22863
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/IDeviceEventListener.java
@@ -0,0 +1,67 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.callback;
+
+import com.github.dsheirer.sdrplay.device.TunerSelect;
+import com.github.dsheirer.sdrplay.parameter.event.EventType;
+import com.github.dsheirer.sdrplay.parameter.event.GainCallbackParameters;
+import com.github.dsheirer.sdrplay.parameter.event.PowerOverloadCallbackParameters;
+import com.github.dsheirer.sdrplay.parameter.event.RspDuoModeCallbackParameters;
+
+/**
+ * Device event listener. Receives events for the device, impacting one or both (if equipped) tuners on the device.
+ */
+public interface IDeviceEventListener
+{
+ /**
+ * Process a device event
+ * @param eventType identifies the type of event
+ * @param tunerSelect identifies which tuner(s) are included in the event (A, B, BOTH, or NEITHER)
+ */
+ void processEvent(EventType eventType, TunerSelect tunerSelect);
+
+ /**
+ * Process a gain change event
+ * @param tunerSelect identifies which tuner(s) are included in the event (A, B, BOTH, or NEITHER)
+ * @param gainCallbackParameters containing event details
+ */
+ void processGainChange(TunerSelect tunerSelect, GainCallbackParameters gainCallbackParameters);
+
+ /**
+ * Process a power overload event
+ * @param tunerSelect identifies which tuner(s) are included in the event (A, B, BOTH, or NEITHER)
+ * @param parameters containing event details
+ */
+ void processPowerOverload(TunerSelect tunerSelect, PowerOverloadCallbackParameters parameters);
+
+ /**
+ * Process an RSP-Duo mode change event
+ * @param tunerSelect identifies which tuner(s) are included in the event (A, B, BOTH, or NEITHER)
+ * @param parameters containing event details
+ */
+ void processRspDuoModeChange(TunerSelect tunerSelect, RspDuoModeCallbackParameters parameters);
+
+ /**
+ * Process a device removed (ie unplugged) event
+ * @param tunerSelect identifies which tuner(s) are included in the event (A, B, BOTH, or NEITHER)
+ */
+ void processDeviceRemoval(TunerSelect tunerSelect);
+
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/IStreamCallbackListener.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/IStreamCallbackListener.java
new file mode 100644
index 000000000..14610ec57
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/IStreamCallbackListener.java
@@ -0,0 +1,32 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.callback;
+
+import com.github.dsheirer.sdrplay.device.TunerSelect;
+
+public interface IStreamCallbackListener
+{
+ /**
+ * Process stream callback parameters and reset value received over the stream callback interface.
+ * @param parameters to process
+ * @param reset value
+ */
+ void process(TunerSelect tunerSelect, StreamCallbackParameters parameters, int reset);
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/IStreamListener.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/IStreamListener.java
new file mode 100644
index 000000000..1360a73d3
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/IStreamListener.java
@@ -0,0 +1,45 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.callback;
+
+import com.github.dsheirer.sdrplay.device.TunerSelect;
+
+/**
+ * Stream Listener interface.
+ */
+public interface IStreamListener
+{
+ /**
+ * Process samples from a single stream of I/Q samples
+ * @param xi array of Inphase samples
+ * @param xq array of Quadrature samples
+ * @param streamCallbackParameters stream callback parameters
+ * @param reset indicates if a re-initialization has occurred within the API and that local buffering should be reset
+ */
+ void processStream(short[] xi, short[] xq, StreamCallbackParameters streamCallbackParameters,
+ boolean reset);
+
+ /**
+ * Indicates which tuner this stream listener is for. Note: this is used to manage asynchronous Updates to ensure
+ * that submitted updates get correctly mapped and resolved in the Device update manager.
+ * @return
+ */
+ TunerSelect getTunerSelect();
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/StreamCallbackAdapter.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/StreamCallbackAdapter.java
new file mode 100644
index 000000000..d21fee3ba
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/StreamCallbackAdapter.java
@@ -0,0 +1,108 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.callback;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_StreamCallback_t;
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_StreamCbParamsT;
+import com.github.dsheirer.sdrplay.util.Flag;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.ValueLayout;
+
+/**
+ * I/Q sample stream callback adapter. Implements the native interface and transfers the native callback data to an
+ * implementation of the Java IStreamListener interface.
+ */
+public class StreamCallbackAdapter implements sdrplay_api_StreamCallback_t
+{
+ private static final Logger mLog = LoggerFactory.getLogger(StreamCallbackAdapter.class);
+ private MemorySession mMemorySession;
+ private IStreamListener mStreamListener;
+ private IStreamCallbackListener mStreamCallbackListener;
+
+ /**
+ * Constructs an instance of the callback implementation
+ * @param memorySession for defining new foreign memory segments
+ * @param streamListener to receive transferred I/Q samples and event details
+ * @param listener to receive callback parameters
+ */
+ public StreamCallbackAdapter(MemorySession memorySession, IStreamListener streamListener,
+ IStreamCallbackListener listener)
+ {
+ if(memorySession == null)
+ {
+ throw new IllegalArgumentException("Resource scope must be non-null");
+ }
+
+ mMemorySession = memorySession;
+ mStreamCallbackListener = listener;
+ setListener(streamListener);
+ }
+
+ /**
+ * Updates the listener for receiving samples
+ * @param listener to receive stream samples
+ */
+ public void setListener(IStreamListener listener)
+ {
+ mStreamListener = listener;
+ }
+
+ /**
+ * Receives callback of foreign memory data, transfers it to Java, and passes to the listener.
+ * @param iSamplesPointer array foreign memory address
+ * @param qSamplesPointer array foreign memory address
+ * @param parametersPointer associated with the callback - foreign memory address
+ * @param sampleCount number of samples in each of the I and Q arrays
+ * @param reset 0 or 1, translated to a boolean
+ * @param deviceContext of the device that sourced the samples
+ */
+ @Override
+ public void apply(MemoryAddress iSamplesPointer, MemoryAddress qSamplesPointer, MemoryAddress parametersPointer,
+ int sampleCount, int reset, MemoryAddress deviceContext)
+ {
+ if(mStreamListener != null || mStreamCallbackListener != null)
+ {
+ //Translate the callback parameters pointer to a memory segment and re-construct the parameters as a Java object
+ StreamCallbackParameters parameters = new StreamCallbackParameters(sdrplay_api_StreamCbParamsT
+ .ofAddress(parametersPointer, mMemorySession));
+
+ if(mStreamCallbackListener != null)
+ {
+ mStreamCallbackListener.process(mStreamListener.getTunerSelect(), parameters, reset);
+ }
+
+ if(mStreamListener != null)
+ {
+ //Allocate memory segments from I/Q pointers, transfer from native to JVM array, and send to listener
+ long arrayByteSize = ValueLayout.JAVA_SHORT.byteSize() * sampleCount;
+ MemorySegment iSamples = MemorySegment.ofAddress(iSamplesPointer, arrayByteSize, mMemorySession);
+ MemorySegment qSamples = MemorySegment.ofAddress(qSamplesPointer, arrayByteSize, mMemorySession);
+ short[] i = iSamples.toArray(ValueLayout.JAVA_SHORT);
+ short[] q = qSamples.toArray(ValueLayout.JAVA_SHORT);
+ mStreamListener.processStream(i, q, parameters, Flag.evaluate(reset));
+ }
+ }
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/StreamCallbackParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/StreamCallbackParameters.java
new file mode 100644
index 000000000..a37952e0f
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/callback/StreamCallbackParameters.java
@@ -0,0 +1,89 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.callback;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_StreamCbParamsT;
+import com.github.dsheirer.sdrplay.util.Flag;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * Stream Callback Parameters structure (sdrplay_api_StreamCbParamsT)
+ */
+public class StreamCallbackParameters
+{
+ private int mFirstSampleNumber;
+ private boolean mGainReductionChanged;
+ private boolean mRfFrequencyChanged;
+ private boolean mSampleRateChanged;
+ private long mNumberSamples;
+
+ /**
+ * Constructs an instance from the foreign memory segment
+ */
+ public StreamCallbackParameters(MemorySegment memorySegment)
+ {
+ mFirstSampleNumber = sdrplay_api_StreamCbParamsT.firstSampleNum$get(memorySegment);
+ mGainReductionChanged = Flag.evaluate(sdrplay_api_StreamCbParamsT.grChanged$get(memorySegment));
+ mRfFrequencyChanged = Flag.evaluate(sdrplay_api_StreamCbParamsT.rfChanged$get(memorySegment));
+ mSampleRateChanged = Flag.evaluate(sdrplay_api_StreamCbParamsT.fsChanged$get(memorySegment));
+ mNumberSamples = sdrplay_api_StreamCbParamsT.numSamples$get(memorySegment);
+ }
+
+ /**
+ * First sample number
+ */
+ public int getFirstSampleNumber()
+ {
+ return mFirstSampleNumber;
+ }
+
+ /**
+ * Indicates if gain reduction value has changed
+ */
+ public boolean isGainReductionChanged()
+ {
+ return mGainReductionChanged;
+ }
+
+ /**
+ * Indicates if RF center frequency has changed
+ */
+ public boolean isRfFrequencyChanged()
+ {
+ return mRfFrequencyChanged;
+ }
+
+ /**
+ * Indicates if sample rate has changed
+ */
+ public boolean isSampleRateChanged()
+ {
+ return mSampleRateChanged;
+ }
+
+ /**
+ * Number of samples
+ */
+ public long getNumberSamples()
+ {
+ return mNumberSamples;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Decimate.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Decimate.java
new file mode 100644
index 000000000..d167f478d
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Decimate.java
@@ -0,0 +1,84 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+/**
+ * Software decimation rates supported by the API for SDRPlay RSP devices
+ */
+public enum Decimate
+{
+ X1(1, 16),
+ X2(2, 16),
+ X4(4, 17),
+ X8(8, 17),
+ X16(16, 18),
+ X32(32, 20);
+
+ private int mValue;
+ private int mSampleSize;
+
+ /**
+ * Constructs an instance
+ * @param value
+ * @param sampleSize in bits to represent effective dynamic range.
+ */
+ Decimate(int value, int sampleSize)
+ {
+ mValue = value;
+ mSampleSize = sampleSize;
+ }
+
+ /**
+ * Decimation value.
+ * @return
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Sample size in bits to represent effective dynamic range for the decimation value.
+ */
+ public int getSampleSize()
+ {
+ return mSampleSize;
+ }
+
+ /**
+ * Indicates if software decimation is enabled.
+ * @return true for all values except X1.
+ */
+ public boolean isEnabled()
+ {
+ return !this.equals(X1);
+ }
+
+ @Override
+ public String toString()
+ {
+ if(this.equals(X1))
+ {
+ return "None";
+ }
+
+ return "x" + getValue();
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Device.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Device.java
new file mode 100644
index 000000000..dfd95f7f8
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Device.java
@@ -0,0 +1,696 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.Status;
+import com.github.dsheirer.sdrplay.UpdateReason;
+import com.github.dsheirer.sdrplay.async.AsyncUpdateFuture;
+import com.github.dsheirer.sdrplay.async.CompletedAsyncUpdate;
+import com.github.dsheirer.sdrplay.callback.IDeviceEventListener;
+import com.github.dsheirer.sdrplay.callback.IStreamCallbackListener;
+import com.github.dsheirer.sdrplay.callback.IStreamListener;
+import com.github.dsheirer.sdrplay.callback.StreamCallbackParameters;
+import com.github.dsheirer.sdrplay.error.DebugLevel;
+import com.github.dsheirer.sdrplay.parameter.composite.CompositeParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.IfMode;
+import com.github.dsheirer.sdrplay.parameter.tuner.LoMode;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract device structure (sdrplay_api_DeviceT)
+ */
+public abstract class Device, R extends RspTuner,?>>
+{
+ private static final Logger mLog = LoggerFactory.getLogger(Device.class);
+
+ private SDRplay mSDRplay;
+ private final UpdateRequestManager mUpdateRequestManager = new UpdateRequestManager();
+ private final IDeviceStruct mDeviceStruct;
+ protected boolean mSelected = false;
+ protected boolean mInitialized = false;
+ private T mCompositeParameters;
+
+ /**
+ * Constructs an SDRPlay device from the foreign memory segment
+ * @param sdrPlay api instance that created this device
+ * @param deviceStruct to parse or access the fields of the device structure
+ */
+ public Device(SDRplay sdrPlay, IDeviceStruct deviceStruct)
+ {
+ mSDRplay = sdrPlay;
+ mDeviceStruct = deviceStruct;
+ }
+
+ /**
+ * Version specific device structure parser
+ */
+ protected IDeviceStruct getDeviceStruct()
+ {
+ return mDeviceStruct;
+ }
+
+ /**
+ * API that owns this device
+ */
+ protected SDRplay getAPI()
+ {
+ return mSDRplay;
+ }
+
+ /**
+ * Stream callback listener for parameter change events.
+ */
+ public IStreamCallbackListener getStreamCallbackListener()
+ {
+ return mUpdateRequestManager;
+ }
+
+ /**
+ * Loads the device parameters for this device. Subsequent calls once the parameters are created are ignored.
+ * @throws SDRPlayException if the device is not selected or if there is an issue loading the parameters
+ */
+ private void loadDeviceParameters() throws SDRPlayException
+ {
+ if(selected())
+ {
+ mCompositeParameters = (T)getAPI().getCompositeParameters(getDeviceType(), getDeviceHandle());
+ }
+ }
+
+ /**
+ * Sets the debug logging level for this device.
+ * @param debugLevel to set
+ */
+ public void setDebugLevel(DebugLevel debugLevel)
+ {
+ try
+ {
+ mSDRplay.setDebugLevel(getDeviceHandle(), debugLevel);
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.info("Unable to set debug level [" + debugLevel + "] for device - not selected", se);
+ }
+ }
+
+ /**
+ * Selects this device for exclusive use and loads the device composite parameters.
+ * @throws SDRPlayException if unable to select the device or if unable to load the composite parameters for use.
+ */
+ public void select() throws SDRPlayException
+ {
+ if(!selected())
+ {
+ getAPI().select(getDeviceMemorySegment());
+ mSelected = true;
+ loadDeviceParameters();
+ }
+ }
+
+ /**
+ * Indicates if this device has been selected via the SDRplay api
+ */
+ protected boolean selected()
+ {
+ return mSelected;
+ }
+
+ /**
+ * Indicates if the device is valid and ready for use
+ */
+ public boolean isValid()
+ {
+ return getDeviceStruct().isValid();
+ }
+
+ /**
+ * Releases this device from exclusive use.
+ */
+ public void release() throws SDRPlayException
+ {
+ if(selected())
+ {
+ mSelected = false;
+ getAPI().release(getDeviceMemorySegment());
+ }
+ }
+
+ /**
+ * Indicates if this device is initialized for use
+ */
+ public boolean isInitialized()
+ {
+ return mInitialized;
+ }
+
+ /**
+ * Initializes this device for single-tuner use and starts the tuner providing raw signal samples to the stream
+ * listener and device events to the event listener.
+ *
+ * Note: invoke select() to select this device for exclusive use before invoking this method. If this device has
+ * previously been initialized, an exception is thrown. Use uninit() to uninitialize this device and stop the
+ * sample stream and event notifications.
+ *
+ * @param eventListener to receive device event notifications
+ * @param streamListener to receive samples from stream. Stream is from either Tuner 1 or Tuner 2 when
+ * the device is selected for single-tuner mode.
+ * @throws SDRPlayException if there is an error
+ */
+ public void initStreamA(IDeviceEventListener eventListener, IStreamListener streamListener) throws SDRPlayException
+ {
+ if(!isSelected())
+ {
+ throw new SDRPlayException("Device must be selected before it can be initialized");
+ }
+
+ if(isInitialized())
+ {
+ throw new SDRPlayException("Device has already been initialized with listeners");
+ }
+
+ getAPI().initA(Device.this, getDeviceHandle(), eventListener, streamListener);
+ mInitialized = true;
+ }
+
+ /**
+ * Initializes this device for dual-tuner stream B use and starts the tuner providing raw signal samples to the stream
+ * listener and device events to the event listener.
+ *
+ * Note: invoke select() to select this device for exclusive use before invoking this method. If this device has
+ * previously been initialized, an exception is thrown. Use uninit() to uninitialize this device and stop the
+ * sample stream and event notifications.
+ *
+ * @param eventListener to receive device event notifications
+ * @param streamListener to receive samples from stream. Stream is from either Tuner 1 or Tuner 2 when
+ * the device is selected for single-tuner mode.
+ * @throws SDRPlayException if there is an error
+ */
+ public void initStreamB(IDeviceEventListener eventListener, IStreamListener streamListener) throws SDRPlayException
+ {
+ if(!isSelected())
+ {
+ throw new SDRPlayException("Device must be selected before it can be initialized");
+ }
+
+ if(isInitialized())
+ {
+ throw new SDRPlayException("Device has already been initialized with listeners");
+ }
+
+ getAPI().initB(Device.this, getDeviceHandle(), eventListener, streamListener);
+ mInitialized = true;
+ }
+
+ /**
+ * Uninitializes this device from use. Note: call is ignored if this device hasn't been initialized
+ * @throws SDRPlayException if there is an error
+ */
+ public void uninitialize() throws SDRPlayException
+ {
+ if(isInitialized())
+ {
+ getAPI().uninit(getDeviceHandle());
+ mInitialized = false;
+ }
+ else
+ {
+ throw new SDRPlayException("Attempt to uninit a device that has not been initialized previously");
+ }
+ }
+
+ /**
+ * Updates this device after parameter change, only when the device is initialized. If the device is not yet
+ * initialized, the update request is ignored.
+ *
+ * @throws SDRPlayException if unable to apply updates
+ */
+ public void update(TunerSelect tunerSelect, UpdateReason ... updateReasons) throws SDRPlayException
+ {
+ if(isInitialized())
+ {
+ submitUpdate(tunerSelect, updateReasons);
+ }
+ }
+
+ private String toString(UpdateReason ... updateReasons)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ boolean first = true;
+
+ for(UpdateReason updateReason: updateReasons)
+ {
+ if(first)
+ {
+ sb.append("[");
+ }
+ else
+ {
+ sb.append(", ");
+ }
+
+ sb.append(updateReason.name());
+
+ first = false;
+ }
+
+ sb.append("]");
+
+ return sb.toString();
+ }
+
+ /**
+ * Asynchronous update request. This method should only be used for Frequency, Gain and Sample Rate updates.
+ * @param tunerSelect tuner being updated
+ * @param updateReason for the parameter that is being updated
+ * @param expectedResponse that is one of Gain, Frequency, or Sample Rate.
+ * @return a future that has already been completed, or if initialized a future that will be completed.
+ */
+ protected AsyncUpdateFuture updateAsync(TunerSelect tunerSelect, UpdateReason updateReason, UpdateReason expectedResponse)
+ {
+ if(!expectedResponse.isAsyncUpdateResponse())
+ {
+ throw new IllegalArgumentException("Invalid expected response: " + expectedResponse +
+ ". Valid values are: " + UpdateReason.ASYNC_UPDATE_RESPONSES);
+ }
+
+ if(isInitialized())
+ {
+ return mUpdateRequestManager.update(tunerSelect, updateReason, expectedResponse);
+ }
+
+ //If not initialized, return success.
+ AsyncUpdateFuture future = new AsyncUpdateFuture(tunerSelect, updateReason, expectedResponse);
+ future.setResult(Status.SUCCESS);
+ return future;
+ }
+
+ /**
+ * Submits an update request to the API. This method is used/managed by the update request manager.
+ * @param tunerSelect for the update
+ * @param updateReasons to apply
+ * @throws SDRPlayException if there is an issue.
+ */
+ private void submitUpdate(TunerSelect tunerSelect, UpdateReason ... updateReasons) throws SDRPlayException
+ {
+ getAPI().update(Device.this, getDeviceHandle(), tunerSelect, updateReasons);
+ }
+
+ /**
+ * Acknowledge tuner power overload events
+ * @param tunerSelect identifying which tuner(s)
+ * @throws SDRPlayException on error
+ */
+ public void acknowledgePowerOverload(TunerSelect tunerSelect) throws SDRPlayException
+ {
+// mLog.info("Acknowledging power overload message for tuner [" + tunerSelect + "]");
+
+ //There's a bug (feature?) in the API ... when you un-initialize the device, it causes a power overload event
+ // and if you acknowledge it, you get an error that the device is not initialized.
+ if(isInitialized())
+ {
+ try
+ {
+ update(tunerSelect, UpdateReason.CONTROL_OVERLOAD_MESSAGE_ACK);
+ }
+ catch(SDRPlayException se)
+ {
+ //Ignore the not initialized exception that can happen when shutting down the receiver, otherwise
+ //rethrow the exception.
+ if(se.getStatus() != Status.NOT_INITIALIZED)
+ {
+ throw se;
+ }
+ }
+ }
+ }
+
+ /**
+ * Tuner selection.
+ * @return tuner select. Defaults to TUNER_1 for all but the RSPduo where it is overridden for tuner 2.
+ */
+ public TunerSelect getTunerSelect()
+ {
+ return TunerSelect.TUNER_1;
+ }
+
+ /**
+ * Foreign memory segment representing this device.
+ */
+ protected MemorySegment getDeviceMemorySegment()
+ {
+ return getDeviceStruct().getDeviceMemorySegment();
+ }
+
+ /**
+ * Handle to this device.
+ *
+ * Note: this device must be selected for exclusive use before you can access this handle.
+ *
+ * @throws SDRPlayException if this method is accessed before the device has been successfully selected
+ */
+ MemoryAddress getDeviceHandle() throws SDRPlayException
+ {
+ if(!selected())
+ {
+ throw new SDRPlayException("This device must be selected for exclusive use before accessing/using the " +
+ "device handle");
+ }
+
+ return getDeviceStruct().getDeviceHandle();
+ }
+
+ /**
+ * Tuner for this device
+ * @return tuner appropriate for the device type
+ * @throws SDRPlayException for various reasons include device not selected or API unavailable
+ */
+ public abstract R getTuner() throws SDRPlayException;
+
+ /**
+ * Composite parameters for this device
+ */
+ public T getCompositeParameters()
+ {
+ return mCompositeParameters;
+ }
+
+ /**
+ * Indicates if this device has composite parameters
+ */
+ public boolean hasCompositeParameters()
+ {
+ return mCompositeParameters != null;
+ }
+
+ /**
+ * Indicates if this device is available and has been selected for exclusive use.
+ */
+ public boolean isSelected()
+ {
+ return mSelected;
+ }
+
+ /**
+ * Device type
+ */
+ public DeviceType getDeviceType()
+ {
+ return getDeviceStruct().getDeviceType();
+ }
+
+ /**
+ * Serial number
+ */
+ public String getSerialNumber()
+ {
+ return getDeviceStruct().getSerialNumber();
+ }
+
+ /**
+ * Current sample rate
+ */
+ public double getSampleRate()
+ {
+ return getCompositeParameters().getDeviceParameters().getSamplingFrequency().getSampleRate();
+ }
+
+ public void setIfMode(IfMode ifMode)
+ {
+ getCompositeParameters().getTunerAParameters().setIfMode(ifMode);
+ }
+
+ public void setLoMode(LoMode loMode)
+ {
+ getCompositeParameters().getTunerAParameters().setLoMode(loMode);
+ }
+
+ /**
+ * Enables or disables wideband signal mode. This should be set according to the IFMode, where IFMode.ZERO is
+ * wideband and all others are not wideband.
+ * @param enable
+ */
+ public void setWidebandSignal(boolean enable) throws SDRPlayException
+ {
+ getCompositeParameters().getControlAParameters().getDecimation().setWideBandSignal(enable);
+
+ if(isInitialized())
+ {
+ update(getTunerSelect(), UpdateReason.CONTROL_DECIMATION);
+ }
+ }
+
+ /**
+ * Sets the software-based decimation factor for the final sample rate.
+ * @param decimate value where X1 is no decimation and all others are decimation enabled values.
+ * @throws SDRPlayException if there is an error while setting decimation
+ */
+ public void setDecimation(Decimate decimate) throws SDRPlayException
+ {
+ getCompositeParameters().getControlAParameters().getDecimation().setDecimationFactor(decimate.getValue());
+ getCompositeParameters().getControlAParameters().getDecimation().setEnabled(decimate.isEnabled());
+
+ if(isInitialized())
+ {
+ update(getTunerSelect(), UpdateReason.CONTROL_DECIMATION);
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("SDRPplay Device").append("\n");
+ sb.append("\tType: ").append(getDeviceType()).append("\n");
+ sb.append("\tSerial Number: ").append(getSerialNumber()).append("\n");
+ sb.append("\tSelected: ").append(isSelected());
+ if(hasCompositeParameters())
+ {
+ sb.append("\t").append(getCompositeParameters());
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Thread-safe manager for asynchronous update request queue processing for an initialized RSP device.
+ *
+ * Once a device has been initialized, any changes to frequency, gain or sample rate require submitting an update
+ * request to the device to apply the parameter change(s). However, since the API supports non-blocking operation,
+ * the operation executes asynchronously. The API supports only a single update request operation
+ * to be in-progress at a time and any overlapping update requests are met with an unsuccessful status code return
+ * from the update method.
+ */
+ class UpdateRequestManager implements IStreamCallbackListener
+ {
+ private static final long UPDATE_QUEUE_PROCESSING_INTERVAL_MS = 75;
+ private final ScheduledExecutorService mExecutorService = Executors.newSingleThreadScheduledExecutor();
+ private final Queue mUpdateQueue = new ConcurrentLinkedQueue();
+ private final Queue mCompletedUpdateQueue = new ConcurrentLinkedQueue();
+ private final ReentrantLock mLock = new ReentrantLock();
+
+ /**
+ * Submits an update request for the specified tuner and update reason for queued processing. This is a
+ * non-blocking operation and the update is performed by a thread from the thread pool.
+ * @param tunerSelect to apply the update
+ * @param updateReason to update
+ * @return an asynchronous future to monitor the progress of the update request
+ */
+ public AsyncUpdateFuture update(TunerSelect tunerSelect, UpdateReason updateReason, UpdateReason expectedResponse)
+ {
+ AsyncUpdateFuture future = new AsyncUpdateFuture(tunerSelect, updateReason, expectedResponse);
+ mUpdateQueue.add(future);
+ processQueuesImmediately();
+ return future;
+ }
+
+ /**
+ * Schedules a process queues task for immediate execution. Non-blocking.
+ */
+ private void processQueuesImmediately()
+ {
+ processQueuesAfterDelay(0);
+ }
+
+ /**
+ * Schedules a process queues task after the delay. Non-blocking
+ * @param delay in milliseconds, or zero for immediate.
+ */
+ private void processQueuesAfterDelay(long delay)
+ {
+ mExecutorService.schedule(() -> processQueues(), delay, TimeUnit.MILLISECONDS);
+ }
+
+ /**
+ * Processes the pending and completed update operation queues. Submits new update requests one at a time and
+ * awaits a stream callback notification that the matching update reason has been applied/updated. Ensures
+ * that only a single update operation is in-progress at any given time.
+ */
+ private synchronized void processQueues()
+ {
+ mLock.lock();
+
+ try
+ {
+ if(mUpdateQueue.isEmpty())
+ {
+ //If we have no pending updates, we don't care about any completed update results
+ mCompletedUpdateQueue.clear();
+ }
+ else
+ {
+ boolean processing = true;
+
+ while(processing)
+ {
+ processing = false;
+
+ AsyncUpdateFuture futureUpdate = mUpdateQueue.peek();
+
+ if(futureUpdate != null)
+ {
+ if(futureUpdate.isSubmitted())
+ {
+ //Process the completion queue
+ while(!mCompletedUpdateQueue.isEmpty())
+ {
+ CompletedAsyncUpdate completedUpdate = mCompletedUpdateQueue.poll();
+
+ if(completedUpdate != null)
+ {
+ if(futureUpdate.matches(completedUpdate))
+ {
+ //Clear the remaining completed updates
+ mCompletedUpdateQueue.clear();
+
+ //Remove and (successfully) complete the current future
+ mUpdateQueue.remove();
+ futureUpdate.setResult(Status.SUCCESS);
+
+ //Signal to immediately reprocess the queue
+ processing = true;
+
+ //Break out of the completed update queue processing
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ //Clear the completed queue and submit the update
+ mCompletedUpdateQueue.clear();
+
+ try
+ {
+ submitUpdate(futureUpdate.getTunerSelect(), futureUpdate.getUpdateReason());
+ futureUpdate.setSubmitted(true);
+ }
+ catch(SDRPlayException se)
+ {
+ futureUpdate = mUpdateQueue.poll();
+ futureUpdate.setError(se);
+ //Set continuous to true to immediately reprocess the next update
+ processing = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ finally
+ {
+ mLock.unlock();
+ }
+
+ if(!mUpdateQueue.isEmpty())
+ {
+ processQueuesAfterDelay(UPDATE_QUEUE_PROCESSING_INTERVAL_MS);
+ }
+ }
+
+ /**
+ * Receives an update completion event. This is a non-blocking operation since this method will be invoked
+ * by the stream callback thread, and we don't want to impact the delivery of streaming samples or events.
+ *
+ * @param tunerSelect tuner that was updated
+ * @param updateReason for what was updated
+ */
+ public void completed(TunerSelect tunerSelect, UpdateReason updateReason)
+ {
+ mCompletedUpdateQueue.add(new CompletedAsyncUpdate(tunerSelect, updateReason));
+ mExecutorService.schedule(this::processQueues, 0, TimeUnit.MILLISECONDS);
+ }
+
+ /**
+ * Resets the update queue.
+ */
+ public void reset()
+ {
+ mLock.lock();
+
+ try
+ {
+ while(!mUpdateQueue.isEmpty())
+ {
+ AsyncUpdateFuture future = mUpdateQueue.poll();
+ future.setResult(Status.UNKNOWN);
+ }
+ }
+ finally
+ {
+ mLock.unlock();
+ }
+ }
+
+ /**
+ * Implements the IStreamCallbackListener interface to receive change notifications from update requests.
+ * @param parameters to process
+ * @param reset value with flags
+ */
+ @Override
+ public void process(TunerSelect tunerSelect, StreamCallbackParameters parameters, int reset)
+ {
+ if(parameters.isSampleRateChanged())
+ {
+ completed(tunerSelect, UpdateReason.DEVICE_SAMPLE_RATE);
+ }
+ if(parameters.isRfFrequencyChanged())
+ {
+ completed(tunerSelect, UpdateReason.TUNER_FREQUENCY_RF);
+ }
+ if(parameters.isGainReductionChanged())
+ {
+ completed(tunerSelect, UpdateReason.TUNER_GAIN_REDUCTION);
+ }
+ }
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/DeviceFactory.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/DeviceFactory.java
new file mode 100644
index 000000000..1d3cc4cf8
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/DeviceFactory.java
@@ -0,0 +1,163 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.Version;
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_DeviceT;
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.SegmentAllocator;
+import java.util.ArrayList;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Factory methods for creating new RSP Device instances
+ */
+public class DeviceFactory
+{
+ private static final Logger mLog = LoggerFactory.getLogger(DeviceFactory.class);
+
+ /**
+ * Creates a foreign memory segment for a DeviceT array, appropriate for the specified version.
+ * @param version value
+ * @param segmentAllocator to allocate the foreign memory
+ * @return devices array
+ */
+ public static MemorySegment createDeviceArray(Version version, SegmentAllocator segmentAllocator)
+ {
+ if(version.gte(Version.V3_08))
+ {
+ return com.github.dsheirer.sdrplay.api.v3_08.sdrplay_api_DeviceT.allocateArray(sdrplay_api_h.SDRPLAY_MAX_DEVICES(), segmentAllocator);
+ }
+ else if(version == Version.V3_07)
+ {
+ return sdrplay_api_DeviceT.allocateArray(sdrplay_api_h.SDRPLAY_MAX_DEVICES(), segmentAllocator);
+ }
+
+ throw new IllegalArgumentException("Unrecognized version: " + version);
+ }
+
+ /**
+ * Parses device information from a list of device structures
+ * @param deviceStructs representing devices to parse
+ * @return a list of device infos
+ */
+ public static List parseDeviceInfos(List deviceStructs)
+ {
+ List deviceInfos = new ArrayList<>();
+
+ for(IDeviceStruct deviceStruct: deviceStructs)
+ {
+ deviceInfos.add(new DeviceInfo(deviceStruct));
+ }
+
+ return deviceInfos;
+ }
+
+ /**
+ * Parses device information from a memory segment containing an array of device structures.
+ * @param version of the API
+ * @param devicesArray memory segment
+ * @param count of device structures in the devicesArray.
+ * @return a list of device infos
+ * @throws exception if version is unrecognized or unsupported
+ */
+ public static List parseDeviceStructs(Version version, MemorySegment devicesArray, int count) throws SDRPlayException
+ {
+ List deviceStructs = new ArrayList<>();
+
+ if(version.gte(Version.V3_08))
+ {
+ devicesArray.elements(com.github.dsheirer.sdrplay.api.v3_08.sdrplay_api_DeviceT.$LAYOUT())
+ .limit(count).forEach(memorySegment ->
+ deviceStructs.add(DeviceFactory.createDeviceStruct(version, memorySegment)));
+ }
+ else if(version == Version.V3_07)
+ {
+ devicesArray.elements(sdrplay_api_DeviceT.$LAYOUT()).limit(count).forEach(memorySegment ->
+ {
+ deviceStructs.add(DeviceFactory.createDeviceStruct(version, memorySegment));
+ });
+ }
+ else
+ {
+ throw new SDRPlayException("Unrecognized version: " + version);
+ }
+
+ return deviceStructs;
+ }
+
+ /**
+ * Creates an SDRplay device from the foreign memory Device instance.
+ * @param sdrPlay for device callback support
+ * @param deviceMemorySegment instance for the device
+ * @return correctly typed device
+ */
+ public static Device createDevice(SDRplay sdrPlay, IDeviceStruct deviceStruct)
+ {
+ switch(deviceStruct.getDeviceType())
+ {
+ case RSP1 -> {
+ return new Rsp1Device(sdrPlay, deviceStruct);
+ }
+ case RSP1A -> {
+ return new Rsp1aDevice(sdrPlay, deviceStruct);
+ }
+ case RSP2 -> {
+ return new Rsp2Device(sdrPlay, deviceStruct);
+ }
+ case RSPduo -> {
+ return new RspDuoDevice(sdrPlay, deviceStruct);
+ }
+ case RSPdx -> {
+ return new RspDxDevice(sdrPlay, deviceStruct);
+ }
+ default -> {
+ return new UnknownDevice(sdrPlay, deviceStruct);
+ }
+ }
+ }
+
+ /**
+ * Creates a device structure parser for the specified API version
+ * @param version to create
+ * @param deviceMemorySegment for the device
+ * @return device structure
+ */
+ private static IDeviceStruct createDeviceStruct(Version version, MemorySegment deviceMemorySegment)
+ {
+ if(version == Version.V3_07)
+ {
+ return new DeviceStruct_v3_07(deviceMemorySegment);
+ }
+ else if(version.gte(Version.V3_08))
+ {
+ return new DeviceStruct_v3_08(deviceMemorySegment);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Unsupported version: " + version);
+ }
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/DeviceInfo.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/DeviceInfo.java
new file mode 100644
index 000000000..977533c35
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/DeviceInfo.java
@@ -0,0 +1,140 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.DeviceSelectionMode;
+import java.util.Objects;
+import org.apache.commons.lang3.Validate;
+
+/**
+ * RSP device information to support device selection.
+ */
+public class DeviceInfo
+{
+ private DeviceSelectionMode mDeviceSelectionMode = DeviceSelectionMode.SINGLE_TUNER_1;
+ private DeviceType mDeviceType;
+ private String mSerialNumber;
+
+ /**
+ * Constructs an instance
+ * @param deviceType of the RSP device
+ * @param serialNumber for the device
+ */
+ public DeviceInfo(DeviceType deviceType, String serialNumber)
+ {
+ Validate.notNull(deviceType, "Device type cannot be null");
+ Validate.notNull(serialNumber, "Device serial number cannot be null");
+
+ mDeviceType = deviceType;
+ mSerialNumber = serialNumber;
+ }
+
+ /**
+ * Alternate constructor where we get the parameters from a device structure.
+ * @param deviceStruct containing device type and serial number values.
+ */
+ public DeviceInfo(IDeviceStruct deviceStruct)
+ {
+ this(deviceStruct.getDeviceType(), deviceStruct.getSerialNumber());
+ }
+
+ /**
+ * Device type for this RSP device
+ * @return type
+ */
+ public DeviceType getDeviceType()
+ {
+ return mDeviceType;
+ }
+
+ /**
+ * Serial number for this RSP device
+ * @return serial number
+ */
+ public String getSerialNumber()
+ {
+ return mSerialNumber;
+ }
+
+ /**
+ * Device selection mode for this RSP device
+ * @return device selection mode where single tuner 1 is default
+ */
+ public DeviceSelectionMode getDeviceSelectionMode()
+ {
+ return mDeviceSelectionMode;
+ }
+
+ /**
+ * Sets the device selection mode. This should be left as default of single tuner 1 unless this device is an RSPduo.
+ * @param deviceSelectionMode to use for this device.
+ */
+ public void setDeviceSelectionMode(DeviceSelectionMode deviceSelectionMode)
+ {
+ Validate.notNull(deviceSelectionMode, "Device selection mode cannot be null");
+ mDeviceSelectionMode = deviceSelectionMode;
+ }
+
+ /**
+ * Clones this instance
+ * @return deep copy.
+ */
+ public DeviceInfo clone()
+ {
+ return new DeviceInfo(mDeviceType, mSerialNumber);
+ }
+
+ /**
+ * Indicates if this device type and serial number matches the details of the device structure.
+ * @param deviceStruct to compare
+ * @return true if the device type and serial number match.
+ */
+ public boolean matches(IDeviceStruct deviceStruct)
+ {
+ return deviceStruct != null && getDeviceType().equals(deviceStruct.getDeviceType()) && getSerialNumber().equals(deviceStruct.getSerialNumber());
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Device: " + getDeviceType() + " Serial Number: " + getSerialNumber() + " Selection Mode: " + getDeviceSelectionMode();
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if(this == o)
+ {
+ return true;
+ }
+ if(o == null || getClass() != o.getClass())
+ {
+ return false;
+ }
+ DeviceInfo that = (DeviceInfo) o;
+ return mDeviceSelectionMode == that.mDeviceSelectionMode && mDeviceType == that.mDeviceType && mSerialNumber.equals(that.mSerialNumber);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(mDeviceSelectionMode, mDeviceType, mSerialNumber);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/DeviceStruct_v3_07.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/DeviceStruct_v3_07.java
new file mode 100644
index 000000000..906f47c63
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/DeviceStruct_v3_07.java
@@ -0,0 +1,100 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_DeviceT;
+
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+
+/**
+ * sdrplay_api_DeviceT structure parser for API version 3.07
+ */
+public class DeviceStruct_v3_07 implements IDeviceStruct
+{
+ private MemorySegment mDeviceMemorySegment;
+ private DeviceType mDeviceType;
+ private String mSerialNumber;
+
+ /**
+ * Constructs an instance
+ * @param deviceMemorySegment of foreign memory
+ */
+ public DeviceStruct_v3_07(MemorySegment deviceMemorySegment)
+ {
+ mDeviceMemorySegment = deviceMemorySegment;
+ mDeviceType = DeviceType.fromValue(0xFF & sdrplay_api_DeviceT.hwVer$get(mDeviceMemorySegment));
+ MemorySegment serialSegment = sdrplay_api_DeviceT.SerNo$slice(mDeviceMemorySegment);
+ mSerialNumber = serialSegment.getUtf8String(0);
+ }
+
+ @Override public MemorySegment getDeviceMemorySegment()
+ {
+ return mDeviceMemorySegment;
+ }
+
+ @Override public String getSerialNumber()
+ {
+ return mSerialNumber;
+ }
+
+ @Override public DeviceType getDeviceType()
+ {
+ return mDeviceType;
+ }
+
+ @Override public TunerSelect getTunerSelect()
+ {
+ return TunerSelect.fromValue(sdrplay_api_DeviceT.tuner$get(getDeviceMemorySegment()));
+ }
+
+ @Override public RspDuoMode getRspDuoMode()
+ {
+ return RspDuoMode.fromValue(sdrplay_api_DeviceT.rspDuoMode$get(getDeviceMemorySegment()));
+ }
+
+ @Override
+ public void setRspDuoMode(RspDuoMode mode)
+ {
+ sdrplay_api_DeviceT.rspDuoMode$set(getDeviceMemorySegment(), mode.getValue());
+ }
+
+ @Override public boolean isValid()
+ {
+ //Always returns true for version 3.07
+ return true;
+ }
+
+ @Override public double getRspDuoSampleFrequency()
+ {
+ return sdrplay_api_DeviceT.rspDuoSampleFreq$get(getDeviceMemorySegment());
+ }
+
+ @Override
+ public void setRspDuoSampleFrequency(double frequency)
+ {
+ sdrplay_api_DeviceT.rspDuoSampleFreq$set(getDeviceMemorySegment(), frequency);
+ }
+
+ @Override public MemoryAddress getDeviceHandle()
+ {
+ return sdrplay_api_DeviceT.dev$get(getDeviceMemorySegment());
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/DeviceStruct_v3_08.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/DeviceStruct_v3_08.java
new file mode 100644
index 000000000..d113e1966
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/DeviceStruct_v3_08.java
@@ -0,0 +1,100 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.api.v3_08.sdrplay_api_DeviceT;
+
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+
+/**
+ * sdrplay_api_DeviceT structure parser for API version 3.07
+ */
+public class DeviceStruct_v3_08 implements IDeviceStruct
+{
+ private MemorySegment mDeviceMemorySegment;
+ private DeviceType mDeviceType;
+ private String mSerialNumber;
+
+ /**
+ * Constructs an instance
+ * @param deviceMemorySegment of foreign memory
+ */
+ public DeviceStruct_v3_08(MemorySegment deviceMemorySegment)
+ {
+ mDeviceMemorySegment = deviceMemorySegment;
+ mDeviceType = DeviceType.fromValue(0xFF & sdrplay_api_DeviceT.hwVer$get(mDeviceMemorySegment));
+ MemorySegment serialSegment = sdrplay_api_DeviceT.SerNo$slice(mDeviceMemorySegment);
+ mSerialNumber = serialSegment.getUtf8String(0);
+ }
+
+ @Override public MemorySegment getDeviceMemorySegment()
+ {
+ return mDeviceMemorySegment;
+ }
+
+ @Override public String getSerialNumber()
+ {
+ return mSerialNumber;
+ }
+
+ @Override public DeviceType getDeviceType()
+ {
+ return mDeviceType;
+ }
+
+ @Override public TunerSelect getTunerSelect()
+ {
+ return TunerSelect.fromValue(sdrplay_api_DeviceT.tuner$get(getDeviceMemorySegment()));
+ }
+
+ @Override public RspDuoMode getRspDuoMode()
+ {
+ return RspDuoMode.fromValue(sdrplay_api_DeviceT.rspDuoMode$get(getDeviceMemorySegment()));
+ }
+
+ @Override
+ public void setRspDuoMode(RspDuoMode mode)
+ {
+ sdrplay_api_DeviceT.rspDuoMode$set(getDeviceMemorySegment(), mode.getValue());
+ }
+
+ @Override public boolean isValid()
+ {
+ //Always returns true for version 3.07
+ return true;
+ }
+
+ @Override public double getRspDuoSampleFrequency()
+ {
+ return sdrplay_api_DeviceT.rspDuoSampleFreq$get(getDeviceMemorySegment());
+ }
+
+ @Override
+ public void setRspDuoSampleFrequency(double frequency)
+ {
+ sdrplay_api_DeviceT.rspDuoSampleFreq$set(getDeviceMemorySegment(), frequency);
+ }
+
+ @Override public MemoryAddress getDeviceHandle()
+ {
+ return sdrplay_api_DeviceT.dev$get(getDeviceMemorySegment());
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/DeviceType.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/DeviceType.java
new file mode 100644
index 000000000..43798f08a
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/DeviceType.java
@@ -0,0 +1,76 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * RSP Device type
+ */
+public enum DeviceType
+{
+ RSP1(sdrplay_api_h.SDRPLAY_RSP1_ID(), "RSP1"),
+ RSP1A(sdrplay_api_h.SDRPLAY_RSP1A_ID(), "RSP1A"),
+ RSP2(sdrplay_api_h.SDRPLAY_RSP2_ID(), "RSP2"),
+ RSPduo(sdrplay_api_h.SDRPLAY_RSPduo_ID(), "RSPduo"),
+ RSPdx(sdrplay_api_h.SDRPLAY_RSPdx_ID(), "RSPdx"),
+ UNKNOWN(Integer.MIN_VALUE, "UNKNOWN");
+
+ private int mValue;
+ private String mDescription;
+
+ DeviceType(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or UNKNOWN if the code is not recognized
+ */
+ public static DeviceType fromValue(int value)
+ {
+ for(DeviceType status: DeviceType.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return UNKNOWN;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/IDeviceStruct.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/IDeviceStruct.java
new file mode 100644
index 000000000..c8d16ec2a
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/IDeviceStruct.java
@@ -0,0 +1,81 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+
+/**
+ * Interface for parsing and accessing the fields of the sdrplay_api_DeviceT structure across
+ * various versions.
+ */
+public interface IDeviceStruct
+{
+ /**
+ * Foreign memory segment for this device structure
+ */
+ MemorySegment getDeviceMemorySegment();
+
+ /**
+ * Serial number of the device
+ */
+ String getSerialNumber();
+
+ /**
+ * Indicates the device type, or model of RSP
+ */
+ DeviceType getDeviceType();
+
+ /**
+ * Indicates single, dual, or master/slave mode for the tuner.
+ */
+ TunerSelect getTunerSelect();
+
+ /**
+ * RSPduo mode
+ */
+ RspDuoMode getRspDuoMode();
+
+ /**
+ * Sets the RSPduo mode
+ * @param mode to set
+ */
+ void setRspDuoMode(RspDuoMode mode);
+
+ /**
+ * Indicates if the device is valid and ready for use (V3.08 and later)
+ */
+ boolean isValid();
+
+ /**
+ * Sample frequency/rate for the RSPduo when in master/slave mode
+ */
+ double getRspDuoSampleFrequency();
+
+ /**
+ * Sets the sample frequency/rate for the RSPduo when in master (only) mode.
+ */
+ void setRspDuoSampleFrequency(double frequency);
+
+ /**
+ * Device handle. Note this is only available if the device has been selected.
+ */
+ MemoryAddress getDeviceHandle();
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp1Device.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp1Device.java
new file mode 100644
index 000000000..07c8940e5
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp1Device.java
@@ -0,0 +1,61 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.parameter.composite.Rsp1CompositeParameters;
+
+/**
+ * RSP1 Device
+ */
+public class Rsp1Device extends Device
+{
+ private Rsp1Tuner mTuner1;
+
+ /**
+ * Constructs an SDRPlay RSP1 device from the foreign memory segment
+ *
+ * @param sdrPlay api instance that created this device
+ * @param deviceStruct parser
+ */
+ Rsp1Device(SDRplay sdrPlay, IDeviceStruct deviceStruct)
+ {
+ super(sdrPlay, deviceStruct);
+ }
+
+ @Override
+ public Rsp1Tuner getTuner() throws SDRPlayException
+ {
+ if(!isSelected())
+ {
+ throw new SDRPlayException("Device must be selected before accessing the tuner");
+ }
+
+ if(mTuner1 == null)
+ {
+ mTuner1 = new Rsp1Tuner(Rsp1Device.this, getAPI(), getTunerSelect(),
+ getCompositeParameters().getDeviceParameters(), getCompositeParameters().getTunerAParameters(),
+ getCompositeParameters().getControlAParameters());
+ }
+
+ return mTuner1;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp1Tuner.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp1Tuner.java
new file mode 100644
index 000000000..147d3bede
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp1Tuner.java
@@ -0,0 +1,46 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.parameter.control.ControlParameters;
+import com.github.dsheirer.sdrplay.parameter.device.Rsp1DeviceParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.Rsp1TunerParameters;
+
+/**
+ * RSP1 Tuner
+ */
+public class Rsp1Tuner extends RspTuner
+{
+ /**
+ * Constructs an instance
+ * @param device parent for this tuner
+ * @param sdrplay api
+ * @param tunerSelect to specify which tuner
+ * @param deviceParameters for this device
+ * @param tunerParameters for this tuner
+ * @param controlParameters for this device
+ */
+ public Rsp1Tuner(Device device, SDRplay sdrplay, TunerSelect tunerSelect, Rsp1DeviceParameters deviceParameters,
+ Rsp1TunerParameters tunerParameters, ControlParameters controlParameters)
+ {
+ super(device, sdrplay, tunerSelect, deviceParameters, tunerParameters, controlParameters);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp1aDevice.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp1aDevice.java
new file mode 100644
index 000000000..bce3c4263
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp1aDevice.java
@@ -0,0 +1,61 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.parameter.composite.Rsp1aCompositeParameters;
+
+/**
+ * RSP1A Device
+ */
+public class Rsp1aDevice extends Device
+{
+ private Rsp1aTuner mTuner1;
+
+ /**
+ * Constructs an SDRPlay RSP1A device from the foreign memory segment
+ *
+ * @param sdrPlay api instance that created this device
+ * @param deviceStruct parser
+ */
+ Rsp1aDevice(SDRplay sdrPlay, IDeviceStruct deviceStruct)
+ {
+ super(sdrPlay, deviceStruct);
+ }
+
+ @Override
+ public Rsp1aTuner getTuner() throws SDRPlayException
+ {
+ if(!isSelected())
+ {
+ throw new SDRPlayException("Device must be selected before accessing the tuner");
+ }
+
+ if(mTuner1 == null)
+ {
+ mTuner1 = new Rsp1aTuner(Rsp1aDevice.this, getAPI(), getTunerSelect(),
+ getCompositeParameters().getDeviceParameters(), getCompositeParameters().getTunerAParameters(),
+ getCompositeParameters().getControlAParameters());
+ }
+
+ return mTuner1;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp1aTuner.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp1aTuner.java
new file mode 100644
index 000000000..db936a0ae
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp1aTuner.java
@@ -0,0 +1,105 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.UpdateReason;
+import com.github.dsheirer.sdrplay.parameter.control.ControlParameters;
+import com.github.dsheirer.sdrplay.parameter.device.Rsp1aDeviceParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.Rsp1aTunerParameters;
+
+/**
+ * RSP1A Tuner
+ */
+public class Rsp1aTuner extends RspTuner
+{
+ /**
+ * Constructs an instance
+ * @param device parent for this tuner
+ * @param sdrplay api
+ * @param tunerSelect to specify which tuner
+ * @param deviceParameters for this device
+ * @param tunerParameters for this tuner
+ * @param controlParameters for this device
+ */
+ public Rsp1aTuner(Device device, SDRplay sdrplay, TunerSelect tunerSelect, Rsp1aDeviceParameters deviceParameters,
+ Rsp1aTunerParameters tunerParameters, ControlParameters controlParameters)
+ {
+ super(device, sdrplay, tunerSelect, deviceParameters, tunerParameters, controlParameters);
+ }
+
+ /**
+ * Indicates if the RF notch is enabled
+ */
+ public boolean isRfNotch()
+ {
+ return getDeviceParameters().isRFNotch();
+ }
+
+ /**
+ * Enables or disables the RF notch
+ * @param enable setting
+ * @throws SDRPlayException if there is an error
+ */
+ public void setRfNotch(boolean enable) throws SDRPlayException
+ {
+ getDeviceParameters().setRFNotch(enable);
+ update(UpdateReason.RSP1A_RF_NOTCH_CONTROL);
+ }
+
+ /**
+ * Indicates if the RF DAB notch is enabled
+ */
+ public boolean isRfDabNotch()
+ {
+ return getDeviceParameters().isRfDabNotch();
+ }
+
+ /**
+ * Enables or disables the RF DAB notch
+ * @param enable value
+ * @throws SDRPlayException if there is an error
+ */
+ public void setRfDabNotch(boolean enable) throws SDRPlayException
+ {
+ getDeviceParameters().setRfDabNotch(enable);
+ update(UpdateReason.RSP1A_RF_DAB_NOTCH_CONTROL);
+ }
+
+ /**
+ * Indicates if the Bias-T is enabled
+ */
+ public boolean isBiasT()
+ {
+ return getTunerParameters().isBiasT();
+ }
+
+ /**
+ * Enables or disables the Bias-T
+ * @param enable value
+ * @throws SDRPlayException if there is an error
+ */
+ public void setBiasT(boolean enable) throws SDRPlayException
+ {
+ getTunerParameters().setBiasT(enable);
+ update(UpdateReason.RSP1A_BIAS_T_CONTROL);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp2Device.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp2Device.java
new file mode 100644
index 000000000..eb725046a
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp2Device.java
@@ -0,0 +1,61 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.parameter.composite.Rsp2CompositeParameters;
+
+/**
+ * RSP2 Device
+ */
+public class Rsp2Device extends Device
+{
+ private Rsp2Tuner mTuner1;
+
+ /**
+ * Constructs an SDRPlay RSP2 device from the foreign memory segment
+ *
+ * @param sdrPlay api instance that created this device
+ * @param deviceStruct parser
+ */
+ Rsp2Device(SDRplay sdrPlay, IDeviceStruct deviceStruct)
+ {
+ super(sdrPlay, deviceStruct);
+ }
+
+ @Override
+ public Rsp2Tuner getTuner() throws SDRPlayException
+ {
+ if(!isSelected())
+ {
+ throw new SDRPlayException("Device must be selected before accessing the tuner");
+ }
+
+ if(mTuner1 == null)
+ {
+ mTuner1 = new Rsp2Tuner(Rsp2Device.this, getAPI(), getTunerSelect(),
+ getCompositeParameters().getDeviceParameters(), getCompositeParameters().getTunerAParameters(),
+ getCompositeParameters().getControlAParameters());
+ }
+
+ return mTuner1;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp2Tuner.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp2Tuner.java
new file mode 100644
index 000000000..187191975
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/Rsp2Tuner.java
@@ -0,0 +1,145 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.UpdateReason;
+import com.github.dsheirer.sdrplay.parameter.control.ControlParameters;
+import com.github.dsheirer.sdrplay.parameter.device.Rsp2DeviceParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.Rsp2AmPort;
+import com.github.dsheirer.sdrplay.parameter.tuner.Rsp2Antenna;
+import com.github.dsheirer.sdrplay.parameter.tuner.Rsp2TunerParameters;
+
+/**
+ * RSP2 Tuner
+ */
+public class Rsp2Tuner extends RspTuner
+{
+ /**
+ * Constructs an instance
+ * @param device parent for this tuner
+ * @param sdrplay api
+ * @param tunerSelect to specify which tuner
+ * @param deviceParameters for this device
+ * @param tunerParameters for this tuner
+ * @param controlParameters for this device
+ */
+ public Rsp2Tuner(Device device, SDRplay sdrplay, TunerSelect tunerSelect, Rsp2DeviceParameters deviceParameters,
+ Rsp2TunerParameters tunerParameters, ControlParameters controlParameters)
+ {
+ super(device, sdrplay, tunerSelect, deviceParameters, tunerParameters, controlParameters);
+ }
+
+ /**
+ * Indicates if the external reference output is enabled.
+ */
+ public boolean isExternalReferenceOutput()
+ {
+ return getDeviceParameters().isExternalReferenceOutput();
+ }
+
+ /**
+ * Enables or disables the external reference output
+ * @param enable value
+ * @throws SDRPlayException if there is an error
+ */
+ public void setExternalReferenceOutput(boolean enable) throws SDRPlayException
+ {
+ getDeviceParameters().setExternalReferenceOutput(enable);
+ update(UpdateReason.RSP2_EXT_REF_CONTROL);
+ }
+
+ /**
+ * Indicates if the Bias-T is enabled
+ */
+ public boolean isBiasT()
+ {
+ return getTunerParameters().isBiasT();
+ }
+
+ /**
+ * Enables or disables the Bias-T
+ * @param enable value
+ * @throws SDRPlayException if there is an error
+ */
+ public void setBiasT(boolean enable) throws SDRPlayException
+ {
+ getTunerParameters().setBiasT(enable);
+ update(UpdateReason.RSP2_BIAS_T_CONTROL);
+ }
+
+ /**
+ * Indicates if the RF notch is enabled
+ */
+ public boolean isRfNotch()
+ {
+ return getTunerParameters().isRfNotch();
+ }
+
+ /**
+ * Enables or disables the RF notch
+ * @param enable setting
+ * @throws SDRPlayException if there is an error
+ */
+ public void setRfNotch(boolean enable) throws SDRPlayException
+ {
+ getTunerParameters().setRfNotch(enable);
+ update(UpdateReason.RSP2_RF_NOTCH_CONTROL);
+ }
+
+ /**
+ * AM port selection
+ */
+ public Rsp2AmPort getAmPort()
+ {
+ return getTunerParameters().getAmPort();
+ }
+
+ /**
+ * Sets the AM port
+ * @param port to select
+ * @throws SDRPlayException if there is an error
+ */
+ public void setAmPort(Rsp2AmPort port) throws SDRPlayException
+ {
+ getTunerParameters().setAmPort(port);
+ update(UpdateReason.RSP2_AM_PORT_SELECT);
+ }
+
+ /**
+ * Antenna selection
+ */
+ public Rsp2Antenna getAntenna()
+ {
+ return getTunerParameters().getAntenna();
+ }
+
+ /**
+ * Sets the antenna
+ * @param antenna to select
+ * @throws SDRPlayException if there is an error
+ */
+ public void setAntenna(Rsp2Antenna antenna) throws SDRPlayException
+ {
+ getTunerParameters().setAntenna(antenna);
+ update(UpdateReason.RSP2_ANTENNA_CONTROL);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDuoDevice.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDuoDevice.java
new file mode 100644
index 000000000..9bb797f76
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDuoDevice.java
@@ -0,0 +1,212 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.UpdateReason;
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_DeviceT;
+import com.github.dsheirer.sdrplay.parameter.composite.RspDuoCompositeParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.IfMode;
+import com.github.dsheirer.sdrplay.parameter.tuner.LoMode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * RSPduo Device
+ */
+public class RspDuoDevice extends Device
+{
+ private static final Logger mLog = LoggerFactory.getLogger(RspDuoDevice.class);
+
+ private RspDuoTuner mTuner;
+
+ /**
+ * Constructs an SDRPlay RSPduo device from the foreign memory segment
+ *
+ * @param sdrPlay api instance that created this device
+ * @param deviceStruct parser
+ */
+ RspDuoDevice(SDRplay sdrPlay, IDeviceStruct deviceStruct)
+ {
+ super(sdrPlay, deviceStruct);
+ }
+
+ /**
+ * Tuner
+ * @return tuner
+ * @throws SDRPlayException if there is an error
+ */
+ @Override
+ public RspDuoTuner getTuner() throws SDRPlayException
+ {
+ if(!isSelected())
+ {
+ throw new SDRPlayException("Device must be selected before accessing the tuner");
+ }
+
+ if(mTuner == null)
+ {
+ if(getTunerSelect().equals(TunerSelect.TUNER_1))
+ {
+ mTuner = new RspDuoTuner1(RspDuoDevice.this, getAPI(),
+ getCompositeParameters().getDeviceParameters(), getCompositeParameters().getTunerAParameters(),
+ getCompositeParameters().getControlAParameters());
+ }
+ else
+ {
+ mTuner = new RspDuoTuner2(RspDuoDevice.this, getAPI(),
+ getCompositeParameters().getDeviceParameters(), getCompositeParameters().getTunerBParameters(),
+ getCompositeParameters().getControlBParameters());
+ }
+ }
+
+ return mTuner;
+ }
+
+ /**
+ * Selected tuner(s).
+ */
+ @Override
+ public TunerSelect getTunerSelect()
+ {
+ return TunerSelect.fromValue(sdrplay_api_DeviceT.tuner$get(getDeviceMemorySegment()));
+ }
+
+ /**
+ * Sets the selected tuner(s)
+ */
+ public void setTunerSelect(TunerSelect tunerSelect)
+ {
+ sdrplay_api_DeviceT.tuner$set(getDeviceMemorySegment(), tunerSelect.getValue());
+ }
+
+ /**
+ * RSPduo mode
+ */
+ public RspDuoMode getRspDuoMode()
+ {
+ return getDeviceStruct().getRspDuoMode();
+ }
+
+ /**
+ * Sets RSPduo mode. Note this must be set before selecting the device for use.
+ * @param mode to set
+ * @throws SDRPlayException if the device has already been selected
+ */
+ public void setRspDuoMode(RspDuoMode mode) throws SDRPlayException
+ {
+ if(isSelected())
+ {
+ throw new SDRPlayException("RSPduo device is already selected. Mode can only be set/changed before the " +
+ "device is selected for use.");
+ }
+
+ getDeviceStruct().setRspDuoMode(mode);
+ }
+
+ /**
+ * Sample rate when in master/slave mode
+ */
+ public double getRspDuoSampleFrequency()
+ {
+ return getDeviceStruct().getRspDuoSampleFrequency();
+ }
+
+ /**
+ * Sets the sample rate when the device is configured for master mode.
+ * @param frequency
+ */
+ public void setRspDuoSampleFrequency(double frequency) throws SDRPlayException
+ {
+ if(!getRspDuoMode().equals(RspDuoMode.MASTER))
+ {
+ throw new SDRPlayException("This method can only be used to set the overall sample rate when the RSPduo " +
+ "device is configured for master mode.");
+ }
+
+ getDeviceStruct().setRspDuoSampleFrequency(frequency);
+ }
+
+ /**
+ * Sets the decimation factor for the final sample rate.
+ * @param decimation as an integer multiple of two (e.g. 1, 2, 4, 8)
+ * @throws SDRPlayException if there is an error while setting decimation
+ */
+ @Override
+ public void setDecimation(Decimate decimation) throws SDRPlayException
+ {
+ if(getTunerSelect() == TunerSelect.TUNER_1)
+ {
+ getCompositeParameters().getControlAParameters().getDecimation().setDecimationFactor(decimation.getValue());
+ getCompositeParameters().getControlAParameters().getDecimation().setEnabled(decimation.isEnabled());
+ update(getTunerSelect(), UpdateReason.CONTROL_DECIMATION);
+ }
+ else if(getTunerSelect() == TunerSelect.TUNER_2)
+ {
+ getCompositeParameters().getControlBParameters().getDecimation().setDecimationFactor(decimation.getValue());
+ getCompositeParameters().getControlBParameters().getDecimation().setEnabled(decimation.isEnabled());
+ update(getTunerSelect(), UpdateReason.CONTROL_DECIMATION);
+ }
+ else if(getTunerSelect() == TunerSelect.TUNER_BOTH)
+ {
+ //Dual-synchronized tuner mode ... let the parent Device class set the value
+ super.setDecimation(decimation);
+ }
+ }
+
+ /**
+ * Sets the IF mode when tuner 2 is selected in single-tuner mode.
+ * @param ifMode to set
+ */
+ public void setIfModeTuner2(IfMode ifMode)
+ {
+ getCompositeParameters().getTunerBParameters().setIfMode(ifMode);
+ }
+
+ /**
+ * Sets the LO mode when tuner 2 is selected in single-tuner mode.
+ * @param loMode to set
+ */
+ public void setLoModeTuner2(LoMode loMode)
+ {
+ getCompositeParameters().getTunerBParameters().setLoMode(loMode);
+ }
+
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("SDRPplay Device").append("\n");
+ sb.append("\tType: " + getDeviceType()).append("\n");
+ sb.append("\tSerial Number: " + getSerialNumber()).append("\n");
+ sb.append("\tTuner: " + getTunerSelect()).append("\n");
+ sb.append("\tRSP Duo: " + getRspDuoMode()).append("\n");
+ sb.append("\tRSP Duo Sample Rate: " + getRspDuoSampleFrequency()).append("\n");
+ sb.append("\tSelected: " + isSelected());
+ if(hasCompositeParameters())
+ {
+ sb.append("\t").append(getCompositeParameters());
+ }
+
+ return sb.toString();
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDuoMode.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDuoMode.java
new file mode 100644
index 000000000..a95de2ff1
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDuoMode.java
@@ -0,0 +1,75 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * RSP-Duo Mode
+ */
+public enum RspDuoMode
+{
+ SINGLE_TUNER(sdrplay_api_h.sdrplay_api_RspDuoMode_Single_Tuner(), "SINGLE TUNER"),
+ DUAL_TUNER(sdrplay_api_h.sdrplay_api_RspDuoMode_Dual_Tuner(), "DUAL TUNER"),
+ MASTER(sdrplay_api_h.sdrplay_api_RspDuoMode_Master(), "MASTER"),
+ SLAVE(sdrplay_api_h.sdrplay_api_RspDuoMode_Slave(), "SLAVE"),
+ UNKNOWN(sdrplay_api_h.sdrplay_api_RspDuoMode_Unknown(), "UNKNOWN");
+
+ private int mValue;
+ private String mDescription;
+
+ RspDuoMode(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or UKNOWN if the code is not recognized
+ */
+ public static RspDuoMode fromValue(int value)
+ {
+ for(RspDuoMode status: RspDuoMode.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return UNKNOWN;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDuoTuner.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDuoTuner.java
new file mode 100644
index 000000000..5b9594f5f
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDuoTuner.java
@@ -0,0 +1,105 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.UpdateReason;
+import com.github.dsheirer.sdrplay.parameter.control.ControlParameters;
+import com.github.dsheirer.sdrplay.parameter.device.RspDuoDeviceParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.RspDuoTunerParameters;
+
+/**
+ * RSPduo Tuner
+ */
+public abstract class RspDuoTuner extends RspTuner
+{
+ /**
+ * Constructs an instance
+ * @param device parent for this tuner
+ * @param sdrplay api
+ * @param tunerSelect to specify which tuner
+ * @param deviceParameters for this device
+ * @param tunerParameters for this tuner
+ * @param controlParameters for this device
+ */
+ public RspDuoTuner(Device device, SDRplay sdrplay, TunerSelect tunerSelect, RspDuoDeviceParameters deviceParameters,
+ RspDuoTunerParameters tunerParameters, ControlParameters controlParameters)
+ {
+ super(device, sdrplay, tunerSelect, deviceParameters, tunerParameters, controlParameters);
+ }
+
+ /**
+ * Indicates if the RF notch is enabled
+ */
+ public boolean isRFNotch()
+ {
+ return getTunerParameters().isRfNotch();
+ }
+
+ /**
+ * Enables or disables the RF notch
+ * @param enable setting
+ * @throws SDRPlayException if there is an error
+ */
+ public void setRfNotch(boolean enable) throws SDRPlayException
+ {
+ getTunerParameters().setRfNotch(enable);
+ update(UpdateReason.RSP_DUO_RF_NOTCH_CONTROL);
+ }
+
+ /**
+ * Indicates if the RF DAB notch is enabled
+ */
+ public boolean isRfDabNotch()
+ {
+ return getTunerParameters().isRfDabNotch();
+ }
+
+ /**
+ * Enables or disables the RF DAB notch
+ * @param enable value
+ * @throws SDRPlayException if there is an error
+ */
+ public void setRfDabNotch(boolean enable) throws SDRPlayException
+ {
+ getTunerParameters().setRfDabNotch(enable);
+ update(UpdateReason.RSP_DUO_RF_DAB_NOTCH_CONTROL);
+ }
+
+ /**
+ * Indicates if the external reference output is enabled.
+ */
+ public boolean isExternalReferenceOutput()
+ {
+ return getDeviceParameters().isExternalReferenceOutput();
+ }
+
+ /**
+ * Enables or disables the external reference output
+ * @param enable value
+ * @throws SDRPlayException if there is an error
+ */
+ public void setExternalReferenceOutput(boolean enable) throws SDRPlayException
+ {
+ getDeviceParameters().setExternalReferenceOutput(enable);
+ update(UpdateReason.RSP_DUO_EXT_REF_CONTROL);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDuoTuner1.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDuoTuner1.java
new file mode 100644
index 000000000..ec7697c23
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDuoTuner1.java
@@ -0,0 +1,87 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.UpdateReason;
+import com.github.dsheirer.sdrplay.parameter.control.ControlParameters;
+import com.github.dsheirer.sdrplay.parameter.device.RspDuoDeviceParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.RspDuoAmPort;
+import com.github.dsheirer.sdrplay.parameter.tuner.RspDuoTunerParameters;
+
+/**
+ * RSPduo Tuner 1
+ */
+public class RspDuoTuner1 extends RspDuoTuner
+{
+ /**
+ * Constructs an instance
+ *
+ * @param device parent for this tuner
+ * @param sdrplay api
+ * @param deviceParameters for this device
+ * @param tunerParameters for this tuner
+ * @param controlParameters for this device
+ */
+ public RspDuoTuner1(Device device, SDRplay sdrplay, RspDuoDeviceParameters deviceParameters,
+ RspDuoTunerParameters tunerParameters, ControlParameters controlParameters)
+ {
+ super(device, sdrplay, TunerSelect.TUNER_1, deviceParameters, tunerParameters, controlParameters);
+ }
+
+ /**
+ * Indicates which AM port is selected
+ */
+ public RspDuoAmPort getAmPort()
+ {
+ return getTunerParameters().getTuner1AmPort();
+ }
+
+ /**
+ * Selects the AM port to use
+ * @param port to use
+ * @throws SDRPlayException if there is an error
+ */
+ public void setAmPort(RspDuoAmPort port) throws SDRPlayException
+ {
+ getTunerParameters().setTuner1AmPort(port);
+ update(UpdateReason.RSP_DUO_AM_PORT_SELECT);
+ }
+
+ /**
+ * Indicates if the AM notch is enabled
+ */
+ public boolean isAmNotch()
+ {
+ return getTunerParameters().isTuner1AmNotch();
+ }
+
+ /**
+ * Enables or disables the AM notch
+ * @param enable for the notch
+ * @throws SDRPlayException if there is an error
+ */
+ public void setAmNotch(boolean enable) throws SDRPlayException
+ {
+ getTunerParameters().setTuner1AmNotch(enable);
+ update(UpdateReason.RSP_DUO_TUNER_1_AM_NOTCH_CONTROL);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDuoTuner2.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDuoTuner2.java
new file mode 100644
index 000000000..eac047bcb
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDuoTuner2.java
@@ -0,0 +1,67 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.UpdateReason;
+import com.github.dsheirer.sdrplay.parameter.control.ControlParameters;
+import com.github.dsheirer.sdrplay.parameter.device.RspDuoDeviceParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.RspDuoTunerParameters;
+
+/**
+ * RSPduo Tuner 2
+ */
+public class RspDuoTuner2 extends RspDuoTuner
+{
+ /**
+ * Constructs an instance
+ *
+ * @param device parent for this tuner
+ * @param sdrplay api
+ * @param deviceParameters for this device
+ * @param tunerParameters for this tuner
+ * @param controlParameters for this device
+ */
+ public RspDuoTuner2(Device device, SDRplay sdrplay, RspDuoDeviceParameters deviceParameters,
+ RspDuoTunerParameters tunerParameters, ControlParameters controlParameters)
+ {
+ super(device, sdrplay, TunerSelect.TUNER_2, deviceParameters, tunerParameters, controlParameters);
+ }
+
+ /**
+ * Indicates if the Bias-T is enabled
+ */
+ public boolean isBiasT()
+ {
+ return getTunerParameters().isBiasT();
+ }
+
+ /**
+ * Enables or disables the Bias-T
+ * @param enable value
+ * @throws SDRPlayException if there is an error
+ */
+ public void setBiasT(boolean enable) throws SDRPlayException
+ {
+ getTunerParameters().setBiasT(enable);
+ update(UpdateReason.RSP_DUO_BIAS_T_CONTROL);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDxDevice.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDxDevice.java
new file mode 100644
index 000000000..4802a82bf
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDxDevice.java
@@ -0,0 +1,62 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.parameter.composite.RspDxCompositeParameters;
+
+/**
+ * RSPdx Device
+ */
+public class RspDxDevice extends Device
+{
+ private RspDxTuner mTuner1;
+
+ /**
+ * Constructs an SDRPlay RSPdx device from the foreign memory segment
+ *
+ * @param sdrPlay api instance that created this device
+ * @param deviceStruct parser
+ */
+ RspDxDevice(SDRplay sdrPlay, IDeviceStruct deviceStruct)
+ {
+ super(sdrPlay, deviceStruct);
+ }
+
+
+ @Override
+ public RspDxTuner getTuner() throws SDRPlayException
+ {
+ if(!isSelected())
+ {
+ throw new SDRPlayException("Device must be selected before accessing the tuner");
+ }
+
+ if(mTuner1 == null)
+ {
+ mTuner1 = new RspDxTuner(RspDxDevice.this, getAPI(), getTunerSelect(),
+ getCompositeParameters().getDeviceParameters(), getCompositeParameters().getTunerAParameters(),
+ getCompositeParameters().getControlAParameters());
+ }
+
+ return mTuner1;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDxTuner.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDxTuner.java
new file mode 100644
index 000000000..547d93443
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspDxTuner.java
@@ -0,0 +1,164 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.UpdateReason;
+import com.github.dsheirer.sdrplay.parameter.control.ControlParameters;
+import com.github.dsheirer.sdrplay.parameter.device.RspDxDeviceParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.HdrModeBandwidth;
+import com.github.dsheirer.sdrplay.parameter.tuner.RspDxAntenna;
+import com.github.dsheirer.sdrplay.parameter.tuner.RspDxTunerParameters;
+
+/**
+ * RSPdx Tuner
+ */
+public class RspDxTuner extends RspTuner
+{
+ /**
+ * Constructs an instance
+ * @param device parent for this tuner
+ * @param sdrplay api
+ * @param tunerSelect to specify which tuner
+ * @param deviceParameters for this device
+ * @param tunerParameters for this tuner
+ * @param controlParameters for this device
+ */
+ public RspDxTuner(Device device, SDRplay sdrplay, TunerSelect tunerSelect, RspDxDeviceParameters deviceParameters,
+ RspDxTunerParameters tunerParameters, ControlParameters controlParameters)
+ {
+ super(device, sdrplay, tunerSelect, deviceParameters, tunerParameters, controlParameters);
+ }
+
+ /**
+ * Indicates if HDR mode is enabled
+ */
+ public boolean isHdrMode()
+ {
+ return getDeviceParameters().isHdr();
+ }
+
+ /**
+ * Enables or disables HDR mode
+ * @param enable mode
+ * @throws SDRPlayException if there is an error
+ */
+ public void setHdrMode(boolean enable) throws SDRPlayException
+ {
+ getDeviceParameters().setHdr(enable);
+ update(UpdateReason.EXTENSION_RSP_DX_HDR_ENABLE);
+ }
+
+ /**
+ * HDR mode bandwidth
+ */
+ public HdrModeBandwidth getHdrModeBandwidth()
+ {
+ return getTunerParameters().getHdrModeBandwidth();
+ }
+
+ /**
+ * Sets HDR mode bandwidth
+ * @param bandwidth to select
+ * @throws SDRPlayException if there is an error
+ */
+ public void setHdrModeBandwidth(HdrModeBandwidth bandwidth) throws SDRPlayException
+ {
+ getTunerParameters().setHdrModeBandwidth(bandwidth);
+ update(UpdateReason.EXTENSION_RSP_DX_HDR_BANDWIDTH);
+ }
+
+ /**
+ * Indicates if the RF notch is enabled
+ */
+ public boolean isRfNotch()
+ {
+ return getDeviceParameters().isRfNotch();
+ }
+
+ /**
+ * Enables or disables the RF notch
+ * @param enable setting
+ * @throws SDRPlayException if there is an error
+ */
+ public void setRfNotch(boolean enable) throws SDRPlayException
+ {
+ getDeviceParameters().setRfNotch(enable);
+ update(UpdateReason.EXTENSION_RSP_DX_RF_NOTCH_CONTROL);
+ }
+
+ /**
+ * Indicates if the RF DAB notch is enabled
+ */
+ public boolean isRfDabNotch()
+ {
+ return getDeviceParameters().isRfDabNotch();
+ }
+
+ /**
+ * Enables or disables the RF DAB notch
+ * @param enable value
+ * @throws SDRPlayException if there is an error
+ */
+ public void setRfDabNotch(boolean enable) throws SDRPlayException
+ {
+ getDeviceParameters().setRfDabNotch(enable);
+ update(UpdateReason.EXTENSION_RSP_DX_RF_DAB_NOTCH_CONTROL);
+ }
+
+ /**
+ * Indicates if the Bias-T is enabled
+ */
+ public boolean isBiasT()
+ {
+ return getDeviceParameters().isBiasT();
+ }
+
+ /**
+ * Enables or disables the Bias-T
+ * @param enable value
+ * @throws SDRPlayException if there is an error
+ */
+ public void setBiasT(boolean enable) throws SDRPlayException
+ {
+ getDeviceParameters().setBiasT(enable);
+ update(UpdateReason.EXTENSION_RSP_DX_BIAS_T_CONTROL);
+ }
+
+ /**
+ * Antenna selection
+ */
+ public RspDxAntenna getAntenna()
+ {
+ return getDeviceParameters().getRspDxAntenna();
+ }
+
+ /**
+ * Sets the antenna selection
+ * @param antenna to select
+ * @throws SDRPlayException if there is an error
+ */
+ public void setAntenna(RspDxAntenna antenna) throws SDRPlayException
+ {
+ getDeviceParameters().setRspDxAntenna(antenna);
+ update(UpdateReason.EXTENSION_RSP_DX_ANTENNA_CONTROL);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspTuner.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspTuner.java
new file mode 100644
index 000000000..5ff90259a
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/RspTuner.java
@@ -0,0 +1,419 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.UpdateReason;
+import com.github.dsheirer.sdrplay.async.AsyncUpdateFuture;
+import com.github.dsheirer.sdrplay.parameter.control.AgcMode;
+import com.github.dsheirer.sdrplay.parameter.control.ControlParameters;
+import com.github.dsheirer.sdrplay.parameter.device.DeviceParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.Bandwidth;
+import com.github.dsheirer.sdrplay.parameter.tuner.Gain;
+import com.github.dsheirer.sdrplay.parameter.tuner.GainReduction;
+import com.github.dsheirer.sdrplay.parameter.tuner.IfMode;
+import com.github.dsheirer.sdrplay.parameter.tuner.LoMode;
+import com.github.dsheirer.sdrplay.parameter.tuner.TunerParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract RSP device tuner
+ * @param RSP device implementation
+ */
+public abstract class RspTuner
+{
+ private static final Logger mLog = LoggerFactory.getLogger(RspTuner.class);
+ private final SDRplay mSDRplay;
+ private final Device mDevice;
+ private final TunerSelect mTunerSelect;
+ private final D mDeviceParameters;
+ private final T mTunerParameters;
+ private final ControlParameters mControlParameters;
+
+ private GainReduction mGainReduction;
+
+ RspTuner(Device device, SDRplay sdrplay, TunerSelect tunerSelect, D deviceParameters, T tunerParameters,
+ ControlParameters controlParameters)
+ {
+ mDevice = device;
+ mSDRplay = sdrplay;
+ mTunerSelect = tunerSelect;
+ mDeviceParameters = deviceParameters;
+ mTunerParameters = tunerParameters;
+ mControlParameters = controlParameters;
+ }
+
+ /**
+ * SDRplay API
+ */
+ private SDRplay getSDRplay()
+ {
+ return mSDRplay;
+ }
+
+ /**
+ * Parent device for this tuner
+ */
+ private Device getDevice()
+ {
+ return mDevice;
+ }
+
+ /**
+ * Selected tuner
+ */
+ public TunerSelect getTunerSelect()
+ {
+ return mTunerSelect;
+ }
+
+ /**
+ * Device parameters
+ */
+ protected D getDeviceParameters()
+ {
+ return mDeviceParameters;
+ }
+
+ /**
+ * Tuner parameters for the selected tuner
+ */
+ public T getTunerParameters()
+ {
+ return mTunerParameters;
+ }
+
+ /**
+ * Control parameters for the selected tuner
+ */
+ protected ControlParameters getControlParameters()
+ {
+ return mControlParameters;
+ }
+
+ /**
+ * Convenience method for notifying the API that parameters for the device have been updated, when the device is
+ * initialized.
+ *
+ * @param updateReasons indicating what has been updated
+ * @throws SDRPlayException if there is an error
+ */
+ protected void update(UpdateReason... updateReasons) throws SDRPlayException
+ {
+ getDevice().update(getTunerSelect(), updateReasons);
+ }
+
+ /**
+ * Convenience method for notifying the device that a parameter for this tuner have been updated.
+ *
+ * Note: the asynchronous device event responses are limited to Frequency, Gain and Sample Rate. For example,
+ * if you update the RSPduo DAB Notch parameter, it will generate a Gain change notification, so we submit
+ * an async update for the DAB Notch, but anticipate a Gain update response.
+ *
+ * @param updateReason indicating what has been updated
+ * @param expectedResponse that will be received indicating that the async operation is completed.
+ */
+ protected AsyncUpdateFuture updateAsync(UpdateReason updateReason, UpdateReason expectedResponse)
+ {
+ return getDevice().updateAsync(getTunerSelect(), updateReason, expectedResponse);
+ }
+
+ /**
+ * Current tuner bandwidth
+ */
+ public Bandwidth getBandwidth()
+ {
+ return getTunerParameters().getBandwidth();
+ }
+
+ /**
+ * Sets tuner bandwidth
+ * @param bandwidth to apply
+ * @throws SDRPlayException if there is an error
+ */
+ public void setBandwidth(Bandwidth bandwidth) throws SDRPlayException
+ {
+ getTunerParameters().setBandwidth(bandwidth);
+ update(UpdateReason.TUNER_BANDWIDTH_TYPE);
+ }
+
+ /**
+ * Center frequency for the tuner
+ */
+ public long getFrequency()
+ {
+ return (long) getTunerParameters().getRfFrequency().getFrequency();
+ }
+
+ /**
+ * Requests to set the center frequency for the tuner asynchronously.
+ *
+ * Note: the API supports the notion of synchronous frequency updates, but in testing I found that you cannot
+ * submit a second frequency change update request until a previously submitted frequency change update
+ * operation had completed, otherwise it would generate a fail status. Therefore, this is method is strictly
+ * an async operation.
+ *
+ * @param frequency in Hertz
+ * @return future that can be monitored for completion of the set frequency operation.
+ */
+ public AsyncUpdateFuture setFrequency(long frequency)
+ {
+ try
+ {
+ getTunerParameters().getRfFrequency().setFrequency(frequency, false);
+ updateGainReduction(frequency);
+ return updateAsync(UpdateReason.TUNER_FREQUENCY_RF, UpdateReason.TUNER_FREQUENCY_RF);
+ }
+ catch(SDRPlayException se)
+ {
+ AsyncUpdateFuture future = new AsyncUpdateFuture(getTunerSelect(), UpdateReason.TUNER_FREQUENCY_RF,
+ UpdateReason.TUNER_FREQUENCY_RF);
+ future.setError(se);
+ return future;
+ }
+ }
+
+ /**
+ * Gain reduction in use for this device with the current RF frequency
+ */
+ public GainReduction getGainReduction()
+ {
+ if(mGainReduction == null)
+ {
+ updateGainReduction(getFrequency());
+ }
+
+ return mGainReduction;
+ }
+
+ /**
+ * Updates the gain reduction, if necessary, for the specified RF frequency
+ *
+ * @param frequency value
+ */
+ private void updateGainReduction(long frequency)
+ {
+ if(mGainReduction == null || !mGainReduction.isValidFor(frequency))
+ {
+ mGainReduction = GainReduction.lookup(getDevice().getDeviceType(), frequency);
+ }
+ }
+
+ /**
+ * Selects a gain value index from the current gain reduction values
+ *
+ * @param index of the gain reduction values to use
+ */
+ public void setGain(int index) throws SDRPlayException
+ {
+ getTunerParameters().getGain().setGain(getGainReduction(), index);
+ update(UpdateReason.TUNER_GAIN_REDUCTION);
+ }
+
+ /**
+ * Sets the automatic gain contral (AGC) mode
+ *
+ * @param mode to set
+ * @throws SDRPlayException if there is an error
+ */
+ public void setAGC(AgcMode mode) throws SDRPlayException
+ {
+ getControlParameters().getAgc().setAgcMode(mode);
+ update(UpdateReason.CONTROL_AGC);
+ }
+
+ /**
+ * AGC Mode
+ */
+ public AgcMode getAGC()
+ {
+ return getControlParameters().getAgc().getAgcMode();
+ }
+
+ /**
+ * Gain for the tuner.
+ */
+ public Gain getGain()
+ {
+ return getTunerParameters().getGain();
+ }
+
+ /**
+ * Current gain index value.
+ * @return current gain index value or -1 if the current gain setting does not match the possible gain reduction options.
+ */
+ public int getGainIndex()
+ {
+ int gainDb = getGain().getGainReductionDb();
+ return getGainReduction().getGainIndex(gainDb);
+ }
+
+ /**
+ * Enables or disables DC correction
+ *
+ * @param enable true or false
+ * @throws SDRPlayException if there is an error
+ */
+ public void setDCCorrection(boolean enable) throws SDRPlayException
+ {
+ getControlParameters().getDcOffset().setDC(enable);
+ update(UpdateReason.CONTROL_DC_OFFSET_IQ_IMBALANCE);
+ }
+
+ /**
+ * Enables or disables IQ imbalance correction
+ *
+ * @param enable true or false
+ * @throws SDRPlayException if there is an error
+ */
+ public void setIQCorrection(boolean enable) throws SDRPlayException
+ {
+ getControlParameters().getDcOffset().setIQ(enable);
+ update(UpdateReason.CONTROL_DC_OFFSET_IQ_IMBALANCE);
+ }
+
+ /**
+ * Sets or updates the parts per million (ppm) frequency correction
+ *
+ * @param ppm value
+ * @throws SDRPlayException
+ */
+ public AsyncUpdateFuture setPPM(double ppm) throws SDRPlayException
+ {
+ getDeviceParameters().setPPM(ppm);
+
+ //Note: async ppm updates effect both frequency and sample rate, so we expect the completion of the
+ //operation will be first FREQUENCY and then SAMPLE RATE, so we watch for sample rate.
+ return updateAsync(UpdateReason.DEVICE_PPM, UpdateReason.DEVICE_SAMPLE_RATE);
+ }
+
+ /**
+ * Parts per million (PPM) frequency correction value
+ *
+ * @return ppm value
+ */
+ public double getPPM()
+ {
+ return getDeviceParameters().getPPM();
+ }
+
+ /**
+ * Perform synchronous update
+ *
+ * @param sampleNumber value
+ * @param period value
+ * @throws SDRPlayException if there is an error
+ */
+ public void setSynchronousUpdate(int sampleNumber, int period) throws SDRPlayException
+ {
+ getDeviceParameters().getSynchronousUpdate().set(sampleNumber, period);
+ update(UpdateReason.DEVICE_SYNC_UPDATE);
+ }
+
+ /**
+ * Resets device functions to default
+ *
+ * @param frequency to reset
+ * @param sampleRate to reset
+ * @param gain to reset
+ * @throws SDRPlayException if there is an error
+ */
+ public void reset(boolean frequency, boolean sampleRate, boolean gain) throws SDRPlayException
+ {
+ getDeviceParameters().getResetFlags().resetGain(gain);
+ getDeviceParameters().getResetFlags().resetFrequency(frequency);
+ getDeviceParameters().getResetFlags().resetSampleRate(sampleRate);
+ update(UpdateReason.DEVICE_RESET_FLAGS);
+ }
+
+ /**
+ * Resets the frequency.
+ *
+ * @param frequency true to reset
+ * @throws SDRPlayException if there is an error
+ */
+ public void resetFrequency(boolean frequency) throws SDRPlayException
+ {
+ reset(frequency, false, false);
+ }
+
+ /**
+ * Resets the sample rate.
+ *
+ * @param sampleRate true to reset
+ * @throws SDRPlayException if there is an error
+ */
+ public void resetSampleRate(boolean sampleRate) throws SDRPlayException
+ {
+ reset(false, sampleRate, false);
+ }
+
+ /**
+ * Resets the gain (reduction).
+ *
+ * @param gain true to reset
+ * @throws SDRPlayException if there is an error
+ */
+ public void resetGain(boolean gain) throws SDRPlayException
+ {
+ reset(false, false, gain);
+ }
+
+ /**
+ * IF mode (type)
+ */
+ public IfMode getIfMode()
+ {
+ return getTunerParameters().getIfMode();
+ }
+
+ /**
+ * Sets the IF mode (type)
+ * @param mode to set
+ * @throws SDRPlayException if there is an error
+ */
+ public void setIfMode(IfMode mode) throws SDRPlayException
+ {
+ getTunerParameters().setIfMode(mode);
+ update(UpdateReason.TUNER_IF_TYPE);
+ }
+
+ /**
+ * Local Oscillator (LO) mode
+ * @return mode
+ */
+ public LoMode getLoMode()
+ {
+ return getTunerParameters().getLoMode();
+ }
+
+ /**
+ * Sets the Local Oscillator (LO) mode
+ * @param mode to set
+ * @throws SDRPlayException if there is an error
+ */
+ public void setLoMode(LoMode mode) throws SDRPlayException
+ {
+ getTunerParameters().setLoMode(mode);
+ update(UpdateReason.TUNER_LO_MODE);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/TunerSelect.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/TunerSelect.java
new file mode 100644
index 000000000..78078de3c
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/TunerSelect.java
@@ -0,0 +1,74 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * Tuner Select
+ */
+public enum TunerSelect
+{
+ TUNER_1(sdrplay_api_h.sdrplay_api_Tuner_A(), "TUNER 1"),
+ TUNER_2(sdrplay_api_h.sdrplay_api_Tuner_B(), "TUNER 2"),
+ TUNER_BOTH(sdrplay_api_h.sdrplay_api_Tuner_Both(), "TUNER 1 & 2"),
+ NEITHER(sdrplay_api_h.sdrplay_api_Tuner_Neither(), "NEITHER");
+
+ private int mValue;
+ private String mDescription;
+
+ TunerSelect(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or NEITHER if the code is not recognized
+ */
+ public static TunerSelect fromValue(int value)
+ {
+ for(TunerSelect status: TunerSelect.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return NEITHER;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/UnknownDevice.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/UnknownDevice.java
new file mode 100644
index 000000000..622cabc3c
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/device/UnknownDevice.java
@@ -0,0 +1,46 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.device;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+
+/**
+ * Unknown or Unrecognized SDRplay Device
+ */
+public class UnknownDevice extends Device
+{
+ /**
+ * Constructs an Unknown SDRPlay device from the foreign memory segment
+ *
+ * @param sdrPlay api instance that created this device
+ * @param deviceStruct parser
+ */
+ UnknownDevice(SDRplay sdrPlay, IDeviceStruct deviceStruct)
+ {
+ super(sdrPlay, deviceStruct);
+ }
+
+ @Override
+ public RspTuner getTuner() throws SDRPlayException
+ {
+ throw new SDRPlayException("Unrecognized device type. Cannot construct tuner");
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/error/DebugLevel.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/error/DebugLevel.java
new file mode 100644
index 000000000..44226683a
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/error/DebugLevel.java
@@ -0,0 +1,76 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.error;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * Debug Level
+ */
+public enum DebugLevel
+{
+ DISABLE(sdrplay_api_h.sdrplay_api_DbgLvl_Disable(), "DISABLE"),
+ VERBOSE(sdrplay_api_h.sdrplay_api_DbgLvl_Verbose(), "VERBOSE"),
+ WARNING(sdrplay_api_h.sdrplay_api_DbgLvl_Warning(), "WARNING"),
+ ERROR(sdrplay_api_h.sdrplay_api_DbgLvl_Error(), "ERROR"),
+ MESSAGE(sdrplay_api_h.sdrplay_api_DbgLvl_Message(), "MESSAGE"),
+ UNKNOWN(-1, "UNKNOWN");
+
+ private int mValue;
+ private String mDescription;
+
+ DebugLevel(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or UNKNOWN if the code is not recognized
+ */
+ public static DebugLevel fromValue(int value)
+ {
+ for(DebugLevel status: DebugLevel.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return UNKNOWN;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/error/ErrorInformation.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/error/ErrorInformation.java
new file mode 100644
index 000000000..a409ac2d0
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/error/ErrorInformation.java
@@ -0,0 +1,78 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.error;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_ErrorInfoT;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * Error Information structure (sdrplay_api_ErrorInfoT)
+ */
+public class ErrorInformation
+{
+ private String mFile;
+ private String mFunction;
+ private int mLine;
+ private String mMessage;
+
+ /**
+ * Constructs an instance from the foreign memory segment
+ */
+ public ErrorInformation(MemorySegment memorySegment)
+ {
+ mFile = sdrplay_api_ErrorInfoT.file$slice(memorySegment).getUtf8String(0);
+ mFunction = sdrplay_api_ErrorInfoT.function$slice(memorySegment).getUtf8String(0);
+ mLine = sdrplay_api_ErrorInfoT.line$get(memorySegment);
+ mMessage = sdrplay_api_ErrorInfoT.message$slice(memorySegment).getUtf8String(0);
+ }
+
+ public String getFile()
+ {
+ return mFile;
+ }
+
+ public String getFunction()
+ {
+ return mFunction;
+ }
+
+ public int getLine()
+ {
+ return mLine;
+ }
+
+ public String getMessage()
+ {
+ return mMessage;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Error Information:").append("\n");
+ sb.append("\t File: ").append(getFile()).append("\n");
+ sb.append("\tFunction: ").append(getFunction()).append("\n");
+ sb.append("\t Line: ").append(getLine()).append("\n");
+ sb.append("\t Message: ").append(getMessage()).append("\n");
+ return sb.toString();
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/CompositeParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/CompositeParameters.java
new file mode 100644
index 000000000..3e28a0463
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/CompositeParameters.java
@@ -0,0 +1,109 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.composite;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_DevParamsT;
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_DeviceParamsT;
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_RxChannelParamsT;
+import com.github.dsheirer.sdrplay.device.DeviceType;
+import com.github.dsheirer.sdrplay.parameter.control.ControlParameters;
+import com.github.dsheirer.sdrplay.parameter.device.DeviceParameters;
+import com.github.dsheirer.sdrplay.parameter.device.DeviceParametersFactory;
+import com.github.dsheirer.sdrplay.parameter.tuner.TunerParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.TunerParametersFactory;
+
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+
+/**
+ * Composite Device Parameters structure (sdrplay_api_DeviceParamsT) providing access to the device parameters and
+ * the tuner 1 parameters. Tuner 2 parameters are only accessible via the RSPduo sub-class implementation.
+ *
+ * Note: sub-class implementations will constrain access to the appropriate sub-structures of the DeviceParamsT
+ * structure for each specific device.
+ */
+public class CompositeParameters
+{
+ private D mDeviceParameters;
+ private T mTunerAParameters;
+ private ControlParameters mControlAParameters;
+
+ /**
+ * Constructs an instance from the foreign memory segment
+ *
+ * @param deviceType to create
+ * @param memorySegment for the composite structure in foreign memory
+ * @param memorySession for allocating additional memory segments for the sub-structures.
+ */
+ public CompositeParameters(DeviceType deviceType, MemorySegment memorySegment, MemorySession memorySession)
+ {
+ MemoryAddress parametersMemoryAddress = sdrplay_api_DeviceParamsT.devParams$get(memorySegment);
+ MemorySegment parametersMemorySegment = sdrplay_api_DevParamsT.ofAddress(parametersMemoryAddress, memorySession);
+ mDeviceParameters = (D) DeviceParametersFactory.create(deviceType, parametersMemorySegment);
+
+ MemoryAddress memoryAddressRxA = sdrplay_api_DeviceParamsT.rxChannelA$get(memorySegment);
+ MemorySegment memorySegmentRxA = sdrplay_api_RxChannelParamsT.ofAddress(memoryAddressRxA, memorySession);
+ mTunerAParameters = (T) TunerParametersFactory.create(deviceType, memorySegmentRxA);
+
+ MemorySegment tunerAControlParametersMemorySegment = sdrplay_api_RxChannelParamsT.ctrlParams$slice(memorySegmentRxA);
+ mControlAParameters = new ControlParameters(tunerAControlParametersMemorySegment);
+ }
+
+ /**
+ * Device parameters
+ */
+ public D getDeviceParameters()
+ {
+ return mDeviceParameters;
+ }
+
+ /**
+ * Tuner A Parameters.
+ *
+ * Note: this is normally mapped to tuner 1. In the RSPduo, this is mapped to Tuner 1 or Tuner 2, according to how
+ * the user has setup the TunerSelect.
+ */
+ public T getTunerAParameters()
+ {
+ return mTunerAParameters;
+ }
+
+ /**
+ * Tuner A Control Parameters
+ *
+ * Note: this is normally mapped to tuner 1. In the RSPduo, this is mapped to Tuner 1 or Tuner 2, according to how
+ * the user has setup the TunerSelect.
+ */
+ public ControlParameters getControlAParameters()
+ {
+ return mControlAParameters;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Composite Parameters\n");
+ sb.append("\tDevice Parameters:\n").append(getDeviceParameters()).append("\n");
+ sb.append("\tTuner A Parameters:\n").append(getTunerAParameters()).append("\n");
+ return sb.toString();
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/CompositeParametersFactory.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/CompositeParametersFactory.java
new file mode 100644
index 000000000..c73b8005d
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/CompositeParametersFactory.java
@@ -0,0 +1,62 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.composite;
+
+import com.github.dsheirer.sdrplay.device.DeviceType;
+
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+
+/**
+ * Creates a composite parameters instance for a device type
+ */
+public class CompositeParametersFactory
+{
+ /**
+ * Creates a composite parameters instance for the specified device type
+ * @param deviceType to create
+ * @param memorySegment of foreign memory structure for the composite parameters
+ * @param memorySession to allocate additional memory structures
+ * @return instance
+ */
+ public static CompositeParameters create(DeviceType deviceType, MemorySegment memorySegment, MemorySession memorySession)
+ {
+ switch(deviceType)
+ {
+ case RSP1 -> {
+ return new Rsp1CompositeParameters(memorySegment, memorySession);
+ }
+ case RSP1A -> {
+ return new Rsp1aCompositeParameters(memorySegment, memorySession);
+ }
+ case RSP2 -> {
+ return new Rsp2CompositeParameters(memorySegment, memorySession);
+ }
+ case RSPduo -> {
+ return new RspDuoCompositeParameters(memorySegment, memorySession);
+ }
+ case RSPdx -> {
+ return new RspDxCompositeParameters(memorySegment, memorySession);
+ }
+ }
+
+ throw new IllegalArgumentException("Unrecognized device type: " + deviceType);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/Rsp1CompositeParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/Rsp1CompositeParameters.java
new file mode 100644
index 000000000..bd19fe4a0
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/Rsp1CompositeParameters.java
@@ -0,0 +1,44 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.composite;
+
+import com.github.dsheirer.sdrplay.device.DeviceType;
+import com.github.dsheirer.sdrplay.parameter.device.Rsp1DeviceParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.Rsp1TunerParameters;
+
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+
+/**
+ * RSP1 Composite parameters (device and tuner)
+ */
+public class Rsp1CompositeParameters extends CompositeParameters
+{
+ /**
+ * Constructs an instance from the foreign memory segment
+ *
+ * @param memorySegment for the composite structure in foreign memory
+ * @param memorySession for allocating additional memory segments for the sub-structures.
+ */
+ public Rsp1CompositeParameters(MemorySegment memorySegment, MemorySession memorySession)
+ {
+ super(DeviceType.RSP1, memorySegment, memorySession);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/Rsp1aCompositeParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/Rsp1aCompositeParameters.java
new file mode 100644
index 000000000..ef031e8e7
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/Rsp1aCompositeParameters.java
@@ -0,0 +1,44 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.composite;
+
+import com.github.dsheirer.sdrplay.device.DeviceType;
+import com.github.dsheirer.sdrplay.parameter.device.Rsp1aDeviceParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.Rsp1aTunerParameters;
+
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+
+/**
+ * RSP1A Composite parameters (device and tuner)
+ */
+public class Rsp1aCompositeParameters extends CompositeParameters
+{
+ /**
+ * Constructs an instance from the foreign memory segment
+ *
+ * @param memorySegment for the composite structure in foreign memory
+ * @param memorySession for allocating additional memory segments for the sub-structures.
+ */
+ public Rsp1aCompositeParameters(MemorySegment memorySegment, MemorySession memorySession)
+ {
+ super(DeviceType.RSP1A, memorySegment, memorySession);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/Rsp2CompositeParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/Rsp2CompositeParameters.java
new file mode 100644
index 000000000..e09116452
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/Rsp2CompositeParameters.java
@@ -0,0 +1,44 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.composite;
+
+import com.github.dsheirer.sdrplay.device.DeviceType;
+import com.github.dsheirer.sdrplay.parameter.device.Rsp2DeviceParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.Rsp2TunerParameters;
+
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+
+/**
+ * RSP2 Composite parameters (device and tuner)
+ */
+public class Rsp2CompositeParameters extends CompositeParameters
+{
+ /**
+ * Constructs an instance from the foreign memory segment
+ *
+ * @param memorySegment for the composite structure in foreign memory
+ * @param memorySession for allocating additional memory segments for the sub-structures.
+ */
+ public Rsp2CompositeParameters(MemorySegment memorySegment, MemorySession memorySession)
+ {
+ super(DeviceType.RSP2, memorySegment, memorySession);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/RspDuoCompositeParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/RspDuoCompositeParameters.java
new file mode 100644
index 000000000..764c3245c
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/RspDuoCompositeParameters.java
@@ -0,0 +1,86 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.composite;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_DeviceParamsT;
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_RxChannelParamsT;
+import com.github.dsheirer.sdrplay.device.DeviceType;
+import com.github.dsheirer.sdrplay.parameter.control.ControlParameters;
+import com.github.dsheirer.sdrplay.parameter.device.RspDuoDeviceParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.RspDuoTunerParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.TunerParametersFactory;
+
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+
+/**
+ * RSPduo Composite parameters (device and two tuners)
+ */
+public class RspDuoCompositeParameters extends CompositeParameters
+{
+ private RspDuoTunerParameters mTunerBParameters;
+ private ControlParameters mControlBParameters;
+
+ /**
+ * Constructs an instance from the foreign memory segment
+ *
+ * @param memorySegment for the composite structure in foreign memory
+ * @param memorySession for allocating additional memory segments for the sub-structures.
+ */
+ public RspDuoCompositeParameters(MemorySegment memorySegment, MemorySession memorySession)
+ {
+ super(DeviceType.RSPduo, memorySegment, memorySession);
+
+ MemoryAddress memoryAddressRxB = sdrplay_api_DeviceParamsT.rxChannelB$get(memorySegment);
+ MemorySegment memorySegmentRxB = sdrplay_api_RxChannelParamsT.ofAddress(memoryAddressRxB, memorySession);
+ mTunerBParameters = (RspDuoTunerParameters) TunerParametersFactory.create(DeviceType.RSPduo, memorySegmentRxB);
+
+ MemorySegment tunerBControlParametersMemorySegment = sdrplay_api_RxChannelParamsT.ctrlParams$slice(memorySegmentRxB);
+ mControlBParameters = new ControlParameters(tunerBControlParametersMemorySegment);
+ }
+
+ /**
+ * Tuner B Tuner Parameters
+ */
+ public RspDuoTunerParameters getTunerBParameters()
+ {
+ return mTunerBParameters;
+ }
+
+ /**
+ * Tuner B Control Parameters
+ */
+ public ControlParameters getControlBParameters()
+ {
+ return mControlBParameters;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Device Composite Parameters\n");
+ sb.append("\tDevice Parameters:\n").append(getDeviceParameters()).append("\n");
+ sb.append("\tTuner Channel A:\n").append(getTunerAParameters()).append("\n");
+ sb.append("\tTuner Channel B:\n").append(getTunerBParameters()).append("\n");
+ return sb.toString();
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/RspDxCompositeParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/RspDxCompositeParameters.java
new file mode 100644
index 000000000..711e612ac
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/composite/RspDxCompositeParameters.java
@@ -0,0 +1,44 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.composite;
+
+import com.github.dsheirer.sdrplay.device.DeviceType;
+import com.github.dsheirer.sdrplay.parameter.device.RspDxDeviceParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.RspDxTunerParameters;
+
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+
+/**
+ * RSPdx Composite parameters (device and receiver)
+ */
+public class RspDxCompositeParameters extends CompositeParameters
+{
+ /**
+ * Constructs an instance from the foreign memory segment
+ *
+ * @param memorySegment for the composite structure in foreign memory
+ * @param memorySession for allocating additional memory segments for the sub-structures.
+ */
+ public RspDxCompositeParameters(MemorySegment memorySegment, MemorySession memorySession)
+ {
+ super(DeviceType.RSPdx, memorySegment, memorySession);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/AdsbMode.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/AdsbMode.java
new file mode 100644
index 000000000..96f616aad
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/AdsbMode.java
@@ -0,0 +1,74 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.control;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * ADSB Mode (for ADS-B decoding applications)
+ */
+public enum AdsbMode
+{
+ NO_DECIMATION_LOWPASS(sdrplay_api_h.sdrplay_api_ADSB_NO_DECIMATION_LOWPASS(), "No Decimation-Lowpass"),
+ NO_DECIMATION_BANDPASS_2_MHZ(sdrplay_api_h.sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_2MHZ(), "No Decimation-Bandpass 2 MHz"),
+ NO_DECIMATION_BANDPASS_3_MHZ(sdrplay_api_h.sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_3MHZ(), "No Decimation-Bandpass 3 MHz"),
+ DECIMATION(sdrplay_api_h.sdrplay_api_ADSB_DECIMATION(), "Decimation");
+
+ private int mValue;
+ private String mDescription;
+
+ AdsbMode(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or DECIMATION if the code is not recognized
+ */
+ public static AdsbMode fromValue(int value)
+ {
+ for(AdsbMode status: AdsbMode.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return DECIMATION;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/Agc.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/Agc.java
new file mode 100644
index 000000000..e88b579f6
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/Agc.java
@@ -0,0 +1,154 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.control;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_AgcT;
+import com.github.dsheirer.sdrplay.util.Flag;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * AGC structure (sdrplay_api_AgcT)
+ */
+public class Agc
+{
+ private MemorySegment mMemorySegment;
+
+ /**
+ * Constructs an instance from the foreign memory segment
+ */
+ public Agc(MemorySegment memorySegment)
+ {
+ mMemorySegment = memorySegment;
+ }
+
+ /**
+ * Foreign memory segment for this structure
+ */
+ private MemorySegment getMemorySegment()
+ {
+ return mMemorySegment;
+ }
+
+ /**
+ * AGC Control (mode)
+ */
+ public AgcMode getAgcMode()
+ {
+ return AgcMode.fromValue(sdrplay_api_AgcT.enable$get(getMemorySegment()));
+ }
+
+ /**
+ * Sets AGC Control (mode)
+ */
+ public void setAgcMode(AgcMode mode)
+ {
+ sdrplay_api_AgcT.enable$set(getMemorySegment(), mode.getValue());
+ }
+
+ /**
+ * Set point dBfs
+ */
+ public int getSetPointDbfs()
+ {
+ return sdrplay_api_AgcT.setPoint_dBfs$get(getMemorySegment());
+ }
+
+ /**
+ * Sets the set point dBfs
+ */
+ public void setSetPointDbfs(int setPointDbfs)
+ {
+ sdrplay_api_AgcT.setPoint_dBfs$set(getMemorySegment(), setPointDbfs);
+ }
+
+ /**
+ * Attack rate in milliseconds
+ */
+ public int getAttackMs()
+ {
+ return sdrplay_api_AgcT.attack_ms$get(getMemorySegment());
+ }
+
+ /**
+ * Sets the attack rate in milliseconds
+ */
+ public void setAttackMs(int attackMs)
+ {
+ sdrplay_api_AgcT.attack_ms$set(getMemorySegment(), (short)attackMs);
+ }
+
+ /**
+ * Decay rate in milliseconds
+ */
+ public int getDecayMs()
+ {
+ return sdrplay_api_AgcT.decay_ms$get(getMemorySegment());
+ }
+
+ /**
+ * Sets the decay rate in milliseconds
+ */
+ public void setDecayMs(int decayMs)
+ {
+ sdrplay_api_AgcT.decay_ms$set(getMemorySegment(), (short)decayMs);
+ }
+
+ /**
+ * Decay delay rate in milliseconds
+ */
+ public int getDecayDelayMs()
+ {
+ return sdrplay_api_AgcT.decay_delay_ms$get(getMemorySegment());
+ }
+
+ /**
+ * Sets the decay delay rate in milliseconds
+ */
+ public void setDecayDelayMs(int decayDelayMs)
+ {
+ sdrplay_api_AgcT.decay_delay_ms$set(getMemorySegment(), (short)decayDelayMs);
+ }
+
+ /**
+ * Decay threshold in dB
+ */
+ public int getDecayThresholdDb()
+ {
+ return sdrplay_api_AgcT.decay_threshold_dB$get(getMemorySegment());
+ }
+
+ /**
+ * Sets the decay threshold in dB
+ */
+ public void setDecayThresholdDb(int decayThresholdDb)
+ {
+ sdrplay_api_AgcT.decay_threshold_dB$set(getMemorySegment(), (short)decayThresholdDb);
+ }
+
+ /**
+ * Sets the changes to be applied as a synchronous update
+ */
+ public void setSynchronousUpdate(boolean syncUpdate)
+ {
+ //Note: this is supposed to be an integer value ... does it represent a boolean (0 or 1) or something else??
+ sdrplay_api_AgcT.syncUpdate$set(getMemorySegment(), Flag.of(syncUpdate));
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/AgcMode.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/AgcMode.java
new file mode 100644
index 000000000..ce8cecf41
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/AgcMode.java
@@ -0,0 +1,75 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.control;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * Automatic Gain Control (AGC) Control (mode)
+ */
+public enum AgcMode
+{
+ DISABLE(sdrplay_api_h.sdrplay_api_AGC_DISABLE(), "DISABLE"),
+ AGC_100_HZ(sdrplay_api_h.sdrplay_api_AGC_100HZ(), "100 Hz"),
+ AGC_50_HZ(sdrplay_api_h.sdrplay_api_AGC_50HZ(), "50 Hz"),
+ AGC_5_HZ(sdrplay_api_h.sdrplay_api_AGC_5HZ(), "5 Hz"),
+ ENABLE(sdrplay_api_h.sdrplay_api_AGC_CTRL_EN(), "ENABLE");
+
+ private int mValue;
+ private String mDescription;
+
+ AgcMode(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or DISABLE if the code is not recognized
+ */
+ public static AgcMode fromValue(int value)
+ {
+ for(AgcMode status: AgcMode.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return DISABLE;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/ControlParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/ControlParameters.java
new file mode 100644
index 000000000..cbca315b6
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/ControlParameters.java
@@ -0,0 +1,94 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.control;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_ControlParamsT;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * Control Parameters structure (sdrplay_api_ControlParamsT)
+ */
+public class ControlParameters
+{
+ private MemorySegment mMemorySegment;
+ private DcOffset mDcOffset;
+ private Decimation mDecimation;
+ private Agc mAgc;
+
+ /**
+ * Creates an instance from the foreign memory segment
+ */
+ public ControlParameters(MemorySegment memorySegment)
+ {
+ mMemorySegment = memorySegment;
+ mDcOffset = new DcOffset(sdrplay_api_ControlParamsT.dcOffset$slice(memorySegment));
+ mDecimation = new Decimation(sdrplay_api_ControlParamsT.decimation$slice(memorySegment));
+ mAgc = new Agc(sdrplay_api_ControlParamsT.agc$slice(memorySegment));
+ }
+
+ /**
+ * Foreign memory segment for this structure
+ */
+ private MemorySegment getMemorySegment()
+ {
+ return mMemorySegment;
+ }
+
+ /**
+ * DC offset settings for DC and IQ correction
+ */
+ public DcOffset getDcOffset()
+ {
+ return mDcOffset;
+ }
+
+ /**
+ * Decimation settings
+ */
+ public Decimation getDecimation()
+ {
+ return mDecimation;
+ }
+
+ /**
+ * Automatic Gain Control (AGC) settings
+ */
+ public Agc getAgc()
+ {
+ return mAgc;
+ }
+
+ /**
+ * Current ADSB mode
+ */
+ public AdsbMode getAdsbMode()
+ {
+ return AdsbMode.fromValue(sdrplay_api_ControlParamsT.adsbMode$get(getMemorySegment()));
+ }
+
+ /**
+ * Sets ADSB mode
+ */
+ public void setAdsbMode(AdsbMode mode)
+ {
+ sdrplay_api_ControlParamsT.adsbMode$set(getMemorySegment(), mode.getValue());
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/DcOffset.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/DcOffset.java
new file mode 100644
index 000000000..e95783dbc
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/DcOffset.java
@@ -0,0 +1,81 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.control;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_DcOffsetT;
+import com.github.dsheirer.sdrplay.util.Flag;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * DC Offset structure (sdrplay_api_DCOffsetT)
+ */
+public class DcOffset
+{
+ private MemorySegment mMemorySegment;
+
+ /**
+ * Constructs an instance from the foreign memory segment
+ */
+ public DcOffset(MemorySegment memorySegment)
+ {
+ mMemorySegment = memorySegment;
+ }
+
+ /**
+ * Foreign memory segment for this structure
+ */
+ private MemorySegment getMemorySegment()
+ {
+ return mMemorySegment;
+ }
+
+ /**
+ * Indicates if DC correction is enabled.
+ */
+ public boolean isDC()
+ {
+ return Flag.evaluate(sdrplay_api_DcOffsetT.DCenable$get(getMemorySegment()));
+ }
+
+ /**
+ * Enable or disable DC correction
+ */
+ public void setDC(boolean enable)
+ {
+ sdrplay_api_DcOffsetT.DCenable$set(getMemorySegment(), Flag.of(enable));
+ }
+
+ /**
+ * Indicates if IQ correction is enabled
+ */
+ public boolean isIQ()
+ {
+ return Flag.evaluate(sdrplay_api_DcOffsetT.IQenable$get(getMemorySegment()));
+ }
+
+ /**
+ * Enable or disable IQ correction
+ */
+ public void setIQ(boolean enable)
+ {
+ sdrplay_api_DcOffsetT.IQenable$set(getMemorySegment(), Flag.of(enable));
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/Decimation.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/Decimation.java
new file mode 100644
index 000000000..13849ed3a
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/control/Decimation.java
@@ -0,0 +1,97 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.control;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_DecimationT;
+import com.github.dsheirer.sdrplay.util.Flag;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * Decimation structure (sdrplay_api_DecimationT)
+ */
+public class Decimation
+{
+ private MemorySegment mMemorySegment;
+
+ /**
+ * Constructs an instance from the foreign memory segment
+ */
+ public Decimation(MemorySegment memorySegment)
+ {
+ mMemorySegment = memorySegment;
+ }
+
+ /**
+ * Foreign memory segment for this structure
+ */
+ public MemorySegment getMemorySegment()
+ {
+ return mMemorySegment;
+ }
+
+ /**
+ * Indicates if decimation is enabled
+ */
+ public boolean isEnabled()
+ {
+ return Flag.evaluate(sdrplay_api_DecimationT.enable$get(getMemorySegment()));
+ }
+
+ /**
+ * Enable or disable decimation
+ */
+ public void setEnabled(boolean enable)
+ {
+ sdrplay_api_DecimationT.enable$set(getMemorySegment(), Flag.of(enable));
+ }
+
+ /**
+ * Decimation factor
+ */
+ public int getDecimationFactor()
+ {
+ return sdrplay_api_DecimationT.decimationFactor$get(getMemorySegment());
+ }
+
+ /**
+ * Sets the decimation factor
+ */
+ public void setDecimationFactor(int decimationFactor)
+ {
+ sdrplay_api_DecimationT.decimationFactor$set(getMemorySegment(), (byte)decimationFactor);
+ }
+
+ /**
+ * Indicates if the wideband signal setting is enabled
+ */
+ public boolean isWideBandSignal()
+ {
+ return Flag.evaluate(sdrplay_api_DecimationT.wideBandSignal$get(getMemorySegment()));
+ }
+
+ /**
+ * Enables or disables the wideband signal setting
+ */
+ public void setWideBandSignal(boolean enable)
+ {
+ sdrplay_api_DecimationT.wideBandSignal$set(getMemorySegment(), Flag.of(enable));
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/DeviceParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/DeviceParameters.java
new file mode 100644
index 000000000..68960bbe4
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/DeviceParameters.java
@@ -0,0 +1,132 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.device;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_DevParamsT;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * Device Parameters structure (sdrplay_api_DevParamsT)
+ */
+public abstract class DeviceParameters
+{
+ private MemorySegment mMemorySegment;
+ private SamplingFrequency mSamplingFrequency;
+ private SynchronousUpdate mSynchronousUpdate;
+ private ResetFlags mResetFlags;
+
+ public DeviceParameters(MemorySegment memorySegment)
+ {
+ mMemorySegment = memorySegment;
+ mSamplingFrequency = new SamplingFrequency(sdrplay_api_DevParamsT.fsFreq$slice(memorySegment));
+ mSynchronousUpdate = new SynchronousUpdate(sdrplay_api_DevParamsT.syncUpdate$slice(memorySegment));
+ mResetFlags = new ResetFlags(sdrplay_api_DevParamsT.resetFlags$slice(memorySegment));
+ }
+
+ /**
+ * Foreign memory segment for this device parameters instance
+ */
+ protected MemorySegment getMemorySegment()
+ {
+ return mMemorySegment;
+ }
+
+ /**
+ * Parts Per Million (ppm) center frequency correction value.
+ * @return ppm
+ */
+ public double getPPM()
+ {
+ return sdrplay_api_DevParamsT.ppm$get(getMemorySegment());
+ }
+
+ /**
+ * Sets the parts per million (ppm) center frequency correction value
+ * @param ppm parts per million
+ */
+ public void setPPM(double ppm)
+ {
+ sdrplay_api_DevParamsT.ppm$set(getMemorySegment(), ppm);
+ }
+
+ /**
+ * Sampling frequency structure.
+ */
+ public SamplingFrequency getSamplingFrequency()
+ {
+ return mSamplingFrequency;
+ }
+
+ /**
+ * Synchronous update structure
+ */
+ public SynchronousUpdate getSynchronousUpdate()
+ {
+ return mSynchronousUpdate;
+ }
+
+ /**
+ * Reset request flags
+ */
+ public ResetFlags getResetFlags()
+ {
+ return mResetFlags;
+ }
+
+ /**
+ * USB Transfer mode currently used by the device
+ */
+ public TransferMode getTransferMode()
+ {
+ return TransferMode.fromValue(sdrplay_api_DevParamsT.mode$get(getMemorySegment()));
+ }
+
+ /**
+ * Sets the USB transfer mode used by the device
+ */
+ public void setTransferMode(TransferMode transferMode)
+ {
+ if(transferMode != TransferMode.UNKNOWN)
+ {
+ sdrplay_api_DevParamsT.mode$set(getMemorySegment(), transferMode.getValue());
+ }
+ }
+
+ public long getSamplesPerPacket()
+ {
+ return sdrplay_api_DevParamsT.samplesPerPkt$get(getMemorySegment());
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("\tDevice Parameters").append("\n");
+ sb.append("\t\tPPM: ").append(getPPM()).append("\n");
+ sb.append("\t\tSample Rate: ").append(getSamplingFrequency()).append("\n");
+ sb.append("\t\tSamples Per Packet: ").append(getSamplesPerPacket()).append("\n");
+ sb.append("\t\tSync Update: ").append(getSynchronousUpdate()).append("\n");
+ sb.append("\t\tReset Flags: ").append(getResetFlags()).append("\n");
+ sb.append("\t\tTransfer Mode: ").append(getTransferMode()).append("\n");
+
+ return sb.toString();
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/DeviceParametersFactory.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/DeviceParametersFactory.java
new file mode 100644
index 000000000..af528ba22
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/DeviceParametersFactory.java
@@ -0,0 +1,60 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.device;
+
+import com.github.dsheirer.sdrplay.device.DeviceType;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * Creates device parameters instance from a foreign memory segment
+ */
+public class DeviceParametersFactory
+{
+ /**
+ * Create a device parameters instance
+ * @param deviceType for the device
+ * @param memorySegment of foreign memory representing the device type
+ * @return instance
+ */
+ public static DeviceParameters create(DeviceType deviceType, MemorySegment memorySegment)
+ {
+ switch(deviceType)
+ {
+ case RSP1 -> {
+ return new Rsp1DeviceParameters(memorySegment);
+ }
+ case RSP1A -> {
+ return new Rsp1aDeviceParameters(memorySegment);
+ }
+ case RSP2 -> {
+ return new Rsp2DeviceParameters(memorySegment);
+ }
+ case RSPduo -> {
+ return new RspDuoDeviceParameters(memorySegment);
+ }
+ case RSPdx -> {
+ return new RspDxDeviceParameters(memorySegment);
+ }
+ }
+
+ throw new IllegalArgumentException("Unrecognized Device Type: " + deviceType);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/ResetFlags.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/ResetFlags.java
new file mode 100644
index 000000000..494a575b1
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/ResetFlags.java
@@ -0,0 +1,74 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.device;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_ResetFlagsT;
+import com.github.dsheirer.sdrplay.util.Flag;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * Reset Flags structure
+ */
+public class ResetFlags
+{
+ private MemorySegment mMemorySegment;
+
+ /**
+ * Constructs an instance from a foreign memory segment and transfers the structure fields into this instance.
+ * @param memorySegment pointer
+ */
+ public ResetFlags(MemorySegment memorySegment)
+ {
+ mMemorySegment = memorySegment;
+ }
+
+ /**
+ * Foreign memory segment
+ */
+ private MemorySegment getMemorySegment()
+ {
+ return mMemorySegment;
+ }
+
+ /**
+ * Request a reset of the gain reduction
+ */
+ public void resetGain(boolean reset)
+ {
+ sdrplay_api_ResetFlagsT.resetGainUpdate$set(getMemorySegment(), reset ? Flag.TRUE : Flag.FALSE);
+ }
+
+ /**
+ * Request a reset of the center frequency value
+ */
+ public void resetFrequency(boolean reset)
+ {
+ sdrplay_api_ResetFlagsT.resetRfUpdate$set(getMemorySegment(), reset ? Flag.TRUE : Flag.FALSE);
+ }
+
+ /**
+ * Request a reset of the sample rate value.
+ */
+ public void resetSampleRate(boolean reset)
+ {
+ sdrplay_api_ResetFlagsT.resetFsUpdate$set(getMemorySegment(), reset ? Flag.TRUE : Flag.FALSE);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/Rsp1DeviceParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/Rsp1DeviceParameters.java
new file mode 100644
index 000000000..7fbb06989
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/Rsp1DeviceParameters.java
@@ -0,0 +1,37 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.device;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * RSP-1 Device Parameters structure
+ */
+public class Rsp1DeviceParameters extends DeviceParameters
+{
+ /**
+ * Constructs an instance
+ * @param memorySegment for this structure
+ */
+ public Rsp1DeviceParameters(MemorySegment memorySegment)
+ {
+ super(memorySegment);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/Rsp1aDeviceParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/Rsp1aDeviceParameters.java
new file mode 100644
index 000000000..d89f3ce9a
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/Rsp1aDeviceParameters.java
@@ -0,0 +1,84 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.device;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_DevParamsT;
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_Rsp1aParamsT;
+import com.github.dsheirer.sdrplay.util.Flag;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * RSP-1A Device Parameters structure
+ */
+public class Rsp1aDeviceParameters extends DeviceParameters
+{
+ private MemorySegment mRsp1AMemorySegment;
+
+ /**
+ * Constructs an instance
+ * @param memorySegment for this structure
+ */
+ public Rsp1aDeviceParameters(MemorySegment memorySegment)
+ {
+ super(memorySegment);
+ mRsp1AMemorySegment = sdrplay_api_DevParamsT.rsp1aParams$slice(memorySegment);
+ }
+
+ /**
+ * Foreign memory segment representing this structure
+ */
+ private MemorySegment getRsp1AMemorySegment()
+ {
+ return mRsp1AMemorySegment;
+ }
+
+ /**
+ * Indicates if RF notch is enabled.
+ */
+ public boolean isRFNotch()
+ {
+ return Flag.evaluate(sdrplay_api_Rsp1aParamsT.rfNotchEnable$get(getRsp1AMemorySegment()));
+ }
+
+ /**
+ * Enables or disables the RF notch.
+ */
+ public void setRFNotch(boolean enable)
+ {
+ sdrplay_api_Rsp1aParamsT.rfNotchEnable$set(getRsp1AMemorySegment(), Flag.of(enable));
+ }
+
+ /**
+ * Indicates if DAB RF notch is enabled
+ */
+ public boolean isRfDabNotch()
+ {
+ return Flag.evaluate(sdrplay_api_Rsp1aParamsT.rfDabNotchEnable$get(getRsp1AMemorySegment()));
+ }
+
+ /**
+ * Enables or disables the DAB RF notch
+ */
+ public void setRfDabNotch(boolean enable)
+ {
+ sdrplay_api_Rsp1aParamsT.rfDabNotchEnable$set(getRsp1AMemorySegment(), Flag.of(enable));
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/Rsp2DeviceParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/Rsp2DeviceParameters.java
new file mode 100644
index 000000000..7e24ee5d6
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/Rsp2DeviceParameters.java
@@ -0,0 +1,68 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.device;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_DevParamsT;
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_Rsp2ParamsT;
+import com.github.dsheirer.sdrplay.util.Flag;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * RSP-2 Device Parameters structure
+ */
+public class Rsp2DeviceParameters extends DeviceParameters
+{
+ private MemorySegment mRsp2MemorySegment;
+
+ /**
+ * Constructs an instance
+ * @param memorySegment for this structure
+ */
+ public Rsp2DeviceParameters(MemorySegment memorySegment)
+ {
+ super(memorySegment);
+ mRsp2MemorySegment = sdrplay_api_DevParamsT.rsp2Params$slice(memorySegment);
+ }
+
+ /**
+ * Foreign memory segment representing this structure
+ */
+ private MemorySegment getRsp2MemorySegment()
+ {
+ return mRsp2MemorySegment;
+ }
+
+ /**
+ * Indicates if the external reference output is enabled
+ */
+ public boolean isExternalReferenceOutput()
+ {
+ return Flag.evaluate(sdrplay_api_Rsp2ParamsT.extRefOutputEn$get(getRsp2MemorySegment()));
+ }
+
+ /**
+ * Enables or disables the external reference output
+ */
+ public void setExternalReferenceOutput(boolean enable)
+ {
+ sdrplay_api_Rsp2ParamsT.extRefOutputEn$set(getRsp2MemorySegment(), Flag.of(enable));
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/RspDuoDeviceParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/RspDuoDeviceParameters.java
new file mode 100644
index 000000000..b141ddf62
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/RspDuoDeviceParameters.java
@@ -0,0 +1,68 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.device;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_DevParamsT;
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_RspDuoParamsT;
+import com.github.dsheirer.sdrplay.util.Flag;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * RSPduo Device Parameters structure
+ */
+public class RspDuoDeviceParameters extends DeviceParameters
+{
+ private MemorySegment mRspDuoMemorySegment;
+
+ /**
+ * Constructs an instance
+ * @param memorySegment for this structure
+ */
+ public RspDuoDeviceParameters(MemorySegment memorySegment)
+ {
+ super(memorySegment);
+ mRspDuoMemorySegment = sdrplay_api_DevParamsT.rspDuoParams$slice(memorySegment);
+ }
+
+ /**
+ * Foreign memory segment representing this structure
+ */
+ private MemorySegment getRspDuoMemorySegment()
+ {
+ return mRspDuoMemorySegment;
+ }
+
+ /**
+ * Indicates if the external reference output is enabled
+ */
+ public boolean isExternalReferenceOutput()
+ {
+ return Flag.evaluate(sdrplay_api_RspDuoParamsT.extRefOutputEn$get(getRspDuoMemorySegment()));
+ }
+
+ /**
+ * Enables or disables the external reference output
+ */
+ public void setExternalReferenceOutput(boolean enable)
+ {
+ sdrplay_api_RspDuoParamsT.extRefOutputEn$set(getRspDuoMemorySegment(), Flag.of(enable));
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/RspDxDeviceParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/RspDxDeviceParameters.java
new file mode 100644
index 000000000..6a2989fc8
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/RspDxDeviceParameters.java
@@ -0,0 +1,132 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.device;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_DevParamsT;
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_RspDxParamsT;
+import com.github.dsheirer.sdrplay.parameter.tuner.RspDxAntenna;
+import com.github.dsheirer.sdrplay.util.Flag;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * RSP-DX Device Parameters structure
+ */
+public class RspDxDeviceParameters extends DeviceParameters
+{
+ private MemorySegment mRspDxMemorySegment;
+
+ /**
+ * Constructs an instance from the foreign memory segment.
+ */
+ public RspDxDeviceParameters(MemorySegment memorySegment)
+ {
+ super(memorySegment);
+ mRspDxMemorySegment = sdrplay_api_DevParamsT.rspDxParams$slice(memorySegment);
+ }
+
+ /**
+ * Foreign memory segment for this structure
+ */
+ private MemorySegment getRspDxMemorySegment()
+ {
+ return mRspDxMemorySegment;
+ }
+
+ /**
+ * Indicates if High Dynamic Range (HDR) is enabled
+ */
+ public boolean isHdr()
+ {
+ return Flag.evaluate(sdrplay_api_RspDxParamsT.hdrEnable$get(getRspDxMemorySegment()));
+ }
+
+ /**
+ * Enables or disables High Dynamic Range (HDR)
+ */
+ public void setHdr(boolean enable)
+ {
+ sdrplay_api_RspDxParamsT.hdrEnable$set(getRspDxMemorySegment(), Flag.of(enable));
+ }
+
+ /**
+ * Indicates if Bias-T is enabled
+ */
+ public boolean isBiasT()
+ {
+ return Flag.evaluate(sdrplay_api_RspDxParamsT.biasTEnable$get(getRspDxMemorySegment()));
+ }
+
+ /**
+ * Enables or disables Bias-T
+ */
+ public void setBiasT(boolean enable)
+ {
+ sdrplay_api_RspDxParamsT.biasTEnable$set(getRspDxMemorySegment(), Flag.of(enable));
+ }
+
+ /**
+ * RSPdx Antenna Setting
+ */
+ public RspDxAntenna getRspDxAntenna()
+ {
+ return RspDxAntenna.fromValue(sdrplay_api_RspDxParamsT.antennaSel$get(getRspDxMemorySegment()));
+ }
+
+ /**
+ * Selects the RSPdx Antenna
+ */
+ public void setRspDxAntenna(RspDxAntenna rspDxAntenna)
+ {
+ sdrplay_api_RspDxParamsT.antennaSel$set(getRspDxMemorySegment(), rspDxAntenna.getValue());
+ }
+
+ /**
+ * Indicates if RF notch is enabled
+ */
+ public boolean isRfNotch()
+ {
+ return Flag.evaluate(sdrplay_api_RspDxParamsT.rfNotchEnable$get(getRspDxMemorySegment()));
+ }
+
+ /**
+ * Enables or disables RF notch
+ */
+ public void setRfNotch(boolean enable)
+ {
+ sdrplay_api_RspDxParamsT.rfNotchEnable$set(getRspDxMemorySegment(), Flag.of(enable));
+ }
+
+ /**
+ * Indicates if the RF DAB notch is enabled
+ */
+ public boolean isRfDabNotch()
+ {
+ return Flag.evaluate(sdrplay_api_RspDxParamsT.rfDabNotchEnable$get(getRspDxMemorySegment()));
+ }
+
+ /**
+ * Enables or disables the RF DAB notch
+ */
+ public void setRfDabNotch(boolean enable)
+ {
+ sdrplay_api_RspDxParamsT.rfDabNotchEnable$set(getRspDxMemorySegment(), Flag.of(enable));
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/SamplingFrequency.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/SamplingFrequency.java
new file mode 100644
index 000000000..d8c2a33a7
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/SamplingFrequency.java
@@ -0,0 +1,87 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.device;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_FsFreqT;
+import com.github.dsheirer.sdrplay.util.Flag;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * Sample Rate structure
+ */
+public class SamplingFrequency
+{
+ private Logger mLog = LoggerFactory.getLogger(SamplingFrequency.class);
+ private MemorySegment mMemorySegment;
+
+ /**
+ * Constructs an instance from a foreign memory segment and transfers the structure fields into this instance.
+ * @param memorySegment pointer
+ */
+ public SamplingFrequency(MemorySegment memorySegment)
+ {
+ mMemorySegment = memorySegment;
+ }
+
+ private MemorySegment getMemorySegment()
+ {
+ return mMemorySegment;
+ }
+
+ /**
+ * Sample rate frequency
+ * @return frequency in Hertz
+ */
+ public double getSampleRate()
+ {
+ return sdrplay_api_FsFreqT.fsHz$get(getMemorySegment());
+ }
+
+ /**
+ * Applies the requested sample rate to the device parameters
+ * @param sampleRate requested rate
+ * @param synchronousUpdate request
+ * @param recalibrate request
+ */
+ public void setSampleRate(double sampleRate, boolean synchronousUpdate, boolean recalibrate)
+ {
+ sdrplay_api_FsFreqT.fsHz$set(getMemorySegment(), sampleRate);
+ sdrplay_api_FsFreqT.syncUpdate$set(getMemorySegment(), synchronousUpdate ? Flag.TRUE : Flag.FALSE);
+ sdrplay_api_FsFreqT.reCal$set(getMemorySegment(), recalibrate ? Flag.TRUE : Flag.FALSE);
+ }
+
+ /**
+ * Applies the requested sample rate to the device parameters with synchronous update and recalibrate set to false.
+ * @param sampleRate requested rate
+ */
+ public void setSampleRate(double sampleRate)
+ {
+ setSampleRate(sampleRate, false, false);
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Sample Rate:" + getSampleRate();
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/SynchronousUpdate.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/SynchronousUpdate.java
new file mode 100644
index 000000000..93b7c9b2c
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/SynchronousUpdate.java
@@ -0,0 +1,57 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.device;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_SyncUpdateT;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * Sync Update structure
+ */
+public class SynchronousUpdate
+{
+ private MemorySegment mMemorySegment;
+
+ /**
+ * Constructs an instance from a foreign memory segment
+ * @param memorySegment pointer
+ */
+ public SynchronousUpdate(MemorySegment memorySegment)
+ {
+ mMemorySegment = memorySegment;
+ }
+
+ private MemorySegment getMemorySegment()
+ {
+ return mMemorySegment;
+ }
+
+ /**
+ * Sets the sample number and period to apply to both tuners for a synchronous update.
+ * @param sampleNumber value
+ * @param period value
+ */
+ public void set(int sampleNumber, int period)
+ {
+ sdrplay_api_SyncUpdateT.sampleNum$set(getMemorySegment(), sampleNumber);
+ sdrplay_api_SyncUpdateT.period$set(getMemorySegment(), period);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/TransferMode.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/TransferMode.java
new file mode 100644
index 000000000..207396a96
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/device/TransferMode.java
@@ -0,0 +1,73 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.device;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * USB Transfer Mode
+ */
+public enum TransferMode
+{
+ ISOCHRONOUS(sdrplay_api_h.sdrplay_api_ISOCH(), "ISOCHRONOUS"),
+ BULK(sdrplay_api_h.sdrplay_api_BULK(), "BULK"),
+ UNKNOWN(-1, "UNKNOWN");
+
+ private int mValue;
+ private String mDescription;
+
+ TransferMode(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or UNKNOWN if the code is not recognized
+ */
+ public static TransferMode fromValue(int value)
+ {
+ for(TransferMode status: TransferMode.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return UNKNOWN;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/EventParametersFactory.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/EventParametersFactory.java
new file mode 100644
index 000000000..28477b828
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/EventParametersFactory.java
@@ -0,0 +1,58 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.event;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_EventParamsT;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * Event Parameters structure (sdrplay_api_EventParamsT)
+ */
+public class EventParametersFactory
+{
+ private GainCallbackParameters mGainCallbackParameters;
+ private PowerOverloadCallbackParameters mPowerOverloadCallbackParameters;
+ private RspDuoModeCallbackParameters mRspDuoModeCallbackParameters;
+
+ /**
+ * Gain event callback parameters
+ */
+ public static GainCallbackParameters createGainCallbackParameters(MemorySegment memorySegment)
+ {
+ return new GainCallbackParameters(sdrplay_api_EventParamsT.gainParams$slice(memorySegment));
+ }
+
+ /**
+ * Power overload event callback parameters
+ */
+ public static PowerOverloadCallbackParameters createPowerOverloadCallbackParameters(MemorySegment memorySegment)
+ {
+ return new PowerOverloadCallbackParameters(sdrplay_api_EventParamsT.powerOverloadParams$slice(memorySegment));
+ }
+
+ /**
+ * RSPduo mode event callback parameters
+ */
+ public static RspDuoModeCallbackParameters createRspDuoModeCallbackParameters(MemorySegment memorySegment)
+ {
+ return new RspDuoModeCallbackParameters(sdrplay_api_EventParamsT.rspDuoModeParams$slice(memorySegment));
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/EventType.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/EventType.java
new file mode 100644
index 000000000..3dd6eacc3
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/EventType.java
@@ -0,0 +1,75 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.event;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * (Callback) Event Type (sdrplay_api_EventT)
+ */
+public enum EventType
+{
+ GAIN_CHANGE(sdrplay_api_h.sdrplay_api_GainChange(), "GAIN CHANGE"),
+ POWER_OVERLOAD_CHANGE(sdrplay_api_h.sdrplay_api_PowerOverloadChange(), "POWER OVERLOAD CHANGE"),
+ DEVICE_REMOVED(sdrplay_api_h.sdrplay_api_DeviceRemoved(), "DEVICE REMOVED"),
+ RSP_DUO_MODE_CHANGE(sdrplay_api_h.sdrplay_api_RspDuoModeChange(), "RSP-DUO MODE CHANGE"),
+ UNKNOWN(-1, "UNKNOWN");
+
+ private int mValue;
+ private String mDescription;
+
+ EventType(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or UNKNOWN if the code is not recognized
+ */
+ public static EventType fromValue(int value)
+ {
+ for(EventType status: EventType.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return UNKNOWN;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/GainCallbackParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/GainCallbackParameters.java
new file mode 100644
index 000000000..878dc0935
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/GainCallbackParameters.java
@@ -0,0 +1,81 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.event;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_GainCbParamT;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * Gain Callback Parameters structure (sdrplay_api_GainCbParamT)
+ */
+public class GainCallbackParameters
+{
+ private static final Logger mLog = LoggerFactory.getLogger(GainCallbackParameters.class);
+ private int mGainReductionDb;
+ private int mLnaGainReductionDb;
+ private double mCurrentGain;
+
+ /**
+ * Constructs an instance from the foreign memory segment
+ */
+ public GainCallbackParameters(MemorySegment memorySegment)
+ {
+ mGainReductionDb = sdrplay_api_GainCbParamT.gRdB$get(memorySegment);
+ mLnaGainReductionDb = sdrplay_api_GainCbParamT.lnaGRdB$get(memorySegment);
+ mCurrentGain = sdrplay_api_GainCbParamT.currGain$get(memorySegment);
+ }
+
+ /**
+ * Current gain reduction value
+ */
+ public int getGainReductionDb()
+ {
+ return mGainReductionDb;
+ }
+
+ /**
+ * Current LNA state setting
+ */
+ public int getLnaGainReductionDb()
+ {
+ return mLnaGainReductionDb;
+ }
+
+ /**
+ * Current gain value
+ */
+ public double getCurrentGain()
+ {
+ return mCurrentGain;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("GR:").append(getGainReductionDb());
+ sb.append(" LNA:").append(getLnaGainReductionDb());
+ sb.append(" CURRENT GAIN:").append(getCurrentGain());
+ return sb.toString();
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/PowerOverloadCallbackParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/PowerOverloadCallbackParameters.java
new file mode 100644
index 000000000..5c506fe4f
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/PowerOverloadCallbackParameters.java
@@ -0,0 +1,49 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.event;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_PowerOverloadCbParamT;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * Power Overload Callback Parameters (sdrplay_api_PowerOverloadCbParamT)
+ */
+public class PowerOverloadCallbackParameters
+{
+ private PowerOverloadEventType mPowerOverloadEventType;
+
+ /**
+ * Constructs an instance from the foreign memory segment
+ */
+ public PowerOverloadCallbackParameters(MemorySegment memorySegment)
+ {
+ mPowerOverloadEventType = PowerOverloadEventType
+ .fromValue(sdrplay_api_PowerOverloadCbParamT.powerOverloadChangeType$get(memorySegment));
+ }
+
+ /**
+ * Event type
+ */
+ public PowerOverloadEventType getPowerOverloadEvent()
+ {
+ return mPowerOverloadEventType;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/PowerOverloadEventType.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/PowerOverloadEventType.java
new file mode 100644
index 000000000..b6862c22c
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/PowerOverloadEventType.java
@@ -0,0 +1,73 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.event;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * Power Overload Callback Event type
+ */
+public enum PowerOverloadEventType
+{
+ OVERLOAD_DETECTED(sdrplay_api_h.sdrplay_api_Overload_Detected(), "OVERLOAD DETECTED"),
+ OVERLOAD_CORRECTED(sdrplay_api_h.sdrplay_api_Overload_Corrected(), "OVERLOAD CORRECTED"),
+ UNKNOWN(-1, "UNKNOWN");
+
+ private int mValue;
+ private String mDescription;
+
+ PowerOverloadEventType(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or UNKNOWN if the code is not recognized
+ */
+ public static PowerOverloadEventType fromValue(int value)
+ {
+ for(PowerOverloadEventType status: PowerOverloadEventType.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return UNKNOWN;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/RspDuoModeCallbackParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/RspDuoModeCallbackParameters.java
new file mode 100644
index 000000000..0b7565739
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/RspDuoModeCallbackParameters.java
@@ -0,0 +1,48 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.event;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_RspDuoModeCbParamT;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * RSP-Duo Mode Callback Parameters (sdrplay_api_RspDuoModeCbParamT)
+ */
+public class RspDuoModeCallbackParameters
+{
+ private RspDuoModeEventType mRspDuoModeEventType;
+
+ /**
+ * Constructs an instance from the foreign memory segment
+ */
+ public RspDuoModeCallbackParameters(MemorySegment memorySegment)
+ {
+ mRspDuoModeEventType = RspDuoModeEventType.fromValue(sdrplay_api_RspDuoModeCbParamT.modeChangeType$get(memorySegment));
+ }
+
+ /**
+ * Event type
+ */
+ public RspDuoModeEventType getRspDuoModeEvent()
+ {
+ return mRspDuoModeEventType;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/RspDuoModeEventType.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/RspDuoModeEventType.java
new file mode 100644
index 000000000..57eec76a0
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/event/RspDuoModeEventType.java
@@ -0,0 +1,78 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.event;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * RSP-Duo Mode Callback Event type
+ */
+public enum RspDuoModeEventType
+{
+ MASTER_INITIALIZED(sdrplay_api_h.sdrplay_api_MasterInitialised(), "MASTER INITIALIZED"),
+ SLAVE_ATTACHED(sdrplay_api_h.sdrplay_api_SlaveAttached(), "SLAVE ATTACHED"),
+ SLAVE_DETACHED(sdrplay_api_h.sdrplay_api_SlaveDetached(), "SLAVE DETACHED"),
+ SLAVE_INITIALIZED(sdrplay_api_h.sdrplay_api_SlaveInitialised(), "SLAVE INITIALIZED"),
+ SLAVE_UNINITIALIZED(sdrplay_api_h.sdrplay_api_SlaveUninitialised(), "SLAVE UNINITIALIZED"),
+ MASTER_DLL_DISAPPEARED(sdrplay_api_h.sdrplay_api_MasterDllDisappeared(), "MASTER DLL DISAPPEARED"),
+ SLAVE_DLL_DISAPPEARED(sdrplay_api_h.sdrplay_api_SlaveDllDisappeared(), "SLAVE DLL DISAPPEARED"),
+ UNKNOWN(-1, "UNKNOWN");
+
+ private int mValue;
+ private String mDescription;
+
+ RspDuoModeEventType(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or UNKNOWN if the code is not recognized
+ */
+ public static RspDuoModeEventType fromValue(int value)
+ {
+ for(RspDuoModeEventType status: RspDuoModeEventType.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return UNKNOWN;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Bandwidth.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Bandwidth.java
new file mode 100644
index 000000000..2bbef028e
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Bandwidth.java
@@ -0,0 +1,89 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * Bandwidth
+ */
+public enum Bandwidth
+{
+ BW_0_200(sdrplay_api_h.sdrplay_api_BW_0_200(), 200_000, "0.200 MHz"),
+ BW_0_300(sdrplay_api_h.sdrplay_api_BW_0_300(), 300_000, "0.300 MHz"),
+ BW_0_600(sdrplay_api_h.sdrplay_api_BW_0_600(), 600_000, "0.600 MHz"),
+ BW_1_536(sdrplay_api_h.sdrplay_api_BW_1_536(), 1_536_000, "1.536 MHz"),
+ BW_5_000(sdrplay_api_h.sdrplay_api_BW_5_000(), 5_000_000, "5.000 MHz"),
+ BW_6_000(sdrplay_api_h.sdrplay_api_BW_6_000(), 6_000_000, "6.000 MHz"),
+ BW_7_000(sdrplay_api_h.sdrplay_api_BW_7_000(), 7_000_000, "7.000 MHz"),
+ BW_8_000(sdrplay_api_h.sdrplay_api_BW_8_000(), 8_000_000, "8.000 MHz"),
+ UNDEFINED(sdrplay_api_h.sdrplay_api_BW_Undefined(), 0, "UNDEFINED");
+
+ private int mValue;
+ private long mBandwidth;
+ private String mDescription;
+
+ Bandwidth(int value, long bandwidth, String description)
+ {
+ mValue = value;
+ mBandwidth = bandwidth;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Bandwidth (Hz)
+ */
+ public long getBandwidth()
+ {
+ return mBandwidth;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or UNDEFINED if the code is not recognized
+ */
+ public static Bandwidth fromValue(int value)
+ {
+ for(Bandwidth status: Bandwidth.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return UNDEFINED;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/DcOffsetTuner.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/DcOffsetTuner.java
new file mode 100644
index 000000000..46161bb8d
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/DcOffsetTuner.java
@@ -0,0 +1,102 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_DcOffsetTunerT;
+import com.github.dsheirer.sdrplay.util.Flag;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * DC Offset Tuner structure (sdrplay_api_DcOffsetTunerT)
+ */
+public class DcOffsetTuner
+{
+ private MemorySegment mMemorySegment;
+
+ /**
+ * Constructs an instance from the foreign memory segment
+ */
+ public DcOffsetTuner(MemorySegment memorySegment)
+ {
+ mMemorySegment = memorySegment;
+ }
+
+ /**
+ * Foreign memory segment for this structure
+ */
+ private MemorySegment getMemorySegment()
+ {
+ return mMemorySegment;
+ }
+
+ /**
+ * DC calibration mode.
+ * @return
+ */
+ public int getDcCal()
+ {
+ return sdrplay_api_DcOffsetTunerT.dcCal$get(getMemorySegment());
+ }
+
+ public void setDcCal(int dcCal)
+ {
+ sdrplay_api_DcOffsetTunerT.dcCal$set(getMemorySegment(), (byte)dcCal);
+ }
+
+ public boolean isSpeedUp()
+ {
+ return Flag.evaluate(sdrplay_api_DcOffsetTunerT.speedUp$get(getMemorySegment()));
+ }
+
+ public void setSpeedUp(boolean speedUp)
+ {
+ sdrplay_api_DcOffsetTunerT.speedUp$set(getMemorySegment(), Flag.of(speedUp));
+ }
+
+ public int getTrackTime()
+ {
+ return sdrplay_api_DcOffsetTunerT.trackTime$get(getMemorySegment());
+ }
+
+ public void setTrackTime(int trackTime)
+ {
+ sdrplay_api_DcOffsetTunerT.trackTime$set(getMemorySegment(), trackTime);
+ }
+
+ public int getRefreshRateTime()
+ {
+ return sdrplay_api_DcOffsetTunerT.refreshRateTime$get(getMemorySegment());
+ }
+
+ public void setRefreshRateTime(int refreshRateTime)
+ {
+ sdrplay_api_DcOffsetTunerT.refreshRateTime$set(getMemorySegment(), refreshRateTime);
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("DC Cal:").append(getDcCal()).append(" Speed Up:").append(isSpeedUp());
+ sb.append(" Track Time:").append(getTrackTime()).append(" Refresh Rate Time:").append(getRefreshRateTime());
+ return sb.toString();
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/FrequencyBand.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/FrequencyBand.java
new file mode 100644
index 000000000..a8a7edf20
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/FrequencyBand.java
@@ -0,0 +1,104 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import java.util.EnumSet;
+
+/**
+ * RSP Frequency Bands
+ */
+public enum FrequencyBand
+{
+ BAND_0_12(1_000, 12_000_000, "0.001-12 MHz"),
+ BAND_12_60(12_000_000, 60_000_000, "12-60 MHz"),
+ BAND_60_250(60_000_000, 250_000_000, "60-250 MHz"),
+ BAND_250_420(250_000_000, 420_000_000, "250-420 MHz"),
+ BAND_420_1000(420_000_000, 1_000_000_000, "420-1000 MHz"),
+ BAND_1000_2000(1_000_000_000, 2_000_000_000, "1000-2000 MHz"),
+ UNKNOWN(-1, 0,"UNKNOWN");
+
+ private long mMinimum;
+ private long mMaximum;
+ private String mDescription;
+
+ FrequencyBand(long min, long max, String description)
+ {
+ mMinimum = min;
+ mMaximum = max;
+ mDescription = description;
+ }
+
+ /**
+ * Valid frequency bands
+ */
+ public static EnumSet VALID_FREQUENCY_BANDS = EnumSet.range(BAND_0_12, BAND_1000_2000);
+
+ /**
+ * Minimum frequency
+ * @return frequency in Hertz
+ */
+ public long getMinimum()
+ {
+ return mMinimum;
+ }
+
+ /**
+ * Maximum frequency
+ * @return frequency in Hertz
+ */
+ public long getMaximum()
+ {
+ return mMaximum;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param frequency to lookup
+ * @return entry or UNKNOWN if the code is not recognized
+ */
+ public static FrequencyBand fromValue(long frequency)
+ {
+ for(FrequencyBand band: FrequencyBand.values())
+ {
+ if(band.contains(frequency))
+ {
+ return band;
+ }
+ }
+
+ return UNKNOWN;
+ }
+
+ /**
+ * Indicates if this frequency band entry contains the specified frequency
+ * @param frequency to check
+ * @return true if this entry contains the frequency
+ */
+ public boolean contains(long frequency)
+ {
+ return getMinimum() <= frequency && frequency < getMaximum();
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Gain.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Gain.java
new file mode 100644
index 000000000..187329361
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Gain.java
@@ -0,0 +1,143 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_GainT;
+import com.github.dsheirer.sdrplay.util.Flag;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * Gain structure (sdrplay_api_GainT)
+ */
+public class Gain
+{
+ private static final Logger mLog = LoggerFactory.getLogger(Gain.class);
+
+ private MemorySegment mMemorySegment;
+ private GainValues mGainValues;
+
+ /**
+ * Constructs an instance from the foreign memory segment
+ */
+ public Gain(MemorySegment memorySegment)
+ {
+ mMemorySegment = memorySegment;
+ mGainValues = new GainValues(sdrplay_api_GainT.gainVals$slice(memorySegment));
+ }
+
+ /**
+ * Foreign memory segment for this structure
+ */
+ private MemorySegment getMemorySegment()
+ {
+ return mMemorySegment;
+ }
+
+ /**
+ * Sets the LNA state and gain reduction from the set of gain reduction values using the specified index
+ * @param gainReduction for the current frequency band
+ * @param index into the gain values to use for LNA state and gain reduction
+ */
+ public void setGain(GainReduction gainReduction, int index)
+ {
+ setLNA(gainReduction.getLnaState(index));
+ setGainReductionDb(gainReduction.getGainReduction(index));
+ }
+
+ /**
+ * Current gain reduction
+ * @return gain dB
+ */
+ public int getGainReductionDb()
+ {
+ return sdrplay_api_GainT.gRdB$get(getMemorySegment());
+ }
+
+ /**
+ * Sets the gain reduction value
+ * @param gainReductionDb
+ */
+ public void setGainReductionDb(int gainReductionDb)
+ {
+ sdrplay_api_GainT.gRdB$set(getMemorySegment(), gainReductionDb);
+ }
+
+ /**
+ * Low Noise Amplifier (LNA) state/value
+ */
+ public int getLNA()
+ {
+ return sdrplay_api_GainT.LNAstate$get(getMemorySegment());
+ }
+
+ /**
+ * Sets the Low Noise Amplifier (LNA) state
+ */
+ public void setLNA(int lna)
+ {
+ sdrplay_api_GainT.LNAstate$set(getMemorySegment(), (byte)lna);
+ }
+
+ /**
+ * Specifies if LNA and gain reduction changes should be applied synchronously
+ */
+ public void setSynchronousUpdate(boolean syncUpdate)
+ {
+ sdrplay_api_GainT.syncUpdate$set(getMemorySegment(), Flag.of(syncUpdate));
+ }
+
+ /**
+ * Minimum gain reduction mode
+ */
+ public MinimumGainReductionMode getMinimumGainReductionMode()
+ {
+ return MinimumGainReductionMode.fromValue(sdrplay_api_GainT.minGr$get(getMemorySegment()));
+ }
+
+ /**
+ * Sets the minimum gain reduction mode
+ */
+ public void setMinimumGainReductionMode(MinimumGainReductionMode minimumGainReductionMode)
+ {
+ sdrplay_api_GainT.minGr$set(getMemorySegment(), minimumGainReductionMode.getValue());
+ }
+
+ /**
+ * Gain values structure
+ */
+ public GainValues getGainValues()
+ {
+ return mGainValues;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Reduction:").append(getGainReductionDb()).append("dB");
+ sb.append(" LNA:").append(getLNA());
+ sb.append(" Min Gain Reduction Mode:").append(getMinimumGainReductionMode());
+ sb.append(" Gain Values:").append(getGainValues());
+ return sb.toString();
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/GainReduction.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/GainReduction.java
new file mode 100644
index 000000000..62cb0ee4e
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/GainReduction.java
@@ -0,0 +1,354 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.device.DeviceType;
+import java.util.EnumSet;
+
+/**
+ * RSP Gain Reduction values and LNA states for each RSP model.
+ *
+ * Use lookup() as convenience method to find a gain reduction entry for a device type and frequency band.
+ *
+ * Reference: SDRplay API Specification, Gain Reduction Tables
+ * and https://github.com/SDRplay/RSPTCPServer/blob/master/rsp_tcp.c
+ */
+public enum GainReduction
+{
+ RSP1_BAND_0_12(FrequencyBand.BAND_0_12,
+ new int[]{ 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,56,53,50,47,44,41,58,55,52,49,46,43,45,42,58,55,52,49,46,43,41,38,35,32,29,26,23,20 }),
+ RSP1_BAND_12_60(FrequencyBand.BAND_12_60,
+ new int[]{ 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,56,53,50,47,44,41,58,55,52,49,46,43,45,42,58,55,52,49,46,43,41,38,35,32,29,26,23,20 }),
+ RSP1_BAND_60_250(FrequencyBand.BAND_60_250,
+ new int[]{ 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,56,53,50,47,44,41,58,55,52,49,46,43,45,42,58,55,52,49,46,43,41,38,35,32,29,26,23,20 }),
+ RSP1_BAND_250_420(FrequencyBand.BAND_250_420,
+ new int[]{ 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,56,53,50,47,44,41,58,55,52,49,46,43,45,42,58,55,52,49,46,43,41,38,35,32,29,26,23,20 }),
+ RSP1_BAND_420_1000(FrequencyBand.BAND_420_1000,
+ new int[]{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
+ new int[]{ 59,57,54,52,50,47,45,43,40,38,36,33,31,29,27,24,22,27,24,22,32,29,27,25,22,27,25,22,20 }),
+ RSP1_BAND_1000_2000(FrequencyBand.BAND_1000_2000,
+ new int[]{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,57,55,52,50,48,46,43,41,44,42,53,51,49,47,44,42,45,43,40,38,36,34,31,29,27,25,22,20 }),
+
+ RSP1A_BAND_0_12(FrequencyBand.BAND_0_12,
+ new int[]{ 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4, 3, 3, 3, 3, 3, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,45,41,57,53,49,46,42,44,40,56,52,48,45,41,44,40,43,45,41,38,34,31,27,24,20 }),
+ RSP1A_BAND_12_60(FrequencyBand.BAND_12_60,
+ new int[]{ 9, 9, 9, 9, 9, 9, 8, 7, 7, 7, 7, 7, 6, 6, 5, 5, 4, 3, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,45,41,42,58,54,51,47,43,46,42,44,41,43,42,44,40,43,45,42,38,34,31,27,24,20 }),
+ RSP1A_BAND_60_250(FrequencyBand.BAND_60_250,
+ new int[]{ 9, 9, 9, 9, 9, 9, 8, 7, 7, 7, 7, 7, 6, 6, 5, 5, 4, 3, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,45,41,42,58,54,51,47,43,46,42,44,41,43,42,44,40,43,45,42,38,34,31,27,24,20 }),
+ RSP1A_BAND_250_420(FrequencyBand.BAND_250_420,
+ new int[]{ 9, 9, 9, 9, 9, 9, 8, 7, 7, 7, 7, 7, 6, 6, 5, 5, 4, 3, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,45,41,42,58,54,51,47,43,46,42,44,41,43,42,44,40,43,45,42,38,34,31,27,24,20 }),
+ RSP1A_BAND_420_1000(FrequencyBand.BAND_420_1000,
+ new int[]{ 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 7, 6, 6, 5, 5, 4, 4, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,44,41,56,52,49,45,41,44,46,42,45,41,44,40,44,40,42,46,42,38,35,31,27,24,20 }),
+ RSP1A_BAND_1000_2000(FrequencyBand.BAND_1000_2000,
+ new int[]{ 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 5, 5, 4, 4, 3, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,45,41,56,53,49,46,42,43,46,42,44,41,43,48,44,40,43,45,42,38,34,31,27,24,20 }),
+
+ RSP2_BAND_0_12(FrequencyBand.BAND_0_12,
+ new int[]{ 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 5, 5, 4, 4, 4, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,44,41,56,52,49,45,41,44,45,41,48,44,40,45,42,43,49,46,42,38,35,31,27,24,20 }),
+ RSP2_BAND_12_60(FrequencyBand.BAND_12_60,
+ new int[]{ 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 5, 5, 4, 4, 4, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,44,41,56,52,49,45,41,44,45,41,48,44,40,45,42,43,49,46,42,38,35,31,27,24,20 }),
+ RSP2_BAND_60_250(FrequencyBand.BAND_60_250,
+ new int[]{ 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 5, 5, 4, 4, 4, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,44,41,56,52,49,45,41,44,45,41,48,44,40,45,42,43,49,46,42,38,35,31,27,24,20 }),
+ RSP2_BAND_250_420(FrequencyBand.BAND_250_420,
+ new int[]{ 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 5, 5, 4, 4, 4, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,44,41,56,52,49,45,41,44,45,41,48,44,40,45,42,43,49,46,42,38,35,31,27,24,20 }),
+ RSP2_BAND_420_1000(FrequencyBand.BAND_420_1000,
+ new int[]{ 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 3, 3, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,56,53,50,48,45,42,58,55,52,49,47,44,41,43,40,44,41,42,46,43,40,37,34,31,29,26,23,20 }),
+ RSP2_BAND_1000_2000(FrequencyBand.BAND_1000_2000,
+ new int[]{ 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,56,54,51,48,45,43,40,56,54,51,48,45,43,40,43,41,44,41,44,42,39,36,34,31,28,25,23,20 }),
+
+ RSP_DUO_BAND_0_12(FrequencyBand.BAND_0_12,
+ new int[]{ 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4, 3, 3, 3, 3, 3, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,45,41,57,53,49,46,42,44,40,56,52,48,45,41,44,40,43,45,41,38,34,31,27,24,20 }),
+ RSP_DUO_BAND_12_60(FrequencyBand.BAND_12_60,
+ new int[]{ 9, 9, 9, 9, 9, 9, 8, 7, 7, 7, 7, 7, 6, 6, 5, 5, 4, 3, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,45,41,42,58,54,51,47,43,46,42,44,41,43,42,44,40,43,45,42,38,34,31,27,24,20 }),
+ RSP_DUO_BAND_60_250(FrequencyBand.BAND_60_250,
+ new int[]{ 9, 9, 9, 9, 9, 9, 8, 7, 7, 7, 7, 7, 6, 6, 5, 5, 4, 3, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,45,41,42,58,54,51,47,43,46,42,44,41,43,42,44,40,43,45,42,38,34,31,27,24,20 }),
+ RSP_DUO_BAND_250_420(FrequencyBand.BAND_250_420,
+ new int[]{ 9, 9, 9, 9, 9, 9, 8, 7, 7, 7, 7, 7, 6, 6, 5, 5, 4, 3, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,45,41,42,58,54,51,47,43,46,42,44,41,43,42,44,40,43,45,42,38,34,31,27,24,20 }),
+ RSP_DUO_BAND_420_1000(FrequencyBand.BAND_420_1000,
+ new int[]{ 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 7, 6, 6, 5, 5, 4, 4, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,44,41,56,52,49,45,41,44,46,42,45,41,44,40,44,40,42,46,42,38,35,31,27,24,20 }),
+ RSP_DUO_BAND_1000_2000(FrequencyBand.BAND_1000_2000,
+ new int[]{ 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 5, 5, 4, 4, 3, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,45,41,56,53,49,46,42,43,46,42,44,41,43,48,44,40,43,45,42,38,34,31,27,24,20 }),
+
+ RSP_DX_BAND_0_12(FrequencyBand.BAND_0_12,
+ new int[]{ 18,18,18,18,18,18,17,16,14,13,12,11,10, 9, 7, 6, 5, 5, 5, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,45,41,41,40,43,42,42,41,41,40,42,42,47,44,40,43,42,42,41,38,34,31,27,24,20 }),
+ RSP_DX_BAND_12_60(FrequencyBand.BAND_12_60,
+ new int[]{ 26,26,26,26,26,25,23,22,20,19,17,16,14,13,11,10, 8, 7, 5, 5, 5, 3, 2, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,50,46,41,40,42,40,42,40,42,41,42,41,43,41,43,41,49,45,40,42,40,42,38,33,29,24,20 }),
+ RSP_DX_BAND_60_250(FrequencyBand.BAND_60_250,
+ new int[]{ 26,26,26,26,26,25,23,22,20,19,17,16,14,13,11,10, 8, 7, 5, 5, 5, 3, 2, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,50,46,41,40,42,40,42,40,42,41,42,41,43,41,43,41,49,45,40,42,40,42,38,33,29,24,20 }),
+ RSP_DX_BAND_250_420(FrequencyBand.BAND_250_420,
+ new int[]{ 27,27,27,27,27,26,24,23,21,20,18,17,15,14,12,11, 9, 8, 6, 6, 5, 3, 2, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,50,46,41,40,42,40,42,40,42,41,42,41,43,41,43,41,46,42,40,42,40,42,38,33,29,24,20 }),
+ RSP_DX_BAND_420_1000(FrequencyBand.BAND_420_1000,
+ new int[]{ 20,20,20,20,20,20,18,17,16,14,13,12,11, 9, 8, 7, 7, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,51,48,44,40,42,42,41,43,42,41,41,43,42,44,40,43,42,41,40,46,43,39,35,31,28,24,20 }),
+ RSP_DX_BAND_1000_2000(FrequencyBand.BAND_1000_2000,
+ new int[]{ 18,18,18,18,18,18,16,15,14,13,11,10, 9, 8, 7, 6, 6, 6, 5, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,44,40,43,42,41,41,43,42,41,41,40,48,45,41,40,42,42,41,42,39,35,31,27,24,20 }),
+
+ //HiZ Port - RSP2 and RSPduo
+ RSP_2_AND_DUO_HIZ_BAND_0_12(FrequencyBand.BAND_0_12,
+ new int[]{ 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,56,54,51,48,45,43,40,56,54,51,48,45,43,40,43,41,44,41,44,42,39,36,34,31,28,25,23,20 }),
+ RSP_2_AND_DUO_HIZ_BAND_12_60(FrequencyBand.BAND_12_60,
+ new int[]{ 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,56,54,51,48,45,43,40,56,54,51,48,45,43,40,43,41,44,41,44,42,39,36,34,31,28,25,23,20 }),
+
+ //RSPdx HDR Mode
+ RSP_DX_HDR_BAND_0_2(FrequencyBand.BAND_0_12,
+ new int[]{ 18,18,18,18,18,18,17,16,14,13,12,11,10, 9, 7, 6, 5, 5, 5, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0 },
+ new int[]{ 59,55,52,48,45,41,41,40,43,42,42,41,41,40,42,42,47,44,40,43,42,42,41,38,34,31,27,24,20 }),
+
+ UNKNOWN(FrequencyBand.UNKNOWN, new int[]{}, new int[]{});
+
+ private FrequencyBand mFrequencyBand;
+ private int[] mLnaStates;
+ private int[] mGainReductions;
+
+ GainReduction(FrequencyBand frequencyBand, int[] lnaStates, int[] gainReductions)
+ {
+ mFrequencyBand = frequencyBand;
+ mLnaStates = lnaStates;
+ mGainReductions = gainReductions;
+ }
+
+ /**
+ * Identifies the index of the gain reduction value from the array of possible gain reduction values.
+ * @param gainReductionValue to lookup index
+ * @return matching index or -1 if a matching index is not found.
+ */
+ public int getGainIndex(int gainReductionValue)
+ {
+ for(int x = 0; x < mGainReductions.length; x++)
+ {
+ if(mGainReductions[x] == gainReductionValue)
+ {
+ return x;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Minimum index for gain values
+ */
+ public static int MIN_GAIN_INDEX = 0;
+
+ /**
+ * Maximum index for gain values
+ */
+ public static int MAX_GAIN_INDEX = 28;
+
+ /**
+ * Number of discrete gain steps available for each entry
+ */
+ public static int GAIN_STEPS_AVAILABLE = 29;
+
+ /**
+ * RSP1 Gain Reduction Tables
+ */
+ public static EnumSet RSP_1_GAINS = EnumSet.range(RSP1_BAND_0_12, RSP1_BAND_1000_2000);
+
+ /**
+ * RSP1A Gain Reduction Tables
+ */
+ public static EnumSet RSP_1A_GAINS = EnumSet.range(RSP1A_BAND_0_12, RSP1A_BAND_1000_2000);
+
+ /**
+ * RSP2 Gain Reduction Tables
+ */
+ public static EnumSet RSP_2_GAINS = EnumSet.range(RSP2_BAND_0_12, RSP2_BAND_1000_2000);
+
+ /**
+ * RSPduo Gain Reduction Tables
+ */
+ public static EnumSet RSP_DUO_GAINS = EnumSet.range(RSP_DUO_BAND_0_12, RSP_DUO_BAND_1000_2000);
+
+ /**
+ * RSPdx Gain Reduction Tables
+ */
+ public static EnumSet RSP_DX_GAINS = EnumSet.range(RSP_DX_BAND_0_12, RSP_DX_BAND_1000_2000);
+
+ /**
+ * RSPdx HDR Mode Gain Reduction Tables
+ */
+ public static EnumSet RSP_DX_HDR_GAINS = EnumSet.of(RSP_DX_HDR_BAND_0_2);
+
+ /**
+ * RSP2 and RSPduo HiZ Port Gain Reduction Tables
+ */
+ public static EnumSet RSP_HIZ_GAINS = EnumSet.range(RSP_2_AND_DUO_HIZ_BAND_0_12, RSP_2_AND_DUO_HIZ_BAND_12_60);
+
+ /**
+ * Lookup the gain reduction entry for a device that matches the frequency band.
+ *
+ * Note: directly use the RSP_DX_HDR_GAINS and RSP_HIZ_GAINS enumeration sets to match for HDR or HIZ modes.
+ *
+ * @param deviceType to lookup
+ * @param frequencyBand to match
+ * @return entry or UNKNOWN
+ */
+ public static GainReduction lookup(DeviceType deviceType, FrequencyBand frequencyBand)
+ {
+ switch(deviceType)
+ {
+ case RSP1 -> {
+ return fromBand(frequencyBand, RSP_1_GAINS);
+ }
+ case RSP1A -> {
+ return fromBand(frequencyBand, RSP_1A_GAINS);
+ }
+ case RSP2 -> {
+ return fromBand(frequencyBand, RSP_2_GAINS);
+ }
+ case RSPduo -> {
+ return fromBand(frequencyBand, RSP_DUO_GAINS);
+ }
+ case RSPdx -> {
+ return fromBand(frequencyBand, RSP_DX_GAINS);
+ }
+ }
+
+ return UNKNOWN;
+ }
+
+ /**
+ * Lookup the gain reduction entry for a device that matches the specified frequency
+ * @param deviceType to lookup
+ * @param frequency to map to a frequency band
+ * @return gain reduction entry or UNKNOWN
+ */
+ public static GainReduction lookup(DeviceType deviceType, long frequency)
+ {
+ FrequencyBand band = FrequencyBand.fromValue(frequency);
+ return lookup(deviceType, band);
+ }
+
+ /**
+ * Look up the gain reduction value that matches the frequency band from the set of gain reduction values.
+ * @param frequencyBand to lookup
+ * @param values to choose from
+ * @return matching entry or UNKNOWN
+ */
+ private static GainReduction fromBand(FrequencyBand frequencyBand, EnumSet values)
+ {
+ for(GainReduction gainReduction: values)
+ {
+ if(gainReduction.getFrequencyBand() == frequencyBand)
+ {
+ return gainReduction;
+ }
+ }
+
+ return UNKNOWN;
+ }
+
+ /**
+ * Frequency band for the range of LNA state and gain reduction values.
+ */
+ public FrequencyBand getFrequencyBand()
+ {
+ return mFrequencyBand;
+ }
+
+ /**
+ * Array of LNA states
+ */
+ private int[] getLnaStates()
+ {
+ return mLnaStates;
+ }
+
+ /**
+ * Array of gain reduction values
+ */
+ private int[] getGainReductions()
+ {
+ return mGainReductions;
+ }
+
+ /**
+ * LNA state value for the specified gain index
+ * @param index for the gain (0 - 29)
+ * @return lna state
+ */
+ public int getLnaState(int index)
+ {
+ if(MIN_GAIN_INDEX <= index && index <= MAX_GAIN_INDEX)
+ {
+ return getLnaStates()[index];
+ }
+
+ throw new IllegalArgumentException("Unrecognized gain index [" + index + "] - valid range: " +
+ MIN_GAIN_INDEX + " <> " + MAX_GAIN_INDEX);
+ }
+
+ /**
+ * Gain reduction value for the specified gain index
+ * @param index for the gain (0 - 29)
+ * @return gain reduction value (dB)
+ */
+ public int getGainReduction(int index)
+ {
+ if(MIN_GAIN_INDEX <= index && index <= MAX_GAIN_INDEX)
+ {
+ return getGainReductions()[index];
+ }
+
+ throw new IllegalArgumentException("Unrecognized gain index [" + index + "] - valid range: " +
+ MIN_GAIN_INDEX + " <> " + MAX_GAIN_INDEX);
+ }
+
+ /**
+ * Indicates if this gain reduction entry is valid for the specified frequency by checking the frequency band
+ * of this entry and testing for containment.
+ * @param frequency to check
+ * @return true if the frequency is contained in the frequency band for this entry.
+ */
+ public boolean isValidFor(long frequency)
+ {
+ return getFrequencyBand().contains(frequency);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/GainValues.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/GainValues.java
new file mode 100644
index 000000000..6e2a617c0
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/GainValues.java
@@ -0,0 +1,74 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_GainValuesT;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * Gain Values structure (sdrplay_api_GainValuesT)
+ *
+ * Note: these are output parameters, so there are no setter methods.
+ */
+public class GainValues
+{
+ private MemorySegment mMemorySegment;
+
+ /**
+ * Constructs an instance from the foreign memory segment
+ */
+ public GainValues(MemorySegment memorySegment)
+ {
+ mMemorySegment = memorySegment;
+ }
+
+ /**
+ * Foreign memory segment for this structure
+ */
+ private MemorySegment getMemorySegment()
+ {
+ return mMemorySegment;
+ }
+
+
+ public float getCurrent()
+ {
+ return sdrplay_api_GainValuesT.curr$get(getMemorySegment());
+ }
+
+ public float getMax()
+ {
+ return sdrplay_api_GainValuesT.max$get(getMemorySegment());
+ }
+
+ public float getMin()
+ {
+ return sdrplay_api_GainValuesT.min$get(getMemorySegment());
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Current:").append(getCurrent()).append(" Max:").append(getMax()).append(" Min:").append(getMin());
+ return sb.toString();
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/HdrModeBandwidth.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/HdrModeBandwidth.java
new file mode 100644
index 000000000..5990e50a6
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/HdrModeBandwidth.java
@@ -0,0 +1,85 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * RSPdx High Dynamic Range (HDR) Mode Bandwidth
+ */
+public enum HdrModeBandwidth
+{
+ BANDWIDTH_0_200(sdrplay_api_h.sdrplay_api_RspDx_HDRMODE_BW_0_200(), 200_000, ".2 MHz"),
+ BANDWIDTH_0_500(sdrplay_api_h.sdrplay_api_RspDx_HDRMODE_BW_0_500(), 500_000, ".5 MHz"),
+ BANDWIDTH_1_200(sdrplay_api_h.sdrplay_api_RspDx_HDRMODE_BW_1_200(), 1_200_000, "1.2 MHz"),
+ BANDWIDTH_1_700(sdrplay_api_h.sdrplay_api_RspDx_HDRMODE_BW_1_700(), 1_700_000, "1.7 MHz"),
+ UNKNOWN(-1, 0, "UNKNOWN");
+
+ private int mValue;
+ private long mBandwidth;
+ private String mDescription;
+
+ HdrModeBandwidth(int value, long bandwidth, String description)
+ {
+ mValue = value;
+ mBandwidth = bandwidth;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Bandwidth in Hertz
+ */
+ public long getBandwidth()
+ {
+ return mBandwidth;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or UKNOWN if the code is not recognized
+ */
+ public static HdrModeBandwidth fromValue(int value)
+ {
+ for(HdrModeBandwidth status: HdrModeBandwidth.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return UNKNOWN;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/IfMode.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/IfMode.java
new file mode 100644
index 000000000..43b125016
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/IfMode.java
@@ -0,0 +1,83 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * Intermediate Frequency (IF) Mode / Frequency
+ */
+public enum IfMode
+{
+ IF_ZERO(sdrplay_api_h.sdrplay_api_IF_Zero(), "ZIF 0.000 MHz"),
+ IF_450(sdrplay_api_h.sdrplay_api_IF_0_450(), "0.450 MHz"),
+ IF_1620(sdrplay_api_h.sdrplay_api_IF_1_620(), "1.620 MHz"),
+ IF_2048(sdrplay_api_h.sdrplay_api_IF_2_048(), "2.048 MHz"),
+ UNDEFINED(sdrplay_api_h.sdrplay_api_IF_Undefined(), "UNDEFINED");
+
+ private int mValue;
+ private String mDescription;
+
+ IfMode(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Indicates the wideband enable decimation setting to use for this IF value.
+ */
+ public boolean isWidebandSignal()
+ {
+ return this.equals(IF_ZERO);
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or UNKNOWN if the code is not recognized
+ */
+ public static IfMode fromValue(int value)
+ {
+ for(IfMode status: IfMode.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return UNDEFINED;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/LoMode.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/LoMode.java
new file mode 100644
index 000000000..dd09bacfd
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/LoMode.java
@@ -0,0 +1,75 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * Local Oscillator Mode
+ */
+public enum LoMode
+{
+ AUTO(sdrplay_api_h.sdrplay_api_LO_Auto(), "AUTO"),
+ MHZ_120(sdrplay_api_h.sdrplay_api_LO_120MHz(), "120 MHz"),
+ MHZ_144(sdrplay_api_h.sdrplay_api_LO_144MHz(), "144 MHz"),
+ MHZ_168(sdrplay_api_h.sdrplay_api_LO_168MHz(), "168 MHz"),
+ UNDEFINED(sdrplay_api_h.sdrplay_api_LO_Undefined(), "UNDEFINED");
+
+ private int mValue;
+ private String mDescription;
+
+ LoMode(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or UNKNOWN if the code is not recognized
+ */
+ public static LoMode fromValue(int value)
+ {
+ for(LoMode status: LoMode.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return UNDEFINED;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/MinimumGainReductionMode.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/MinimumGainReductionMode.java
new file mode 100644
index 000000000..26c9b53c6
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/MinimumGainReductionMode.java
@@ -0,0 +1,73 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * Minimum Gain Reduction (mode)
+ */
+public enum MinimumGainReductionMode
+{
+ EXTENDED(sdrplay_api_h.sdrplay_api_EXTENDED_MIN_GR(), "EXTENDED"),
+ NORMAL(sdrplay_api_h.sdrplay_api_NORMAL_MIN_GR(), "NORMAL"),
+ UNKNOWN(-1, "UNKNOWN");
+
+ private int mValue;
+ private String mDescription;
+
+ MinimumGainReductionMode(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or UNKNOWN if the code is not recognized
+ */
+ public static MinimumGainReductionMode fromValue(int value)
+ {
+ for(MinimumGainReductionMode status: MinimumGainReductionMode.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return UNKNOWN;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/RfFrequency.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/RfFrequency.java
new file mode 100644
index 000000000..7fc08a854
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/RfFrequency.java
@@ -0,0 +1,95 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_RfFreqT;
+import com.github.dsheirer.sdrplay.util.Flag;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * RF Frequency structure (sdrplay_api_RfFreqT)
+ */
+public class RfFrequency
+{
+ private static final double MINIMUM_FREQUENCY = 1_200;
+ private static final double MAXIMUM_FREQUENCY = 2_000_000_000;
+ private MemorySegment mMemorySegment;
+
+ /**
+ * Constructs an instance from the foreign memory segment
+ * @param memorySegment representing the structure
+ */
+ public RfFrequency(MemorySegment memorySegment)
+ {
+ mMemorySegment = memorySegment;
+ }
+
+ private MemorySegment getMemorySegment()
+ {
+ return mMemorySegment;
+ }
+
+ /**
+ * RF Frequency
+ * @return frequency in Hertz
+ */
+ public double getFrequency()
+ {
+ return sdrplay_api_RfFreqT.rfHz$get(getMemorySegment());
+ }
+
+ /**
+ * Sets the RF frequency
+ * @param frequency (0 < frequency <= 2,000,000,000 Hz)
+ * @param synchronousUpdate to set the frequency as a synchronous update
+ * @throws SDRPlayException for an invalid frequency (ie out of valid range)
+ */
+ public void setFrequency(double frequency, boolean synchronousUpdate) throws SDRPlayException
+ {
+ if(MINIMUM_FREQUENCY < frequency && frequency <= MAXIMUM_FREQUENCY)
+ {
+ sdrplay_api_RfFreqT.rfHz$set(getMemorySegment(), frequency);
+ sdrplay_api_RfFreqT.syncUpdate$set(getMemorySegment(), Flag.of(synchronousUpdate));
+ }
+ else
+ {
+ throw new SDRPlayException("Invalid frequency: " + frequency + " - valid range: " +
+ MINIMUM_FREQUENCY + "-" + MAXIMUM_FREQUENCY);
+ }
+ }
+
+ /**
+ * Sets the RF frequency as a synchronous update
+ */
+ public void setFrequency(double frequency) throws SDRPlayException
+ {
+ setFrequency(frequency, true);
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Frequency:").append(getFrequency());
+ return sb.toString();
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp1TunerParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp1TunerParameters.java
new file mode 100644
index 000000000..6b1dfd114
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp1TunerParameters.java
@@ -0,0 +1,38 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * RSP1 Tuner Parameters structure
+ *
+ * Note: the RSP1 doesn't have any additional settings beyond the basic tuner parameters
+ */
+public class Rsp1TunerParameters extends TunerParameters
+{
+ /**
+ * Constructs an instance from the foreign memory segment.
+ */
+ public Rsp1TunerParameters(MemorySegment tunerParametersMemorySegment)
+ {
+ super(tunerParametersMemorySegment);
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp1aTunerParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp1aTunerParameters.java
new file mode 100644
index 000000000..459e7c7e5
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp1aTunerParameters.java
@@ -0,0 +1,66 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_Rsp1aTunerParamsT;
+import com.github.dsheirer.sdrplay.util.Flag;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * RSP-1A Tuner Parameters structure
+ */
+public class Rsp1aTunerParameters extends TunerParameters
+{
+ private MemorySegment mRsp1aMemorySegment;
+
+ /**
+ * Constructs an instance from the foreign memory segment.
+ */
+ public Rsp1aTunerParameters(MemorySegment tunerParametersMemorySegment, MemorySegment rsp1aMemorySegment)
+ {
+ super(tunerParametersMemorySegment);
+ mRsp1aMemorySegment = rsp1aMemorySegment;
+ }
+
+ /**
+ * Foreign memory segment for this structure
+ */
+ private MemorySegment getRsp1aMemorySegment()
+ {
+ return mRsp1aMemorySegment;
+ }
+
+ /**
+ * Indicates if the Bias-T is enabled
+ */
+ public boolean isBiasT()
+ {
+ return Flag.evaluate(sdrplay_api_Rsp1aTunerParamsT.biasTEnable$get(getRsp1aMemorySegment()));
+ }
+
+ /**
+ * Enable or disable the Bias-T
+ */
+ public void setBiasT(boolean enable)
+ {
+ sdrplay_api_Rsp1aTunerParamsT.biasTEnable$set(getRsp1aMemorySegment(), Flag.of(enable));
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp2AmPort.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp2AmPort.java
new file mode 100644
index 000000000..a0914a738
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp2AmPort.java
@@ -0,0 +1,72 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * RSP-2 AM Port
+ */
+public enum Rsp2AmPort
+{
+ PORT_1_HIGH_Z(sdrplay_api_h.sdrplay_api_Rsp2_AMPORT_1(), "HIGH-Z"),
+ PORT_2_SMA(sdrplay_api_h.sdrplay_api_Rsp2_AMPORT_2(), "SMA");
+
+ private int mValue;
+ private String mDescription;
+
+ Rsp2AmPort(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or PORT 2 if the code is not recognized
+ */
+ public static Rsp2AmPort fromValue(int value)
+ {
+ for(Rsp2AmPort status: Rsp2AmPort.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return PORT_2_SMA;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp2Antenna.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp2Antenna.java
new file mode 100644
index 000000000..2e35f8824
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp2Antenna.java
@@ -0,0 +1,72 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * RSP-2 Antenna
+ */
+public enum Rsp2Antenna
+{
+ ANTENNA_A(sdrplay_api_h.sdrplay_api_Rsp2_ANTENNA_A(), "ANT A"),
+ ANTENNA_B(sdrplay_api_h.sdrplay_api_Rsp2_ANTENNA_B(), "ANT B");
+
+ private int mValue;
+ private String mDescription;
+
+ Rsp2Antenna(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or ANTENNA A if the code is not recognized
+ */
+ public static Rsp2Antenna fromValue(int value)
+ {
+ for(Rsp2Antenna status: Rsp2Antenna.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return ANTENNA_A;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp2AntennaSelection.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp2AntennaSelection.java
new file mode 100644
index 000000000..a246d9078
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp2AntennaSelection.java
@@ -0,0 +1,65 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+/**
+ * RSP-2 Antenna
+ */
+public enum Rsp2AntennaSelection
+{
+ ANT_A(Rsp2Antenna.ANTENNA_A, Rsp2AmPort.PORT_2_SMA,"ANT A"),
+ ANT_B(Rsp2Antenna.ANTENNA_B, Rsp2AmPort.PORT_2_SMA, "ANT B"),
+ HIGH_Z(Rsp2Antenna.ANTENNA_B, Rsp2AmPort.PORT_1_HIGH_Z, "HIGH Z");
+
+ private Rsp2Antenna mAntenna;
+ private Rsp2AmPort mAmPort;
+ private String mDescription;
+
+ Rsp2AntennaSelection(Rsp2Antenna antenna, Rsp2AmPort amPort, String description)
+ {
+ mAntenna = antenna;
+ mAmPort = amPort;
+ mDescription = description;
+ }
+
+ /**
+ * Antenna setting for the selection.
+ * @return antenna
+ */
+ public Rsp2Antenna getAntenna()
+ {
+ return mAntenna;
+ }
+
+ /**
+ * AM Port for the selection
+ * @return am port
+ */
+ public Rsp2AmPort getAmPort()
+ {
+ return mAmPort;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp2TunerParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp2TunerParameters.java
new file mode 100644
index 000000000..252155cca
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/Rsp2TunerParameters.java
@@ -0,0 +1,111 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_Rsp2TunerParamsT;
+import com.github.dsheirer.sdrplay.util.Flag;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * RSP2 Tuner Parameters structure
+ */
+public class Rsp2TunerParameters extends TunerParameters
+{
+ private MemorySegment mRsp2MemorySegment;
+
+ public Rsp2TunerParameters(MemorySegment tunerParametersMemorySegment, MemorySegment rsp2MemorySegment)
+ {
+ super(tunerParametersMemorySegment);
+ mRsp2MemorySegment = rsp2MemorySegment;
+ }
+
+ /**
+ * Foreign memory segment for this structure
+ */
+ private MemorySegment getRsp2MemorySegment()
+ {
+ return mRsp2MemorySegment;
+ }
+
+ /**
+ * Indicates if the Bias-T is enabled
+ */
+ public boolean isBiasT()
+ {
+ return Flag.evaluate(sdrplay_api_Rsp2TunerParamsT.biasTEnable$get(getRsp2MemorySegment()));
+ }
+
+ /**
+ * Enables or disables the Bias-T
+ */
+ public void setBiasT(boolean enable)
+ {
+ sdrplay_api_Rsp2TunerParamsT.biasTEnable$set(getRsp2MemorySegment(), Flag.of(enable));
+ }
+
+ /**
+ * Current AM port setting
+ */
+ public Rsp2AmPort getAmPort()
+ {
+ return Rsp2AmPort.fromValue(sdrplay_api_Rsp2TunerParamsT.amPortSel$get(getRsp2MemorySegment()));
+ }
+
+ /**
+ * Sets the AM port to use
+ */
+ public void setAmPort(Rsp2AmPort amPort)
+ {
+ sdrplay_api_Rsp2TunerParamsT.amPortSel$set(getRsp2MemorySegment(), amPort.getValue());
+ }
+
+ /**
+ * Antenna setting
+ */
+ public Rsp2Antenna getAntenna()
+ {
+ return Rsp2Antenna.fromValue(sdrplay_api_Rsp2TunerParamsT.antennaSel$get(getRsp2MemorySegment()));
+ }
+
+ /**
+ * Sets the antenna
+ */
+ public void setAntenna(Rsp2Antenna rsp2Antenna)
+ {
+ sdrplay_api_Rsp2TunerParamsT.antennaSel$set(getRsp2MemorySegment(), rsp2Antenna.getValue());
+ }
+
+ /**
+ * Indicates if the RF notch is enabled
+ */
+ public boolean isRfNotch()
+ {
+ return Flag.evaluate(sdrplay_api_Rsp2TunerParamsT.rfNotchEnable$get(getRsp2MemorySegment()));
+ }
+
+ /**
+ * Enables or disables the RF notch
+ */
+ public void setRfNotch(boolean enable)
+ {
+ sdrplay_api_Rsp2TunerParamsT.rfNotchEnable$set(getRsp2MemorySegment(), Flag.of(enable));
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/RspDuoAmPort.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/RspDuoAmPort.java
new file mode 100644
index 000000000..6debfa34c
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/RspDuoAmPort.java
@@ -0,0 +1,72 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * RSP-Duo AM Port
+ */
+public enum RspDuoAmPort
+{
+ PORT_1(sdrplay_api_h.sdrplay_api_RspDuo_AMPORT_1(), "HIGH Z"),
+ PORT_2(sdrplay_api_h.sdrplay_api_RspDuo_AMPORT_2(), "50\u2126 SMA");
+
+ private int mValue;
+ private String mDescription;
+
+ RspDuoAmPort(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or PORT_2 if the code is not recognized
+ */
+ public static RspDuoAmPort fromValue(int value)
+ {
+ for(RspDuoAmPort status: RspDuoAmPort.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return PORT_2;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/RspDuoTunerParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/RspDuoTunerParameters.java
new file mode 100644
index 000000000..18f31818a
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/RspDuoTunerParameters.java
@@ -0,0 +1,132 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_RspDuoTunerParamsT;
+import com.github.dsheirer.sdrplay.util.Flag;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * RSPduo Tuner Parameters structure
+ */
+public class RspDuoTunerParameters extends TunerParameters
+{
+ private MemorySegment mRspDuoMemorySegment;
+
+ /**
+ * Constructs an instance from the foreign memory segment
+ * @param tunerParametersMemorySegment of foreign memory structure
+ * @param rspDuoMemorySegment of foreign memory structure
+ */
+ RspDuoTunerParameters(MemorySegment tunerParametersMemorySegment, MemorySegment rspDuoMemorySegment)
+ {
+ super(tunerParametersMemorySegment);
+ mRspDuoMemorySegment = rspDuoMemorySegment;
+ }
+
+ /**
+ * Foreign memory segment for this structure
+ */
+ private MemorySegment getRspDuoMemorySegment()
+ {
+ return mRspDuoMemorySegment;
+ }
+
+ /**
+ * Indicates if the Bias-T is enabled
+ */
+ public boolean isBiasT()
+ {
+ return Flag.evaluate(sdrplay_api_RspDuoTunerParamsT.biasTEnable$get(getRspDuoMemorySegment()));
+ }
+
+ /**
+ * Enables or disables the Bias-T
+ */
+ public void setBiasT(boolean enable)
+ {
+ sdrplay_api_RspDuoTunerParamsT.biasTEnable$set(getRspDuoMemorySegment(), Flag.of(enable));
+ }
+
+ /**
+ * Tuner 1 AM port setting
+ */
+ public RspDuoAmPort getTuner1AmPort()
+ {
+ return RspDuoAmPort.fromValue(sdrplay_api_RspDuoTunerParamsT.tuner1AmPortSel$get(getRspDuoMemorySegment()));
+ }
+
+ /**
+ * Set Tuner 1 AM port setting
+ */
+ public void setTuner1AmPort(RspDuoAmPort amPort)
+ {
+ sdrplay_api_RspDuoTunerParamsT.tuner1AmPortSel$set(getRspDuoMemorySegment(), amPort.getValue());
+ }
+
+ /**
+ * Indicates if Tuner 1 AM notch is enabled
+ */
+ public boolean isTuner1AmNotch()
+ {
+ return Flag.evaluate(sdrplay_api_RspDuoTunerParamsT.tuner1AmNotchEnable$get(getRspDuoMemorySegment()));
+ }
+
+ /**
+ * Enables or disables the Tuner 1 AM notch
+ */
+ public void setTuner1AmNotch(boolean enable)
+ {
+ sdrplay_api_RspDuoTunerParamsT.tuner1AmNotchEnable$set(getRspDuoMemorySegment(), Flag.of(enable));
+ }
+
+ /**
+ * Indicates if the RF notch is enabled
+ */
+ public boolean isRfNotch()
+ {
+ return Flag.evaluate(sdrplay_api_RspDuoTunerParamsT.rfNotchEnable$get(getRspDuoMemorySegment()));
+ }
+
+ /**
+ * Enables or disables the RF notch
+ */
+ public void setRfNotch(boolean enable)
+ {
+ sdrplay_api_RspDuoTunerParamsT.rfNotchEnable$set(getRspDuoMemorySegment(), Flag.of(enable));
+ }
+
+ /**
+ * Indicates if the RF DAB notch is enabled
+ */
+ public boolean isRfDabNotch()
+ {
+ return Flag.evaluate(sdrplay_api_RspDuoTunerParamsT.rfDabNotchEnable$get(getRspDuoMemorySegment()));
+ }
+
+ /**
+ * Enables or disables the RF DAB notch
+ */
+ public void setRfDabNotch(boolean enable)
+ {
+ sdrplay_api_RspDuoTunerParamsT.rfDabNotchEnable$set(getRspDuoMemorySegment(), Flag.of(enable));
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/RspDxAntenna.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/RspDxAntenna.java
new file mode 100644
index 000000000..bcdd433e0
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/RspDxAntenna.java
@@ -0,0 +1,73 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_h;
+
+/**
+ * RSP-Dx Antenna
+ */
+public enum RspDxAntenna
+{
+ ANTENNA_A(sdrplay_api_h.sdrplay_api_RspDx_ANTENNA_A(), "ANT A (1 kHz to 2 GHz)"),
+ ANTENNA_B(sdrplay_api_h.sdrplay_api_RspDx_ANTENNA_B(), "ANT B (1 kHz to 2 GHz)"),
+ ANTENNA_C(sdrplay_api_h.sdrplay_api_RspDx_ANTENNA_C(), "ANT C (1 kHz to 200 MHz)");
+
+ private int mValue;
+ private String mDescription;
+
+ RspDxAntenna(int value, String description)
+ {
+ mValue = value;
+ mDescription = description;
+ }
+
+ /**
+ * Numeric value
+ */
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Lookup the entry from a return code
+ * @param value to lookup
+ * @return entry or ANTENNA A if the code is not recognized
+ */
+ public static RspDxAntenna fromValue(int value)
+ {
+ for(RspDxAntenna status: RspDxAntenna.values())
+ {
+ if(status.getValue() == value)
+ {
+ return status;
+ }
+ }
+
+ return ANTENNA_A;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/RspDxTunerParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/RspDxTunerParameters.java
new file mode 100644
index 000000000..f02931c52
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/RspDxTunerParameters.java
@@ -0,0 +1,65 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_RspDxTunerParamsT;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * RSP-Dx Tuner Parameters structure
+ */
+public class RspDxTunerParameters extends TunerParameters
+{
+ private MemorySegment mRspDxMemorySegment;
+
+ /**
+ * Constructs an instance from the foreign memory segment.
+ */
+ public RspDxTunerParameters(MemorySegment tunerParametersMemorySegment, MemorySegment rspDxMemorySegment)
+ {
+ super(tunerParametersMemorySegment);
+ mRspDxMemorySegment = rspDxMemorySegment;
+ }
+
+ /**
+ * Foreign memory segment for this structure
+ */
+ private MemorySegment getRspDxMemorySegment()
+ {
+ return mRspDxMemorySegment;
+ }
+
+ /**
+ * Current bandwidth setting for High Dynamic Range (HDR) mode
+ */
+ public HdrModeBandwidth getHdrModeBandwidth()
+ {
+ return HdrModeBandwidth.fromValue(sdrplay_api_RspDxTunerParamsT.hdrBw$get(getRspDxMemorySegment()));
+ }
+
+ /**
+ * Sets bandwidth for High Dynamic Range (HDR) mode
+ */
+ public void setHdrModeBandwidth(HdrModeBandwidth bandwidth)
+ {
+ sdrplay_api_RspDxTunerParamsT.hdrBw$set(getRspDxMemorySegment(), bandwidth.getValue());
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/TunerParameters.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/TunerParameters.java
new file mode 100644
index 000000000..006f77a07
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/TunerParameters.java
@@ -0,0 +1,140 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_TunerParamsT;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * Tuner Parameters structure (sdrplay_api_TunerParamsT)
+ */
+public abstract class TunerParameters
+{
+ private MemorySegment mMemorySegment;
+ private RfFrequency mRfFrequency;
+ private Gain mGain;
+ private DcOffsetTuner mDcOffsetTuner;
+
+ /**
+ * Constructs an instance from the foreign memory segment
+ */
+ public TunerParameters(MemorySegment memorySegment)
+ {
+ mMemorySegment = memorySegment;
+ mRfFrequency = new RfFrequency(sdrplay_api_TunerParamsT.rfFreq$slice(memorySegment));
+ mGain = new Gain(sdrplay_api_TunerParamsT.gain$slice(memorySegment));
+ mDcOffsetTuner = new DcOffsetTuner(sdrplay_api_TunerParamsT.dcOffsetTuner$slice(memorySegment));
+ }
+
+ /**
+ * Foreign memory segment for this tuner parameters structure
+ */
+ private MemorySegment getMemorySegment()
+ {
+ return mMemorySegment;
+ }
+
+ /**
+ * IF bandwidth
+ */
+ public Bandwidth getBandwidth()
+ {
+ return Bandwidth.fromValue(sdrplay_api_TunerParamsT.bwType$get(getMemorySegment()));
+ }
+
+ /**
+ * Sets the IF bandwidth
+ */
+ public void setBandwidth(Bandwidth bandwidth)
+ {
+ sdrplay_api_TunerParamsT.bwType$set(getMemorySegment(), bandwidth.getValue());
+ }
+
+ /**
+ * IF mode
+ */
+ public IfMode getIfMode()
+ {
+ return IfMode.fromValue(sdrplay_api_TunerParamsT.ifType$get(getMemorySegment()));
+ }
+
+ /**
+ * Sets IF mode
+ */
+ public void setIfMode(IfMode ifMode)
+ {
+ sdrplay_api_TunerParamsT.ifType$set(getMemorySegment(), ifMode.getValue());
+ }
+
+ /**
+ * LO mode
+ */
+ public LoMode getLoMode()
+ {
+ return LoMode.fromValue(sdrplay_api_TunerParamsT.loMode$get(getMemorySegment()));
+ }
+
+ /**
+ * Sets LO mode
+ */
+ public void setLoMode(LoMode loMode)
+ {
+ sdrplay_api_TunerParamsT.loMode$set(getMemorySegment(), loMode.getValue());
+ }
+
+ /**
+ * Gain settings structure
+ */
+ public Gain getGain()
+ {
+ return mGain;
+ }
+
+ /**
+ * RF frequency structure
+ */
+ public RfFrequency getRfFrequency()
+ {
+ return mRfFrequency;
+ }
+
+ /**
+ * DC offset tuner structure
+ */
+ public DcOffsetTuner getDcOffsetTuner()
+ {
+ return mDcOffsetTuner;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Tuner Parameters\n");
+ sb.append("\tBandwidth: ").append(getBandwidth()).append("\n");
+ sb.append("\tIF Mode: ").append(getIfMode()).append("\n");
+ sb.append("\tLO Mode: ").append(getLoMode()).append("\n");
+ sb.append("\tGain: ").append(getGain()).append("\n");
+ sb.append("\tRF Frequency: ").append(getRfFrequency()).append("\n");
+ sb.append("\tDC Offset Tuner: ").append(getDcOffsetTuner()).append("\n");
+ return sb.toString();
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/TunerParametersFactory.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/TunerParametersFactory.java
new file mode 100644
index 000000000..ab46b5b24
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/parameter/tuner/TunerParametersFactory.java
@@ -0,0 +1,66 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.parameter.tuner;
+
+import com.github.dsheirer.sdrplay.api.v3_07.sdrplay_api_RxChannelParamsT;
+import com.github.dsheirer.sdrplay.device.DeviceType;
+
+import java.lang.foreign.MemorySegment;
+
+/**
+ * Factory for creating tuner parameters structures
+ */
+public class TunerParametersFactory
+{
+ /**
+ * Creats a tuner parameters instance for the specified device type
+ * @param deviceType to create
+ * @param memorySegment for the sdrplay_api_RxChannelParamsT structure
+ * @return tuner parameters
+ */
+ public static TunerParameters create(DeviceType deviceType, MemorySegment memorySegment)
+ {
+ MemorySegment tunerParametersMemorySegment = sdrplay_api_RxChannelParamsT.tunerParams$slice(memorySegment);
+
+ switch(deviceType)
+ {
+ case RSP1 -> {
+ return new Rsp1TunerParameters(tunerParametersMemorySegment);
+ }
+ case RSP1A -> {
+ MemorySegment rsp1AMemorySegment = sdrplay_api_RxChannelParamsT.rsp1aTunerParams$slice(memorySegment);
+ return new Rsp1aTunerParameters(memorySegment, rsp1AMemorySegment);
+ }
+ case RSP2 -> {
+ MemorySegment rsp2MemorySegment = sdrplay_api_RxChannelParamsT.rsp2TunerParams$slice(memorySegment);
+ return new Rsp2TunerParameters(memorySegment, rsp2MemorySegment);
+ }
+ case RSPduo -> {
+ MemorySegment rspDuoMemorySegment = sdrplay_api_RxChannelParamsT.rspDuoTunerParams$slice(memorySegment);
+ return new RspDuoTunerParameters(memorySegment, rspDuoMemorySegment);
+ }
+ case RSPdx -> {
+ MemorySegment rspDxMemorySegment = sdrplay_api_RxChannelParamsT.rspDxTunerParams$slice(memorySegment);
+ return new RspDxTunerParameters(memorySegment, rspDxMemorySegment);
+ }
+ default -> throw new IllegalArgumentException("Unrecognized device type: " + deviceType);
+ }
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/util/Flag.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/util/Flag.java
new file mode 100644
index 000000000..ff4ead27b
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/util/Flag.java
@@ -0,0 +1,59 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.util;
+
+/**
+ * Utility for integer and byte values representing true/false flags.
+ */
+public class Flag
+{
+ public static final byte TRUE = 0x01;
+ public static final byte FALSE = 0x00;
+
+ /**
+ * Evaluates the boolean value false (0x00) or true
+ * @param value to evaluate
+ * @return true of the value is non-zero
+ */
+ public static boolean evaluate(byte value)
+ {
+ return value != FALSE;
+ }
+
+ /**
+ * Evaluates the boolean value false (0) or true
+ * @param value to evaluate
+ * @return true of the value is non-zero
+ */
+ public static boolean evaluate(int value)
+ {
+ return value != 0;
+ }
+
+ /**
+ * Returns a byte value representing the boolean value.
+ * @param value to lookup
+ * @return byte flag value
+ */
+ public static byte of(boolean value)
+ {
+ return value ? TRUE : FALSE;
+ }
+}
diff --git a/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/util/Retry.java b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/util/Retry.java
new file mode 100644
index 000000000..cc0812122
--- /dev/null
+++ b/jsdrplay/src/main/java/com/github/dsheirer/sdrplay/util/Retry.java
@@ -0,0 +1,91 @@
+/*
+ * *****************************************************************************
+ * 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 com.github.dsheirer.sdrplay.util;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+
+/**
+ * Utility for retrying SDRplay API operations with thread sleep delay
+ *
+ * Note: the SDRplay API is non-blocking and therefore non-deterministic because it will return a Fail status code
+ * if it can't execute the requested operation at that time. Your only recourse is to repeatedly attempt an
+ * operation until you get a successful status return code.
+ */
+public class Retry
+{
+ /**
+ * Attempts to execute the runnable up to a maximum of 5 attempts, sleeping the thread by 20 millis each time.
+ * @param r to execute
+ */
+ public static void quietly(Retryable r)
+ {
+ quietly(5, 20, r);
+ }
+
+ /**
+ * Attempts to execute the runnable up to a maximum of (attempts), sleeping the thread by (pause) millis each time.
+ * @param attempts number of tries
+ * @param pause in milliseconds between each attempt
+ * @param r to execute
+ */
+ public static void quietly(int attempts, long pause, Retryable r)
+ {
+ int attempt = 0;
+
+ boolean success = false;
+
+ while(attempt < attempts && !success)
+ {
+ attempt++;
+
+ try
+ {
+ r.run();
+ success = true;
+ }
+ catch(SDRPlayException e)
+ {
+ //Quietly ... no logging
+ }
+
+ if(!success)
+ {
+ try
+ {
+ Thread.sleep(pause);
+ }
+ catch(Exception e)
+ {
+ //Do nothing
+ }
+ }
+ }
+ }
+
+ /**
+ * Functional interface that encapsulates an SDRplay API operation that can throw an SDRplay exception and that
+ * can be attempted multiple times until successful.
+ */
+ @FunctionalInterface
+ public interface Retryable
+ {
+ void run() throws SDRPlayException;
+ }
+}
diff --git a/jsdrplay/src/main/java/module-info.java b/jsdrplay/src/main/java/module-info.java
new file mode 100644
index 000000000..61e6fb795
--- /dev/null
+++ b/jsdrplay/src/main/java/module-info.java
@@ -0,0 +1,18 @@
+module io.github.dsheirer.sdrplay {
+ exports com.github.dsheirer.sdrplay;
+ exports com.github.dsheirer.sdrplay.device;
+ exports com.github.dsheirer.sdrplay.callback;
+ exports com.github.dsheirer.sdrplay.parameter.composite;
+ exports com.github.dsheirer.sdrplay.parameter.device;
+ exports com.github.dsheirer.sdrplay.parameter.tuner;
+ exports com.github.dsheirer.sdrplay.parameter.control;
+ exports com.github.dsheirer.sdrplay.error;
+ exports com.github.dsheirer.sdrplay.parameter.event;
+ exports com.github.dsheirer.sdrplay.util;
+ exports com.github.dsheirer.sdrplay.async;
+
+ requires ch.qos.logback.classic;
+ requires org.apache.commons.lang3;
+ requires org.slf4j;
+ requires sdrplay.api;
+}
\ No newline at end of file
diff --git a/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/RspDeviceTest.java b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/RspDeviceTest.java
new file mode 100644
index 000000000..e2309ca79
--- /dev/null
+++ b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/RspDeviceTest.java
@@ -0,0 +1,135 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.dsherer.sdrplay.test;
+
+import com.github.dsheirer.sdrplay.DeviceSelectionMode;
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.device.Device;
+import com.github.dsheirer.sdrplay.device.DeviceInfo;
+import com.github.dsheirer.sdrplay.device.DeviceType;
+import io.github.dsherer.sdrplay.test.listener.LoggingStreamConsumer;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Unit testing for an RSP1A device
+ */
+public class RspDeviceTest
+{
+ public static final Logger mLog = LoggerFactory.getLogger(RspDeviceTest.class);
+
+ @Test
+ @DisplayName("List available RSP devices")
+ public void listDevices()
+ {
+ SDRplay api = new SDRplay();
+
+ try
+ {
+ for(DeviceInfo deviceInfo: api.getDeviceInfos())
+ {
+ mLog.info(deviceInfo.toString());
+ }
+
+ api.close();
+ }
+ catch(Exception se)
+ {
+ mLog.error("Error closing API", se);
+ }
+ }
+
+ /**
+ * Tests an RSP1A.
+ */
+ @Test
+ @DisplayName("Test an RSP1A device")
+ public void testRSP1A()
+ {
+ testDevice(DeviceType.RSP1A, DeviceSelectionMode.SINGLE_TUNER_1);
+ }
+
+ /**
+ * Tests an RSP1.
+ */
+ @Test
+ @DisplayName("Test an RSP1 device")
+ public void testRSP1()
+ {
+ testDevice(DeviceType.RSP1, DeviceSelectionMode.SINGLE_TUNER_1);
+ }
+
+ /**
+ * Tests the RSPduo with the specified device selection mode
+ * @param deviceSelectionMode
+ */
+ private void testDevice(DeviceType deviceType, DeviceSelectionMode deviceSelectionMode)
+ {
+ SDRplay api = new SDRplay();
+ mLog.info("Version: " + api.getVersion());
+ try
+ {
+ DeviceInfo deviceInfo = api.getDeviceInfo(deviceType);
+ mLog.info("Testing: " + deviceInfo + " With Device Selection Mode: " + deviceSelectionMode);
+ Device device = api.getDevice(deviceInfo);
+ device.select();
+ mLog.info("Device: " + device.toString());
+
+ mLog.info("Selected: " + device.getClass());
+
+ mLog.info("Setting Sample Rate");
+// device.setSampleRate(SampleRate.RATE_0_250);
+
+ mLog.info("Setting Frequencies");
+ device.getTuner().setFrequency(460_450_000);
+
+ mLog.info("Gain Reduction: " + device.getTuner().getGainReduction());
+ mLog.info("AGC Mode: " + device.getTuner().getAGC());
+ mLog.info("Gain: " + device.getTuner().getGain());
+ mLog.info("LO Mode:" + device.getTuner().getLoMode());
+ mLog.info("IF Mode:" + device.getTuner().getIfMode());
+
+ mLog.info("Capturing Samples ...");
+ LoggingStreamConsumer loggingStreamConsumer = new LoggingStreamConsumer(device);
+ loggingStreamConsumer.process(5);
+// loggingStreamConsumer.logSpectrum1();
+
+ device.release();
+ mLog.info("Released");
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error testing device", se);
+ }
+
+ try
+ {
+ api.close();
+ }
+ catch(Exception se)
+ {
+ mLog.error("Error closing api");
+ }
+ }
+
+}
diff --git a/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/RspDuoTest.java b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/RspDuoTest.java
new file mode 100644
index 000000000..eeb1dca1d
--- /dev/null
+++ b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/RspDuoTest.java
@@ -0,0 +1,144 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.dsherer.sdrplay.test;
+
+import org.junit.jupiter.api.TestInstance;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Unit testing for an RSPduo device
+ */
+@TestInstance(TestInstance.Lifecycle.PER_METHOD)
+public class RspDuoTest
+{
+ private static Logger mLog = LoggerFactory.getLogger(RspDuoTest.class);
+
+// /**
+// * Tests an RSPduo configured for single tuner 1.
+// */
+// @Test
+// @DisplayName("Test an RSPduo device using single tuner mode with tuner 1")
+// public void testSingleTuner1()
+// {
+// testDuo(DeviceSelectionMode.SINGLE_TUNER_1);
+// }
+//
+// /**
+// * Tests an RSPduo configured for single tuner 2.
+// */
+// @Test
+// @DisplayName("Test an RSPduo device using single tuner mode with tuner 2")
+// public void testSingleTuner2()
+// {
+// testDuo(DeviceSelectionMode.SINGLE_TUNER_2);
+// }
+//
+// /**
+// * Tests an RSPduo configured for master with tuner 1.
+// */
+// @Test
+// @DisplayName("Test an RSPduo device using master tuner mode with tuner 1")
+// public void testMasterTuner1()
+// {
+// testDuo(DeviceSelectionMode.MASTER_TUNER_1);
+// }
+//
+// /**
+// * Tests the RSPduo with the specified device selection mode
+// * @param deviceSelectionMode
+// */
+// private void testDuo(DeviceSelectionMode deviceSelectionMode)
+// {
+// SDRplay api = new SDRplay();
+//
+// DeviceInfo deviceInfo = api.getDeviceInfo(DeviceType.RSPduo);
+//
+// if(deviceInfo != null)
+// {
+// mLog.info("Testing: " + deviceInfo + " With Device Selection Mode: " + deviceSelectionMode);
+//
+// if(deviceInfo.getDeviceSelectionModes().contains(deviceSelectionMode))
+// {
+// try
+// {
+// Device device = api.select(deviceInfo, deviceSelectionMode);
+//
+// if(device instanceof RspDuoDevice)
+// {
+// mLog.info("Selected: " + device.getClass());
+//
+// if(deviceSelectionMode.isMasterMode())
+// {
+// mLog.info("Setting IF Mode");
+// device.getTuner().setIfMode(IfMode.IF_2048);
+//
+// mLog.info("Setting Sample Rate");
+//// device.setSampleRate(SampleRate.DUO_RATE_0_500);
+// }
+// else
+// {
+// mLog.info("Setting Sample Rate");
+//// device.setSampleRate(SampleRate.RATE_10_000);
+// }
+//
+// mLog.info("Setting Frequencies");
+// device.getTuner().setFrequency(460_450_000);
+//
+// mLog.info("Gain Reduction: " + device.getTuner().getGainReduction());
+// mLog.info("AGC Mode: " + device.getTuner().getAGC());
+// mLog.info("Gain: " + device.getTuner().getGain());
+// mLog.info("LO Mode:" + device.getTuner().getLoMode());
+// mLog.info("IF Mode:" + device.getTuner().getIfMode());
+//
+// mLog.info("Capturing Samples ...");
+// LoggingStreamConsumer loggingStreamConsumer = new LoggingStreamConsumer(device);
+// loggingStreamConsumer.process(5);
+// loggingStreamConsumer.logSpectrumA();
+// }
+// else
+// {
+// mLog.error("Unrecognized Device Type: " + device.getClass());
+// }
+//
+// device.release();
+// mLog.info("Released");
+// }
+// catch(SDRPlayException se)
+// {
+// mLog.error("Error testing device", se);
+// }
+// }
+// }
+// else
+// {
+// mLog.info("Unable to obtain RSPduo device to test");
+// }
+//
+// try
+// {
+// api.close();
+// }
+// catch(Exception se)
+// {
+// mLog.error("Error closing api");
+// }
+// }
+}
diff --git a/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/SDRplayTest.java b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/SDRplayTest.java
new file mode 100644
index 000000000..159a40d44
--- /dev/null
+++ b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/SDRplayTest.java
@@ -0,0 +1,69 @@
+/*
+ * *****************************************************************************
+ * 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.dsherer.sdrplay.test;
+
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.parameter.tuner.GainReduction;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class SDRplayTest
+{
+ public static Logger mlog = LoggerFactory.getLogger(SDRplayTest.class);
+
+ public SDRplayTest()
+ {
+ }
+
+ @Test
+ public void loadLibrary()
+ {
+ mlog.info("Loading SDRplay API");
+ SDRplay sdrplay = new SDRplay();
+ assertTrue(sdrplay.isAvailable(), "Library is not available");
+ }
+
+ @Test
+ @DisplayName("Ensure each Gain Reduction entry has the specified number of gain indices")
+ void testGainReductionIndices()
+ {
+ for(GainReduction gainReduction: GainReduction.values())
+ {
+ if(gainReduction != GainReduction.UNKNOWN)
+ {
+ for(int x = GainReduction.MIN_GAIN_INDEX; x <= GainReduction.MAX_GAIN_INDEX; x++)
+ {
+ int grValue = gainReduction.getGainReduction(x);
+ assertTrue(0 <= grValue, "Gain reduction value greater than 0");
+ assertTrue(59 >= grValue, "Gain reduction value less than 60");
+
+ int lnaValue = gainReduction.getLnaState(x);
+ assertTrue(0 <= lnaValue, "LNA value greater than 0");
+ assertTrue(27 >= lnaValue, "LNA value less than 60");
+ }
+ }
+ }
+ }
+
+}
diff --git a/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/Window.java b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/Window.java
new file mode 100644
index 000000000..2a34d22d6
--- /dev/null
+++ b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/Window.java
@@ -0,0 +1,498 @@
+/*
+ * *****************************************************************************
+ * 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.dsherer.sdrplay.test;
+
+import java.util.Arrays;
+import org.apache.commons.math3.util.FastMath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Window factory and corresponding utility methods.
+ */
+public class Window
+{
+ private final static Logger mLog = LoggerFactory.getLogger(Window.class);
+
+ private static final double TWO_PI = FastMath.PI * 2.0d;
+ private static final double FOUR_PI = FastMath.PI * 4.0d;
+ private static final double SIX_PI = FastMath.PI * 6.0d;
+ private static final double EIGHT_PI = FastMath.PI * 8.0d;
+
+ /**
+ * Creates a window of the specified type and length.
+ *
+ * @param type of window
+ * @param length of window
+ * @return window of the specified type and length
+ */
+ public static double[] getWindow(WindowType type, int length)
+ {
+ switch(type)
+ {
+ case BLACKMAN:
+ return getBlackman(length);
+ case BLACKMAN_HARRIS_4:
+ return getBlackmanHarris4(length);
+ case BLACKMAN_HARRIS_7:
+ return getBlackmanHarris7(length);
+ case BLACKMAN_NUTALL:
+ return getBlackmanNutall(length);
+ case COSINE:
+ return getCosine(length);
+ case FLAT_TOP:
+ return getFlatTop(length);
+ case HAMMING:
+ return getHamming(length);
+ case HANN:
+ return getHann(length);
+ case KAISER:
+ throw new IllegalArgumentException("Kaiser Window cannot be created via this method. Use the getKaiser() method instead.");
+ case NUTALL:
+ return getNutall(length);
+ case NONE:
+ default:
+ return getRectangular(length);
+ }
+ }
+
+ /**
+ * Creates an all-pass or rectangular window.
+ *
+ * @param length of the window
+ * @return rectangular window
+ */
+ public static double[] getRectangular(int length)
+ {
+ double[] coefficients = new double[length];
+
+ Arrays.fill(coefficients, 1.0d);
+
+ return coefficients;
+ }
+
+ /**
+ * Creates a cosine window of the specified length.
+ *
+ * @param length of the window
+ * @return cosine window
+ */
+ public static double[] getCosine(int length)
+ {
+ double[] coefficients = new double[length];
+
+ if(length % 2 == 0) //Even length
+ {
+ int half = (int)((length - 1) / 2);
+
+ for(int x = -half; x < length / 2 + 1; x++)
+ {
+ coefficients[x + half] = FastMath.cos(
+ ((double)x * FastMath.PI) / ((double)length + 1.0d));
+ }
+ }
+ else //Odd length
+ {
+ int half = (int)length / 2;
+
+ for(int x = -half; x < half + 1; x++)
+ {
+ coefficients[x + half] = FastMath.cos(
+ ((double)x * FastMath.PI) / ((double)length + 1.0d));
+ }
+ }
+
+ return coefficients;
+ }
+
+ /**
+ * Creates a 3-term Blackman window.
+ *
+ * @param length of the window
+ * @return Blackman window
+ */
+ public static double[] getBlackman(int length)
+ {
+ double[] coefficients = new double[length];
+
+ double denominator = length - 1;
+
+ double a0 = 0.426590713672;
+ double a1 = 0.496560619089;
+ double a2 = 0.0768486672399;
+
+ for(int x = 0; x < length; x++)
+ {
+ coefficients[x] = a0 -
+ (a1 * FastMath.cos((TWO_PI * (double)x) / denominator)) +
+ (a2 * FastMath.cos((FOUR_PI * (double)x) / denominator));
+ }
+
+ return coefficients;
+ }
+
+ /**
+ * Creates a 4-term Nutall window
+ *
+ * @param length of the window
+ * @return Nutall window
+ */
+ public static double[] getNutall(int length)
+ {
+ double[] coefficients = new double[length];
+
+ double denominator = length - 1;
+ double a0 = 0.355768;
+ double a1 = 0.487396;
+ double a2 = 0.144232;
+ double a3 = 0.012604;
+
+ for(int x = 0; x < length; x++)
+ {
+ coefficients[x] = a0 -
+ (a1 * FastMath.cos(TWO_PI * (double)x / denominator)) +
+ (a2 * FastMath.cos(FOUR_PI * (double)x / denominator)) -
+ (a3 * FastMath.cos(SIX_PI * (double)x / denominator));
+ }
+
+ return coefficients;
+ }
+
+ /**
+ * Creates a 4-term Blackman-Nutall window
+ *
+ * @param length of the window
+ * @return Blackman-Nutall window
+ */
+ public static double[] getBlackmanNutall(int length)
+ {
+ double[] coefficients = new double[length];
+
+ double denominator = length - 1;
+ double a0 = 0.3635819;
+ double a1 = 0.4891775;
+ double a2 = 0.1365995;
+ double a3 = 0.0106411;
+
+ for(int x = 0; x < length; x++)
+ {
+ coefficients[x] = a0 -
+ (a1 * FastMath.cos(TWO_PI * (double)x / denominator)) +
+ (a2 * FastMath.cos(FOUR_PI * (double)x / denominator)) -
+ (a3 * FastMath.cos(SIX_PI * (double)x / denominator));
+ }
+
+ return coefficients;
+ }
+
+ /**
+ * Creates a 4-term Blackman-Harris window
+ *
+ * @param length of the window
+ * @return Blackman-Harris window
+ */
+ public static double[] getBlackmanHarris4(int length)
+ {
+ double[] coefficients = new double[length];
+
+ double denominator = length - 1;
+ double a0 = 0.35875;
+ double a1 = 0.48829;
+ double a2 = 0.14128;
+ double a3 = 0.01168;
+
+ for(int x = 0; x < length; x++)
+ {
+ coefficients[x] = a0 -
+ (a1 * FastMath.cos(TWO_PI * (double)x / denominator)) +
+ (a2 * FastMath.cos(FOUR_PI * (double)x / denominator)) -
+ (a3 * FastMath.cos(SIX_PI * (double)x / denominator));
+ }
+
+ return coefficients;
+ }
+
+ /**
+ * Creates a 7-term Blackman-Harris window
+ *
+ * @param length of the window
+ * @return Blackman-Harris window
+ */
+ public static double[] getBlackmanHarris7(int length)
+ {
+ double[] coefficients = new double[length];
+
+ double denominator = length - 1;
+
+ double a0 = 0.27105140069342;
+ double a1 = 0.43329793923448;
+ double a2 = 0.21812299954311;
+ double a3 = 0.06592544638803;
+ double a4 = 0.01081174209837;
+ double a5 = 0.00077658482522;
+ double a6 = 0.00001388721735;
+
+
+ for(int x = 0; x < length; x++)
+ {
+ double w = TWO_PI * (double)x / denominator;
+
+ coefficients[x] = a0 -
+ (a1 * FastMath.cos(w)) +
+ (a2 * FastMath.cos(2.0 * w)) -
+ (a3 * FastMath.cos(3.0 * w)) +
+ (a4 * FastMath.cos(4.0 * w)) -
+ (a5 * FastMath.cos(5.0 * w)) +
+ (a6 * FastMath.cos(6.0 * w));
+ }
+
+ return coefficients;
+ }
+
+ /**
+ * Creates a Hamming window
+ *
+ * @param length of the window
+ * @return Hamming window
+ */
+ public static double[] getHamming(int length)
+ {
+ double[] coefficients = new double[length];
+
+ for(int x = 0; x < length; x++)
+ {
+ coefficients[x] = 0.54 - (0.46 * FastMath.cos((TWO_PI * x) / (length - 1)));
+ }
+
+ return coefficients;
+ }
+
+ /**
+ * Creates a Hann window
+ *
+ * @param length of the window
+ * @return Hann window
+ */
+ public static double[] getHann(int length)
+ {
+ double[] coefficients = new double[length];
+
+ for(int x = 0; x < length; x++)
+ {
+ coefficients[x] = 0.5 - (0.5 * FastMath.cos(TWO_PI * (double)x / (length - 1)));
+ }
+
+ return coefficients;
+ }
+
+ /**
+ * Creates a 4-term Blackman-Harris window
+ *
+ * @param length of the window
+ * @return Blackman-Harris window
+ */
+ public static double[] getFlatTop(int length)
+ {
+ double[] coefficients = new double[length];
+
+ double denominator = length - 1;
+
+ double a0 = 0.215578948;
+ double a1 = 0.41663158;
+ double a2 = 0.277263158;
+ double a3 = 0.083578947;
+ double a4 = 0.006947368;
+
+ for(int x = 0; x < length; x++)
+ {
+ coefficients[x] = a0 -
+ (a1 * FastMath.cos(TWO_PI * (double)x / denominator)) +
+ (a2 * FastMath.cos(FOUR_PI * (double)x / denominator)) -
+ (a3 * FastMath.cos(SIX_PI * (double)x / denominator)) +
+ (a4 * FastMath.cos(EIGHT_PI * (double)x / denominator));
+ }
+
+ return coefficients;
+ }
+
+ /**
+ * Calculates the beta (roll-off factor) for a Kaiser window based on the specified attenuation.
+ *
+ * @param attenuation in decibels
+ * @return beta value in the range of 0.0 to 1.0
+ */
+ public static double getKaiserBeta(double attenuation)
+ {
+ if(attenuation > 50.0)
+ {
+ return 0.1102 * (attenuation - 8.7);
+ }
+ else if(attenuation >= 21.0)
+ {
+ return (0.5842 * FastMath.pow(attenuation - 21.0, 0.4)) + (0.07886 * (attenuation - 21.0));
+ }
+ else
+ {
+ return 0.0;
+ }
+ }
+
+ /**
+ * Creates a Kaiser window.
+ *
+ * @param length of the window
+ * @param attenuation desired
+ * @return window
+ */
+ public static double[] getKaiser(int length, double attenuation)
+ {
+ double[] coefficients = new double[length];
+
+ double beta = getKaiserBeta(attenuation);
+
+ double betaBesselZerothOrder = getBesselZerothOrder(beta);
+
+ double temp;
+
+ for(int x = 0; x < coefficients.length; x++)
+ {
+ temp = beta * FastMath.sqrt(1.0 - FastMath.pow(2.0 * x / (length - 1) - 1.0, 2));
+ coefficients[x] = getBesselZerothOrder(temp) / betaBesselZerothOrder;
+ }
+
+ return coefficients;
+ }
+
+
+ /**
+ * Zeroth order modified Bessel function.
+ *
+ * @param x Value.
+ * @return Return value.
+ */
+ public final static double getBesselZerothOrder(final double x)
+ {
+ double f = 1;
+ final double x2 = x * x * 0.25;
+ double xc = x2;
+ double v = 1 + x2;
+ for (int i = 2; i < 100; i++)
+ {
+ f *= i;
+ xc *= x2;
+ final double a = xc / (f * f);
+ v += a;
+ if (a < 1e-20) break;
+ }
+
+ return v;
+ }
+
+ /**
+ * Apply the window against an array of float-type samples
+ */
+ public static float[] apply(double[] coefficients, float[] samples)
+ {
+ for(int x = 0; x < coefficients.length; x++)
+ {
+ samples[x] = (float)(samples[x] * coefficients[x]);
+ }
+
+ return samples;
+ }
+
+ /**
+ * Apply the window type against the float array of samples
+ *
+ * @param type of window to use
+ * @param samples to be windowed
+ * @return windowed samples
+ */
+ public static float[] apply(WindowType type, float[] samples)
+ {
+ double[] coefficients = getWindow(type, samples.length);
+
+ return apply(coefficients, samples);
+ }
+
+ /**
+ * Apply the window against an array of double-type samples
+ */
+ public static double[] apply(double[] coefficients, double[] samples)
+ {
+ for(int x = 0; x < coefficients.length; x++)
+ {
+ samples[x] = samples[x] * coefficients[x];
+ }
+
+ return samples;
+ }
+
+ /**
+ * Apply the window type against the double array of samples
+ *
+ * @param type of window to use
+ * @param samples to be windowed
+ * @return windowed samples
+ */
+ public static double[] apply(WindowType type, double[] samples)
+ {
+ double[] coefficients = getWindow(type, samples.length);
+
+ return apply(coefficients, samples);
+ }
+
+ /**
+ * Window types
+ */
+ public enum WindowType
+ {
+ BLACKMAN("Blackman"),
+ BLACKMAN_HARRIS_4("Blackman-Harris 4"),
+ BLACKMAN_HARRIS_7("Blackman-Harris 7"),
+ BLACKMAN_NUTALL("Blackman-Nutall"),
+ COSINE("Cosine"),
+ FLAT_TOP("Flat Top"),
+ HAMMING("Hamming"),
+ HANN("Hann"),
+ KAISER("Kaiser"),
+ NUTALL("Nutall"),
+ NONE("None");
+
+ private String mLabel;
+
+ WindowType(String label)
+ {
+ mLabel = label;
+ }
+
+ public String toString()
+ {
+ return mLabel;
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ double[] kaiser = getKaiser(16, 80.0);
+
+ mLog.debug("Window:" + Arrays.toString(kaiser));
+ }
+}
diff --git a/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/listener/ISampleCountListener.java b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/listener/ISampleCountListener.java
new file mode 100644
index 000000000..a9ec32ad9
--- /dev/null
+++ b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/listener/ISampleCountListener.java
@@ -0,0 +1,31 @@
+/*
+ * *****************************************************************************
+ * 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.dsherer.sdrplay.test.listener;
+
+/**
+ * Listener interface to be notified of cumulative/increasing sample count
+ */
+public interface ISampleCountListener
+{
+ /**
+ * Notification of the current sample count
+ */
+ void sampleCount(long sampleCount);
+}
diff --git a/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/listener/LoggingDeviceEventListener.java b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/listener/LoggingDeviceEventListener.java
new file mode 100644
index 000000000..b5be7757d
--- /dev/null
+++ b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/listener/LoggingDeviceEventListener.java
@@ -0,0 +1,90 @@
+/*
+ * *****************************************************************************
+ * 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.dsherer.sdrplay.test.listener;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.callback.IDeviceEventListener;
+import com.github.dsheirer.sdrplay.device.Device;
+import com.github.dsheirer.sdrplay.device.TunerSelect;
+import com.github.dsheirer.sdrplay.parameter.event.EventType;
+import com.github.dsheirer.sdrplay.parameter.event.GainCallbackParameters;
+import com.github.dsheirer.sdrplay.parameter.event.PowerOverloadCallbackParameters;
+import com.github.dsheirer.sdrplay.parameter.event.RspDuoModeCallbackParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Logging device event listener for debug or testing.
+ */
+public class LoggingDeviceEventListener implements IDeviceEventListener
+{
+ private static final Logger mLog = LoggerFactory.getLogger(LoggingDeviceEventListener.class);
+ private String mLabel;
+ private Device mDevice;
+
+ /**
+ * Constructs an instance
+ * @param label prefix for logging.
+ */
+ public LoggingDeviceEventListener(String label, Device device)
+ {
+ mLabel = label;
+ mDevice = device;
+ }
+
+ @Override
+ public void processEvent(EventType eventType, TunerSelect tunerSelect)
+ {
+ mLog.info(mLabel + " - Unrecognized Event: " + eventType + " Tuner:" + tunerSelect);
+ }
+
+ @Override
+ public void processGainChange(TunerSelect tunerSelect, GainCallbackParameters gainCallbackParameters)
+ {
+ mLog.info(mLabel + " - Gain Change - Tuner: " + tunerSelect + " " + gainCallbackParameters.toString());
+ }
+
+ @Override
+ public void processPowerOverload(TunerSelect tunerSelect, PowerOverloadCallbackParameters parameters)
+ {
+ mLog.info(mLabel + " - Power Overload - Tuner: " + tunerSelect + " - acknowledging");
+
+ try
+ {
+ mDevice.acknowledgePowerOverload(tunerSelect);
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to acknowledge power overload for tuner(s): " + tunerSelect + ": " + se.getLocalizedMessage());
+ }
+ }
+
+ @Override
+ public void processRspDuoModeChange(TunerSelect tunerSelect, RspDuoModeCallbackParameters parameters)
+ {
+ mLog.info(mLabel + " - RSPduo Mode Change - Tuner: " + tunerSelect + " Event:" + parameters.getRspDuoModeEvent());
+ }
+
+ @Override
+ public void processDeviceRemoval(TunerSelect tunerSelect)
+ {
+ mLog.info(mLabel + " - Device Removed");
+ }
+}
diff --git a/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/listener/LoggingStreamConsumer.java b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/listener/LoggingStreamConsumer.java
new file mode 100644
index 000000000..203edfd96
--- /dev/null
+++ b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/listener/LoggingStreamConsumer.java
@@ -0,0 +1,123 @@
+/*
+ * *****************************************************************************
+ * 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.dsherer.sdrplay.test.listener;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.callback.IDeviceEventListener;
+import com.github.dsheirer.sdrplay.device.Device;
+import com.github.dsheirer.sdrplay.device.TunerSelect;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Streaming samples consumer that can initialize a device, process streaming data for 5 seconds, and un-initialize
+ * the device.
+ */
+public class LoggingStreamConsumer
+{
+ private static final Logger mLog = LoggerFactory.getLogger(LoggingStreamConsumer.class);
+ private Device mDevice;
+ private LoggingStreamListener mStreamAListener;
+ private LoggingStreamListener mStreamBListener;
+ private IDeviceEventListener mDeviceEventListener;
+
+ public LoggingStreamConsumer(Device device, TunerSelect tunerA, TunerSelect tunerB)
+ {
+ mDevice = device;
+ mDeviceEventListener = new LoggingDeviceEventListener(device.getDeviceType().toString(), device);
+ mStreamAListener = new LoggingStreamListener("Stream A", tunerA);
+ mStreamBListener = new LoggingStreamListener("Stream B", tunerB);
+ }
+
+ public LoggingStreamConsumer(Device device)
+ {
+ this(device, TunerSelect.TUNER_1, TunerSelect.TUNER_2);
+ }
+
+ /**
+ * Initializes the device, consumes samples for the specified period and then uninitializes the device.
+ * @param durationSeconds duration of the test in seconds.
+ * @throws SDRPlayException
+ */
+ public void process(int durationSeconds) throws SDRPlayException
+ {
+ mLog.info("Initializing device ...");
+ mDevice.initStreamA(mDeviceEventListener, mStreamAListener);
+
+ final long startTimestamp = System.currentTimeMillis();
+
+ CountDownLatch latch = new CountDownLatch(1);
+
+ ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
+ executorService.schedule(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ try
+ {
+ mLog.info("Un-initializing the device");
+ mDevice.uninitialize();
+
+ mStreamAListener.logSampleRate(System.currentTimeMillis() - startTimestamp);
+ mStreamBListener.logSampleRate(System.currentTimeMillis() - startTimestamp);
+
+ mLog.info("releasing device");
+ mDevice.release();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error releasing RSPduo device", se);
+ }
+
+ latch.countDown();
+ }
+ }, durationSeconds, TimeUnit.SECONDS);
+
+ try
+ {
+ latch.await(durationSeconds + 10, TimeUnit.SECONDS);
+ }
+ catch(InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Logs the spectral (FFT) data captured from stream A.
+ */
+ public void logSpectrumA()
+ {
+ mStreamAListener.logSpectrum();
+ }
+
+ /**
+ * Logs the spectral (FFT) data captured from stream B.
+ */
+ public void logSpectrumB()
+ {
+ mStreamBListener.logSpectrum();
+ }
+}
diff --git a/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/listener/LoggingStreamListener.java b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/listener/LoggingStreamListener.java
new file mode 100644
index 000000000..6aa69195f
--- /dev/null
+++ b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/listener/LoggingStreamListener.java
@@ -0,0 +1,203 @@
+/*
+ * *****************************************************************************
+ * 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.dsherer.sdrplay.test.listener;
+
+import com.github.dsheirer.sdrplay.callback.IStreamListener;
+import com.github.dsheirer.sdrplay.callback.StreamCallbackParameters;
+import com.github.dsheirer.sdrplay.device.TunerSelect;
+import io.github.dsherer.sdrplay.test.Window;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.math3.util.FastMath;
+import org.jtransforms.fft.FloatFFT_1D;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Simple stream listener for debug/testing. Provides logging
+ */
+public class LoggingStreamListener implements IStreamListener
+{
+ private static final Logger mLog = LoggerFactory.getLogger(LoggingStreamListener.class);
+ private final String mLabel;
+ private final TunerSelect mTunerSelect;
+ private long mSampleCount = 0;
+ private static final int FFT_SIZE = 8192;
+ private short[] mISamples = new short[FFT_SIZE];
+ private short[] mQSamples = new short[FFT_SIZE];
+ private ISampleCountListener mSampleCountListener;
+
+ /**
+ * Constructs an instance.
+ * @param label to use as a prefix for logging
+ * @param tunerSelect to indicate which tuner is producing the samples.
+ */
+ public LoggingStreamListener(String label, TunerSelect tunerSelect)
+ {
+ mLabel = label;
+ mTunerSelect = tunerSelect;
+ }
+
+ @Override
+ public TunerSelect getTunerSelect()
+ {
+ return mTunerSelect;
+ }
+
+ /**
+ * Registers the listener to be notified of the cumulative sample count received by this stream listener.
+ */
+ public void setSampleCountListener(ISampleCountListener listener)
+ {
+ mSampleCountListener = listener;
+ }
+
+ public short[] getISamples()
+ {
+ return mISamples;
+ }
+
+ public short[] getQSamples()
+ {
+ return mQSamples;
+ }
+
+ /**
+ * Resets the sample counter and the log emission interval counter
+ */
+ public void reset()
+ {
+ mSampleCount = 0;
+ }
+
+ /**
+ * Calculates the estimated sample rate using the sample count and the provided elapsed milliseconds value.
+ * @param elapsedMilliseconds value
+ */
+ public void logSampleRate(long elapsedMilliseconds)
+ {
+ DecimalFormat df = new DecimalFormat("0.000");
+
+ mLog.info(mLabel + " - " + NumberFormat.getNumberInstance().format(mSampleCount) +
+ " samples captured in " + df.format(elapsedMilliseconds / 1E3d) +
+ " secs. Approximate Sample Rate:" +
+ df.format(mSampleCount / (elapsedMilliseconds / 1E3d) / 1E6d) + " MHz");
+ }
+
+ /**
+ * Sample count
+ */
+ public long getSampleCount()
+ {
+ return mSampleCount;
+ }
+
+ @Override
+ public void processStream(short[] xi, short[] xq, StreamCallbackParameters parameters,
+ boolean reset)
+ {
+ //Retain latest set of samples for post run FFT
+ System.arraycopy(mISamples, xi.length, mISamples, 0, mISamples.length - xi.length);
+ System.arraycopy(xi, 0, mISamples, mISamples.length - xi.length, xi.length);
+ System.arraycopy(mQSamples, xq.length, mQSamples, 0, mQSamples.length - xq.length);
+ System.arraycopy(xq, 0, mQSamples, mQSamples.length - xq.length, xq.length);
+
+ if(reset || parameters.isGainReductionChanged() || parameters.isRfFrequencyChanged() || parameters.isSampleRateChanged())
+ {
+ List changes = new ArrayList<>();
+ if(reset)
+ {
+ changes.add("TUNER RESET");
+ }
+ if(parameters.isGainReductionChanged())
+ {
+ changes.add("GAIN REDUCTION");
+ }
+ if(parameters.isRfFrequencyChanged())
+ {
+ changes.add("RF CENTER FREQUENCY");
+ }
+ if(parameters.isSampleRateChanged())
+ {
+ changes.add("SAMPLE RATE");
+ }
+
+ mLog.info(mLabel + " - Parameters Changed " + changes);
+ }
+
+ mSampleCount += parameters.getNumberSamples();
+
+ if(mSampleCountListener != null)
+ {
+ mSampleCountListener.sampleCount(mSampleCount);
+ }
+ }
+
+ public void logSpectrum()
+ {
+ if(mISamples != null && mQSamples != null)
+ {
+ float multiplier = 1.0f / Short.MAX_VALUE;
+
+ float[] samples = new float[FFT_SIZE * 2];
+
+ for(int x = 0; x < FFT_SIZE; x ++)
+ {
+ samples[x * 2] = mISamples[x] * multiplier;
+ samples[x * 2 + 1] = mQSamples[x] * multiplier;
+ }
+
+ Window.apply(Window.WindowType.BLACKMAN, samples);
+
+ FloatFFT_1D fft = new FloatFFT_1D(FFT_SIZE);
+ fft.complexForward(samples);
+
+ double[] db = new double[FFT_SIZE];
+
+ //dB scaling factor for 14-bit sample size
+ double scalor = -20.0 * Math.log10(1.0 / Math.pow(2.0, 13));
+
+ for(int x = 0; x < FFT_SIZE; x++)
+ {
+ double magnitude = Math.pow(samples[x * 2], 2.0) + Math.pow(samples[x * 2 + 1], 2.0);
+ db[x] = ((10.0 * FastMath.log10(magnitude) / FFT_SIZE) * scalor * 100) - 72;
+ }
+
+ double[] db_arranged = new double[FFT_SIZE];
+ System.arraycopy(db, 0, db_arranged, FFT_SIZE / 2, FFT_SIZE / 2);
+ System.arraycopy(db, FFT_SIZE / 2, db_arranged, 0, FFT_SIZE / 2);
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("\n\n=========================================== " + mLabel +
+ " FFT Spectrum ===========================================================\n\n");
+ for(int x = 0; x < db_arranged.length; x++)
+ {
+ sb.append(db_arranged[x]).append("\n");
+ }
+ mLog.info(mLabel + " - Calculated Spectrum (FFT): " + sb);
+ }
+ else
+ {
+ mLog.info(mLabel + " either I or Q samples were null ... no fft for you today");
+ }
+ }
+}
diff --git a/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/listener/SampleCountLogger.java b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/listener/SampleCountLogger.java
new file mode 100644
index 000000000..2faa26ce1
--- /dev/null
+++ b/jsdrplay/src/test/java/io/github/dsherer/sdrplay/test/listener/SampleCountLogger.java
@@ -0,0 +1,49 @@
+/*
+ * *****************************************************************************
+ * 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.dsherer.sdrplay.test.listener;
+
+/**
+ * Logs the cumulative/running sample count
+ */
+public class SampleCountLogger implements ISampleCountListener
+{
+ private final String mLabel;
+ private final int mSampleLogInterval;
+
+ public SampleCountLogger(String label, int sampleLoggingInterval)
+ {
+ mLabel = label;
+ mSampleLogInterval = sampleLoggingInterval;
+ }
+
+ @Override
+ public void sampleCount(long sampleCount)
+ {
+
+// mEmitSampleLogCount++;
+//
+// if(mEmitSampleLogCount % mSampleLogInterval == 0)
+// {
+// mEmitSampleLogCount = 0;
+// mLog.info(mLabel + " - Samples Received: " + mSampleCount);
+// }
+
+ }
+}
diff --git a/sdrplay-api/api/README.txt b/sdrplay-api/api/README.txt
new file mode 100644
index 000000000..ff2036b1b
--- /dev/null
+++ b/sdrplay-api/api/README.txt
@@ -0,0 +1,36 @@
+Auto-generating Java code from SDRPlay API using jextract.
+
+Note: the api headers in the 3.11 folder are equivalent to the 3.08 headers. The only
+difference from the 3.07 headers is the addition of the boolean 'valid' flag to DeviceT structure.
+
+1. Download JDK19 compatible build of jextract JDK: https://jdk.java.net/jextract/
+2. If generating on windows platform, modify the sdrplay_api.h to remove the windows
+ pieces of the file. Specifically:
+2a. Comment out these lines but leave the *HANDLE typedef:
+
+//#if defined(_M_X64) || defined(_M_IX86) || defined(_M_ARM64)
+//#include "windows.h"
+//#elif defined (__GNUC__)
+typedef void *HANDLE;
+//#endif
+
+//#ifndef _SDRPLAY_DLL_QUALIFIER
+//#if !defined(STATIC_LIB) && (defined(_M_X64) || defined(_M_IX86) || defined(_M_ARM64))
+//#define _SDRPLAY_DLL_QUALIFIER __declspec(dllimport)
+//#elif defined(STATIC_LIB) || defined(__GNUC__)
+//#define _SDRPLAY_DLL_QUALIFIER
+//#endif
+//#endif // _SDRPLAY_DLL_QUALIFIER
+
+2b. Remove the '_SDRPLAY_DLL_QUALIFIER' from in front of the method declarations
+
+2c. Change the 3.11 version string to 3.08 either in the header file, or in the generated java class
+
+3. Open command prompt to the root source code where the generated files should be placed:
+..\SDRtrunk\sdrplay-api\src\main\java
+
+4. Generate the code:
+c:\Users\Denny\Downloads\jdk-19-ea2-panama\bin\jextract "C:\Users\Denny\git\sdrtrunk\sdrplay-api\api\v3_11\sdrplay_api.h" -l libsdrplay_api --source
+
+5. Do this for all versions of the API.
+
diff --git a/sdrplay-api/api/v3_07/sdrplay_api.h b/sdrplay-api/api/v3_07/sdrplay_api.h
new file mode 100644
index 000000000..321b8a511
--- /dev/null
+++ b/sdrplay-api/api/v3_07/sdrplay_api.h
@@ -0,0 +1,229 @@
+#ifndef SDRPLAY_API_H
+#define SDRPLAY_API_H
+
+#include "sdrplay_api_dev.h"
+#include "sdrplay_api_rx_channel.h"
+#include "sdrplay_api_callback.h"
+
+//#if defined(_M_X64) || defined(_M_IX86)
+//#include "windows.h"
+//#elif defined (__GNUC__)
+typedef void *HANDLE;
+//#endif
+
+//#ifndef _SDRPLAY_DLL_QUALIFIER
+//#if !defined(STATIC_LIB) && (defined(_M_X64) || defined(_M_IX86))
+//#define _SDRPLAY_DLL_QUALIFIER __declspec(dllimport)
+//#elif defined(STATIC_LIB) || defined(__GNUC__)
+//#define _SDRPLAY_DLL_QUALIFIER
+//#endif
+//#endif // _SDRPLAY_DLL_QUALIFIER
+
+// Application code should check that it is compiled against the same API version
+// sdrplay_api_ApiVersion() returns the API version
+#define SDRPLAY_API_VERSION (float)(3.07)
+
+// API Constants
+#define SDRPLAY_MAX_DEVICES (16)
+#define SDRPLAY_MAX_TUNERS_PER_DEVICE (2)
+
+#define SDRPLAY_MAX_SER_NO_LEN (64)
+#define SDRPLAY_MAX_ROOT_NM_LEN (32)
+
+#define SDRPLAY_RSP1_ID (1)
+#define SDRPLAY_RSP1A_ID (255)
+#define SDRPLAY_RSP2_ID (2)
+#define SDRPLAY_RSPduo_ID (3)
+#define SDRPLAY_RSPdx_ID (4)
+
+// Enum types
+typedef enum
+{
+ sdrplay_api_Success = 0,
+ sdrplay_api_Fail = 1,
+ sdrplay_api_InvalidParam = 2,
+ sdrplay_api_OutOfRange = 3,
+ sdrplay_api_GainUpdateError = 4,
+ sdrplay_api_RfUpdateError = 5,
+ sdrplay_api_FsUpdateError = 6,
+ sdrplay_api_HwError = 7,
+ sdrplay_api_AliasingError = 8,
+ sdrplay_api_AlreadyInitialised = 9,
+ sdrplay_api_NotInitialised = 10,
+ sdrplay_api_NotEnabled = 11,
+ sdrplay_api_HwVerError = 12,
+ sdrplay_api_OutOfMemError = 13,
+ sdrplay_api_ServiceNotResponding = 14,
+ sdrplay_api_StartPending = 15,
+ sdrplay_api_StopPending = 16,
+ sdrplay_api_InvalidMode = 17,
+ sdrplay_api_FailedVerification1 = 18,
+ sdrplay_api_FailedVerification2 = 19,
+ sdrplay_api_FailedVerification3 = 20,
+ sdrplay_api_FailedVerification4 = 21,
+ sdrplay_api_FailedVerification5 = 22,
+ sdrplay_api_FailedVerification6 = 23,
+ sdrplay_api_InvalidServiceVersion = 24
+} sdrplay_api_ErrT;
+
+typedef enum
+{
+ sdrplay_api_Update_None = 0x00000000,
+
+ // Reasons for master only mode
+ sdrplay_api_Update_Dev_Fs = 0x00000001,
+ sdrplay_api_Update_Dev_Ppm = 0x00000002,
+ sdrplay_api_Update_Dev_SyncUpdate = 0x00000004,
+ sdrplay_api_Update_Dev_ResetFlags = 0x00000008,
+
+ sdrplay_api_Update_Rsp1a_BiasTControl = 0x00000010,
+ sdrplay_api_Update_Rsp1a_RfNotchControl = 0x00000020,
+ sdrplay_api_Update_Rsp1a_RfDabNotchControl = 0x00000040,
+
+ sdrplay_api_Update_Rsp2_BiasTControl = 0x00000080,
+ sdrplay_api_Update_Rsp2_AmPortSelect = 0x00000100,
+ sdrplay_api_Update_Rsp2_AntennaControl = 0x00000200,
+ sdrplay_api_Update_Rsp2_RfNotchControl = 0x00000400,
+ sdrplay_api_Update_Rsp2_ExtRefControl = 0x00000800,
+
+ sdrplay_api_Update_RspDuo_ExtRefControl = 0x00001000,
+
+ sdrplay_api_Update_Master_Spare_1 = 0x00002000,
+ sdrplay_api_Update_Master_Spare_2 = 0x00004000,
+
+ // Reasons for master and slave mode
+ // Note: sdrplay_api_Update_Tuner_Gr MUST be the first value defined in this section!
+ sdrplay_api_Update_Tuner_Gr = 0x00008000,
+ sdrplay_api_Update_Tuner_GrLimits = 0x00010000,
+ sdrplay_api_Update_Tuner_Frf = 0x00020000,
+ sdrplay_api_Update_Tuner_BwType = 0x00040000,
+ sdrplay_api_Update_Tuner_IfType = 0x00080000,
+ sdrplay_api_Update_Tuner_DcOffset = 0x00100000,
+ sdrplay_api_Update_Tuner_LoMode = 0x00200000,
+
+ sdrplay_api_Update_Ctrl_DCoffsetIQimbalance = 0x00400000,
+ sdrplay_api_Update_Ctrl_Decimation = 0x00800000,
+ sdrplay_api_Update_Ctrl_Agc = 0x01000000,
+ sdrplay_api_Update_Ctrl_AdsbMode = 0x02000000,
+ sdrplay_api_Update_Ctrl_OverloadMsgAck = 0x04000000,
+
+ sdrplay_api_Update_RspDuo_BiasTControl = 0x08000000,
+ sdrplay_api_Update_RspDuo_AmPortSelect = 0x10000000,
+ sdrplay_api_Update_RspDuo_Tuner1AmNotchControl = 0x20000000,
+ sdrplay_api_Update_RspDuo_RfNotchControl = 0x40000000,
+ sdrplay_api_Update_RspDuo_RfDabNotchControl = 0x80000000,
+} sdrplay_api_ReasonForUpdateT;
+
+typedef enum
+{
+ sdrplay_api_Update_Ext1_None = 0x00000000,
+
+ // Reasons for master only mode
+ sdrplay_api_Update_RspDx_HdrEnable = 0x00000001,
+ sdrplay_api_Update_RspDx_BiasTControl = 0x00000002,
+ sdrplay_api_Update_RspDx_AntennaControl = 0x00000004,
+ sdrplay_api_Update_RspDx_RfNotchControl = 0x00000008,
+ sdrplay_api_Update_RspDx_RfDabNotchControl = 0x00000010,
+ sdrplay_api_Update_RspDx_HdrBw = 0x00000020,
+
+ // Reasons for master and slave mode
+} sdrplay_api_ReasonForUpdateExtension1T;
+
+typedef enum
+{
+ sdrplay_api_DbgLvl_Disable = 0,
+ sdrplay_api_DbgLvl_Verbose = 1,
+ sdrplay_api_DbgLvl_Warning = 2,
+ sdrplay_api_DbgLvl_Error = 3,
+ sdrplay_api_DbgLvl_Message = 4,
+} sdrplay_api_DbgLvl_t;
+
+// Device structure
+typedef struct
+{
+ char SerNo[SDRPLAY_MAX_SER_NO_LEN];
+ unsigned char hwVer;
+ sdrplay_api_TunerSelectT tuner;
+ sdrplay_api_RspDuoModeT rspDuoMode;
+ double rspDuoSampleFreq;
+ HANDLE dev;
+} sdrplay_api_DeviceT;
+
+// Device parameter structure
+typedef struct
+{
+ sdrplay_api_DevParamsT *devParams;
+ sdrplay_api_RxChannelParamsT *rxChannelA;
+ sdrplay_api_RxChannelParamsT *rxChannelB;
+} sdrplay_api_DeviceParamsT;
+
+// Extended error message structure
+typedef struct
+{
+ char file[256];
+ char function[256];
+ int line;
+ char message[1024];
+} sdrplay_api_ErrorInfoT;
+
+// Comman API function types
+typedef sdrplay_api_ErrT (*sdrplay_api_Open_t)(void);
+typedef sdrplay_api_ErrT (*sdrplay_api_Close_t)(void);
+typedef sdrplay_api_ErrT (*sdrplay_api_ApiVersion_t)(float *apiVer);
+typedef sdrplay_api_ErrT (*sdrplay_api_LockDeviceApi_t)(void);
+typedef sdrplay_api_ErrT (*sdrplay_api_UnlockDeviceApi_t)(void);
+typedef sdrplay_api_ErrT (*sdrplay_api_GetDevices_t)(sdrplay_api_DeviceT *devices, unsigned int *numDevs, unsigned int maxDevs);
+typedef sdrplay_api_ErrT (*sdrplay_api_SelectDevice_t)(sdrplay_api_DeviceT *device);
+typedef sdrplay_api_ErrT (*sdrplay_api_ReleaseDevice_t)(sdrplay_api_DeviceT *device);
+typedef const char* (*sdrplay_api_GetErrorString_t)(sdrplay_api_ErrT err);
+typedef sdrplay_api_ErrorInfoT* (*sdrplay_api_GetLastError_t)(sdrplay_api_DeviceT *device);
+typedef sdrplay_api_ErrT (*sdrplay_api_DisableHeartbeat_t)(void);
+
+// Device API function types
+typedef sdrplay_api_ErrT (*sdrplay_api_DebugEnable_t)(HANDLE dev, sdrplay_api_DbgLvl_t dbgLvl);
+typedef sdrplay_api_ErrT (*sdrplay_api_GetDeviceParams_t)(HANDLE dev, sdrplay_api_DeviceParamsT **deviceParams);
+typedef sdrplay_api_ErrT (*sdrplay_api_Init_t)(HANDLE dev, sdrplay_api_CallbackFnsT *callbackFns, void *cbContext);
+typedef sdrplay_api_ErrT (*sdrplay_api_Uninit_t)(HANDLE dev);
+typedef sdrplay_api_ErrT (*sdrplay_api_Update_t)(HANDLE dev, sdrplay_api_TunerSelectT tuner, sdrplay_api_ReasonForUpdateT reasonForUpdate, sdrplay_api_ReasonForUpdateExtension1T reasonForUpdateExt1);
+typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoActiveTuner_t)(HANDLE dev, sdrplay_api_TunerSelectT *tuner, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
+typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t)(double *currentSampleRate);
+typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoMode_t)(sdrplay_api_DeviceT *currDevice, sdrplay_api_DeviceParamsT **deviceParams,
+ sdrplay_api_RspDuoModeT rspDuoMode, double sampleRate, sdrplay_api_TunerSelectT tuner,
+ sdrplay_api_Bw_MHzT bwType, sdrplay_api_If_kHzT ifType, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
+
+// API function definitions
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ // Comman API function definitions
+ sdrplay_api_ErrT sdrplay_api_Open(void);
+ sdrplay_api_ErrT sdrplay_api_Close(void);
+ sdrplay_api_ErrT sdrplay_api_ApiVersion(float *apiVer);
+ sdrplay_api_ErrT sdrplay_api_LockDeviceApi(void);
+ sdrplay_api_ErrT sdrplay_api_UnlockDeviceApi(void);
+ sdrplay_api_ErrT sdrplay_api_GetDevices(sdrplay_api_DeviceT *devices, unsigned int *numDevs, unsigned int maxDevs);
+ sdrplay_api_ErrT sdrplay_api_SelectDevice(sdrplay_api_DeviceT *device);
+ sdrplay_api_ErrT sdrplay_api_ReleaseDevice(sdrplay_api_DeviceT *device);
+ const char* sdrplay_api_GetErrorString(sdrplay_api_ErrT err);
+ sdrplay_api_ErrorInfoT* sdrplay_api_GetLastError(sdrplay_api_DeviceT *device);
+ sdrplay_api_ErrT sdrplay_api_DisableHeartbeat(void); // Must be called before sdrplay_api_SelectDevice()
+
+ // Device API function definitions
+ sdrplay_api_ErrT sdrplay_api_DebugEnable(HANDLE dev, sdrplay_api_DbgLvl_t enable);
+ sdrplay_api_ErrT sdrplay_api_GetDeviceParams(HANDLE dev, sdrplay_api_DeviceParamsT **deviceParams);
+ sdrplay_api_ErrT sdrplay_api_Init(HANDLE dev, sdrplay_api_CallbackFnsT *callbackFns, void *cbContext);
+ sdrplay_api_ErrT sdrplay_api_Uninit(HANDLE dev);
+ sdrplay_api_ErrT sdrplay_api_Update(HANDLE dev, sdrplay_api_TunerSelectT tuner, sdrplay_api_ReasonForUpdateT reasonForUpdate, sdrplay_api_ReasonForUpdateExtension1T reasonForUpdateExt1);
+ sdrplay_api_ErrT sdrplay_api_SwapRspDuoActiveTuner(HANDLE dev, sdrplay_api_TunerSelectT *currentTuner, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
+ sdrplay_api_ErrT sdrplay_api_SwapRspDuoDualTunerModeSampleRate(HANDLE dev, double *currentSampleRate);
+ sdrplay_api_ErrT sdrplay_api_SwapRspDuoMode(sdrplay_api_DeviceT *currDevice, sdrplay_api_DeviceParamsT **deviceParams,
+ sdrplay_api_RspDuoModeT rspDuoMode, double sampleRate, sdrplay_api_TunerSelectT tuner,
+ sdrplay_api_Bw_MHzT bwType, sdrplay_api_If_kHzT ifType, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //SDRPLAY_API_H
diff --git a/sdrplay-api/api/v3_07/sdrplay_api_callback.h b/sdrplay-api/api/v3_07/sdrplay_api_callback.h
new file mode 100644
index 000000000..88d560490
--- /dev/null
+++ b/sdrplay-api/api/v3_07/sdrplay_api_callback.h
@@ -0,0 +1,78 @@
+#ifndef SDRPLAY_API_CALLBACK_H
+#define SDRPLAY_API_CALLBACK_H
+
+// Event callback enums
+typedef enum
+{
+ sdrplay_api_Overload_Detected = 0,
+ sdrplay_api_Overload_Corrected = 1,
+} sdrplay_api_PowerOverloadCbEventIdT;
+
+typedef enum
+{
+ sdrplay_api_MasterInitialised = 0,
+ sdrplay_api_SlaveAttached = 1,
+ sdrplay_api_SlaveDetached = 2,
+ sdrplay_api_SlaveInitialised = 3,
+ sdrplay_api_SlaveUninitialised = 4,
+ sdrplay_api_MasterDllDisappeared = 5,
+ sdrplay_api_SlaveDllDisappeared = 6,
+} sdrplay_api_RspDuoModeCbEventIdT;
+
+typedef enum
+{
+ sdrplay_api_GainChange = 0,
+ sdrplay_api_PowerOverloadChange = 1,
+ sdrplay_api_DeviceRemoved = 2,
+ sdrplay_api_RspDuoModeChange = 3,
+} sdrplay_api_EventT;
+
+// Event callback parameter structs
+typedef struct
+{
+ unsigned int gRdB;
+ unsigned int lnaGRdB;
+ double currGain;
+} sdrplay_api_GainCbParamT;
+
+typedef struct
+{
+ sdrplay_api_PowerOverloadCbEventIdT powerOverloadChangeType;
+} sdrplay_api_PowerOverloadCbParamT;
+
+typedef struct
+{
+ sdrplay_api_RspDuoModeCbEventIdT modeChangeType;
+} sdrplay_api_RspDuoModeCbParamT;
+
+// Event parameters overlay
+typedef union
+{
+ sdrplay_api_GainCbParamT gainParams;
+ sdrplay_api_PowerOverloadCbParamT powerOverloadParams;
+ sdrplay_api_RspDuoModeCbParamT rspDuoModeParams;
+} sdrplay_api_EventParamsT;
+
+// Stream callback parameter structs
+typedef struct
+{
+ unsigned int firstSampleNum;
+ int grChanged;
+ int rfChanged;
+ int fsChanged;
+ unsigned int numSamples;
+} sdrplay_api_StreamCbParamsT;
+
+// Callback function prototypes
+typedef void (*sdrplay_api_StreamCallback_t)(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext);
+typedef void (*sdrplay_api_EventCallback_t)(sdrplay_api_EventT eventId, sdrplay_api_TunerSelectT tuner, sdrplay_api_EventParamsT *params, void *cbContext);
+
+// Callback function struct
+typedef struct
+{
+ sdrplay_api_StreamCallback_t StreamACbFn;
+ sdrplay_api_StreamCallback_t StreamBCbFn;
+ sdrplay_api_EventCallback_t EventCbFn;
+} sdrplay_api_CallbackFnsT;
+
+#endif //SDRPLAY_API_CALLBACK_H
diff --git a/sdrplay-api/api/v3_07/sdrplay_api_control.h b/sdrplay-api/api/v3_07/sdrplay_api_control.h
new file mode 100644
index 000000000..5a52a1046
--- /dev/null
+++ b/sdrplay-api/api/v3_07/sdrplay_api_control.h
@@ -0,0 +1,55 @@
+#ifndef SDRPLAY_API_CONTROL_H
+#define SDRPLAY_API_CONTROL_H
+
+// Control parameter enums
+typedef enum
+{
+ sdrplay_api_AGC_DISABLE = 0,
+ sdrplay_api_AGC_100HZ = 1,
+ sdrplay_api_AGC_50HZ = 2,
+ sdrplay_api_AGC_5HZ = 3,
+ sdrplay_api_AGC_CTRL_EN = 4
+} sdrplay_api_AgcControlT;
+
+typedef enum
+{
+ sdrplay_api_ADSB_DECIMATION = 0,
+ sdrplay_api_ADSB_NO_DECIMATION_LOWPASS = 1,
+ sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_2MHZ = 2,
+ sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_3MHZ = 3
+} sdrplay_api_AdsbModeT;
+
+// Control parameter structs
+typedef struct
+{
+ unsigned char DCenable; // default: 1
+ unsigned char IQenable; // default: 1
+} sdrplay_api_DcOffsetT;
+
+typedef struct
+{
+ unsigned char enable; // default: 0
+ unsigned char decimationFactor; // default: 1
+ unsigned char wideBandSignal; // default: 0
+} sdrplay_api_DecimationT;
+
+typedef struct
+{
+ sdrplay_api_AgcControlT enable; // default: sdrplay_api_AGC_50HZ
+ int setPoint_dBfs; // default: -60
+ unsigned short attack_ms; // default: 0
+ unsigned short decay_ms; // default: 0
+ unsigned short decay_delay_ms; // default: 0
+ unsigned short decay_threshold_dB; // default: 0
+ int syncUpdate; // default: 0
+} sdrplay_api_AgcT;
+
+typedef struct
+{
+ sdrplay_api_DcOffsetT dcOffset;
+ sdrplay_api_DecimationT decimation;
+ sdrplay_api_AgcT agc;
+ sdrplay_api_AdsbModeT adsbMode; //default: sdrplay_api_ADSB_DECIMATION
+} sdrplay_api_ControlParamsT;
+
+#endif //SDRPLAY_API_CONTROL_H
diff --git a/sdrplay-api/api/v3_07/sdrplay_api_dev.h b/sdrplay-api/api/v3_07/sdrplay_api_dev.h
new file mode 100644
index 000000000..5ac99ae25
--- /dev/null
+++ b/sdrplay-api/api/v3_07/sdrplay_api_dev.h
@@ -0,0 +1,51 @@
+#ifndef SDRPLAY_API_DEV_H
+#define SDRPLAY_API_DEV_H
+
+#include "sdrplay_api_rsp1a.h"
+#include "sdrplay_api_rsp2.h"
+#include "sdrplay_api_rspDuo.h"
+#include "sdrplay_api_rspDx.h"
+
+// Dev parameter enums
+typedef enum
+{
+ sdrplay_api_ISOCH = 0,
+ sdrplay_api_BULK = 1
+} sdrplay_api_TransferModeT;
+
+// Dev parameter structs
+typedef struct
+{
+ double fsHz; // default: 2000000.0
+ unsigned char syncUpdate; // default: 0
+ unsigned char reCal; // default: 0
+} sdrplay_api_FsFreqT;
+
+typedef struct
+{
+ unsigned int sampleNum; // default: 0
+ unsigned int period; // default: 0
+} sdrplay_api_SyncUpdateT;
+
+typedef struct
+{
+ unsigned char resetGainUpdate; // default: 0
+ unsigned char resetRfUpdate; // default: 0
+ unsigned char resetFsUpdate; // default: 0
+} sdrplay_api_ResetFlagsT;
+
+typedef struct
+{
+ double ppm; // default: 0.0
+ sdrplay_api_FsFreqT fsFreq;
+ sdrplay_api_SyncUpdateT syncUpdate;
+ sdrplay_api_ResetFlagsT resetFlags;
+ sdrplay_api_TransferModeT mode; // default: sdrplay_api_ISOCH
+ unsigned int samplesPerPkt; // default: 0 (output param)
+ sdrplay_api_Rsp1aParamsT rsp1aParams;
+ sdrplay_api_Rsp2ParamsT rsp2Params;
+ sdrplay_api_RspDuoParamsT rspDuoParams;
+ sdrplay_api_RspDxParamsT rspDxParams;
+} sdrplay_api_DevParamsT;
+
+#endif //SDRPLAY_API_DEV_H
diff --git a/sdrplay-api/api/v3_07/sdrplay_api_rsp1a.h b/sdrplay-api/api/v3_07/sdrplay_api_rsp1a.h
new file mode 100644
index 000000000..3affbcc3e
--- /dev/null
+++ b/sdrplay-api/api/v3_07/sdrplay_api_rsp1a.h
@@ -0,0 +1,22 @@
+#ifndef SDRPLAY_API_RSP1A_H
+#define SDRPLAY_API_RSP1A_H
+
+#define RSPIA_NUM_LNA_STATES 10
+#define RSPIA_NUM_LNA_STATES_AM 7
+#define RSPIA_NUM_LNA_STATES_LBAND 9
+
+// RSP1A parameter enums
+
+// RSP1A parameter structs
+typedef struct
+{
+ unsigned char rfNotchEnable; // default: 0
+ unsigned char rfDabNotchEnable; // default: 0
+} sdrplay_api_Rsp1aParamsT;
+
+typedef struct
+{
+ unsigned char biasTEnable; // default: 0
+} sdrplay_api_Rsp1aTunerParamsT;
+
+#endif //SDRPLAY_API_RSP1A_H
diff --git a/sdrplay-api/api/v3_07/sdrplay_api_rsp2.h b/sdrplay-api/api/v3_07/sdrplay_api_rsp2.h
new file mode 100644
index 000000000..930d3e956
--- /dev/null
+++ b/sdrplay-api/api/v3_07/sdrplay_api_rsp2.h
@@ -0,0 +1,35 @@
+#ifndef SDRPLAY_API_RSP2_H
+#define SDRPLAY_API_RSP2_H
+
+#define RSPII_NUM_LNA_STATES 9
+#define RSPII_NUM_LNA_STATES_AMPORT 5
+#define RSPII_NUM_LNA_STATES_420MHZ 6
+
+// RSP2 parameter enums
+typedef enum
+{
+ sdrplay_api_Rsp2_ANTENNA_A = 5,
+ sdrplay_api_Rsp2_ANTENNA_B = 6,
+} sdrplay_api_Rsp2_AntennaSelectT;
+
+typedef enum
+{
+ sdrplay_api_Rsp2_AMPORT_1 = 1,
+ sdrplay_api_Rsp2_AMPORT_2 = 0,
+} sdrplay_api_Rsp2_AmPortSelectT;
+
+// RSP2 parameter structs
+typedef struct
+{
+ unsigned char extRefOutputEn; // default: 0
+} sdrplay_api_Rsp2ParamsT;
+
+typedef struct
+{
+ unsigned char biasTEnable; // default: 0
+ sdrplay_api_Rsp2_AmPortSelectT amPortSel; // default: sdrplay_api_Rsp2_AMPORT_2
+ sdrplay_api_Rsp2_AntennaSelectT antennaSel; // default: sdrplay_api_Rsp2_ANTENNA_A
+ unsigned char rfNotchEnable; // default: 0
+} sdrplay_api_Rsp2TunerParamsT;
+
+#endif //SDRPLAY_API_RSP2_H
diff --git a/sdrplay-api/api/v3_07/sdrplay_api_rspDuo.h b/sdrplay-api/api/v3_07/sdrplay_api_rspDuo.h
new file mode 100644
index 000000000..3c4566350
--- /dev/null
+++ b/sdrplay-api/api/v3_07/sdrplay_api_rspDuo.h
@@ -0,0 +1,40 @@
+#ifndef SDRPLAY_API_RSPduo_H
+#define SDRPLAY_API_RSPduo_H
+
+#define RSPDUO_NUM_LNA_STATES 10
+#define RSPDUO_NUM_LNA_STATES_AMPORT 5
+#define RSPDUO_NUM_LNA_STATES_AM 7
+#define RSPDUO_NUM_LNA_STATES_LBAND 9
+
+// RSPduo parameter enums
+typedef enum
+{
+ sdrplay_api_RspDuoMode_Unknown = 0,
+ sdrplay_api_RspDuoMode_Single_Tuner = 1,
+ sdrplay_api_RspDuoMode_Dual_Tuner = 2,
+ sdrplay_api_RspDuoMode_Master = 4,
+ sdrplay_api_RspDuoMode_Slave = 8,
+} sdrplay_api_RspDuoModeT;
+
+typedef enum
+{
+ sdrplay_api_RspDuo_AMPORT_1 = 1,
+ sdrplay_api_RspDuo_AMPORT_2 = 0,
+} sdrplay_api_RspDuo_AmPortSelectT;
+
+// RSPduo parameter structs
+typedef struct
+{
+ int extRefOutputEn; // default: 0
+} sdrplay_api_RspDuoParamsT;
+
+typedef struct
+{
+ unsigned char biasTEnable; // default: 0
+ sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel; // default: sdrplay_api_RspDuo_AMPORT_2
+ unsigned char tuner1AmNotchEnable; // default: 0
+ unsigned char rfNotchEnable; // default: 0
+ unsigned char rfDabNotchEnable; // default: 0
+} sdrplay_api_RspDuoTunerParamsT;
+
+#endif //SDRPLAY_API_RSPduo_H
diff --git a/sdrplay-api/api/v3_07/sdrplay_api_rspDx.h b/sdrplay-api/api/v3_07/sdrplay_api_rspDx.h
new file mode 100644
index 000000000..14cad9dc0
--- /dev/null
+++ b/sdrplay-api/api/v3_07/sdrplay_api_rspDx.h
@@ -0,0 +1,45 @@
+#ifndef SDRPLAY_API_RSPDX_H
+#define SDRPLAY_API_RSPDX_H
+
+#include "sdrplay_api_tuner.h"
+
+#define RSPDX_NUM_LNA_STATES 28 // Number of LNA states in all bands (except where defined differently below)
+#define RSPDX_NUM_LNA_STATES_AMPORT2_0_12 19 // Number of LNA states when using AM Port 2 between 0 and 12MHz
+#define RSPDX_NUM_LNA_STATES_AMPORT2_12_60 20 // Number of LNA states when using AM Port 2 between 12 and 60MHz
+#define RSPDX_NUM_LNA_STATES_VHF_BAND3 27 // Number of LNA states in VHF and Band3
+#define RSPDX_NUM_LNA_STATES_420MHZ 21 // Number of LNA states in 420MHz band
+#define RSPDX_NUM_LNA_STATES_LBAND 19 // Number of LNA states in L-band
+#define RSPDX_NUM_LNA_STATES_DX 26 // Number of LNA states in DX path
+
+// RSPdx parameter enums
+typedef enum
+{
+ sdrplay_api_RspDx_ANTENNA_A = 0,
+ sdrplay_api_RspDx_ANTENNA_B = 1,
+ sdrplay_api_RspDx_ANTENNA_C = 2,
+} sdrplay_api_RspDx_AntennaSelectT;
+
+typedef enum
+{
+ sdrplay_api_RspDx_HDRMODE_BW_0_200 = 0,
+ sdrplay_api_RspDx_HDRMODE_BW_0_500 = 1,
+ sdrplay_api_RspDx_HDRMODE_BW_1_200 = 2,
+ sdrplay_api_RspDx_HDRMODE_BW_1_700 = 3,
+} sdrplay_api_RspDx_HdrModeBwT;
+
+// RSPdx parameter structs
+typedef struct
+{
+ unsigned char hdrEnable; // default: 0
+ unsigned char biasTEnable; // default: 0
+ sdrplay_api_RspDx_AntennaSelectT antennaSel; // default: sdrplay_api_RspDx_ANTENNA_A
+ unsigned char rfNotchEnable; // default: 0
+ unsigned char rfDabNotchEnable; // default: 0
+} sdrplay_api_RspDxParamsT;
+
+typedef struct
+{
+ sdrplay_api_RspDx_HdrModeBwT hdrBw; // default: sdrplay_api_RspDx_HDRMODE_BW_1_700
+} sdrplay_api_RspDxTunerParamsT;
+
+#endif //SDRPLAY_API_RSPDX_H
diff --git a/sdrplay-api/api/v3_07/sdrplay_api_rx_channel.h b/sdrplay-api/api/v3_07/sdrplay_api_rx_channel.h
new file mode 100644
index 000000000..010080402
--- /dev/null
+++ b/sdrplay-api/api/v3_07/sdrplay_api_rx_channel.h
@@ -0,0 +1,21 @@
+#ifndef SDRPLAY_API_RX_CHANNEL_H
+#define SDRPLAY_API_RX_CHANNEL_H
+
+#include "sdrplay_api_tuner.h"
+#include "sdrplay_api_control.h"
+#include "sdrplay_api_rsp1a.h"
+#include "sdrplay_api_rsp2.h"
+#include "sdrplay_api_rspDuo.h"
+#include "sdrplay_api_rspDx.h"
+
+typedef struct
+{
+ sdrplay_api_TunerParamsT tunerParams;
+ sdrplay_api_ControlParamsT ctrlParams;
+ sdrplay_api_Rsp1aTunerParamsT rsp1aTunerParams;
+ sdrplay_api_Rsp2TunerParamsT rsp2TunerParams;
+ sdrplay_api_RspDuoTunerParamsT rspDuoTunerParams;
+ sdrplay_api_RspDxTunerParamsT rspDxTunerParams;
+} sdrplay_api_RxChannelParamsT;
+
+#endif //SDRPLAY_API_RX_CHANNEL_H
diff --git a/sdrplay-api/api/v3_07/sdrplay_api_tuner.h b/sdrplay-api/api/v3_07/sdrplay_api_tuner.h
new file mode 100644
index 000000000..a5c446d61
--- /dev/null
+++ b/sdrplay-api/api/v3_07/sdrplay_api_tuner.h
@@ -0,0 +1,93 @@
+#ifndef SDRPLAY_API_TUNER_H
+#define SDRPLAY_API_TUNER_H
+
+#define MAX_BB_GR (59)
+
+// Tuner parameter enums
+typedef enum
+{
+ sdrplay_api_BW_Undefined = 0,
+ sdrplay_api_BW_0_200 = 200,
+ sdrplay_api_BW_0_300 = 300,
+ sdrplay_api_BW_0_600 = 600,
+ sdrplay_api_BW_1_536 = 1536,
+ sdrplay_api_BW_5_000 = 5000,
+ sdrplay_api_BW_6_000 = 6000,
+ sdrplay_api_BW_7_000 = 7000,
+ sdrplay_api_BW_8_000 = 8000
+} sdrplay_api_Bw_MHzT;
+
+typedef enum
+{
+ sdrplay_api_IF_Undefined = -1,
+ sdrplay_api_IF_Zero = 0,
+ sdrplay_api_IF_0_450 = 450,
+ sdrplay_api_IF_1_620 = 1620,
+ sdrplay_api_IF_2_048 = 2048
+} sdrplay_api_If_kHzT;
+
+typedef enum
+{
+ sdrplay_api_LO_Undefined = 0,
+ sdrplay_api_LO_Auto = 1,
+ sdrplay_api_LO_120MHz = 2,
+ sdrplay_api_LO_144MHz = 3,
+ sdrplay_api_LO_168MHz = 4
+} sdrplay_api_LoModeT;
+
+typedef enum
+{
+ sdrplay_api_EXTENDED_MIN_GR = 0,
+ sdrplay_api_NORMAL_MIN_GR = 20
+} sdrplay_api_MinGainReductionT;
+
+typedef enum
+{
+ sdrplay_api_Tuner_Neither = 0,
+ sdrplay_api_Tuner_A = 1,
+ sdrplay_api_Tuner_B = 2,
+ sdrplay_api_Tuner_Both = 3,
+} sdrplay_api_TunerSelectT;
+
+// Tuner parameter structs
+typedef struct
+{
+ float curr;
+ float max;
+ float min;
+} sdrplay_api_GainValuesT;
+
+typedef struct
+{
+ int gRdB; // default: 50
+ unsigned char LNAstate; // default: 0
+ unsigned char syncUpdate; // default: 0
+ sdrplay_api_MinGainReductionT minGr; // default: sdrplay_api_NORMAL_MIN_GR
+ sdrplay_api_GainValuesT gainVals; // output parameter
+} sdrplay_api_GainT;
+
+typedef struct
+{
+ double rfHz; // default: 200000000.0
+ unsigned char syncUpdate; // default: 0
+} sdrplay_api_RfFreqT;
+
+typedef struct
+{
+ unsigned char dcCal; // default: 3 (Periodic mode)
+ unsigned char speedUp; // default: 0 (No speedup)
+ int trackTime; // default: 1 (=> time in uSec = (72 * 3 * trackTime) / 24e6 = 9uSec)
+ int refreshRateTime; // default: 2048 (=> time in uSec = (72 * 3 * refreshRateTime) / 24e6 = 18432uSec)
+} sdrplay_api_DcOffsetTunerT;
+
+typedef struct
+{
+ sdrplay_api_Bw_MHzT bwType; // default: sdrplay_api_BW_0_200
+ sdrplay_api_If_kHzT ifType; // default: sdrplay_api_IF_Zero
+ sdrplay_api_LoModeT loMode; // default: sdrplay_api_LO_Auto
+ sdrplay_api_GainT gain;
+ sdrplay_api_RfFreqT rfFreq;
+ sdrplay_api_DcOffsetTunerT dcOffsetTuner;
+} sdrplay_api_TunerParamsT;
+
+#endif //SDRPLAY_API_TUNER_H
diff --git a/sdrplay-api/api/v3_11/sdrplay_api.h b/sdrplay-api/api/v3_11/sdrplay_api.h
new file mode 100644
index 000000000..f3400d88a
--- /dev/null
+++ b/sdrplay-api/api/v3_11/sdrplay_api.h
@@ -0,0 +1,230 @@
+#ifndef SDRPLAY_API_H
+#define SDRPLAY_API_H
+
+#include "sdrplay_api_dev.h"
+#include "sdrplay_api_rx_channel.h"
+#include "sdrplay_api_callback.h"
+
+//#if defined(_M_X64) || defined(_M_IX86) || defined(_M_ARM64)
+//#include "windows.h"
+//#elif defined (__GNUC__)
+typedef void *HANDLE;
+//#endif
+
+//#ifndef _SDRPLAY_DLL_QUALIFIER
+//#if !defined(STATIC_LIB) && (defined(_M_X64) || defined(_M_IX86) || defined(_M_ARM64))
+//#define _SDRPLAY_DLL_QUALIFIER __declspec(dllimport)
+//#elif defined(STATIC_LIB) || defined(__GNUC__)
+//#define _SDRPLAY_DLL_QUALIFIER
+//#endif
+//#endif // _SDRPLAY_DLL_QUALIFIER
+
+// Application code should check that it is compiled against the same API version
+// sdrplay_api_ApiVersion() returns the API version
+#define SDRPLAY_API_VERSION (float)(3.11)
+
+// API Constants
+#define SDRPLAY_MAX_DEVICES (16)
+#define SDRPLAY_MAX_TUNERS_PER_DEVICE (2)
+
+#define SDRPLAY_MAX_SER_NO_LEN (64)
+#define SDRPLAY_MAX_ROOT_NM_LEN (32)
+
+#define SDRPLAY_RSP1_ID (1)
+#define SDRPLAY_RSP1A_ID (255)
+#define SDRPLAY_RSP2_ID (2)
+#define SDRPLAY_RSPduo_ID (3)
+#define SDRPLAY_RSPdx_ID (4)
+
+// Enum types
+typedef enum
+{
+ sdrplay_api_Success = 0,
+ sdrplay_api_Fail = 1,
+ sdrplay_api_InvalidParam = 2,
+ sdrplay_api_OutOfRange = 3,
+ sdrplay_api_GainUpdateError = 4,
+ sdrplay_api_RfUpdateError = 5,
+ sdrplay_api_FsUpdateError = 6,
+ sdrplay_api_HwError = 7,
+ sdrplay_api_AliasingError = 8,
+ sdrplay_api_AlreadyInitialised = 9,
+ sdrplay_api_NotInitialised = 10,
+ sdrplay_api_NotEnabled = 11,
+ sdrplay_api_HwVerError = 12,
+ sdrplay_api_OutOfMemError = 13,
+ sdrplay_api_ServiceNotResponding = 14,
+ sdrplay_api_StartPending = 15,
+ sdrplay_api_StopPending = 16,
+ sdrplay_api_InvalidMode = 17,
+ sdrplay_api_FailedVerification1 = 18,
+ sdrplay_api_FailedVerification2 = 19,
+ sdrplay_api_FailedVerification3 = 20,
+ sdrplay_api_FailedVerification4 = 21,
+ sdrplay_api_FailedVerification5 = 22,
+ sdrplay_api_FailedVerification6 = 23,
+ sdrplay_api_InvalidServiceVersion = 24
+} sdrplay_api_ErrT;
+
+typedef enum
+{
+ sdrplay_api_Update_None = 0x00000000,
+
+ // Reasons for master only mode
+ sdrplay_api_Update_Dev_Fs = 0x00000001,
+ sdrplay_api_Update_Dev_Ppm = 0x00000002,
+ sdrplay_api_Update_Dev_SyncUpdate = 0x00000004,
+ sdrplay_api_Update_Dev_ResetFlags = 0x00000008,
+
+ sdrplay_api_Update_Rsp1a_BiasTControl = 0x00000010,
+ sdrplay_api_Update_Rsp1a_RfNotchControl = 0x00000020,
+ sdrplay_api_Update_Rsp1a_RfDabNotchControl = 0x00000040,
+
+ sdrplay_api_Update_Rsp2_BiasTControl = 0x00000080,
+ sdrplay_api_Update_Rsp2_AmPortSelect = 0x00000100,
+ sdrplay_api_Update_Rsp2_AntennaControl = 0x00000200,
+ sdrplay_api_Update_Rsp2_RfNotchControl = 0x00000400,
+ sdrplay_api_Update_Rsp2_ExtRefControl = 0x00000800,
+
+ sdrplay_api_Update_RspDuo_ExtRefControl = 0x00001000,
+
+ sdrplay_api_Update_Master_Spare_1 = 0x00002000,
+ sdrplay_api_Update_Master_Spare_2 = 0x00004000,
+
+ // Reasons for master and slave mode
+ // Note: sdrplay_api_Update_Tuner_Gr MUST be the first value defined in this section!
+ sdrplay_api_Update_Tuner_Gr = 0x00008000,
+ sdrplay_api_Update_Tuner_GrLimits = 0x00010000,
+ sdrplay_api_Update_Tuner_Frf = 0x00020000,
+ sdrplay_api_Update_Tuner_BwType = 0x00040000,
+ sdrplay_api_Update_Tuner_IfType = 0x00080000,
+ sdrplay_api_Update_Tuner_DcOffset = 0x00100000,
+ sdrplay_api_Update_Tuner_LoMode = 0x00200000,
+
+ sdrplay_api_Update_Ctrl_DCoffsetIQimbalance = 0x00400000,
+ sdrplay_api_Update_Ctrl_Decimation = 0x00800000,
+ sdrplay_api_Update_Ctrl_Agc = 0x01000000,
+ sdrplay_api_Update_Ctrl_AdsbMode = 0x02000000,
+ sdrplay_api_Update_Ctrl_OverloadMsgAck = 0x04000000,
+
+ sdrplay_api_Update_RspDuo_BiasTControl = 0x08000000,
+ sdrplay_api_Update_RspDuo_AmPortSelect = 0x10000000,
+ sdrplay_api_Update_RspDuo_Tuner1AmNotchControl = 0x20000000,
+ sdrplay_api_Update_RspDuo_RfNotchControl = 0x40000000,
+ sdrplay_api_Update_RspDuo_RfDabNotchControl = 0x80000000,
+} sdrplay_api_ReasonForUpdateT;
+
+typedef enum
+{
+ sdrplay_api_Update_Ext1_None = 0x00000000,
+
+ // Reasons for master only mode
+ sdrplay_api_Update_RspDx_HdrEnable = 0x00000001,
+ sdrplay_api_Update_RspDx_BiasTControl = 0x00000002,
+ sdrplay_api_Update_RspDx_AntennaControl = 0x00000004,
+ sdrplay_api_Update_RspDx_RfNotchControl = 0x00000008,
+ sdrplay_api_Update_RspDx_RfDabNotchControl = 0x00000010,
+ sdrplay_api_Update_RspDx_HdrBw = 0x00000020,
+
+ // Reasons for master and slave mode
+} sdrplay_api_ReasonForUpdateExtension1T;
+
+typedef enum
+{
+ sdrplay_api_DbgLvl_Disable = 0,
+ sdrplay_api_DbgLvl_Verbose = 1,
+ sdrplay_api_DbgLvl_Warning = 2,
+ sdrplay_api_DbgLvl_Error = 3,
+ sdrplay_api_DbgLvl_Message = 4,
+} sdrplay_api_DbgLvl_t;
+
+// Device structure
+typedef struct
+{
+ char SerNo[SDRPLAY_MAX_SER_NO_LEN];
+ unsigned char hwVer;
+ sdrplay_api_TunerSelectT tuner;
+ sdrplay_api_RspDuoModeT rspDuoMode;
+ unsigned char valid;
+ double rspDuoSampleFreq;
+ HANDLE dev;
+} sdrplay_api_DeviceT;
+
+// Device parameter structure
+typedef struct
+{
+ sdrplay_api_DevParamsT *devParams;
+ sdrplay_api_RxChannelParamsT *rxChannelA;
+ sdrplay_api_RxChannelParamsT *rxChannelB;
+} sdrplay_api_DeviceParamsT;
+
+// Extended error message structure
+typedef struct
+{
+ char file[256];
+ char function[256];
+ int line;
+ char message[1024];
+} sdrplay_api_ErrorInfoT;
+
+// Comman API function types
+typedef sdrplay_api_ErrT (*sdrplay_api_Open_t)(void);
+typedef sdrplay_api_ErrT (*sdrplay_api_Close_t)(void);
+typedef sdrplay_api_ErrT (*sdrplay_api_ApiVersion_t)(float *apiVer);
+typedef sdrplay_api_ErrT (*sdrplay_api_LockDeviceApi_t)(void);
+typedef sdrplay_api_ErrT (*sdrplay_api_UnlockDeviceApi_t)(void);
+typedef sdrplay_api_ErrT (*sdrplay_api_GetDevices_t)(sdrplay_api_DeviceT *devices, unsigned int *numDevs, unsigned int maxDevs);
+typedef sdrplay_api_ErrT (*sdrplay_api_SelectDevice_t)(sdrplay_api_DeviceT *device);
+typedef sdrplay_api_ErrT (*sdrplay_api_ReleaseDevice_t)(sdrplay_api_DeviceT *device);
+typedef const char* (*sdrplay_api_GetErrorString_t)(sdrplay_api_ErrT err);
+typedef sdrplay_api_ErrorInfoT* (*sdrplay_api_GetLastError_t)(sdrplay_api_DeviceT *device);
+typedef sdrplay_api_ErrT (*sdrplay_api_DisableHeartbeat_t)(void);
+
+// Device API function types
+typedef sdrplay_api_ErrT (*sdrplay_api_DebugEnable_t)(HANDLE dev, sdrplay_api_DbgLvl_t dbgLvl);
+typedef sdrplay_api_ErrT (*sdrplay_api_GetDeviceParams_t)(HANDLE dev, sdrplay_api_DeviceParamsT **deviceParams);
+typedef sdrplay_api_ErrT (*sdrplay_api_Init_t)(HANDLE dev, sdrplay_api_CallbackFnsT *callbackFns, void *cbContext);
+typedef sdrplay_api_ErrT (*sdrplay_api_Uninit_t)(HANDLE dev);
+typedef sdrplay_api_ErrT (*sdrplay_api_Update_t)(HANDLE dev, sdrplay_api_TunerSelectT tuner, sdrplay_api_ReasonForUpdateT reasonForUpdate, sdrplay_api_ReasonForUpdateExtension1T reasonForUpdateExt1);
+typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoActiveTuner_t)(HANDLE dev, sdrplay_api_TunerSelectT *tuner, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
+typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t)(double *currentSampleRate, double newSampleRate);
+typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoMode_t)(sdrplay_api_DeviceT *currDevice, sdrplay_api_DeviceParamsT **deviceParams,
+ sdrplay_api_RspDuoModeT rspDuoMode, double sampleRate, sdrplay_api_TunerSelectT tuner,
+ sdrplay_api_Bw_MHzT bwType, sdrplay_api_If_kHzT ifType, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
+
+// API function definitions
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ // Comman API function definitions
+ sdrplay_api_ErrT sdrplay_api_Open(void);
+ sdrplay_api_ErrT sdrplay_api_Close(void);
+ sdrplay_api_ErrT sdrplay_api_ApiVersion(float *apiVer);
+ sdrplay_api_ErrT sdrplay_api_LockDeviceApi(void);
+ sdrplay_api_ErrT sdrplay_api_UnlockDeviceApi(void);
+ sdrplay_api_ErrT sdrplay_api_GetDevices(sdrplay_api_DeviceT *devices, unsigned int *numDevs, unsigned int maxDevs);
+ sdrplay_api_ErrT sdrplay_api_SelectDevice(sdrplay_api_DeviceT *device);
+ sdrplay_api_ErrT sdrplay_api_ReleaseDevice(sdrplay_api_DeviceT *device);
+ const char* sdrplay_api_GetErrorString(sdrplay_api_ErrT err);
+ sdrplay_api_ErrorInfoT* sdrplay_api_GetLastError(sdrplay_api_DeviceT *device);
+ sdrplay_api_ErrT sdrplay_api_DisableHeartbeat(void); // Must be called before sdrplay_api_SelectDevice()
+
+ // Device API function definitions
+ sdrplay_api_ErrT sdrplay_api_DebugEnable(HANDLE dev, sdrplay_api_DbgLvl_t enable);
+ sdrplay_api_ErrT sdrplay_api_GetDeviceParams(HANDLE dev, sdrplay_api_DeviceParamsT **deviceParams);
+ sdrplay_api_ErrT sdrplay_api_Init(HANDLE dev, sdrplay_api_CallbackFnsT *callbackFns, void *cbContext);
+ sdrplay_api_ErrT sdrplay_api_Uninit(HANDLE dev);
+ sdrplay_api_ErrT sdrplay_api_Update(HANDLE dev, sdrplay_api_TunerSelectT tuner, sdrplay_api_ReasonForUpdateT reasonForUpdate, sdrplay_api_ReasonForUpdateExtension1T reasonForUpdateExt1);
+ sdrplay_api_ErrT sdrplay_api_SwapRspDuoActiveTuner(HANDLE dev, sdrplay_api_TunerSelectT *currentTuner, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
+ sdrplay_api_ErrT sdrplay_api_SwapRspDuoDualTunerModeSampleRate(HANDLE dev, double *currentSampleRate, double newSampleRate);
+ sdrplay_api_ErrT sdrplay_api_SwapRspDuoMode(sdrplay_api_DeviceT *currDevice, sdrplay_api_DeviceParamsT **deviceParams,
+ sdrplay_api_RspDuoModeT rspDuoMode, double sampleRate, sdrplay_api_TunerSelectT tuner,
+ sdrplay_api_Bw_MHzT bwType, sdrplay_api_If_kHzT ifType, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //SDRPLAY_API_H
diff --git a/sdrplay-api/api/v3_11/sdrplay_api_callback.h b/sdrplay-api/api/v3_11/sdrplay_api_callback.h
new file mode 100644
index 000000000..0da80502a
--- /dev/null
+++ b/sdrplay-api/api/v3_11/sdrplay_api_callback.h
@@ -0,0 +1,79 @@
+#ifndef SDRPLAY_API_CALLBACK_H
+#define SDRPLAY_API_CALLBACK_H
+
+// Event callback enums
+typedef enum
+{
+ sdrplay_api_Overload_Detected = 0,
+ sdrplay_api_Overload_Corrected = 1,
+} sdrplay_api_PowerOverloadCbEventIdT;
+
+typedef enum
+{
+ sdrplay_api_MasterInitialised = 0,
+ sdrplay_api_SlaveAttached = 1,
+ sdrplay_api_SlaveDetached = 2,
+ sdrplay_api_SlaveInitialised = 3,
+ sdrplay_api_SlaveUninitialised = 4,
+ sdrplay_api_MasterDllDisappeared = 5,
+ sdrplay_api_SlaveDllDisappeared = 6,
+} sdrplay_api_RspDuoModeCbEventIdT;
+
+typedef enum
+{
+ sdrplay_api_GainChange = 0,
+ sdrplay_api_PowerOverloadChange = 1,
+ sdrplay_api_DeviceRemoved = 2,
+ sdrplay_api_RspDuoModeChange = 3,
+ sdrplay_api_DeviceFailure = 4,
+} sdrplay_api_EventT;
+
+// Event callback parameter structs
+typedef struct
+{
+ unsigned int gRdB;
+ unsigned int lnaGRdB;
+ double currGain;
+} sdrplay_api_GainCbParamT;
+
+typedef struct
+{
+ sdrplay_api_PowerOverloadCbEventIdT powerOverloadChangeType;
+} sdrplay_api_PowerOverloadCbParamT;
+
+typedef struct
+{
+ sdrplay_api_RspDuoModeCbEventIdT modeChangeType;
+} sdrplay_api_RspDuoModeCbParamT;
+
+// Event parameters overlay
+typedef union
+{
+ sdrplay_api_GainCbParamT gainParams;
+ sdrplay_api_PowerOverloadCbParamT powerOverloadParams;
+ sdrplay_api_RspDuoModeCbParamT rspDuoModeParams;
+} sdrplay_api_EventParamsT;
+
+// Stream callback parameter structs
+typedef struct
+{
+ unsigned int firstSampleNum;
+ int grChanged;
+ int rfChanged;
+ int fsChanged;
+ unsigned int numSamples;
+} sdrplay_api_StreamCbParamsT;
+
+// Callback function prototypes
+typedef void (*sdrplay_api_StreamCallback_t)(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext);
+typedef void (*sdrplay_api_EventCallback_t)(sdrplay_api_EventT eventId, sdrplay_api_TunerSelectT tuner, sdrplay_api_EventParamsT *params, void *cbContext);
+
+// Callback function struct
+typedef struct
+{
+ sdrplay_api_StreamCallback_t StreamACbFn;
+ sdrplay_api_StreamCallback_t StreamBCbFn;
+ sdrplay_api_EventCallback_t EventCbFn;
+} sdrplay_api_CallbackFnsT;
+
+#endif //SDRPLAY_API_CALLBACK_H
diff --git a/sdrplay-api/api/v3_11/sdrplay_api_control.h b/sdrplay-api/api/v3_11/sdrplay_api_control.h
new file mode 100644
index 000000000..5a52a1046
--- /dev/null
+++ b/sdrplay-api/api/v3_11/sdrplay_api_control.h
@@ -0,0 +1,55 @@
+#ifndef SDRPLAY_API_CONTROL_H
+#define SDRPLAY_API_CONTROL_H
+
+// Control parameter enums
+typedef enum
+{
+ sdrplay_api_AGC_DISABLE = 0,
+ sdrplay_api_AGC_100HZ = 1,
+ sdrplay_api_AGC_50HZ = 2,
+ sdrplay_api_AGC_5HZ = 3,
+ sdrplay_api_AGC_CTRL_EN = 4
+} sdrplay_api_AgcControlT;
+
+typedef enum
+{
+ sdrplay_api_ADSB_DECIMATION = 0,
+ sdrplay_api_ADSB_NO_DECIMATION_LOWPASS = 1,
+ sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_2MHZ = 2,
+ sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_3MHZ = 3
+} sdrplay_api_AdsbModeT;
+
+// Control parameter structs
+typedef struct
+{
+ unsigned char DCenable; // default: 1
+ unsigned char IQenable; // default: 1
+} sdrplay_api_DcOffsetT;
+
+typedef struct
+{
+ unsigned char enable; // default: 0
+ unsigned char decimationFactor; // default: 1
+ unsigned char wideBandSignal; // default: 0
+} sdrplay_api_DecimationT;
+
+typedef struct
+{
+ sdrplay_api_AgcControlT enable; // default: sdrplay_api_AGC_50HZ
+ int setPoint_dBfs; // default: -60
+ unsigned short attack_ms; // default: 0
+ unsigned short decay_ms; // default: 0
+ unsigned short decay_delay_ms; // default: 0
+ unsigned short decay_threshold_dB; // default: 0
+ int syncUpdate; // default: 0
+} sdrplay_api_AgcT;
+
+typedef struct
+{
+ sdrplay_api_DcOffsetT dcOffset;
+ sdrplay_api_DecimationT decimation;
+ sdrplay_api_AgcT agc;
+ sdrplay_api_AdsbModeT adsbMode; //default: sdrplay_api_ADSB_DECIMATION
+} sdrplay_api_ControlParamsT;
+
+#endif //SDRPLAY_API_CONTROL_H
diff --git a/sdrplay-api/api/v3_11/sdrplay_api_dev.h b/sdrplay-api/api/v3_11/sdrplay_api_dev.h
new file mode 100644
index 000000000..5ac99ae25
--- /dev/null
+++ b/sdrplay-api/api/v3_11/sdrplay_api_dev.h
@@ -0,0 +1,51 @@
+#ifndef SDRPLAY_API_DEV_H
+#define SDRPLAY_API_DEV_H
+
+#include "sdrplay_api_rsp1a.h"
+#include "sdrplay_api_rsp2.h"
+#include "sdrplay_api_rspDuo.h"
+#include "sdrplay_api_rspDx.h"
+
+// Dev parameter enums
+typedef enum
+{
+ sdrplay_api_ISOCH = 0,
+ sdrplay_api_BULK = 1
+} sdrplay_api_TransferModeT;
+
+// Dev parameter structs
+typedef struct
+{
+ double fsHz; // default: 2000000.0
+ unsigned char syncUpdate; // default: 0
+ unsigned char reCal; // default: 0
+} sdrplay_api_FsFreqT;
+
+typedef struct
+{
+ unsigned int sampleNum; // default: 0
+ unsigned int period; // default: 0
+} sdrplay_api_SyncUpdateT;
+
+typedef struct
+{
+ unsigned char resetGainUpdate; // default: 0
+ unsigned char resetRfUpdate; // default: 0
+ unsigned char resetFsUpdate; // default: 0
+} sdrplay_api_ResetFlagsT;
+
+typedef struct
+{
+ double ppm; // default: 0.0
+ sdrplay_api_FsFreqT fsFreq;
+ sdrplay_api_SyncUpdateT syncUpdate;
+ sdrplay_api_ResetFlagsT resetFlags;
+ sdrplay_api_TransferModeT mode; // default: sdrplay_api_ISOCH
+ unsigned int samplesPerPkt; // default: 0 (output param)
+ sdrplay_api_Rsp1aParamsT rsp1aParams;
+ sdrplay_api_Rsp2ParamsT rsp2Params;
+ sdrplay_api_RspDuoParamsT rspDuoParams;
+ sdrplay_api_RspDxParamsT rspDxParams;
+} sdrplay_api_DevParamsT;
+
+#endif //SDRPLAY_API_DEV_H
diff --git a/sdrplay-api/api/v3_11/sdrplay_api_rsp1a.h b/sdrplay-api/api/v3_11/sdrplay_api_rsp1a.h
new file mode 100644
index 000000000..3affbcc3e
--- /dev/null
+++ b/sdrplay-api/api/v3_11/sdrplay_api_rsp1a.h
@@ -0,0 +1,22 @@
+#ifndef SDRPLAY_API_RSP1A_H
+#define SDRPLAY_API_RSP1A_H
+
+#define RSPIA_NUM_LNA_STATES 10
+#define RSPIA_NUM_LNA_STATES_AM 7
+#define RSPIA_NUM_LNA_STATES_LBAND 9
+
+// RSP1A parameter enums
+
+// RSP1A parameter structs
+typedef struct
+{
+ unsigned char rfNotchEnable; // default: 0
+ unsigned char rfDabNotchEnable; // default: 0
+} sdrplay_api_Rsp1aParamsT;
+
+typedef struct
+{
+ unsigned char biasTEnable; // default: 0
+} sdrplay_api_Rsp1aTunerParamsT;
+
+#endif //SDRPLAY_API_RSP1A_H
diff --git a/sdrplay-api/api/v3_11/sdrplay_api_rsp2.h b/sdrplay-api/api/v3_11/sdrplay_api_rsp2.h
new file mode 100644
index 000000000..930d3e956
--- /dev/null
+++ b/sdrplay-api/api/v3_11/sdrplay_api_rsp2.h
@@ -0,0 +1,35 @@
+#ifndef SDRPLAY_API_RSP2_H
+#define SDRPLAY_API_RSP2_H
+
+#define RSPII_NUM_LNA_STATES 9
+#define RSPII_NUM_LNA_STATES_AMPORT 5
+#define RSPII_NUM_LNA_STATES_420MHZ 6
+
+// RSP2 parameter enums
+typedef enum
+{
+ sdrplay_api_Rsp2_ANTENNA_A = 5,
+ sdrplay_api_Rsp2_ANTENNA_B = 6,
+} sdrplay_api_Rsp2_AntennaSelectT;
+
+typedef enum
+{
+ sdrplay_api_Rsp2_AMPORT_1 = 1,
+ sdrplay_api_Rsp2_AMPORT_2 = 0,
+} sdrplay_api_Rsp2_AmPortSelectT;
+
+// RSP2 parameter structs
+typedef struct
+{
+ unsigned char extRefOutputEn; // default: 0
+} sdrplay_api_Rsp2ParamsT;
+
+typedef struct
+{
+ unsigned char biasTEnable; // default: 0
+ sdrplay_api_Rsp2_AmPortSelectT amPortSel; // default: sdrplay_api_Rsp2_AMPORT_2
+ sdrplay_api_Rsp2_AntennaSelectT antennaSel; // default: sdrplay_api_Rsp2_ANTENNA_A
+ unsigned char rfNotchEnable; // default: 0
+} sdrplay_api_Rsp2TunerParamsT;
+
+#endif //SDRPLAY_API_RSP2_H
diff --git a/sdrplay-api/api/v3_11/sdrplay_api_rspDuo.h b/sdrplay-api/api/v3_11/sdrplay_api_rspDuo.h
new file mode 100644
index 000000000..3c4566350
--- /dev/null
+++ b/sdrplay-api/api/v3_11/sdrplay_api_rspDuo.h
@@ -0,0 +1,40 @@
+#ifndef SDRPLAY_API_RSPduo_H
+#define SDRPLAY_API_RSPduo_H
+
+#define RSPDUO_NUM_LNA_STATES 10
+#define RSPDUO_NUM_LNA_STATES_AMPORT 5
+#define RSPDUO_NUM_LNA_STATES_AM 7
+#define RSPDUO_NUM_LNA_STATES_LBAND 9
+
+// RSPduo parameter enums
+typedef enum
+{
+ sdrplay_api_RspDuoMode_Unknown = 0,
+ sdrplay_api_RspDuoMode_Single_Tuner = 1,
+ sdrplay_api_RspDuoMode_Dual_Tuner = 2,
+ sdrplay_api_RspDuoMode_Master = 4,
+ sdrplay_api_RspDuoMode_Slave = 8,
+} sdrplay_api_RspDuoModeT;
+
+typedef enum
+{
+ sdrplay_api_RspDuo_AMPORT_1 = 1,
+ sdrplay_api_RspDuo_AMPORT_2 = 0,
+} sdrplay_api_RspDuo_AmPortSelectT;
+
+// RSPduo parameter structs
+typedef struct
+{
+ int extRefOutputEn; // default: 0
+} sdrplay_api_RspDuoParamsT;
+
+typedef struct
+{
+ unsigned char biasTEnable; // default: 0
+ sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel; // default: sdrplay_api_RspDuo_AMPORT_2
+ unsigned char tuner1AmNotchEnable; // default: 0
+ unsigned char rfNotchEnable; // default: 0
+ unsigned char rfDabNotchEnable; // default: 0
+} sdrplay_api_RspDuoTunerParamsT;
+
+#endif //SDRPLAY_API_RSPduo_H
diff --git a/sdrplay-api/api/v3_11/sdrplay_api_rspDx.h b/sdrplay-api/api/v3_11/sdrplay_api_rspDx.h
new file mode 100644
index 000000000..0528de96c
--- /dev/null
+++ b/sdrplay-api/api/v3_11/sdrplay_api_rspDx.h
@@ -0,0 +1,46 @@
+#ifndef SDRPLAY_API_RSPDX_H
+#define SDRPLAY_API_RSPDX_H
+
+#include "sdrplay_api_tuner.h"
+
+#define RSPDX_NUM_LNA_STATES 28 // Number of LNA states in all bands (except where defined differently below)
+#define RSPDX_NUM_LNA_STATES_AMPORT2_0_12 19 // Number of LNA states when using AM Port 2 between 0 and 12MHz
+#define RSPDX_NUM_LNA_STATES_AMPORT2_12_50 20 // Number of LNA states when using AM Port 2 between 12 and 50MHz
+#define RSPDX_NUM_LNA_STATES_AMPORT2_50_60 25 // Number of LNA states when using AM Port 2 between 50 and 60MHz
+#define RSPDX_NUM_LNA_STATES_VHF_BAND3 27 // Number of LNA states in VHF and Band3
+#define RSPDX_NUM_LNA_STATES_420MHZ 21 // Number of LNA states in 420MHz band
+#define RSPDX_NUM_LNA_STATES_LBAND 19 // Number of LNA states in L-band
+#define RSPDX_NUM_LNA_STATES_DX 22 // Number of LNA states in DX path
+
+// RSPdx parameter enums
+typedef enum
+{
+ sdrplay_api_RspDx_ANTENNA_A = 0,
+ sdrplay_api_RspDx_ANTENNA_B = 1,
+ sdrplay_api_RspDx_ANTENNA_C = 2,
+} sdrplay_api_RspDx_AntennaSelectT;
+
+typedef enum
+{
+ sdrplay_api_RspDx_HDRMODE_BW_0_200 = 0,
+ sdrplay_api_RspDx_HDRMODE_BW_0_500 = 1,
+ sdrplay_api_RspDx_HDRMODE_BW_1_200 = 2,
+ sdrplay_api_RspDx_HDRMODE_BW_1_700 = 3,
+} sdrplay_api_RspDx_HdrModeBwT;
+
+// RSPdx parameter structs
+typedef struct
+{
+ unsigned char hdrEnable; // default: 0
+ unsigned char biasTEnable; // default: 0
+ sdrplay_api_RspDx_AntennaSelectT antennaSel; // default: sdrplay_api_RspDx_ANTENNA_A
+ unsigned char rfNotchEnable; // default: 0
+ unsigned char rfDabNotchEnable; // default: 0
+} sdrplay_api_RspDxParamsT;
+
+typedef struct
+{
+ sdrplay_api_RspDx_HdrModeBwT hdrBw; // default: sdrplay_api_RspDx_HDRMODE_BW_1_700
+} sdrplay_api_RspDxTunerParamsT;
+
+#endif //SDRPLAY_API_RSPDX_H
diff --git a/sdrplay-api/api/v3_11/sdrplay_api_rx_channel.h b/sdrplay-api/api/v3_11/sdrplay_api_rx_channel.h
new file mode 100644
index 000000000..010080402
--- /dev/null
+++ b/sdrplay-api/api/v3_11/sdrplay_api_rx_channel.h
@@ -0,0 +1,21 @@
+#ifndef SDRPLAY_API_RX_CHANNEL_H
+#define SDRPLAY_API_RX_CHANNEL_H
+
+#include "sdrplay_api_tuner.h"
+#include "sdrplay_api_control.h"
+#include "sdrplay_api_rsp1a.h"
+#include "sdrplay_api_rsp2.h"
+#include "sdrplay_api_rspDuo.h"
+#include "sdrplay_api_rspDx.h"
+
+typedef struct
+{
+ sdrplay_api_TunerParamsT tunerParams;
+ sdrplay_api_ControlParamsT ctrlParams;
+ sdrplay_api_Rsp1aTunerParamsT rsp1aTunerParams;
+ sdrplay_api_Rsp2TunerParamsT rsp2TunerParams;
+ sdrplay_api_RspDuoTunerParamsT rspDuoTunerParams;
+ sdrplay_api_RspDxTunerParamsT rspDxTunerParams;
+} sdrplay_api_RxChannelParamsT;
+
+#endif //SDRPLAY_API_RX_CHANNEL_H
diff --git a/sdrplay-api/api/v3_11/sdrplay_api_tuner.h b/sdrplay-api/api/v3_11/sdrplay_api_tuner.h
new file mode 100644
index 000000000..a5c446d61
--- /dev/null
+++ b/sdrplay-api/api/v3_11/sdrplay_api_tuner.h
@@ -0,0 +1,93 @@
+#ifndef SDRPLAY_API_TUNER_H
+#define SDRPLAY_API_TUNER_H
+
+#define MAX_BB_GR (59)
+
+// Tuner parameter enums
+typedef enum
+{
+ sdrplay_api_BW_Undefined = 0,
+ sdrplay_api_BW_0_200 = 200,
+ sdrplay_api_BW_0_300 = 300,
+ sdrplay_api_BW_0_600 = 600,
+ sdrplay_api_BW_1_536 = 1536,
+ sdrplay_api_BW_5_000 = 5000,
+ sdrplay_api_BW_6_000 = 6000,
+ sdrplay_api_BW_7_000 = 7000,
+ sdrplay_api_BW_8_000 = 8000
+} sdrplay_api_Bw_MHzT;
+
+typedef enum
+{
+ sdrplay_api_IF_Undefined = -1,
+ sdrplay_api_IF_Zero = 0,
+ sdrplay_api_IF_0_450 = 450,
+ sdrplay_api_IF_1_620 = 1620,
+ sdrplay_api_IF_2_048 = 2048
+} sdrplay_api_If_kHzT;
+
+typedef enum
+{
+ sdrplay_api_LO_Undefined = 0,
+ sdrplay_api_LO_Auto = 1,
+ sdrplay_api_LO_120MHz = 2,
+ sdrplay_api_LO_144MHz = 3,
+ sdrplay_api_LO_168MHz = 4
+} sdrplay_api_LoModeT;
+
+typedef enum
+{
+ sdrplay_api_EXTENDED_MIN_GR = 0,
+ sdrplay_api_NORMAL_MIN_GR = 20
+} sdrplay_api_MinGainReductionT;
+
+typedef enum
+{
+ sdrplay_api_Tuner_Neither = 0,
+ sdrplay_api_Tuner_A = 1,
+ sdrplay_api_Tuner_B = 2,
+ sdrplay_api_Tuner_Both = 3,
+} sdrplay_api_TunerSelectT;
+
+// Tuner parameter structs
+typedef struct
+{
+ float curr;
+ float max;
+ float min;
+} sdrplay_api_GainValuesT;
+
+typedef struct
+{
+ int gRdB; // default: 50
+ unsigned char LNAstate; // default: 0
+ unsigned char syncUpdate; // default: 0
+ sdrplay_api_MinGainReductionT minGr; // default: sdrplay_api_NORMAL_MIN_GR
+ sdrplay_api_GainValuesT gainVals; // output parameter
+} sdrplay_api_GainT;
+
+typedef struct
+{
+ double rfHz; // default: 200000000.0
+ unsigned char syncUpdate; // default: 0
+} sdrplay_api_RfFreqT;
+
+typedef struct
+{
+ unsigned char dcCal; // default: 3 (Periodic mode)
+ unsigned char speedUp; // default: 0 (No speedup)
+ int trackTime; // default: 1 (=> time in uSec = (72 * 3 * trackTime) / 24e6 = 9uSec)
+ int refreshRateTime; // default: 2048 (=> time in uSec = (72 * 3 * refreshRateTime) / 24e6 = 18432uSec)
+} sdrplay_api_DcOffsetTunerT;
+
+typedef struct
+{
+ sdrplay_api_Bw_MHzT bwType; // default: sdrplay_api_BW_0_200
+ sdrplay_api_If_kHzT ifType; // default: sdrplay_api_IF_Zero
+ sdrplay_api_LoModeT loMode; // default: sdrplay_api_LO_Auto
+ sdrplay_api_GainT gain;
+ sdrplay_api_RfFreqT rfFreq;
+ sdrplay_api_DcOffsetTunerT dcOffsetTuner;
+} sdrplay_api_TunerParamsT;
+
+#endif //SDRPLAY_API_TUNER_H
diff --git a/sdrplay-api/build.gradle b/sdrplay-api/build.gradle
new file mode 100644
index 000000000..8a542e169
--- /dev/null
+++ b/sdrplay-api/build.gradle
@@ -0,0 +1,47 @@
+plugins {
+ id 'java'
+ id 'maven-publish'
+}
+
+group 'com.github.DSheirer'
+version '3.11.0.0'
+
+repositories {
+ mavenCentral()
+ maven { url "https://jitpack.io" }
+}
+
+//Java 19 is required for this version of the Project Panama preview/incubator feature
+java {
+ toolchain {
+ languageVersion = JavaLanguageVersion.of(19)
+ }
+}
+
+dependencies {
+ implementation 'org.slf4j:slf4j-api:1.7.32'
+ testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
+ testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
+}
+
+/**
+ * This is needed for the JDK19 panama until it moves out of preview
+ */
+tasks.withType(JavaCompile) {
+ options.compilerArgs.add("--enable-preview") //Panama Foreign Function/Memory is preview in JDK 19
+}
+
+
+test {
+ //Exclude all tests by default
+ exclude '**/*'
+ useJUnitPlatform()
+}
+
+publishing {
+ publications {
+ mavenJava(MavenPublication) {
+ from components.java
+ }
+ }
+}
\ No newline at end of file
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/Constants$root.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/Constants$root.java
new file mode 100644
index 000000000..898f4a81c
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/Constants$root.java
@@ -0,0 +1,34 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import static java.lang.foreign.ValueLayout.ADDRESS;
+import static java.lang.foreign.ValueLayout.JAVA_BOOLEAN;
+import static java.lang.foreign.ValueLayout.JAVA_BYTE;
+import static java.lang.foreign.ValueLayout.JAVA_DOUBLE;
+import static java.lang.foreign.ValueLayout.JAVA_FLOAT;
+import static java.lang.foreign.ValueLayout.JAVA_INT;
+import static java.lang.foreign.ValueLayout.JAVA_LONG;
+import static java.lang.foreign.ValueLayout.JAVA_SHORT;
+import static java.lang.foreign.ValueLayout.OfAddress;
+import static java.lang.foreign.ValueLayout.OfBoolean;
+import static java.lang.foreign.ValueLayout.OfByte;
+import static java.lang.foreign.ValueLayout.OfDouble;
+import static java.lang.foreign.ValueLayout.OfFloat;
+import static java.lang.foreign.ValueLayout.OfInt;
+import static java.lang.foreign.ValueLayout.OfLong;
+import static java.lang.foreign.ValueLayout.OfShort;
+public class Constants$root {
+
+ static final OfBoolean C_BOOL$LAYOUT = JAVA_BOOLEAN;
+ static final OfByte C_CHAR$LAYOUT = JAVA_BYTE;
+ static final OfShort C_SHORT$LAYOUT = JAVA_SHORT.withBitAlignment(16);
+ static final OfInt C_INT$LAYOUT = JAVA_INT.withBitAlignment(32);
+ static final OfInt C_LONG$LAYOUT = JAVA_INT.withBitAlignment(32);
+ static final OfLong C_LONG_LONG$LAYOUT = JAVA_LONG.withBitAlignment(64);
+ static final OfFloat C_FLOAT$LAYOUT = JAVA_FLOAT.withBitAlignment(32);
+ static final OfDouble C_DOUBLE$LAYOUT = JAVA_DOUBLE.withBitAlignment(64);
+ static final OfAddress C_POINTER$LAYOUT = ADDRESS.withBitAlignment(64);
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/RuntimeHelper.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/RuntimeHelper.java
new file mode 100644
index 000000000..28385ba41
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/RuntimeHelper.java
@@ -0,0 +1,228 @@
+package com.github.dsheirer.sdrplay.api.v3_07;
+// Generated by jextract
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.Linker;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.foreign.SymbolLookup;
+import java.lang.foreign.ValueLayout;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+import static java.lang.foreign.ValueLayout.ADDRESS;
+import static java.lang.foreign.ValueLayout.JAVA_DOUBLE;
+import static java.lang.foreign.ValueLayout.JAVA_LONG;
+
+final class RuntimeHelper {
+
+ private RuntimeHelper() {}
+ private final static Linker LINKER = Linker.nativeLinker();
+ private final static ClassLoader LOADER = RuntimeHelper.class.getClassLoader();
+ private final static MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup();
+ private final static SymbolLookup SYMBOL_LOOKUP;
+
+ final static SegmentAllocator CONSTANT_ALLOCATOR =
+ (size, align) -> MemorySegment.allocateNative(size, align, MemorySession.openImplicit());
+
+ static {
+// System.loadLibrary("libsdrplay_api");
+ SymbolLookup loaderLookup = SymbolLookup.loaderLookup();
+ SYMBOL_LOOKUP = name -> loaderLookup.lookup(name).or(() -> LINKER.defaultLookup().lookup(name));
+ }
+
+ static T requireNonNull(T obj, String symbolName) {
+ if (obj == null) {
+ throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName);
+ }
+ return obj;
+ }
+
+ private final static SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); };
+
+ static final MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) {
+ return SYMBOL_LOOKUP.lookup(name).map(symbol -> MemorySegment.ofAddress(symbol.address(), layout.byteSize(), MemorySession.openShared())).orElse(null);
+ }
+
+ static final MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) {
+ return SYMBOL_LOOKUP.lookup(name).
+ map(addr -> LINKER.downcallHandle(addr, fdesc)).
+ orElse(null);
+ }
+
+ static final MethodHandle downcallHandle(FunctionDescriptor fdesc) {
+ return LINKER.downcallHandle(fdesc);
+ }
+
+ static final MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) {
+ return SYMBOL_LOOKUP.lookup(name).
+ map(addr -> VarargsInvoker.make(addr, fdesc)).
+ orElse(null);
+ }
+
+ static final MemorySegment upcallStub(Class fi, Z z, FunctionDescriptor fdesc, MemorySession session) {
+ try {
+ MethodHandle handle = MH_LOOKUP.findVirtual(fi, "apply", Linker.upcallType(fdesc));
+ handle = handle.bindTo(z);
+ return LINKER.upcallStub(handle, fdesc, session);
+ } catch (Throwable ex) {
+ throw new AssertionError(ex);
+ }
+ }
+
+ static MemorySegment asArray(MemoryAddress addr, MemoryLayout layout, int numElements, MemorySession session) {
+ return MemorySegment.ofAddress(addr, numElements * layout.byteSize(), session);
+ }
+
+ // Internals only below this point
+
+ private static class VarargsInvoker {
+ private static final MethodHandle INVOKE_MH;
+ private final MemorySegment symbol;
+ private final FunctionDescriptor function;
+
+ private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) {
+ this.symbol = symbol;
+ this.function = function;
+ }
+
+ static {
+ try {
+ INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class));
+ } catch (ReflectiveOperationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) {
+ VarargsInvoker invoker = new VarargsInvoker(symbol, function);
+ MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1);
+ MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class);
+ for (MemoryLayout layout : function.argumentLayouts()) {
+ mtype = mtype.appendParameterTypes(carrier(layout, false));
+ }
+ mtype = mtype.appendParameterTypes(Object[].class);
+ if (mtype.returnType().equals(MemorySegment.class)) {
+ mtype = mtype.insertParameterTypes(0, SegmentAllocator.class);
+ } else {
+ handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR);
+ }
+ return handle.asType(mtype);
+ }
+
+ static Class> carrier(MemoryLayout layout, boolean ret) {
+ if (layout instanceof ValueLayout valueLayout) {
+ return (ret || valueLayout.carrier() != MemoryAddress.class) ?
+ valueLayout.carrier() : Addressable.class;
+ } else if (layout instanceof GroupLayout) {
+ return MemorySegment.class;
+ } else {
+ throw new AssertionError("Cannot get here!");
+ }
+ }
+
+ private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable {
+ // one trailing Object[]
+ int nNamedArgs = function.argumentLayouts().size();
+ assert(args.length == nNamedArgs + 1);
+ // The last argument is the array of vararg collector
+ Object[] unnamedArgs = (Object[]) args[args.length - 1];
+
+ int argsCount = nNamedArgs + unnamedArgs.length;
+ Class>[] argTypes = new Class>[argsCount];
+ MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length];
+
+ int pos = 0;
+ for (pos = 0; pos < nNamedArgs; pos++) {
+ argLayouts[pos] = function.argumentLayouts().get(pos);
+ }
+
+ assert pos == nNamedArgs;
+ for (Object o: unnamedArgs) {
+ argLayouts[pos] = variadicLayout(normalize(o.getClass()));
+ pos++;
+ }
+ assert pos == argsCount;
+
+ FunctionDescriptor f = (function.returnLayout().isEmpty()) ?
+ FunctionDescriptor.ofVoid(argLayouts) :
+ FunctionDescriptor.of(function.returnLayout().get(), argLayouts);
+ MethodHandle mh = LINKER.downcallHandle(symbol, f);
+ if (mh.type().returnType() == MemorySegment.class) {
+ mh = mh.bindTo(allocator);
+ }
+ // flatten argument list so that it can be passed to an asSpreader MH
+ Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length];
+ System.arraycopy(args, 0, allArgs, 0, nNamedArgs);
+ System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length);
+
+ return mh.asSpreader(Object[].class, argsCount).invoke(allArgs);
+ }
+
+ private static Class> unboxIfNeeded(Class> clazz) {
+ if (clazz == Boolean.class) {
+ return boolean.class;
+ } else if (clazz == Void.class) {
+ return void.class;
+ } else if (clazz == Byte.class) {
+ return byte.class;
+ } else if (clazz == Character.class) {
+ return char.class;
+ } else if (clazz == Short.class) {
+ return short.class;
+ } else if (clazz == Integer.class) {
+ return int.class;
+ } else if (clazz == Long.class) {
+ return long.class;
+ } else if (clazz == Float.class) {
+ return float.class;
+ } else if (clazz == Double.class) {
+ return double.class;
+ } else {
+ return clazz;
+ }
+ }
+
+ private Class> promote(Class> c) {
+ if (c == byte.class || c == char.class || c == short.class || c == int.class) {
+ return long.class;
+ } else if (c == float.class) {
+ return double.class;
+ } else {
+ return c;
+ }
+ }
+
+ private Class> normalize(Class> c) {
+ c = unboxIfNeeded(c);
+ if (c.isPrimitive()) {
+ return promote(c);
+ }
+ if (MemoryAddress.class.isAssignableFrom(c)) {
+ return MemoryAddress.class;
+ }
+ if (MemorySegment.class.isAssignableFrom(c)) {
+ return MemorySegment.class;
+ }
+ throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName());
+ }
+
+ private MemoryLayout variadicLayout(Class> c) {
+ if (c == long.class) {
+ return JAVA_LONG;
+ } else if (c == double.class) {
+ return JAVA_DOUBLE;
+ } else if (MemoryAddress.class.isAssignableFrom(c)) {
+ return ADDRESS;
+ } else {
+ throw new IllegalArgumentException("Unhandled variadic argument class: " + c);
+ }
+ }
+ }
+}
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$0.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$0.java
new file mode 100644
index 000000000..d28b2b571
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$0.java
@@ -0,0 +1,35 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$0 {
+
+ static final FunctionDescriptor sdrplay_api_StreamCallback_t$FUNC = FunctionDescriptor.ofVoid(
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_StreamCallback_t$MH = RuntimeHelper.downcallHandle(
+ constants$0.sdrplay_api_StreamCallback_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_EventCallback_t$FUNC = FunctionDescriptor.ofVoid(
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_EventCallback_t$MH = RuntimeHelper.downcallHandle(
+ constants$0.sdrplay_api_EventCallback_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_Open_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_Open_t$MH = RuntimeHelper.downcallHandle(
+ constants$0.sdrplay_api_Open_t$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$1.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$1.java
new file mode 100644
index 000000000..daf28fe8d
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$1.java
@@ -0,0 +1,25 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$1 {
+
+ static final FunctionDescriptor sdrplay_api_Close_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_Close_t$MH = RuntimeHelper.downcallHandle(
+ constants$1.sdrplay_api_Close_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_ApiVersion_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_ApiVersion_t$MH = RuntimeHelper.downcallHandle(
+ constants$1.sdrplay_api_ApiVersion_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_LockDeviceApi_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_LockDeviceApi_t$MH = RuntimeHelper.downcallHandle(
+ constants$1.sdrplay_api_LockDeviceApi_t$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$10.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$10.java
new file mode 100644
index 000000000..71c755949
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$10.java
@@ -0,0 +1,25 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$10 {
+
+ static final FunctionDescriptor sdrplay_api_SwapRspDuoMode$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_DOUBLE$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_SwapRspDuoMode$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_SwapRspDuoMode",
+ constants$10.sdrplay_api_SwapRspDuoMode$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$2.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$2.java
new file mode 100644
index 000000000..90db15b83
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$2.java
@@ -0,0 +1,29 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$2 {
+
+ static final FunctionDescriptor sdrplay_api_UnlockDeviceApi_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_UnlockDeviceApi_t$MH = RuntimeHelper.downcallHandle(
+ constants$2.sdrplay_api_UnlockDeviceApi_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_GetDevices_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_GetDevices_t$MH = RuntimeHelper.downcallHandle(
+ constants$2.sdrplay_api_GetDevices_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_SelectDevice_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_SelectDevice_t$MH = RuntimeHelper.downcallHandle(
+ constants$2.sdrplay_api_SelectDevice_t$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$3.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$3.java
new file mode 100644
index 000000000..6e98cf9fb
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$3.java
@@ -0,0 +1,29 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$3 {
+
+ static final FunctionDescriptor sdrplay_api_ReleaseDevice_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_ReleaseDevice_t$MH = RuntimeHelper.downcallHandle(
+ constants$3.sdrplay_api_ReleaseDevice_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_GetErrorString_t$FUNC = FunctionDescriptor.of(Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_GetErrorString_t$MH = RuntimeHelper.downcallHandle(
+ constants$3.sdrplay_api_GetErrorString_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_GetLastError_t$FUNC = FunctionDescriptor.of(Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_GetLastError_t$MH = RuntimeHelper.downcallHandle(
+ constants$3.sdrplay_api_GetLastError_t$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$4.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$4.java
new file mode 100644
index 000000000..937135618
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$4.java
@@ -0,0 +1,29 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$4 {
+
+ static final FunctionDescriptor sdrplay_api_DisableHeartbeat_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_DisableHeartbeat_t$MH = RuntimeHelper.downcallHandle(
+ constants$4.sdrplay_api_DisableHeartbeat_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_DebugEnable_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_DebugEnable_t$MH = RuntimeHelper.downcallHandle(
+ constants$4.sdrplay_api_DebugEnable_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_GetDeviceParams_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_GetDeviceParams_t$MH = RuntimeHelper.downcallHandle(
+ constants$4.sdrplay_api_GetDeviceParams_t$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$5.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$5.java
new file mode 100644
index 000000000..6350e37aa
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$5.java
@@ -0,0 +1,34 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$5 {
+
+ static final FunctionDescriptor sdrplay_api_Init_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_Init_t$MH = RuntimeHelper.downcallHandle(
+ constants$5.sdrplay_api_Init_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_Uninit_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_Uninit_t$MH = RuntimeHelper.downcallHandle(
+ constants$5.sdrplay_api_Uninit_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_Update_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_Update_t$MH = RuntimeHelper.downcallHandle(
+ constants$5.sdrplay_api_Update_t$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$6.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$6.java
new file mode 100644
index 000000000..0ae887d52
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$6.java
@@ -0,0 +1,38 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$6 {
+
+ static final FunctionDescriptor sdrplay_api_SwapRspDuoActiveTuner_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_SwapRspDuoActiveTuner_t$MH = RuntimeHelper.downcallHandle(
+ constants$6.sdrplay_api_SwapRspDuoActiveTuner_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t$MH = RuntimeHelper.downcallHandle(
+ constants$6.sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_SwapRspDuoMode_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_DOUBLE$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_SwapRspDuoMode_t$MH = RuntimeHelper.downcallHandle(
+ constants$6.sdrplay_api_SwapRspDuoMode_t$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$7.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$7.java
new file mode 100644
index 000000000..01b1cbc2a
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$7.java
@@ -0,0 +1,47 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$7 {
+
+ static final FunctionDescriptor sdrplay_api_Open$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_Open$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_Open",
+ constants$7.sdrplay_api_Open$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_Close$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_Close$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_Close",
+ constants$7.sdrplay_api_Close$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_ApiVersion$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_ApiVersion$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_ApiVersion",
+ constants$7.sdrplay_api_ApiVersion$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_LockDeviceApi$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_LockDeviceApi$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_LockDeviceApi",
+ constants$7.sdrplay_api_LockDeviceApi$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_UnlockDeviceApi$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_UnlockDeviceApi$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_UnlockDeviceApi",
+ constants$7.sdrplay_api_UnlockDeviceApi$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_GetDevices$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_GetDevices$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_GetDevices",
+ constants$7.sdrplay_api_GetDevices$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$8.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$8.java
new file mode 100644
index 000000000..a63156010
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$8.java
@@ -0,0 +1,52 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$8 {
+
+ static final FunctionDescriptor sdrplay_api_SelectDevice$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_SelectDevice$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_SelectDevice",
+ constants$8.sdrplay_api_SelectDevice$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_ReleaseDevice$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_ReleaseDevice$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_ReleaseDevice",
+ constants$8.sdrplay_api_ReleaseDevice$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_GetErrorString$FUNC = FunctionDescriptor.of(Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_GetErrorString$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_GetErrorString",
+ constants$8.sdrplay_api_GetErrorString$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_GetLastError$FUNC = FunctionDescriptor.of(Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_GetLastError$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_GetLastError",
+ constants$8.sdrplay_api_GetLastError$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_DisableHeartbeat$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_DisableHeartbeat$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_DisableHeartbeat",
+ constants$8.sdrplay_api_DisableHeartbeat$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_DebugEnable$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_DebugEnable$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_DebugEnable",
+ constants$8.sdrplay_api_DebugEnable$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$9.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$9.java
new file mode 100644
index 000000000..482c7addd
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/constants$9.java
@@ -0,0 +1,62 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$9 {
+
+ static final FunctionDescriptor sdrplay_api_GetDeviceParams$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_GetDeviceParams$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_GetDeviceParams",
+ constants$9.sdrplay_api_GetDeviceParams$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_Init$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_Init$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_Init",
+ constants$9.sdrplay_api_Init$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_Uninit$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_Uninit$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_Uninit",
+ constants$9.sdrplay_api_Uninit$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_Update$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_Update$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_Update",
+ constants$9.sdrplay_api_Update$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_SwapRspDuoActiveTuner$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_SwapRspDuoActiveTuner$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_SwapRspDuoActiveTuner",
+ constants$9.sdrplay_api_SwapRspDuoActiveTuner$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_SwapRspDuoDualTunerModeSampleRate$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_SwapRspDuoDualTunerModeSampleRate$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_SwapRspDuoDualTunerModeSampleRate",
+ constants$9.sdrplay_api_SwapRspDuoDualTunerModeSampleRate$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_AgcT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_AgcT.java
new file mode 100644
index 000000000..f0344317e
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_AgcT.java
@@ -0,0 +1,146 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_AgcT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("enable"),
+ Constants$root.C_LONG$LAYOUT.withName("setPoint_dBfs"),
+ Constants$root.C_SHORT$LAYOUT.withName("attack_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_delay_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_threshold_dB"),
+ Constants$root.C_LONG$LAYOUT.withName("syncUpdate")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_AgcT.$struct$LAYOUT;
+ }
+ static final VarHandle enable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("enable"));
+ public static VarHandle enable$VH() {
+ return sdrplay_api_AgcT.enable$VH;
+ }
+ public static int enable$get(MemorySegment seg) {
+ return (int)sdrplay_api_AgcT.enable$VH.get(seg);
+ }
+ public static void enable$set( MemorySegment seg, int x) {
+ sdrplay_api_AgcT.enable$VH.set(seg, x);
+ }
+ public static int enable$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_AgcT.enable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void enable$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_AgcT.enable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle setPoint_dBfs$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("setPoint_dBfs"));
+ public static VarHandle setPoint_dBfs$VH() {
+ return sdrplay_api_AgcT.setPoint_dBfs$VH;
+ }
+ public static int setPoint_dBfs$get(MemorySegment seg) {
+ return (int)sdrplay_api_AgcT.setPoint_dBfs$VH.get(seg);
+ }
+ public static void setPoint_dBfs$set( MemorySegment seg, int x) {
+ sdrplay_api_AgcT.setPoint_dBfs$VH.set(seg, x);
+ }
+ public static int setPoint_dBfs$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_AgcT.setPoint_dBfs$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void setPoint_dBfs$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_AgcT.setPoint_dBfs$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle attack_ms$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("attack_ms"));
+ public static VarHandle attack_ms$VH() {
+ return sdrplay_api_AgcT.attack_ms$VH;
+ }
+ public static short attack_ms$get(MemorySegment seg) {
+ return (short)sdrplay_api_AgcT.attack_ms$VH.get(seg);
+ }
+ public static void attack_ms$set( MemorySegment seg, short x) {
+ sdrplay_api_AgcT.attack_ms$VH.set(seg, x);
+ }
+ public static short attack_ms$get(MemorySegment seg, long index) {
+ return (short)sdrplay_api_AgcT.attack_ms$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void attack_ms$set(MemorySegment seg, long index, short x) {
+ sdrplay_api_AgcT.attack_ms$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle decay_ms$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("decay_ms"));
+ public static VarHandle decay_ms$VH() {
+ return sdrplay_api_AgcT.decay_ms$VH;
+ }
+ public static short decay_ms$get(MemorySegment seg) {
+ return (short)sdrplay_api_AgcT.decay_ms$VH.get(seg);
+ }
+ public static void decay_ms$set( MemorySegment seg, short x) {
+ sdrplay_api_AgcT.decay_ms$VH.set(seg, x);
+ }
+ public static short decay_ms$get(MemorySegment seg, long index) {
+ return (short)sdrplay_api_AgcT.decay_ms$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void decay_ms$set(MemorySegment seg, long index, short x) {
+ sdrplay_api_AgcT.decay_ms$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle decay_delay_ms$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("decay_delay_ms"));
+ public static VarHandle decay_delay_ms$VH() {
+ return sdrplay_api_AgcT.decay_delay_ms$VH;
+ }
+ public static short decay_delay_ms$get(MemorySegment seg) {
+ return (short)sdrplay_api_AgcT.decay_delay_ms$VH.get(seg);
+ }
+ public static void decay_delay_ms$set( MemorySegment seg, short x) {
+ sdrplay_api_AgcT.decay_delay_ms$VH.set(seg, x);
+ }
+ public static short decay_delay_ms$get(MemorySegment seg, long index) {
+ return (short)sdrplay_api_AgcT.decay_delay_ms$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void decay_delay_ms$set(MemorySegment seg, long index, short x) {
+ sdrplay_api_AgcT.decay_delay_ms$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle decay_threshold_dB$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("decay_threshold_dB"));
+ public static VarHandle decay_threshold_dB$VH() {
+ return sdrplay_api_AgcT.decay_threshold_dB$VH;
+ }
+ public static short decay_threshold_dB$get(MemorySegment seg) {
+ return (short)sdrplay_api_AgcT.decay_threshold_dB$VH.get(seg);
+ }
+ public static void decay_threshold_dB$set( MemorySegment seg, short x) {
+ sdrplay_api_AgcT.decay_threshold_dB$VH.set(seg, x);
+ }
+ public static short decay_threshold_dB$get(MemorySegment seg, long index) {
+ return (short)sdrplay_api_AgcT.decay_threshold_dB$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void decay_threshold_dB$set(MemorySegment seg, long index, short x) {
+ sdrplay_api_AgcT.decay_threshold_dB$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle syncUpdate$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("syncUpdate"));
+ public static VarHandle syncUpdate$VH() {
+ return sdrplay_api_AgcT.syncUpdate$VH;
+ }
+ public static int syncUpdate$get(MemorySegment seg) {
+ return (int)sdrplay_api_AgcT.syncUpdate$VH.get(seg);
+ }
+ public static void syncUpdate$set( MemorySegment seg, int x) {
+ sdrplay_api_AgcT.syncUpdate$VH.set(seg, x);
+ }
+ public static int syncUpdate$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_AgcT.syncUpdate$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void syncUpdate$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_AgcT.syncUpdate$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_ApiVersion_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_ApiVersion_t.java
new file mode 100644
index 000000000..b86ca9f45
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_ApiVersion_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_ApiVersion_t {
+
+ int apply(java.lang.foreign.MemoryAddress apiVer);
+ static MemorySegment allocate(sdrplay_api_ApiVersion_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_ApiVersion_t.class, fi, constants$1.sdrplay_api_ApiVersion_t$FUNC, session);
+ }
+ static sdrplay_api_ApiVersion_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _apiVer) -> {
+ try {
+ return (int)constants$1.sdrplay_api_ApiVersion_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_apiVer);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_CallbackFnsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_CallbackFnsT.java
new file mode 100644
index 000000000..b7ebdb0a1
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_CallbackFnsT.java
@@ -0,0 +1,87 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_CallbackFnsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_POINTER$LAYOUT.withName("StreamACbFn"),
+ Constants$root.C_POINTER$LAYOUT.withName("StreamBCbFn"),
+ Constants$root.C_POINTER$LAYOUT.withName("EventCbFn")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_CallbackFnsT.$struct$LAYOUT;
+ }
+ static final VarHandle StreamACbFn$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("StreamACbFn"));
+ public static VarHandle StreamACbFn$VH() {
+ return sdrplay_api_CallbackFnsT.StreamACbFn$VH;
+ }
+ public static MemoryAddress StreamACbFn$get(MemorySegment seg) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_CallbackFnsT.StreamACbFn$VH.get(seg);
+ }
+ public static void StreamACbFn$set( MemorySegment seg, MemoryAddress x) {
+ sdrplay_api_CallbackFnsT.StreamACbFn$VH.set(seg, x);
+ }
+ public static MemoryAddress StreamACbFn$get(MemorySegment seg, long index) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_CallbackFnsT.StreamACbFn$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void StreamACbFn$set(MemorySegment seg, long index, MemoryAddress x) {
+ sdrplay_api_CallbackFnsT.StreamACbFn$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static sdrplay_api_StreamCallback_t StreamACbFn (MemorySegment segment, MemorySession session) {
+ return sdrplay_api_StreamCallback_t.ofAddress(StreamACbFn$get(segment), session);
+ }
+ static final VarHandle StreamBCbFn$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("StreamBCbFn"));
+ public static VarHandle StreamBCbFn$VH() {
+ return sdrplay_api_CallbackFnsT.StreamBCbFn$VH;
+ }
+ public static MemoryAddress StreamBCbFn$get(MemorySegment seg) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_CallbackFnsT.StreamBCbFn$VH.get(seg);
+ }
+ public static void StreamBCbFn$set( MemorySegment seg, MemoryAddress x) {
+ sdrplay_api_CallbackFnsT.StreamBCbFn$VH.set(seg, x);
+ }
+ public static MemoryAddress StreamBCbFn$get(MemorySegment seg, long index) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_CallbackFnsT.StreamBCbFn$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void StreamBCbFn$set(MemorySegment seg, long index, MemoryAddress x) {
+ sdrplay_api_CallbackFnsT.StreamBCbFn$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static sdrplay_api_StreamCallback_t StreamBCbFn (MemorySegment segment, MemorySession session) {
+ return sdrplay_api_StreamCallback_t.ofAddress(StreamBCbFn$get(segment), session);
+ }
+ static final VarHandle EventCbFn$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("EventCbFn"));
+ public static VarHandle EventCbFn$VH() {
+ return sdrplay_api_CallbackFnsT.EventCbFn$VH;
+ }
+ public static MemoryAddress EventCbFn$get(MemorySegment seg) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_CallbackFnsT.EventCbFn$VH.get(seg);
+ }
+ public static void EventCbFn$set( MemorySegment seg, MemoryAddress x) {
+ sdrplay_api_CallbackFnsT.EventCbFn$VH.set(seg, x);
+ }
+ public static MemoryAddress EventCbFn$get(MemorySegment seg, long index) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_CallbackFnsT.EventCbFn$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void EventCbFn$set(MemorySegment seg, long index, MemoryAddress x) {
+ sdrplay_api_CallbackFnsT.EventCbFn$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static sdrplay_api_EventCallback_t EventCbFn (MemorySegment segment, MemorySession session) {
+ return sdrplay_api_EventCallback_t.ofAddress(EventCbFn$get(segment), session);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Close_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Close_t.java
new file mode 100644
index 000000000..7fc96c078
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Close_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_Close_t {
+
+ int apply();
+ static MemorySegment allocate(sdrplay_api_Close_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_Close_t.class, fi, constants$1.sdrplay_api_Close_t$FUNC, session);
+ }
+ static sdrplay_api_Close_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return () -> {
+ try {
+ return (int)constants$1.sdrplay_api_Close_t$MH.invokeExact((Addressable)symbol);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_ControlParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_ControlParamsT.java
new file mode 100644
index 000000000..cbebfc4dd
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_ControlParamsT.java
@@ -0,0 +1,72 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_ControlParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("DCenable"),
+ Constants$root.C_CHAR$LAYOUT.withName("IQenable")
+ ).withName("dcOffset"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("enable"),
+ Constants$root.C_CHAR$LAYOUT.withName("decimationFactor"),
+ Constants$root.C_CHAR$LAYOUT.withName("wideBandSignal")
+ ).withName("decimation"),
+ MemoryLayout.paddingLayout(24),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("enable"),
+ Constants$root.C_LONG$LAYOUT.withName("setPoint_dBfs"),
+ Constants$root.C_SHORT$LAYOUT.withName("attack_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_delay_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_threshold_dB"),
+ Constants$root.C_LONG$LAYOUT.withName("syncUpdate")
+ ).withName("agc"),
+ Constants$root.C_LONG$LAYOUT.withName("adsbMode")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_ControlParamsT.$struct$LAYOUT;
+ }
+ public static MemorySegment dcOffset$slice(MemorySegment seg) {
+ return seg.asSlice(0, 2);
+ }
+ public static MemorySegment decimation$slice(MemorySegment seg) {
+ return seg.asSlice(2, 3);
+ }
+ public static MemorySegment agc$slice(MemorySegment seg) {
+ return seg.asSlice(8, 20);
+ }
+ static final VarHandle adsbMode$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("adsbMode"));
+ public static VarHandle adsbMode$VH() {
+ return sdrplay_api_ControlParamsT.adsbMode$VH;
+ }
+ public static int adsbMode$get(MemorySegment seg) {
+ return (int)sdrplay_api_ControlParamsT.adsbMode$VH.get(seg);
+ }
+ public static void adsbMode$set( MemorySegment seg, int x) {
+ sdrplay_api_ControlParamsT.adsbMode$VH.set(seg, x);
+ }
+ public static int adsbMode$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_ControlParamsT.adsbMode$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void adsbMode$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_ControlParamsT.adsbMode$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DcOffsetT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DcOffsetT.java
new file mode 100644
index 000000000..594c0c025
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DcOffsetT.java
@@ -0,0 +1,61 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_DcOffsetT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("DCenable"),
+ Constants$root.C_CHAR$LAYOUT.withName("IQenable")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_DcOffsetT.$struct$LAYOUT;
+ }
+ static final VarHandle DCenable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("DCenable"));
+ public static VarHandle DCenable$VH() {
+ return sdrplay_api_DcOffsetT.DCenable$VH;
+ }
+ public static byte DCenable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_DcOffsetT.DCenable$VH.get(seg);
+ }
+ public static void DCenable$set( MemorySegment seg, byte x) {
+ sdrplay_api_DcOffsetT.DCenable$VH.set(seg, x);
+ }
+ public static byte DCenable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_DcOffsetT.DCenable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void DCenable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_DcOffsetT.DCenable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle IQenable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("IQenable"));
+ public static VarHandle IQenable$VH() {
+ return sdrplay_api_DcOffsetT.IQenable$VH;
+ }
+ public static byte IQenable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_DcOffsetT.IQenable$VH.get(seg);
+ }
+ public static void IQenable$set( MemorySegment seg, byte x) {
+ sdrplay_api_DcOffsetT.IQenable$VH.set(seg, x);
+ }
+ public static byte IQenable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_DcOffsetT.IQenable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void IQenable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_DcOffsetT.IQenable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DcOffsetTunerT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DcOffsetTunerT.java
new file mode 100644
index 000000000..4d870467d
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DcOffsetTunerT.java
@@ -0,0 +1,96 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_DcOffsetTunerT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("dcCal"),
+ Constants$root.C_CHAR$LAYOUT.withName("speedUp"),
+ MemoryLayout.paddingLayout(16),
+ Constants$root.C_LONG$LAYOUT.withName("trackTime"),
+ Constants$root.C_LONG$LAYOUT.withName("refreshRateTime")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_DcOffsetTunerT.$struct$LAYOUT;
+ }
+ static final VarHandle dcCal$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("dcCal"));
+ public static VarHandle dcCal$VH() {
+ return sdrplay_api_DcOffsetTunerT.dcCal$VH;
+ }
+ public static byte dcCal$get(MemorySegment seg) {
+ return (byte)sdrplay_api_DcOffsetTunerT.dcCal$VH.get(seg);
+ }
+ public static void dcCal$set( MemorySegment seg, byte x) {
+ sdrplay_api_DcOffsetTunerT.dcCal$VH.set(seg, x);
+ }
+ public static byte dcCal$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_DcOffsetTunerT.dcCal$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void dcCal$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_DcOffsetTunerT.dcCal$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle speedUp$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("speedUp"));
+ public static VarHandle speedUp$VH() {
+ return sdrplay_api_DcOffsetTunerT.speedUp$VH;
+ }
+ public static byte speedUp$get(MemorySegment seg) {
+ return (byte)sdrplay_api_DcOffsetTunerT.speedUp$VH.get(seg);
+ }
+ public static void speedUp$set( MemorySegment seg, byte x) {
+ sdrplay_api_DcOffsetTunerT.speedUp$VH.set(seg, x);
+ }
+ public static byte speedUp$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_DcOffsetTunerT.speedUp$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void speedUp$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_DcOffsetTunerT.speedUp$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle trackTime$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("trackTime"));
+ public static VarHandle trackTime$VH() {
+ return sdrplay_api_DcOffsetTunerT.trackTime$VH;
+ }
+ public static int trackTime$get(MemorySegment seg) {
+ return (int)sdrplay_api_DcOffsetTunerT.trackTime$VH.get(seg);
+ }
+ public static void trackTime$set( MemorySegment seg, int x) {
+ sdrplay_api_DcOffsetTunerT.trackTime$VH.set(seg, x);
+ }
+ public static int trackTime$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_DcOffsetTunerT.trackTime$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void trackTime$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_DcOffsetTunerT.trackTime$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle refreshRateTime$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("refreshRateTime"));
+ public static VarHandle refreshRateTime$VH() {
+ return sdrplay_api_DcOffsetTunerT.refreshRateTime$VH;
+ }
+ public static int refreshRateTime$get(MemorySegment seg) {
+ return (int)sdrplay_api_DcOffsetTunerT.refreshRateTime$VH.get(seg);
+ }
+ public static void refreshRateTime$set( MemorySegment seg, int x) {
+ sdrplay_api_DcOffsetTunerT.refreshRateTime$VH.set(seg, x);
+ }
+ public static int refreshRateTime$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_DcOffsetTunerT.refreshRateTime$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void refreshRateTime$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_DcOffsetTunerT.refreshRateTime$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DebugEnable_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DebugEnable_t.java
new file mode 100644
index 000000000..7f70bb114
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DebugEnable_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_DebugEnable_t {
+
+ int apply(java.lang.foreign.MemoryAddress dev, int dbgLvl);
+ static MemorySegment allocate(sdrplay_api_DebugEnable_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_DebugEnable_t.class, fi, constants$4.sdrplay_api_DebugEnable_t$FUNC, session);
+ }
+ static sdrplay_api_DebugEnable_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _dev, int _dbgLvl) -> {
+ try {
+ return (int)constants$4.sdrplay_api_DebugEnable_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_dev, _dbgLvl);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DecimationT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DecimationT.java
new file mode 100644
index 000000000..f6acaf0c4
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DecimationT.java
@@ -0,0 +1,78 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_DecimationT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("enable"),
+ Constants$root.C_CHAR$LAYOUT.withName("decimationFactor"),
+ Constants$root.C_CHAR$LAYOUT.withName("wideBandSignal")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_DecimationT.$struct$LAYOUT;
+ }
+ static final VarHandle enable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("enable"));
+ public static VarHandle enable$VH() {
+ return sdrplay_api_DecimationT.enable$VH;
+ }
+ public static byte enable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_DecimationT.enable$VH.get(seg);
+ }
+ public static void enable$set( MemorySegment seg, byte x) {
+ sdrplay_api_DecimationT.enable$VH.set(seg, x);
+ }
+ public static byte enable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_DecimationT.enable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void enable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_DecimationT.enable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle decimationFactor$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("decimationFactor"));
+ public static VarHandle decimationFactor$VH() {
+ return sdrplay_api_DecimationT.decimationFactor$VH;
+ }
+ public static byte decimationFactor$get(MemorySegment seg) {
+ return (byte)sdrplay_api_DecimationT.decimationFactor$VH.get(seg);
+ }
+ public static void decimationFactor$set( MemorySegment seg, byte x) {
+ sdrplay_api_DecimationT.decimationFactor$VH.set(seg, x);
+ }
+ public static byte decimationFactor$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_DecimationT.decimationFactor$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void decimationFactor$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_DecimationT.decimationFactor$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle wideBandSignal$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("wideBandSignal"));
+ public static VarHandle wideBandSignal$VH() {
+ return sdrplay_api_DecimationT.wideBandSignal$VH;
+ }
+ public static byte wideBandSignal$get(MemorySegment seg) {
+ return (byte)sdrplay_api_DecimationT.wideBandSignal$VH.get(seg);
+ }
+ public static void wideBandSignal$set( MemorySegment seg, byte x) {
+ sdrplay_api_DecimationT.wideBandSignal$VH.set(seg, x);
+ }
+ public static byte wideBandSignal$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_DecimationT.wideBandSignal$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void wideBandSignal$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_DecimationT.wideBandSignal$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DevParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DevParamsT.java
new file mode 100644
index 000000000..6dd22573e
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DevParamsT.java
@@ -0,0 +1,135 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_DevParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_DOUBLE$LAYOUT.withName("ppm"),
+ MemoryLayout.structLayout(
+ Constants$root.C_DOUBLE$LAYOUT.withName("fsHz"),
+ Constants$root.C_CHAR$LAYOUT.withName("syncUpdate"),
+ Constants$root.C_CHAR$LAYOUT.withName("reCal"),
+ MemoryLayout.paddingLayout(48)
+ ).withName("fsFreq"),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("sampleNum"),
+ Constants$root.C_LONG$LAYOUT.withName("period")
+ ).withName("syncUpdate"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("resetGainUpdate"),
+ Constants$root.C_CHAR$LAYOUT.withName("resetRfUpdate"),
+ Constants$root.C_CHAR$LAYOUT.withName("resetFsUpdate")
+ ).withName("resetFlags"),
+ MemoryLayout.paddingLayout(8),
+ Constants$root.C_LONG$LAYOUT.withName("mode"),
+ Constants$root.C_LONG$LAYOUT.withName("samplesPerPkt"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("rfNotchEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfDabNotchEnable")
+ ).withName("rsp1aParams"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("extRefOutputEn")
+ ).withName("rsp2Params"),
+ MemoryLayout.paddingLayout(8),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("extRefOutputEn")
+ ).withName("rspDuoParams"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("hdrEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("biasTEnable"),
+ MemoryLayout.paddingLayout(16),
+ Constants$root.C_LONG$LAYOUT.withName("antennaSel"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfNotchEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfDabNotchEnable"),
+ MemoryLayout.paddingLayout(16)
+ ).withName("rspDxParams")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_DevParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle ppm$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("ppm"));
+ public static VarHandle ppm$VH() {
+ return sdrplay_api_DevParamsT.ppm$VH;
+ }
+ public static double ppm$get(MemorySegment seg) {
+ return (double)sdrplay_api_DevParamsT.ppm$VH.get(seg);
+ }
+ public static void ppm$set( MemorySegment seg, double x) {
+ sdrplay_api_DevParamsT.ppm$VH.set(seg, x);
+ }
+ public static double ppm$get(MemorySegment seg, long index) {
+ return (double)sdrplay_api_DevParamsT.ppm$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void ppm$set(MemorySegment seg, long index, double x) {
+ sdrplay_api_DevParamsT.ppm$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static MemorySegment fsFreq$slice(MemorySegment seg) {
+ return seg.asSlice(8, 16);
+ }
+ public static MemorySegment syncUpdate$slice(MemorySegment seg) {
+ return seg.asSlice(24, 8);
+ }
+ public static MemorySegment resetFlags$slice(MemorySegment seg) {
+ return seg.asSlice(32, 3);
+ }
+ static final VarHandle mode$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("mode"));
+ public static VarHandle mode$VH() {
+ return sdrplay_api_DevParamsT.mode$VH;
+ }
+ public static int mode$get(MemorySegment seg) {
+ return (int)sdrplay_api_DevParamsT.mode$VH.get(seg);
+ }
+ public static void mode$set( MemorySegment seg, int x) {
+ sdrplay_api_DevParamsT.mode$VH.set(seg, x);
+ }
+ public static int mode$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_DevParamsT.mode$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void mode$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_DevParamsT.mode$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle samplesPerPkt$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("samplesPerPkt"));
+ public static VarHandle samplesPerPkt$VH() {
+ return sdrplay_api_DevParamsT.samplesPerPkt$VH;
+ }
+ public static int samplesPerPkt$get(MemorySegment seg) {
+ return (int)sdrplay_api_DevParamsT.samplesPerPkt$VH.get(seg);
+ }
+ public static void samplesPerPkt$set( MemorySegment seg, int x) {
+ sdrplay_api_DevParamsT.samplesPerPkt$VH.set(seg, x);
+ }
+ public static int samplesPerPkt$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_DevParamsT.samplesPerPkt$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void samplesPerPkt$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_DevParamsT.samplesPerPkt$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static MemorySegment rsp1aParams$slice(MemorySegment seg) {
+ return seg.asSlice(44, 2);
+ }
+ public static MemorySegment rsp2Params$slice(MemorySegment seg) {
+ return seg.asSlice(46, 1);
+ }
+ public static MemorySegment rspDuoParams$slice(MemorySegment seg) {
+ return seg.asSlice(48, 4);
+ }
+ public static MemorySegment rspDxParams$slice(MemorySegment seg) {
+ return seg.asSlice(52, 12);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DeviceParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DeviceParamsT.java
new file mode 100644
index 000000000..4f9525e64
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DeviceParamsT.java
@@ -0,0 +1,78 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_DeviceParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_POINTER$LAYOUT.withName("devParams"),
+ Constants$root.C_POINTER$LAYOUT.withName("rxChannelA"),
+ Constants$root.C_POINTER$LAYOUT.withName("rxChannelB")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_DeviceParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle devParams$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("devParams"));
+ public static VarHandle devParams$VH() {
+ return sdrplay_api_DeviceParamsT.devParams$VH;
+ }
+ public static MemoryAddress devParams$get(MemorySegment seg) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_DeviceParamsT.devParams$VH.get(seg);
+ }
+ public static void devParams$set( MemorySegment seg, MemoryAddress x) {
+ sdrplay_api_DeviceParamsT.devParams$VH.set(seg, x);
+ }
+ public static MemoryAddress devParams$get(MemorySegment seg, long index) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_DeviceParamsT.devParams$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void devParams$set(MemorySegment seg, long index, MemoryAddress x) {
+ sdrplay_api_DeviceParamsT.devParams$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rxChannelA$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rxChannelA"));
+ public static VarHandle rxChannelA$VH() {
+ return sdrplay_api_DeviceParamsT.rxChannelA$VH;
+ }
+ public static MemoryAddress rxChannelA$get(MemorySegment seg) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_DeviceParamsT.rxChannelA$VH.get(seg);
+ }
+ public static void rxChannelA$set( MemorySegment seg, MemoryAddress x) {
+ sdrplay_api_DeviceParamsT.rxChannelA$VH.set(seg, x);
+ }
+ public static MemoryAddress rxChannelA$get(MemorySegment seg, long index) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_DeviceParamsT.rxChannelA$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rxChannelA$set(MemorySegment seg, long index, MemoryAddress x) {
+ sdrplay_api_DeviceParamsT.rxChannelA$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rxChannelB$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rxChannelB"));
+ public static VarHandle rxChannelB$VH() {
+ return sdrplay_api_DeviceParamsT.rxChannelB$VH;
+ }
+ public static MemoryAddress rxChannelB$get(MemorySegment seg) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_DeviceParamsT.rxChannelB$VH.get(seg);
+ }
+ public static void rxChannelB$set( MemorySegment seg, MemoryAddress x) {
+ sdrplay_api_DeviceParamsT.rxChannelB$VH.set(seg, x);
+ }
+ public static MemoryAddress rxChannelB$get(MemorySegment seg, long index) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_DeviceParamsT.rxChannelB$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rxChannelB$set(MemorySegment seg, long index, MemoryAddress x) {
+ sdrplay_api_DeviceParamsT.rxChannelB$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DeviceT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DeviceT.java
new file mode 100644
index 000000000..0782fd31d
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DeviceT.java
@@ -0,0 +1,118 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_DeviceT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ MemoryLayout.sequenceLayout(64, Constants$root.C_CHAR$LAYOUT).withName("SerNo"),
+ Constants$root.C_CHAR$LAYOUT.withName("hwVer"),
+ MemoryLayout.paddingLayout(24),
+ Constants$root.C_LONG$LAYOUT.withName("tuner"),
+ Constants$root.C_LONG$LAYOUT.withName("rspDuoMode"),
+ MemoryLayout.paddingLayout(32),
+ Constants$root.C_DOUBLE$LAYOUT.withName("rspDuoSampleFreq"),
+ Constants$root.C_POINTER$LAYOUT.withName("dev")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_DeviceT.$struct$LAYOUT;
+ }
+ public static MemorySegment SerNo$slice(MemorySegment seg) {
+ return seg.asSlice(0, 64);
+ }
+ static final VarHandle hwVer$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("hwVer"));
+ public static VarHandle hwVer$VH() {
+ return sdrplay_api_DeviceT.hwVer$VH;
+ }
+ public static byte hwVer$get(MemorySegment seg) {
+ return (byte)sdrplay_api_DeviceT.hwVer$VH.get(seg);
+ }
+ public static void hwVer$set( MemorySegment seg, byte x) {
+ sdrplay_api_DeviceT.hwVer$VH.set(seg, x);
+ }
+ public static byte hwVer$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_DeviceT.hwVer$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void hwVer$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_DeviceT.hwVer$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle tuner$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("tuner"));
+ public static VarHandle tuner$VH() {
+ return sdrplay_api_DeviceT.tuner$VH;
+ }
+ public static int tuner$get(MemorySegment seg) {
+ return (int)sdrplay_api_DeviceT.tuner$VH.get(seg);
+ }
+ public static void tuner$set( MemorySegment seg, int x) {
+ sdrplay_api_DeviceT.tuner$VH.set(seg, x);
+ }
+ public static int tuner$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_DeviceT.tuner$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void tuner$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_DeviceT.tuner$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rspDuoMode$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rspDuoMode"));
+ public static VarHandle rspDuoMode$VH() {
+ return sdrplay_api_DeviceT.rspDuoMode$VH;
+ }
+ public static int rspDuoMode$get(MemorySegment seg) {
+ return (int)sdrplay_api_DeviceT.rspDuoMode$VH.get(seg);
+ }
+ public static void rspDuoMode$set( MemorySegment seg, int x) {
+ sdrplay_api_DeviceT.rspDuoMode$VH.set(seg, x);
+ }
+ public static int rspDuoMode$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_DeviceT.rspDuoMode$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rspDuoMode$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_DeviceT.rspDuoMode$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rspDuoSampleFreq$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rspDuoSampleFreq"));
+ public static VarHandle rspDuoSampleFreq$VH() {
+ return sdrplay_api_DeviceT.rspDuoSampleFreq$VH;
+ }
+ public static double rspDuoSampleFreq$get(MemorySegment seg) {
+ return (double)sdrplay_api_DeviceT.rspDuoSampleFreq$VH.get(seg);
+ }
+ public static void rspDuoSampleFreq$set( MemorySegment seg, double x) {
+ sdrplay_api_DeviceT.rspDuoSampleFreq$VH.set(seg, x);
+ }
+ public static double rspDuoSampleFreq$get(MemorySegment seg, long index) {
+ return (double)sdrplay_api_DeviceT.rspDuoSampleFreq$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rspDuoSampleFreq$set(MemorySegment seg, long index, double x) {
+ sdrplay_api_DeviceT.rspDuoSampleFreq$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle dev$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("dev"));
+ public static VarHandle dev$VH() {
+ return sdrplay_api_DeviceT.dev$VH;
+ }
+ public static MemoryAddress dev$get(MemorySegment seg) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_DeviceT.dev$VH.get(seg);
+ }
+ public static void dev$set( MemorySegment seg, MemoryAddress x) {
+ sdrplay_api_DeviceT.dev$VH.set(seg, x);
+ }
+ public static MemoryAddress dev$get(MemorySegment seg, long index) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_DeviceT.dev$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void dev$set(MemorySegment seg, long index, MemoryAddress x) {
+ sdrplay_api_DeviceT.dev$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DisableHeartbeat_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DisableHeartbeat_t.java
new file mode 100644
index 000000000..bb29a06fa
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_DisableHeartbeat_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_DisableHeartbeat_t {
+
+ int apply();
+ static MemorySegment allocate(sdrplay_api_DisableHeartbeat_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_DisableHeartbeat_t.class, fi, constants$4.sdrplay_api_DisableHeartbeat_t$FUNC, session);
+ }
+ static sdrplay_api_DisableHeartbeat_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return () -> {
+ try {
+ return (int)constants$4.sdrplay_api_DisableHeartbeat_t$MH.invokeExact((Addressable)symbol);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_ErrorInfoT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_ErrorInfoT.java
new file mode 100644
index 000000000..373f42b13
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_ErrorInfoT.java
@@ -0,0 +1,56 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_ErrorInfoT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ MemoryLayout.sequenceLayout(256, Constants$root.C_CHAR$LAYOUT).withName("file"),
+ MemoryLayout.sequenceLayout(256, Constants$root.C_CHAR$LAYOUT).withName("function"),
+ Constants$root.C_LONG$LAYOUT.withName("line"),
+ MemoryLayout.sequenceLayout(1024, Constants$root.C_CHAR$LAYOUT).withName("message")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_ErrorInfoT.$struct$LAYOUT;
+ }
+ public static MemorySegment file$slice(MemorySegment seg) {
+ return seg.asSlice(0, 256);
+ }
+ public static MemorySegment function$slice(MemorySegment seg) {
+ return seg.asSlice(256, 256);
+ }
+ static final VarHandle line$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("line"));
+ public static VarHandle line$VH() {
+ return sdrplay_api_ErrorInfoT.line$VH;
+ }
+ public static int line$get(MemorySegment seg) {
+ return (int)sdrplay_api_ErrorInfoT.line$VH.get(seg);
+ }
+ public static void line$set( MemorySegment seg, int x) {
+ sdrplay_api_ErrorInfoT.line$VH.set(seg, x);
+ }
+ public static int line$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_ErrorInfoT.line$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void line$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_ErrorInfoT.line$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static MemorySegment message$slice(MemorySegment seg) {
+ return seg.asSlice(516, 1024);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_EventCallback_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_EventCallback_t.java
new file mode 100644
index 000000000..78a724ae9
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_EventCallback_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_EventCallback_t {
+
+ void apply(int eventId, int tuner, java.lang.foreign.MemoryAddress params, java.lang.foreign.MemoryAddress cbContext);
+ static MemorySegment allocate(sdrplay_api_EventCallback_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_EventCallback_t.class, fi, constants$0.sdrplay_api_EventCallback_t$FUNC, session);
+ }
+ static sdrplay_api_EventCallback_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (int _eventId, int _tuner, java.lang.foreign.MemoryAddress _params, java.lang.foreign.MemoryAddress _cbContext) -> {
+ try {
+ constants$0.sdrplay_api_EventCallback_t$MH.invokeExact((Addressable)symbol, _eventId, _tuner, (java.lang.foreign.Addressable)_params, (java.lang.foreign.Addressable)_cbContext);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_EventParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_EventParamsT.java
new file mode 100644
index 000000000..3e8c49be6
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_EventParamsT.java
@@ -0,0 +1,46 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+public class sdrplay_api_EventParamsT {
+
+ static final GroupLayout $union$LAYOUT = MemoryLayout.unionLayout(
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("gRdB"),
+ Constants$root.C_LONG$LAYOUT.withName("lnaGRdB"),
+ Constants$root.C_DOUBLE$LAYOUT.withName("currGain")
+ ).withName("gainParams"),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("powerOverloadChangeType")
+ ).withName("powerOverloadParams"),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("modeChangeType")
+ ).withName("rspDuoModeParams")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_EventParamsT.$union$LAYOUT;
+ }
+ public static MemorySegment gainParams$slice(MemorySegment seg) {
+ return seg.asSlice(0, 16);
+ }
+ public static MemorySegment powerOverloadParams$slice(MemorySegment seg) {
+ return seg.asSlice(0, 4);
+ }
+ public static MemorySegment rspDuoModeParams$slice(MemorySegment seg) {
+ return seg.asSlice(0, 4);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_FsFreqT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_FsFreqT.java
new file mode 100644
index 000000000..94e55b3b3
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_FsFreqT.java
@@ -0,0 +1,79 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_FsFreqT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_DOUBLE$LAYOUT.withName("fsHz"),
+ Constants$root.C_CHAR$LAYOUT.withName("syncUpdate"),
+ Constants$root.C_CHAR$LAYOUT.withName("reCal"),
+ MemoryLayout.paddingLayout(48)
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_FsFreqT.$struct$LAYOUT;
+ }
+ static final VarHandle fsHz$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("fsHz"));
+ public static VarHandle fsHz$VH() {
+ return sdrplay_api_FsFreqT.fsHz$VH;
+ }
+ public static double fsHz$get(MemorySegment seg) {
+ return (double)sdrplay_api_FsFreqT.fsHz$VH.get(seg);
+ }
+ public static void fsHz$set( MemorySegment seg, double x) {
+ sdrplay_api_FsFreqT.fsHz$VH.set(seg, x);
+ }
+ public static double fsHz$get(MemorySegment seg, long index) {
+ return (double)sdrplay_api_FsFreqT.fsHz$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void fsHz$set(MemorySegment seg, long index, double x) {
+ sdrplay_api_FsFreqT.fsHz$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle syncUpdate$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("syncUpdate"));
+ public static VarHandle syncUpdate$VH() {
+ return sdrplay_api_FsFreqT.syncUpdate$VH;
+ }
+ public static byte syncUpdate$get(MemorySegment seg) {
+ return (byte)sdrplay_api_FsFreqT.syncUpdate$VH.get(seg);
+ }
+ public static void syncUpdate$set( MemorySegment seg, byte x) {
+ sdrplay_api_FsFreqT.syncUpdate$VH.set(seg, x);
+ }
+ public static byte syncUpdate$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_FsFreqT.syncUpdate$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void syncUpdate$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_FsFreqT.syncUpdate$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle reCal$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("reCal"));
+ public static VarHandle reCal$VH() {
+ return sdrplay_api_FsFreqT.reCal$VH;
+ }
+ public static byte reCal$get(MemorySegment seg) {
+ return (byte)sdrplay_api_FsFreqT.reCal$VH.get(seg);
+ }
+ public static void reCal$set( MemorySegment seg, byte x) {
+ sdrplay_api_FsFreqT.reCal$VH.set(seg, x);
+ }
+ public static byte reCal$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_FsFreqT.reCal$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void reCal$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_FsFreqT.reCal$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GainCbParamT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GainCbParamT.java
new file mode 100644
index 000000000..437e99f3d
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GainCbParamT.java
@@ -0,0 +1,78 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_GainCbParamT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("gRdB"),
+ Constants$root.C_LONG$LAYOUT.withName("lnaGRdB"),
+ Constants$root.C_DOUBLE$LAYOUT.withName("currGain")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_GainCbParamT.$struct$LAYOUT;
+ }
+ static final VarHandle gRdB$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("gRdB"));
+ public static VarHandle gRdB$VH() {
+ return sdrplay_api_GainCbParamT.gRdB$VH;
+ }
+ public static int gRdB$get(MemorySegment seg) {
+ return (int)sdrplay_api_GainCbParamT.gRdB$VH.get(seg);
+ }
+ public static void gRdB$set( MemorySegment seg, int x) {
+ sdrplay_api_GainCbParamT.gRdB$VH.set(seg, x);
+ }
+ public static int gRdB$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_GainCbParamT.gRdB$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void gRdB$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_GainCbParamT.gRdB$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle lnaGRdB$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("lnaGRdB"));
+ public static VarHandle lnaGRdB$VH() {
+ return sdrplay_api_GainCbParamT.lnaGRdB$VH;
+ }
+ public static int lnaGRdB$get(MemorySegment seg) {
+ return (int)sdrplay_api_GainCbParamT.lnaGRdB$VH.get(seg);
+ }
+ public static void lnaGRdB$set( MemorySegment seg, int x) {
+ sdrplay_api_GainCbParamT.lnaGRdB$VH.set(seg, x);
+ }
+ public static int lnaGRdB$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_GainCbParamT.lnaGRdB$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void lnaGRdB$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_GainCbParamT.lnaGRdB$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle currGain$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("currGain"));
+ public static VarHandle currGain$VH() {
+ return sdrplay_api_GainCbParamT.currGain$VH;
+ }
+ public static double currGain$get(MemorySegment seg) {
+ return (double)sdrplay_api_GainCbParamT.currGain$VH.get(seg);
+ }
+ public static void currGain$set( MemorySegment seg, double x) {
+ sdrplay_api_GainCbParamT.currGain$VH.set(seg, x);
+ }
+ public static double currGain$get(MemorySegment seg, long index) {
+ return (double)sdrplay_api_GainCbParamT.currGain$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void currGain$set(MemorySegment seg, long index, double x) {
+ sdrplay_api_GainCbParamT.currGain$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GainT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GainT.java
new file mode 100644
index 000000000..4416db86d
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GainT.java
@@ -0,0 +1,104 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_GainT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("gRdB"),
+ Constants$root.C_CHAR$LAYOUT.withName("LNAstate"),
+ Constants$root.C_CHAR$LAYOUT.withName("syncUpdate"),
+ MemoryLayout.paddingLayout(16),
+ Constants$root.C_LONG$LAYOUT.withName("minGr"),
+ MemoryLayout.structLayout(
+ Constants$root.C_FLOAT$LAYOUT.withName("curr"),
+ Constants$root.C_FLOAT$LAYOUT.withName("max"),
+ Constants$root.C_FLOAT$LAYOUT.withName("min")
+ ).withName("gainVals")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_GainT.$struct$LAYOUT;
+ }
+ static final VarHandle gRdB$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("gRdB"));
+ public static VarHandle gRdB$VH() {
+ return sdrplay_api_GainT.gRdB$VH;
+ }
+ public static int gRdB$get(MemorySegment seg) {
+ return (int)sdrplay_api_GainT.gRdB$VH.get(seg);
+ }
+ public static void gRdB$set( MemorySegment seg, int x) {
+ sdrplay_api_GainT.gRdB$VH.set(seg, x);
+ }
+ public static int gRdB$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_GainT.gRdB$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void gRdB$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_GainT.gRdB$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle LNAstate$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("LNAstate"));
+ public static VarHandle LNAstate$VH() {
+ return sdrplay_api_GainT.LNAstate$VH;
+ }
+ public static byte LNAstate$get(MemorySegment seg) {
+ return (byte)sdrplay_api_GainT.LNAstate$VH.get(seg);
+ }
+ public static void LNAstate$set( MemorySegment seg, byte x) {
+ sdrplay_api_GainT.LNAstate$VH.set(seg, x);
+ }
+ public static byte LNAstate$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_GainT.LNAstate$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void LNAstate$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_GainT.LNAstate$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle syncUpdate$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("syncUpdate"));
+ public static VarHandle syncUpdate$VH() {
+ return sdrplay_api_GainT.syncUpdate$VH;
+ }
+ public static byte syncUpdate$get(MemorySegment seg) {
+ return (byte)sdrplay_api_GainT.syncUpdate$VH.get(seg);
+ }
+ public static void syncUpdate$set( MemorySegment seg, byte x) {
+ sdrplay_api_GainT.syncUpdate$VH.set(seg, x);
+ }
+ public static byte syncUpdate$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_GainT.syncUpdate$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void syncUpdate$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_GainT.syncUpdate$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle minGr$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("minGr"));
+ public static VarHandle minGr$VH() {
+ return sdrplay_api_GainT.minGr$VH;
+ }
+ public static int minGr$get(MemorySegment seg) {
+ return (int)sdrplay_api_GainT.minGr$VH.get(seg);
+ }
+ public static void minGr$set( MemorySegment seg, int x) {
+ sdrplay_api_GainT.minGr$VH.set(seg, x);
+ }
+ public static int minGr$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_GainT.minGr$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void minGr$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_GainT.minGr$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static MemorySegment gainVals$slice(MemorySegment seg) {
+ return seg.asSlice(12, 12);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GainValuesT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GainValuesT.java
new file mode 100644
index 000000000..8c1c0aa05
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GainValuesT.java
@@ -0,0 +1,78 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_GainValuesT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_FLOAT$LAYOUT.withName("curr"),
+ Constants$root.C_FLOAT$LAYOUT.withName("max"),
+ Constants$root.C_FLOAT$LAYOUT.withName("min")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_GainValuesT.$struct$LAYOUT;
+ }
+ static final VarHandle curr$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("curr"));
+ public static VarHandle curr$VH() {
+ return sdrplay_api_GainValuesT.curr$VH;
+ }
+ public static float curr$get(MemorySegment seg) {
+ return (float)sdrplay_api_GainValuesT.curr$VH.get(seg);
+ }
+ public static void curr$set( MemorySegment seg, float x) {
+ sdrplay_api_GainValuesT.curr$VH.set(seg, x);
+ }
+ public static float curr$get(MemorySegment seg, long index) {
+ return (float)sdrplay_api_GainValuesT.curr$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void curr$set(MemorySegment seg, long index, float x) {
+ sdrplay_api_GainValuesT.curr$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle max$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("max"));
+ public static VarHandle max$VH() {
+ return sdrplay_api_GainValuesT.max$VH;
+ }
+ public static float max$get(MemorySegment seg) {
+ return (float)sdrplay_api_GainValuesT.max$VH.get(seg);
+ }
+ public static void max$set( MemorySegment seg, float x) {
+ sdrplay_api_GainValuesT.max$VH.set(seg, x);
+ }
+ public static float max$get(MemorySegment seg, long index) {
+ return (float)sdrplay_api_GainValuesT.max$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void max$set(MemorySegment seg, long index, float x) {
+ sdrplay_api_GainValuesT.max$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle min$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("min"));
+ public static VarHandle min$VH() {
+ return sdrplay_api_GainValuesT.min$VH;
+ }
+ public static float min$get(MemorySegment seg) {
+ return (float)sdrplay_api_GainValuesT.min$VH.get(seg);
+ }
+ public static void min$set( MemorySegment seg, float x) {
+ sdrplay_api_GainValuesT.min$VH.set(seg, x);
+ }
+ public static float min$get(MemorySegment seg, long index) {
+ return (float)sdrplay_api_GainValuesT.min$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void min$set(MemorySegment seg, long index, float x) {
+ sdrplay_api_GainValuesT.min$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GetDeviceParams_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GetDeviceParams_t.java
new file mode 100644
index 000000000..cdda61777
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GetDeviceParams_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_GetDeviceParams_t {
+
+ int apply(java.lang.foreign.MemoryAddress dev, java.lang.foreign.MemoryAddress deviceParams);
+ static MemorySegment allocate(sdrplay_api_GetDeviceParams_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_GetDeviceParams_t.class, fi, constants$4.sdrplay_api_GetDeviceParams_t$FUNC, session);
+ }
+ static sdrplay_api_GetDeviceParams_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _dev, java.lang.foreign.MemoryAddress _deviceParams) -> {
+ try {
+ return (int)constants$4.sdrplay_api_GetDeviceParams_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_dev, (java.lang.foreign.Addressable)_deviceParams);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GetDevices_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GetDevices_t.java
new file mode 100644
index 000000000..862320a6b
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GetDevices_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_GetDevices_t {
+
+ int apply(java.lang.foreign.MemoryAddress devices, java.lang.foreign.MemoryAddress numDevs, int maxDevs);
+ static MemorySegment allocate(sdrplay_api_GetDevices_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_GetDevices_t.class, fi, constants$2.sdrplay_api_GetDevices_t$FUNC, session);
+ }
+ static sdrplay_api_GetDevices_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _devices, java.lang.foreign.MemoryAddress _numDevs, int _maxDevs) -> {
+ try {
+ return (int)constants$2.sdrplay_api_GetDevices_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_devices, (java.lang.foreign.Addressable)_numDevs, _maxDevs);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GetErrorString_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GetErrorString_t.java
new file mode 100644
index 000000000..6d9c160a3
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GetErrorString_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_GetErrorString_t {
+
+ java.lang.foreign.Addressable apply(int err);
+ static MemorySegment allocate(sdrplay_api_GetErrorString_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_GetErrorString_t.class, fi, constants$3.sdrplay_api_GetErrorString_t$FUNC, session);
+ }
+ static sdrplay_api_GetErrorString_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (int _err) -> {
+ try {
+ return (java.lang.foreign.Addressable)(java.lang.foreign.MemoryAddress)constants$3.sdrplay_api_GetErrorString_t$MH.invokeExact((Addressable)symbol, _err);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GetLastError_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GetLastError_t.java
new file mode 100644
index 000000000..582b28573
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_GetLastError_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_GetLastError_t {
+
+ java.lang.foreign.Addressable apply(java.lang.foreign.MemoryAddress device);
+ static MemorySegment allocate(sdrplay_api_GetLastError_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_GetLastError_t.class, fi, constants$3.sdrplay_api_GetLastError_t$FUNC, session);
+ }
+ static sdrplay_api_GetLastError_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _device) -> {
+ try {
+ return (java.lang.foreign.Addressable)(java.lang.foreign.MemoryAddress)constants$3.sdrplay_api_GetLastError_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_device);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Init_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Init_t.java
new file mode 100644
index 000000000..8a81e82d9
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Init_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_Init_t {
+
+ int apply(java.lang.foreign.MemoryAddress dev, java.lang.foreign.MemoryAddress callbackFns, java.lang.foreign.MemoryAddress cbContext);
+ static MemorySegment allocate(sdrplay_api_Init_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_Init_t.class, fi, constants$5.sdrplay_api_Init_t$FUNC, session);
+ }
+ static sdrplay_api_Init_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _dev, java.lang.foreign.MemoryAddress _callbackFns, java.lang.foreign.MemoryAddress _cbContext) -> {
+ try {
+ return (int)constants$5.sdrplay_api_Init_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_dev, (java.lang.foreign.Addressable)_callbackFns, (java.lang.foreign.Addressable)_cbContext);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_LockDeviceApi_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_LockDeviceApi_t.java
new file mode 100644
index 000000000..9a69199b3
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_LockDeviceApi_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_LockDeviceApi_t {
+
+ int apply();
+ static MemorySegment allocate(sdrplay_api_LockDeviceApi_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_LockDeviceApi_t.class, fi, constants$1.sdrplay_api_LockDeviceApi_t$FUNC, session);
+ }
+ static sdrplay_api_LockDeviceApi_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return () -> {
+ try {
+ return (int)constants$1.sdrplay_api_LockDeviceApi_t$MH.invokeExact((Addressable)symbol);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Open_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Open_t.java
new file mode 100644
index 000000000..d09836636
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Open_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_Open_t {
+
+ int apply();
+ static MemorySegment allocate(sdrplay_api_Open_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_Open_t.class, fi, constants$0.sdrplay_api_Open_t$FUNC, session);
+ }
+ static sdrplay_api_Open_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return () -> {
+ try {
+ return (int)constants$0.sdrplay_api_Open_t$MH.invokeExact((Addressable)symbol);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_PowerOverloadCbParamT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_PowerOverloadCbParamT.java
new file mode 100644
index 000000000..9a1a5d80f
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_PowerOverloadCbParamT.java
@@ -0,0 +1,44 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_PowerOverloadCbParamT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("powerOverloadChangeType")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_PowerOverloadCbParamT.$struct$LAYOUT;
+ }
+ static final VarHandle powerOverloadChangeType$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("powerOverloadChangeType"));
+ public static VarHandle powerOverloadChangeType$VH() {
+ return sdrplay_api_PowerOverloadCbParamT.powerOverloadChangeType$VH;
+ }
+ public static int powerOverloadChangeType$get(MemorySegment seg) {
+ return (int)sdrplay_api_PowerOverloadCbParamT.powerOverloadChangeType$VH.get(seg);
+ }
+ public static void powerOverloadChangeType$set( MemorySegment seg, int x) {
+ sdrplay_api_PowerOverloadCbParamT.powerOverloadChangeType$VH.set(seg, x);
+ }
+ public static int powerOverloadChangeType$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_PowerOverloadCbParamT.powerOverloadChangeType$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void powerOverloadChangeType$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_PowerOverloadCbParamT.powerOverloadChangeType$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_ReleaseDevice_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_ReleaseDevice_t.java
new file mode 100644
index 000000000..e5ae69066
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_ReleaseDevice_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_ReleaseDevice_t {
+
+ int apply(java.lang.foreign.MemoryAddress device);
+ static MemorySegment allocate(sdrplay_api_ReleaseDevice_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_ReleaseDevice_t.class, fi, constants$3.sdrplay_api_ReleaseDevice_t$FUNC, session);
+ }
+ static sdrplay_api_ReleaseDevice_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _device) -> {
+ try {
+ return (int)constants$3.sdrplay_api_ReleaseDevice_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_device);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_ResetFlagsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_ResetFlagsT.java
new file mode 100644
index 000000000..30399c091
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_ResetFlagsT.java
@@ -0,0 +1,78 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_ResetFlagsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("resetGainUpdate"),
+ Constants$root.C_CHAR$LAYOUT.withName("resetRfUpdate"),
+ Constants$root.C_CHAR$LAYOUT.withName("resetFsUpdate")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_ResetFlagsT.$struct$LAYOUT;
+ }
+ static final VarHandle resetGainUpdate$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("resetGainUpdate"));
+ public static VarHandle resetGainUpdate$VH() {
+ return sdrplay_api_ResetFlagsT.resetGainUpdate$VH;
+ }
+ public static byte resetGainUpdate$get(MemorySegment seg) {
+ return (byte)sdrplay_api_ResetFlagsT.resetGainUpdate$VH.get(seg);
+ }
+ public static void resetGainUpdate$set( MemorySegment seg, byte x) {
+ sdrplay_api_ResetFlagsT.resetGainUpdate$VH.set(seg, x);
+ }
+ public static byte resetGainUpdate$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_ResetFlagsT.resetGainUpdate$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void resetGainUpdate$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_ResetFlagsT.resetGainUpdate$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle resetRfUpdate$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("resetRfUpdate"));
+ public static VarHandle resetRfUpdate$VH() {
+ return sdrplay_api_ResetFlagsT.resetRfUpdate$VH;
+ }
+ public static byte resetRfUpdate$get(MemorySegment seg) {
+ return (byte)sdrplay_api_ResetFlagsT.resetRfUpdate$VH.get(seg);
+ }
+ public static void resetRfUpdate$set( MemorySegment seg, byte x) {
+ sdrplay_api_ResetFlagsT.resetRfUpdate$VH.set(seg, x);
+ }
+ public static byte resetRfUpdate$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_ResetFlagsT.resetRfUpdate$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void resetRfUpdate$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_ResetFlagsT.resetRfUpdate$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle resetFsUpdate$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("resetFsUpdate"));
+ public static VarHandle resetFsUpdate$VH() {
+ return sdrplay_api_ResetFlagsT.resetFsUpdate$VH;
+ }
+ public static byte resetFsUpdate$get(MemorySegment seg) {
+ return (byte)sdrplay_api_ResetFlagsT.resetFsUpdate$VH.get(seg);
+ }
+ public static void resetFsUpdate$set( MemorySegment seg, byte x) {
+ sdrplay_api_ResetFlagsT.resetFsUpdate$VH.set(seg, x);
+ }
+ public static byte resetFsUpdate$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_ResetFlagsT.resetFsUpdate$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void resetFsUpdate$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_ResetFlagsT.resetFsUpdate$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RfFreqT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RfFreqT.java
new file mode 100644
index 000000000..7dbeb6781
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RfFreqT.java
@@ -0,0 +1,62 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_RfFreqT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_DOUBLE$LAYOUT.withName("rfHz"),
+ Constants$root.C_CHAR$LAYOUT.withName("syncUpdate"),
+ MemoryLayout.paddingLayout(56)
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_RfFreqT.$struct$LAYOUT;
+ }
+ static final VarHandle rfHz$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfHz"));
+ public static VarHandle rfHz$VH() {
+ return sdrplay_api_RfFreqT.rfHz$VH;
+ }
+ public static double rfHz$get(MemorySegment seg) {
+ return (double)sdrplay_api_RfFreqT.rfHz$VH.get(seg);
+ }
+ public static void rfHz$set( MemorySegment seg, double x) {
+ sdrplay_api_RfFreqT.rfHz$VH.set(seg, x);
+ }
+ public static double rfHz$get(MemorySegment seg, long index) {
+ return (double)sdrplay_api_RfFreqT.rfHz$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfHz$set(MemorySegment seg, long index, double x) {
+ sdrplay_api_RfFreqT.rfHz$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle syncUpdate$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("syncUpdate"));
+ public static VarHandle syncUpdate$VH() {
+ return sdrplay_api_RfFreqT.syncUpdate$VH;
+ }
+ public static byte syncUpdate$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RfFreqT.syncUpdate$VH.get(seg);
+ }
+ public static void syncUpdate$set( MemorySegment seg, byte x) {
+ sdrplay_api_RfFreqT.syncUpdate$VH.set(seg, x);
+ }
+ public static byte syncUpdate$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RfFreqT.syncUpdate$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void syncUpdate$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RfFreqT.syncUpdate$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Rsp1aParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Rsp1aParamsT.java
new file mode 100644
index 000000000..230048e6c
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Rsp1aParamsT.java
@@ -0,0 +1,61 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_Rsp1aParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("rfNotchEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfDabNotchEnable")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_Rsp1aParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle rfNotchEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfNotchEnable"));
+ public static VarHandle rfNotchEnable$VH() {
+ return sdrplay_api_Rsp1aParamsT.rfNotchEnable$VH;
+ }
+ public static byte rfNotchEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_Rsp1aParamsT.rfNotchEnable$VH.get(seg);
+ }
+ public static void rfNotchEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_Rsp1aParamsT.rfNotchEnable$VH.set(seg, x);
+ }
+ public static byte rfNotchEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_Rsp1aParamsT.rfNotchEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfNotchEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_Rsp1aParamsT.rfNotchEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rfDabNotchEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfDabNotchEnable"));
+ public static VarHandle rfDabNotchEnable$VH() {
+ return sdrplay_api_Rsp1aParamsT.rfDabNotchEnable$VH;
+ }
+ public static byte rfDabNotchEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_Rsp1aParamsT.rfDabNotchEnable$VH.get(seg);
+ }
+ public static void rfDabNotchEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_Rsp1aParamsT.rfDabNotchEnable$VH.set(seg, x);
+ }
+ public static byte rfDabNotchEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_Rsp1aParamsT.rfDabNotchEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfDabNotchEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_Rsp1aParamsT.rfDabNotchEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Rsp1aTunerParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Rsp1aTunerParamsT.java
new file mode 100644
index 000000000..a2139d913
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Rsp1aTunerParamsT.java
@@ -0,0 +1,44 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_Rsp1aTunerParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("biasTEnable")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_Rsp1aTunerParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle biasTEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("biasTEnable"));
+ public static VarHandle biasTEnable$VH() {
+ return sdrplay_api_Rsp1aTunerParamsT.biasTEnable$VH;
+ }
+ public static byte biasTEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_Rsp1aTunerParamsT.biasTEnable$VH.get(seg);
+ }
+ public static void biasTEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_Rsp1aTunerParamsT.biasTEnable$VH.set(seg, x);
+ }
+ public static byte biasTEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_Rsp1aTunerParamsT.biasTEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void biasTEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_Rsp1aTunerParamsT.biasTEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Rsp2ParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Rsp2ParamsT.java
new file mode 100644
index 000000000..9894d3751
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Rsp2ParamsT.java
@@ -0,0 +1,44 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_Rsp2ParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("extRefOutputEn")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_Rsp2ParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle extRefOutputEn$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("extRefOutputEn"));
+ public static VarHandle extRefOutputEn$VH() {
+ return sdrplay_api_Rsp2ParamsT.extRefOutputEn$VH;
+ }
+ public static byte extRefOutputEn$get(MemorySegment seg) {
+ return (byte)sdrplay_api_Rsp2ParamsT.extRefOutputEn$VH.get(seg);
+ }
+ public static void extRefOutputEn$set( MemorySegment seg, byte x) {
+ sdrplay_api_Rsp2ParamsT.extRefOutputEn$VH.set(seg, x);
+ }
+ public static byte extRefOutputEn$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_Rsp2ParamsT.extRefOutputEn$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void extRefOutputEn$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_Rsp2ParamsT.extRefOutputEn$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Rsp2TunerParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Rsp2TunerParamsT.java
new file mode 100644
index 000000000..0943f422d
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Rsp2TunerParamsT.java
@@ -0,0 +1,97 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_Rsp2TunerParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("biasTEnable"),
+ MemoryLayout.paddingLayout(24),
+ Constants$root.C_LONG$LAYOUT.withName("amPortSel"),
+ Constants$root.C_LONG$LAYOUT.withName("antennaSel"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfNotchEnable"),
+ MemoryLayout.paddingLayout(24)
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_Rsp2TunerParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle biasTEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("biasTEnable"));
+ public static VarHandle biasTEnable$VH() {
+ return sdrplay_api_Rsp2TunerParamsT.biasTEnable$VH;
+ }
+ public static byte biasTEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_Rsp2TunerParamsT.biasTEnable$VH.get(seg);
+ }
+ public static void biasTEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_Rsp2TunerParamsT.biasTEnable$VH.set(seg, x);
+ }
+ public static byte biasTEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_Rsp2TunerParamsT.biasTEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void biasTEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_Rsp2TunerParamsT.biasTEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle amPortSel$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("amPortSel"));
+ public static VarHandle amPortSel$VH() {
+ return sdrplay_api_Rsp2TunerParamsT.amPortSel$VH;
+ }
+ public static int amPortSel$get(MemorySegment seg) {
+ return (int)sdrplay_api_Rsp2TunerParamsT.amPortSel$VH.get(seg);
+ }
+ public static void amPortSel$set( MemorySegment seg, int x) {
+ sdrplay_api_Rsp2TunerParamsT.amPortSel$VH.set(seg, x);
+ }
+ public static int amPortSel$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_Rsp2TunerParamsT.amPortSel$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void amPortSel$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_Rsp2TunerParamsT.amPortSel$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle antennaSel$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("antennaSel"));
+ public static VarHandle antennaSel$VH() {
+ return sdrplay_api_Rsp2TunerParamsT.antennaSel$VH;
+ }
+ public static int antennaSel$get(MemorySegment seg) {
+ return (int)sdrplay_api_Rsp2TunerParamsT.antennaSel$VH.get(seg);
+ }
+ public static void antennaSel$set( MemorySegment seg, int x) {
+ sdrplay_api_Rsp2TunerParamsT.antennaSel$VH.set(seg, x);
+ }
+ public static int antennaSel$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_Rsp2TunerParamsT.antennaSel$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void antennaSel$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_Rsp2TunerParamsT.antennaSel$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rfNotchEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfNotchEnable"));
+ public static VarHandle rfNotchEnable$VH() {
+ return sdrplay_api_Rsp2TunerParamsT.rfNotchEnable$VH;
+ }
+ public static byte rfNotchEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_Rsp2TunerParamsT.rfNotchEnable$VH.get(seg);
+ }
+ public static void rfNotchEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_Rsp2TunerParamsT.rfNotchEnable$VH.set(seg, x);
+ }
+ public static byte rfNotchEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_Rsp2TunerParamsT.rfNotchEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfNotchEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_Rsp2TunerParamsT.rfNotchEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RspDuoModeCbParamT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RspDuoModeCbParamT.java
new file mode 100644
index 000000000..e874cf37c
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RspDuoModeCbParamT.java
@@ -0,0 +1,44 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_RspDuoModeCbParamT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("modeChangeType")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_RspDuoModeCbParamT.$struct$LAYOUT;
+ }
+ static final VarHandle modeChangeType$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("modeChangeType"));
+ public static VarHandle modeChangeType$VH() {
+ return sdrplay_api_RspDuoModeCbParamT.modeChangeType$VH;
+ }
+ public static int modeChangeType$get(MemorySegment seg) {
+ return (int)sdrplay_api_RspDuoModeCbParamT.modeChangeType$VH.get(seg);
+ }
+ public static void modeChangeType$set( MemorySegment seg, int x) {
+ sdrplay_api_RspDuoModeCbParamT.modeChangeType$VH.set(seg, x);
+ }
+ public static int modeChangeType$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_RspDuoModeCbParamT.modeChangeType$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void modeChangeType$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_RspDuoModeCbParamT.modeChangeType$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RspDuoParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RspDuoParamsT.java
new file mode 100644
index 000000000..320ef4c95
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RspDuoParamsT.java
@@ -0,0 +1,44 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_RspDuoParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("extRefOutputEn")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_RspDuoParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle extRefOutputEn$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("extRefOutputEn"));
+ public static VarHandle extRefOutputEn$VH() {
+ return sdrplay_api_RspDuoParamsT.extRefOutputEn$VH;
+ }
+ public static int extRefOutputEn$get(MemorySegment seg) {
+ return (int)sdrplay_api_RspDuoParamsT.extRefOutputEn$VH.get(seg);
+ }
+ public static void extRefOutputEn$set( MemorySegment seg, int x) {
+ sdrplay_api_RspDuoParamsT.extRefOutputEn$VH.set(seg, x);
+ }
+ public static int extRefOutputEn$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_RspDuoParamsT.extRefOutputEn$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void extRefOutputEn$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_RspDuoParamsT.extRefOutputEn$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RspDuoTunerParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RspDuoTunerParamsT.java
new file mode 100644
index 000000000..b22abff47
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RspDuoTunerParamsT.java
@@ -0,0 +1,114 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_RspDuoTunerParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("biasTEnable"),
+ MemoryLayout.paddingLayout(24),
+ Constants$root.C_LONG$LAYOUT.withName("tuner1AmPortSel"),
+ Constants$root.C_CHAR$LAYOUT.withName("tuner1AmNotchEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfNotchEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfDabNotchEnable"),
+ MemoryLayout.paddingLayout(8)
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_RspDuoTunerParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle biasTEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("biasTEnable"));
+ public static VarHandle biasTEnable$VH() {
+ return sdrplay_api_RspDuoTunerParamsT.biasTEnable$VH;
+ }
+ public static byte biasTEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RspDuoTunerParamsT.biasTEnable$VH.get(seg);
+ }
+ public static void biasTEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_RspDuoTunerParamsT.biasTEnable$VH.set(seg, x);
+ }
+ public static byte biasTEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RspDuoTunerParamsT.biasTEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void biasTEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RspDuoTunerParamsT.biasTEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle tuner1AmPortSel$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("tuner1AmPortSel"));
+ public static VarHandle tuner1AmPortSel$VH() {
+ return sdrplay_api_RspDuoTunerParamsT.tuner1AmPortSel$VH;
+ }
+ public static int tuner1AmPortSel$get(MemorySegment seg) {
+ return (int)sdrplay_api_RspDuoTunerParamsT.tuner1AmPortSel$VH.get(seg);
+ }
+ public static void tuner1AmPortSel$set( MemorySegment seg, int x) {
+ sdrplay_api_RspDuoTunerParamsT.tuner1AmPortSel$VH.set(seg, x);
+ }
+ public static int tuner1AmPortSel$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_RspDuoTunerParamsT.tuner1AmPortSel$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void tuner1AmPortSel$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_RspDuoTunerParamsT.tuner1AmPortSel$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle tuner1AmNotchEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("tuner1AmNotchEnable"));
+ public static VarHandle tuner1AmNotchEnable$VH() {
+ return sdrplay_api_RspDuoTunerParamsT.tuner1AmNotchEnable$VH;
+ }
+ public static byte tuner1AmNotchEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RspDuoTunerParamsT.tuner1AmNotchEnable$VH.get(seg);
+ }
+ public static void tuner1AmNotchEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_RspDuoTunerParamsT.tuner1AmNotchEnable$VH.set(seg, x);
+ }
+ public static byte tuner1AmNotchEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RspDuoTunerParamsT.tuner1AmNotchEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void tuner1AmNotchEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RspDuoTunerParamsT.tuner1AmNotchEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rfNotchEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfNotchEnable"));
+ public static VarHandle rfNotchEnable$VH() {
+ return sdrplay_api_RspDuoTunerParamsT.rfNotchEnable$VH;
+ }
+ public static byte rfNotchEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RspDuoTunerParamsT.rfNotchEnable$VH.get(seg);
+ }
+ public static void rfNotchEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_RspDuoTunerParamsT.rfNotchEnable$VH.set(seg, x);
+ }
+ public static byte rfNotchEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RspDuoTunerParamsT.rfNotchEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfNotchEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RspDuoTunerParamsT.rfNotchEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rfDabNotchEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfDabNotchEnable"));
+ public static VarHandle rfDabNotchEnable$VH() {
+ return sdrplay_api_RspDuoTunerParamsT.rfDabNotchEnable$VH;
+ }
+ public static byte rfDabNotchEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RspDuoTunerParamsT.rfDabNotchEnable$VH.get(seg);
+ }
+ public static void rfDabNotchEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_RspDuoTunerParamsT.rfDabNotchEnable$VH.set(seg, x);
+ }
+ public static byte rfDabNotchEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RspDuoTunerParamsT.rfDabNotchEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfDabNotchEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RspDuoTunerParamsT.rfDabNotchEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RspDxParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RspDxParamsT.java
new file mode 100644
index 000000000..a64be491b
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RspDxParamsT.java
@@ -0,0 +1,114 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_RspDxParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("hdrEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("biasTEnable"),
+ MemoryLayout.paddingLayout(16),
+ Constants$root.C_LONG$LAYOUT.withName("antennaSel"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfNotchEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfDabNotchEnable"),
+ MemoryLayout.paddingLayout(16)
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_RspDxParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle hdrEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("hdrEnable"));
+ public static VarHandle hdrEnable$VH() {
+ return sdrplay_api_RspDxParamsT.hdrEnable$VH;
+ }
+ public static byte hdrEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RspDxParamsT.hdrEnable$VH.get(seg);
+ }
+ public static void hdrEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_RspDxParamsT.hdrEnable$VH.set(seg, x);
+ }
+ public static byte hdrEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RspDxParamsT.hdrEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void hdrEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RspDxParamsT.hdrEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle biasTEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("biasTEnable"));
+ public static VarHandle biasTEnable$VH() {
+ return sdrplay_api_RspDxParamsT.biasTEnable$VH;
+ }
+ public static byte biasTEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RspDxParamsT.biasTEnable$VH.get(seg);
+ }
+ public static void biasTEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_RspDxParamsT.biasTEnable$VH.set(seg, x);
+ }
+ public static byte biasTEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RspDxParamsT.biasTEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void biasTEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RspDxParamsT.biasTEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle antennaSel$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("antennaSel"));
+ public static VarHandle antennaSel$VH() {
+ return sdrplay_api_RspDxParamsT.antennaSel$VH;
+ }
+ public static int antennaSel$get(MemorySegment seg) {
+ return (int)sdrplay_api_RspDxParamsT.antennaSel$VH.get(seg);
+ }
+ public static void antennaSel$set( MemorySegment seg, int x) {
+ sdrplay_api_RspDxParamsT.antennaSel$VH.set(seg, x);
+ }
+ public static int antennaSel$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_RspDxParamsT.antennaSel$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void antennaSel$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_RspDxParamsT.antennaSel$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rfNotchEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfNotchEnable"));
+ public static VarHandle rfNotchEnable$VH() {
+ return sdrplay_api_RspDxParamsT.rfNotchEnable$VH;
+ }
+ public static byte rfNotchEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RspDxParamsT.rfNotchEnable$VH.get(seg);
+ }
+ public static void rfNotchEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_RspDxParamsT.rfNotchEnable$VH.set(seg, x);
+ }
+ public static byte rfNotchEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RspDxParamsT.rfNotchEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfNotchEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RspDxParamsT.rfNotchEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rfDabNotchEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfDabNotchEnable"));
+ public static VarHandle rfDabNotchEnable$VH() {
+ return sdrplay_api_RspDxParamsT.rfDabNotchEnable$VH;
+ }
+ public static byte rfDabNotchEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RspDxParamsT.rfDabNotchEnable$VH.get(seg);
+ }
+ public static void rfDabNotchEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_RspDxParamsT.rfDabNotchEnable$VH.set(seg, x);
+ }
+ public static byte rfDabNotchEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RspDxParamsT.rfDabNotchEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfDabNotchEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RspDxParamsT.rfDabNotchEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RspDxTunerParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RspDxTunerParamsT.java
new file mode 100644
index 000000000..531b614a3
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RspDxTunerParamsT.java
@@ -0,0 +1,44 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_RspDxTunerParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("hdrBw")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_RspDxTunerParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle hdrBw$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("hdrBw"));
+ public static VarHandle hdrBw$VH() {
+ return sdrplay_api_RspDxTunerParamsT.hdrBw$VH;
+ }
+ public static int hdrBw$get(MemorySegment seg) {
+ return (int)sdrplay_api_RspDxTunerParamsT.hdrBw$VH.get(seg);
+ }
+ public static void hdrBw$set( MemorySegment seg, int x) {
+ sdrplay_api_RspDxTunerParamsT.hdrBw$VH.set(seg, x);
+ }
+ public static int hdrBw$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_RspDxTunerParamsT.hdrBw$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void hdrBw$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_RspDxTunerParamsT.hdrBw$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RxChannelParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RxChannelParamsT.java
new file mode 100644
index 000000000..1a374f7ab
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_RxChannelParamsT.java
@@ -0,0 +1,122 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+public class sdrplay_api_RxChannelParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("bwType"),
+ Constants$root.C_LONG$LAYOUT.withName("ifType"),
+ Constants$root.C_LONG$LAYOUT.withName("loMode"),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("gRdB"),
+ Constants$root.C_CHAR$LAYOUT.withName("LNAstate"),
+ Constants$root.C_CHAR$LAYOUT.withName("syncUpdate"),
+ MemoryLayout.paddingLayout(16),
+ Constants$root.C_LONG$LAYOUT.withName("minGr"),
+ MemoryLayout.structLayout(
+ Constants$root.C_FLOAT$LAYOUT.withName("curr"),
+ Constants$root.C_FLOAT$LAYOUT.withName("max"),
+ Constants$root.C_FLOAT$LAYOUT.withName("min")
+ ).withName("gainVals")
+ ).withName("gain"),
+ MemoryLayout.paddingLayout(32),
+ MemoryLayout.structLayout(
+ Constants$root.C_DOUBLE$LAYOUT.withName("rfHz"),
+ Constants$root.C_CHAR$LAYOUT.withName("syncUpdate"),
+ MemoryLayout.paddingLayout(56)
+ ).withName("rfFreq"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("dcCal"),
+ Constants$root.C_CHAR$LAYOUT.withName("speedUp"),
+ MemoryLayout.paddingLayout(16),
+ Constants$root.C_LONG$LAYOUT.withName("trackTime"),
+ Constants$root.C_LONG$LAYOUT.withName("refreshRateTime")
+ ).withName("dcOffsetTuner"),
+ MemoryLayout.paddingLayout(32)
+ ).withName("tunerParams"),
+ MemoryLayout.structLayout(
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("DCenable"),
+ Constants$root.C_CHAR$LAYOUT.withName("IQenable")
+ ).withName("dcOffset"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("enable"),
+ Constants$root.C_CHAR$LAYOUT.withName("decimationFactor"),
+ Constants$root.C_CHAR$LAYOUT.withName("wideBandSignal")
+ ).withName("decimation"),
+ MemoryLayout.paddingLayout(24),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("enable"),
+ Constants$root.C_LONG$LAYOUT.withName("setPoint_dBfs"),
+ Constants$root.C_SHORT$LAYOUT.withName("attack_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_delay_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_threshold_dB"),
+ Constants$root.C_LONG$LAYOUT.withName("syncUpdate")
+ ).withName("agc"),
+ Constants$root.C_LONG$LAYOUT.withName("adsbMode")
+ ).withName("ctrlParams"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("biasTEnable")
+ ).withName("rsp1aTunerParams"),
+ MemoryLayout.paddingLayout(24),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("biasTEnable"),
+ MemoryLayout.paddingLayout(24),
+ Constants$root.C_LONG$LAYOUT.withName("amPortSel"),
+ Constants$root.C_LONG$LAYOUT.withName("antennaSel"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfNotchEnable"),
+ MemoryLayout.paddingLayout(24)
+ ).withName("rsp2TunerParams"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("biasTEnable"),
+ MemoryLayout.paddingLayout(24),
+ Constants$root.C_LONG$LAYOUT.withName("tuner1AmPortSel"),
+ Constants$root.C_CHAR$LAYOUT.withName("tuner1AmNotchEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfNotchEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfDabNotchEnable"),
+ MemoryLayout.paddingLayout(8)
+ ).withName("rspDuoTunerParams"),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("hdrBw")
+ ).withName("rspDxTunerParams"),
+ MemoryLayout.paddingLayout(32)
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_RxChannelParamsT.$struct$LAYOUT;
+ }
+ public static MemorySegment tunerParams$slice(MemorySegment seg) {
+ return seg.asSlice(0, 72);
+ }
+ public static MemorySegment ctrlParams$slice(MemorySegment seg) {
+ return seg.asSlice(72, 32);
+ }
+ public static MemorySegment rsp1aTunerParams$slice(MemorySegment seg) {
+ return seg.asSlice(104, 1);
+ }
+ public static MemorySegment rsp2TunerParams$slice(MemorySegment seg) {
+ return seg.asSlice(108, 16);
+ }
+ public static MemorySegment rspDuoTunerParams$slice(MemorySegment seg) {
+ return seg.asSlice(124, 12);
+ }
+ public static MemorySegment rspDxTunerParams$slice(MemorySegment seg) {
+ return seg.asSlice(136, 4);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_SelectDevice_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_SelectDevice_t.java
new file mode 100644
index 000000000..8e20a84da
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_SelectDevice_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_SelectDevice_t {
+
+ int apply(java.lang.foreign.MemoryAddress device);
+ static MemorySegment allocate(sdrplay_api_SelectDevice_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_SelectDevice_t.class, fi, constants$2.sdrplay_api_SelectDevice_t$FUNC, session);
+ }
+ static sdrplay_api_SelectDevice_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _device) -> {
+ try {
+ return (int)constants$2.sdrplay_api_SelectDevice_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_device);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_StreamCallback_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_StreamCallback_t.java
new file mode 100644
index 000000000..36af2f587
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_StreamCallback_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_StreamCallback_t {
+
+ void apply(java.lang.foreign.MemoryAddress xi, java.lang.foreign.MemoryAddress xq, java.lang.foreign.MemoryAddress params, int numSamples, int reset, java.lang.foreign.MemoryAddress cbContext);
+ static MemorySegment allocate(sdrplay_api_StreamCallback_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_StreamCallback_t.class, fi, constants$0.sdrplay_api_StreamCallback_t$FUNC, session);
+ }
+ static sdrplay_api_StreamCallback_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _xi, java.lang.foreign.MemoryAddress _xq, java.lang.foreign.MemoryAddress _params, int _numSamples, int _reset, java.lang.foreign.MemoryAddress _cbContext) -> {
+ try {
+ constants$0.sdrplay_api_StreamCallback_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_xi, (java.lang.foreign.Addressable)_xq, (java.lang.foreign.Addressable)_params, _numSamples, _reset, (java.lang.foreign.Addressable)_cbContext);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_StreamCbParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_StreamCbParamsT.java
new file mode 100644
index 000000000..ef2805a71
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_StreamCbParamsT.java
@@ -0,0 +1,112 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_StreamCbParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("firstSampleNum"),
+ Constants$root.C_LONG$LAYOUT.withName("grChanged"),
+ Constants$root.C_LONG$LAYOUT.withName("rfChanged"),
+ Constants$root.C_LONG$LAYOUT.withName("fsChanged"),
+ Constants$root.C_LONG$LAYOUT.withName("numSamples")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_StreamCbParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle firstSampleNum$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("firstSampleNum"));
+ public static VarHandle firstSampleNum$VH() {
+ return sdrplay_api_StreamCbParamsT.firstSampleNum$VH;
+ }
+ public static int firstSampleNum$get(MemorySegment seg) {
+ return (int)sdrplay_api_StreamCbParamsT.firstSampleNum$VH.get(seg);
+ }
+ public static void firstSampleNum$set( MemorySegment seg, int x) {
+ sdrplay_api_StreamCbParamsT.firstSampleNum$VH.set(seg, x);
+ }
+ public static int firstSampleNum$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_StreamCbParamsT.firstSampleNum$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void firstSampleNum$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_StreamCbParamsT.firstSampleNum$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle grChanged$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("grChanged"));
+ public static VarHandle grChanged$VH() {
+ return sdrplay_api_StreamCbParamsT.grChanged$VH;
+ }
+ public static int grChanged$get(MemorySegment seg) {
+ return (int)sdrplay_api_StreamCbParamsT.grChanged$VH.get(seg);
+ }
+ public static void grChanged$set( MemorySegment seg, int x) {
+ sdrplay_api_StreamCbParamsT.grChanged$VH.set(seg, x);
+ }
+ public static int grChanged$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_StreamCbParamsT.grChanged$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void grChanged$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_StreamCbParamsT.grChanged$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rfChanged$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfChanged"));
+ public static VarHandle rfChanged$VH() {
+ return sdrplay_api_StreamCbParamsT.rfChanged$VH;
+ }
+ public static int rfChanged$get(MemorySegment seg) {
+ return (int)sdrplay_api_StreamCbParamsT.rfChanged$VH.get(seg);
+ }
+ public static void rfChanged$set( MemorySegment seg, int x) {
+ sdrplay_api_StreamCbParamsT.rfChanged$VH.set(seg, x);
+ }
+ public static int rfChanged$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_StreamCbParamsT.rfChanged$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfChanged$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_StreamCbParamsT.rfChanged$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle fsChanged$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("fsChanged"));
+ public static VarHandle fsChanged$VH() {
+ return sdrplay_api_StreamCbParamsT.fsChanged$VH;
+ }
+ public static int fsChanged$get(MemorySegment seg) {
+ return (int)sdrplay_api_StreamCbParamsT.fsChanged$VH.get(seg);
+ }
+ public static void fsChanged$set( MemorySegment seg, int x) {
+ sdrplay_api_StreamCbParamsT.fsChanged$VH.set(seg, x);
+ }
+ public static int fsChanged$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_StreamCbParamsT.fsChanged$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void fsChanged$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_StreamCbParamsT.fsChanged$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle numSamples$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("numSamples"));
+ public static VarHandle numSamples$VH() {
+ return sdrplay_api_StreamCbParamsT.numSamples$VH;
+ }
+ public static int numSamples$get(MemorySegment seg) {
+ return (int)sdrplay_api_StreamCbParamsT.numSamples$VH.get(seg);
+ }
+ public static void numSamples$set( MemorySegment seg, int x) {
+ sdrplay_api_StreamCbParamsT.numSamples$VH.set(seg, x);
+ }
+ public static int numSamples$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_StreamCbParamsT.numSamples$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void numSamples$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_StreamCbParamsT.numSamples$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_SwapRspDuoActiveTuner_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_SwapRspDuoActiveTuner_t.java
new file mode 100644
index 000000000..83798c8fa
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_SwapRspDuoActiveTuner_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_SwapRspDuoActiveTuner_t {
+
+ int apply(java.lang.foreign.MemoryAddress dev, java.lang.foreign.MemoryAddress tuner, int tuner1AmPortSel);
+ static MemorySegment allocate(sdrplay_api_SwapRspDuoActiveTuner_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_SwapRspDuoActiveTuner_t.class, fi, constants$6.sdrplay_api_SwapRspDuoActiveTuner_t$FUNC, session);
+ }
+ static sdrplay_api_SwapRspDuoActiveTuner_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _dev, java.lang.foreign.MemoryAddress _tuner, int _tuner1AmPortSel) -> {
+ try {
+ return (int)constants$6.sdrplay_api_SwapRspDuoActiveTuner_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_dev, (java.lang.foreign.Addressable)_tuner, _tuner1AmPortSel);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t.java
new file mode 100644
index 000000000..1f496ba29
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t {
+
+ int apply(java.lang.foreign.MemoryAddress currentSampleRate);
+ static MemorySegment allocate(sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t.class, fi, constants$6.sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t$FUNC, session);
+ }
+ static sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _currentSampleRate) -> {
+ try {
+ return (int)constants$6.sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_currentSampleRate);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_SwapRspDuoMode_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_SwapRspDuoMode_t.java
new file mode 100644
index 000000000..707a59dc8
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_SwapRspDuoMode_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_SwapRspDuoMode_t {
+
+ int apply(java.lang.foreign.MemoryAddress currDevice, java.lang.foreign.MemoryAddress deviceParams, int rspDuoMode, double sampleRate, int tuner, int bwType, int ifType, int tuner1AmPortSel);
+ static MemorySegment allocate(sdrplay_api_SwapRspDuoMode_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_SwapRspDuoMode_t.class, fi, constants$6.sdrplay_api_SwapRspDuoMode_t$FUNC, session);
+ }
+ static sdrplay_api_SwapRspDuoMode_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _currDevice, java.lang.foreign.MemoryAddress _deviceParams, int _rspDuoMode, double _sampleRate, int _tuner, int _bwType, int _ifType, int _tuner1AmPortSel) -> {
+ try {
+ return (int)constants$6.sdrplay_api_SwapRspDuoMode_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_currDevice, (java.lang.foreign.Addressable)_deviceParams, _rspDuoMode, _sampleRate, _tuner, _bwType, _ifType, _tuner1AmPortSel);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_SyncUpdateT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_SyncUpdateT.java
new file mode 100644
index 000000000..d60d8d484
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_SyncUpdateT.java
@@ -0,0 +1,61 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_SyncUpdateT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("sampleNum"),
+ Constants$root.C_LONG$LAYOUT.withName("period")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_SyncUpdateT.$struct$LAYOUT;
+ }
+ static final VarHandle sampleNum$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("sampleNum"));
+ public static VarHandle sampleNum$VH() {
+ return sdrplay_api_SyncUpdateT.sampleNum$VH;
+ }
+ public static int sampleNum$get(MemorySegment seg) {
+ return (int)sdrplay_api_SyncUpdateT.sampleNum$VH.get(seg);
+ }
+ public static void sampleNum$set( MemorySegment seg, int x) {
+ sdrplay_api_SyncUpdateT.sampleNum$VH.set(seg, x);
+ }
+ public static int sampleNum$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_SyncUpdateT.sampleNum$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void sampleNum$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_SyncUpdateT.sampleNum$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle period$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("period"));
+ public static VarHandle period$VH() {
+ return sdrplay_api_SyncUpdateT.period$VH;
+ }
+ public static int period$get(MemorySegment seg) {
+ return (int)sdrplay_api_SyncUpdateT.period$VH.get(seg);
+ }
+ public static void period$set( MemorySegment seg, int x) {
+ sdrplay_api_SyncUpdateT.period$VH.set(seg, x);
+ }
+ public static int period$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_SyncUpdateT.period$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void period$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_SyncUpdateT.period$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_TunerParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_TunerParamsT.java
new file mode 100644
index 000000000..1a946c66e
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_TunerParamsT.java
@@ -0,0 +1,113 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_TunerParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("bwType"),
+ Constants$root.C_LONG$LAYOUT.withName("ifType"),
+ Constants$root.C_LONG$LAYOUT.withName("loMode"),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("gRdB"),
+ Constants$root.C_CHAR$LAYOUT.withName("LNAstate"),
+ Constants$root.C_CHAR$LAYOUT.withName("syncUpdate"),
+ MemoryLayout.paddingLayout(16),
+ Constants$root.C_LONG$LAYOUT.withName("minGr"),
+ MemoryLayout.structLayout(
+ Constants$root.C_FLOAT$LAYOUT.withName("curr"),
+ Constants$root.C_FLOAT$LAYOUT.withName("max"),
+ Constants$root.C_FLOAT$LAYOUT.withName("min")
+ ).withName("gainVals")
+ ).withName("gain"),
+ MemoryLayout.paddingLayout(32),
+ MemoryLayout.structLayout(
+ Constants$root.C_DOUBLE$LAYOUT.withName("rfHz"),
+ Constants$root.C_CHAR$LAYOUT.withName("syncUpdate"),
+ MemoryLayout.paddingLayout(56)
+ ).withName("rfFreq"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("dcCal"),
+ Constants$root.C_CHAR$LAYOUT.withName("speedUp"),
+ MemoryLayout.paddingLayout(16),
+ Constants$root.C_LONG$LAYOUT.withName("trackTime"),
+ Constants$root.C_LONG$LAYOUT.withName("refreshRateTime")
+ ).withName("dcOffsetTuner"),
+ MemoryLayout.paddingLayout(32)
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_TunerParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle bwType$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("bwType"));
+ public static VarHandle bwType$VH() {
+ return sdrplay_api_TunerParamsT.bwType$VH;
+ }
+ public static int bwType$get(MemorySegment seg) {
+ return (int)sdrplay_api_TunerParamsT.bwType$VH.get(seg);
+ }
+ public static void bwType$set( MemorySegment seg, int x) {
+ sdrplay_api_TunerParamsT.bwType$VH.set(seg, x);
+ }
+ public static int bwType$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_TunerParamsT.bwType$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void bwType$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_TunerParamsT.bwType$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle ifType$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("ifType"));
+ public static VarHandle ifType$VH() {
+ return sdrplay_api_TunerParamsT.ifType$VH;
+ }
+ public static int ifType$get(MemorySegment seg) {
+ return (int)sdrplay_api_TunerParamsT.ifType$VH.get(seg);
+ }
+ public static void ifType$set( MemorySegment seg, int x) {
+ sdrplay_api_TunerParamsT.ifType$VH.set(seg, x);
+ }
+ public static int ifType$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_TunerParamsT.ifType$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void ifType$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_TunerParamsT.ifType$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle loMode$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("loMode"));
+ public static VarHandle loMode$VH() {
+ return sdrplay_api_TunerParamsT.loMode$VH;
+ }
+ public static int loMode$get(MemorySegment seg) {
+ return (int)sdrplay_api_TunerParamsT.loMode$VH.get(seg);
+ }
+ public static void loMode$set( MemorySegment seg, int x) {
+ sdrplay_api_TunerParamsT.loMode$VH.set(seg, x);
+ }
+ public static int loMode$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_TunerParamsT.loMode$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void loMode$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_TunerParamsT.loMode$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static MemorySegment gain$slice(MemorySegment seg) {
+ return seg.asSlice(12, 24);
+ }
+ public static MemorySegment rfFreq$slice(MemorySegment seg) {
+ return seg.asSlice(40, 16);
+ }
+ public static MemorySegment dcOffsetTuner$slice(MemorySegment seg) {
+ return seg.asSlice(56, 12);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Uninit_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Uninit_t.java
new file mode 100644
index 000000000..8b5ed1cd7
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Uninit_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_Uninit_t {
+
+ int apply(java.lang.foreign.MemoryAddress dev);
+ static MemorySegment allocate(sdrplay_api_Uninit_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_Uninit_t.class, fi, constants$5.sdrplay_api_Uninit_t$FUNC, session);
+ }
+ static sdrplay_api_Uninit_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _dev) -> {
+ try {
+ return (int)constants$5.sdrplay_api_Uninit_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_dev);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_UnlockDeviceApi_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_UnlockDeviceApi_t.java
new file mode 100644
index 000000000..ddf868f77
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_UnlockDeviceApi_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_UnlockDeviceApi_t {
+
+ int apply();
+ static MemorySegment allocate(sdrplay_api_UnlockDeviceApi_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_UnlockDeviceApi_t.class, fi, constants$2.sdrplay_api_UnlockDeviceApi_t$FUNC, session);
+ }
+ static sdrplay_api_UnlockDeviceApi_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return () -> {
+ try {
+ return (int)constants$2.sdrplay_api_UnlockDeviceApi_t$MH.invokeExact((Addressable)symbol);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Update_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Update_t.java
new file mode 100644
index 000000000..e8feb3926
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_Update_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_Update_t {
+
+ int apply(java.lang.foreign.MemoryAddress dev, int tuner, int reasonForUpdate, int reasonForUpdateExt1);
+ static MemorySegment allocate(sdrplay_api_Update_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_Update_t.class, fi, constants$5.sdrplay_api_Update_t$FUNC, session);
+ }
+ static sdrplay_api_Update_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _dev, int _tuner, int _reasonForUpdate, int _reasonForUpdateExt1) -> {
+ try {
+ return (int)constants$5.sdrplay_api_Update_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_dev, _tuner, _reasonForUpdate, _reasonForUpdateExt1);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_h.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_h.java
new file mode 100644
index 000000000..380403eb0
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_07/sdrplay_api_h.java
@@ -0,0 +1,734 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_07;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.invoke.MethodHandle;
+
+import static java.lang.foreign.ValueLayout.OfAddress;
+import static java.lang.foreign.ValueLayout.OfByte;
+import static java.lang.foreign.ValueLayout.OfDouble;
+import static java.lang.foreign.ValueLayout.OfFloat;
+import static java.lang.foreign.ValueLayout.OfInt;
+import static java.lang.foreign.ValueLayout.OfLong;
+import static java.lang.foreign.ValueLayout.OfShort;
+public class sdrplay_api_h {
+
+ /* package-private */ sdrplay_api_h() {}
+ public static OfByte C_CHAR = Constants$root.C_CHAR$LAYOUT;
+ public static OfShort C_SHORT = Constants$root.C_SHORT$LAYOUT;
+ public static OfInt C_INT = Constants$root.C_LONG$LAYOUT;
+ public static OfInt C_LONG = Constants$root.C_LONG$LAYOUT;
+ public static OfLong C_LONG_LONG = Constants$root.C_LONG_LONG$LAYOUT;
+ public static OfFloat C_FLOAT = Constants$root.C_FLOAT$LAYOUT;
+ public static OfDouble C_DOUBLE = Constants$root.C_DOUBLE$LAYOUT;
+ public static OfAddress C_POINTER = Constants$root.C_POINTER$LAYOUT;
+ public static int RSPIA_NUM_LNA_STATES() {
+ return (int)10L;
+ }
+ public static int RSPIA_NUM_LNA_STATES_AM() {
+ return (int)7L;
+ }
+ public static int RSPIA_NUM_LNA_STATES_LBAND() {
+ return (int)9L;
+ }
+ public static int RSPII_NUM_LNA_STATES() {
+ return (int)9L;
+ }
+ public static int RSPII_NUM_LNA_STATES_AMPORT() {
+ return (int)5L;
+ }
+ public static int RSPII_NUM_LNA_STATES_420MHZ() {
+ return (int)6L;
+ }
+ public static int RSPDUO_NUM_LNA_STATES() {
+ return (int)10L;
+ }
+ public static int RSPDUO_NUM_LNA_STATES_AMPORT() {
+ return (int)5L;
+ }
+ public static int RSPDUO_NUM_LNA_STATES_AM() {
+ return (int)7L;
+ }
+ public static int RSPDUO_NUM_LNA_STATES_LBAND() {
+ return (int)9L;
+ }
+ public static int RSPDX_NUM_LNA_STATES() {
+ return (int)28L;
+ }
+ public static int RSPDX_NUM_LNA_STATES_AMPORT2_0_12() {
+ return (int)19L;
+ }
+ public static int RSPDX_NUM_LNA_STATES_AMPORT2_12_60() {
+ return (int)20L;
+ }
+ public static int RSPDX_NUM_LNA_STATES_VHF_BAND3() {
+ return (int)27L;
+ }
+ public static int RSPDX_NUM_LNA_STATES_420MHZ() {
+ return (int)21L;
+ }
+ public static int RSPDX_NUM_LNA_STATES_LBAND() {
+ return (int)19L;
+ }
+ public static int RSPDX_NUM_LNA_STATES_DX() {
+ return (int)26L;
+ }
+ public static int sdrplay_api_Rsp2_ANTENNA_A() {
+ return (int)5L;
+ }
+ public static int sdrplay_api_Rsp2_ANTENNA_B() {
+ return (int)6L;
+ }
+ public static int sdrplay_api_Rsp2_AMPORT_1() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_Rsp2_AMPORT_2() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_RspDuoMode_Unknown() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_RspDuoMode_Single_Tuner() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_RspDuoMode_Dual_Tuner() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_RspDuoMode_Master() {
+ return (int)4L;
+ }
+ public static int sdrplay_api_RspDuoMode_Slave() {
+ return (int)8L;
+ }
+ public static int sdrplay_api_RspDuo_AMPORT_1() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_RspDuo_AMPORT_2() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_BW_Undefined() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_BW_0_200() {
+ return (int)200L;
+ }
+ public static int sdrplay_api_BW_0_300() {
+ return (int)300L;
+ }
+ public static int sdrplay_api_BW_0_600() {
+ return (int)600L;
+ }
+ public static int sdrplay_api_BW_1_536() {
+ return (int)1536L;
+ }
+ public static int sdrplay_api_BW_5_000() {
+ return (int)5000L;
+ }
+ public static int sdrplay_api_BW_6_000() {
+ return (int)6000L;
+ }
+ public static int sdrplay_api_BW_7_000() {
+ return (int)7000L;
+ }
+ public static int sdrplay_api_BW_8_000() {
+ return (int)8000L;
+ }
+ public static int sdrplay_api_IF_Undefined() {
+ return (int)-1L;
+ }
+ public static int sdrplay_api_IF_Zero() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_IF_0_450() {
+ return (int)450L;
+ }
+ public static int sdrplay_api_IF_1_620() {
+ return (int)1620L;
+ }
+ public static int sdrplay_api_IF_2_048() {
+ return (int)2048L;
+ }
+ public static int sdrplay_api_LO_Undefined() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_LO_Auto() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_LO_120MHz() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_LO_144MHz() {
+ return (int)3L;
+ }
+ public static int sdrplay_api_LO_168MHz() {
+ return (int)4L;
+ }
+ public static int sdrplay_api_EXTENDED_MIN_GR() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_NORMAL_MIN_GR() {
+ return (int)20L;
+ }
+ public static int sdrplay_api_Tuner_Neither() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_Tuner_A() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_Tuner_B() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_Tuner_Both() {
+ return (int)3L;
+ }
+ public static int sdrplay_api_RspDx_ANTENNA_A() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_RspDx_ANTENNA_B() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_RspDx_ANTENNA_C() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_RspDx_HDRMODE_BW_0_200() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_RspDx_HDRMODE_BW_0_500() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_RspDx_HDRMODE_BW_1_200() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_RspDx_HDRMODE_BW_1_700() {
+ return (int)3L;
+ }
+ public static int sdrplay_api_ISOCH() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_BULK() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_AGC_DISABLE() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_AGC_100HZ() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_AGC_50HZ() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_AGC_5HZ() {
+ return (int)3L;
+ }
+ public static int sdrplay_api_AGC_CTRL_EN() {
+ return (int)4L;
+ }
+ public static int sdrplay_api_ADSB_DECIMATION() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_ADSB_NO_DECIMATION_LOWPASS() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_2MHZ() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_3MHZ() {
+ return (int)3L;
+ }
+ public static int sdrplay_api_Overload_Detected() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_Overload_Corrected() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_MasterInitialised() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_SlaveAttached() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_SlaveDetached() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_SlaveInitialised() {
+ return (int)3L;
+ }
+ public static int sdrplay_api_SlaveUninitialised() {
+ return (int)4L;
+ }
+ public static int sdrplay_api_MasterDllDisappeared() {
+ return (int)5L;
+ }
+ public static int sdrplay_api_SlaveDllDisappeared() {
+ return (int)6L;
+ }
+ public static int sdrplay_api_GainChange() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_PowerOverloadChange() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_DeviceRemoved() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_RspDuoModeChange() {
+ return (int)3L;
+ }
+ public static OfAddress HANDLE = Constants$root.C_POINTER$LAYOUT;
+ public static int sdrplay_api_Success() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_Fail() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_InvalidParam() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_OutOfRange() {
+ return (int)3L;
+ }
+ public static int sdrplay_api_GainUpdateError() {
+ return (int)4L;
+ }
+ public static int sdrplay_api_RfUpdateError() {
+ return (int)5L;
+ }
+ public static int sdrplay_api_FsUpdateError() {
+ return (int)6L;
+ }
+ public static int sdrplay_api_HwError() {
+ return (int)7L;
+ }
+ public static int sdrplay_api_AliasingError() {
+ return (int)8L;
+ }
+ public static int sdrplay_api_AlreadyInitialised() {
+ return (int)9L;
+ }
+ public static int sdrplay_api_NotInitialised() {
+ return (int)10L;
+ }
+ public static int sdrplay_api_NotEnabled() {
+ return (int)11L;
+ }
+ public static int sdrplay_api_HwVerError() {
+ return (int)12L;
+ }
+ public static int sdrplay_api_OutOfMemError() {
+ return (int)13L;
+ }
+ public static int sdrplay_api_ServiceNotResponding() {
+ return (int)14L;
+ }
+ public static int sdrplay_api_StartPending() {
+ return (int)15L;
+ }
+ public static int sdrplay_api_StopPending() {
+ return (int)16L;
+ }
+ public static int sdrplay_api_InvalidMode() {
+ return (int)17L;
+ }
+ public static int sdrplay_api_FailedVerification1() {
+ return (int)18L;
+ }
+ public static int sdrplay_api_FailedVerification2() {
+ return (int)19L;
+ }
+ public static int sdrplay_api_FailedVerification3() {
+ return (int)20L;
+ }
+ public static int sdrplay_api_FailedVerification4() {
+ return (int)21L;
+ }
+ public static int sdrplay_api_FailedVerification5() {
+ return (int)22L;
+ }
+ public static int sdrplay_api_FailedVerification6() {
+ return (int)23L;
+ }
+ public static int sdrplay_api_InvalidServiceVersion() {
+ return (int)24L;
+ }
+ public static int sdrplay_api_Update_None() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_Update_Dev_Fs() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_Update_Dev_Ppm() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_Update_Dev_SyncUpdate() {
+ return (int)4L;
+ }
+ public static int sdrplay_api_Update_Dev_ResetFlags() {
+ return (int)8L;
+ }
+ public static int sdrplay_api_Update_Rsp1a_BiasTControl() {
+ return (int)16L;
+ }
+ public static int sdrplay_api_Update_Rsp1a_RfNotchControl() {
+ return (int)32L;
+ }
+ public static int sdrplay_api_Update_Rsp1a_RfDabNotchControl() {
+ return (int)64L;
+ }
+ public static int sdrplay_api_Update_Rsp2_BiasTControl() {
+ return (int)128L;
+ }
+ public static int sdrplay_api_Update_Rsp2_AmPortSelect() {
+ return (int)256L;
+ }
+ public static int sdrplay_api_Update_Rsp2_AntennaControl() {
+ return (int)512L;
+ }
+ public static int sdrplay_api_Update_Rsp2_RfNotchControl() {
+ return (int)1024L;
+ }
+ public static int sdrplay_api_Update_Rsp2_ExtRefControl() {
+ return (int)2048L;
+ }
+ public static int sdrplay_api_Update_RspDuo_ExtRefControl() {
+ return (int)4096L;
+ }
+ public static int sdrplay_api_Update_Master_Spare_1() {
+ return (int)8192L;
+ }
+ public static int sdrplay_api_Update_Master_Spare_2() {
+ return (int)16384L;
+ }
+ public static int sdrplay_api_Update_Tuner_Gr() {
+ return (int)32768L;
+ }
+ public static int sdrplay_api_Update_Tuner_GrLimits() {
+ return (int)65536L;
+ }
+ public static int sdrplay_api_Update_Tuner_Frf() {
+ return (int)131072L;
+ }
+ public static int sdrplay_api_Update_Tuner_BwType() {
+ return (int)262144L;
+ }
+ public static int sdrplay_api_Update_Tuner_IfType() {
+ return (int)524288L;
+ }
+ public static int sdrplay_api_Update_Tuner_DcOffset() {
+ return (int)1048576L;
+ }
+ public static int sdrplay_api_Update_Tuner_LoMode() {
+ return (int)2097152L;
+ }
+ public static int sdrplay_api_Update_Ctrl_DCoffsetIQimbalance() {
+ return (int)4194304L;
+ }
+ public static int sdrplay_api_Update_Ctrl_Decimation() {
+ return (int)8388608L;
+ }
+ public static int sdrplay_api_Update_Ctrl_Agc() {
+ return (int)16777216L;
+ }
+ public static int sdrplay_api_Update_Ctrl_AdsbMode() {
+ return (int)33554432L;
+ }
+ public static int sdrplay_api_Update_Ctrl_OverloadMsgAck() {
+ return (int)67108864L;
+ }
+ public static int sdrplay_api_Update_RspDuo_BiasTControl() {
+ return (int)134217728L;
+ }
+ public static int sdrplay_api_Update_RspDuo_AmPortSelect() {
+ return (int)268435456L;
+ }
+ public static int sdrplay_api_Update_RspDuo_Tuner1AmNotchControl() {
+ return (int)536870912L;
+ }
+ public static int sdrplay_api_Update_RspDuo_RfNotchControl() {
+ return (int)1073741824L;
+ }
+ public static int sdrplay_api_Update_RspDuo_RfDabNotchControl() {
+ return (int)-2147483648L;
+ }
+ public static int sdrplay_api_Update_Ext1_None() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_Update_RspDx_HdrEnable() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_Update_RspDx_BiasTControl() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_Update_RspDx_AntennaControl() {
+ return (int)4L;
+ }
+ public static int sdrplay_api_Update_RspDx_RfNotchControl() {
+ return (int)8L;
+ }
+ public static int sdrplay_api_Update_RspDx_RfDabNotchControl() {
+ return (int)16L;
+ }
+ public static int sdrplay_api_Update_RspDx_HdrBw() {
+ return (int)32L;
+ }
+ public static int sdrplay_api_DbgLvl_Disable() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_DbgLvl_Verbose() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_DbgLvl_Warning() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_DbgLvl_Error() {
+ return (int)3L;
+ }
+ public static int sdrplay_api_DbgLvl_Message() {
+ return (int)4L;
+ }
+ public static MethodHandle sdrplay_api_Open$MH() {
+ return RuntimeHelper.requireNonNull(constants$7.sdrplay_api_Open$MH,"sdrplay_api_Open");
+ }
+ public static int sdrplay_api_Open () {
+ var mh$ = sdrplay_api_Open$MH();
+ try {
+ return (int)mh$.invokeExact();
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_Close$MH() {
+ return RuntimeHelper.requireNonNull(constants$7.sdrplay_api_Close$MH,"sdrplay_api_Close");
+ }
+ public static int sdrplay_api_Close () {
+ var mh$ = sdrplay_api_Close$MH();
+ try {
+ return (int)mh$.invokeExact();
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_ApiVersion$MH() {
+ return RuntimeHelper.requireNonNull(constants$7.sdrplay_api_ApiVersion$MH,"sdrplay_api_ApiVersion");
+ }
+ public static int sdrplay_api_ApiVersion ( Addressable apiVer) {
+ var mh$ = sdrplay_api_ApiVersion$MH();
+ try {
+ return (int)mh$.invokeExact(apiVer);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_LockDeviceApi$MH() {
+ return RuntimeHelper.requireNonNull(constants$7.sdrplay_api_LockDeviceApi$MH,"sdrplay_api_LockDeviceApi");
+ }
+ public static int sdrplay_api_LockDeviceApi () {
+ var mh$ = sdrplay_api_LockDeviceApi$MH();
+ try {
+ return (int)mh$.invokeExact();
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_UnlockDeviceApi$MH() {
+ return RuntimeHelper.requireNonNull(constants$7.sdrplay_api_UnlockDeviceApi$MH,"sdrplay_api_UnlockDeviceApi");
+ }
+ public static int sdrplay_api_UnlockDeviceApi () {
+ var mh$ = sdrplay_api_UnlockDeviceApi$MH();
+ try {
+ return (int)mh$.invokeExact();
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_GetDevices$MH() {
+ return RuntimeHelper.requireNonNull(constants$7.sdrplay_api_GetDevices$MH,"sdrplay_api_GetDevices");
+ }
+ public static int sdrplay_api_GetDevices ( Addressable devices, Addressable numDevs, int maxDevs) {
+ var mh$ = sdrplay_api_GetDevices$MH();
+ try {
+ return (int)mh$.invokeExact(devices, numDevs, maxDevs);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_SelectDevice$MH() {
+ return RuntimeHelper.requireNonNull(constants$8.sdrplay_api_SelectDevice$MH,"sdrplay_api_SelectDevice");
+ }
+ public static int sdrplay_api_SelectDevice ( Addressable device) {
+ var mh$ = sdrplay_api_SelectDevice$MH();
+ try {
+ return (int)mh$.invokeExact(device);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_ReleaseDevice$MH() {
+ return RuntimeHelper.requireNonNull(constants$8.sdrplay_api_ReleaseDevice$MH,"sdrplay_api_ReleaseDevice");
+ }
+ public static int sdrplay_api_ReleaseDevice ( Addressable device) {
+ var mh$ = sdrplay_api_ReleaseDevice$MH();
+ try {
+ return (int)mh$.invokeExact(device);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_GetErrorString$MH() {
+ return RuntimeHelper.requireNonNull(constants$8.sdrplay_api_GetErrorString$MH,"sdrplay_api_GetErrorString");
+ }
+ public static MemoryAddress sdrplay_api_GetErrorString ( int err) {
+ var mh$ = sdrplay_api_GetErrorString$MH();
+ try {
+ return (java.lang.foreign.MemoryAddress)mh$.invokeExact(err);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_GetLastError$MH() {
+ return RuntimeHelper.requireNonNull(constants$8.sdrplay_api_GetLastError$MH,"sdrplay_api_GetLastError");
+ }
+ public static MemoryAddress sdrplay_api_GetLastError ( Addressable device) {
+ var mh$ = sdrplay_api_GetLastError$MH();
+ try {
+ return (java.lang.foreign.MemoryAddress)mh$.invokeExact(device);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_DisableHeartbeat$MH() {
+ return RuntimeHelper.requireNonNull(constants$8.sdrplay_api_DisableHeartbeat$MH,"sdrplay_api_DisableHeartbeat");
+ }
+ public static int sdrplay_api_DisableHeartbeat () {
+ var mh$ = sdrplay_api_DisableHeartbeat$MH();
+ try {
+ return (int)mh$.invokeExact();
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_DebugEnable$MH() {
+ return RuntimeHelper.requireNonNull(constants$8.sdrplay_api_DebugEnable$MH,"sdrplay_api_DebugEnable");
+ }
+ public static int sdrplay_api_DebugEnable ( Addressable dev, int enable) {
+ var mh$ = sdrplay_api_DebugEnable$MH();
+ try {
+ return (int)mh$.invokeExact(dev, enable);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_GetDeviceParams$MH() {
+ return RuntimeHelper.requireNonNull(constants$9.sdrplay_api_GetDeviceParams$MH,"sdrplay_api_GetDeviceParams");
+ }
+ public static int sdrplay_api_GetDeviceParams ( Addressable dev, Addressable deviceParams) {
+ var mh$ = sdrplay_api_GetDeviceParams$MH();
+ try {
+ return (int)mh$.invokeExact(dev, deviceParams);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_Init$MH() {
+ return RuntimeHelper.requireNonNull(constants$9.sdrplay_api_Init$MH,"sdrplay_api_Init");
+ }
+ public static int sdrplay_api_Init ( Addressable dev, Addressable callbackFns, Addressable cbContext) {
+ var mh$ = sdrplay_api_Init$MH();
+ try {
+ return (int)mh$.invokeExact(dev, callbackFns, cbContext);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_Uninit$MH() {
+ return RuntimeHelper.requireNonNull(constants$9.sdrplay_api_Uninit$MH,"sdrplay_api_Uninit");
+ }
+ public static int sdrplay_api_Uninit ( Addressable dev) {
+ var mh$ = sdrplay_api_Uninit$MH();
+ try {
+ return (int)mh$.invokeExact(dev);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_Update$MH() {
+ return RuntimeHelper.requireNonNull(constants$9.sdrplay_api_Update$MH,"sdrplay_api_Update");
+ }
+ public static int sdrplay_api_Update ( Addressable dev, int tuner, int reasonForUpdate, int reasonForUpdateExt1) {
+ var mh$ = sdrplay_api_Update$MH();
+ try {
+ return (int)mh$.invokeExact(dev, tuner, reasonForUpdate, reasonForUpdateExt1);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_SwapRspDuoActiveTuner$MH() {
+ return RuntimeHelper.requireNonNull(constants$9.sdrplay_api_SwapRspDuoActiveTuner$MH,"sdrplay_api_SwapRspDuoActiveTuner");
+ }
+ public static int sdrplay_api_SwapRspDuoActiveTuner ( Addressable dev, Addressable currentTuner, int tuner1AmPortSel) {
+ var mh$ = sdrplay_api_SwapRspDuoActiveTuner$MH();
+ try {
+ return (int)mh$.invokeExact(dev, currentTuner, tuner1AmPortSel);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_SwapRspDuoDualTunerModeSampleRate$MH() {
+ return RuntimeHelper.requireNonNull(constants$9.sdrplay_api_SwapRspDuoDualTunerModeSampleRate$MH,"sdrplay_api_SwapRspDuoDualTunerModeSampleRate");
+ }
+ public static int sdrplay_api_SwapRspDuoDualTunerModeSampleRate ( Addressable dev, Addressable currentSampleRate) {
+ var mh$ = sdrplay_api_SwapRspDuoDualTunerModeSampleRate$MH();
+ try {
+ return (int)mh$.invokeExact(dev, currentSampleRate);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_SwapRspDuoMode$MH() {
+ return RuntimeHelper.requireNonNull(constants$10.sdrplay_api_SwapRspDuoMode$MH,"sdrplay_api_SwapRspDuoMode");
+ }
+ public static int sdrplay_api_SwapRspDuoMode ( Addressable currDevice, Addressable deviceParams, int rspDuoMode, double sampleRate, int tuner, int bwType, int ifType, int tuner1AmPortSel) {
+ var mh$ = sdrplay_api_SwapRspDuoMode$MH();
+ try {
+ return (int)mh$.invokeExact(currDevice, deviceParams, rspDuoMode, sampleRate, tuner, bwType, ifType, tuner1AmPortSel);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static int MAX_BB_GR() {
+ return (int)59L;
+ }
+ public static float SDRPLAY_API_VERSION() {
+ return 3.07f;
+ }
+ public static int SDRPLAY_MAX_DEVICES() {
+ return (int)16L;
+ }
+ public static int SDRPLAY_MAX_TUNERS_PER_DEVICE() {
+ return (int)2L;
+ }
+ public static int SDRPLAY_MAX_SER_NO_LEN() {
+ return (int)64L;
+ }
+ public static int SDRPLAY_MAX_ROOT_NM_LEN() {
+ return (int)32L;
+ }
+ public static int SDRPLAY_RSP1_ID() {
+ return (int)1L;
+ }
+ public static int SDRPLAY_RSP1A_ID() {
+ return (int)255L;
+ }
+ public static int SDRPLAY_RSP2_ID() {
+ return (int)2L;
+ }
+ public static int SDRPLAY_RSPduo_ID() {
+ return (int)3L;
+ }
+ public static int SDRPLAY_RSPdx_ID() {
+ return (int)4L;
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/Constants$root.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/Constants$root.java
new file mode 100644
index 000000000..59c0b3b40
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/Constants$root.java
@@ -0,0 +1,34 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import static java.lang.foreign.ValueLayout.ADDRESS;
+import static java.lang.foreign.ValueLayout.JAVA_BOOLEAN;
+import static java.lang.foreign.ValueLayout.JAVA_BYTE;
+import static java.lang.foreign.ValueLayout.JAVA_DOUBLE;
+import static java.lang.foreign.ValueLayout.JAVA_FLOAT;
+import static java.lang.foreign.ValueLayout.JAVA_INT;
+import static java.lang.foreign.ValueLayout.JAVA_LONG;
+import static java.lang.foreign.ValueLayout.JAVA_SHORT;
+import static java.lang.foreign.ValueLayout.OfAddress;
+import static java.lang.foreign.ValueLayout.OfBoolean;
+import static java.lang.foreign.ValueLayout.OfByte;
+import static java.lang.foreign.ValueLayout.OfDouble;
+import static java.lang.foreign.ValueLayout.OfFloat;
+import static java.lang.foreign.ValueLayout.OfInt;
+import static java.lang.foreign.ValueLayout.OfLong;
+import static java.lang.foreign.ValueLayout.OfShort;
+public class Constants$root {
+
+ static final OfBoolean C_BOOL$LAYOUT = JAVA_BOOLEAN;
+ static final OfByte C_CHAR$LAYOUT = JAVA_BYTE;
+ static final OfShort C_SHORT$LAYOUT = JAVA_SHORT.withBitAlignment(16);
+ static final OfInt C_INT$LAYOUT = JAVA_INT.withBitAlignment(32);
+ static final OfInt C_LONG$LAYOUT = JAVA_INT.withBitAlignment(32);
+ static final OfLong C_LONG_LONG$LAYOUT = JAVA_LONG.withBitAlignment(64);
+ static final OfFloat C_FLOAT$LAYOUT = JAVA_FLOAT.withBitAlignment(32);
+ static final OfDouble C_DOUBLE$LAYOUT = JAVA_DOUBLE.withBitAlignment(64);
+ static final OfAddress C_POINTER$LAYOUT = ADDRESS.withBitAlignment(64);
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/RuntimeHelper.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/RuntimeHelper.java
new file mode 100644
index 000000000..15adbf055
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/RuntimeHelper.java
@@ -0,0 +1,228 @@
+package com.github.dsheirer.sdrplay.api.v3_08;
+// Generated by jextract
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.Linker;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.foreign.SymbolLookup;
+import java.lang.foreign.ValueLayout;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+import static java.lang.foreign.ValueLayout.ADDRESS;
+import static java.lang.foreign.ValueLayout.JAVA_DOUBLE;
+import static java.lang.foreign.ValueLayout.JAVA_LONG;
+
+final class RuntimeHelper {
+
+ private RuntimeHelper() {}
+ private final static Linker LINKER = Linker.nativeLinker();
+ private final static ClassLoader LOADER = RuntimeHelper.class.getClassLoader();
+ private final static MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup();
+ private final static SymbolLookup SYMBOL_LOOKUP;
+
+ final static SegmentAllocator CONSTANT_ALLOCATOR =
+ (size, align) -> MemorySegment.allocateNative(size, align, MemorySession.openImplicit());
+
+ static {
+// System.loadLibrary("libsdrplay_api");
+ SymbolLookup loaderLookup = SymbolLookup.loaderLookup();
+ SYMBOL_LOOKUP = name -> loaderLookup.lookup(name).or(() -> LINKER.defaultLookup().lookup(name));
+ }
+
+ static T requireNonNull(T obj, String symbolName) {
+ if (obj == null) {
+ throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName);
+ }
+ return obj;
+ }
+
+ private final static SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); };
+
+ static final MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) {
+ return SYMBOL_LOOKUP.lookup(name).map(symbol -> MemorySegment.ofAddress(symbol.address(), layout.byteSize(), MemorySession.openShared())).orElse(null);
+ }
+
+ static final MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) {
+ return SYMBOL_LOOKUP.lookup(name).
+ map(addr -> LINKER.downcallHandle(addr, fdesc)).
+ orElse(null);
+ }
+
+ static final MethodHandle downcallHandle(FunctionDescriptor fdesc) {
+ return LINKER.downcallHandle(fdesc);
+ }
+
+ static final MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) {
+ return SYMBOL_LOOKUP.lookup(name).
+ map(addr -> VarargsInvoker.make(addr, fdesc)).
+ orElse(null);
+ }
+
+ static final MemorySegment upcallStub(Class fi, Z z, FunctionDescriptor fdesc, MemorySession session) {
+ try {
+ MethodHandle handle = MH_LOOKUP.findVirtual(fi, "apply", Linker.upcallType(fdesc));
+ handle = handle.bindTo(z);
+ return LINKER.upcallStub(handle, fdesc, session);
+ } catch (Throwable ex) {
+ throw new AssertionError(ex);
+ }
+ }
+
+ static MemorySegment asArray(MemoryAddress addr, MemoryLayout layout, int numElements, MemorySession session) {
+ return MemorySegment.ofAddress(addr, numElements * layout.byteSize(), session);
+ }
+
+ // Internals only below this point
+
+ private static class VarargsInvoker {
+ private static final MethodHandle INVOKE_MH;
+ private final MemorySegment symbol;
+ private final FunctionDescriptor function;
+
+ private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) {
+ this.symbol = symbol;
+ this.function = function;
+ }
+
+ static {
+ try {
+ INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class));
+ } catch (ReflectiveOperationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) {
+ VarargsInvoker invoker = new VarargsInvoker(symbol, function);
+ MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1);
+ MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class);
+ for (MemoryLayout layout : function.argumentLayouts()) {
+ mtype = mtype.appendParameterTypes(carrier(layout, false));
+ }
+ mtype = mtype.appendParameterTypes(Object[].class);
+ if (mtype.returnType().equals(MemorySegment.class)) {
+ mtype = mtype.insertParameterTypes(0, SegmentAllocator.class);
+ } else {
+ handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR);
+ }
+ return handle.asType(mtype);
+ }
+
+ static Class> carrier(MemoryLayout layout, boolean ret) {
+ if (layout instanceof ValueLayout valueLayout) {
+ return (ret || valueLayout.carrier() != MemoryAddress.class) ?
+ valueLayout.carrier() : Addressable.class;
+ } else if (layout instanceof GroupLayout) {
+ return MemorySegment.class;
+ } else {
+ throw new AssertionError("Cannot get here!");
+ }
+ }
+
+ private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable {
+ // one trailing Object[]
+ int nNamedArgs = function.argumentLayouts().size();
+ assert(args.length == nNamedArgs + 1);
+ // The last argument is the array of vararg collector
+ Object[] unnamedArgs = (Object[]) args[args.length - 1];
+
+ int argsCount = nNamedArgs + unnamedArgs.length;
+ Class>[] argTypes = new Class>[argsCount];
+ MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length];
+
+ int pos = 0;
+ for (pos = 0; pos < nNamedArgs; pos++) {
+ argLayouts[pos] = function.argumentLayouts().get(pos);
+ }
+
+ assert pos == nNamedArgs;
+ for (Object o: unnamedArgs) {
+ argLayouts[pos] = variadicLayout(normalize(o.getClass()));
+ pos++;
+ }
+ assert pos == argsCount;
+
+ FunctionDescriptor f = (function.returnLayout().isEmpty()) ?
+ FunctionDescriptor.ofVoid(argLayouts) :
+ FunctionDescriptor.of(function.returnLayout().get(), argLayouts);
+ MethodHandle mh = LINKER.downcallHandle(symbol, f);
+ if (mh.type().returnType() == MemorySegment.class) {
+ mh = mh.bindTo(allocator);
+ }
+ // flatten argument list so that it can be passed to an asSpreader MH
+ Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length];
+ System.arraycopy(args, 0, allArgs, 0, nNamedArgs);
+ System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length);
+
+ return mh.asSpreader(Object[].class, argsCount).invoke(allArgs);
+ }
+
+ private static Class> unboxIfNeeded(Class> clazz) {
+ if (clazz == Boolean.class) {
+ return boolean.class;
+ } else if (clazz == Void.class) {
+ return void.class;
+ } else if (clazz == Byte.class) {
+ return byte.class;
+ } else if (clazz == Character.class) {
+ return char.class;
+ } else if (clazz == Short.class) {
+ return short.class;
+ } else if (clazz == Integer.class) {
+ return int.class;
+ } else if (clazz == Long.class) {
+ return long.class;
+ } else if (clazz == Float.class) {
+ return float.class;
+ } else if (clazz == Double.class) {
+ return double.class;
+ } else {
+ return clazz;
+ }
+ }
+
+ private Class> promote(Class> c) {
+ if (c == byte.class || c == char.class || c == short.class || c == int.class) {
+ return long.class;
+ } else if (c == float.class) {
+ return double.class;
+ } else {
+ return c;
+ }
+ }
+
+ private Class> normalize(Class> c) {
+ c = unboxIfNeeded(c);
+ if (c.isPrimitive()) {
+ return promote(c);
+ }
+ if (MemoryAddress.class.isAssignableFrom(c)) {
+ return MemoryAddress.class;
+ }
+ if (MemorySegment.class.isAssignableFrom(c)) {
+ return MemorySegment.class;
+ }
+ throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName());
+ }
+
+ private MemoryLayout variadicLayout(Class> c) {
+ if (c == long.class) {
+ return JAVA_LONG;
+ } else if (c == double.class) {
+ return JAVA_DOUBLE;
+ } else if (MemoryAddress.class.isAssignableFrom(c)) {
+ return ADDRESS;
+ } else {
+ throw new IllegalArgumentException("Unhandled variadic argument class: " + c);
+ }
+ }
+ }
+}
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$0.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$0.java
new file mode 100644
index 000000000..5db56877a
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$0.java
@@ -0,0 +1,35 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$0 {
+
+ static final FunctionDescriptor sdrplay_api_StreamCallback_t$FUNC = FunctionDescriptor.ofVoid(
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_StreamCallback_t$MH = RuntimeHelper.downcallHandle(
+ constants$0.sdrplay_api_StreamCallback_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_EventCallback_t$FUNC = FunctionDescriptor.ofVoid(
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_EventCallback_t$MH = RuntimeHelper.downcallHandle(
+ constants$0.sdrplay_api_EventCallback_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_Open_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_Open_t$MH = RuntimeHelper.downcallHandle(
+ constants$0.sdrplay_api_Open_t$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$1.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$1.java
new file mode 100644
index 000000000..7c879d8f1
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$1.java
@@ -0,0 +1,25 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$1 {
+
+ static final FunctionDescriptor sdrplay_api_Close_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_Close_t$MH = RuntimeHelper.downcallHandle(
+ constants$1.sdrplay_api_Close_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_ApiVersion_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_ApiVersion_t$MH = RuntimeHelper.downcallHandle(
+ constants$1.sdrplay_api_ApiVersion_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_LockDeviceApi_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_LockDeviceApi_t$MH = RuntimeHelper.downcallHandle(
+ constants$1.sdrplay_api_LockDeviceApi_t$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$10.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$10.java
new file mode 100644
index 000000000..aaaaa0251
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$10.java
@@ -0,0 +1,25 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$10 {
+
+ static final FunctionDescriptor sdrplay_api_SwapRspDuoMode$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_DOUBLE$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_SwapRspDuoMode$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_SwapRspDuoMode",
+ constants$10.sdrplay_api_SwapRspDuoMode$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$2.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$2.java
new file mode 100644
index 000000000..870d3eef2
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$2.java
@@ -0,0 +1,29 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$2 {
+
+ static final FunctionDescriptor sdrplay_api_UnlockDeviceApi_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_UnlockDeviceApi_t$MH = RuntimeHelper.downcallHandle(
+ constants$2.sdrplay_api_UnlockDeviceApi_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_GetDevices_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_GetDevices_t$MH = RuntimeHelper.downcallHandle(
+ constants$2.sdrplay_api_GetDevices_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_SelectDevice_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_SelectDevice_t$MH = RuntimeHelper.downcallHandle(
+ constants$2.sdrplay_api_SelectDevice_t$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$3.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$3.java
new file mode 100644
index 000000000..2be759d82
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$3.java
@@ -0,0 +1,29 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$3 {
+
+ static final FunctionDescriptor sdrplay_api_ReleaseDevice_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_ReleaseDevice_t$MH = RuntimeHelper.downcallHandle(
+ constants$3.sdrplay_api_ReleaseDevice_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_GetErrorString_t$FUNC = FunctionDescriptor.of(Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_GetErrorString_t$MH = RuntimeHelper.downcallHandle(
+ constants$3.sdrplay_api_GetErrorString_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_GetLastError_t$FUNC = FunctionDescriptor.of(Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_GetLastError_t$MH = RuntimeHelper.downcallHandle(
+ constants$3.sdrplay_api_GetLastError_t$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$4.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$4.java
new file mode 100644
index 000000000..1453fdf7f
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$4.java
@@ -0,0 +1,29 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$4 {
+
+ static final FunctionDescriptor sdrplay_api_DisableHeartbeat_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_DisableHeartbeat_t$MH = RuntimeHelper.downcallHandle(
+ constants$4.sdrplay_api_DisableHeartbeat_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_DebugEnable_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_DebugEnable_t$MH = RuntimeHelper.downcallHandle(
+ constants$4.sdrplay_api_DebugEnable_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_GetDeviceParams_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_GetDeviceParams_t$MH = RuntimeHelper.downcallHandle(
+ constants$4.sdrplay_api_GetDeviceParams_t$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$5.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$5.java
new file mode 100644
index 000000000..5cf82e9b0
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$5.java
@@ -0,0 +1,34 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$5 {
+
+ static final FunctionDescriptor sdrplay_api_Init_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_Init_t$MH = RuntimeHelper.downcallHandle(
+ constants$5.sdrplay_api_Init_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_Uninit_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_Uninit_t$MH = RuntimeHelper.downcallHandle(
+ constants$5.sdrplay_api_Uninit_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_Update_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_Update_t$MH = RuntimeHelper.downcallHandle(
+ constants$5.sdrplay_api_Update_t$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$6.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$6.java
new file mode 100644
index 000000000..a861cc2c2
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$6.java
@@ -0,0 +1,39 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$6 {
+
+ static final FunctionDescriptor sdrplay_api_SwapRspDuoActiveTuner_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_SwapRspDuoActiveTuner_t$MH = RuntimeHelper.downcallHandle(
+ constants$6.sdrplay_api_SwapRspDuoActiveTuner_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_DOUBLE$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t$MH = RuntimeHelper.downcallHandle(
+ constants$6.sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_SwapRspDuoMode_t$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_DOUBLE$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_SwapRspDuoMode_t$MH = RuntimeHelper.downcallHandle(
+ constants$6.sdrplay_api_SwapRspDuoMode_t$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$7.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$7.java
new file mode 100644
index 000000000..84eb47d85
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$7.java
@@ -0,0 +1,47 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$7 {
+
+ static final FunctionDescriptor sdrplay_api_Open$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_Open$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_Open",
+ constants$7.sdrplay_api_Open$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_Close$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_Close$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_Close",
+ constants$7.sdrplay_api_Close$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_ApiVersion$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_ApiVersion$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_ApiVersion",
+ constants$7.sdrplay_api_ApiVersion$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_LockDeviceApi$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_LockDeviceApi$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_LockDeviceApi",
+ constants$7.sdrplay_api_LockDeviceApi$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_UnlockDeviceApi$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_UnlockDeviceApi$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_UnlockDeviceApi",
+ constants$7.sdrplay_api_UnlockDeviceApi$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_GetDevices$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_GetDevices$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_GetDevices",
+ constants$7.sdrplay_api_GetDevices$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$8.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$8.java
new file mode 100644
index 000000000..e5b60bce5
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$8.java
@@ -0,0 +1,52 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$8 {
+
+ static final FunctionDescriptor sdrplay_api_SelectDevice$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_SelectDevice$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_SelectDevice",
+ constants$8.sdrplay_api_SelectDevice$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_ReleaseDevice$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_ReleaseDevice$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_ReleaseDevice",
+ constants$8.sdrplay_api_ReleaseDevice$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_GetErrorString$FUNC = FunctionDescriptor.of(Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_GetErrorString$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_GetErrorString",
+ constants$8.sdrplay_api_GetErrorString$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_GetLastError$FUNC = FunctionDescriptor.of(Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_GetLastError$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_GetLastError",
+ constants$8.sdrplay_api_GetLastError$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_DisableHeartbeat$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT);
+ static final MethodHandle sdrplay_api_DisableHeartbeat$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_DisableHeartbeat",
+ constants$8.sdrplay_api_DisableHeartbeat$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_DebugEnable$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_DebugEnable$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_DebugEnable",
+ constants$8.sdrplay_api_DebugEnable$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$9.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$9.java
new file mode 100644
index 000000000..74f5fc68e
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/constants$9.java
@@ -0,0 +1,63 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+class constants$9 {
+
+ static final FunctionDescriptor sdrplay_api_GetDeviceParams$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_GetDeviceParams$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_GetDeviceParams",
+ constants$9.sdrplay_api_GetDeviceParams$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_Init$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_Init$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_Init",
+ constants$9.sdrplay_api_Init$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_Uninit$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_Uninit$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_Uninit",
+ constants$9.sdrplay_api_Uninit$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_Update$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_Update$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_Update",
+ constants$9.sdrplay_api_Update$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_SwapRspDuoActiveTuner$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_LONG$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_SwapRspDuoActiveTuner$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_SwapRspDuoActiveTuner",
+ constants$9.sdrplay_api_SwapRspDuoActiveTuner$FUNC
+ );
+ static final FunctionDescriptor sdrplay_api_SwapRspDuoDualTunerModeSampleRate$FUNC = FunctionDescriptor.of(Constants$root.C_LONG$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_POINTER$LAYOUT,
+ Constants$root.C_DOUBLE$LAYOUT
+ );
+ static final MethodHandle sdrplay_api_SwapRspDuoDualTunerModeSampleRate$MH = RuntimeHelper.downcallHandle(
+ "sdrplay_api_SwapRspDuoDualTunerModeSampleRate",
+ constants$9.sdrplay_api_SwapRspDuoDualTunerModeSampleRate$FUNC
+ );
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_AgcT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_AgcT.java
new file mode 100644
index 000000000..3b901e400
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_AgcT.java
@@ -0,0 +1,146 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_AgcT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("enable"),
+ Constants$root.C_LONG$LAYOUT.withName("setPoint_dBfs"),
+ Constants$root.C_SHORT$LAYOUT.withName("attack_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_delay_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_threshold_dB"),
+ Constants$root.C_LONG$LAYOUT.withName("syncUpdate")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_AgcT.$struct$LAYOUT;
+ }
+ static final VarHandle enable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("enable"));
+ public static VarHandle enable$VH() {
+ return sdrplay_api_AgcT.enable$VH;
+ }
+ public static int enable$get(MemorySegment seg) {
+ return (int)sdrplay_api_AgcT.enable$VH.get(seg);
+ }
+ public static void enable$set( MemorySegment seg, int x) {
+ sdrplay_api_AgcT.enable$VH.set(seg, x);
+ }
+ public static int enable$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_AgcT.enable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void enable$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_AgcT.enable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle setPoint_dBfs$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("setPoint_dBfs"));
+ public static VarHandle setPoint_dBfs$VH() {
+ return sdrplay_api_AgcT.setPoint_dBfs$VH;
+ }
+ public static int setPoint_dBfs$get(MemorySegment seg) {
+ return (int)sdrplay_api_AgcT.setPoint_dBfs$VH.get(seg);
+ }
+ public static void setPoint_dBfs$set( MemorySegment seg, int x) {
+ sdrplay_api_AgcT.setPoint_dBfs$VH.set(seg, x);
+ }
+ public static int setPoint_dBfs$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_AgcT.setPoint_dBfs$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void setPoint_dBfs$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_AgcT.setPoint_dBfs$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle attack_ms$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("attack_ms"));
+ public static VarHandle attack_ms$VH() {
+ return sdrplay_api_AgcT.attack_ms$VH;
+ }
+ public static short attack_ms$get(MemorySegment seg) {
+ return (short)sdrplay_api_AgcT.attack_ms$VH.get(seg);
+ }
+ public static void attack_ms$set( MemorySegment seg, short x) {
+ sdrplay_api_AgcT.attack_ms$VH.set(seg, x);
+ }
+ public static short attack_ms$get(MemorySegment seg, long index) {
+ return (short)sdrplay_api_AgcT.attack_ms$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void attack_ms$set(MemorySegment seg, long index, short x) {
+ sdrplay_api_AgcT.attack_ms$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle decay_ms$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("decay_ms"));
+ public static VarHandle decay_ms$VH() {
+ return sdrplay_api_AgcT.decay_ms$VH;
+ }
+ public static short decay_ms$get(MemorySegment seg) {
+ return (short)sdrplay_api_AgcT.decay_ms$VH.get(seg);
+ }
+ public static void decay_ms$set( MemorySegment seg, short x) {
+ sdrplay_api_AgcT.decay_ms$VH.set(seg, x);
+ }
+ public static short decay_ms$get(MemorySegment seg, long index) {
+ return (short)sdrplay_api_AgcT.decay_ms$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void decay_ms$set(MemorySegment seg, long index, short x) {
+ sdrplay_api_AgcT.decay_ms$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle decay_delay_ms$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("decay_delay_ms"));
+ public static VarHandle decay_delay_ms$VH() {
+ return sdrplay_api_AgcT.decay_delay_ms$VH;
+ }
+ public static short decay_delay_ms$get(MemorySegment seg) {
+ return (short)sdrplay_api_AgcT.decay_delay_ms$VH.get(seg);
+ }
+ public static void decay_delay_ms$set( MemorySegment seg, short x) {
+ sdrplay_api_AgcT.decay_delay_ms$VH.set(seg, x);
+ }
+ public static short decay_delay_ms$get(MemorySegment seg, long index) {
+ return (short)sdrplay_api_AgcT.decay_delay_ms$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void decay_delay_ms$set(MemorySegment seg, long index, short x) {
+ sdrplay_api_AgcT.decay_delay_ms$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle decay_threshold_dB$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("decay_threshold_dB"));
+ public static VarHandle decay_threshold_dB$VH() {
+ return sdrplay_api_AgcT.decay_threshold_dB$VH;
+ }
+ public static short decay_threshold_dB$get(MemorySegment seg) {
+ return (short)sdrplay_api_AgcT.decay_threshold_dB$VH.get(seg);
+ }
+ public static void decay_threshold_dB$set( MemorySegment seg, short x) {
+ sdrplay_api_AgcT.decay_threshold_dB$VH.set(seg, x);
+ }
+ public static short decay_threshold_dB$get(MemorySegment seg, long index) {
+ return (short)sdrplay_api_AgcT.decay_threshold_dB$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void decay_threshold_dB$set(MemorySegment seg, long index, short x) {
+ sdrplay_api_AgcT.decay_threshold_dB$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle syncUpdate$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("syncUpdate"));
+ public static VarHandle syncUpdate$VH() {
+ return sdrplay_api_AgcT.syncUpdate$VH;
+ }
+ public static int syncUpdate$get(MemorySegment seg) {
+ return (int)sdrplay_api_AgcT.syncUpdate$VH.get(seg);
+ }
+ public static void syncUpdate$set( MemorySegment seg, int x) {
+ sdrplay_api_AgcT.syncUpdate$VH.set(seg, x);
+ }
+ public static int syncUpdate$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_AgcT.syncUpdate$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void syncUpdate$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_AgcT.syncUpdate$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_ApiVersion_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_ApiVersion_t.java
new file mode 100644
index 000000000..53b4cd921
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_ApiVersion_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_ApiVersion_t {
+
+ int apply(java.lang.foreign.MemoryAddress apiVer);
+ static MemorySegment allocate(sdrplay_api_ApiVersion_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_ApiVersion_t.class, fi, constants$1.sdrplay_api_ApiVersion_t$FUNC, session);
+ }
+ static sdrplay_api_ApiVersion_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _apiVer) -> {
+ try {
+ return (int)constants$1.sdrplay_api_ApiVersion_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_apiVer);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_CallbackFnsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_CallbackFnsT.java
new file mode 100644
index 000000000..caeceea40
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_CallbackFnsT.java
@@ -0,0 +1,87 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_CallbackFnsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_POINTER$LAYOUT.withName("StreamACbFn"),
+ Constants$root.C_POINTER$LAYOUT.withName("StreamBCbFn"),
+ Constants$root.C_POINTER$LAYOUT.withName("EventCbFn")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_CallbackFnsT.$struct$LAYOUT;
+ }
+ static final VarHandle StreamACbFn$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("StreamACbFn"));
+ public static VarHandle StreamACbFn$VH() {
+ return sdrplay_api_CallbackFnsT.StreamACbFn$VH;
+ }
+ public static MemoryAddress StreamACbFn$get(MemorySegment seg) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_CallbackFnsT.StreamACbFn$VH.get(seg);
+ }
+ public static void StreamACbFn$set( MemorySegment seg, MemoryAddress x) {
+ sdrplay_api_CallbackFnsT.StreamACbFn$VH.set(seg, x);
+ }
+ public static MemoryAddress StreamACbFn$get(MemorySegment seg, long index) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_CallbackFnsT.StreamACbFn$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void StreamACbFn$set(MemorySegment seg, long index, MemoryAddress x) {
+ sdrplay_api_CallbackFnsT.StreamACbFn$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static sdrplay_api_StreamCallback_t StreamACbFn (MemorySegment segment, MemorySession session) {
+ return sdrplay_api_StreamCallback_t.ofAddress(StreamACbFn$get(segment), session);
+ }
+ static final VarHandle StreamBCbFn$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("StreamBCbFn"));
+ public static VarHandle StreamBCbFn$VH() {
+ return sdrplay_api_CallbackFnsT.StreamBCbFn$VH;
+ }
+ public static MemoryAddress StreamBCbFn$get(MemorySegment seg) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_CallbackFnsT.StreamBCbFn$VH.get(seg);
+ }
+ public static void StreamBCbFn$set( MemorySegment seg, MemoryAddress x) {
+ sdrplay_api_CallbackFnsT.StreamBCbFn$VH.set(seg, x);
+ }
+ public static MemoryAddress StreamBCbFn$get(MemorySegment seg, long index) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_CallbackFnsT.StreamBCbFn$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void StreamBCbFn$set(MemorySegment seg, long index, MemoryAddress x) {
+ sdrplay_api_CallbackFnsT.StreamBCbFn$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static sdrplay_api_StreamCallback_t StreamBCbFn (MemorySegment segment, MemorySession session) {
+ return sdrplay_api_StreamCallback_t.ofAddress(StreamBCbFn$get(segment), session);
+ }
+ static final VarHandle EventCbFn$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("EventCbFn"));
+ public static VarHandle EventCbFn$VH() {
+ return sdrplay_api_CallbackFnsT.EventCbFn$VH;
+ }
+ public static MemoryAddress EventCbFn$get(MemorySegment seg) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_CallbackFnsT.EventCbFn$VH.get(seg);
+ }
+ public static void EventCbFn$set( MemorySegment seg, MemoryAddress x) {
+ sdrplay_api_CallbackFnsT.EventCbFn$VH.set(seg, x);
+ }
+ public static MemoryAddress EventCbFn$get(MemorySegment seg, long index) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_CallbackFnsT.EventCbFn$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void EventCbFn$set(MemorySegment seg, long index, MemoryAddress x) {
+ sdrplay_api_CallbackFnsT.EventCbFn$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static sdrplay_api_EventCallback_t EventCbFn (MemorySegment segment, MemorySession session) {
+ return sdrplay_api_EventCallback_t.ofAddress(EventCbFn$get(segment), session);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Close_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Close_t.java
new file mode 100644
index 000000000..776889103
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Close_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_Close_t {
+
+ int apply();
+ static MemorySegment allocate(sdrplay_api_Close_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_Close_t.class, fi, constants$1.sdrplay_api_Close_t$FUNC, session);
+ }
+ static sdrplay_api_Close_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return () -> {
+ try {
+ return (int)constants$1.sdrplay_api_Close_t$MH.invokeExact((Addressable)symbol);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_ControlParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_ControlParamsT.java
new file mode 100644
index 000000000..74c8e4047
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_ControlParamsT.java
@@ -0,0 +1,72 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_ControlParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("DCenable"),
+ Constants$root.C_CHAR$LAYOUT.withName("IQenable")
+ ).withName("dcOffset"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("enable"),
+ Constants$root.C_CHAR$LAYOUT.withName("decimationFactor"),
+ Constants$root.C_CHAR$LAYOUT.withName("wideBandSignal")
+ ).withName("decimation"),
+ MemoryLayout.paddingLayout(24),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("enable"),
+ Constants$root.C_LONG$LAYOUT.withName("setPoint_dBfs"),
+ Constants$root.C_SHORT$LAYOUT.withName("attack_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_delay_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_threshold_dB"),
+ Constants$root.C_LONG$LAYOUT.withName("syncUpdate")
+ ).withName("agc"),
+ Constants$root.C_LONG$LAYOUT.withName("adsbMode")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_ControlParamsT.$struct$LAYOUT;
+ }
+ public static MemorySegment dcOffset$slice(MemorySegment seg) {
+ return seg.asSlice(0, 2);
+ }
+ public static MemorySegment decimation$slice(MemorySegment seg) {
+ return seg.asSlice(2, 3);
+ }
+ public static MemorySegment agc$slice(MemorySegment seg) {
+ return seg.asSlice(8, 20);
+ }
+ static final VarHandle adsbMode$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("adsbMode"));
+ public static VarHandle adsbMode$VH() {
+ return sdrplay_api_ControlParamsT.adsbMode$VH;
+ }
+ public static int adsbMode$get(MemorySegment seg) {
+ return (int)sdrplay_api_ControlParamsT.adsbMode$VH.get(seg);
+ }
+ public static void adsbMode$set( MemorySegment seg, int x) {
+ sdrplay_api_ControlParamsT.adsbMode$VH.set(seg, x);
+ }
+ public static int adsbMode$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_ControlParamsT.adsbMode$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void adsbMode$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_ControlParamsT.adsbMode$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DcOffsetT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DcOffsetT.java
new file mode 100644
index 000000000..0b4565a03
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DcOffsetT.java
@@ -0,0 +1,61 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_DcOffsetT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("DCenable"),
+ Constants$root.C_CHAR$LAYOUT.withName("IQenable")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_DcOffsetT.$struct$LAYOUT;
+ }
+ static final VarHandle DCenable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("DCenable"));
+ public static VarHandle DCenable$VH() {
+ return sdrplay_api_DcOffsetT.DCenable$VH;
+ }
+ public static byte DCenable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_DcOffsetT.DCenable$VH.get(seg);
+ }
+ public static void DCenable$set( MemorySegment seg, byte x) {
+ sdrplay_api_DcOffsetT.DCenable$VH.set(seg, x);
+ }
+ public static byte DCenable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_DcOffsetT.DCenable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void DCenable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_DcOffsetT.DCenable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle IQenable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("IQenable"));
+ public static VarHandle IQenable$VH() {
+ return sdrplay_api_DcOffsetT.IQenable$VH;
+ }
+ public static byte IQenable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_DcOffsetT.IQenable$VH.get(seg);
+ }
+ public static void IQenable$set( MemorySegment seg, byte x) {
+ sdrplay_api_DcOffsetT.IQenable$VH.set(seg, x);
+ }
+ public static byte IQenable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_DcOffsetT.IQenable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void IQenable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_DcOffsetT.IQenable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DcOffsetTunerT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DcOffsetTunerT.java
new file mode 100644
index 000000000..eeb25400d
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DcOffsetTunerT.java
@@ -0,0 +1,96 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_DcOffsetTunerT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("dcCal"),
+ Constants$root.C_CHAR$LAYOUT.withName("speedUp"),
+ MemoryLayout.paddingLayout(16),
+ Constants$root.C_LONG$LAYOUT.withName("trackTime"),
+ Constants$root.C_LONG$LAYOUT.withName("refreshRateTime")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_DcOffsetTunerT.$struct$LAYOUT;
+ }
+ static final VarHandle dcCal$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("dcCal"));
+ public static VarHandle dcCal$VH() {
+ return sdrplay_api_DcOffsetTunerT.dcCal$VH;
+ }
+ public static byte dcCal$get(MemorySegment seg) {
+ return (byte)sdrplay_api_DcOffsetTunerT.dcCal$VH.get(seg);
+ }
+ public static void dcCal$set( MemorySegment seg, byte x) {
+ sdrplay_api_DcOffsetTunerT.dcCal$VH.set(seg, x);
+ }
+ public static byte dcCal$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_DcOffsetTunerT.dcCal$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void dcCal$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_DcOffsetTunerT.dcCal$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle speedUp$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("speedUp"));
+ public static VarHandle speedUp$VH() {
+ return sdrplay_api_DcOffsetTunerT.speedUp$VH;
+ }
+ public static byte speedUp$get(MemorySegment seg) {
+ return (byte)sdrplay_api_DcOffsetTunerT.speedUp$VH.get(seg);
+ }
+ public static void speedUp$set( MemorySegment seg, byte x) {
+ sdrplay_api_DcOffsetTunerT.speedUp$VH.set(seg, x);
+ }
+ public static byte speedUp$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_DcOffsetTunerT.speedUp$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void speedUp$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_DcOffsetTunerT.speedUp$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle trackTime$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("trackTime"));
+ public static VarHandle trackTime$VH() {
+ return sdrplay_api_DcOffsetTunerT.trackTime$VH;
+ }
+ public static int trackTime$get(MemorySegment seg) {
+ return (int)sdrplay_api_DcOffsetTunerT.trackTime$VH.get(seg);
+ }
+ public static void trackTime$set( MemorySegment seg, int x) {
+ sdrplay_api_DcOffsetTunerT.trackTime$VH.set(seg, x);
+ }
+ public static int trackTime$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_DcOffsetTunerT.trackTime$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void trackTime$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_DcOffsetTunerT.trackTime$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle refreshRateTime$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("refreshRateTime"));
+ public static VarHandle refreshRateTime$VH() {
+ return sdrplay_api_DcOffsetTunerT.refreshRateTime$VH;
+ }
+ public static int refreshRateTime$get(MemorySegment seg) {
+ return (int)sdrplay_api_DcOffsetTunerT.refreshRateTime$VH.get(seg);
+ }
+ public static void refreshRateTime$set( MemorySegment seg, int x) {
+ sdrplay_api_DcOffsetTunerT.refreshRateTime$VH.set(seg, x);
+ }
+ public static int refreshRateTime$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_DcOffsetTunerT.refreshRateTime$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void refreshRateTime$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_DcOffsetTunerT.refreshRateTime$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DebugEnable_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DebugEnable_t.java
new file mode 100644
index 000000000..b5ec4cd7c
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DebugEnable_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_DebugEnable_t {
+
+ int apply(java.lang.foreign.MemoryAddress dev, int dbgLvl);
+ static MemorySegment allocate(sdrplay_api_DebugEnable_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_DebugEnable_t.class, fi, constants$4.sdrplay_api_DebugEnable_t$FUNC, session);
+ }
+ static sdrplay_api_DebugEnable_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _dev, int _dbgLvl) -> {
+ try {
+ return (int)constants$4.sdrplay_api_DebugEnable_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_dev, _dbgLvl);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DecimationT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DecimationT.java
new file mode 100644
index 000000000..8d8fe1c81
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DecimationT.java
@@ -0,0 +1,78 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_DecimationT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("enable"),
+ Constants$root.C_CHAR$LAYOUT.withName("decimationFactor"),
+ Constants$root.C_CHAR$LAYOUT.withName("wideBandSignal")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_DecimationT.$struct$LAYOUT;
+ }
+ static final VarHandle enable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("enable"));
+ public static VarHandle enable$VH() {
+ return sdrplay_api_DecimationT.enable$VH;
+ }
+ public static byte enable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_DecimationT.enable$VH.get(seg);
+ }
+ public static void enable$set( MemorySegment seg, byte x) {
+ sdrplay_api_DecimationT.enable$VH.set(seg, x);
+ }
+ public static byte enable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_DecimationT.enable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void enable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_DecimationT.enable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle decimationFactor$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("decimationFactor"));
+ public static VarHandle decimationFactor$VH() {
+ return sdrplay_api_DecimationT.decimationFactor$VH;
+ }
+ public static byte decimationFactor$get(MemorySegment seg) {
+ return (byte)sdrplay_api_DecimationT.decimationFactor$VH.get(seg);
+ }
+ public static void decimationFactor$set( MemorySegment seg, byte x) {
+ sdrplay_api_DecimationT.decimationFactor$VH.set(seg, x);
+ }
+ public static byte decimationFactor$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_DecimationT.decimationFactor$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void decimationFactor$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_DecimationT.decimationFactor$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle wideBandSignal$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("wideBandSignal"));
+ public static VarHandle wideBandSignal$VH() {
+ return sdrplay_api_DecimationT.wideBandSignal$VH;
+ }
+ public static byte wideBandSignal$get(MemorySegment seg) {
+ return (byte)sdrplay_api_DecimationT.wideBandSignal$VH.get(seg);
+ }
+ public static void wideBandSignal$set( MemorySegment seg, byte x) {
+ sdrplay_api_DecimationT.wideBandSignal$VH.set(seg, x);
+ }
+ public static byte wideBandSignal$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_DecimationT.wideBandSignal$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void wideBandSignal$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_DecimationT.wideBandSignal$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DevParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DevParamsT.java
new file mode 100644
index 000000000..0424f37b7
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DevParamsT.java
@@ -0,0 +1,135 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_DevParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_DOUBLE$LAYOUT.withName("ppm"),
+ MemoryLayout.structLayout(
+ Constants$root.C_DOUBLE$LAYOUT.withName("fsHz"),
+ Constants$root.C_CHAR$LAYOUT.withName("syncUpdate"),
+ Constants$root.C_CHAR$LAYOUT.withName("reCal"),
+ MemoryLayout.paddingLayout(48)
+ ).withName("fsFreq"),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("sampleNum"),
+ Constants$root.C_LONG$LAYOUT.withName("period")
+ ).withName("syncUpdate"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("resetGainUpdate"),
+ Constants$root.C_CHAR$LAYOUT.withName("resetRfUpdate"),
+ Constants$root.C_CHAR$LAYOUT.withName("resetFsUpdate")
+ ).withName("resetFlags"),
+ MemoryLayout.paddingLayout(8),
+ Constants$root.C_LONG$LAYOUT.withName("mode"),
+ Constants$root.C_LONG$LAYOUT.withName("samplesPerPkt"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("rfNotchEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfDabNotchEnable")
+ ).withName("rsp1aParams"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("extRefOutputEn")
+ ).withName("rsp2Params"),
+ MemoryLayout.paddingLayout(8),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("extRefOutputEn")
+ ).withName("rspDuoParams"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("hdrEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("biasTEnable"),
+ MemoryLayout.paddingLayout(16),
+ Constants$root.C_LONG$LAYOUT.withName("antennaSel"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfNotchEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfDabNotchEnable"),
+ MemoryLayout.paddingLayout(16)
+ ).withName("rspDxParams")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_DevParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle ppm$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("ppm"));
+ public static VarHandle ppm$VH() {
+ return sdrplay_api_DevParamsT.ppm$VH;
+ }
+ public static double ppm$get(MemorySegment seg) {
+ return (double)sdrplay_api_DevParamsT.ppm$VH.get(seg);
+ }
+ public static void ppm$set( MemorySegment seg, double x) {
+ sdrplay_api_DevParamsT.ppm$VH.set(seg, x);
+ }
+ public static double ppm$get(MemorySegment seg, long index) {
+ return (double)sdrplay_api_DevParamsT.ppm$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void ppm$set(MemorySegment seg, long index, double x) {
+ sdrplay_api_DevParamsT.ppm$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static MemorySegment fsFreq$slice(MemorySegment seg) {
+ return seg.asSlice(8, 16);
+ }
+ public static MemorySegment syncUpdate$slice(MemorySegment seg) {
+ return seg.asSlice(24, 8);
+ }
+ public static MemorySegment resetFlags$slice(MemorySegment seg) {
+ return seg.asSlice(32, 3);
+ }
+ static final VarHandle mode$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("mode"));
+ public static VarHandle mode$VH() {
+ return sdrplay_api_DevParamsT.mode$VH;
+ }
+ public static int mode$get(MemorySegment seg) {
+ return (int)sdrplay_api_DevParamsT.mode$VH.get(seg);
+ }
+ public static void mode$set( MemorySegment seg, int x) {
+ sdrplay_api_DevParamsT.mode$VH.set(seg, x);
+ }
+ public static int mode$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_DevParamsT.mode$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void mode$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_DevParamsT.mode$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle samplesPerPkt$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("samplesPerPkt"));
+ public static VarHandle samplesPerPkt$VH() {
+ return sdrplay_api_DevParamsT.samplesPerPkt$VH;
+ }
+ public static int samplesPerPkt$get(MemorySegment seg) {
+ return (int)sdrplay_api_DevParamsT.samplesPerPkt$VH.get(seg);
+ }
+ public static void samplesPerPkt$set( MemorySegment seg, int x) {
+ sdrplay_api_DevParamsT.samplesPerPkt$VH.set(seg, x);
+ }
+ public static int samplesPerPkt$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_DevParamsT.samplesPerPkt$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void samplesPerPkt$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_DevParamsT.samplesPerPkt$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static MemorySegment rsp1aParams$slice(MemorySegment seg) {
+ return seg.asSlice(44, 2);
+ }
+ public static MemorySegment rsp2Params$slice(MemorySegment seg) {
+ return seg.asSlice(46, 1);
+ }
+ public static MemorySegment rspDuoParams$slice(MemorySegment seg) {
+ return seg.asSlice(48, 4);
+ }
+ public static MemorySegment rspDxParams$slice(MemorySegment seg) {
+ return seg.asSlice(52, 12);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DeviceParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DeviceParamsT.java
new file mode 100644
index 000000000..0dbae360d
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DeviceParamsT.java
@@ -0,0 +1,78 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_DeviceParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_POINTER$LAYOUT.withName("devParams"),
+ Constants$root.C_POINTER$LAYOUT.withName("rxChannelA"),
+ Constants$root.C_POINTER$LAYOUT.withName("rxChannelB")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_DeviceParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle devParams$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("devParams"));
+ public static VarHandle devParams$VH() {
+ return sdrplay_api_DeviceParamsT.devParams$VH;
+ }
+ public static MemoryAddress devParams$get(MemorySegment seg) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_DeviceParamsT.devParams$VH.get(seg);
+ }
+ public static void devParams$set( MemorySegment seg, MemoryAddress x) {
+ sdrplay_api_DeviceParamsT.devParams$VH.set(seg, x);
+ }
+ public static MemoryAddress devParams$get(MemorySegment seg, long index) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_DeviceParamsT.devParams$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void devParams$set(MemorySegment seg, long index, MemoryAddress x) {
+ sdrplay_api_DeviceParamsT.devParams$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rxChannelA$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rxChannelA"));
+ public static VarHandle rxChannelA$VH() {
+ return sdrplay_api_DeviceParamsT.rxChannelA$VH;
+ }
+ public static MemoryAddress rxChannelA$get(MemorySegment seg) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_DeviceParamsT.rxChannelA$VH.get(seg);
+ }
+ public static void rxChannelA$set( MemorySegment seg, MemoryAddress x) {
+ sdrplay_api_DeviceParamsT.rxChannelA$VH.set(seg, x);
+ }
+ public static MemoryAddress rxChannelA$get(MemorySegment seg, long index) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_DeviceParamsT.rxChannelA$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rxChannelA$set(MemorySegment seg, long index, MemoryAddress x) {
+ sdrplay_api_DeviceParamsT.rxChannelA$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rxChannelB$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rxChannelB"));
+ public static VarHandle rxChannelB$VH() {
+ return sdrplay_api_DeviceParamsT.rxChannelB$VH;
+ }
+ public static MemoryAddress rxChannelB$get(MemorySegment seg) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_DeviceParamsT.rxChannelB$VH.get(seg);
+ }
+ public static void rxChannelB$set( MemorySegment seg, MemoryAddress x) {
+ sdrplay_api_DeviceParamsT.rxChannelB$VH.set(seg, x);
+ }
+ public static MemoryAddress rxChannelB$get(MemorySegment seg, long index) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_DeviceParamsT.rxChannelB$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rxChannelB$set(MemorySegment seg, long index, MemoryAddress x) {
+ sdrplay_api_DeviceParamsT.rxChannelB$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DeviceT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DeviceT.java
new file mode 100644
index 000000000..e578f52f3
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DeviceT.java
@@ -0,0 +1,135 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_DeviceT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ MemoryLayout.sequenceLayout(64, Constants$root.C_CHAR$LAYOUT).withName("SerNo"),
+ Constants$root.C_CHAR$LAYOUT.withName("hwVer"),
+ MemoryLayout.paddingLayout(24),
+ Constants$root.C_LONG$LAYOUT.withName("tuner"),
+ Constants$root.C_LONG$LAYOUT.withName("rspDuoMode"),
+ Constants$root.C_CHAR$LAYOUT.withName("valid"),
+ MemoryLayout.paddingLayout(24),
+ Constants$root.C_DOUBLE$LAYOUT.withName("rspDuoSampleFreq"),
+ Constants$root.C_POINTER$LAYOUT.withName("dev")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_DeviceT.$struct$LAYOUT;
+ }
+ public static MemorySegment SerNo$slice(MemorySegment seg) {
+ return seg.asSlice(0, 64);
+ }
+ static final VarHandle hwVer$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("hwVer"));
+ public static VarHandle hwVer$VH() {
+ return sdrplay_api_DeviceT.hwVer$VH;
+ }
+ public static byte hwVer$get(MemorySegment seg) {
+ return (byte)sdrplay_api_DeviceT.hwVer$VH.get(seg);
+ }
+ public static void hwVer$set( MemorySegment seg, byte x) {
+ sdrplay_api_DeviceT.hwVer$VH.set(seg, x);
+ }
+ public static byte hwVer$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_DeviceT.hwVer$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void hwVer$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_DeviceT.hwVer$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle tuner$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("tuner"));
+ public static VarHandle tuner$VH() {
+ return sdrplay_api_DeviceT.tuner$VH;
+ }
+ public static int tuner$get(MemorySegment seg) {
+ return (int)sdrplay_api_DeviceT.tuner$VH.get(seg);
+ }
+ public static void tuner$set( MemorySegment seg, int x) {
+ sdrplay_api_DeviceT.tuner$VH.set(seg, x);
+ }
+ public static int tuner$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_DeviceT.tuner$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void tuner$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_DeviceT.tuner$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rspDuoMode$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rspDuoMode"));
+ public static VarHandle rspDuoMode$VH() {
+ return sdrplay_api_DeviceT.rspDuoMode$VH;
+ }
+ public static int rspDuoMode$get(MemorySegment seg) {
+ return (int)sdrplay_api_DeviceT.rspDuoMode$VH.get(seg);
+ }
+ public static void rspDuoMode$set( MemorySegment seg, int x) {
+ sdrplay_api_DeviceT.rspDuoMode$VH.set(seg, x);
+ }
+ public static int rspDuoMode$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_DeviceT.rspDuoMode$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rspDuoMode$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_DeviceT.rspDuoMode$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle valid$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("valid"));
+ public static VarHandle valid$VH() {
+ return sdrplay_api_DeviceT.valid$VH;
+ }
+ public static byte valid$get(MemorySegment seg) {
+ return (byte)sdrplay_api_DeviceT.valid$VH.get(seg);
+ }
+ public static void valid$set( MemorySegment seg, byte x) {
+ sdrplay_api_DeviceT.valid$VH.set(seg, x);
+ }
+ public static byte valid$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_DeviceT.valid$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void valid$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_DeviceT.valid$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rspDuoSampleFreq$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rspDuoSampleFreq"));
+ public static VarHandle rspDuoSampleFreq$VH() {
+ return sdrplay_api_DeviceT.rspDuoSampleFreq$VH;
+ }
+ public static double rspDuoSampleFreq$get(MemorySegment seg) {
+ return (double)sdrplay_api_DeviceT.rspDuoSampleFreq$VH.get(seg);
+ }
+ public static void rspDuoSampleFreq$set( MemorySegment seg, double x) {
+ sdrplay_api_DeviceT.rspDuoSampleFreq$VH.set(seg, x);
+ }
+ public static double rspDuoSampleFreq$get(MemorySegment seg, long index) {
+ return (double)sdrplay_api_DeviceT.rspDuoSampleFreq$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rspDuoSampleFreq$set(MemorySegment seg, long index, double x) {
+ sdrplay_api_DeviceT.rspDuoSampleFreq$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle dev$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("dev"));
+ public static VarHandle dev$VH() {
+ return sdrplay_api_DeviceT.dev$VH;
+ }
+ public static MemoryAddress dev$get(MemorySegment seg) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_DeviceT.dev$VH.get(seg);
+ }
+ public static void dev$set( MemorySegment seg, MemoryAddress x) {
+ sdrplay_api_DeviceT.dev$VH.set(seg, x);
+ }
+ public static MemoryAddress dev$get(MemorySegment seg, long index) {
+ return (java.lang.foreign.MemoryAddress)sdrplay_api_DeviceT.dev$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void dev$set(MemorySegment seg, long index, MemoryAddress x) {
+ sdrplay_api_DeviceT.dev$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DisableHeartbeat_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DisableHeartbeat_t.java
new file mode 100644
index 000000000..6c3e5bbe1
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_DisableHeartbeat_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_DisableHeartbeat_t {
+
+ int apply();
+ static MemorySegment allocate(sdrplay_api_DisableHeartbeat_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_DisableHeartbeat_t.class, fi, constants$4.sdrplay_api_DisableHeartbeat_t$FUNC, session);
+ }
+ static sdrplay_api_DisableHeartbeat_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return () -> {
+ try {
+ return (int)constants$4.sdrplay_api_DisableHeartbeat_t$MH.invokeExact((Addressable)symbol);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_ErrorInfoT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_ErrorInfoT.java
new file mode 100644
index 000000000..262dcc868
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_ErrorInfoT.java
@@ -0,0 +1,56 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_ErrorInfoT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ MemoryLayout.sequenceLayout(256, Constants$root.C_CHAR$LAYOUT).withName("file"),
+ MemoryLayout.sequenceLayout(256, Constants$root.C_CHAR$LAYOUT).withName("function"),
+ Constants$root.C_LONG$LAYOUT.withName("line"),
+ MemoryLayout.sequenceLayout(1024, Constants$root.C_CHAR$LAYOUT).withName("message")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_ErrorInfoT.$struct$LAYOUT;
+ }
+ public static MemorySegment file$slice(MemorySegment seg) {
+ return seg.asSlice(0, 256);
+ }
+ public static MemorySegment function$slice(MemorySegment seg) {
+ return seg.asSlice(256, 256);
+ }
+ static final VarHandle line$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("line"));
+ public static VarHandle line$VH() {
+ return sdrplay_api_ErrorInfoT.line$VH;
+ }
+ public static int line$get(MemorySegment seg) {
+ return (int)sdrplay_api_ErrorInfoT.line$VH.get(seg);
+ }
+ public static void line$set( MemorySegment seg, int x) {
+ sdrplay_api_ErrorInfoT.line$VH.set(seg, x);
+ }
+ public static int line$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_ErrorInfoT.line$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void line$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_ErrorInfoT.line$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static MemorySegment message$slice(MemorySegment seg) {
+ return seg.asSlice(516, 1024);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_EventCallback_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_EventCallback_t.java
new file mode 100644
index 000000000..3d4f5edd8
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_EventCallback_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_EventCallback_t {
+
+ void apply(int eventId, int tuner, java.lang.foreign.MemoryAddress params, java.lang.foreign.MemoryAddress cbContext);
+ static MemorySegment allocate(sdrplay_api_EventCallback_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_EventCallback_t.class, fi, constants$0.sdrplay_api_EventCallback_t$FUNC, session);
+ }
+ static sdrplay_api_EventCallback_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (int _eventId, int _tuner, java.lang.foreign.MemoryAddress _params, java.lang.foreign.MemoryAddress _cbContext) -> {
+ try {
+ constants$0.sdrplay_api_EventCallback_t$MH.invokeExact((Addressable)symbol, _eventId, _tuner, (java.lang.foreign.Addressable)_params, (java.lang.foreign.Addressable)_cbContext);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_EventParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_EventParamsT.java
new file mode 100644
index 000000000..8cebd0c1f
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_EventParamsT.java
@@ -0,0 +1,46 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+public class sdrplay_api_EventParamsT {
+
+ static final GroupLayout $union$LAYOUT = MemoryLayout.unionLayout(
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("gRdB"),
+ Constants$root.C_LONG$LAYOUT.withName("lnaGRdB"),
+ Constants$root.C_DOUBLE$LAYOUT.withName("currGain")
+ ).withName("gainParams"),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("powerOverloadChangeType")
+ ).withName("powerOverloadParams"),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("modeChangeType")
+ ).withName("rspDuoModeParams")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_EventParamsT.$union$LAYOUT;
+ }
+ public static MemorySegment gainParams$slice(MemorySegment seg) {
+ return seg.asSlice(0, 16);
+ }
+ public static MemorySegment powerOverloadParams$slice(MemorySegment seg) {
+ return seg.asSlice(0, 4);
+ }
+ public static MemorySegment rspDuoModeParams$slice(MemorySegment seg) {
+ return seg.asSlice(0, 4);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_FsFreqT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_FsFreqT.java
new file mode 100644
index 000000000..bdbfc5f8e
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_FsFreqT.java
@@ -0,0 +1,79 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_FsFreqT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_DOUBLE$LAYOUT.withName("fsHz"),
+ Constants$root.C_CHAR$LAYOUT.withName("syncUpdate"),
+ Constants$root.C_CHAR$LAYOUT.withName("reCal"),
+ MemoryLayout.paddingLayout(48)
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_FsFreqT.$struct$LAYOUT;
+ }
+ static final VarHandle fsHz$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("fsHz"));
+ public static VarHandle fsHz$VH() {
+ return sdrplay_api_FsFreqT.fsHz$VH;
+ }
+ public static double fsHz$get(MemorySegment seg) {
+ return (double)sdrplay_api_FsFreqT.fsHz$VH.get(seg);
+ }
+ public static void fsHz$set( MemorySegment seg, double x) {
+ sdrplay_api_FsFreqT.fsHz$VH.set(seg, x);
+ }
+ public static double fsHz$get(MemorySegment seg, long index) {
+ return (double)sdrplay_api_FsFreqT.fsHz$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void fsHz$set(MemorySegment seg, long index, double x) {
+ sdrplay_api_FsFreqT.fsHz$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle syncUpdate$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("syncUpdate"));
+ public static VarHandle syncUpdate$VH() {
+ return sdrplay_api_FsFreqT.syncUpdate$VH;
+ }
+ public static byte syncUpdate$get(MemorySegment seg) {
+ return (byte)sdrplay_api_FsFreqT.syncUpdate$VH.get(seg);
+ }
+ public static void syncUpdate$set( MemorySegment seg, byte x) {
+ sdrplay_api_FsFreqT.syncUpdate$VH.set(seg, x);
+ }
+ public static byte syncUpdate$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_FsFreqT.syncUpdate$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void syncUpdate$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_FsFreqT.syncUpdate$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle reCal$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("reCal"));
+ public static VarHandle reCal$VH() {
+ return sdrplay_api_FsFreqT.reCal$VH;
+ }
+ public static byte reCal$get(MemorySegment seg) {
+ return (byte)sdrplay_api_FsFreqT.reCal$VH.get(seg);
+ }
+ public static void reCal$set( MemorySegment seg, byte x) {
+ sdrplay_api_FsFreqT.reCal$VH.set(seg, x);
+ }
+ public static byte reCal$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_FsFreqT.reCal$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void reCal$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_FsFreqT.reCal$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GainCbParamT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GainCbParamT.java
new file mode 100644
index 000000000..e2da8a2be
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GainCbParamT.java
@@ -0,0 +1,78 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_GainCbParamT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("gRdB"),
+ Constants$root.C_LONG$LAYOUT.withName("lnaGRdB"),
+ Constants$root.C_DOUBLE$LAYOUT.withName("currGain")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_GainCbParamT.$struct$LAYOUT;
+ }
+ static final VarHandle gRdB$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("gRdB"));
+ public static VarHandle gRdB$VH() {
+ return sdrplay_api_GainCbParamT.gRdB$VH;
+ }
+ public static int gRdB$get(MemorySegment seg) {
+ return (int)sdrplay_api_GainCbParamT.gRdB$VH.get(seg);
+ }
+ public static void gRdB$set( MemorySegment seg, int x) {
+ sdrplay_api_GainCbParamT.gRdB$VH.set(seg, x);
+ }
+ public static int gRdB$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_GainCbParamT.gRdB$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void gRdB$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_GainCbParamT.gRdB$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle lnaGRdB$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("lnaGRdB"));
+ public static VarHandle lnaGRdB$VH() {
+ return sdrplay_api_GainCbParamT.lnaGRdB$VH;
+ }
+ public static int lnaGRdB$get(MemorySegment seg) {
+ return (int)sdrplay_api_GainCbParamT.lnaGRdB$VH.get(seg);
+ }
+ public static void lnaGRdB$set( MemorySegment seg, int x) {
+ sdrplay_api_GainCbParamT.lnaGRdB$VH.set(seg, x);
+ }
+ public static int lnaGRdB$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_GainCbParamT.lnaGRdB$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void lnaGRdB$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_GainCbParamT.lnaGRdB$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle currGain$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("currGain"));
+ public static VarHandle currGain$VH() {
+ return sdrplay_api_GainCbParamT.currGain$VH;
+ }
+ public static double currGain$get(MemorySegment seg) {
+ return (double)sdrplay_api_GainCbParamT.currGain$VH.get(seg);
+ }
+ public static void currGain$set( MemorySegment seg, double x) {
+ sdrplay_api_GainCbParamT.currGain$VH.set(seg, x);
+ }
+ public static double currGain$get(MemorySegment seg, long index) {
+ return (double)sdrplay_api_GainCbParamT.currGain$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void currGain$set(MemorySegment seg, long index, double x) {
+ sdrplay_api_GainCbParamT.currGain$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GainT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GainT.java
new file mode 100644
index 000000000..48db78e45
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GainT.java
@@ -0,0 +1,104 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_GainT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("gRdB"),
+ Constants$root.C_CHAR$LAYOUT.withName("LNAstate"),
+ Constants$root.C_CHAR$LAYOUT.withName("syncUpdate"),
+ MemoryLayout.paddingLayout(16),
+ Constants$root.C_LONG$LAYOUT.withName("minGr"),
+ MemoryLayout.structLayout(
+ Constants$root.C_FLOAT$LAYOUT.withName("curr"),
+ Constants$root.C_FLOAT$LAYOUT.withName("max"),
+ Constants$root.C_FLOAT$LAYOUT.withName("min")
+ ).withName("gainVals")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_GainT.$struct$LAYOUT;
+ }
+ static final VarHandle gRdB$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("gRdB"));
+ public static VarHandle gRdB$VH() {
+ return sdrplay_api_GainT.gRdB$VH;
+ }
+ public static int gRdB$get(MemorySegment seg) {
+ return (int)sdrplay_api_GainT.gRdB$VH.get(seg);
+ }
+ public static void gRdB$set( MemorySegment seg, int x) {
+ sdrplay_api_GainT.gRdB$VH.set(seg, x);
+ }
+ public static int gRdB$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_GainT.gRdB$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void gRdB$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_GainT.gRdB$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle LNAstate$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("LNAstate"));
+ public static VarHandle LNAstate$VH() {
+ return sdrplay_api_GainT.LNAstate$VH;
+ }
+ public static byte LNAstate$get(MemorySegment seg) {
+ return (byte)sdrplay_api_GainT.LNAstate$VH.get(seg);
+ }
+ public static void LNAstate$set( MemorySegment seg, byte x) {
+ sdrplay_api_GainT.LNAstate$VH.set(seg, x);
+ }
+ public static byte LNAstate$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_GainT.LNAstate$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void LNAstate$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_GainT.LNAstate$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle syncUpdate$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("syncUpdate"));
+ public static VarHandle syncUpdate$VH() {
+ return sdrplay_api_GainT.syncUpdate$VH;
+ }
+ public static byte syncUpdate$get(MemorySegment seg) {
+ return (byte)sdrplay_api_GainT.syncUpdate$VH.get(seg);
+ }
+ public static void syncUpdate$set( MemorySegment seg, byte x) {
+ sdrplay_api_GainT.syncUpdate$VH.set(seg, x);
+ }
+ public static byte syncUpdate$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_GainT.syncUpdate$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void syncUpdate$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_GainT.syncUpdate$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle minGr$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("minGr"));
+ public static VarHandle minGr$VH() {
+ return sdrplay_api_GainT.minGr$VH;
+ }
+ public static int minGr$get(MemorySegment seg) {
+ return (int)sdrplay_api_GainT.minGr$VH.get(seg);
+ }
+ public static void minGr$set( MemorySegment seg, int x) {
+ sdrplay_api_GainT.minGr$VH.set(seg, x);
+ }
+ public static int minGr$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_GainT.minGr$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void minGr$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_GainT.minGr$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static MemorySegment gainVals$slice(MemorySegment seg) {
+ return seg.asSlice(12, 12);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GainValuesT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GainValuesT.java
new file mode 100644
index 000000000..7e4b26f11
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GainValuesT.java
@@ -0,0 +1,78 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_GainValuesT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_FLOAT$LAYOUT.withName("curr"),
+ Constants$root.C_FLOAT$LAYOUT.withName("max"),
+ Constants$root.C_FLOAT$LAYOUT.withName("min")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_GainValuesT.$struct$LAYOUT;
+ }
+ static final VarHandle curr$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("curr"));
+ public static VarHandle curr$VH() {
+ return sdrplay_api_GainValuesT.curr$VH;
+ }
+ public static float curr$get(MemorySegment seg) {
+ return (float)sdrplay_api_GainValuesT.curr$VH.get(seg);
+ }
+ public static void curr$set( MemorySegment seg, float x) {
+ sdrplay_api_GainValuesT.curr$VH.set(seg, x);
+ }
+ public static float curr$get(MemorySegment seg, long index) {
+ return (float)sdrplay_api_GainValuesT.curr$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void curr$set(MemorySegment seg, long index, float x) {
+ sdrplay_api_GainValuesT.curr$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle max$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("max"));
+ public static VarHandle max$VH() {
+ return sdrplay_api_GainValuesT.max$VH;
+ }
+ public static float max$get(MemorySegment seg) {
+ return (float)sdrplay_api_GainValuesT.max$VH.get(seg);
+ }
+ public static void max$set( MemorySegment seg, float x) {
+ sdrplay_api_GainValuesT.max$VH.set(seg, x);
+ }
+ public static float max$get(MemorySegment seg, long index) {
+ return (float)sdrplay_api_GainValuesT.max$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void max$set(MemorySegment seg, long index, float x) {
+ sdrplay_api_GainValuesT.max$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle min$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("min"));
+ public static VarHandle min$VH() {
+ return sdrplay_api_GainValuesT.min$VH;
+ }
+ public static float min$get(MemorySegment seg) {
+ return (float)sdrplay_api_GainValuesT.min$VH.get(seg);
+ }
+ public static void min$set( MemorySegment seg, float x) {
+ sdrplay_api_GainValuesT.min$VH.set(seg, x);
+ }
+ public static float min$get(MemorySegment seg, long index) {
+ return (float)sdrplay_api_GainValuesT.min$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void min$set(MemorySegment seg, long index, float x) {
+ sdrplay_api_GainValuesT.min$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GetDeviceParams_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GetDeviceParams_t.java
new file mode 100644
index 000000000..6644f606b
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GetDeviceParams_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_GetDeviceParams_t {
+
+ int apply(java.lang.foreign.MemoryAddress dev, java.lang.foreign.MemoryAddress deviceParams);
+ static MemorySegment allocate(sdrplay_api_GetDeviceParams_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_GetDeviceParams_t.class, fi, constants$4.sdrplay_api_GetDeviceParams_t$FUNC, session);
+ }
+ static sdrplay_api_GetDeviceParams_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _dev, java.lang.foreign.MemoryAddress _deviceParams) -> {
+ try {
+ return (int)constants$4.sdrplay_api_GetDeviceParams_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_dev, (java.lang.foreign.Addressable)_deviceParams);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GetDevices_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GetDevices_t.java
new file mode 100644
index 000000000..ae53feb31
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GetDevices_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_GetDevices_t {
+
+ int apply(java.lang.foreign.MemoryAddress devices, java.lang.foreign.MemoryAddress numDevs, int maxDevs);
+ static MemorySegment allocate(sdrplay_api_GetDevices_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_GetDevices_t.class, fi, constants$2.sdrplay_api_GetDevices_t$FUNC, session);
+ }
+ static sdrplay_api_GetDevices_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _devices, java.lang.foreign.MemoryAddress _numDevs, int _maxDevs) -> {
+ try {
+ return (int)constants$2.sdrplay_api_GetDevices_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_devices, (java.lang.foreign.Addressable)_numDevs, _maxDevs);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GetErrorString_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GetErrorString_t.java
new file mode 100644
index 000000000..63316412d
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GetErrorString_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_GetErrorString_t {
+
+ java.lang.foreign.Addressable apply(int err);
+ static MemorySegment allocate(sdrplay_api_GetErrorString_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_GetErrorString_t.class, fi, constants$3.sdrplay_api_GetErrorString_t$FUNC, session);
+ }
+ static sdrplay_api_GetErrorString_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (int _err) -> {
+ try {
+ return (java.lang.foreign.Addressable)(java.lang.foreign.MemoryAddress)constants$3.sdrplay_api_GetErrorString_t$MH.invokeExact((Addressable)symbol, _err);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GetLastError_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GetLastError_t.java
new file mode 100644
index 000000000..ccb2f928d
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_GetLastError_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_GetLastError_t {
+
+ java.lang.foreign.Addressable apply(java.lang.foreign.MemoryAddress device);
+ static MemorySegment allocate(sdrplay_api_GetLastError_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_GetLastError_t.class, fi, constants$3.sdrplay_api_GetLastError_t$FUNC, session);
+ }
+ static sdrplay_api_GetLastError_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _device) -> {
+ try {
+ return (java.lang.foreign.Addressable)(java.lang.foreign.MemoryAddress)constants$3.sdrplay_api_GetLastError_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_device);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Init_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Init_t.java
new file mode 100644
index 000000000..b132623cb
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Init_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_Init_t {
+
+ int apply(java.lang.foreign.MemoryAddress dev, java.lang.foreign.MemoryAddress callbackFns, java.lang.foreign.MemoryAddress cbContext);
+ static MemorySegment allocate(sdrplay_api_Init_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_Init_t.class, fi, constants$5.sdrplay_api_Init_t$FUNC, session);
+ }
+ static sdrplay_api_Init_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _dev, java.lang.foreign.MemoryAddress _callbackFns, java.lang.foreign.MemoryAddress _cbContext) -> {
+ try {
+ return (int)constants$5.sdrplay_api_Init_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_dev, (java.lang.foreign.Addressable)_callbackFns, (java.lang.foreign.Addressable)_cbContext);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_LockDeviceApi_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_LockDeviceApi_t.java
new file mode 100644
index 000000000..024d7b996
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_LockDeviceApi_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_LockDeviceApi_t {
+
+ int apply();
+ static MemorySegment allocate(sdrplay_api_LockDeviceApi_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_LockDeviceApi_t.class, fi, constants$1.sdrplay_api_LockDeviceApi_t$FUNC, session);
+ }
+ static sdrplay_api_LockDeviceApi_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return () -> {
+ try {
+ return (int)constants$1.sdrplay_api_LockDeviceApi_t$MH.invokeExact((Addressable)symbol);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Open_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Open_t.java
new file mode 100644
index 000000000..399da163c
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Open_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_Open_t {
+
+ int apply();
+ static MemorySegment allocate(sdrplay_api_Open_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_Open_t.class, fi, constants$0.sdrplay_api_Open_t$FUNC, session);
+ }
+ static sdrplay_api_Open_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return () -> {
+ try {
+ return (int)constants$0.sdrplay_api_Open_t$MH.invokeExact((Addressable)symbol);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_PowerOverloadCbParamT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_PowerOverloadCbParamT.java
new file mode 100644
index 000000000..0d0699496
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_PowerOverloadCbParamT.java
@@ -0,0 +1,44 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_PowerOverloadCbParamT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("powerOverloadChangeType")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_PowerOverloadCbParamT.$struct$LAYOUT;
+ }
+ static final VarHandle powerOverloadChangeType$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("powerOverloadChangeType"));
+ public static VarHandle powerOverloadChangeType$VH() {
+ return sdrplay_api_PowerOverloadCbParamT.powerOverloadChangeType$VH;
+ }
+ public static int powerOverloadChangeType$get(MemorySegment seg) {
+ return (int)sdrplay_api_PowerOverloadCbParamT.powerOverloadChangeType$VH.get(seg);
+ }
+ public static void powerOverloadChangeType$set( MemorySegment seg, int x) {
+ sdrplay_api_PowerOverloadCbParamT.powerOverloadChangeType$VH.set(seg, x);
+ }
+ public static int powerOverloadChangeType$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_PowerOverloadCbParamT.powerOverloadChangeType$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void powerOverloadChangeType$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_PowerOverloadCbParamT.powerOverloadChangeType$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_ReleaseDevice_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_ReleaseDevice_t.java
new file mode 100644
index 000000000..f33acfa34
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_ReleaseDevice_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_ReleaseDevice_t {
+
+ int apply(java.lang.foreign.MemoryAddress device);
+ static MemorySegment allocate(sdrplay_api_ReleaseDevice_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_ReleaseDevice_t.class, fi, constants$3.sdrplay_api_ReleaseDevice_t$FUNC, session);
+ }
+ static sdrplay_api_ReleaseDevice_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _device) -> {
+ try {
+ return (int)constants$3.sdrplay_api_ReleaseDevice_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_device);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_ResetFlagsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_ResetFlagsT.java
new file mode 100644
index 000000000..1edb0819c
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_ResetFlagsT.java
@@ -0,0 +1,78 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_ResetFlagsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("resetGainUpdate"),
+ Constants$root.C_CHAR$LAYOUT.withName("resetRfUpdate"),
+ Constants$root.C_CHAR$LAYOUT.withName("resetFsUpdate")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_ResetFlagsT.$struct$LAYOUT;
+ }
+ static final VarHandle resetGainUpdate$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("resetGainUpdate"));
+ public static VarHandle resetGainUpdate$VH() {
+ return sdrplay_api_ResetFlagsT.resetGainUpdate$VH;
+ }
+ public static byte resetGainUpdate$get(MemorySegment seg) {
+ return (byte)sdrplay_api_ResetFlagsT.resetGainUpdate$VH.get(seg);
+ }
+ public static void resetGainUpdate$set( MemorySegment seg, byte x) {
+ sdrplay_api_ResetFlagsT.resetGainUpdate$VH.set(seg, x);
+ }
+ public static byte resetGainUpdate$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_ResetFlagsT.resetGainUpdate$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void resetGainUpdate$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_ResetFlagsT.resetGainUpdate$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle resetRfUpdate$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("resetRfUpdate"));
+ public static VarHandle resetRfUpdate$VH() {
+ return sdrplay_api_ResetFlagsT.resetRfUpdate$VH;
+ }
+ public static byte resetRfUpdate$get(MemorySegment seg) {
+ return (byte)sdrplay_api_ResetFlagsT.resetRfUpdate$VH.get(seg);
+ }
+ public static void resetRfUpdate$set( MemorySegment seg, byte x) {
+ sdrplay_api_ResetFlagsT.resetRfUpdate$VH.set(seg, x);
+ }
+ public static byte resetRfUpdate$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_ResetFlagsT.resetRfUpdate$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void resetRfUpdate$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_ResetFlagsT.resetRfUpdate$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle resetFsUpdate$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("resetFsUpdate"));
+ public static VarHandle resetFsUpdate$VH() {
+ return sdrplay_api_ResetFlagsT.resetFsUpdate$VH;
+ }
+ public static byte resetFsUpdate$get(MemorySegment seg) {
+ return (byte)sdrplay_api_ResetFlagsT.resetFsUpdate$VH.get(seg);
+ }
+ public static void resetFsUpdate$set( MemorySegment seg, byte x) {
+ sdrplay_api_ResetFlagsT.resetFsUpdate$VH.set(seg, x);
+ }
+ public static byte resetFsUpdate$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_ResetFlagsT.resetFsUpdate$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void resetFsUpdate$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_ResetFlagsT.resetFsUpdate$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RfFreqT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RfFreqT.java
new file mode 100644
index 000000000..ed54aa0c1
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RfFreqT.java
@@ -0,0 +1,62 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_RfFreqT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_DOUBLE$LAYOUT.withName("rfHz"),
+ Constants$root.C_CHAR$LAYOUT.withName("syncUpdate"),
+ MemoryLayout.paddingLayout(56)
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_RfFreqT.$struct$LAYOUT;
+ }
+ static final VarHandle rfHz$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfHz"));
+ public static VarHandle rfHz$VH() {
+ return sdrplay_api_RfFreqT.rfHz$VH;
+ }
+ public static double rfHz$get(MemorySegment seg) {
+ return (double)sdrplay_api_RfFreqT.rfHz$VH.get(seg);
+ }
+ public static void rfHz$set( MemorySegment seg, double x) {
+ sdrplay_api_RfFreqT.rfHz$VH.set(seg, x);
+ }
+ public static double rfHz$get(MemorySegment seg, long index) {
+ return (double)sdrplay_api_RfFreqT.rfHz$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfHz$set(MemorySegment seg, long index, double x) {
+ sdrplay_api_RfFreqT.rfHz$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle syncUpdate$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("syncUpdate"));
+ public static VarHandle syncUpdate$VH() {
+ return sdrplay_api_RfFreqT.syncUpdate$VH;
+ }
+ public static byte syncUpdate$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RfFreqT.syncUpdate$VH.get(seg);
+ }
+ public static void syncUpdate$set( MemorySegment seg, byte x) {
+ sdrplay_api_RfFreqT.syncUpdate$VH.set(seg, x);
+ }
+ public static byte syncUpdate$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RfFreqT.syncUpdate$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void syncUpdate$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RfFreqT.syncUpdate$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Rsp1aParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Rsp1aParamsT.java
new file mode 100644
index 000000000..d48d979e3
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Rsp1aParamsT.java
@@ -0,0 +1,61 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_Rsp1aParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("rfNotchEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfDabNotchEnable")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_Rsp1aParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle rfNotchEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfNotchEnable"));
+ public static VarHandle rfNotchEnable$VH() {
+ return sdrplay_api_Rsp1aParamsT.rfNotchEnable$VH;
+ }
+ public static byte rfNotchEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_Rsp1aParamsT.rfNotchEnable$VH.get(seg);
+ }
+ public static void rfNotchEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_Rsp1aParamsT.rfNotchEnable$VH.set(seg, x);
+ }
+ public static byte rfNotchEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_Rsp1aParamsT.rfNotchEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfNotchEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_Rsp1aParamsT.rfNotchEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rfDabNotchEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfDabNotchEnable"));
+ public static VarHandle rfDabNotchEnable$VH() {
+ return sdrplay_api_Rsp1aParamsT.rfDabNotchEnable$VH;
+ }
+ public static byte rfDabNotchEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_Rsp1aParamsT.rfDabNotchEnable$VH.get(seg);
+ }
+ public static void rfDabNotchEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_Rsp1aParamsT.rfDabNotchEnable$VH.set(seg, x);
+ }
+ public static byte rfDabNotchEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_Rsp1aParamsT.rfDabNotchEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfDabNotchEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_Rsp1aParamsT.rfDabNotchEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Rsp1aTunerParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Rsp1aTunerParamsT.java
new file mode 100644
index 000000000..afb62b2e8
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Rsp1aTunerParamsT.java
@@ -0,0 +1,44 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_Rsp1aTunerParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("biasTEnable")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_Rsp1aTunerParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle biasTEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("biasTEnable"));
+ public static VarHandle biasTEnable$VH() {
+ return sdrplay_api_Rsp1aTunerParamsT.biasTEnable$VH;
+ }
+ public static byte biasTEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_Rsp1aTunerParamsT.biasTEnable$VH.get(seg);
+ }
+ public static void biasTEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_Rsp1aTunerParamsT.biasTEnable$VH.set(seg, x);
+ }
+ public static byte biasTEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_Rsp1aTunerParamsT.biasTEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void biasTEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_Rsp1aTunerParamsT.biasTEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Rsp2ParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Rsp2ParamsT.java
new file mode 100644
index 000000000..c668c179d
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Rsp2ParamsT.java
@@ -0,0 +1,44 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_Rsp2ParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("extRefOutputEn")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_Rsp2ParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle extRefOutputEn$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("extRefOutputEn"));
+ public static VarHandle extRefOutputEn$VH() {
+ return sdrplay_api_Rsp2ParamsT.extRefOutputEn$VH;
+ }
+ public static byte extRefOutputEn$get(MemorySegment seg) {
+ return (byte)sdrplay_api_Rsp2ParamsT.extRefOutputEn$VH.get(seg);
+ }
+ public static void extRefOutputEn$set( MemorySegment seg, byte x) {
+ sdrplay_api_Rsp2ParamsT.extRefOutputEn$VH.set(seg, x);
+ }
+ public static byte extRefOutputEn$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_Rsp2ParamsT.extRefOutputEn$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void extRefOutputEn$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_Rsp2ParamsT.extRefOutputEn$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Rsp2TunerParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Rsp2TunerParamsT.java
new file mode 100644
index 000000000..f814a873f
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Rsp2TunerParamsT.java
@@ -0,0 +1,97 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_Rsp2TunerParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("biasTEnable"),
+ MemoryLayout.paddingLayout(24),
+ Constants$root.C_LONG$LAYOUT.withName("amPortSel"),
+ Constants$root.C_LONG$LAYOUT.withName("antennaSel"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfNotchEnable"),
+ MemoryLayout.paddingLayout(24)
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_Rsp2TunerParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle biasTEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("biasTEnable"));
+ public static VarHandle biasTEnable$VH() {
+ return sdrplay_api_Rsp2TunerParamsT.biasTEnable$VH;
+ }
+ public static byte biasTEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_Rsp2TunerParamsT.biasTEnable$VH.get(seg);
+ }
+ public static void biasTEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_Rsp2TunerParamsT.biasTEnable$VH.set(seg, x);
+ }
+ public static byte biasTEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_Rsp2TunerParamsT.biasTEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void biasTEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_Rsp2TunerParamsT.biasTEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle amPortSel$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("amPortSel"));
+ public static VarHandle amPortSel$VH() {
+ return sdrplay_api_Rsp2TunerParamsT.amPortSel$VH;
+ }
+ public static int amPortSel$get(MemorySegment seg) {
+ return (int)sdrplay_api_Rsp2TunerParamsT.amPortSel$VH.get(seg);
+ }
+ public static void amPortSel$set( MemorySegment seg, int x) {
+ sdrplay_api_Rsp2TunerParamsT.amPortSel$VH.set(seg, x);
+ }
+ public static int amPortSel$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_Rsp2TunerParamsT.amPortSel$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void amPortSel$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_Rsp2TunerParamsT.amPortSel$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle antennaSel$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("antennaSel"));
+ public static VarHandle antennaSel$VH() {
+ return sdrplay_api_Rsp2TunerParamsT.antennaSel$VH;
+ }
+ public static int antennaSel$get(MemorySegment seg) {
+ return (int)sdrplay_api_Rsp2TunerParamsT.antennaSel$VH.get(seg);
+ }
+ public static void antennaSel$set( MemorySegment seg, int x) {
+ sdrplay_api_Rsp2TunerParamsT.antennaSel$VH.set(seg, x);
+ }
+ public static int antennaSel$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_Rsp2TunerParamsT.antennaSel$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void antennaSel$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_Rsp2TunerParamsT.antennaSel$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rfNotchEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfNotchEnable"));
+ public static VarHandle rfNotchEnable$VH() {
+ return sdrplay_api_Rsp2TunerParamsT.rfNotchEnable$VH;
+ }
+ public static byte rfNotchEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_Rsp2TunerParamsT.rfNotchEnable$VH.get(seg);
+ }
+ public static void rfNotchEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_Rsp2TunerParamsT.rfNotchEnable$VH.set(seg, x);
+ }
+ public static byte rfNotchEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_Rsp2TunerParamsT.rfNotchEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfNotchEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_Rsp2TunerParamsT.rfNotchEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RspDuoModeCbParamT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RspDuoModeCbParamT.java
new file mode 100644
index 000000000..f5f18e963
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RspDuoModeCbParamT.java
@@ -0,0 +1,44 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_RspDuoModeCbParamT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("modeChangeType")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_RspDuoModeCbParamT.$struct$LAYOUT;
+ }
+ static final VarHandle modeChangeType$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("modeChangeType"));
+ public static VarHandle modeChangeType$VH() {
+ return sdrplay_api_RspDuoModeCbParamT.modeChangeType$VH;
+ }
+ public static int modeChangeType$get(MemorySegment seg) {
+ return (int)sdrplay_api_RspDuoModeCbParamT.modeChangeType$VH.get(seg);
+ }
+ public static void modeChangeType$set( MemorySegment seg, int x) {
+ sdrplay_api_RspDuoModeCbParamT.modeChangeType$VH.set(seg, x);
+ }
+ public static int modeChangeType$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_RspDuoModeCbParamT.modeChangeType$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void modeChangeType$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_RspDuoModeCbParamT.modeChangeType$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RspDuoParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RspDuoParamsT.java
new file mode 100644
index 000000000..2b08a48e7
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RspDuoParamsT.java
@@ -0,0 +1,44 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_RspDuoParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("extRefOutputEn")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_RspDuoParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle extRefOutputEn$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("extRefOutputEn"));
+ public static VarHandle extRefOutputEn$VH() {
+ return sdrplay_api_RspDuoParamsT.extRefOutputEn$VH;
+ }
+ public static int extRefOutputEn$get(MemorySegment seg) {
+ return (int)sdrplay_api_RspDuoParamsT.extRefOutputEn$VH.get(seg);
+ }
+ public static void extRefOutputEn$set( MemorySegment seg, int x) {
+ sdrplay_api_RspDuoParamsT.extRefOutputEn$VH.set(seg, x);
+ }
+ public static int extRefOutputEn$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_RspDuoParamsT.extRefOutputEn$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void extRefOutputEn$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_RspDuoParamsT.extRefOutputEn$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RspDuoTunerParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RspDuoTunerParamsT.java
new file mode 100644
index 000000000..4daa64e29
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RspDuoTunerParamsT.java
@@ -0,0 +1,114 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_RspDuoTunerParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("biasTEnable"),
+ MemoryLayout.paddingLayout(24),
+ Constants$root.C_LONG$LAYOUT.withName("tuner1AmPortSel"),
+ Constants$root.C_CHAR$LAYOUT.withName("tuner1AmNotchEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfNotchEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfDabNotchEnable"),
+ MemoryLayout.paddingLayout(8)
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_RspDuoTunerParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle biasTEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("biasTEnable"));
+ public static VarHandle biasTEnable$VH() {
+ return sdrplay_api_RspDuoTunerParamsT.biasTEnable$VH;
+ }
+ public static byte biasTEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RspDuoTunerParamsT.biasTEnable$VH.get(seg);
+ }
+ public static void biasTEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_RspDuoTunerParamsT.biasTEnable$VH.set(seg, x);
+ }
+ public static byte biasTEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RspDuoTunerParamsT.biasTEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void biasTEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RspDuoTunerParamsT.biasTEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle tuner1AmPortSel$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("tuner1AmPortSel"));
+ public static VarHandle tuner1AmPortSel$VH() {
+ return sdrplay_api_RspDuoTunerParamsT.tuner1AmPortSel$VH;
+ }
+ public static int tuner1AmPortSel$get(MemorySegment seg) {
+ return (int)sdrplay_api_RspDuoTunerParamsT.tuner1AmPortSel$VH.get(seg);
+ }
+ public static void tuner1AmPortSel$set( MemorySegment seg, int x) {
+ sdrplay_api_RspDuoTunerParamsT.tuner1AmPortSel$VH.set(seg, x);
+ }
+ public static int tuner1AmPortSel$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_RspDuoTunerParamsT.tuner1AmPortSel$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void tuner1AmPortSel$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_RspDuoTunerParamsT.tuner1AmPortSel$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle tuner1AmNotchEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("tuner1AmNotchEnable"));
+ public static VarHandle tuner1AmNotchEnable$VH() {
+ return sdrplay_api_RspDuoTunerParamsT.tuner1AmNotchEnable$VH;
+ }
+ public static byte tuner1AmNotchEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RspDuoTunerParamsT.tuner1AmNotchEnable$VH.get(seg);
+ }
+ public static void tuner1AmNotchEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_RspDuoTunerParamsT.tuner1AmNotchEnable$VH.set(seg, x);
+ }
+ public static byte tuner1AmNotchEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RspDuoTunerParamsT.tuner1AmNotchEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void tuner1AmNotchEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RspDuoTunerParamsT.tuner1AmNotchEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rfNotchEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfNotchEnable"));
+ public static VarHandle rfNotchEnable$VH() {
+ return sdrplay_api_RspDuoTunerParamsT.rfNotchEnable$VH;
+ }
+ public static byte rfNotchEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RspDuoTunerParamsT.rfNotchEnable$VH.get(seg);
+ }
+ public static void rfNotchEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_RspDuoTunerParamsT.rfNotchEnable$VH.set(seg, x);
+ }
+ public static byte rfNotchEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RspDuoTunerParamsT.rfNotchEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfNotchEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RspDuoTunerParamsT.rfNotchEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rfDabNotchEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfDabNotchEnable"));
+ public static VarHandle rfDabNotchEnable$VH() {
+ return sdrplay_api_RspDuoTunerParamsT.rfDabNotchEnable$VH;
+ }
+ public static byte rfDabNotchEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RspDuoTunerParamsT.rfDabNotchEnable$VH.get(seg);
+ }
+ public static void rfDabNotchEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_RspDuoTunerParamsT.rfDabNotchEnable$VH.set(seg, x);
+ }
+ public static byte rfDabNotchEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RspDuoTunerParamsT.rfDabNotchEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfDabNotchEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RspDuoTunerParamsT.rfDabNotchEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RspDxParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RspDxParamsT.java
new file mode 100644
index 000000000..285357928
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RspDxParamsT.java
@@ -0,0 +1,114 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_RspDxParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("hdrEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("biasTEnable"),
+ MemoryLayout.paddingLayout(16),
+ Constants$root.C_LONG$LAYOUT.withName("antennaSel"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfNotchEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfDabNotchEnable"),
+ MemoryLayout.paddingLayout(16)
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_RspDxParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle hdrEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("hdrEnable"));
+ public static VarHandle hdrEnable$VH() {
+ return sdrplay_api_RspDxParamsT.hdrEnable$VH;
+ }
+ public static byte hdrEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RspDxParamsT.hdrEnable$VH.get(seg);
+ }
+ public static void hdrEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_RspDxParamsT.hdrEnable$VH.set(seg, x);
+ }
+ public static byte hdrEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RspDxParamsT.hdrEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void hdrEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RspDxParamsT.hdrEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle biasTEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("biasTEnable"));
+ public static VarHandle biasTEnable$VH() {
+ return sdrplay_api_RspDxParamsT.biasTEnable$VH;
+ }
+ public static byte biasTEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RspDxParamsT.biasTEnable$VH.get(seg);
+ }
+ public static void biasTEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_RspDxParamsT.biasTEnable$VH.set(seg, x);
+ }
+ public static byte biasTEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RspDxParamsT.biasTEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void biasTEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RspDxParamsT.biasTEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle antennaSel$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("antennaSel"));
+ public static VarHandle antennaSel$VH() {
+ return sdrplay_api_RspDxParamsT.antennaSel$VH;
+ }
+ public static int antennaSel$get(MemorySegment seg) {
+ return (int)sdrplay_api_RspDxParamsT.antennaSel$VH.get(seg);
+ }
+ public static void antennaSel$set( MemorySegment seg, int x) {
+ sdrplay_api_RspDxParamsT.antennaSel$VH.set(seg, x);
+ }
+ public static int antennaSel$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_RspDxParamsT.antennaSel$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void antennaSel$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_RspDxParamsT.antennaSel$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rfNotchEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfNotchEnable"));
+ public static VarHandle rfNotchEnable$VH() {
+ return sdrplay_api_RspDxParamsT.rfNotchEnable$VH;
+ }
+ public static byte rfNotchEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RspDxParamsT.rfNotchEnable$VH.get(seg);
+ }
+ public static void rfNotchEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_RspDxParamsT.rfNotchEnable$VH.set(seg, x);
+ }
+ public static byte rfNotchEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RspDxParamsT.rfNotchEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfNotchEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RspDxParamsT.rfNotchEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rfDabNotchEnable$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfDabNotchEnable"));
+ public static VarHandle rfDabNotchEnable$VH() {
+ return sdrplay_api_RspDxParamsT.rfDabNotchEnable$VH;
+ }
+ public static byte rfDabNotchEnable$get(MemorySegment seg) {
+ return (byte)sdrplay_api_RspDxParamsT.rfDabNotchEnable$VH.get(seg);
+ }
+ public static void rfDabNotchEnable$set( MemorySegment seg, byte x) {
+ sdrplay_api_RspDxParamsT.rfDabNotchEnable$VH.set(seg, x);
+ }
+ public static byte rfDabNotchEnable$get(MemorySegment seg, long index) {
+ return (byte)sdrplay_api_RspDxParamsT.rfDabNotchEnable$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfDabNotchEnable$set(MemorySegment seg, long index, byte x) {
+ sdrplay_api_RspDxParamsT.rfDabNotchEnable$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RspDxTunerParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RspDxTunerParamsT.java
new file mode 100644
index 000000000..41325bc6c
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RspDxTunerParamsT.java
@@ -0,0 +1,44 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_RspDxTunerParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("hdrBw")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_RspDxTunerParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle hdrBw$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("hdrBw"));
+ public static VarHandle hdrBw$VH() {
+ return sdrplay_api_RspDxTunerParamsT.hdrBw$VH;
+ }
+ public static int hdrBw$get(MemorySegment seg) {
+ return (int)sdrplay_api_RspDxTunerParamsT.hdrBw$VH.get(seg);
+ }
+ public static void hdrBw$set( MemorySegment seg, int x) {
+ sdrplay_api_RspDxTunerParamsT.hdrBw$VH.set(seg, x);
+ }
+ public static int hdrBw$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_RspDxTunerParamsT.hdrBw$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void hdrBw$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_RspDxTunerParamsT.hdrBw$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RxChannelParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RxChannelParamsT.java
new file mode 100644
index 000000000..db48f2649
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_RxChannelParamsT.java
@@ -0,0 +1,122 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+public class sdrplay_api_RxChannelParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("bwType"),
+ Constants$root.C_LONG$LAYOUT.withName("ifType"),
+ Constants$root.C_LONG$LAYOUT.withName("loMode"),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("gRdB"),
+ Constants$root.C_CHAR$LAYOUT.withName("LNAstate"),
+ Constants$root.C_CHAR$LAYOUT.withName("syncUpdate"),
+ MemoryLayout.paddingLayout(16),
+ Constants$root.C_LONG$LAYOUT.withName("minGr"),
+ MemoryLayout.structLayout(
+ Constants$root.C_FLOAT$LAYOUT.withName("curr"),
+ Constants$root.C_FLOAT$LAYOUT.withName("max"),
+ Constants$root.C_FLOAT$LAYOUT.withName("min")
+ ).withName("gainVals")
+ ).withName("gain"),
+ MemoryLayout.paddingLayout(32),
+ MemoryLayout.structLayout(
+ Constants$root.C_DOUBLE$LAYOUT.withName("rfHz"),
+ Constants$root.C_CHAR$LAYOUT.withName("syncUpdate"),
+ MemoryLayout.paddingLayout(56)
+ ).withName("rfFreq"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("dcCal"),
+ Constants$root.C_CHAR$LAYOUT.withName("speedUp"),
+ MemoryLayout.paddingLayout(16),
+ Constants$root.C_LONG$LAYOUT.withName("trackTime"),
+ Constants$root.C_LONG$LAYOUT.withName("refreshRateTime")
+ ).withName("dcOffsetTuner"),
+ MemoryLayout.paddingLayout(32)
+ ).withName("tunerParams"),
+ MemoryLayout.structLayout(
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("DCenable"),
+ Constants$root.C_CHAR$LAYOUT.withName("IQenable")
+ ).withName("dcOffset"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("enable"),
+ Constants$root.C_CHAR$LAYOUT.withName("decimationFactor"),
+ Constants$root.C_CHAR$LAYOUT.withName("wideBandSignal")
+ ).withName("decimation"),
+ MemoryLayout.paddingLayout(24),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("enable"),
+ Constants$root.C_LONG$LAYOUT.withName("setPoint_dBfs"),
+ Constants$root.C_SHORT$LAYOUT.withName("attack_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_delay_ms"),
+ Constants$root.C_SHORT$LAYOUT.withName("decay_threshold_dB"),
+ Constants$root.C_LONG$LAYOUT.withName("syncUpdate")
+ ).withName("agc"),
+ Constants$root.C_LONG$LAYOUT.withName("adsbMode")
+ ).withName("ctrlParams"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("biasTEnable")
+ ).withName("rsp1aTunerParams"),
+ MemoryLayout.paddingLayout(24),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("biasTEnable"),
+ MemoryLayout.paddingLayout(24),
+ Constants$root.C_LONG$LAYOUT.withName("amPortSel"),
+ Constants$root.C_LONG$LAYOUT.withName("antennaSel"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfNotchEnable"),
+ MemoryLayout.paddingLayout(24)
+ ).withName("rsp2TunerParams"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("biasTEnable"),
+ MemoryLayout.paddingLayout(24),
+ Constants$root.C_LONG$LAYOUT.withName("tuner1AmPortSel"),
+ Constants$root.C_CHAR$LAYOUT.withName("tuner1AmNotchEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfNotchEnable"),
+ Constants$root.C_CHAR$LAYOUT.withName("rfDabNotchEnable"),
+ MemoryLayout.paddingLayout(8)
+ ).withName("rspDuoTunerParams"),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("hdrBw")
+ ).withName("rspDxTunerParams"),
+ MemoryLayout.paddingLayout(32)
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_RxChannelParamsT.$struct$LAYOUT;
+ }
+ public static MemorySegment tunerParams$slice(MemorySegment seg) {
+ return seg.asSlice(0, 72);
+ }
+ public static MemorySegment ctrlParams$slice(MemorySegment seg) {
+ return seg.asSlice(72, 32);
+ }
+ public static MemorySegment rsp1aTunerParams$slice(MemorySegment seg) {
+ return seg.asSlice(104, 1);
+ }
+ public static MemorySegment rsp2TunerParams$slice(MemorySegment seg) {
+ return seg.asSlice(108, 16);
+ }
+ public static MemorySegment rspDuoTunerParams$slice(MemorySegment seg) {
+ return seg.asSlice(124, 12);
+ }
+ public static MemorySegment rspDxTunerParams$slice(MemorySegment seg) {
+ return seg.asSlice(136, 4);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_SelectDevice_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_SelectDevice_t.java
new file mode 100644
index 000000000..f37ff9f9c
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_SelectDevice_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_SelectDevice_t {
+
+ int apply(java.lang.foreign.MemoryAddress device);
+ static MemorySegment allocate(sdrplay_api_SelectDevice_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_SelectDevice_t.class, fi, constants$2.sdrplay_api_SelectDevice_t$FUNC, session);
+ }
+ static sdrplay_api_SelectDevice_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _device) -> {
+ try {
+ return (int)constants$2.sdrplay_api_SelectDevice_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_device);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_StreamCallback_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_StreamCallback_t.java
new file mode 100644
index 000000000..029027bd0
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_StreamCallback_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_StreamCallback_t {
+
+ void apply(java.lang.foreign.MemoryAddress xi, java.lang.foreign.MemoryAddress xq, java.lang.foreign.MemoryAddress params, int numSamples, int reset, java.lang.foreign.MemoryAddress cbContext);
+ static MemorySegment allocate(sdrplay_api_StreamCallback_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_StreamCallback_t.class, fi, constants$0.sdrplay_api_StreamCallback_t$FUNC, session);
+ }
+ static sdrplay_api_StreamCallback_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _xi, java.lang.foreign.MemoryAddress _xq, java.lang.foreign.MemoryAddress _params, int _numSamples, int _reset, java.lang.foreign.MemoryAddress _cbContext) -> {
+ try {
+ constants$0.sdrplay_api_StreamCallback_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_xi, (java.lang.foreign.Addressable)_xq, (java.lang.foreign.Addressable)_params, _numSamples, _reset, (java.lang.foreign.Addressable)_cbContext);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_StreamCbParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_StreamCbParamsT.java
new file mode 100644
index 000000000..d412615a5
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_StreamCbParamsT.java
@@ -0,0 +1,112 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_StreamCbParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("firstSampleNum"),
+ Constants$root.C_LONG$LAYOUT.withName("grChanged"),
+ Constants$root.C_LONG$LAYOUT.withName("rfChanged"),
+ Constants$root.C_LONG$LAYOUT.withName("fsChanged"),
+ Constants$root.C_LONG$LAYOUT.withName("numSamples")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_StreamCbParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle firstSampleNum$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("firstSampleNum"));
+ public static VarHandle firstSampleNum$VH() {
+ return sdrplay_api_StreamCbParamsT.firstSampleNum$VH;
+ }
+ public static int firstSampleNum$get(MemorySegment seg) {
+ return (int)sdrplay_api_StreamCbParamsT.firstSampleNum$VH.get(seg);
+ }
+ public static void firstSampleNum$set( MemorySegment seg, int x) {
+ sdrplay_api_StreamCbParamsT.firstSampleNum$VH.set(seg, x);
+ }
+ public static int firstSampleNum$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_StreamCbParamsT.firstSampleNum$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void firstSampleNum$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_StreamCbParamsT.firstSampleNum$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle grChanged$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("grChanged"));
+ public static VarHandle grChanged$VH() {
+ return sdrplay_api_StreamCbParamsT.grChanged$VH;
+ }
+ public static int grChanged$get(MemorySegment seg) {
+ return (int)sdrplay_api_StreamCbParamsT.grChanged$VH.get(seg);
+ }
+ public static void grChanged$set( MemorySegment seg, int x) {
+ sdrplay_api_StreamCbParamsT.grChanged$VH.set(seg, x);
+ }
+ public static int grChanged$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_StreamCbParamsT.grChanged$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void grChanged$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_StreamCbParamsT.grChanged$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle rfChanged$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("rfChanged"));
+ public static VarHandle rfChanged$VH() {
+ return sdrplay_api_StreamCbParamsT.rfChanged$VH;
+ }
+ public static int rfChanged$get(MemorySegment seg) {
+ return (int)sdrplay_api_StreamCbParamsT.rfChanged$VH.get(seg);
+ }
+ public static void rfChanged$set( MemorySegment seg, int x) {
+ sdrplay_api_StreamCbParamsT.rfChanged$VH.set(seg, x);
+ }
+ public static int rfChanged$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_StreamCbParamsT.rfChanged$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void rfChanged$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_StreamCbParamsT.rfChanged$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle fsChanged$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("fsChanged"));
+ public static VarHandle fsChanged$VH() {
+ return sdrplay_api_StreamCbParamsT.fsChanged$VH;
+ }
+ public static int fsChanged$get(MemorySegment seg) {
+ return (int)sdrplay_api_StreamCbParamsT.fsChanged$VH.get(seg);
+ }
+ public static void fsChanged$set( MemorySegment seg, int x) {
+ sdrplay_api_StreamCbParamsT.fsChanged$VH.set(seg, x);
+ }
+ public static int fsChanged$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_StreamCbParamsT.fsChanged$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void fsChanged$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_StreamCbParamsT.fsChanged$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle numSamples$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("numSamples"));
+ public static VarHandle numSamples$VH() {
+ return sdrplay_api_StreamCbParamsT.numSamples$VH;
+ }
+ public static int numSamples$get(MemorySegment seg) {
+ return (int)sdrplay_api_StreamCbParamsT.numSamples$VH.get(seg);
+ }
+ public static void numSamples$set( MemorySegment seg, int x) {
+ sdrplay_api_StreamCbParamsT.numSamples$VH.set(seg, x);
+ }
+ public static int numSamples$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_StreamCbParamsT.numSamples$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void numSamples$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_StreamCbParamsT.numSamples$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_SwapRspDuoActiveTuner_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_SwapRspDuoActiveTuner_t.java
new file mode 100644
index 000000000..b28289d6a
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_SwapRspDuoActiveTuner_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_SwapRspDuoActiveTuner_t {
+
+ int apply(java.lang.foreign.MemoryAddress dev, java.lang.foreign.MemoryAddress tuner, int tuner1AmPortSel);
+ static MemorySegment allocate(sdrplay_api_SwapRspDuoActiveTuner_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_SwapRspDuoActiveTuner_t.class, fi, constants$6.sdrplay_api_SwapRspDuoActiveTuner_t$FUNC, session);
+ }
+ static sdrplay_api_SwapRspDuoActiveTuner_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _dev, java.lang.foreign.MemoryAddress _tuner, int _tuner1AmPortSel) -> {
+ try {
+ return (int)constants$6.sdrplay_api_SwapRspDuoActiveTuner_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_dev, (java.lang.foreign.Addressable)_tuner, _tuner1AmPortSel);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t.java
new file mode 100644
index 000000000..987f5747b
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t {
+
+ int apply(java.lang.foreign.MemoryAddress currentSampleRate, double newSampleRate);
+ static MemorySegment allocate(sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t.class, fi, constants$6.sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t$FUNC, session);
+ }
+ static sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _currentSampleRate, double _newSampleRate) -> {
+ try {
+ return (int)constants$6.sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_currentSampleRate, _newSampleRate);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_SwapRspDuoMode_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_SwapRspDuoMode_t.java
new file mode 100644
index 000000000..7b13b348f
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_SwapRspDuoMode_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_SwapRspDuoMode_t {
+
+ int apply(java.lang.foreign.MemoryAddress currDevice, java.lang.foreign.MemoryAddress deviceParams, int rspDuoMode, double sampleRate, int tuner, int bwType, int ifType, int tuner1AmPortSel);
+ static MemorySegment allocate(sdrplay_api_SwapRspDuoMode_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_SwapRspDuoMode_t.class, fi, constants$6.sdrplay_api_SwapRspDuoMode_t$FUNC, session);
+ }
+ static sdrplay_api_SwapRspDuoMode_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _currDevice, java.lang.foreign.MemoryAddress _deviceParams, int _rspDuoMode, double _sampleRate, int _tuner, int _bwType, int _ifType, int _tuner1AmPortSel) -> {
+ try {
+ return (int)constants$6.sdrplay_api_SwapRspDuoMode_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_currDevice, (java.lang.foreign.Addressable)_deviceParams, _rspDuoMode, _sampleRate, _tuner, _bwType, _ifType, _tuner1AmPortSel);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_SyncUpdateT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_SyncUpdateT.java
new file mode 100644
index 000000000..9ea8d932d
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_SyncUpdateT.java
@@ -0,0 +1,61 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_SyncUpdateT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("sampleNum"),
+ Constants$root.C_LONG$LAYOUT.withName("period")
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_SyncUpdateT.$struct$LAYOUT;
+ }
+ static final VarHandle sampleNum$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("sampleNum"));
+ public static VarHandle sampleNum$VH() {
+ return sdrplay_api_SyncUpdateT.sampleNum$VH;
+ }
+ public static int sampleNum$get(MemorySegment seg) {
+ return (int)sdrplay_api_SyncUpdateT.sampleNum$VH.get(seg);
+ }
+ public static void sampleNum$set( MemorySegment seg, int x) {
+ sdrplay_api_SyncUpdateT.sampleNum$VH.set(seg, x);
+ }
+ public static int sampleNum$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_SyncUpdateT.sampleNum$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void sampleNum$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_SyncUpdateT.sampleNum$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle period$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("period"));
+ public static VarHandle period$VH() {
+ return sdrplay_api_SyncUpdateT.period$VH;
+ }
+ public static int period$get(MemorySegment seg) {
+ return (int)sdrplay_api_SyncUpdateT.period$VH.get(seg);
+ }
+ public static void period$set( MemorySegment seg, int x) {
+ sdrplay_api_SyncUpdateT.period$VH.set(seg, x);
+ }
+ public static int period$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_SyncUpdateT.period$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void period$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_SyncUpdateT.period$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_TunerParamsT.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_TunerParamsT.java
new file mode 100644
index 000000000..8e34576ed
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_TunerParamsT.java
@@ -0,0 +1,113 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+import java.lang.foreign.SegmentAllocator;
+import java.lang.invoke.VarHandle;
+public class sdrplay_api_TunerParamsT {
+
+ static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("bwType"),
+ Constants$root.C_LONG$LAYOUT.withName("ifType"),
+ Constants$root.C_LONG$LAYOUT.withName("loMode"),
+ MemoryLayout.structLayout(
+ Constants$root.C_LONG$LAYOUT.withName("gRdB"),
+ Constants$root.C_CHAR$LAYOUT.withName("LNAstate"),
+ Constants$root.C_CHAR$LAYOUT.withName("syncUpdate"),
+ MemoryLayout.paddingLayout(16),
+ Constants$root.C_LONG$LAYOUT.withName("minGr"),
+ MemoryLayout.structLayout(
+ Constants$root.C_FLOAT$LAYOUT.withName("curr"),
+ Constants$root.C_FLOAT$LAYOUT.withName("max"),
+ Constants$root.C_FLOAT$LAYOUT.withName("min")
+ ).withName("gainVals")
+ ).withName("gain"),
+ MemoryLayout.paddingLayout(32),
+ MemoryLayout.structLayout(
+ Constants$root.C_DOUBLE$LAYOUT.withName("rfHz"),
+ Constants$root.C_CHAR$LAYOUT.withName("syncUpdate"),
+ MemoryLayout.paddingLayout(56)
+ ).withName("rfFreq"),
+ MemoryLayout.structLayout(
+ Constants$root.C_CHAR$LAYOUT.withName("dcCal"),
+ Constants$root.C_CHAR$LAYOUT.withName("speedUp"),
+ MemoryLayout.paddingLayout(16),
+ Constants$root.C_LONG$LAYOUT.withName("trackTime"),
+ Constants$root.C_LONG$LAYOUT.withName("refreshRateTime")
+ ).withName("dcOffsetTuner"),
+ MemoryLayout.paddingLayout(32)
+ );
+ public static MemoryLayout $LAYOUT() {
+ return sdrplay_api_TunerParamsT.$struct$LAYOUT;
+ }
+ static final VarHandle bwType$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("bwType"));
+ public static VarHandle bwType$VH() {
+ return sdrplay_api_TunerParamsT.bwType$VH;
+ }
+ public static int bwType$get(MemorySegment seg) {
+ return (int)sdrplay_api_TunerParamsT.bwType$VH.get(seg);
+ }
+ public static void bwType$set( MemorySegment seg, int x) {
+ sdrplay_api_TunerParamsT.bwType$VH.set(seg, x);
+ }
+ public static int bwType$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_TunerParamsT.bwType$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void bwType$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_TunerParamsT.bwType$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle ifType$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("ifType"));
+ public static VarHandle ifType$VH() {
+ return sdrplay_api_TunerParamsT.ifType$VH;
+ }
+ public static int ifType$get(MemorySegment seg) {
+ return (int)sdrplay_api_TunerParamsT.ifType$VH.get(seg);
+ }
+ public static void ifType$set( MemorySegment seg, int x) {
+ sdrplay_api_TunerParamsT.ifType$VH.set(seg, x);
+ }
+ public static int ifType$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_TunerParamsT.ifType$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void ifType$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_TunerParamsT.ifType$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ static final VarHandle loMode$VH = $struct$LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("loMode"));
+ public static VarHandle loMode$VH() {
+ return sdrplay_api_TunerParamsT.loMode$VH;
+ }
+ public static int loMode$get(MemorySegment seg) {
+ return (int)sdrplay_api_TunerParamsT.loMode$VH.get(seg);
+ }
+ public static void loMode$set( MemorySegment seg, int x) {
+ sdrplay_api_TunerParamsT.loMode$VH.set(seg, x);
+ }
+ public static int loMode$get(MemorySegment seg, long index) {
+ return (int)sdrplay_api_TunerParamsT.loMode$VH.get(seg.asSlice(index*sizeof()));
+ }
+ public static void loMode$set(MemorySegment seg, long index, int x) {
+ sdrplay_api_TunerParamsT.loMode$VH.set(seg.asSlice(index*sizeof()), x);
+ }
+ public static MemorySegment gain$slice(MemorySegment seg) {
+ return seg.asSlice(12, 24);
+ }
+ public static MemorySegment rfFreq$slice(MemorySegment seg) {
+ return seg.asSlice(40, 16);
+ }
+ public static MemorySegment dcOffsetTuner$slice(MemorySegment seg) {
+ return seg.asSlice(56, 12);
+ }
+ public static long sizeof() { return $LAYOUT().byteSize(); }
+ public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); }
+ public static MemorySegment allocateArray(int len, SegmentAllocator allocator) {
+ return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT()));
+ }
+ public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Uninit_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Uninit_t.java
new file mode 100644
index 000000000..0dc19bbae
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Uninit_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_Uninit_t {
+
+ int apply(java.lang.foreign.MemoryAddress dev);
+ static MemorySegment allocate(sdrplay_api_Uninit_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_Uninit_t.class, fi, constants$5.sdrplay_api_Uninit_t$FUNC, session);
+ }
+ static sdrplay_api_Uninit_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _dev) -> {
+ try {
+ return (int)constants$5.sdrplay_api_Uninit_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_dev);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_UnlockDeviceApi_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_UnlockDeviceApi_t.java
new file mode 100644
index 000000000..d7aa1f639
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_UnlockDeviceApi_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_UnlockDeviceApi_t {
+
+ int apply();
+ static MemorySegment allocate(sdrplay_api_UnlockDeviceApi_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_UnlockDeviceApi_t.class, fi, constants$2.sdrplay_api_UnlockDeviceApi_t$FUNC, session);
+ }
+ static sdrplay_api_UnlockDeviceApi_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return () -> {
+ try {
+ return (int)constants$2.sdrplay_api_UnlockDeviceApi_t$MH.invokeExact((Addressable)symbol);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Update_t.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Update_t.java
new file mode 100644
index 000000000..2caca357f
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_Update_t.java
@@ -0,0 +1,27 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.MemorySession;
+public interface sdrplay_api_Update_t {
+
+ int apply(java.lang.foreign.MemoryAddress dev, int tuner, int reasonForUpdate, int reasonForUpdateExt1);
+ static MemorySegment allocate(sdrplay_api_Update_t fi, MemorySession session) {
+ return RuntimeHelper.upcallStub(sdrplay_api_Update_t.class, fi, constants$5.sdrplay_api_Update_t$FUNC, session);
+ }
+ static sdrplay_api_Update_t ofAddress(MemoryAddress addr, MemorySession session) {
+ MemorySegment symbol = MemorySegment.ofAddress(addr, 0, session);
+ return (java.lang.foreign.MemoryAddress _dev, int _tuner, int _reasonForUpdate, int _reasonForUpdateExt1) -> {
+ try {
+ return (int)constants$5.sdrplay_api_Update_t$MH.invokeExact((Addressable)symbol, (java.lang.foreign.Addressable)_dev, _tuner, _reasonForUpdate, _reasonForUpdateExt1);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ };
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_h.java b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_h.java
new file mode 100644
index 000000000..067e97ebe
--- /dev/null
+++ b/sdrplay-api/src/main/java/com/github/dsheirer/sdrplay/api/v3_08/sdrplay_api_h.java
@@ -0,0 +1,740 @@
+// Generated by jextract
+
+package com.github.dsheirer.sdrplay.api.v3_08;
+
+import java.lang.foreign.Addressable;
+import java.lang.foreign.MemoryAddress;
+import java.lang.invoke.MethodHandle;
+
+import static java.lang.foreign.ValueLayout.OfAddress;
+import static java.lang.foreign.ValueLayout.OfByte;
+import static java.lang.foreign.ValueLayout.OfDouble;
+import static java.lang.foreign.ValueLayout.OfFloat;
+import static java.lang.foreign.ValueLayout.OfInt;
+import static java.lang.foreign.ValueLayout.OfLong;
+import static java.lang.foreign.ValueLayout.OfShort;
+public class sdrplay_api_h {
+
+ /* package-private */ sdrplay_api_h() {}
+ public static OfByte C_CHAR = Constants$root.C_CHAR$LAYOUT;
+ public static OfShort C_SHORT = Constants$root.C_SHORT$LAYOUT;
+ public static OfInt C_INT = Constants$root.C_LONG$LAYOUT;
+ public static OfInt C_LONG = Constants$root.C_LONG$LAYOUT;
+ public static OfLong C_LONG_LONG = Constants$root.C_LONG_LONG$LAYOUT;
+ public static OfFloat C_FLOAT = Constants$root.C_FLOAT$LAYOUT;
+ public static OfDouble C_DOUBLE = Constants$root.C_DOUBLE$LAYOUT;
+ public static OfAddress C_POINTER = Constants$root.C_POINTER$LAYOUT;
+ public static int RSPIA_NUM_LNA_STATES() {
+ return (int)10L;
+ }
+ public static int RSPIA_NUM_LNA_STATES_AM() {
+ return (int)7L;
+ }
+ public static int RSPIA_NUM_LNA_STATES_LBAND() {
+ return (int)9L;
+ }
+ public static int RSPII_NUM_LNA_STATES() {
+ return (int)9L;
+ }
+ public static int RSPII_NUM_LNA_STATES_AMPORT() {
+ return (int)5L;
+ }
+ public static int RSPII_NUM_LNA_STATES_420MHZ() {
+ return (int)6L;
+ }
+ public static int RSPDUO_NUM_LNA_STATES() {
+ return (int)10L;
+ }
+ public static int RSPDUO_NUM_LNA_STATES_AMPORT() {
+ return (int)5L;
+ }
+ public static int RSPDUO_NUM_LNA_STATES_AM() {
+ return (int)7L;
+ }
+ public static int RSPDUO_NUM_LNA_STATES_LBAND() {
+ return (int)9L;
+ }
+ public static int RSPDX_NUM_LNA_STATES() {
+ return (int)28L;
+ }
+ public static int RSPDX_NUM_LNA_STATES_AMPORT2_0_12() {
+ return (int)19L;
+ }
+ public static int RSPDX_NUM_LNA_STATES_AMPORT2_12_50() {
+ return (int)20L;
+ }
+ public static int RSPDX_NUM_LNA_STATES_AMPORT2_50_60() {
+ return (int)25L;
+ }
+ public static int RSPDX_NUM_LNA_STATES_VHF_BAND3() {
+ return (int)27L;
+ }
+ public static int RSPDX_NUM_LNA_STATES_420MHZ() {
+ return (int)21L;
+ }
+ public static int RSPDX_NUM_LNA_STATES_LBAND() {
+ return (int)19L;
+ }
+ public static int RSPDX_NUM_LNA_STATES_DX() {
+ return (int)22L;
+ }
+ public static int sdrplay_api_Rsp2_ANTENNA_A() {
+ return (int)5L;
+ }
+ public static int sdrplay_api_Rsp2_ANTENNA_B() {
+ return (int)6L;
+ }
+ public static int sdrplay_api_Rsp2_AMPORT_1() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_Rsp2_AMPORT_2() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_RspDuoMode_Unknown() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_RspDuoMode_Single_Tuner() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_RspDuoMode_Dual_Tuner() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_RspDuoMode_Master() {
+ return (int)4L;
+ }
+ public static int sdrplay_api_RspDuoMode_Slave() {
+ return (int)8L;
+ }
+ public static int sdrplay_api_RspDuo_AMPORT_1() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_RspDuo_AMPORT_2() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_BW_Undefined() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_BW_0_200() {
+ return (int)200L;
+ }
+ public static int sdrplay_api_BW_0_300() {
+ return (int)300L;
+ }
+ public static int sdrplay_api_BW_0_600() {
+ return (int)600L;
+ }
+ public static int sdrplay_api_BW_1_536() {
+ return (int)1536L;
+ }
+ public static int sdrplay_api_BW_5_000() {
+ return (int)5000L;
+ }
+ public static int sdrplay_api_BW_6_000() {
+ return (int)6000L;
+ }
+ public static int sdrplay_api_BW_7_000() {
+ return (int)7000L;
+ }
+ public static int sdrplay_api_BW_8_000() {
+ return (int)8000L;
+ }
+ public static int sdrplay_api_IF_Undefined() {
+ return (int)-1L;
+ }
+ public static int sdrplay_api_IF_Zero() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_IF_0_450() {
+ return (int)450L;
+ }
+ public static int sdrplay_api_IF_1_620() {
+ return (int)1620L;
+ }
+ public static int sdrplay_api_IF_2_048() {
+ return (int)2048L;
+ }
+ public static int sdrplay_api_LO_Undefined() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_LO_Auto() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_LO_120MHz() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_LO_144MHz() {
+ return (int)3L;
+ }
+ public static int sdrplay_api_LO_168MHz() {
+ return (int)4L;
+ }
+ public static int sdrplay_api_EXTENDED_MIN_GR() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_NORMAL_MIN_GR() {
+ return (int)20L;
+ }
+ public static int sdrplay_api_Tuner_Neither() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_Tuner_A() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_Tuner_B() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_Tuner_Both() {
+ return (int)3L;
+ }
+ public static int sdrplay_api_RspDx_ANTENNA_A() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_RspDx_ANTENNA_B() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_RspDx_ANTENNA_C() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_RspDx_HDRMODE_BW_0_200() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_RspDx_HDRMODE_BW_0_500() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_RspDx_HDRMODE_BW_1_200() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_RspDx_HDRMODE_BW_1_700() {
+ return (int)3L;
+ }
+ public static int sdrplay_api_ISOCH() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_BULK() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_AGC_DISABLE() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_AGC_100HZ() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_AGC_50HZ() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_AGC_5HZ() {
+ return (int)3L;
+ }
+ public static int sdrplay_api_AGC_CTRL_EN() {
+ return (int)4L;
+ }
+ public static int sdrplay_api_ADSB_DECIMATION() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_ADSB_NO_DECIMATION_LOWPASS() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_2MHZ() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_3MHZ() {
+ return (int)3L;
+ }
+ public static int sdrplay_api_Overload_Detected() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_Overload_Corrected() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_MasterInitialised() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_SlaveAttached() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_SlaveDetached() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_SlaveInitialised() {
+ return (int)3L;
+ }
+ public static int sdrplay_api_SlaveUninitialised() {
+ return (int)4L;
+ }
+ public static int sdrplay_api_MasterDllDisappeared() {
+ return (int)5L;
+ }
+ public static int sdrplay_api_SlaveDllDisappeared() {
+ return (int)6L;
+ }
+ public static int sdrplay_api_GainChange() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_PowerOverloadChange() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_DeviceRemoved() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_RspDuoModeChange() {
+ return (int)3L;
+ }
+ public static int sdrplay_api_DeviceFailure() {
+ return (int)4L;
+ }
+ public static OfAddress HANDLE = Constants$root.C_POINTER$LAYOUT;
+ public static int sdrplay_api_Success() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_Fail() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_InvalidParam() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_OutOfRange() {
+ return (int)3L;
+ }
+ public static int sdrplay_api_GainUpdateError() {
+ return (int)4L;
+ }
+ public static int sdrplay_api_RfUpdateError() {
+ return (int)5L;
+ }
+ public static int sdrplay_api_FsUpdateError() {
+ return (int)6L;
+ }
+ public static int sdrplay_api_HwError() {
+ return (int)7L;
+ }
+ public static int sdrplay_api_AliasingError() {
+ return (int)8L;
+ }
+ public static int sdrplay_api_AlreadyInitialised() {
+ return (int)9L;
+ }
+ public static int sdrplay_api_NotInitialised() {
+ return (int)10L;
+ }
+ public static int sdrplay_api_NotEnabled() {
+ return (int)11L;
+ }
+ public static int sdrplay_api_HwVerError() {
+ return (int)12L;
+ }
+ public static int sdrplay_api_OutOfMemError() {
+ return (int)13L;
+ }
+ public static int sdrplay_api_ServiceNotResponding() {
+ return (int)14L;
+ }
+ public static int sdrplay_api_StartPending() {
+ return (int)15L;
+ }
+ public static int sdrplay_api_StopPending() {
+ return (int)16L;
+ }
+ public static int sdrplay_api_InvalidMode() {
+ return (int)17L;
+ }
+ public static int sdrplay_api_FailedVerification1() {
+ return (int)18L;
+ }
+ public static int sdrplay_api_FailedVerification2() {
+ return (int)19L;
+ }
+ public static int sdrplay_api_FailedVerification3() {
+ return (int)20L;
+ }
+ public static int sdrplay_api_FailedVerification4() {
+ return (int)21L;
+ }
+ public static int sdrplay_api_FailedVerification5() {
+ return (int)22L;
+ }
+ public static int sdrplay_api_FailedVerification6() {
+ return (int)23L;
+ }
+ public static int sdrplay_api_InvalidServiceVersion() {
+ return (int)24L;
+ }
+ public static int sdrplay_api_Update_None() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_Update_Dev_Fs() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_Update_Dev_Ppm() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_Update_Dev_SyncUpdate() {
+ return (int)4L;
+ }
+ public static int sdrplay_api_Update_Dev_ResetFlags() {
+ return (int)8L;
+ }
+ public static int sdrplay_api_Update_Rsp1a_BiasTControl() {
+ return (int)16L;
+ }
+ public static int sdrplay_api_Update_Rsp1a_RfNotchControl() {
+ return (int)32L;
+ }
+ public static int sdrplay_api_Update_Rsp1a_RfDabNotchControl() {
+ return (int)64L;
+ }
+ public static int sdrplay_api_Update_Rsp2_BiasTControl() {
+ return (int)128L;
+ }
+ public static int sdrplay_api_Update_Rsp2_AmPortSelect() {
+ return (int)256L;
+ }
+ public static int sdrplay_api_Update_Rsp2_AntennaControl() {
+ return (int)512L;
+ }
+ public static int sdrplay_api_Update_Rsp2_RfNotchControl() {
+ return (int)1024L;
+ }
+ public static int sdrplay_api_Update_Rsp2_ExtRefControl() {
+ return (int)2048L;
+ }
+ public static int sdrplay_api_Update_RspDuo_ExtRefControl() {
+ return (int)4096L;
+ }
+ public static int sdrplay_api_Update_Master_Spare_1() {
+ return (int)8192L;
+ }
+ public static int sdrplay_api_Update_Master_Spare_2() {
+ return (int)16384L;
+ }
+ public static int sdrplay_api_Update_Tuner_Gr() {
+ return (int)32768L;
+ }
+ public static int sdrplay_api_Update_Tuner_GrLimits() {
+ return (int)65536L;
+ }
+ public static int sdrplay_api_Update_Tuner_Frf() {
+ return (int)131072L;
+ }
+ public static int sdrplay_api_Update_Tuner_BwType() {
+ return (int)262144L;
+ }
+ public static int sdrplay_api_Update_Tuner_IfType() {
+ return (int)524288L;
+ }
+ public static int sdrplay_api_Update_Tuner_DcOffset() {
+ return (int)1048576L;
+ }
+ public static int sdrplay_api_Update_Tuner_LoMode() {
+ return (int)2097152L;
+ }
+ public static int sdrplay_api_Update_Ctrl_DCoffsetIQimbalance() {
+ return (int)4194304L;
+ }
+ public static int sdrplay_api_Update_Ctrl_Decimation() {
+ return (int)8388608L;
+ }
+ public static int sdrplay_api_Update_Ctrl_Agc() {
+ return (int)16777216L;
+ }
+ public static int sdrplay_api_Update_Ctrl_AdsbMode() {
+ return (int)33554432L;
+ }
+ public static int sdrplay_api_Update_Ctrl_OverloadMsgAck() {
+ return (int)67108864L;
+ }
+ public static int sdrplay_api_Update_RspDuo_BiasTControl() {
+ return (int)134217728L;
+ }
+ public static int sdrplay_api_Update_RspDuo_AmPortSelect() {
+ return (int)268435456L;
+ }
+ public static int sdrplay_api_Update_RspDuo_Tuner1AmNotchControl() {
+ return (int)536870912L;
+ }
+ public static int sdrplay_api_Update_RspDuo_RfNotchControl() {
+ return (int)1073741824L;
+ }
+ public static int sdrplay_api_Update_RspDuo_RfDabNotchControl() {
+ return (int)-2147483648L;
+ }
+ public static int sdrplay_api_Update_Ext1_None() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_Update_RspDx_HdrEnable() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_Update_RspDx_BiasTControl() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_Update_RspDx_AntennaControl() {
+ return (int)4L;
+ }
+ public static int sdrplay_api_Update_RspDx_RfNotchControl() {
+ return (int)8L;
+ }
+ public static int sdrplay_api_Update_RspDx_RfDabNotchControl() {
+ return (int)16L;
+ }
+ public static int sdrplay_api_Update_RspDx_HdrBw() {
+ return (int)32L;
+ }
+ public static int sdrplay_api_DbgLvl_Disable() {
+ return (int)0L;
+ }
+ public static int sdrplay_api_DbgLvl_Verbose() {
+ return (int)1L;
+ }
+ public static int sdrplay_api_DbgLvl_Warning() {
+ return (int)2L;
+ }
+ public static int sdrplay_api_DbgLvl_Error() {
+ return (int)3L;
+ }
+ public static int sdrplay_api_DbgLvl_Message() {
+ return (int)4L;
+ }
+ public static MethodHandle sdrplay_api_Open$MH() {
+ return RuntimeHelper.requireNonNull(constants$7.sdrplay_api_Open$MH,"sdrplay_api_Open");
+ }
+ public static int sdrplay_api_Open () {
+ var mh$ = sdrplay_api_Open$MH();
+ try {
+ return (int)mh$.invokeExact();
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_Close$MH() {
+ return RuntimeHelper.requireNonNull(constants$7.sdrplay_api_Close$MH,"sdrplay_api_Close");
+ }
+ public static int sdrplay_api_Close () {
+ var mh$ = sdrplay_api_Close$MH();
+ try {
+ return (int)mh$.invokeExact();
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_ApiVersion$MH() {
+ return RuntimeHelper.requireNonNull(constants$7.sdrplay_api_ApiVersion$MH,"sdrplay_api_ApiVersion");
+ }
+ public static int sdrplay_api_ApiVersion ( Addressable apiVer) {
+ var mh$ = sdrplay_api_ApiVersion$MH();
+ try {
+ return (int)mh$.invokeExact(apiVer);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_LockDeviceApi$MH() {
+ return RuntimeHelper.requireNonNull(constants$7.sdrplay_api_LockDeviceApi$MH,"sdrplay_api_LockDeviceApi");
+ }
+ public static int sdrplay_api_LockDeviceApi () {
+ var mh$ = sdrplay_api_LockDeviceApi$MH();
+ try {
+ return (int)mh$.invokeExact();
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_UnlockDeviceApi$MH() {
+ return RuntimeHelper.requireNonNull(constants$7.sdrplay_api_UnlockDeviceApi$MH,"sdrplay_api_UnlockDeviceApi");
+ }
+ public static int sdrplay_api_UnlockDeviceApi () {
+ var mh$ = sdrplay_api_UnlockDeviceApi$MH();
+ try {
+ return (int)mh$.invokeExact();
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_GetDevices$MH() {
+ return RuntimeHelper.requireNonNull(constants$7.sdrplay_api_GetDevices$MH,"sdrplay_api_GetDevices");
+ }
+ public static int sdrplay_api_GetDevices ( Addressable devices, Addressable numDevs, int maxDevs) {
+ var mh$ = sdrplay_api_GetDevices$MH();
+ try {
+ return (int)mh$.invokeExact(devices, numDevs, maxDevs);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_SelectDevice$MH() {
+ return RuntimeHelper.requireNonNull(constants$8.sdrplay_api_SelectDevice$MH,"sdrplay_api_SelectDevice");
+ }
+ public static int sdrplay_api_SelectDevice ( Addressable device) {
+ var mh$ = sdrplay_api_SelectDevice$MH();
+ try {
+ return (int)mh$.invokeExact(device);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_ReleaseDevice$MH() {
+ return RuntimeHelper.requireNonNull(constants$8.sdrplay_api_ReleaseDevice$MH,"sdrplay_api_ReleaseDevice");
+ }
+ public static int sdrplay_api_ReleaseDevice ( Addressable device) {
+ var mh$ = sdrplay_api_ReleaseDevice$MH();
+ try {
+ return (int)mh$.invokeExact(device);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_GetErrorString$MH() {
+ return RuntimeHelper.requireNonNull(constants$8.sdrplay_api_GetErrorString$MH,"sdrplay_api_GetErrorString");
+ }
+ public static MemoryAddress sdrplay_api_GetErrorString ( int err) {
+ var mh$ = sdrplay_api_GetErrorString$MH();
+ try {
+ return (java.lang.foreign.MemoryAddress)mh$.invokeExact(err);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_GetLastError$MH() {
+ return RuntimeHelper.requireNonNull(constants$8.sdrplay_api_GetLastError$MH,"sdrplay_api_GetLastError");
+ }
+ public static MemoryAddress sdrplay_api_GetLastError ( Addressable device) {
+ var mh$ = sdrplay_api_GetLastError$MH();
+ try {
+ return (java.lang.foreign.MemoryAddress)mh$.invokeExact(device);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_DisableHeartbeat$MH() {
+ return RuntimeHelper.requireNonNull(constants$8.sdrplay_api_DisableHeartbeat$MH,"sdrplay_api_DisableHeartbeat");
+ }
+ public static int sdrplay_api_DisableHeartbeat () {
+ var mh$ = sdrplay_api_DisableHeartbeat$MH();
+ try {
+ return (int)mh$.invokeExact();
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_DebugEnable$MH() {
+ return RuntimeHelper.requireNonNull(constants$8.sdrplay_api_DebugEnable$MH,"sdrplay_api_DebugEnable");
+ }
+ public static int sdrplay_api_DebugEnable ( Addressable dev, int enable) {
+ var mh$ = sdrplay_api_DebugEnable$MH();
+ try {
+ return (int)mh$.invokeExact(dev, enable);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_GetDeviceParams$MH() {
+ return RuntimeHelper.requireNonNull(constants$9.sdrplay_api_GetDeviceParams$MH,"sdrplay_api_GetDeviceParams");
+ }
+ public static int sdrplay_api_GetDeviceParams ( Addressable dev, Addressable deviceParams) {
+ var mh$ = sdrplay_api_GetDeviceParams$MH();
+ try {
+ return (int)mh$.invokeExact(dev, deviceParams);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_Init$MH() {
+ return RuntimeHelper.requireNonNull(constants$9.sdrplay_api_Init$MH,"sdrplay_api_Init");
+ }
+ public static int sdrplay_api_Init ( Addressable dev, Addressable callbackFns, Addressable cbContext) {
+ var mh$ = sdrplay_api_Init$MH();
+ try {
+ return (int)mh$.invokeExact(dev, callbackFns, cbContext);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_Uninit$MH() {
+ return RuntimeHelper.requireNonNull(constants$9.sdrplay_api_Uninit$MH,"sdrplay_api_Uninit");
+ }
+ public static int sdrplay_api_Uninit ( Addressable dev) {
+ var mh$ = sdrplay_api_Uninit$MH();
+ try {
+ return (int)mh$.invokeExact(dev);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_Update$MH() {
+ return RuntimeHelper.requireNonNull(constants$9.sdrplay_api_Update$MH,"sdrplay_api_Update");
+ }
+ public static int sdrplay_api_Update ( Addressable dev, int tuner, int reasonForUpdate, int reasonForUpdateExt1) {
+ var mh$ = sdrplay_api_Update$MH();
+ try {
+ return (int)mh$.invokeExact(dev, tuner, reasonForUpdate, reasonForUpdateExt1);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_SwapRspDuoActiveTuner$MH() {
+ return RuntimeHelper.requireNonNull(constants$9.sdrplay_api_SwapRspDuoActiveTuner$MH,"sdrplay_api_SwapRspDuoActiveTuner");
+ }
+ public static int sdrplay_api_SwapRspDuoActiveTuner ( Addressable dev, Addressable currentTuner, int tuner1AmPortSel) {
+ var mh$ = sdrplay_api_SwapRspDuoActiveTuner$MH();
+ try {
+ return (int)mh$.invokeExact(dev, currentTuner, tuner1AmPortSel);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_SwapRspDuoDualTunerModeSampleRate$MH() {
+ return RuntimeHelper.requireNonNull(constants$9.sdrplay_api_SwapRspDuoDualTunerModeSampleRate$MH,"sdrplay_api_SwapRspDuoDualTunerModeSampleRate");
+ }
+ public static int sdrplay_api_SwapRspDuoDualTunerModeSampleRate ( Addressable dev, Addressable currentSampleRate, double newSampleRate) {
+ var mh$ = sdrplay_api_SwapRspDuoDualTunerModeSampleRate$MH();
+ try {
+ return (int)mh$.invokeExact(dev, currentSampleRate, newSampleRate);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static MethodHandle sdrplay_api_SwapRspDuoMode$MH() {
+ return RuntimeHelper.requireNonNull(constants$10.sdrplay_api_SwapRspDuoMode$MH,"sdrplay_api_SwapRspDuoMode");
+ }
+ public static int sdrplay_api_SwapRspDuoMode ( Addressable currDevice, Addressable deviceParams, int rspDuoMode, double sampleRate, int tuner, int bwType, int ifType, int tuner1AmPortSel) {
+ var mh$ = sdrplay_api_SwapRspDuoMode$MH();
+ try {
+ return (int)mh$.invokeExact(currDevice, deviceParams, rspDuoMode, sampleRate, tuner, bwType, ifType, tuner1AmPortSel);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ public static int MAX_BB_GR() {
+ return (int)59L;
+ }
+ public static float SDRPLAY_API_VERSION() {
+ return 3.08f;
+ }
+ public static int SDRPLAY_MAX_DEVICES() {
+ return (int)16L;
+ }
+ public static int SDRPLAY_MAX_TUNERS_PER_DEVICE() {
+ return (int)2L;
+ }
+ public static int SDRPLAY_MAX_SER_NO_LEN() {
+ return (int)64L;
+ }
+ public static int SDRPLAY_MAX_ROOT_NM_LEN() {
+ return (int)32L;
+ }
+ public static int SDRPLAY_RSP1_ID() {
+ return (int)1L;
+ }
+ public static int SDRPLAY_RSP1A_ID() {
+ return (int)255L;
+ }
+ public static int SDRPLAY_RSP2_ID() {
+ return (int)2L;
+ }
+ public static int SDRPLAY_RSPduo_ID() {
+ return (int)3L;
+ }
+ public static int SDRPLAY_RSPdx_ID() {
+ return (int)4L;
+ }
+}
+
+
diff --git a/sdrplay-api/src/main/java/module-info.java b/sdrplay-api/src/main/java/module-info.java
new file mode 100644
index 000000000..f9c0992be
--- /dev/null
+++ b/sdrplay-api/src/main/java/module-info.java
@@ -0,0 +1,4 @@
+module sdrplay.api {
+ exports com.github.dsheirer.sdrplay.api.v3_07;
+ exports com.github.dsheirer.sdrplay.api.v3_08;
+}
\ No newline at end of file
diff --git a/sdrplay-api/src/main/resources/README b/sdrplay-api/src/main/resources/README
new file mode 100644
index 000000000..5d61b3ad3
--- /dev/null
+++ b/sdrplay-api/src/main/resources/README
@@ -0,0 +1,15 @@
+SDRplay API 3.07
+Auto-created from sdrplay api header files using JDK 17 jextract tool:
+
+1. Install the sdrplay api
+2. On Linux, headers are located here: /usr/local/include/*.h
+3. cd into the (project)/jSDRplay/sdrplay-api/src/main/java/ directory
+4. Run: jextract -t io.github.dsheirer.sdrplay.api /usr/local/include/sdrplay_api.h -l libsdrplay_api --source
+
+IntelliJ setup
+1. Run configuration
+2. JVM Option: --enable-native-access=ALL-UNNAMED
+3. Add library location to the java.library.path:
+ Linux: /usr/local/lib
+ Windows: ??
+ MacOS: ??
diff --git a/settings.gradle b/settings.gradle
index e592e50ed..ea97b6db6 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1,4 @@
-rootProject.name = 'sdr-trunk'
\ No newline at end of file
+rootProject.name = 'sdr-trunk'
+
+include 'jsdrplay'
+include 'sdrplay-api'
diff --git a/src/main/java/io/github/dsheirer/gui/SDRTrunk.java b/src/main/java/io/github/dsheirer/gui/SDRTrunk.java
index 70c5a1146..6a4df9715 100644
--- a/src/main/java/io/github/dsheirer/gui/SDRTrunk.java
+++ b/src/main/java/io/github/dsheirer/gui/SDRTrunk.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2023 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
@@ -59,6 +59,26 @@
import io.github.dsheirer.util.ThreadPool;
import io.github.dsheirer.util.TimeStamp;
import io.github.dsheirer.vector.calibrate.CalibrationManager;
+import java.awt.AWTException;
+import java.awt.Desktop;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.GraphicsEnvironment;
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Locale;
+import java.util.Optional;
import javafx.application.Platform;
import javafx.scene.control.ButtonType;
import jiconfont.icons.font_awesome.FontAwesome;
@@ -80,26 +100,6 @@
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import javax.swing.plaf.metal.MetalLookAndFeel;
-import java.awt.AWTException;
-import java.awt.Desktop;
-import java.awt.Dimension;
-import java.awt.EventQueue;
-import java.awt.GraphicsEnvironment;
-import java.awt.Point;
-import java.awt.Robot;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.KeyEvent;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-import java.awt.image.BufferedImage;
-import java.io.IOException;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.List;
-import java.util.Locale;
-import java.util.Optional;
public class SDRTrunk implements Listener
{
@@ -247,7 +247,11 @@ public SDRTrunk()
{
mMainGui.setVisible(true);
Tuner tuner = tunerSpectralDisplayManager.showFirstTuner();
- updateTitle(tuner);
+
+ if(tuner != null)
+ {
+ updateTitle(tuner.getPreferredName());
+ }
}
if(calibrating && !GraphicsEnvironment.isHeadless())
@@ -623,21 +627,34 @@ private Path getHomePath()
@Override
public void receive(TunerEvent event)
{
- if(event.getEvent() == TunerEvent.Event.REQUEST_MAIN_SPECTRAL_DISPLAY)
+ switch(event.getEvent())
{
- updateTitle(event.getTuner());
+ case REQUEST_MAIN_SPECTRAL_DISPLAY:
+ updateTitle(event.getTuner().getPreferredName());
+ break;
+ case REQUEST_CLEAR_MAIN_SPECTRAL_DISPLAY:
+ updateTitle(null);
+ break;
+ case NOTIFICATION_SHUTTING_DOWN:
+ Tuner currentTuner = mSpectralPanel.getTuner();
+
+ if(event.hasTuner() && event.getTuner().equals(currentTuner) || currentTuner == null)
+ {
+ updateTitle(null);
+ }
+ break;
}
}
/**
* Updates the title bar with the tuner name
- * @param tuner optional
+ * @param tunerName optional
*/
- private void updateTitle(Tuner tuner)
+ private void updateTitle(String tunerName)
{
- if(tuner != null)
+ if(tunerName != null)
{
- mMainGui.setTitle(mTitle + " - " + tuner.getPreferredName());
+ mMainGui.setTitle(mTitle + " - " + tunerName);
}
else
{
diff --git a/src/main/java/io/github/dsheirer/gui/preference/PreferenceEditorFactory.java b/src/main/java/io/github/dsheirer/gui/preference/PreferenceEditorFactory.java
index 5ec247de2..b2dd2ec8f 100644
--- a/src/main/java/io/github/dsheirer/gui/preference/PreferenceEditorFactory.java
+++ b/src/main/java/io/github/dsheirer/gui/preference/PreferenceEditorFactory.java
@@ -53,7 +53,7 @@ public static Node getEditor(PreferenceEditorType preferenceEditorType, UserPref
return new DirectoryPreferenceEditor(userPreferences);
case JMBE_LIBRARY:
return new JmbeLibraryPreferenceEditor(userPreferences);
- case SOURCE_TUNER_CHANNELIZER:
+ case SOURCE_TUNERS:
return new TunerPreferenceEditor(userPreferences);
case TALKGROUP_FORMAT:
return new TalkgroupFormatPreferenceEditor(userPreferences);
diff --git a/src/main/java/io/github/dsheirer/gui/preference/PreferenceEditorType.java b/src/main/java/io/github/dsheirer/gui/preference/PreferenceEditorType.java
index 7c8d87618..22b268ef8 100644
--- a/src/main/java/io/github/dsheirer/gui/preference/PreferenceEditorType.java
+++ b/src/main/java/io/github/dsheirer/gui/preference/PreferenceEditorType.java
@@ -31,7 +31,7 @@ public enum PreferenceEditorType
AUDIO_RECORD("Record"),
AUDIO_OUTPUT("Output/Tones"),
AUDIO_DUPLICATE_CALL_DETECTION("Duplicate Calls"),
- SOURCE_TUNER_CHANNELIZER("Tuner Channelizer"),
+ SOURCE_TUNERS("Tuners"),
TALKGROUP_FORMAT("Talkgroup & Radio ID"),
VECTOR_CALIBRATION("Vector Calibration"),
DEFAULT("Default");
diff --git a/src/main/java/io/github/dsheirer/gui/preference/UserPreferencesEditor.java b/src/main/java/io/github/dsheirer/gui/preference/UserPreferencesEditor.java
index 240621136..37add324c 100644
--- a/src/main/java/io/github/dsheirer/gui/preference/UserPreferencesEditor.java
+++ b/src/main/java/io/github/dsheirer/gui/preference/UserPreferencesEditor.java
@@ -22,6 +22,8 @@
import io.github.dsheirer.eventbus.MyEventBus;
import io.github.dsheirer.gui.playlist.ViewPlaylistRequest;
import io.github.dsheirer.preference.UserPreferences;
+import java.util.EnumMap;
+import java.util.Map;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
@@ -44,9 +46,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.EnumMap;
-import java.util.Map;
-
/**
* Preferences editor dialog
*/
@@ -196,7 +195,7 @@ private TreeView getEditorSelectionTreeView()
storageItem.setExpanded(true);
TreeItem sourceItem = new TreeItem<>("Source");
- sourceItem.getChildren().add(new TreeItem(PreferenceEditorType.SOURCE_TUNER_CHANNELIZER));
+ sourceItem.getChildren().add(new TreeItem(PreferenceEditorType.SOURCE_TUNERS));
treeRoot.getChildren().add(sourceItem);
sourceItem.setExpanded(true);
diff --git a/src/main/java/io/github/dsheirer/gui/preference/tuner/RspDuoSelectionMode.java b/src/main/java/io/github/dsheirer/gui/preference/tuner/RspDuoSelectionMode.java
new file mode 100644
index 000000000..d726acbb5
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/gui/preference/tuner/RspDuoSelectionMode.java
@@ -0,0 +1,62 @@
+/*
+ * *****************************************************************************
+ * 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.gui.preference.tuner;
+
+/**
+ * RSPduo tuner select mode preferences.
+ */
+public enum RspDuoSelectionMode
+{
+ DUAL("Dual Tuner"),
+ SINGLE_1("Single Tuner 1"),
+ SINGLE_2("Single Tuner 2");
+
+ private String mLabel;
+
+ RspDuoSelectionMode(String label)
+ {
+ mLabel = label;
+ }
+
+ @Override
+ public String toString()
+ {
+ return mLabel;
+ }
+
+ /**
+ * Lookup the enum entry from the value.
+ * @param value to match
+ * @return matched value or (default) DUAL if the value couldn't be matched.
+ */
+ public static RspDuoSelectionMode fromValue(String value)
+ {
+ try
+ {
+ return RspDuoSelectionMode.valueOf(value);
+ }
+ catch(Exception e)
+ {
+ //Do nothing
+ }
+
+ return DUAL;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/gui/preference/tuner/TunerPreferenceEditor.java b/src/main/java/io/github/dsheirer/gui/preference/tuner/TunerPreferenceEditor.java
index 25a68d99c..d633c93c7 100644
--- a/src/main/java/io/github/dsheirer/gui/preference/tuner/TunerPreferenceEditor.java
+++ b/src/main/java/io/github/dsheirer/gui/preference/tuner/TunerPreferenceEditor.java
@@ -1,23 +1,20 @@
/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2022 Dennis Sheirer
*
- * * ******************************************************************************
- * * Copyright (C) 2014-2020 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
- * * *****************************************************************************
+ * 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.gui.preference.tuner;
@@ -55,6 +52,8 @@ public class TunerPreferenceEditor extends HBox
private Label mHelpTextPolyphaseLabel;
private Label mHeterodyneLabel;
private Label mHelpTextHeterodyneLabel;
+ private ChoiceBox mRspDuoTunerModeChoiceBox;
+ private Label mRspDuoModeLabel;
public TunerPreferenceEditor(UserPreferences userPreferences)
{
@@ -66,19 +65,24 @@ private GridPane getEditorPane()
{
if(mEditorPane == null)
{
+ int row = 0;
mEditorPane = new GridPane();
mEditorPane.setVgap(10);
mEditorPane.setHgap(10);
mEditorPane.setPadding(new Insets(10, 10, 10, 10));
- GridPane.setHalignment(getChannelizerLabel(), HPos.LEFT);
- mEditorPane.add(getChannelizerLabel(), 0, 0);
- mEditorPane.add(getChannelizerTypeChoiceBox(), 1, 0);
- mEditorPane.add(new Separator(Orientation.HORIZONTAL), 0, 1, 2, 1);
- mEditorPane.add(getPolyphaseLabel(), 0, 2, 2, 1);
- mEditorPane.add(getHelpTextPolyphaseLabel(), 0, 3, 2, 3);
- mEditorPane.add(new Label(" "), 0, 6);
- mEditorPane.add(getHeterodyneLabel(), 0, 7, 2, 1);
- mEditorPane.add(getHelpTextHeterodyneLabel(), 0, 8, 2, 3);
+ GridPane.setHalignment(getChannelizerLabel(), HPos.RIGHT);
+ mEditorPane.add(getChannelizerLabel(), 0, row);
+ mEditorPane.add(getChannelizerTypeChoiceBox(), 1, row);
+ mEditorPane.add(getPolyphaseLabel(), 0, ++row, 2, 1);
+ mEditorPane.add(getHelpTextPolyphaseLabel(), 0, ++row, 2, 3);
+ row += 3;
+ mEditorPane.add(new Label(" "), 0, row);
+ mEditorPane.add(getHeterodyneLabel(), 0, ++row, 2, 1);
+ mEditorPane.add(getHelpTextHeterodyneLabel(), 0, ++row, 2, 3);
+ row += 3;
+ mEditorPane.add(new Separator(Orientation.HORIZONTAL), 0, row, 2, 1);
+ mEditorPane.add(getRspDuoModeLabel(), 0, ++row);
+ mEditorPane.add(getRspDuoTunerModeChoiceBox(), 1, row);
}
return mEditorPane;
@@ -161,4 +165,40 @@ private Label getHelpTextHeterodyneLabel()
return mHelpTextHeterodyneLabel;
}
+
+ private ChoiceBox getRspDuoTunerModeChoiceBox()
+ {
+ if(mRspDuoTunerModeChoiceBox == null)
+ {
+ mRspDuoTunerModeChoiceBox = new ChoiceBox<>();
+ mRspDuoTunerModeChoiceBox.getItems().addAll(RspDuoSelectionMode.values());
+
+ RspDuoSelectionMode current = mTunerPreference.getRspDuoTunerMode();
+ mRspDuoTunerModeChoiceBox.getSelectionModel().select(current);
+
+ mRspDuoTunerModeChoiceBox.setOnAction(event -> {
+ RspDuoSelectionMode selected = mRspDuoTunerModeChoiceBox.getSelectionModel().getSelectedItem();
+ mTunerPreference.setRspDuoTunerMode(selected);
+
+ Label label = new Label("Please restart the application for this change to take effect");
+ label.setWrapText(true);
+ Alert alert = new Alert(Alert.AlertType.WARNING);
+ alert.getDialogPane().setContent(label);
+ alert.initOwner(((Node)getRspDuoTunerModeChoiceBox()).getScene().getWindow());
+ alert.show();
+ });
+ }
+
+ return mRspDuoTunerModeChoiceBox;
+ }
+
+ private Label getRspDuoModeLabel()
+ {
+ if(mRspDuoModeLabel == null)
+ {
+ mRspDuoModeLabel = new Label("SDRPlay RSPduo Selection Mode");
+ }
+
+ return mRspDuoModeLabel;
+ }
}
diff --git a/src/main/java/io/github/dsheirer/preference/source/TunerPreference.java b/src/main/java/io/github/dsheirer/preference/source/TunerPreference.java
index 94d40e4c7..ebfb84776 100644
--- a/src/main/java/io/github/dsheirer/preference/source/TunerPreference.java
+++ b/src/main/java/io/github/dsheirer/preference/source/TunerPreference.java
@@ -19,14 +19,14 @@
package io.github.dsheirer.preference.source;
+import io.github.dsheirer.gui.preference.tuner.RspDuoSelectionMode;
import io.github.dsheirer.preference.Preference;
import io.github.dsheirer.preference.PreferenceType;
import io.github.dsheirer.sample.Listener;
+import java.util.prefs.Preferences;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.prefs.Preferences;
-
/**
* Tuner preferences
*/
@@ -35,8 +35,10 @@ public class TunerPreference extends Preference
private final static Logger mLog = LoggerFactory.getLogger(TunerPreference.class);
private Preferences mPreferences = Preferences.userNodeForPackage(TunerPreference.class);
private static final String PREFERENCE_KEY_CHANNELIZER_TYPE = "channelizer.type";
+ private static final String PREFERENCE_KEY_RSP_DUO_TUNER_MODE = "rsp.duo.tuner.mode";
private ChannelizerType mChannelizerType;
+ private RspDuoSelectionMode mRspDuoSelectionMode;
/**
* Constructs a tuner preference with the update listener
@@ -94,4 +96,30 @@ public void setChannelizerType(ChannelizerType type)
mPreferences.put(PREFERENCE_KEY_CHANNELIZER_TYPE, mChannelizerType.name());
notifyPreferenceUpdated();
}
+
+ /**
+ * RSPduo tuner select mode.
+ * @return mode or a default value of DUAL
+ */
+ public RspDuoSelectionMode getRspDuoTunerMode()
+ {
+ if(mRspDuoSelectionMode == null)
+ {
+ String mode = mPreferences.get(PREFERENCE_KEY_RSP_DUO_TUNER_MODE, RspDuoSelectionMode.DUAL.name());
+ mRspDuoSelectionMode = RspDuoSelectionMode.fromValue(mode);
+ }
+
+ return mRspDuoSelectionMode;
+ }
+
+ /**
+ * Sets the RSPduo tuner select mode
+ * @param mode to use
+ */
+ public void setRspDuoTunerMode(RspDuoSelectionMode mode)
+ {
+ mRspDuoSelectionMode = mode;
+ mPreferences.put(PREFERENCE_KEY_RSP_DUO_TUNER_MODE, mRspDuoSelectionMode.name());
+ notifyPreferenceUpdated();
+ }
}
diff --git a/src/main/java/io/github/dsheirer/sample/Broadcaster.java b/src/main/java/io/github/dsheirer/sample/Broadcaster.java
index 494b289f6..703e9cf33 100644
--- a/src/main/java/io/github/dsheirer/sample/Broadcaster.java
+++ b/src/main/java/io/github/dsheirer/sample/Broadcaster.java
@@ -18,12 +18,13 @@
*/
package io.github.dsheirer.sample;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Broadcasts an item to multiple listeners
@@ -100,6 +101,10 @@ public void addListener(Listener listener)
mListeners.add(listener);
}
}
+ catch(Exception e)
+ {
+ mLog.error("Unexpected error while adding listener", e);
+ }
finally
{
mLock.unlock();
@@ -120,6 +125,10 @@ public void removeListener(Listener listener)
{
mListeners.remove(listener);
}
+ catch(Exception e)
+ {
+ mLog.error("Unexpected error while removing listener", e);
+ }
finally
{
mLock.unlock();
@@ -151,6 +160,10 @@ public void broadcast(T t)
listener.receive(t);
}
}
+ catch(Exception e)
+ {
+ mLog.error("Unexpected error while broadcasting to listeners", e);
+ }
finally
{
mLock.unlock();
diff --git a/src/main/java/io/github/dsheirer/source/tuner/ITunerErrorListener.java b/src/main/java/io/github/dsheirer/source/tuner/ITunerErrorListener.java
index 4332783e2..4d8446fc3 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/ITunerErrorListener.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/ITunerErrorListener.java
@@ -1,23 +1,20 @@
/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 Dennis Sheirer
*
- * * ******************************************************************************
- * * Copyright (C) 2014-2020 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
- * * *****************************************************************************
+ * 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;
@@ -29,4 +26,9 @@ public interface ITunerErrorListener
* @param errorMessage to set
*/
void setErrorMessage(String errorMessage);
+
+ /**
+ * Indicates that the tuner has been removed from the system.
+ */
+ void tunerRemoved();
}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/LoggingTunerErrorListener.java b/src/main/java/io/github/dsheirer/source/tuner/LoggingTunerErrorListener.java
index 785b4a0f4..676e93f49 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/LoggingTunerErrorListener.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/LoggingTunerErrorListener.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2023 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
@@ -34,4 +34,10 @@ public void setErrorMessage(String errorMessage)
{
mLog.error("Tuner Error: " + errorMessage);
}
+
+ @Override
+ public void tunerRemoved()
+ {
+ mLog.warn("Tuner removal detected");
+ }
}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/Tuner.java b/src/main/java/io/github/dsheirer/source/tuner/Tuner.java
index aa86e1742..ea4142f01 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/Tuner.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/Tuner.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2023 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
@@ -149,6 +149,22 @@ public void setErrorMessage(String errorMessage)
}
}
+ /**
+ * Process tuner removal error from tuner controller and propagate to an external listener.
+ */
+ @Override
+ public void tunerRemoved()
+ {
+ mLog.info("Tuner processing tuner removal. Stopping ...");
+ stop();
+
+ mLog.info("Tuner pushing tuner removal event to external listener (tuner model)");
+ if(mTunerErrorListener != null)
+ {
+ mTunerErrorListener.tunerRemoved();
+ }
+ }
+
/**
* Sets the channel source manager
* @param manager to use
diff --git a/src/main/java/io/github/dsheirer/source/tuner/TunerClass.java b/src/main/java/io/github/dsheirer/source/tuner/TunerClass.java
index 3d8823f20..51906891e 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/TunerClass.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/TunerClass.java
@@ -30,6 +30,7 @@ public enum TunerClass
FUNCUBE_DONGLE_PRO_PLUS("Funcube Dongle Pro+" ),
HACKRF("HackRF" ),
RTL2832("RTL-2832"),
+ RSP("RSP"),
TEST_TUNER("Test"),
RECORDING_TUNER("Recording"),
UNKNOWN("Unknown" );
diff --git a/src/main/java/io/github/dsheirer/source/tuner/TunerController.java b/src/main/java/io/github/dsheirer/source/tuner/TunerController.java
index cede08c06..581258f20 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/TunerController.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/TunerController.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2023 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
@@ -46,7 +46,11 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
INativeBufferProvider, Listener, ITunerErrorListener
{
private final static Logger mLog = LoggerFactory.getLogger(TunerController.class);
+
+ //Protects access to the native buffer broadcaster for adding, removing or checking for listener count.
+ protected ReentrantLock mBufferListenerLock = new ReentrantLock();
protected Broadcaster mNativeBufferBroadcaster = new Broadcaster();
+
protected FrequencyController mFrequencyController;
private int mMiddleUnusableHalfBandwidth;
private int mMeasuredFrequencyError;
@@ -129,6 +133,19 @@ public void setErrorMessage(String errorMessage)
}
}
+ /**
+ * Indicates that the tuner has been removed from the system and requests the listener to process the cleanup.
+ */
+ @Override
+ public void tunerRemoved()
+ {
+ //Request parent tuner process the shutdown and cleanup
+ if(mTunerErrorListener != null)
+ {
+ mTunerErrorListener.tunerRemoved();
+ }
+ }
+
/**
* Number of samples contained in each complex buffer provided by this tuner.
*
@@ -572,7 +589,16 @@ public void removeListener( ISourceEventProcessor processor )
@Override
public void addBufferListener(Listener listener)
{
- mNativeBufferBroadcaster.addListener(listener);
+ mBufferListenerLock.lock();
+
+ try
+ {
+ mNativeBufferBroadcaster.addListener(listener);
+ }
+ finally
+ {
+ mBufferListenerLock.unlock();
+ }
}
/**
@@ -581,7 +607,16 @@ public void addBufferListener(Listener listener)
@Override
public void removeBufferListener(Listener listener)
{
- mNativeBufferBroadcaster.removeListener(listener);
+ mBufferListenerLock.lock();
+
+ try
+ {
+ mNativeBufferBroadcaster.removeListener(listener);
+ }
+ finally
+ {
+ mBufferListenerLock.unlock();
+ }
}
/**
@@ -590,7 +625,20 @@ public void removeBufferListener(Listener listener)
@Override
public boolean hasBufferListeners()
{
- return mNativeBufferBroadcaster.hasListeners();
+ boolean hasListeners;
+
+ mBufferListenerLock.lock();
+
+ try
+ {
+ hasListeners = mNativeBufferBroadcaster.hasListeners();
+ }
+ finally
+ {
+ mBufferListenerLock.unlock();
+ }
+
+ return hasListeners;
}
/**
@@ -598,6 +646,7 @@ public boolean hasBufferListeners()
*/
protected void broadcast(INativeBuffer complexSamples)
{
+ //Note: unprotected access to the broadcaster ... the broadcaster uses thread-save internal list
mNativeBufferBroadcaster.broadcast(complexSamples);
}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/TunerEvent.java b/src/main/java/io/github/dsheirer/source/tuner/TunerEvent.java
index 887ec2ded..02c8eb2b8 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/TunerEvent.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/TunerEvent.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2023 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
@@ -54,6 +54,24 @@ public boolean hasTuner()
return mTuner != null;
}
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Tuner Event [").append(getEvent().name()).append("] for tuner [");
+ if(hasTuner())
+ {
+ sb.append(getTuner());
+ }
+ else
+ {
+ sb.append("No Tuner");
+ }
+
+ sb.append("]");
+ return sb.toString();
+ }
+
/**
* Event type
*/
@@ -75,6 +93,7 @@ public enum Event
NOTIFICATION_SHUTTING_DOWN,
REQUEST_CLEAR_MAIN_SPECTRAL_DISPLAY,
+ REQUEST_ENABLE_RSP_SLAVE_DEVICE,
REQUEST_MAIN_SPECTRAL_DISPLAY,
REQUEST_NEW_SPECTRAL_DISPLAY;
}
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 7b3010a84..039cb81c1 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/TunerFactory.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/TunerFactory.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2023 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
@@ -19,6 +19,17 @@
package io.github.dsheirer.source.tuner;
+import com.github.dsheirer.sdrplay.DeviceSelectionMode;
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.device.Device;
+import com.github.dsheirer.sdrplay.device.DeviceInfo;
+import com.github.dsheirer.sdrplay.device.Rsp1Device;
+import com.github.dsheirer.sdrplay.device.Rsp1aDevice;
+import com.github.dsheirer.sdrplay.device.Rsp2Device;
+import com.github.dsheirer.sdrplay.device.RspDuoDevice;
+import com.github.dsheirer.sdrplay.device.RspDxDevice;
+import io.github.dsheirer.gui.preference.tuner.RspDuoSelectionMode;
import io.github.dsheirer.preference.UserPreferences;
import io.github.dsheirer.preference.source.ChannelizerType;
import io.github.dsheirer.source.SourceException;
@@ -53,7 +64,50 @@
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.sdrplay.DiscoveredRspTuner;
+import io.github.dsheirer.source.tuner.sdrplay.RspTuner;
+import io.github.dsheirer.source.tuner.sdrplay.rsp1.ControlRsp1;
+import io.github.dsheirer.source.tuner.sdrplay.rsp1.DiscoveredRsp1Tuner;
+import io.github.dsheirer.source.tuner.sdrplay.rsp1.IControlRsp1;
+import io.github.dsheirer.source.tuner.sdrplay.rsp1.Rsp1TunerConfiguration;
+import io.github.dsheirer.source.tuner.sdrplay.rsp1.Rsp1TunerController;
+import io.github.dsheirer.source.tuner.sdrplay.rsp1.Rsp1TunerEditor;
+import io.github.dsheirer.source.tuner.sdrplay.rsp1a.ControlRsp1a;
+import io.github.dsheirer.source.tuner.sdrplay.rsp1a.DiscoveredRsp1aTuner;
+import io.github.dsheirer.source.tuner.sdrplay.rsp1a.IControlRsp1a;
+import io.github.dsheirer.source.tuner.sdrplay.rsp1a.Rsp1aTunerConfiguration;
+import io.github.dsheirer.source.tuner.sdrplay.rsp1a.Rsp1aTunerController;
+import io.github.dsheirer.source.tuner.sdrplay.rsp1a.Rsp1aTunerEditor;
+import io.github.dsheirer.source.tuner.sdrplay.rsp2.ControlRsp2;
+import io.github.dsheirer.source.tuner.sdrplay.rsp2.DiscoveredRsp2Tuner;
+import io.github.dsheirer.source.tuner.sdrplay.rsp2.IControlRsp2;
+import io.github.dsheirer.source.tuner.sdrplay.rsp2.Rsp2TunerConfiguration;
+import io.github.dsheirer.source.tuner.sdrplay.rsp2.Rsp2TunerController;
+import io.github.dsheirer.source.tuner.sdrplay.rsp2.Rsp2TunerEditor;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.ControlRspDuoTuner1Master;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.ControlRspDuoTuner1Single;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.ControlRspDuoTuner2Single;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.ControlRspDuoTuner2Slave;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.DiscoveredRspDuoTuner1;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.DiscoveredRspDuoTuner2;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.IControlRspDuoTuner1;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.IControlRspDuoTuner2;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.MasterSlaveBridge;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.RspDuoTuner1Configuration;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.RspDuoTuner1Controller;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.RspDuoTuner1Editor;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.RspDuoTuner2Configuration;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.RspDuoTuner2Controller;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.RspDuoTuner2Editor;
+import io.github.dsheirer.source.tuner.sdrplay.rspDx.ControlRspDx;
+import io.github.dsheirer.source.tuner.sdrplay.rspDx.DiscoveredRspDxTuner;
+import io.github.dsheirer.source.tuner.sdrplay.rspDx.IControlRspDx;
+import io.github.dsheirer.source.tuner.sdrplay.rspDx.RspDxTunerConfiguration;
+import io.github.dsheirer.source.tuner.sdrplay.rspDx.RspDxTunerController;
+import io.github.dsheirer.source.tuner.sdrplay.rspDx.RspDxTunerEditor;
import io.github.dsheirer.source.tuner.ui.TunerEditor;
+import java.util.ArrayList;
+import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -66,6 +120,182 @@ public class TunerFactory
{
private static final Logger mLog = LoggerFactory.getLogger(TunerFactory.class);
+ /**
+ * Creates one or two (e.g. RSPduo) Discovered RSP tuner instances for the RSP device.
+ * @param deviceInfo describing the RSP device
+ * @param channelizerType to use with the device
+ * @param selectionMode to specify how to configure an RSPduo dual-tuner device.
+ * @return zero or more discovered RSP tuners.
+ */
+ public static List getRspTuners(DeviceInfo deviceInfo, ChannelizerType channelizerType, RspDuoSelectionMode selectionMode)
+ {
+ List tuners = new ArrayList<>();
+
+ switch(deviceInfo.getDeviceType())
+ {
+ case RSP1:
+ tuners.add(new DiscoveredRsp1Tuner(deviceInfo, channelizerType));
+ break;
+ case RSP1A:
+ tuners.add(new DiscoveredRsp1aTuner(deviceInfo, channelizerType));
+ break;
+ case RSP2:
+ tuners.add(new DiscoveredRsp2Tuner(deviceInfo, channelizerType));
+ break;
+ case RSPdx:
+ tuners.add(new DiscoveredRspDxTuner(deviceInfo, channelizerType));
+ break;
+ case RSPduo:
+ switch(selectionMode)
+ {
+ case SINGLE_1:
+ deviceInfo.setDeviceSelectionMode(DeviceSelectionMode.SINGLE_TUNER_1);
+ tuners.add(new DiscoveredRspDuoTuner1(deviceInfo, channelizerType));
+ break;
+ case SINGLE_2:
+ deviceInfo.setDeviceSelectionMode(DeviceSelectionMode.SINGLE_TUNER_2);
+ tuners.add(new DiscoveredRspDuoTuner2(deviceInfo, channelizerType));
+ break;
+ case DUAL:
+ MasterSlaveBridge bridge = new MasterSlaveBridge();
+ deviceInfo.setDeviceSelectionMode(DeviceSelectionMode.MASTER_TUNER_1);
+ tuners.add(new DiscoveredRspDuoTuner1(deviceInfo, channelizerType, bridge));
+
+ DeviceInfo deviceInfoTuner2 = deviceInfo.clone();
+ deviceInfoTuner2.setDeviceSelectionMode(DeviceSelectionMode.SLAVE_TUNER_2);
+ tuners.add(new DiscoveredRspDuoTuner2(deviceInfoTuner2, channelizerType, bridge));
+ break;
+ }
+ break;
+ }
+
+ return tuners;
+ }
+
+ /**
+ * Locates the matching RSP device described by the device info object and creates an RSP tuner instance.
+ * @param deviceInfo to match
+ * @param channelizerType for the tuner
+ * @param tunerErrorListener to monitor the tuner's status
+ * @return constructed RSP tuner instance
+ * @throws SDRPlayException if the device is not available or is not supported
+ */
+ public static RspTuner getRspTuner(DeviceInfo deviceInfo, ChannelizerType channelizerType,
+ ITunerErrorListener tunerErrorListener) throws SDRPlayException
+ {
+ //API instance is retained across the lifecycle of the constructed device, so we only close it if we don't get
+ //a device from it.
+ SDRplay api = new SDRplay();
+
+ if(api.isAvailable())
+ {
+ Device device = api.getDevice(deviceInfo);
+
+ switch(device.getDeviceType())
+ {
+ case RSP1:
+ if(device instanceof Rsp1Device rsp1Device)
+ {
+ IControlRsp1 controlRsp1 = new ControlRsp1(rsp1Device);
+ Rsp1TunerController rsp1TunerController = new Rsp1TunerController(controlRsp1, tunerErrorListener);
+ return new RspTuner(rsp1TunerController, tunerErrorListener, channelizerType);
+ }
+ break;
+ case RSP1A:
+ if(device instanceof Rsp1aDevice rsp1aDevice)
+ {
+ IControlRsp1a controlRsp1a = new ControlRsp1a(rsp1aDevice);
+ Rsp1aTunerController rsp1aTunerController = new Rsp1aTunerController(controlRsp1a, tunerErrorListener);
+ return new RspTuner(rsp1aTunerController, tunerErrorListener, channelizerType);
+ }
+ break;
+ case RSP2:
+ if(device instanceof Rsp2Device rsp2Device)
+ {
+ IControlRsp2 controlRsp2 = new ControlRsp2(rsp2Device);
+ Rsp2TunerController rsp2TunerController = new Rsp2TunerController(controlRsp2, tunerErrorListener);
+ return new RspTuner(rsp2TunerController, tunerErrorListener, channelizerType);
+ }
+ break;
+ case RSPdx:
+ if(device instanceof RspDxDevice rspDxDevice)
+ {
+ IControlRspDx controlRspDx = new ControlRspDx(rspDxDevice);
+ RspDxTunerController rspDxTunerController = new RspDxTunerController(controlRspDx, tunerErrorListener);
+ return new RspTuner(rspDxTunerController, tunerErrorListener, channelizerType);
+ }
+ break;
+ case RSPduo:
+ if(device instanceof RspDuoDevice rspDuoDevice)
+ {
+ switch(deviceInfo.getDeviceSelectionMode())
+ {
+ case SINGLE_TUNER_1:
+ IControlRspDuoTuner1 controlRspDuoTuner1 = new ControlRspDuoTuner1Single(rspDuoDevice);
+ RspDuoTuner1Controller rspDuoTuner1Controller = new RspDuoTuner1Controller(controlRspDuoTuner1, tunerErrorListener);
+ return new RspTuner(rspDuoTuner1Controller, tunerErrorListener, channelizerType);
+ case SINGLE_TUNER_2:
+ IControlRspDuoTuner2 controlRspDuoTuner2 = new ControlRspDuoTuner2Single(rspDuoDevice);
+ RspDuoTuner2Controller rspDuoTuner2Controller = new RspDuoTuner2Controller(controlRspDuoTuner2, tunerErrorListener);
+ return new RspTuner(rspDuoTuner2Controller, tunerErrorListener, channelizerType);
+ default:
+ throw new SDRPlayException("This method only supports RSPduo single tuner configurations");
+ }
+ }
+ break;
+ case default:
+ mLog.warn("Unrecognized SDRplay RSP Device Type: " + device.getDeviceType() + " SER#: " + device.getSerialNumber());
+ break;
+ }
+ }
+
+ throw new SDRPlayException("Unable to obtain RSP tuner");
+ }
+
+ /**
+ * Locates the matching RSP device described by the device info object and creates an RSP tuner instance.
+ * @param deviceInfo to match
+ * @param channelizerType for the tuner
+ * @param tunerErrorListener to monitor the tuner's status
+ * @param bridge to link master/slave instances together
+ * @return constructed RSP tuner instance
+ * @throws SDRPlayException if the device is not available or is not supported
+ */
+ public static RspTuner getRspDuoTuner(DeviceInfo deviceInfo, ChannelizerType channelizerType,
+ ITunerErrorListener tunerErrorListener, MasterSlaveBridge bridge) throws SDRPlayException
+ {
+ SDRplay api = new SDRplay();
+
+ if(api.isAvailable())
+ {
+ Device device = api.getDevice(deviceInfo);
+
+ switch(device.getDeviceType())
+ {
+ case RSPduo:
+ if(device instanceof RspDuoDevice rspDuoDevice)
+ {
+ switch(deviceInfo.getDeviceSelectionMode())
+ {
+ case MASTER_TUNER_1:
+ IControlRspDuoTuner1 controlRspDuoTuner1 = new ControlRspDuoTuner1Master(rspDuoDevice, bridge);
+ RspDuoTuner1Controller rspDuoTuner1Controller = new RspDuoTuner1Controller(controlRspDuoTuner1, tunerErrorListener);
+ return new RspTuner(rspDuoTuner1Controller, tunerErrorListener, channelizerType);
+ case SLAVE_TUNER_2:
+ IControlRspDuoTuner2 controlRspDuoTuner2 = new ControlRspDuoTuner2Slave(rspDuoDevice, bridge);
+ RspDuoTuner2Controller rspDuoTuner2Controller = new RspDuoTuner2Controller(controlRspDuoTuner2, tunerErrorListener);
+ return new RspTuner(rspDuoTuner2Controller, tunerErrorListener, channelizerType);
+ default:
+ throw new SDRPlayException("This method only supports RSPduo single tuner configurations");
+ }
+ }
+ break;
+ }
+ }
+
+ throw new SDRPlayException("Unable to obtain RSPduo tuner");
+ }
+
/**
* Create a USB tuner
* @param tunerClass to instantiate
@@ -148,6 +378,18 @@ public static TunerConfiguration getTunerConfiguration(TunerType type, String un
return new R820TTunerConfiguration(uniqueID);
case RECORDING:
return RecordingTunerConfiguration.create();
+ case RSP_1:
+ return new Rsp1TunerConfiguration(uniqueID);
+ case RSP_1A:
+ return new Rsp1aTunerConfiguration(uniqueID);
+ case RSP_2:
+ return new Rsp2TunerConfiguration(uniqueID);
+ case RSP_DUO_1:
+ return new RspDuoTuner1Configuration(uniqueID);
+ case RSP_DUO_2:
+ return new RspDuoTuner2Configuration(uniqueID);
+ case RSP_DX:
+ return new RspDxTunerConfiguration(uniqueID);
default:
throw new IllegalArgumentException("Unrecognized tuner type [" + type.name() + "]");
}
@@ -169,6 +411,42 @@ public static TunerEditor getEditor(UserPreferences userPreferences, DiscoveredT
return new FCD2TunerEditor(userPreferences, tunerManager, discoveredTuner);
case HACKRF:
return new HackRFTunerEditor(userPreferences, tunerManager, discoveredTuner);
+ case RSP:
+ if(discoveredTuner instanceof DiscoveredRspTuner discoveredRspTuner)
+ {
+ switch(discoveredRspTuner.getDeviceType())
+ {
+ case RSP1:
+ return new Rsp1TunerEditor(userPreferences, tunerManager, discoveredRspTuner);
+ case RSP1A:
+ return new Rsp1aTunerEditor(userPreferences, tunerManager, discoveredRspTuner);
+ case RSP2:
+ return new Rsp2TunerEditor(userPreferences, tunerManager, discoveredRspTuner);
+ case RSPdx:
+ return new RspDxTunerEditor(userPreferences, tunerManager, discoveredRspTuner);
+ case RSPduo:
+ if(discoveredRspTuner instanceof DiscoveredRspDuoTuner1 duoTuner1)
+ {
+ return new RspDuoTuner1Editor(userPreferences, tunerManager, duoTuner1);
+ }
+ else if(discoveredRspTuner instanceof DiscoveredRspDuoTuner2 duoTuner2)
+ {
+ return new RspDuoTuner2Editor(userPreferences, tunerManager, duoTuner2);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Unrecognized RSPduo device type:" +
+ discoveredRspTuner.getClass());
+ }
+ case UNKNOWN:
+ throw new IllegalArgumentException("Unrecognized RSP device type: " +
+ discoveredRspTuner.getDeviceType());
+ }
+ }
+ throw new IllegalArgumentException("Unrecognized discovered RSP tuner class: " +
+ discoveredTuner.getClass());
+ case RECORDING_TUNER:
+ return new RecordingTunerEditor(userPreferences, tunerManager, discoveredTuner);
case RTL2832:
if(discoveredTuner.hasTuner())
{
@@ -181,8 +459,6 @@ public static TunerEditor getEditor(UserPreferences userPreferences, DiscoveredT
}
}
return new RTL2832UnknownTunerEditor(userPreferences, tunerManager, discoveredTuner);
- case RECORDING_TUNER:
- return new RecordingTunerEditor(userPreferences, tunerManager, discoveredTuner);
case TEST_TUNER:
case UNKNOWN:
default:
diff --git a/src/main/java/io/github/dsheirer/source/tuner/TunerType.java b/src/main/java/io/github/dsheirer/source/tuner/TunerType.java
index c8686e084..de36198eb 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/TunerType.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/TunerType.java
@@ -37,6 +37,13 @@ public enum TunerType
HACKRF_RAD1O("RAD1O"),
RAFAELMICRO_R820T("R820T"),
RAFAELMICRO_R828D("R828D"),
+ RSP_1("RSP1"),
+ RSP_1A("RSP1A"),
+ RSP_2("RSP2"),
+ RSP_DUO_1("RSPduo Tuner 1"),
+ RSP_DUO_2("RSPduo Tuner 2"),
+ RSP_DX("RSPdx"),
+
TEST("Test"),
RECORDING("Recording"),
UNKNOWN("Unknown");
diff --git a/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfiguration.java
index 1b8c55688..2827ea7da 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfiguration.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfiguration.java
@@ -31,6 +31,7 @@
import io.github.dsheirer.source.tuner.recording.RecordingTunerConfiguration;
import io.github.dsheirer.source.tuner.rtl.e4k.E4KTunerConfiguration;
import io.github.dsheirer.source.tuner.rtl.r820t.R820TTunerConfiguration;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerConfiguration;
/**
* Abstract class to hold a configuration for a specific type of tuner
@@ -44,6 +45,7 @@
@JsonSubTypes.Type(value = HackRFTunerConfiguration.class, name = "hackRFTunerConfiguration"),
@JsonSubTypes.Type(value = RecordingTunerConfiguration.class, name = "recordingTunerConfiguration"),
@JsonSubTypes.Type(value = R820TTunerConfiguration.class, name = "r820TTunerConfiguration"),
+ @JsonSubTypes.Type(value = RspTunerConfiguration.class, name = "rspTunerConfiguration"),
})
@JacksonXmlRootElement(localName = "tuner_configuration")
public abstract class TunerConfiguration
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 cd61a9fa9..069d60c0c 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
@@ -147,6 +147,12 @@ public void saveConfigurations()
}
}
+ /**
+ * Monitors discovered tuner enabled status and applies configurations or updates disable state of tuners.
+ * @param discoveredTuner that has a status change.
+ * @param previous tuner status
+ * @param current tuner status
+ */
@Override
public void tunerStatusUpdated(DiscoveredTuner discoveredTuner, TunerStatus previous, TunerStatus current)
{
@@ -157,6 +163,23 @@ public void tunerStatusUpdated(DiscoveredTuner discoveredTuner, TunerStatus prev
else if(current == TunerStatus.ENABLED)
{
removeDisabledTuner(discoveredTuner);
+
+ if(discoveredTuner.hasTuner())
+ {
+ TunerType tunerType = discoveredTuner.getTuner().getTunerType();
+
+ if(tunerType != TunerType.RECORDING)
+ {
+ TunerConfiguration tunerConfiguration = getTunerConfiguration(tunerType, discoveredTuner.getId());
+
+ if(tunerConfiguration != null)
+ {
+ discoveredTuner.setTunerConfiguration(tunerConfiguration);
+ saveConfigurations();
+ }
+ }
+ }
+
}
}
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 bd8fd3dbd..42eb2df18 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
@@ -219,7 +219,10 @@ public boolean hasTunerConfiguration()
*/
public void addTunerStatusListener(IDiscoveredTunerStatusListener listener)
{
- mListeners.add(listener);
+ if(!mListeners.contains(listener))
+ {
+ mListeners.add(listener);
+ }
}
/**
@@ -257,6 +260,12 @@ public void setErrorMessage(String errorMessage)
setTunerStatus(TunerStatus.ERROR);
}
+ @Override
+ public void tunerRemoved()
+ {
+ setTunerStatus(TunerStatus.REMOVED);
+ }
+
/**
* Indicates if this tuner has an error message.
*/
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 2441ef7b6..a65c4b004 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
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2023 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
@@ -19,6 +19,10 @@
package io.github.dsheirer.source.tuner.manager;
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.SDRplay;
+import com.github.dsheirer.sdrplay.device.DeviceInfo;
+import io.github.dsheirer.gui.preference.tuner.RspDuoSelectionMode;
import io.github.dsheirer.preference.UserPreferences;
import io.github.dsheirer.preference.source.ChannelizerType;
import io.github.dsheirer.source.Source;
@@ -28,6 +32,7 @@
import io.github.dsheirer.source.config.SourceConfiguration;
import io.github.dsheirer.source.mixer.MixerManager;
import io.github.dsheirer.source.tuner.TunerClass;
+import io.github.dsheirer.source.tuner.TunerFactory;
import io.github.dsheirer.source.tuner.TunerType;
import io.github.dsheirer.source.tuner.channel.ChannelSpecification;
import io.github.dsheirer.source.tuner.channel.MultiFrequencyTunerChannelSource;
@@ -36,6 +41,8 @@
import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
import io.github.dsheirer.source.tuner.configuration.TunerConfigurationManager;
import io.github.dsheirer.source.tuner.recording.RecordingTunerConfiguration;
+import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.DiscoveredRspDuoTuner1;
import io.github.dsheirer.source.tuner.ui.DiscoveredTunerModel;
import io.github.dsheirer.util.ThreadPool;
import java.nio.ByteBuffer;
@@ -63,14 +70,13 @@
public class TunerManager implements IDiscoveredTunerStatusListener
{
private static final Logger mLog = LoggerFactory.getLogger(TunerManager.class);
- private static final int MAXIMUM_USB_2_DATA_RATE = 480000000;
-
private UserPreferences mUserPreferences;
private DiscoveredTunerModel mDiscoveredTunerModel = new DiscoveredTunerModel();
private TunerConfigurationManager mTunerConfigurationManager;
private HotplugEventSupport mHotplugEventSupport = new HotplugEventSupport();
private Context mLibUsbApplicationContext = new Context();
private boolean mLibUsbInitialized = false;
+ private SDRplay mSDRplay;
/**
* Constructs an instance
@@ -142,6 +148,13 @@ public void stop()
//Stop all tuners
mDiscoveredTunerModel.releaseDiscoveredTuners();
+ //Shutdown SDRplay API instance
+ if(mSDRplay != null)
+ {
+ mSDRplay.close();
+ mSDRplay = null;
+ }
+
//Shutdown LibUsb
if(mLibUsbInitialized)
{
@@ -238,37 +251,7 @@ private void addUsbTuner(DiscoveredUSBTuner discoveredUSBTuner)
{
if(!mDiscoveredTunerModel.hasUsbTuner(discoveredUSBTuner.getBus(), discoveredUSBTuner.getPortAddress()))
{
- discoveredUSBTuner.addTunerStatusListener(this);
-
- //Set the tuner to disabled if the user has previously blacklisted the tuner
- if(mTunerConfigurationManager.isDisabled(discoveredUSBTuner))
- {
- discoveredUSBTuner.setEnabled(false);
- mLog.info("Tuner: " + discoveredUSBTuner + " - Added / Disabled");
- }
- else
- {
- mLog.info("Tuner: " + discoveredUSBTuner + " - Added / Starting ...");
- //Attempt to start the discovered tuner and determine the tuner type
- discoveredUSBTuner.start();
-
- if(discoveredUSBTuner.hasTuner())
- {
- TunerType tunerType = discoveredUSBTuner.getTuner().getTunerType();
-
- TunerConfiguration tunerConfiguration = mTunerConfigurationManager
- .getTunerConfiguration(tunerType, discoveredUSBTuner.getId());
-
- if(tunerConfiguration != null)
- {
- mLog.info("Tuner: " + discoveredUSBTuner + " - Applying Tuner Configuration");
- discoveredUSBTuner.setTunerConfiguration(tunerConfiguration);
- mTunerConfigurationManager.saveConfigurations();
- }
- }
- }
-
- mDiscoveredTunerModel.addDiscoveredTuner(discoveredUSBTuner);
+ startAndConfigureTuner(discoveredUSBTuner);
}
}
@@ -282,12 +265,77 @@ private DiscoveredTuner removeUsbTuner(int bus, String portAddress)
return mDiscoveredTunerModel.removeUsbTuner(bus, portAddress);
}
+ /**
+ * Starts, configures and adds the tuner to the tuner model.
+ * @param discoveredTuner to add and configure
+ */
+ private void startAndConfigureTuner(DiscoveredTuner discoveredTuner)
+ {
+ discoveredTuner.addTunerStatusListener(this);
+
+ //Set the tuner to disabled if the user has previously blacklisted the tuner
+ if(mTunerConfigurationManager.isDisabled(discoveredTuner))
+ {
+ discoveredTuner.setEnabled(false);
+ mLog.info("Tuner: " + discoveredTuner + " - Added / Disabled");
+ }
+ else
+ {
+ mLog.info("Tuner: " + discoveredTuner + " - Added / Starting ...");
+ //Attempt to start the discovered tuner and determine the tuner type
+ tunerStatusUpdated(discoveredTuner, TunerStatus.DISABLED, TunerStatus.ENABLED);
+ }
+
+ mDiscoveredTunerModel.addDiscoveredTuner(discoveredTuner);
+ }
+
/**
* Discover SDRPlay RSP tuners
*/
private void discoverSdrPlayTuners()
{
- //placeholder ...
+ ChannelizerType channelizerType = mUserPreferences.getTunerPreference().getChannelizerType();
+ RspDuoSelectionMode duoSelectionMode = mUserPreferences.getTunerPreference().getRspDuoTunerMode();
+
+ //Note: we have to keep this first API instance open while we use any RSP tuners, otherwise the additional API
+ //instance(s) used by the individual tuners become unresponsive. Note sure why.
+ mSDRplay = new SDRplay();
+
+ if(mSDRplay.isAvailable())
+ {
+ try
+ {
+ List deviceInfos = mSDRplay.getDeviceInfos();
+
+ mLog.info("Discovered [" + deviceInfos.size() + "] RSP devices from SDRplay API");
+
+ if(deviceInfos.isEmpty())
+ {
+ mSDRplay.close();
+ mSDRplay = null;
+ return;
+ }
+
+ for(DeviceInfo deviceInfo: deviceInfos)
+ {
+ List tuners = TunerFactory.getRspTuners(deviceInfo, channelizerType, duoSelectionMode);
+
+ for(DiscoveredRspTuner tuner: tuners)
+ {
+ startAndConfigureTuner(tuner);
+ }
+ }
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.info("Unable to get list of devices from SDRplay API");
+ }
+ }
+ else
+ {
+ mSDRplay.close();
+ mSDRplay = null;
+ }
}
/**
@@ -329,30 +377,44 @@ private void discoverRecordingTuners()
@Override
public void tunerStatusUpdated(DiscoveredTuner discoveredTuner, TunerStatus previous, TunerStatus current)
{
- mTunerConfigurationManager.tunerStatusUpdated(discoveredTuner, previous, current);
-
- if(previous != TunerStatus.ENABLED && current == TunerStatus.ENABLED)
+ if(current == TunerStatus.ENABLED)
{
discoveredTuner.start();
+ }
- if(discoveredTuner.hasTuner())
- {
- TunerType tunerType = discoveredTuner.getTuner().getTunerType();
+ //Special handling for RSPduo to auto-update enabled state for slave device when configured for master/slave operation
+ if(discoveredTuner instanceof DiscoveredRspDuoTuner1 rspDuoTuner1 && rspDuoTuner1.getDeviceInfo().getDeviceSelectionMode().isMasterMode())
+ {
+ String id = rspDuoTuner1.getId();
+ id = id.replace(DiscoveredRspDuoTuner1.RSP_DUO_ID_PREFIX + "1", DiscoveredRspDuoTuner1.RSP_DUO_ID_PREFIX + "2");
+ DiscoveredTuner rspDuoTuner2 = getDiscoveredTunerModel().getDiscoveredTuner(id);
- //Don't fetch or create a configuration for recording tuners
- if(tunerType != TunerType.RECORDING)
+ if(rspDuoTuner2 != null)
+ {
+ if(previous == TunerStatus.ENABLED && current == TunerStatus.DISABLED)
{
- TunerConfiguration tunerConfiguration = mTunerConfigurationManager
- .getTunerConfiguration(tunerType, discoveredTuner.getId());
-
- if(tunerConfiguration != null)
- {
- discoveredTuner.setTunerConfiguration(tunerConfiguration);
- mTunerConfigurationManager.saveConfigurations();
- }
+ rspDuoTuner2.setEnabled(false);
}
+ else if(previous == TunerStatus.DISABLED && current == TunerStatus.ENABLED)
+ {
+ rspDuoTuner2.setEnabled(true);
+ rspDuoTuner2.start();
+ }
+ }
+
+ //Notify tuner configuration manager to apply tuner configurations & update disabled tuner states
+ mTunerConfigurationManager.tunerStatusUpdated(rspDuoTuner1, previous, current);
+
+ if(rspDuoTuner2 != null)
+ {
+ mTunerConfigurationManager.tunerStatusUpdated(rspDuoTuner2, previous, current);
}
}
+ else
+ {
+ //Notify tuner configuration manager to apply tuner configuration
+ mTunerConfigurationManager.tunerStatusUpdated(discoveredTuner, previous, current);
+ }
}
/**
diff --git a/src/main/java/io/github/dsheirer/source/tuner/manager/TunerStatus.java b/src/main/java/io/github/dsheirer/source/tuner/manager/TunerStatus.java
index d32cb001a..04ab2d5b6 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/manager/TunerStatus.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/manager/TunerStatus.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2023 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
@@ -34,6 +34,12 @@ public enum TunerStatus
*/
DISABLED("Disabled"),
+
+ /**
+ * Indicates that the tuner has been removed from the system.
+ */
+ REMOVED("Removed"),
+
/**
* A tuner that has an error state and is unusable
*/
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/ControlRsp.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/ControlRsp.java
new file mode 100644
index 000000000..4194b7239
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/ControlRsp.java
@@ -0,0 +1,371 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay;
+
+import com.github.dsheirer.sdrplay.DeviceSelectionMode;
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.Status;
+import com.github.dsheirer.sdrplay.UpdateReason;
+import com.github.dsheirer.sdrplay.callback.IDeviceEventListener;
+import com.github.dsheirer.sdrplay.callback.IStreamListener;
+import com.github.dsheirer.sdrplay.device.Device;
+import com.github.dsheirer.sdrplay.device.TunerSelect;
+import com.github.dsheirer.sdrplay.parameter.control.AgcMode;
+import com.github.dsheirer.sdrplay.parameter.tuner.GainReduction;
+import com.github.dsheirer.sdrplay.parameter.tuner.IfMode;
+import com.github.dsheirer.sdrplay.parameter.tuner.LoMode;
+import java.util.concurrent.locks.ReentrantLock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base RSP control implementation
+ */
+public abstract class ControlRsp implements IControlRsp
+{
+ private static final Logger mLog = LoggerFactory.getLogger(ControlRsp.class);
+ private T mDevice;
+ protected RspSampleRate mSampleRate = RspSampleRate.RATE_8_000;
+ protected int mGain;
+ private IDeviceEventListener mDeviceEventListener;
+ private IStreamListener mStreamListener;
+
+ //Streaming control lock and boolean status indicator. Access to the boolean indicator is protected by the lock.
+ protected ReentrantLock mStreamingLock = new ReentrantLock();
+ protected boolean mStreaming = false;
+
+ /**
+ * Constructs an instance
+ * @param device for the device, obtained from the API
+ */
+ public ControlRsp(T device)
+ {
+ mDevice = device;
+ }
+
+ @Override
+ public TunerSelect getTunerSelect()
+ {
+ return TunerSelect.TUNER_1;
+ }
+
+ @Override
+ public void start() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().select();
+
+ //Enable automatic DC and I/Q correction
+ getDevice().getCompositeParameters().getControlAParameters().getDcOffset().setDC(true);
+ getDevice().getCompositeParameters().getControlAParameters().getDcOffset().setIQ(true);
+
+ //Setup IF, LO, and AGC Mode
+ getDevice().getCompositeParameters().getControlAParameters().getAgc().setAgcMode(AgcMode.DISABLE);
+ getDevice().setIfMode(IfMode.IF_ZERO);
+ getDevice().setLoMode(LoMode.AUTO);
+ }
+ else
+ {
+ throw new SDRPlayException("Unable to start - device is null");
+ }
+ }
+
+ @Override
+ public void stop() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ stopStream();
+ getDevice().release();
+ clearDevice();
+ }
+ }
+
+ @Override
+ public void startStream()
+ {
+ mStreamingLock.lock();
+
+ try
+ {
+ if(hasDevice())
+ {
+ if(!mStreaming)
+ {
+ getDevice().initStreamA(getDeviceEventListener(), getStreamListener());
+ mStreaming = true;
+ }
+ }
+ else
+ {
+ mLog.error("Unable to start RSP device sample stream - device not started");
+ }
+ }
+ catch(SDRPlayException se)
+ {
+ if(se.getStatus() == Status.FAIL)
+ {
+ mLog.error("Unable to start RSP streaming - device may have been unplugged - removing.");
+ if(mDeviceEventListener != null)
+ {
+ mDeviceEventListener.processDeviceRemoval(getTunerSelect());
+ }
+ }
+ else
+ {
+ mLog.error("Unable to initialize/start streaming for RSP device", se);
+ }
+ }
+ finally
+ {
+ mStreamingLock.unlock();
+ }
+ }
+
+ @Override
+ public void stopStream()
+ {
+ mStreamingLock.lock();
+
+ try
+ {
+ if(hasDevice() && mStreaming)
+ {
+ getDevice().uninitialize();
+ }
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to uninitialize/stop streaming for RSP device");
+ }
+ finally
+ {
+ mStreaming = false;
+ mStreamingLock.unlock();
+ }
+ }
+
+ @Override
+ public DeviceSelectionMode getDeviceSelectionMode()
+ {
+ //Default device selection mode for all tuners except the RSPduo
+ return DeviceSelectionMode.SINGLE_TUNER_1;
+ }
+
+ /**
+ * Device descriptor for this device
+ */
+ public T getDevice()
+ {
+ return mDevice;
+ }
+
+ /**
+ * RSP device was unplugged from USB bus. Clear the device and do not attempt any further interaction with the
+ * device via the API.
+ */
+ @Override
+ public void deviceRemoved()
+ {
+ clearDevice();
+
+ mStreamingLock.lock();
+
+ try
+ {
+ mStreaming = false;
+ }
+ finally
+ {
+ mStreamingLock.unlock();
+ }
+ }
+
+ /**
+ * Clears/nullifies the device. This should be invoked after stopping the device to prevent reuse.
+ */
+ public void clearDevice()
+ {
+ mDevice = null;
+ }
+
+ /**
+ * Indicates if this control has a non-null device.
+ * @return true if non-null device.
+ */
+ public boolean hasDevice()
+ {
+ return getDevice() != null;
+ }
+
+ /**
+ * Sets the sample rate
+ * @param sampleRate enumeration value.
+ * @throws SDRPlayException
+ */
+ @Override
+ public void setSampleRate(RspSampleRate sampleRate) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ mSampleRate = sampleRate;
+ getDevice().getTuner().setBandwidth(sampleRate.getBandwidth());
+ getDevice().getCompositeParameters().getDeviceParameters().getSamplingFrequency()
+ .setSampleRate(sampleRate.getSampleRate());
+ getDevice().update(getTunerSelect(), UpdateReason.DEVICE_SAMPLE_RATE);
+ getDevice().getCompositeParameters().getControlAParameters().getDecimation().setWideBandSignal(true);
+ getDevice().setDecimation(sampleRate.getDecimation());
+ }
+ else
+ {
+ throw new SDRPlayException("RSP tuner has not been started - can't apply sample rate");
+ }
+ }
+
+ /**
+ * Sets the gain index
+ * @param gain index value (0 - 28)
+ * @throws SDRPlayException
+ */
+ @Override
+ public void setGain(int gain) throws SDRPlayException
+ {
+ validateGain(gain);
+
+ if(gain != mGain)
+ {
+ mGain = gain;
+ getDevice().getTuner().setGain(mGain);
+ }
+ }
+
+
+ @Override
+ public void acknowledgePowerOverload(TunerSelect tunerSelect) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().acknowledgePowerOverload(tunerSelect);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public long getTunedFrequency() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getDevice().getTuner().getFrequency();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setTunedFrequency(long frequency) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().getTuner().setFrequency(frequency);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ /**
+ * Current sample rate setting
+ */
+ @Override
+ public RspSampleRate getSampleRateEnumeration()
+ {
+ return mSampleRate;
+ }
+
+ /**
+ * Current sample rate
+ */
+ @Override
+ public double getCurrentSampleRate()
+ {
+ return getSampleRateEnumeration().getEffectiveSampleRate();
+ }
+
+ /**
+ * Current gain index
+ * @return gain index
+ */
+ @Override
+ public int getGain()
+ {
+ return mGain;
+ }
+
+ /**
+ * Verifies that the requested gain index setting is within the range of valid gain values.
+ * @param gain to validate
+ * @throws SDRPlayException if the gain index value is outside the range of valid values.
+ */
+ protected void validateGain(int gain) throws SDRPlayException
+ {
+ if(gain < GainReduction.MIN_GAIN_INDEX || gain > GainReduction.MAX_GAIN_INDEX)
+ {
+ throw new SDRPlayException("Invalid gain index value [" + gain + "]. Valid range is " +
+ GainReduction.MIN_GAIN_INDEX + " - " + GainReduction.MAX_GAIN_INDEX);
+ }
+ }
+
+ /**
+ * Registers listeners to receive device events and sample streams.
+ * @param deviceEventListener to receive device events
+ * @param streamListener to receive sample stream and related parameters.
+ */
+ @Override
+ public void resister(IDeviceEventListener deviceEventListener, IStreamListener streamListener)
+ {
+ mDeviceEventListener = deviceEventListener;
+ mStreamListener = streamListener;
+ }
+
+ /**
+ * Registered device event listener
+ * @return device event listener or null if a listener has not been registered.
+ */
+ protected IDeviceEventListener getDeviceEventListener()
+ {
+ return mDeviceEventListener;
+ }
+
+ /**
+ * Registered stream listener
+ * @return stream listener or null if a listener has not been registered.
+ */
+ protected IStreamListener getStreamListener()
+ {
+ return mStreamListener;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/DiscoveredRspTuner.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/DiscoveredRspTuner.java
new file mode 100644
index 000000000..af990cfe9
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/DiscoveredRspTuner.java
@@ -0,0 +1,122 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay;
+
+import com.github.dsheirer.sdrplay.device.DeviceInfo;
+import com.github.dsheirer.sdrplay.device.DeviceType;
+import io.github.dsheirer.preference.source.ChannelizerType;
+import io.github.dsheirer.source.tuner.TunerClass;
+import io.github.dsheirer.source.tuner.TunerFactory;
+import io.github.dsheirer.source.tuner.manager.DiscoveredTuner;
+
+/**
+ * Discovered SDRplay RSP tuner
+ */
+public abstract class DiscoveredRspTuner extends DiscoveredTuner
+{
+ private final DeviceInfo mDeviceInfo;
+ private final ChannelizerType mChannelizerType;
+
+ /**
+ * Constructs an instance
+ * @param deviceInfo to select the device from the API
+ */
+ public DiscoveredRspTuner(DeviceInfo deviceInfo, ChannelizerType channelizerType)
+ {
+ mDeviceInfo = deviceInfo;
+ mChannelizerType = channelizerType;
+ }
+
+ /**
+ * Information about the discovered RSP device
+ * @return device info
+ */
+ public DeviceInfo getDeviceInfo()
+ {
+ return mDeviceInfo;
+ }
+
+ /**
+ * Channelizer type to use for the tuner
+ */
+ protected ChannelizerType getChannelizerType()
+ {
+ return mChannelizerType;
+ }
+
+ @Override
+ public TunerClass getTunerClass()
+ {
+ return TunerClass.RSP;
+ }
+
+ /**
+ * Type of RSP tuner device
+ */
+ public DeviceType getDeviceType()
+ {
+ return mDeviceInfo.getDeviceType();
+ }
+
+ /**
+ * Constructs and starts the tuner
+ */
+ @Override
+ public void start()
+ {
+ if(isAvailable() && !hasTuner())
+ {
+ try
+ {
+ mTuner = TunerFactory.getRspTuner(getDeviceInfo(), getChannelizerType(), this);
+ }
+ catch(Exception se)
+ {
+ setErrorMessage("Tuner unavailable [" + getId() + "]");
+ mTuner = null;
+ }
+
+ if(hasTuner())
+ {
+ try
+ {
+ mTuner.start();
+ }
+ catch(Exception se)
+ {
+ setErrorMessage("Error starting tuner [" + getId() + "]");
+ mTuner = null;
+ }
+ }
+ }
+ }
+
+ @Override
+ public String getId()
+ {
+ return getDeviceType().name() + " SER#" + getDeviceInfo().getSerialNumber();
+ }
+
+ @Override
+ public String toString()
+ {
+ return getId();
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/IControlRsp.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/IControlRsp.java
new file mode 100644
index 000000000..031a801f5
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/IControlRsp.java
@@ -0,0 +1,128 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay;
+
+import com.github.dsheirer.sdrplay.DeviceSelectionMode;
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.callback.IDeviceEventListener;
+import com.github.dsheirer.sdrplay.callback.IStreamListener;
+import com.github.dsheirer.sdrplay.device.Device;
+import com.github.dsheirer.sdrplay.device.TunerSelect;
+
+/**
+ * Control interface for base RSP device
+ */
+public interface IControlRsp
+{
+ DeviceSelectionMode getDeviceSelectionMode();
+
+ /**
+ * Device descriptor for this RSP
+ * @return device descriptor
+ */
+ Device getDevice();
+
+ /**
+ * Process an RSP device removal. Device memory resources should be nullified and the software should not attempt
+ * any further interaction with the device via the API.
+ */
+ void deviceRemoved();
+
+ /**
+ * Selected tuner for this RSP.
+ * @return selected tuner.
+ */
+ TunerSelect getTunerSelect();
+
+ /**
+ * Starts the device
+ */
+ void start() throws SDRPlayException;
+
+ /**
+ * Stops the device
+ */
+ void stop() throws SDRPlayException;
+
+ /**
+ * Registers listeners to receive device events and streaming samples when startStream() is invoked.
+ * @param deviceEventListener to receive device events
+ * @param streamListener to receive sample stream and related parameters.
+ */
+ void resister(IDeviceEventListener deviceEventListener, IStreamListener streamListener);
+
+ /**
+ * Starts the sample stream and delivers the samples to the registered listener.
+ */
+ void startStream();
+
+ /**
+ * Stops the sample stream.
+ */
+ void stopStream();
+
+ /**
+ * Callback to acknowledge a power overload event.
+ * @param tunerSelect identifies the tuner where the power overload is happening.
+ */
+ void acknowledgePowerOverload(TunerSelect tunerSelect) throws SDRPlayException;
+
+ /**
+ * Current center tune frequency
+ * @return frequency in Hertz
+ */
+ long getTunedFrequency() throws SDRPlayException;
+
+ /**
+ * Sets the center tune frequency
+ * @param frequency in Hertz
+ */
+ void setTunedFrequency(long frequency) throws SDRPlayException;
+
+ /**
+ * Current sample rate enumeration value
+ * @return sample rate enumeration.
+ */
+ RspSampleRate getSampleRateEnumeration();
+
+ /**
+ * Sets the sample rate.
+ * @param rspSampleRate enumeration value.
+ */
+ void setSampleRate(RspSampleRate rspSampleRate) throws SDRPlayException;
+
+ /**
+ * Current sample rate value.
+ * @return sample rate in Hertz
+ */
+ double getCurrentSampleRate();
+
+ /**
+ * Sets the gain index value.
+ * @param gain index value (0 - 28)
+ */
+ void setGain(int gain) throws SDRPlayException;
+
+ /**
+ * Current gain index value
+ * @return gain index value (0 - 28)
+ */
+ int getGain();
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspNativeBuffer.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspNativeBuffer.java
new file mode 100644
index 000000000..e8cb792b8
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspNativeBuffer.java
@@ -0,0 +1,141 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay;
+
+import io.github.dsheirer.buffer.AbstractNativeBuffer;
+import io.github.dsheirer.sample.complex.ComplexSamples;
+import io.github.dsheirer.sample.complex.InterleavedComplexSamples;
+import java.util.Iterator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Native buffer implementation for RSP tuner I/Q sample buffers.
+ *
+ * Note: in testing with API v3.07, the daemon returns 2016 samples in each of the I and Q arrays.
+ */
+public class RspNativeBuffer extends AbstractNativeBuffer
+{
+ private static final Logger mLog = LoggerFactory.getLogger(RspNativeBuffer.class);
+ private static final float SAMPLE_TO_FLOAT = 1.0f / 32768.0f;
+ private short[] mISamples;
+ private short[] mQSamples;
+
+ /**
+ * Constructs an instance
+ * @param i samples array
+ * @param q samples array
+ * @param timestamp for the first sample
+ * @param samplesPerMillisecond used to calculate sub-buffer fragment timestamp offsets from the start of this buffer.
+ */
+ public RspNativeBuffer(short[] i, short[] q, long timestamp, float samplesPerMillisecond)
+ {
+ super(timestamp, samplesPerMillisecond);
+ mISamples = i;
+ mQSamples = q;
+ }
+
+ /**
+ * Iterator over samples that produces complex sample buffers.
+ */
+ @Override
+ public Iterator iterator()
+ {
+ return new SampleIterator();
+ }
+
+ /**
+ * Iterator over samples that produces interleaved complex sample buffers
+ */
+ @Override
+ public Iterator iteratorInterleaved()
+ {
+ return new InterleavedSampleIterator();
+ }
+
+ @Override
+ public int sampleCount()
+ {
+ return mISamples.length * 2;
+ }
+
+ /**
+ * Iterator providing (non-interleaved) complex sample buffers
+ */
+ private class SampleIterator implements Iterator
+ {
+ private int mSamplePointer;
+
+ @Override
+ public boolean hasNext()
+ {
+ return mSamplePointer < mISamples.length;
+ }
+
+ @Override
+ public ComplexSamples next()
+ {
+ float[] i = new float[mISamples.length];
+ float[] q = new float[mISamples.length];
+
+ for(int x = 0; x < mISamples.length; x++)
+ {
+ i[x] = mISamples[x] * SAMPLE_TO_FLOAT;
+ q[x] = mQSamples[x] * SAMPLE_TO_FLOAT;
+ }
+
+ mSamplePointer += mISamples.length;
+
+ return new ComplexSamples(i, q, getTimestamp());
+ }
+ }
+
+ /**
+ * Interator providing interleaved sample buffers.
+ */
+ private class InterleavedSampleIterator implements Iterator
+ {
+ private int mSamplePointer;
+
+ @Override
+ public boolean hasNext()
+ {
+ return mSamplePointer < mISamples.length;
+ }
+
+ @Override
+ public InterleavedComplexSamples next()
+ {
+ float[] samples = new float[mISamples.length * 2];
+
+ int index = 0;
+
+ for(int x = 0; x < mISamples.length; x++)
+ {
+ samples[index++] = mISamples[x] * SAMPLE_TO_FLOAT;
+ samples[index++] = mQSamples[x] * SAMPLE_TO_FLOAT;
+ }
+
+ mSamplePointer += mISamples.length;
+
+ return new InterleavedComplexSamples(samples, getTimestamp());
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspSampleRate.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspSampleRate.java
new file mode 100644
index 000000000..7bd243310
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspSampleRate.java
@@ -0,0 +1,185 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay;
+
+import com.github.dsheirer.sdrplay.device.Decimate;
+import com.github.dsheirer.sdrplay.parameter.tuner.Bandwidth;
+
+import java.util.EnumSet;
+
+/**
+ * RSP device Sample Rate, Bandwidth and Decimation enumeration
+ *
+ * Note: final effective sample rate must be greater than IF bandwidth setting to avoid aliasing. The available IF
+ * bandwidth values effectively dictate the available sample rates
+ */
+public enum RspSampleRate
+{
+ RATE_0_250(8_000_000, 016_000, Bandwidth.BW_0_300, Decimate.X32, "0.250 MHz (0.234 usable)"),
+ RATE_0_500(8_000_000, 024_000, Bandwidth.BW_0_600, Decimate.X16, "0.500 MHz (0.476 usable)"),
+ RATE_1_000(8_000_000, 100_000, Bandwidth.BW_1_536, Decimate.X8, "1.000 MHz (0.900 usable)"),
+ RATE_1_500(6_000_000, 140_000, Bandwidth.BW_1_536, Decimate.X4, "1.500 MHz (1.360 usable)"),
+ RATE_3_000(6_000_000, 300_000, Bandwidth.BW_5_000, Decimate.X2, "3.000 MHz (2.700 usable)"),
+ RATE_4_000(8_000_000, 340_000, Bandwidth.BW_5_000, Decimate.X2, "4.000 MHz (3.560 usable)"),
+ RATE_5_000(5_000_000, 880_000, Bandwidth.BW_5_000, Decimate.X1, "5.000 MHz (4.120 usable)"),
+ RATE_6_000(6_000_000, 800_000, Bandwidth.BW_6_000, Decimate.X1, "6.000 MHz (5.200 usable)"),
+ RATE_7_000(7_000_000, 1_040_000, Bandwidth.BW_7_000, Decimate.X1, "7.000 MHz (5.960 usable)"),
+ RATE_8_000(8_000_000, 1_060_000, Bandwidth.BW_8_000, Decimate.X1, "8.000 MHz (6.940 usable)"),
+ RATE_9_000(9_000_000, 1_620_000, Bandwidth.BW_8_000, Decimate.X1, "9.000 MHz (7.380 usable)"),
+ RATE_10_000(10_000_000, 1_500_000, Bandwidth.BW_8_000, Decimate.X1, "10.000 MHz (8.500 usable)"),
+
+ /**
+ * Note: in dual tuner mode, available sample rates are 6 or 8 MHz with an effective output rate of
+ * 2 MHz. Decimation is applied against the final 2 MHz rate, not the original 6/8 sampling rate.
+ */
+ DUO_RATE_0_500(8_000_000, 50_000, Bandwidth.BW_8_000, Decimate.X4, "0.500 MHz (0.450 usable)"),
+ DUO_RATE_1_000(8_000_000, 50_000, Bandwidth.BW_8_000, Decimate.X2, "1.000 MHz (0.950 usable)"),
+ DUO_RATE_1_500(6_000_000, 0, Bandwidth.BW_6_000, Decimate.X1, "1.500 MHz (1.500 usable)"),
+ DUO_RATE_2_000(8_000_000, 0, Bandwidth.BW_8_000, Decimate.X1, "2.000 MHz (2.000 usable)"),
+
+ UNDEFINED(0, 0, Bandwidth.UNDEFINED, Decimate.X1, "UNDEFINED");
+
+ private long mSampleRate;
+ private long mUnusable;
+ private Bandwidth mBandwidth;
+ private Decimate mDecimation;
+ private String mDescription;
+
+ /**
+ * Constructs an instance
+ * @param sampleRate in hertz
+ * @param unusable bandwidth (total) in Hertz due to IF or decimation filter roll-off at spectrum edges
+ * @param bandwidth of the frequency spectrum
+ * @param decimation to be applied to the original sample rate to achieve the effective sample rate
+ * @param description for UI display
+ */
+ RspSampleRate(long sampleRate, long unusable, Bandwidth bandwidth, Decimate decimation, String description)
+ {
+ mSampleRate = sampleRate;
+ mUnusable = unusable;
+ mBandwidth = bandwidth;
+ mDecimation = decimation;
+ mDescription = description;
+ }
+
+ /**
+ * Single tuner sample rates for all devices operating in single tuner mode
+ */
+ public static EnumSet SINGLE_TUNER_SAMPLE_RATES = EnumSet.range(RATE_0_250, RATE_10_000);
+
+ /**
+ * RSPduo dual-tuner mode sample rates
+ */
+ public static EnumSet DUAL_TUNER_SAMPLE_RATES = EnumSet.range(DUO_RATE_0_500, DUO_RATE_2_000);
+
+ /**
+ * Sample Rate
+ * @return sample rate (Hz)
+ */
+ public long getSampleRate()
+ {
+ return mSampleRate;
+ }
+
+ /**
+ * Usable bandwidth in range 0.0 to 1.0, where 1.0 is 100% usable bandwidth
+ */
+ public double getUsableBandwidth()
+ {
+ if(getSampleRate() != 0)
+ {
+ return 1.0 - ((double)mUnusable / (double)getEffectiveSampleRate());
+ }
+
+ return 0.0;
+ }
+
+ /**
+ * Indicates if this is a sample rate supported by the RSPduo operating in dual-tuner mode.
+ * @return true if this is a dual-tuner sample rate.
+ */
+ public boolean isDualTunerSampleRate()
+ {
+ return DUAL_TUNER_SAMPLE_RATES.contains(this);
+ }
+
+ /**
+ * Sample size in bits. Can be used to adjust spectral display for effective dynamic range.
+ * @return sample size in bits.
+ */
+ public int getSampleSize()
+ {
+ return mDecimation.getSampleSize();
+ }
+
+ /**
+ * Decimation rate to be applied against sample rate.
+ * @return decimation value
+ */
+ public Decimate getDecimation()
+ {
+ return mDecimation;
+ }
+
+ /**
+ * Indicates if this sample rate specifies decimation
+ */
+ public boolean hasDecimation()
+ {
+ return getDecimation().isEnabled();
+ }
+
+ /**
+ * Effective Sample Rate (sample rate / decimation). Note: for RSPduo operating in dual-tuner mode, an
+ * inherent x4 decimation is applied in the hardware.
+ * @return effective sample rate (Hz)
+ */
+ public long getEffectiveSampleRate()
+ {
+ if(isDualTunerSampleRate())
+ {
+ //Dual tuner sample rate is specified at 8 MHz, but there is an inherent x4 decimation to 2 MHz
+ //on top of the user specified decimation rate.
+ return getSampleRate() / getDecimation().getValue() / 4;
+ }
+ else
+ {
+ return getSampleRate() / getDecimation().getValue();
+ }
+ }
+
+ /**
+ * Bandwidth entry
+ */
+ public Bandwidth getBandwidth()
+ {
+ return mBandwidth;
+ }
+
+ /**
+ * Overrides the default string representation to use the UI description/label.
+ * @return string representation of the entry
+ */
+ @Override
+ public String toString()
+ {
+ return mDescription;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTuner.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTuner.java
new file mode 100644
index 000000000..8e339a441
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTuner.java
@@ -0,0 +1,104 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay;
+
+import io.github.dsheirer.preference.source.ChannelizerType;
+import io.github.dsheirer.source.tuner.ITunerErrorListener;
+import io.github.dsheirer.source.tuner.Tuner;
+import io.github.dsheirer.source.tuner.TunerClass;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.IControlRspDuoTuner1;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.IControlRspDuoTuner2;
+
+/**
+ * Generic RSP tuner with a device specific tuner controller implementation.
+ */
+public class RspTuner extends Tuner
+{
+ /**
+ * Constructs an instance
+ * @param tunerController for controlling the tuner
+ * @param tunerErrorListener to process errors from this tuner
+ * @param channelizerType to use with this tuner
+ */
+ public RspTuner(RspTunerController tunerController, ITunerErrorListener tunerErrorListener, ChannelizerType channelizerType)
+ {
+ super(tunerController, tunerErrorListener, channelizerType);
+ }
+
+ @Override
+ public int getMaximumUSBBitsPerSecond()
+ {
+ //12-bits per sample, 2 samples per frame, 10 MHz sample rate
+ return 320_000_000;
+ }
+
+ @Override
+ public String getUniqueID()
+ {
+ return getRspTunerController().getControlRsp().getDevice().getSerialNumber();
+ }
+
+ @Override
+ public TunerClass getTunerClass()
+ {
+ return TunerClass.RSP;
+ }
+
+ /**
+ * RSP Tuner controller for this tuner
+ */
+ public RspTunerController getRspTunerController()
+ {
+ return (RspTunerController)getTunerController();
+ }
+
+ @Override
+ public String getPreferredName()
+ {
+ if(getRspTunerController().getControlRsp() instanceof IControlRspDuoTuner1 &&
+ getRspTunerController().getControlRsp().getDevice() != null)
+ {
+ return getRspTunerController().getControlRsp().getDevice().getDeviceType() +
+ " SER:" + getRspTunerController().getControlRsp().getDevice().getSerialNumber() + " Tuner 1";
+ }
+ else if(getRspTunerController().getControlRsp() instanceof IControlRspDuoTuner2 &&
+ getRspTunerController().getControlRsp().getDevice() != null)
+ {
+ return getRspTunerController().getControlRsp().getDevice().getDeviceType() +
+ " SER:" + getRspTunerController().getControlRsp().getDevice().getSerialNumber() + " Tuner 2";
+ }
+ else if(getRspTunerController().getControlRsp() instanceof IControlRsp &&
+ getRspTunerController().getControlRsp().getDevice() != null)
+ {
+ return getRspTunerController().getControlRsp().getDevice().getDeviceType() +
+ " SER:" + getRspTunerController().getControlRsp().getDevice().getSerialNumber();
+ }
+ else
+ {
+ return "RSP Tuner - Device Not Available";
+ }
+ }
+
+ @Override
+ public double getSampleSize()
+ {
+ return getRspTunerController().getControlRsp().getSampleRateEnumeration().getSampleSize();
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerConfiguration.java
new file mode 100644
index 000000000..6e14bf167
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerConfiguration.java
@@ -0,0 +1,106 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay;
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.github.dsheirer.sdrplay.parameter.tuner.GainReduction;
+import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
+import io.github.dsheirer.source.tuner.sdrplay.rsp1a.Rsp1aTunerConfiguration;
+import io.github.dsheirer.source.tuner.sdrplay.rsp2.Rsp2TunerConfiguration;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.RspDuoTuner1Configuration;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.RspDuoTuner2Configuration;
+import io.github.dsheirer.source.tuner.sdrplay.rspDx.RspDxTunerConfiguration;
+
+/**
+ * Abstract RSP tuner configuration
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
+@JsonSubTypes({
+ @JsonSubTypes.Type(value = Rsp1aTunerConfiguration.class, name = "rsp1aTunerConfiguration"),
+ @JsonSubTypes.Type(value = Rsp2TunerConfiguration.class, name = "rsp2TunerConfiguration"),
+ @JsonSubTypes.Type(value = RspDuoTuner1Configuration.class, name = "rspDuoTuner1Configuration"),
+ @JsonSubTypes.Type(value = RspDuoTuner2Configuration.class, name = "rspDuoTuner2Configuration"),
+ @JsonSubTypes.Type(value = RspDxTunerConfiguration.class, name = "rspDxTunerConfiguration"),
+})
+public abstract class RspTunerConfiguration extends TunerConfiguration
+{
+ public static final RspSampleRate DEFAULT_SINGLE_TUNER_SAMPLE_RATE = RspSampleRate.RATE_8_000;
+ public static final RspSampleRate DEFAULT_DUAL_TUNER_SAMPLE_RATE = RspSampleRate.DUO_RATE_2_000;
+
+ private RspSampleRate mRspSampleRate = DEFAULT_SINGLE_TUNER_SAMPLE_RATE;
+ private int mGain = 14;
+
+ /**
+ * JAXB Constructor
+ */
+ public RspTunerConfiguration()
+ {
+ }
+
+ /**
+ * Constructs an instance with the specified unique id
+ * @param uniqueId for the tuner
+ */
+ public RspTunerConfiguration(String uniqueId)
+ {
+ super(uniqueId);
+ }
+
+ /**
+ * Sample rate for the tuner
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "sampleRate")
+ public RspSampleRate getSampleRate()
+ {
+ return mRspSampleRate;
+ }
+
+ /**
+ * Sets the sample rate for the tuner
+ */
+ public void setSampleRate(RspSampleRate rspSampleRate)
+ {
+ mRspSampleRate = rspSampleRate;
+ }
+
+ /**
+ * Gain index to use
+ * @return gain index, 0 - 28
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "gain")
+ public int getGain()
+ {
+ return mGain;
+ }
+
+ /**
+ * Sets the gain index
+ * @param gain index, 0 - 28
+ */
+ public void setGain(int gain)
+ {
+ if(GainReduction.MIN_GAIN_INDEX <= gain && gain <= GainReduction.MAX_GAIN_INDEX)
+ {
+ mGain = gain;
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerController.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerController.java
new file mode 100644
index 000000000..d4e813fdf
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerController.java
@@ -0,0 +1,325 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.callback.IDeviceEventListener;
+import com.github.dsheirer.sdrplay.callback.IStreamListener;
+import com.github.dsheirer.sdrplay.callback.StreamCallbackParameters;
+import com.github.dsheirer.sdrplay.device.TunerSelect;
+import com.github.dsheirer.sdrplay.parameter.event.EventType;
+import com.github.dsheirer.sdrplay.parameter.event.GainCallbackParameters;
+import com.github.dsheirer.sdrplay.parameter.event.PowerOverloadCallbackParameters;
+import com.github.dsheirer.sdrplay.parameter.event.RspDuoModeCallbackParameters;
+import io.github.dsheirer.buffer.INativeBuffer;
+import io.github.dsheirer.sample.Listener;
+import io.github.dsheirer.source.SourceException;
+import io.github.dsheirer.source.tuner.ITunerErrorListener;
+import io.github.dsheirer.source.tuner.TunerController;
+import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract/Base RSP tuner controller
+ */
+public abstract class RspTunerController extends TunerController
+ implements IDeviceEventListener, IStreamListener
+{
+ private static final Logger mLog = LoggerFactory.getLogger(RspTunerController.class);
+ protected static final long MINIMUM_FREQUENCY = 100_000;
+ protected static final long MAXIMUM_FREQUENCY = 2_000_000_000;
+ protected static final int MIDDLE_UNUSABLE_BANDWIDTH = 0;
+ private I mControlRsp;
+
+ /**
+ * Abstract tuner controller class. The tuner controller manages frequency bandwidth and currently tuned channels
+ * that are being fed samples from the tuner.
+ *
+ * @param controlRsp that is the RSP tuner
+ * @param tunerErrorListener to monitor errors produced from this tuner controller
+ */
+ public RspTunerController(I controlRsp, ITunerErrorListener tunerErrorListener)
+ {
+ super(tunerErrorListener);
+ mControlRsp = controlRsp;
+
+ //Register this controller to receive device events and sample streams when startStream() is invoked.
+ mControlRsp.resister(this, this);
+
+ setMinimumFrequency(MINIMUM_FREQUENCY);
+ setMaximumFrequency(MAXIMUM_FREQUENCY);
+ setMiddleUnusableHalfBandwidth(MIDDLE_UNUSABLE_BANDWIDTH);
+ setUsableBandwidthPercentage(1.0); //Initial value
+ }
+
+ @Override
+ public void apply(TunerConfiguration config) throws SourceException
+ {
+ if(config instanceof RspTunerConfiguration rtc)
+ {
+ //This sets the frequency and software PPM
+ super.apply(config);
+
+ try
+ {
+ setSampleRate(rtc.getSampleRate());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSP sample rate to " + rtc.getSampleRate(), se);
+ }
+
+ try
+ {
+ getControlRsp().setGain(rtc.getGain());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSP gain index to " + rtc.getGain());
+ }
+ }
+ }
+
+ /**
+ * The RSP control for this tuner controller
+ */
+ public I getControlRsp()
+ {
+ return mControlRsp;
+ }
+
+ @Override
+ public TunerSelect getTunerSelect()
+ {
+ return mControlRsp.getTunerSelect();
+ }
+
+ @Override
+ public void processStream(short[] inphase, short[] quadrature,
+ StreamCallbackParameters parameters, boolean reset)
+ {
+ //RSP I/Q sample buffers are small and don't currently get fragmented by the RspNativeBuffer, so we don't
+ //calculate the sub-buffer samples per millisecond value -- just use a constant value of 0.
+ mNativeBufferBroadcaster.broadcast(new RspNativeBuffer(inphase, quadrature, System.currentTimeMillis(), 0.0f));
+
+ if(reset)
+ {
+// mLog.info(getControlRsp().getDeviceDescriptor().getDeviceType() + " - sample stream was reset");
+ }
+ if(parameters.isGainReductionChanged())
+ {
+// mLog.info("^^^ Got a gain reduction change");
+ }
+ if(parameters.isRfFrequencyChanged())
+ {
+// mLog.info("^^^ Got a frequency changed");
+ }
+ if(parameters.isSampleRateChanged())
+ {
+// mLog.info("^^^ Got a sample rate changed");
+ }
+ }
+
+ /**
+ * Starts this RSP tuner and attempts to claim the device via the API
+ * @throws SourceException
+ */
+ @Override
+ public void start() throws SourceException
+ {
+ try
+ {
+ mControlRsp.start();
+ }
+ catch(SDRPlayException se)
+ {
+ throw new SourceException("Unable to select tuner - in use");
+ }
+ }
+
+ @Override
+ public void stop()
+ {
+ try
+ {
+ mControlRsp.stop();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error releasing RSP tuner device", se);
+ }
+ }
+
+ /**
+ * Adds the listener to receive native buffers and starts the sample stream when this is the first listener.
+ * @param listener to add
+ */
+ @Override
+ public void addBufferListener(Listener listener)
+ {
+ mBufferListenerLock.lock();
+
+ try
+ {
+ if(!hasBufferListeners())
+ {
+ mControlRsp.startStream();
+ }
+
+ super.addBufferListener(listener);
+ }
+ finally
+ {
+ mBufferListenerLock.unlock();
+ }
+ }
+
+ /**
+ * Removes the listener from receiving native buffers and stops the sample stream when this is the last listener.
+ * @param listener to remove
+ */
+ @Override
+ public void removeBufferListener(Listener listener)
+ {
+ mBufferListenerLock.lock();
+
+ try
+ {
+ super.removeBufferListener(listener);
+
+ if(!hasBufferListeners())
+ {
+ mControlRsp.stopStream();
+ }
+ }
+ finally
+ {
+ mBufferListenerLock.unlock();
+ }
+ }
+
+ /**
+ * Currently tuned frequency
+ * @return frequency in Hertz
+ * @throws SourceException if there is an error
+ */
+ @Override
+ public long getTunedFrequency() throws SourceException
+ {
+ try
+ {
+ return getControlRsp().getTunedFrequency();
+ }
+ catch(SDRPlayException se)
+ {
+ throw new SourceException("Error setting tuned frequency", se);
+ }
+ }
+
+ /**
+ * Sets the center tuned frequency.
+ * @param frequency in Hertz
+ * @throws SourceException if there is an error
+ */
+ @Override
+ public void setTunedFrequency(long frequency) throws SourceException
+ {
+ try
+ {
+ getControlRsp().setTunedFrequency(frequency);
+ }
+ catch(SDRPlayException se)
+ {
+ throw new SourceException("Unable to set center frequency [" + frequency + "]", se);
+ }
+ }
+
+ /**
+ * Sets the sample rate
+ * @param rspSampleRate to apply
+ * @throws SDRPlayException if there is an error
+ */
+ public void setSampleRate(RspSampleRate rspSampleRate) throws SDRPlayException
+ {
+ getControlRsp().setSampleRate(rspSampleRate);
+
+ try
+ {
+ mFrequencyController.setSampleRate((int) rspSampleRate.getEffectiveSampleRate());
+ }
+ catch(SourceException se)
+ {
+ mLog.error("Error setting sample rate in frequency controller");
+ }
+
+ //Update the usable bandwidth based on the sample rate and filtered bandwidth
+ setUsableBandwidthPercentage(rspSampleRate.getUsableBandwidth());
+ }
+
+ @Override
+ public double getCurrentSampleRate() throws SourceException
+ {
+ return getControlRsp().getCurrentSampleRate();
+ }
+
+ @Override
+ public int getBufferSampleCount()
+ {
+ return 128;
+ }
+
+ //Device Event Listener interface methods ...
+ @Override
+ public void processEvent(EventType eventType, TunerSelect tunerSelect) {}
+ @Override
+ public void processGainChange(TunerSelect tunerSelect, GainCallbackParameters parameters) {}
+ @Override
+ public void processRspDuoModeChange(TunerSelect tunerSelect, RspDuoModeCallbackParameters parameters) {}
+ @Override
+ public void processPowerOverload(TunerSelect tunerSelect, PowerOverloadCallbackParameters parameters)
+ {
+ if(getControlRsp() != null)
+ {
+ try
+ {
+ getControlRsp().acknowledgePowerOverload(tunerSelect);
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to acknowledge power overload for [" + tunerSelect + "]", se);
+ }
+ }
+ }
+
+ @Override
+ public void processDeviceRemoval(TunerSelect tunerSelect)
+ {
+ mLog.info("Processing device removal for tuner [" + tunerSelect + "] controller class [" + getClass().getSimpleName() + "]");
+ //Command the control RSP to nullify the device so that we cease all attempts to control the device via the API
+ if(getControlRsp() != null)
+ {
+ getControlRsp().deviceRemoved();
+ }
+
+ //Signal that tuner is removed so parent tuner and discovered tuner wrapper can do graceful removal/cleanup
+ tunerRemoved();
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerEditor.java
new file mode 100644
index 000000000..60b729957
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerEditor.java
@@ -0,0 +1,108 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay;
+
+import com.github.dsheirer.sdrplay.parameter.tuner.GainReduction;
+import io.github.dsheirer.preference.UserPreferences;
+import io.github.dsheirer.source.tuner.manager.TunerManager;
+import io.github.dsheirer.source.tuner.ui.TunerEditor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JSlider;
+
+/**
+ * Abstract RSP tuner editor
+ */
+public abstract class RspTunerEditor extends TunerEditor
+{
+ private Logger mLog = LoggerFactory.getLogger(RspTunerEditor.class);
+ private JSlider mGainSlider;
+ private JLabel mGainValueLabel;
+
+ /**
+ * Constructs an instance
+ * @param userPreferences for preference settings
+ * @param tunerManager to notify for state changes
+ * @param discoveredTuner to be edited.
+ */
+ public RspTunerEditor(UserPreferences userPreferences, TunerManager tunerManager, DiscoveredRspTuner discoveredTuner)
+ {
+ super(userPreferences, tunerManager, discoveredTuner);
+ }
+
+ private RspTunerController getTunerController()
+ {
+ return (RspTunerController) getTuner().getTunerController();
+ }
+
+ /**
+ * Gain reduction slider control
+ */
+ protected JSlider getGainSlider()
+ {
+ if(mGainSlider == null)
+ {
+ mGainSlider = new JSlider(JSlider.HORIZONTAL, GainReduction.MIN_GAIN_INDEX,
+ GainReduction.MAX_GAIN_INDEX, GainReduction.MIN_GAIN_INDEX);
+ mGainSlider.setEnabled(false);
+ mGainSlider.setMajorTickSpacing(1);
+ mGainSlider.setPaintTicks(true);
+ mGainSlider.addChangeListener(event ->
+ {
+ int gain = mGainSlider.getValue();
+
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setGain(gain);
+ save();
+ }
+ catch(Exception e)
+ {
+ mLog.error("Couldn't set RSP gain to:" + gain, e);
+ JOptionPane.showMessageDialog(mGainSlider, "Couldn't set RSP gain value to " + gain);
+ }
+ }
+
+ getGainValueLabel().setText(String.valueOf(gain));
+ });
+ }
+
+ return mGainSlider;
+ }
+
+ /**
+ * Label for displaying current gain index value
+ */
+ protected JLabel getGainValueLabel()
+ {
+ if(mGainValueLabel == null)
+ {
+ mGainValueLabel = new JLabel("0");
+ mGainValueLabel.setEnabled(false);
+ }
+
+ return mGainValueLabel;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/ControlRsp1.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/ControlRsp1.java
new file mode 100644
index 000000000..754d565b5
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/ControlRsp1.java
@@ -0,0 +1,42 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rsp1;
+
+import com.github.dsheirer.sdrplay.device.Rsp1Device;
+import io.github.dsheirer.source.tuner.sdrplay.ControlRsp;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Control wrapper for an RSP1 Device
+ */
+public class ControlRsp1 extends ControlRsp implements IControlRsp1
+{
+ private Logger mLog = LoggerFactory.getLogger(ControlRsp1.class);
+
+ /**
+ * Constructs an instance
+ * @param device for the device
+ */
+ public ControlRsp1(Rsp1Device device)
+ {
+ super(device);
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/DiscoveredRsp1Tuner.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/DiscoveredRsp1Tuner.java
new file mode 100644
index 000000000..4a6144ac8
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/DiscoveredRsp1Tuner.java
@@ -0,0 +1,40 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rsp1;
+
+import com.github.dsheirer.sdrplay.device.DeviceInfo;
+import io.github.dsheirer.preference.source.ChannelizerType;
+import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
+
+/**
+ * RSP1 discovered tuner.
+ */
+public class DiscoveredRsp1Tuner extends DiscoveredRspTuner
+{
+ /**
+ * Constructs an instance
+ * @param deviceInfo for controlling the RSP1A after it's been started
+ * @param channelizerType to use for the tuner once started
+ */
+ public DiscoveredRsp1Tuner(DeviceInfo deviceInfo, ChannelizerType channelizerType)
+ {
+ super(deviceInfo, channelizerType);
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/IControlRsp1.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/IControlRsp1.java
new file mode 100644
index 000000000..424097066
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/IControlRsp1.java
@@ -0,0 +1,30 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rsp1;
+
+import io.github.dsheirer.source.tuner.sdrplay.IControlRsp;
+
+/**
+ * Control interface for RSP1A device
+ */
+public interface IControlRsp1 extends IControlRsp
+{
+ //No additional features beyond the base control.
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/Rsp1TunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/Rsp1TunerConfiguration.java
new file mode 100644
index 000000000..08660965d
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/Rsp1TunerConfiguration.java
@@ -0,0 +1,51 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rsp1;
+
+import io.github.dsheirer.source.tuner.TunerType;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerConfiguration;
+
+/**
+ * RSP1 tuner configuration
+ */
+public class Rsp1TunerConfiguration extends RspTunerConfiguration
+{
+ /**
+ * Constructs an instance
+ * @param uniqueId for the tuner
+ */
+ public Rsp1TunerConfiguration(String uniqueId)
+ {
+ super(uniqueId);
+ }
+
+ /**
+ * JAXB constructor
+ */
+ public Rsp1TunerConfiguration()
+ {
+ }
+
+ @Override
+ public TunerType getTunerType()
+ {
+ return TunerType.RSP_1;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/Rsp1TunerController.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/Rsp1TunerController.java
new file mode 100644
index 000000000..68c174273
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/Rsp1TunerController.java
@@ -0,0 +1,66 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rsp1;
+
+import io.github.dsheirer.source.SourceException;
+import io.github.dsheirer.source.tuner.ITunerErrorListener;
+import io.github.dsheirer.source.tuner.TunerType;
+import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Tuner controller for RSP1
+ */
+public class Rsp1TunerController extends RspTunerController
+{
+ private Logger mLog = LoggerFactory.getLogger(Rsp1TunerController.class);
+
+ /**
+ * Constructs an instance
+ *
+ * @param control interface for the RSP1 tuner
+ * @param tunerErrorListener to monitor errors produced from this tuner controller
+ */
+ public Rsp1TunerController(IControlRsp1 control, ITunerErrorListener tunerErrorListener)
+ {
+ super(control, tunerErrorListener);
+ }
+
+ @Override
+ public TunerType getTunerType()
+ {
+ return TunerType.RSP_1;
+ }
+
+ @Override
+ public void apply(TunerConfiguration config) throws SourceException
+ {
+ if(config instanceof Rsp1TunerConfiguration)
+ {
+ super.apply(config);
+ }
+ else
+ {
+ mLog.error("Invalid RSP1 tuner configuration type: " + config.getClass());
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/Rsp1TunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/Rsp1TunerEditor.java
new file mode 100644
index 000000000..590b4039a
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/Rsp1TunerEditor.java
@@ -0,0 +1,172 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rsp1;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import io.github.dsheirer.preference.UserPreferences;
+import io.github.dsheirer.source.tuner.manager.TunerManager;
+import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
+import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerEditor;
+import net.miginfocom.swing.MigLayout;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JSeparator;
+import javax.swing.SpinnerNumberModel;
+
+/**
+ * RSP1 Tuner Editor
+ */
+public class Rsp1TunerEditor extends RspTunerEditor
+{
+ private static final Logger mLog = LoggerFactory.getLogger(Rsp1TunerEditor.class);
+
+ private JComboBox mSampleRateCombo;
+
+ /**
+ * Constructs an instance
+ * @param userPreferences for settings
+ * @param tunerManager for state updates
+ * @param discoveredTuner to edit or control.
+ */
+ public Rsp1TunerEditor(UserPreferences userPreferences, TunerManager tunerManager, DiscoveredRspTuner discoveredTuner)
+ {
+ super(userPreferences, tunerManager, discoveredTuner);
+ init();
+ tunerStatusUpdated();
+ }
+
+ private void init()
+ {
+ setLayout(new MigLayout("fill,wrap 3", "[right][grow,fill][fill]",
+ "[][][][][][][][][][][][grow]"));
+
+ add(new JLabel("Tuner:"));
+ add(getTunerIdLabel(), "wrap");
+
+ add(new JLabel("Status:"));
+ add(getTunerStatusLabel(), "wrap");
+
+ add(getButtonPanel(), "span,align left");
+
+ add(new JSeparator(), "span,growx,push");
+
+ add(new JLabel("Frequency (MHz):"));
+ add(getFrequencyPanel(), "wrap");
+
+ add(new JLabel("Sample Rate:"));
+ add(getSampleRateCombo(), "wrap");
+
+ add(new JLabel("Gain:"));
+ add(getGainSlider());
+ add(getGainValueLabel());
+
+ add(new JSeparator(), "span,growx,push");
+ }
+
+ /**
+ * Access tuner controller
+ */
+ private Rsp1TunerController getTunerController()
+ {
+ if(hasTuner())
+ {
+ return (Rsp1TunerController)getTuner().getTunerController();
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void tunerStatusUpdated()
+ {
+ setLoading(true);
+
+ getTunerIdLabel().setText(getDiscoveredTuner().getId());
+
+ String status = getDiscoveredTuner().getTunerStatus().toString();
+ if(getDiscoveredTuner().hasErrorMessage())
+ {
+ status += " - " + getDiscoveredTuner().getErrorMessage();
+ }
+ getTunerStatusLabel().setText(status);
+ getButtonPanel().updateControls();
+ getFrequencyPanel().updateControls();
+
+ getSampleRateCombo().setEnabled(hasTuner() && !getTuner().getTunerController().isLockedSampleRate());
+ getSampleRateCombo().setSelectedItem(hasTuner() ? getTunerController().getControlRsp().getSampleRateEnumeration() : null);
+
+ getGainSlider().setEnabled(hasTuner());
+ getGainValueLabel().setEnabled(hasTuner());
+ getGainSlider().setValue(hasTuner() ? getTunerController().getControlRsp().getGain() : 0);
+
+ setLoading(false);
+ }
+
+ @Override
+ public void save()
+ {
+ if(hasConfiguration() && !isLoading())
+ {
+ getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
+ getConfiguration().setFrequencyCorrection(value);
+ getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
+ getConfiguration().setSampleRate((RspSampleRate)getSampleRateCombo().getSelectedItem());
+ getConfiguration().setGain(getGainSlider().getValue());
+
+ saveConfiguration();
+ }
+ }
+
+ /**
+ * Sample rate selection combobox control
+ */
+ private JComboBox getSampleRateCombo()
+ {
+ if(mSampleRateCombo == null)
+ {
+ RspSampleRate[] rspSampleRates = RspSampleRate.SINGLE_TUNER_SAMPLE_RATES.toArray(new RspSampleRate[RspSampleRate.SINGLE_TUNER_SAMPLE_RATES.size()]);
+ mSampleRateCombo = new JComboBox<>(rspSampleRates);
+ mSampleRateCombo.setEnabled(false);
+ mSampleRateCombo.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ RspSampleRate selected = (RspSampleRate)mSampleRateCombo.getSelectedItem();
+
+ try
+ {
+ getTunerController().setSampleRate(selected);
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting sample rate for RSP1A tuner", se);
+ }
+ }
+ });
+ }
+
+ return mSampleRateCombo;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/ControlRsp1a.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/ControlRsp1a.java
new file mode 100644
index 000000000..af1dd02c3
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/ControlRsp1a.java
@@ -0,0 +1,121 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rsp1a;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.device.Rsp1aDevice;
+import io.github.dsheirer.source.tuner.sdrplay.ControlRsp;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Control wrapper for an RSP1A Device
+ */
+public class ControlRsp1a extends ControlRsp implements IControlRsp1a
+{
+ private Logger mLog = LoggerFactory.getLogger(ControlRsp1a.class);
+
+ /**
+ * Constructs an instance
+ * @param device for the device
+ */
+ public ControlRsp1a(Rsp1aDevice device)
+ {
+ super(device);
+ }
+
+ @Override
+ public boolean isBiasT() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getDevice().getTuner().isBiasT();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setBiasT(boolean enabled) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().getTuner().setBiasT(enabled);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public boolean isRfDabNotch() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getDevice().getTuner().isRfDabNotch();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setRfDabNotch(boolean enabled) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().getTuner().setRfDabNotch(enabled);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public boolean isRfNotch() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getDevice().getTuner().isRfNotch();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setRfNotch(boolean enabled) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().getTuner().setRfNotch(enabled);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/DiscoveredRsp1aTuner.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/DiscoveredRsp1aTuner.java
new file mode 100644
index 000000000..c2994f0ab
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/DiscoveredRsp1aTuner.java
@@ -0,0 +1,40 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rsp1a;
+
+import com.github.dsheirer.sdrplay.device.DeviceInfo;
+import io.github.dsheirer.preference.source.ChannelizerType;
+import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
+
+/**
+ * RSP1A discovered tuner.
+ */
+public class DiscoveredRsp1aTuner extends DiscoveredRspTuner
+{
+ /**
+ * Constructs an instance
+ * @param deviceInfo for controlling the RSP1A after it's been started
+ * @param channelizerType to use for the tuner once started
+ */
+ public DiscoveredRsp1aTuner(DeviceInfo deviceInfo, ChannelizerType channelizerType)
+ {
+ super(deviceInfo, channelizerType);
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/IControlRsp1a.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/IControlRsp1a.java
new file mode 100644
index 000000000..4da745f35
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/IControlRsp1a.java
@@ -0,0 +1,71 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rsp1a;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import io.github.dsheirer.source.tuner.sdrplay.IControlRsp;
+
+/**
+ * Control interface for RSP1A device
+ */
+public interface IControlRsp1a extends IControlRsp
+{
+ /**
+ * Indicates if the Bias-T power is enabled.
+ * @return true if enabled.
+ * @throws exception if the device is no started/selected
+ */
+ boolean isBiasT() throws SDRPlayException;
+
+ /**
+ * Sets the enabled state of the Bias-T power.
+ * @param enabled true to power on the Bias-T
+ * @throws exception if the device is no started/selected
+ */
+ void setBiasT(boolean enabled) throws SDRPlayException;
+
+ /**
+ * Indicates if the RF DAB notch is enabled (DAB broadcast band filter).
+ * @return true if enabled.
+ * @throws exception if the device is no started/selected
+ */
+ boolean isRfDabNotch() throws SDRPlayException;
+
+ /**
+ * Sets the enabled state of the RF DAB notch.
+ * @param enabled true to filter the DAB broadcast band frequency range.
+ * @throws exception if the device is no started/selected
+ */
+ void setRfDabNotch(boolean enabled) throws SDRPlayException;
+
+ /**
+ * Indicates if the RF notch is enabled (FM broadcast band filter).
+ * @return true if enabled.
+ * @throws exception if the device is no started/selected
+ */
+ boolean isRfNotch() throws SDRPlayException;
+
+ /**
+ * Sets the enabled state of the RF notch
+ * @param enabled true to filter the FM broadcast band frequency range.
+ * @throws exception if the device is no started/selected
+ */
+ void setRfNotch(boolean enabled) throws SDRPlayException;
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/Rsp1aTunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/Rsp1aTunerConfiguration.java
new file mode 100644
index 000000000..d2915b3a2
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/Rsp1aTunerConfiguration.java
@@ -0,0 +1,109 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rsp1a;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import io.github.dsheirer.source.tuner.TunerType;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerConfiguration;
+
+/**
+ * RSP1A tuner configuration
+ */
+public class Rsp1aTunerConfiguration extends RspTunerConfiguration
+{
+ private boolean mRfNotch;
+ private boolean mRfDabNotch;
+ private boolean mBiasT;
+
+ /**
+ * Constructs an instance
+ * @param uniqueId for the tuner
+ */
+ public Rsp1aTunerConfiguration(String uniqueId)
+ {
+ super(uniqueId);
+ }
+
+ /**
+ * JAXB constructor
+ */
+ public Rsp1aTunerConfiguration()
+ {
+ }
+
+ @Override
+ public TunerType getTunerType()
+ {
+ return TunerType.RSP_1A;
+ }
+
+ /**
+ * Indicates if the RF notch is enabled.
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "rf_notch")
+ public boolean isRfNotch()
+ {
+ return mRfNotch;
+ }
+
+ /**
+ * Sets the enabled state of the RF notch
+ * @param enabled
+ */
+ public void setRfNotch(boolean enabled)
+ {
+ mRfNotch = enabled;
+ }
+
+ /**
+ * Indicates if the RF Digital Audio Broadcast (DAB) notch is enabled.
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "dab_notch")
+ public boolean isRfDabNotch()
+ {
+ return mRfDabNotch;
+ }
+
+ /**
+ * Sets the enabled state of the RF DAB notch
+ * @param enabled
+ */
+ public void setRfDabNotch(boolean enabled)
+ {
+ mRfDabNotch = enabled;
+ }
+
+ /**
+ * Indicates if the Bias-T is enabled.
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "bias_t")
+ public boolean isBiasT()
+ {
+ return mBiasT;
+ }
+
+ /**
+ * Sets the enabled state of the Bias-T
+ */
+ public void setBiasT(boolean enabled)
+ {
+ mBiasT = enabled;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/Rsp1aTunerController.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/Rsp1aTunerController.java
new file mode 100644
index 000000000..0933dc940
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/Rsp1aTunerController.java
@@ -0,0 +1,94 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rsp1a;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import io.github.dsheirer.source.SourceException;
+import io.github.dsheirer.source.tuner.ITunerErrorListener;
+import io.github.dsheirer.source.tuner.TunerType;
+import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Tuner controller for RSP1a
+ */
+public class Rsp1aTunerController extends RspTunerController
+{
+ private Logger mLog = LoggerFactory.getLogger(Rsp1aTunerController.class);
+
+ /**
+ * Constructs an instance
+ *
+ * @param control interface for the RSP1A tuner
+ * @param tunerErrorListener to monitor errors produced from this tuner controller
+ */
+ public Rsp1aTunerController(IControlRsp1a control, ITunerErrorListener tunerErrorListener)
+ {
+ super(control, tunerErrorListener);
+ }
+
+ @Override
+ public TunerType getTunerType()
+ {
+ return TunerType.RSP_1A;
+ }
+
+ @Override
+ public void apply(TunerConfiguration config) throws SourceException
+ {
+ if(config instanceof Rsp1aTunerConfiguration rtc)
+ {
+ super.apply(config);
+
+ try
+ {
+ getControlRsp().setBiasT(rtc.isBiasT());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSP1A bias-T enabled to " + rtc.isBiasT());
+ }
+
+ try
+ {
+ getControlRsp().setRfNotch(rtc.isRfNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSP1A RF Notch enabled to " + rtc.isRfNotch());
+ }
+
+ try
+ {
+ getControlRsp().setRfDabNotch(rtc.isRfDabNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSP1A RF DAB Notch enabled to " + rtc.isRfDabNotch());
+ }
+ }
+ else
+ {
+ mLog.error("Invalid RSP1A tuner configuration type: " + config.getClass());
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/Rsp1aTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/Rsp1aTunerEditor.java
new file mode 100644
index 000000000..687bc3ec4
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/Rsp1aTunerEditor.java
@@ -0,0 +1,300 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rsp1a;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import io.github.dsheirer.preference.UserPreferences;
+import io.github.dsheirer.source.tuner.manager.TunerManager;
+import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
+import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerEditor;
+import net.miginfocom.swing.MigLayout;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JSeparator;
+import javax.swing.SpinnerNumberModel;
+
+/**
+ * RSP1A Tuner Editor
+ */
+public class Rsp1aTunerEditor extends RspTunerEditor
+{
+ private static final Logger mLog = LoggerFactory.getLogger(Rsp1aTunerEditor.class);
+
+ private JComboBox mSampleRateCombo;
+ private JCheckBox mBiasTCheckBox;
+ private JCheckBox mRfDabNotchCheckBox;
+ private JCheckBox mRfNotchCheckBox;
+
+ /**
+ * Constructs an instance
+ * @param userPreferences for settings
+ * @param tunerManager for state updates
+ * @param discoveredTuner to edit or control.
+ */
+ public Rsp1aTunerEditor(UserPreferences userPreferences, TunerManager tunerManager, DiscoveredRspTuner discoveredTuner)
+ {
+ super(userPreferences, tunerManager, discoveredTuner);
+ init();
+ tunerStatusUpdated();
+ }
+
+ private void init()
+ {
+ setLayout(new MigLayout("fill,wrap 3", "[right][grow,fill][fill]",
+ "[][][][][][][][][][][][grow]"));
+
+ add(new JLabel("Tuner:"));
+ add(getTunerIdLabel(), "wrap");
+
+ add(new JLabel("Status:"));
+ add(getTunerStatusLabel(), "wrap");
+
+ add(getButtonPanel(), "span,align left");
+
+ add(new JSeparator(), "span,growx,push");
+
+ add(new JLabel("Frequency (MHz):"));
+ add(getFrequencyPanel(), "wrap");
+
+ add(new JLabel("Sample Rate:"));
+ add(getSampleRateCombo(), "wrap");
+
+ add(new JLabel("Gain:"));
+ add(getGainSlider());
+ add(getGainValueLabel());
+
+ add(new JSeparator(), "span,growx,push");
+
+ add(new JLabel());
+ add(getBiasTCheckBox(), "wrap");
+ add(new JLabel());
+ add(getRfNotchCheckBox(), "wrap");
+ add(new JLabel());
+ add(getRfDabNotchCheckBox(), "wrap");
+ }
+
+ /**
+ * Access tuner controller
+ */
+ private Rsp1aTunerController getTunerController()
+ {
+ if(hasTuner())
+ {
+ return (Rsp1aTunerController)getTuner().getTunerController();
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void tunerStatusUpdated()
+ {
+ setLoading(true);
+
+ getTunerIdLabel().setText(getDiscoveredTuner().getId());
+
+ String status = getDiscoveredTuner().getTunerStatus().toString();
+ if(getDiscoveredTuner().hasErrorMessage())
+ {
+ status += " - " + getDiscoveredTuner().getErrorMessage();
+ }
+ getTunerStatusLabel().setText(status);
+ getButtonPanel().updateControls();
+ getFrequencyPanel().updateControls();
+
+ getSampleRateCombo().setEnabled(hasTuner() && !getTuner().getTunerController().isLockedSampleRate());
+ getSampleRateCombo().setSelectedItem(hasTuner() ? getTunerController().getControlRsp().getSampleRateEnumeration() : null);
+
+ getGainSlider().setEnabled(hasTuner());
+ getGainValueLabel().setEnabled(hasTuner());
+ getGainSlider().setValue(hasTuner() ? getTunerController().getControlRsp().getGain() : 0);
+
+ getBiasTCheckBox().setEnabled(hasTuner());
+ try
+ {
+ getBiasTCheckBox().setSelected(hasTuner() && getTunerController().getControlRsp().isBiasT());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting Bias-T enabled state in editor");
+ }
+
+ getRfDabNotchCheckBox().setEnabled(hasTuner());
+ try
+ {
+ getRfDabNotchCheckBox().setSelected(hasTuner() && getTunerController().getControlRsp().isRfDabNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RF DAB Notch enabled state in editor");
+ }
+
+ getRfNotchCheckBox().setEnabled(hasTuner());
+ try
+ {
+ getRfNotchCheckBox().setSelected(hasTuner() ? getTunerController().getControlRsp().isRfNotch() : false);
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RF Notch enabled state in editor");
+ }
+
+ setLoading(false);
+ }
+
+ @Override
+ public void save()
+ {
+ if(hasConfiguration() && !isLoading())
+ {
+ getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
+ getConfiguration().setFrequencyCorrection(value);
+ getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
+ getConfiguration().setSampleRate((RspSampleRate)getSampleRateCombo().getSelectedItem());
+ getConfiguration().setBiasT(getBiasTCheckBox().isSelected());
+ getConfiguration().setRfNotch(getRfNotchCheckBox().isSelected());
+ getConfiguration().setRfDabNotch(getRfDabNotchCheckBox().isSelected());
+ getConfiguration().setGain(getGainSlider().getValue());
+
+ saveConfiguration();
+ }
+ }
+
+ /**
+ * Sample rate selection combobox control
+ */
+ private JComboBox getSampleRateCombo()
+ {
+ if(mSampleRateCombo == null)
+ {
+ RspSampleRate[] rspSampleRates = RspSampleRate.SINGLE_TUNER_SAMPLE_RATES.toArray(new RspSampleRate[RspSampleRate.SINGLE_TUNER_SAMPLE_RATES.size()]);
+ mSampleRateCombo = new JComboBox<>(rspSampleRates);
+ mSampleRateCombo.setEnabled(false);
+ mSampleRateCombo.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ RspSampleRate selected = (RspSampleRate)mSampleRateCombo.getSelectedItem();
+
+ try
+ {
+ getTunerController().setSampleRate(selected);
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting sample rate for RSP1A tuner", se);
+ }
+ }
+ });
+ }
+
+ return mSampleRateCombo;
+ }
+
+ /**
+ * Checkbox control for Bias-T
+ */
+ private JCheckBox getBiasTCheckBox()
+ {
+ if(mBiasTCheckBox == null)
+ {
+ mBiasTCheckBox = new JCheckBox("Bias-T Power");
+ mBiasTCheckBox.setEnabled(false);
+ mBiasTCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setBiasT(mBiasTCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSP1A Bias-T enabled to " + mBiasTCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mBiasTCheckBox;
+ }
+
+ /**
+ * Checkbox control for RF DAB notch
+ */
+ private JCheckBox getRfDabNotchCheckBox()
+ {
+ if(mRfDabNotchCheckBox == null)
+ {
+ mRfDabNotchCheckBox = new JCheckBox("DAB Broadcast Band Filter (160-235 MHz)");
+ mRfDabNotchCheckBox.setEnabled(false);
+ mRfDabNotchCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setRfDabNotch(mRfDabNotchCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSP1A RF DAB notch enabled to " + mRfDabNotchCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mRfDabNotchCheckBox;
+ }
+
+ /**
+ * Checkbox control for RF notch
+ */
+ private JCheckBox getRfNotchCheckBox()
+ {
+ if(mRfNotchCheckBox == null)
+ {
+ mRfNotchCheckBox = new JCheckBox("FM Broadcast Band Filter (77-115 MHz)");
+ mRfNotchCheckBox.setEnabled(false);
+ mRfNotchCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setRfNotch(mRfNotchCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSP1A RF notch enabled to " + mRfNotchCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mRfNotchCheckBox;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/ControlRsp2.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/ControlRsp2.java
new file mode 100644
index 000000000..33b6dd7da
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/ControlRsp2.java
@@ -0,0 +1,144 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rsp2;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.device.Rsp2Device;
+import com.github.dsheirer.sdrplay.parameter.tuner.Rsp2AntennaSelection;
+import io.github.dsheirer.source.tuner.sdrplay.ControlRsp;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Control wrapper for an RSP2 Device
+ */
+public class ControlRsp2 extends ControlRsp implements IControlRsp2
+{
+ private Logger mLog = LoggerFactory.getLogger(ControlRsp2.class);
+ private Rsp2AntennaSelection mAntennaSelection = Rsp2AntennaSelection.ANT_A;
+
+ /**
+ * Constructs an instance
+ * @param sdrplayApi to control the device
+ * @param device to control
+ */
+ public ControlRsp2(Rsp2Device device)
+ {
+ super(device);
+ }
+
+ @Override
+ public boolean isBiasT() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getDevice().getTuner().isBiasT();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setBiasT(boolean enabled) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().getTuner().setBiasT(enabled);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public boolean isExternalReferenceOutput() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getDevice().getTuner().isExternalReferenceOutput();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setExternalReferenceOutput(boolean enabled) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().getTuner().setExternalReferenceOutput(enabled);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public boolean isRfNotch() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getDevice().getTuner().isRfNotch();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setRfNotch(boolean enabled) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().getTuner().setRfNotch(enabled);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public Rsp2AntennaSelection getAntennaSelection() throws SDRPlayException
+ {
+ return mAntennaSelection;
+ }
+
+ @Override
+ public void setAntennaSelection(Rsp2AntennaSelection selection) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().getTuner().setAmPort(selection.getAmPort());
+ getDevice().getTuner().setAntenna(selection.getAntenna());
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/DiscoveredRsp2Tuner.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/DiscoveredRsp2Tuner.java
new file mode 100644
index 000000000..9032a87d3
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/DiscoveredRsp2Tuner.java
@@ -0,0 +1,40 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rsp2;
+
+import com.github.dsheirer.sdrplay.device.DeviceInfo;
+import io.github.dsheirer.preference.source.ChannelizerType;
+import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
+
+/**
+ * RSP2 discovered tuner.
+ */
+public class DiscoveredRsp2Tuner extends DiscoveredRspTuner
+{
+ /**
+ * Constructs an instance
+ * @param deviceInfo for the tuner
+ * @param channelizerType to use for the tuner once started
+ */
+ public DiscoveredRsp2Tuner(DeviceInfo deviceInfo, ChannelizerType channelizerType)
+ {
+ super(deviceInfo, channelizerType);
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/IControlRsp2.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/IControlRsp2.java
new file mode 100644
index 000000000..9e8eed542
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/IControlRsp2.java
@@ -0,0 +1,86 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rsp2;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.parameter.tuner.Rsp2AntennaSelection;
+import io.github.dsheirer.source.tuner.sdrplay.IControlRsp;
+
+/**
+ * Control interface for RSP2 device
+ */
+public interface IControlRsp2 extends IControlRsp
+{
+ /**
+ * Indicates if the Bias-T power is enabled.
+ * @return true if enabled.
+ * @throws SDRPlayException if the device is no started/selected
+ */
+ boolean isBiasT() throws SDRPlayException;
+
+ /**
+ * Sets the enabled state of the Bias-T power.
+ * @param enabled true to power on the Bias-T
+ * @throws SDRPlayException if the device is not started (selected).
+ */
+ void setBiasT(boolean enabled) throws SDRPlayException;
+
+ /**
+ * Indicates the enabled state of the external reference output.
+ * @return true if enabled.
+ * @throws SDRPlayException if the device is not started (selected).
+ */
+ boolean isExternalReferenceOutput() throws SDRPlayException;
+
+ /**
+ * Sets the enabled state of the external reference output.
+ * @param enabled true to enable.
+ * @throws SDRPlayException if the device is not started (selected).
+ */
+ void setExternalReferenceOutput(boolean enabled) throws SDRPlayException;
+
+ /**
+ * Indicates if the RF notch is enabled (FM broadcast band filter).
+ * @return true if enabled.
+ * @throws SDRPlayException if the device is not started (selected).
+ */
+ boolean isRfNotch() throws SDRPlayException;
+
+ /**
+ * Sets the enabled state of the RF notch
+ * @param enabled true to filter the FM broadcast band frequency range.
+ * @throws SDRPlayException if the device is not started (selected).
+ */
+ void setRfNotch(boolean enabled) throws SDRPlayException;
+
+ /**
+ * Antenna currently being used.
+ * @return antenna being used.
+ * @throws SDRPlayException if the device is not started (selected).
+ */
+ Rsp2AntennaSelection getAntennaSelection() throws SDRPlayException;
+
+ /**
+ * Sets the antenna selection
+ * @param antenna to use
+ * @throws SDRPlayException if the device is not started (selected).
+ */
+ void setAntennaSelection(Rsp2AntennaSelection antenna) throws SDRPlayException;
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/Rsp2TunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/Rsp2TunerConfiguration.java
new file mode 100644
index 000000000..e136d897c
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/Rsp2TunerConfiguration.java
@@ -0,0 +1,126 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rsp2;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.github.dsheirer.sdrplay.parameter.tuner.Rsp2AntennaSelection;
+import io.github.dsheirer.source.tuner.TunerType;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerConfiguration;
+
+/**
+ * RSP2 tuner configuration
+ */
+public class Rsp2TunerConfiguration extends RspTunerConfiguration
+{
+ private boolean mBiasT;
+ private boolean mExternalReferenceOutput;
+ private boolean mRfNotch;
+ private Rsp2AntennaSelection mAntennaSelection = Rsp2AntennaSelection.ANT_A;
+
+ /**
+ * Constructs an instance
+ * @param uniqueId for the tuner
+ */
+ public Rsp2TunerConfiguration(String uniqueId)
+ {
+ super(uniqueId);
+ }
+
+ /**
+ * JAXB constructor
+ */
+ public Rsp2TunerConfiguration()
+ {
+ }
+
+ @Override
+ public TunerType getTunerType()
+ {
+ return TunerType.RSP_2;
+ }
+
+ /**
+ * Indicates if the external reference output is enabled.
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "external_reference_output")
+ public boolean isExternalReferenceOutput()
+ {
+ return mExternalReferenceOutput;
+ }
+
+ /**
+ * Sets the enabled state of the external reference output.
+ */
+ public void setExternalReferenceOutput(boolean enabled)
+ {
+ mExternalReferenceOutput = enabled;
+ }
+
+ /**
+ * Indicates if the Bias-T is enabled
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "bias_t")
+ public boolean isBiasT()
+ {
+ return mBiasT;
+ }
+
+ /**
+ * Sets the enabled state of the Bias-T
+ */
+ public void setBiasT(boolean enabled)
+ {
+ mBiasT = enabled;
+ }
+
+ /**
+ * Indicates if the RF Notch is enabled
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "rf_notch")
+ public boolean isRfNotch()
+ {
+ return mRfNotch;
+ }
+
+ /**
+ * Sets the enabled state of the RF Notch.
+ */
+ public void setRfNotch(boolean rfNotch)
+ {
+ mRfNotch = rfNotch;
+ }
+
+ /**
+ * Antenna selection
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "antenna")
+ public Rsp2AntennaSelection getAntennaSelection()
+ {
+ return mAntennaSelection;
+ }
+
+ /**
+ * Sets the antenna selection
+ */
+ public void setAntennaSelection(Rsp2AntennaSelection selection)
+ {
+ mAntennaSelection = selection;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/Rsp2TunerController.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/Rsp2TunerController.java
new file mode 100644
index 000000000..9ebbecea0
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/Rsp2TunerController.java
@@ -0,0 +1,103 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rsp2;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import io.github.dsheirer.source.SourceException;
+import io.github.dsheirer.source.tuner.ITunerErrorListener;
+import io.github.dsheirer.source.tuner.TunerType;
+import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Tuner controller for RSP2
+ */
+public class Rsp2TunerController extends RspTunerController
+{
+ private Logger mLog = LoggerFactory.getLogger(Rsp2TunerController.class);
+
+ /**
+ * Constructs an instance
+ *
+ * @param control interface for the RSP2 tuner
+ * @param tunerErrorListener to monitor errors produced from this tuner controller
+ */
+ public Rsp2TunerController(IControlRsp2 control, ITunerErrorListener tunerErrorListener)
+ {
+ super(control, tunerErrorListener);
+ }
+
+ @Override
+ public TunerType getTunerType()
+ {
+ return TunerType.RSP_2;
+ }
+
+ @Override
+ public void apply(TunerConfiguration config) throws SourceException
+ {
+ if(config instanceof Rsp2TunerConfiguration rtc)
+ {
+ super.apply(config);
+
+ try
+ {
+ getControlRsp().setBiasT(rtc.isBiasT());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSP2 bias-T enabled to " + rtc.isBiasT());
+ }
+
+ try
+ {
+ getControlRsp().setExternalReferenceOutput(rtc.isExternalReferenceOutput());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSP2 external reference output enabled to " + rtc.isExternalReferenceOutput());
+ }
+
+ try
+ {
+ getControlRsp().setRfNotch(rtc.isRfNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSP2 RF Notch enabled to " + rtc.isRfNotch());
+ }
+
+ try
+ {
+ getControlRsp().setAntennaSelection(rtc.getAntennaSelection());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSP2 antenna selection to " + rtc.getAntennaSelection());
+ }
+ }
+ else
+ {
+ mLog.error("Invalid RSP2 tuner configuration type: " + config.getClass());
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/Rsp2TunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/Rsp2TunerEditor.java
new file mode 100644
index 000000000..cc7e83742
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/Rsp2TunerEditor.java
@@ -0,0 +1,345 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rsp2;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.parameter.tuner.Rsp2AntennaSelection;
+import io.github.dsheirer.preference.UserPreferences;
+import io.github.dsheirer.source.tuner.manager.TunerManager;
+import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
+import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerEditor;
+import net.miginfocom.swing.MigLayout;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JSeparator;
+import javax.swing.SpinnerNumberModel;
+
+/**
+ * RSP2 Tuner Editor
+ */
+public class Rsp2TunerEditor extends RspTunerEditor
+{
+ private static final Logger mLog = LoggerFactory.getLogger(Rsp2TunerEditor.class);
+
+ private JComboBox mSampleRateCombo;
+ private JCheckBox mBiasTCheckBox;
+ private JCheckBox mExternalReferenceOutputCheckBox;
+ private JCheckBox mRfNotchCheckBox;
+ private JComboBox mAntennaSelectionCombo;
+
+ /**
+ * Constructs an instance
+ * @param userPreferences for settings
+ * @param tunerManager for state updates
+ * @param discoveredTuner to edit or control.
+ */
+ public Rsp2TunerEditor(UserPreferences userPreferences, TunerManager tunerManager, DiscoveredRspTuner discoveredTuner)
+ {
+ super(userPreferences, tunerManager, discoveredTuner);
+ init();
+ tunerStatusUpdated();
+ }
+
+ private void init()
+ {
+ setLayout(new MigLayout("fill,wrap 3", "[right][grow,fill][fill]",
+ "[][][][][][][][][][][][grow]"));
+
+ add(new JLabel("Tuner:"));
+ add(getTunerIdLabel(), "wrap");
+
+ add(new JLabel("Status:"));
+ add(getTunerStatusLabel(), "wrap");
+
+ add(getButtonPanel(), "span,align left");
+
+ add(new JSeparator(), "span,growx,push");
+
+ add(new JLabel("Frequency (MHz):"));
+ add(getFrequencyPanel(), "wrap");
+
+ add(new JLabel("Sample Rate:"));
+ add(getSampleRateCombo(), "wrap");
+
+ add(new JLabel("Gain:"));
+ add(getGainSlider());
+ add(getGainValueLabel());
+
+ add(new JSeparator(), "span,growx,push");
+
+ add(new JLabel());
+ add(getBiasTCheckBox(), "wrap");
+ add(new JLabel());
+ add(getExternalReferenceOutputCheckBox(), "wrap");
+ add(new JLabel());
+ add(getRfNotchCheckBox(), "wrap");
+ add(new JLabel());
+ add(getAntennaSelectionCombo(), "wrap");
+ }
+
+ /**
+ * Access tuner controller
+ */
+ private Rsp2TunerController getTunerController()
+ {
+ if(hasTuner())
+ {
+ return (Rsp2TunerController) getTuner().getTunerController();
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void tunerStatusUpdated()
+ {
+ setLoading(true);
+
+ getTunerIdLabel().setText(getDiscoveredTuner().getId());
+
+ String status = getDiscoveredTuner().getTunerStatus().toString();
+ if(getDiscoveredTuner().hasErrorMessage())
+ {
+ status += " - " + getDiscoveredTuner().getErrorMessage();
+ }
+ getTunerStatusLabel().setText(status);
+ getButtonPanel().updateControls();
+ getFrequencyPanel().updateControls();
+
+ getSampleRateCombo().setEnabled(hasTuner() && !getTuner().getTunerController().isLockedSampleRate());
+ getSampleRateCombo().setSelectedItem(hasTuner() ? getTunerController().getControlRsp().getSampleRateEnumeration() : null);
+
+ getGainSlider().setEnabled(hasTuner());
+ getGainValueLabel().setEnabled(hasTuner());
+ getGainSlider().setValue(hasTuner() ? getTunerController().getControlRsp().getGain() : 0);
+
+ getBiasTCheckBox().setEnabled(hasTuner());
+ try
+ {
+ getBiasTCheckBox().setSelected(hasTuner() && getTunerController().getControlRsp().isBiasT());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting Bias-T enabled state in editor");
+ }
+
+ getExternalReferenceOutputCheckBox().setEnabled(hasTuner());
+ try
+ {
+ getExternalReferenceOutputCheckBox().setSelected(hasTuner() && getTunerController().getControlRsp().isExternalReferenceOutput());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RF DAB Notch enabled state in editor");
+ }
+
+ getRfNotchCheckBox().setEnabled(hasTuner());
+ try
+ {
+ getRfNotchCheckBox().setSelected(hasTuner() && getTunerController().getControlRsp().isRfNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RF Notch enabled state in editor");
+ }
+
+ getAntennaSelectionCombo().setEnabled(hasTuner());
+ try
+ {
+ getAntennaSelectionCombo().setSelectedItem(hasTuner() ? getTunerController().getControlRsp().getAntennaSelection() : null);
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting antenna selection in editor");
+ }
+
+ setLoading(false);
+ }
+
+ @Override
+ public void save()
+ {
+ if(hasConfiguration() && !isLoading())
+ {
+ getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
+ getConfiguration().setFrequencyCorrection(value);
+ getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
+ getConfiguration().setSampleRate((RspSampleRate)getSampleRateCombo().getSelectedItem());
+ getConfiguration().setBiasT(getBiasTCheckBox().isSelected());
+ getConfiguration().setRfNotch(getRfNotchCheckBox().isSelected());
+ getConfiguration().setAntennaSelection((Rsp2AntennaSelection)getAntennaSelectionCombo().getSelectedItem());
+ getConfiguration().setGain(getGainSlider().getValue());
+
+ saveConfiguration();
+ }
+ }
+
+ /**
+ * Sample rate selection combobox control
+ */
+ private JComboBox getSampleRateCombo()
+ {
+ if(mSampleRateCombo == null)
+ {
+ RspSampleRate[] rspSampleRates = RspSampleRate.SINGLE_TUNER_SAMPLE_RATES.toArray(new RspSampleRate[RspSampleRate.SINGLE_TUNER_SAMPLE_RATES.size()]);
+ mSampleRateCombo = new JComboBox<>(rspSampleRates);
+ mSampleRateCombo.setEnabled(false);
+ mSampleRateCombo.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ RspSampleRate selected = (RspSampleRate)mSampleRateCombo.getSelectedItem();
+
+ try
+ {
+ getTunerController().setSampleRate(selected);
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting sample rate for RSP2 tuner", se);
+ }
+ }
+ });
+ }
+
+ return mSampleRateCombo;
+ }
+
+ /**
+ * Checkbox control for Bias-T
+ */
+ private JCheckBox getBiasTCheckBox()
+ {
+ if(mBiasTCheckBox == null)
+ {
+ mBiasTCheckBox = new JCheckBox("ANT B Bias-T Power");
+ mBiasTCheckBox.setEnabled(false);
+ mBiasTCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setBiasT(mBiasTCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSP2 Bias-T enabled to " + mBiasTCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mBiasTCheckBox;
+ }
+
+ /**
+ * Checkbox control for RF notch
+ */
+ private JCheckBox getRfNotchCheckBox()
+ {
+ if(mRfNotchCheckBox == null)
+ {
+ mRfNotchCheckBox = new JCheckBox("FM Broadcast Band Filter (77-115 MHz)");
+ mRfNotchCheckBox.setEnabled(false);
+ mRfNotchCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setRfNotch(mRfNotchCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSP2 RF notch enabled to " + mRfNotchCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mRfNotchCheckBox;
+ }
+
+ /**
+ * Checkbox control for External Reference Output
+ */
+ private JCheckBox getExternalReferenceOutputCheckBox()
+ {
+ if(mExternalReferenceOutputCheckBox == null)
+ {
+ mExternalReferenceOutputCheckBox = new JCheckBox("External Reference Output");
+ mExternalReferenceOutputCheckBox.setEnabled(false);
+ mExternalReferenceOutputCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setExternalReferenceOutput(mExternalReferenceOutputCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSP2 external reference output notch enabled to " +
+ mExternalReferenceOutputCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mExternalReferenceOutputCheckBox;
+ }
+
+ /**
+ * Antenna selection combobox control
+ */
+ private JComboBox getAntennaSelectionCombo()
+ {
+ if(mAntennaSelectionCombo == null)
+ {
+ mAntennaSelectionCombo = new JComboBox<>(Rsp2AntennaSelection.values());
+ mAntennaSelectionCombo.setEnabled(false);
+ mAntennaSelectionCombo.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ Rsp2AntennaSelection selected = (Rsp2AntennaSelection)mAntennaSelectionCombo.getSelectedItem();
+
+ try
+ {
+ getTunerController().getControlRsp().setAntennaSelection(selected);
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting Antenna selection for RSP2", se);
+ }
+ }
+ });
+ }
+
+ return mAntennaSelectionCombo;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuo.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuo.java
new file mode 100644
index 000000000..8f95293c8
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuo.java
@@ -0,0 +1,347 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rspDuo;
+
+import com.github.dsheirer.sdrplay.DeviceSelectionMode;
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.Status;
+import com.github.dsheirer.sdrplay.UpdateReason;
+import com.github.dsheirer.sdrplay.device.RspDuoDevice;
+import com.github.dsheirer.sdrplay.device.RspDuoTuner;
+import com.github.dsheirer.sdrplay.device.TunerSelect;
+import com.github.dsheirer.sdrplay.parameter.control.AgcMode;
+import com.github.dsheirer.sdrplay.parameter.control.ControlParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.IfMode;
+import com.github.dsheirer.sdrplay.parameter.tuner.LoMode;
+import com.github.dsheirer.sdrplay.parameter.tuner.TunerParameters;
+import io.github.dsheirer.source.tuner.sdrplay.ControlRsp;
+import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base control wrapper for an RSPduo operating in either single-tuner or master or slave mode.
+ */
+public abstract class ControlRspDuo extends ControlRsp implements IControlRspDuo
+{
+ private final Logger mLog = LoggerFactory.getLogger(ControlRspDuo.class);
+
+ /**
+ * Constructs an instance
+ *
+ * @param device for the device, obtained from the API
+ */
+ public ControlRspDuo(RspDuoDevice device)
+ {
+ super(device);
+ }
+
+ /**
+ * Access the tuner
+ * @return tuner
+ * @throws SDRPlayException if the device is not started/selected
+ */
+ protected abstract T getTuner() throws SDRPlayException;
+
+ /**
+ * Device selection mode - tuner 1 or tuner 2
+ * @return mode
+ */
+ public abstract DeviceSelectionMode getDeviceSelectionMode();
+
+ /**
+ * Control parameters for either tuner 1 or tuner 2
+ * @return control parameters
+ */
+ protected abstract ControlParameters getControlParameters();
+
+ /**
+ * Tuner parameters for either tuner 1 or tuner 2
+ */
+ protected abstract TunerParameters getTunerParameters();
+
+ @Override
+ public void start() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().setRspDuoMode(getDeviceSelectionMode().getRspDuoMode());
+ getDevice().setTunerSelect(getDeviceSelectionMode().getTunerSelect());
+
+ //In master mode, we have to set the sample rate here, before we select the device
+ if(getDeviceSelectionMode().isMasterMode())
+ {
+ getDevice().setRspDuoSampleFrequency(8_000_000);
+ }
+
+ getDevice().select();
+
+ //Enable automatic DC and I/Q correction
+ getControlParameters().getDcOffset().setDC(true);
+ getControlParameters().getDcOffset().setIQ(true);
+
+ //Setup LO and AGC Mode
+ getControlParameters().getAgc().setAgcMode(AgcMode.DISABLE);
+ getTunerParameters().setLoMode(LoMode.AUTO);
+
+ //Setup IF mode. In master/slave dual-tuner mode use IF_2048, otherwise use IF_ZERO
+ if(getDeviceSelectionMode().isSingleTunerMode())
+ {
+ getTunerParameters().setIfMode(IfMode.IF_ZERO);
+ }
+ else
+ {
+ getTunerParameters().setIfMode(IfMode.IF_2048);
+ }
+ }
+ else
+ {
+ throw new SDRPlayException("Unable to start - no device");
+ }
+ }
+
+ @Override
+ public void startStream()
+ {
+ mStreamingLock.lock();
+
+ try
+ {
+ if(hasDevice() && !mStreaming)
+ {
+ if(getDeviceSelectionMode().isSlaveMode())
+ {
+ getDevice().initStreamB(getDeviceEventListener(), getStreamListener());
+ }
+ else
+ {
+ getDevice().initStreamA(getDeviceEventListener(), getStreamListener());
+ }
+
+ mStreaming = true;
+ }
+ }
+ catch(SDRPlayException se)
+ {
+ if(se.getStatus() == Status.FAIL)
+ {
+ if(getDeviceEventListener() != null)
+ {
+ getDeviceEventListener().processDeviceRemoval(getTunerSelect());
+ }
+ }
+ else
+ {
+ mLog.error("Unable to initialize/start streaming for RSPduo", se);
+ }
+ }
+ finally
+ {
+ mStreamingLock.unlock();
+ }
+ }
+
+ @Override
+ public void stopStream()
+ {
+ mStreamingLock.lock();
+
+ try
+ {
+ if(hasDevice() && mStreaming)
+ {
+ getDevice().uninitialize();
+ mStreaming = false;
+ }
+ }
+ catch(Exception e)
+ {
+ mLog.error("Error while stopping RSPduo stream", e);
+ }
+ finally
+ {
+ mStreamingLock.unlock();
+ }
+ }
+
+ /**
+ * Sets the sample rate
+ * @param sampleRate enumeration value.
+ * @throws SDRPlayException if the device is not started/initialized
+ */
+ @Override
+ public void setSampleRate(RspSampleRate sampleRate) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ mSampleRate = sampleRate;
+
+ getDevice().getTuner().setBandwidth(sampleRate.getBandwidth());
+ getDevice().getCompositeParameters().getDeviceParameters().getSamplingFrequency()
+ .setSampleRate(sampleRate.getSampleRate());
+ //Only send an update if we're in single-tuner mode ... not sure why we don't have to for dual-tuner mode.
+ if(getDeviceSelectionMode() != DeviceSelectionMode.MASTER_TUNER_1)
+ {
+ getDevice().update(getTunerSelect(), UpdateReason.DEVICE_SAMPLE_RATE);
+ }
+
+ getControlParameters().getDecimation().setWideBandSignal(true);
+ getDevice().setDecimation(sampleRate.getDecimation());
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ /**
+ * Sets the gain index
+ * @param gain index value (0 - 28)
+ * @throws SDRPlayException for errors setting gain value.
+ */
+ @Override
+ public void setGain(int gain) throws SDRPlayException
+ {
+ validateGain(gain);
+
+ if(gain != mGain)
+ {
+ mGain = gain;
+ getTuner().setGain(mGain);
+ }
+ }
+
+ @Override
+ public void acknowledgePowerOverload(TunerSelect tunerSelect) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().acknowledgePowerOverload(tunerSelect);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public long getTunedFrequency() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getTuner().getFrequency();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setTunedFrequency(long frequency) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getTuner().setFrequency(frequency);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public boolean isRfDabNotch() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getTuner().isRfDabNotch();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setRfDabNotch(boolean enabled) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getTuner().setRfDabNotch(enabled);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public boolean isRfNotch() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getTuner().isRFNotch();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setRfNotch(boolean enabled) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getTuner().setRfNotch(enabled);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public boolean isExternalReferenceOutput() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getTuner().isExternalReferenceOutput();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setExternalReferenceOutput(boolean enabled) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getTuner().setExternalReferenceOutput(enabled);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner1.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner1.java
new file mode 100644
index 000000000..4e05307eb
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner1.java
@@ -0,0 +1,133 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rspDuo;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.device.RspDuoDevice;
+import com.github.dsheirer.sdrplay.device.RspDuoTuner1;
+import com.github.dsheirer.sdrplay.device.TunerSelect;
+import com.github.dsheirer.sdrplay.parameter.control.ControlParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.RspDuoAmPort;
+import com.github.dsheirer.sdrplay.parameter.tuner.TunerParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base control wrapper for an RSPduo Tuner 1
+ */
+public abstract class ControlRspDuoTuner1 extends ControlRspDuo implements IControlRspDuoTuner1
+{
+ private Logger mLog = LoggerFactory.getLogger(ControlRspDuoTuner1.class);
+
+ /**
+ * Constructs an instance
+ *
+ * @param device to control
+ */
+ public ControlRspDuoTuner1(RspDuoDevice device)
+ {
+ super(device);
+ }
+
+ /**
+ * Access tuner 1.
+ * @return tuner
+ * @throws SDRPlayException if the device is not started.
+ */
+ protected RspDuoTuner1 getTuner() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return (RspDuoTuner1) getDevice().getTuner();
+ }
+
+ throw new SDRPlayException("RSPduo device is not started");
+ }
+
+ @Override
+ public TunerSelect getTunerSelect()
+ {
+ return TunerSelect.TUNER_1;
+ }
+
+ @Override
+ protected ControlParameters getControlParameters()
+ {
+ return getDevice().getCompositeParameters().getControlAParameters();
+ }
+
+ @Override
+ protected TunerParameters getTunerParameters()
+ {
+ return getDevice().getCompositeParameters().getTunerAParameters();
+ }
+
+ @Override
+ public boolean isAmNotch() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getTuner().isAmNotch();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setAmNotch(boolean enabled) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getTuner().setAmNotch(enabled);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public RspDuoAmPort getAmPort() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getTuner().getAmPort();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setAmPort(RspDuoAmPort port) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getTuner().setAmPort(port);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner1Master.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner1Master.java
new file mode 100644
index 000000000..641921df0
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner1Master.java
@@ -0,0 +1,157 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rspDuo;
+
+import com.github.dsheirer.sdrplay.DeviceSelectionMode;
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.device.RspDuoDevice;
+import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
+import java.util.EnumSet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * RSPduo operating in dual-tuner mode with tuner 1 configured as master.
+ */
+public class ControlRspDuoTuner1Master extends ControlRspDuoTuner1
+{
+ private static final Logger mLog = LoggerFactory.getLogger(ControlRspDuoTuner1Master.class);
+
+ /**
+ * Bridge to tuner 2 slave device.
+ */
+ private MasterSlaveBridge mMasterSlaveBridge;
+
+ /**
+ * Flag to indicate that continuous streaming is required because the slave device is streaming.
+ */
+ private boolean mContinuousStream = false;
+
+ /**
+ * Constructs an instance
+ *
+ * @param device to control
+ */
+ public ControlRspDuoTuner1Master(RspDuoDevice device, MasterSlaveBridge bridge)
+ {
+ super(device);
+ mMasterSlaveBridge = bridge;
+ }
+
+ @Override
+ public DeviceSelectionMode getDeviceSelectionMode()
+ {
+ return DeviceSelectionMode.MASTER_TUNER_1;
+ }
+
+ @Override
+ public EnumSet getSupportedSampleRates()
+ {
+ return RspSampleRate.DUAL_TUNER_SAMPLE_RATES;
+ }
+
+ @Override
+ public void setSampleRate(RspSampleRate sampleRate) throws SDRPlayException
+ {
+ if(!sampleRate.isDualTunerSampleRate())
+ {
+ throw new SDRPlayException("Use dual-tuner sample rates only");
+ }
+
+ super.setSampleRate(sampleRate);
+
+ //Notify tuner 2 slave device to configure for this sample rate
+ if(mMasterSlaveBridge != null)
+ {
+ mMasterSlaveBridge.notifySampleRate(sampleRate);
+ }
+ }
+
+ /**
+ * Overrides parent stop method to disable continous streaming flag before stopping this device so that the
+ * stream can be stopped.
+ * @throws SDRPlayException if there is an error
+ */
+ @Override
+ public void stop() throws SDRPlayException
+ {
+ mStreamingLock.lock();
+
+ try
+ {
+ if(mMasterSlaveBridge != null)
+ {
+ mMasterSlaveBridge.stopSlave();
+ }
+ }
+ catch(Exception e)
+ {
+ mLog.error("Error stopping slave device while preparing to stop the master device.");
+ }
+
+ try
+ {
+ mContinuousStream = false;
+ super.stop();
+ }
+ finally
+ {
+ mStreamingLock.unlock();
+ }
+ }
+
+ @Override
+ public void stopStream()
+ {
+ mStreamingLock.lock();
+
+ try
+ {
+ if(!mContinuousStream)
+ {
+ super.stopStream();
+ }
+ }
+ finally
+ {
+ mStreamingLock.unlock();
+ }
+ }
+
+ /**
+ * Starts this tuner streaming continuously. Streaming will only stop once stop() is invoked. This method is
+ * invoked by a tuner 2 slave device to ensure that this master tuner 1 device is streaming continously while the
+ * slave is streaming.
+ */
+ public void startStreamContinuously()
+ {
+ mStreamingLock.lock();
+
+ try
+ {
+ mContinuousStream = true;
+ startStream();
+ }
+ finally
+ {
+ mStreamingLock.unlock();
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner1Single.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner1Single.java
new file mode 100644
index 000000000..022707dfc
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner1Single.java
@@ -0,0 +1,65 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rspDuo;
+
+import com.github.dsheirer.sdrplay.DeviceSelectionMode;
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.device.RspDuoDevice;
+import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
+import java.util.EnumSet;
+
+/**
+ * RSPduo with tuner 1 configured as single tuner.
+ */
+public class ControlRspDuoTuner1Single extends ControlRspDuoTuner1
+{
+ /**
+ * Constructs an instance
+ *
+ * @param device to control
+ */
+ public ControlRspDuoTuner1Single(RspDuoDevice device)
+ {
+ super(device);
+ }
+
+ @Override
+ public DeviceSelectionMode getDeviceSelectionMode()
+ {
+ return DeviceSelectionMode.SINGLE_TUNER_1;
+ }
+
+ @Override
+ public EnumSet getSupportedSampleRates()
+ {
+ return RspSampleRate.SINGLE_TUNER_SAMPLE_RATES;
+ }
+
+ @Override
+ public void setSampleRate(RspSampleRate sampleRate) throws SDRPlayException
+ {
+ if(sampleRate.isDualTunerSampleRate())
+ {
+ throw new SDRPlayException("Use single-tuner sample rates only");
+ }
+
+ super.setSampleRate(sampleRate);
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner2.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner2.java
new file mode 100644
index 000000000..d054436af
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner2.java
@@ -0,0 +1,106 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rspDuo;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.device.RspDuoDevice;
+import com.github.dsheirer.sdrplay.device.RspDuoTuner2;
+import com.github.dsheirer.sdrplay.device.TunerSelect;
+import com.github.dsheirer.sdrplay.parameter.control.ControlParameters;
+import com.github.dsheirer.sdrplay.parameter.tuner.TunerParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base control wrapper for an RSPduo Tuner 2
+ */
+public abstract class ControlRspDuoTuner2 extends ControlRspDuo implements IControlRspDuoTuner2
+{
+ private Logger mLog = LoggerFactory.getLogger(ControlRspDuoTuner2.class);
+
+ /**
+ * Constructs an instance
+ *
+ * @param device for the device, obtained from the API
+ */
+ public ControlRspDuoTuner2(RspDuoDevice device)
+ {
+ super(device);
+ }
+
+ /**
+ * Access tuner 2.
+ * @return tuner
+ * @throws SDRPlayException if the device is not started.
+ */
+ protected RspDuoTuner2 getTuner() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return (RspDuoTuner2) getDevice().getTuner();
+ }
+
+ throw new SDRPlayException("RSPduo device is not started");
+ }
+
+ @Override
+ public TunerSelect getTunerSelect()
+ {
+ return TunerSelect.TUNER_2;
+ }
+
+ @Override
+ protected ControlParameters getControlParameters()
+ {
+ return getDevice().getCompositeParameters().getControlBParameters();
+ }
+
+ @Override
+ protected TunerParameters getTunerParameters()
+ {
+ return getDevice().getCompositeParameters().getTunerBParameters();
+ }
+
+ @Override
+ public boolean isBiasT() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getTuner().isBiasT();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setBiasT(boolean enabled) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getTuner().setBiasT(enabled);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner2Single.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner2Single.java
new file mode 100644
index 000000000..64bf8ccfe
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner2Single.java
@@ -0,0 +1,75 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rspDuo;
+
+import com.github.dsheirer.sdrplay.DeviceSelectionMode;
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.device.RspDuoDevice;
+import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
+import java.util.EnumSet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Control wrapper for an RSPduo Tuner 2 operating in single-tuner mode.
+ */
+public class ControlRspDuoTuner2Single extends ControlRspDuoTuner2
+{
+ private Logger mLog = LoggerFactory.getLogger(ControlRspDuoTuner2Single.class);
+
+ /**
+ * Constructs an instance
+ *
+ * @param device to control
+ */
+ public ControlRspDuoTuner2Single(RspDuoDevice device)
+ {
+ super(device);
+ }
+
+ @Override
+ public DeviceSelectionMode getDeviceSelectionMode()
+ {
+ return DeviceSelectionMode.SINGLE_TUNER_2;
+ }
+
+ @Override
+ public boolean isSlaveMode()
+ {
+ return false;
+ }
+
+ @Override
+ public EnumSet getSupportedSampleRates()
+ {
+ return RspSampleRate.SINGLE_TUNER_SAMPLE_RATES;
+ }
+
+ @Override
+ public void setSampleRate(RspSampleRate sampleRate) throws SDRPlayException
+ {
+ if(sampleRate.isDualTunerSampleRate())
+ {
+ throw new SDRPlayException("Use single-tuner sample rates only");
+ }
+
+ super.setSampleRate(sampleRate);
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner2Slave.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner2Slave.java
new file mode 100644
index 000000000..f31cc2c6c
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/ControlRspDuoTuner2Slave.java
@@ -0,0 +1,102 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rspDuo;
+
+import com.github.dsheirer.sdrplay.DeviceSelectionMode;
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.device.RspDuoDevice;
+import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
+import java.util.EnumSet;
+
+/**
+ * Control wrapper for an RSPduo Tuner 2 operating in dual-tuner mode as the slave device
+ */
+public class ControlRspDuoTuner2Slave extends ControlRspDuoTuner2
+{
+ private MasterSlaveBridge mMasterSlaveBridge;
+
+ /**
+ * Constructs an instance
+ *
+ * @param device to control
+ */
+ public ControlRspDuoTuner2Slave(RspDuoDevice device, MasterSlaveBridge bridge)
+ {
+ super(device);
+ mMasterSlaveBridge = bridge;
+ }
+
+ /**
+ * Overrides the default method to request that master starts streaming so that this slave can also
+ * start streaming. Uses the bridge to put master in a continuous streaming mode where master is
+ * started and a flag is set to prevent master from stopping streaming.
+ */
+ @Override
+ public void startStream()
+ {
+ if(mMasterSlaveBridge != null)
+ {
+ mMasterSlaveBridge.startMasterStreamContinuously();
+ }
+
+ super.startStream();
+ }
+
+ @Override
+ public boolean isSlaveMode()
+ {
+ return true;
+ }
+
+ @Override
+ public DeviceSelectionMode getDeviceSelectionMode()
+ {
+ return DeviceSelectionMode.SLAVE_TUNER_2;
+ }
+
+ @Override
+ public EnumSet getSupportedSampleRates()
+ {
+ //In dual-tuner mode only the master device can set the sample rate
+ return EnumSet.noneOf(RspSampleRate.class);
+ }
+
+ @Override
+ public void setSampleRate(RspSampleRate sampleRate) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ mSampleRate = sampleRate;
+ getDevice().getTuner().setBandwidth(sampleRate.getBandwidth());
+ getControlParameters().getDecimation().setWideBandSignal(true);
+ getDevice().setDecimation(sampleRate.getDecimation());
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setExternalReferenceOutput(boolean enabled) throws SDRPlayException
+ {
+ //Ignore ... tuner 2 configured for slave mode does not control the external reference output
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/DiscoveredRspDuoTuner1.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/DiscoveredRspDuoTuner1.java
new file mode 100644
index 000000000..cb8f79ca1
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/DiscoveredRspDuoTuner1.java
@@ -0,0 +1,125 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rspDuo;
+
+import com.github.dsheirer.sdrplay.device.DeviceInfo;
+import io.github.dsheirer.preference.source.ChannelizerType;
+import io.github.dsheirer.source.tuner.TunerFactory;
+import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
+import io.github.dsheirer.source.tuner.sdrplay.RspTuner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * RSPduo Tuner 1 discovered tuner.
+ *
+ * When constructed with a master-slave bridge, this device will be used in master-slave mode. If the bridge is not
+ * provided as construction time, the device will be configured for single-tuner operation.
+ */
+public class DiscoveredRspDuoTuner1 extends DiscoveredRspTuner
+{
+ private static final Logger mLog = LoggerFactory.getLogger(DiscoveredRspTuner.class);
+ public static final String RSP_DUO_ID_PREFIX = "RSPduo Tuner ";
+ private MasterSlaveBridge mMasterSlaveBridge;
+
+ /**
+ * Constructs an instance configured for a single-tuner
+ * @param deviceInfo describing the tuner
+ * @param channelizerType to use for the tuner once started
+ */
+ public DiscoveredRspDuoTuner1(DeviceInfo deviceInfo, ChannelizerType channelizerType)
+ {
+ super(deviceInfo, channelizerType);
+ }
+
+ /**
+ * Constructs an instance configured as Master Tuner 1.
+ * @param deviceInfo describing the tuner
+ * @param channelizerType to use for the tuner once started
+ * @param bridge for synchronizing with the slaved tuner 2.
+ */
+ public DiscoveredRspDuoTuner1(DeviceInfo deviceInfo, ChannelizerType channelizerType, MasterSlaveBridge bridge)
+ {
+ super(deviceInfo, channelizerType);
+ mMasterSlaveBridge = bridge;
+ }
+
+ /**
+ * Constructs and starts the tuner
+ */
+ @Override
+ public void start()
+ {
+ if(isAvailable() && !hasTuner())
+ {
+ try
+ {
+ if(mMasterSlaveBridge != null)
+ {
+ mTuner = TunerFactory.getRspDuoTuner(getDeviceInfo(), getChannelizerType(), this, mMasterSlaveBridge);
+
+ if(mTuner instanceof RspTuner rspTuner &&
+ rspTuner.getRspTunerController() instanceof RspDuoTuner1Controller rspDuoTuner1Controller)
+ {
+ mMasterSlaveBridge.setMaster(rspDuoTuner1Controller);
+ }
+ }
+ else
+ {
+ mTuner = TunerFactory.getRspTuner(getDeviceInfo(), getChannelizerType(), this);
+ }
+ }
+ catch(Exception se)
+ {
+ setErrorMessage("Tuner unavailable [" + getId() + "]");
+ mTuner = null;
+ }
+
+ if(hasTuner())
+ {
+ try
+ {
+ mTuner.start();
+ }
+ catch(Exception se)
+ {
+ mLog.error("Error", se);
+ setErrorMessage("Error starting tuner [" + getId() + "]");
+ mTuner = null;
+ }
+ }
+ }
+ }
+
+ @Override
+ public String getId()
+ {
+ return RSP_DUO_ID_PREFIX + "1 SER#" + getDeviceInfo().getSerialNumber();
+ }
+
+ /**
+ * ID for the slave tuner device, if one is present in the system.
+ * @return slave tuner ID
+ */
+ public String getSlaveId()
+ {
+ return RSP_DUO_ID_PREFIX + "2 SER#" + getDeviceInfo().getSerialNumber();
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/DiscoveredRspDuoTuner2.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/DiscoveredRspDuoTuner2.java
new file mode 100644
index 000000000..054eec9b5
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/DiscoveredRspDuoTuner2.java
@@ -0,0 +1,121 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rspDuo;
+
+import com.github.dsheirer.sdrplay.device.DeviceInfo;
+import io.github.dsheirer.preference.source.ChannelizerType;
+import io.github.dsheirer.source.tuner.TunerFactory;
+import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
+
+/**
+ * RSPduo Tuner 2 discovered tuner.
+ *
+ * When constructed with a master-slave bridge, this device will be used in master-slave mode. If the bridge is not
+ * provided as construction time, the device will be configured for single-tuner operation.
+ */
+public class DiscoveredRspDuoTuner2 extends DiscoveredRspTuner
+{
+ private MasterSlaveBridge mMasterSlaveBridge;
+
+ /**
+ * Constructs an instance configured for a single-tuner
+ * @param deviceInfo describing the tuner
+ * @param channelizerType to use for the tuner once started
+ */
+ public DiscoveredRspDuoTuner2(DeviceInfo deviceInfo, ChannelizerType channelizerType)
+ {
+ super(deviceInfo, channelizerType);
+ }
+
+ /**
+ * Constructs an instance configured as Slave Tuner 2.
+ * @param deviceInfo describing the tuner
+ * @param channelizerType to use for the tuner once started
+ * @param bridge for synchronizing with the master tuner 1.
+ */
+ public DiscoveredRspDuoTuner2(DeviceInfo deviceInfo, ChannelizerType channelizerType, MasterSlaveBridge bridge)
+ {
+ super(deviceInfo, channelizerType);
+ mMasterSlaveBridge = bridge;
+ }
+
+ /**
+ * Constructs and starts the tuner
+ */
+ @Override
+ public void start()
+ {
+ if(isAvailable() && !hasTuner())
+ {
+ try
+ {
+ if(mMasterSlaveBridge != null)
+ {
+ mTuner = TunerFactory.getRspDuoTuner(getDeviceInfo(), getChannelizerType(), this, mMasterSlaveBridge);
+ }
+ else
+ {
+ mTuner = TunerFactory.getRspTuner(getDeviceInfo(), getChannelizerType(), this);
+ }
+ }
+ catch(Exception se)
+ {
+ setErrorMessage("Tuner unavailable [" + getId() + "]");
+ mTuner = null;
+ }
+
+ if(hasTuner())
+ {
+ try
+ {
+ mTuner.start();
+
+ if(mMasterSlaveBridge != null)
+ {
+ if(mTuner.getTunerController() instanceof RspDuoTuner2Controller rspDuoTuner2Controller)
+ {
+ mMasterSlaveBridge.setSlave(rspDuoTuner2Controller);
+ }
+ }
+ }
+ catch(Exception se)
+ {
+ setErrorMessage("Error starting tuner [" + getId() + "]");
+ mTuner = null;
+ }
+ }
+ }
+ }
+
+ @Override
+ public String getId()
+ {
+ return DiscoveredRspDuoTuner1.RSP_DUO_ID_PREFIX + "2 SER#" + getDeviceInfo().getSerialNumber();
+ }
+
+ /**
+ * ID for the slave tuner device, if one is present in the system.
+ * @return slave tuner ID
+ */
+ public String getMasterId()
+ {
+ return DiscoveredRspDuoTuner1.RSP_DUO_ID_PREFIX + "1 SER#" + getDeviceInfo().getSerialNumber();
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/IControlRspDuo.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/IControlRspDuo.java
new file mode 100644
index 000000000..2719548d0
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/IControlRspDuo.java
@@ -0,0 +1,80 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rspDuo;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import io.github.dsheirer.source.tuner.sdrplay.IControlRsp;
+import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
+
+import java.util.EnumSet;
+
+/**
+ * Control interface for RSPduo device (tuner 1 or 2)
+ */
+public interface IControlRspDuo extends IControlRsp
+{
+ /**
+ * Set of valid sample rates to use with the RSPduo in the current operating mode
+ * @return supported sample rates or an empty set if you cannot set the sample rate on this tuner.
+ */
+ EnumSet getSupportedSampleRates();
+
+ /**
+ * Indicates if the RF DAB notch is enabled (DAB broadcast band filter).
+ * @return true if enabled.
+ * @throws exception if the device is not started (selected).
+ */
+ boolean isRfDabNotch() throws SDRPlayException;
+
+ /**
+ * Sets the enabled state of the RF DAB notch.
+ * @param enabled true to filter the DAB broadcast band frequency range.
+ * @throws exception if the device is not started (selected).
+ */
+ void setRfDabNotch(boolean enabled) throws SDRPlayException;
+
+ /**
+ * Indicates if the RF notch is enabled (FM broadcast band filter).
+ * @return true if enabled.
+ * @throws exception if the device is not started (selected).
+ */
+ boolean isRfNotch() throws SDRPlayException;
+
+ /**
+ * Sets the enabled state of the RF notch
+ * @param enabled true to filter the FM broadcast band frequency range.
+ * @throws exception if the device is not started (selected).
+ */
+ void setRfNotch(boolean enabled) throws SDRPlayException;
+
+ /**
+ * Indicates the enabled state of the external reference output.
+ * @return true if enabled.
+ * @throws exception if the device is not started (selected).
+ */
+ boolean isExternalReferenceOutput() throws SDRPlayException;
+
+ /**
+ * Sets the enabled state of the external reference output.
+ * @param enabled true to enable.
+ * @throws exception if the device is not started (selected).
+ */
+ void setExternalReferenceOutput(boolean enabled) throws SDRPlayException;
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/IControlRspDuoTuner1.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/IControlRspDuoTuner1.java
new file mode 100644
index 000000000..cb38d0203
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/IControlRspDuoTuner1.java
@@ -0,0 +1,57 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rspDuo;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.parameter.tuner.RspDuoAmPort;
+
+/**
+ * Control interface for RSPduo Tuner 1 device
+ */
+public interface IControlRspDuoTuner1 extends IControlRspDuo
+{
+ /**
+ * Indicates if the AM notch is enabled (AM broadcast band filter)
+ * @return true if enabled.
+ * @throws exception if the device is not started (selected).
+ */
+ boolean isAmNotch() throws SDRPlayException;
+
+ /**
+ * Sets the enabled state of the AM notch filter.
+ * @param enabled true to enable
+ * @throws exception if the device is not started (selected).
+ */
+ void setAmNotch(boolean enabled) throws SDRPlayException;
+
+ /**
+ * Current port selection setting for the AM port.
+ * @return selected AM port
+ * @throws exception if the device is not started (selected).
+ */
+ RspDuoAmPort getAmPort() throws SDRPlayException;
+
+ /**
+ * Sets the AM port.
+ * @param amPort to use.
+ * @throws exception if the device is not started (selected).
+ */
+ void setAmPort(RspDuoAmPort amPort) throws SDRPlayException;
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/IControlRspDuoTuner2.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/IControlRspDuoTuner2.java
new file mode 100644
index 000000000..bfeccfec7
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/IControlRspDuoTuner2.java
@@ -0,0 +1,48 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rspDuo;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+
+/**
+ * Control interface for RSPduo Tuner 2 device
+ */
+public interface IControlRspDuoTuner2 extends IControlRspDuo
+{
+ /**
+ * Indicates if the Bias-T power is enabled.
+ * @return true if enabled.
+ * @throws SDRPlayException if the device is no started/selected
+ */
+ boolean isBiasT() throws SDRPlayException;
+
+ /**
+ * Sets the enabled state of the Bias-T power.
+ * @param enabled true to power on the Bias-T
+ * @throws SDRPlayException if the device is no started/selected
+ */
+ void setBiasT(boolean enabled) throws SDRPlayException;
+
+ /**
+ * Indicates if this tuner is configured for dual-tuner slave mode.
+ * @return true if slave mode.
+ */
+ boolean isSlaveMode();
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/MasterSlaveBridge.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/MasterSlaveBridge.java
new file mode 100644
index 000000000..b4b21817f
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/MasterSlaveBridge.java
@@ -0,0 +1,134 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rspDuo;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Bridge providing streaming control synchronization between master and slave devices. Additionally, this bridge
+ * allows the master device to notify the slave device of sample rate changes so that the slave can apply appropriate
+ * sample rate settings such as bandwidth and decimation. The RSPduo's two tuners do not operate independently.
+ * Streaming on the slave does not start until streaming on the master starts. The master cannot be shutdown until the
+ * slave is shutdown. This class provides the bridging to ensure that these sequencing requirements are met.
+ */
+public class MasterSlaveBridge
+{
+ private static final Logger mLog = LoggerFactory.getLogger(MasterSlaveBridge.class);
+ private RspDuoTuner1Controller mMaster;
+ private RspDuoTuner2Controller mSlave;
+
+ public MasterSlaveBridge()
+ {
+ }
+
+ /**
+ * Sets the master tuner controller
+ * @param master to set
+ */
+ public void setMaster(RspDuoTuner1Controller master)
+ {
+ mMaster = master;
+ }
+
+ /**
+ * Sets the slave tuner controller and transfers the sample rate setting from the master.
+ * @param slave to set
+ */
+ public void setSlave(RspDuoTuner2Controller slave)
+ {
+ mSlave = slave;
+
+ if(hasMasterControl())
+ {
+ //Transfer master sample rate setting to slave
+ notifySampleRate(getMasterControl().getSampleRateEnumeration());
+ }
+ }
+
+ /**
+ * Access to the tuner 1 master controller
+ */
+ private ControlRspDuoTuner1Master getMasterControl()
+ {
+ if(mMaster != null && mMaster.getControlRsp() instanceof ControlRspDuoTuner1Master masterControl)
+ {
+ return masterControl;
+ }
+
+ return null;
+ }
+
+ /**
+ * Indicates if we have access to a non-null master control
+ * @return true if non-null.
+ */
+ private boolean hasMasterControl()
+ {
+ return getMasterControl() != null;
+ }
+
+ /**
+ * A blocking call that ensures that the master device is streaming before returning. This method is intended to
+ * be called by the slave to ensure that the master is streaming before the slave initiates streaming. Once the
+ * slave invokes this method, the master will stream continuously until stop() is invoked on the master.
+ */
+ public void startMasterStreamContinuously()
+ {
+ if(hasMasterControl())
+ {
+ getMasterControl().startStreamContinuously();
+ }
+ }
+
+ /**
+ * A blocking call that ensures that the slave device stops streaming before returning. This method is intended
+ * to be invoked by the master device, just prior to stopping the master.
+ */
+ public void stopSlave()
+ {
+ if(mSlave != null)
+ {
+ mSlave.stop();
+ mSlave = null;
+ }
+ }
+
+ /**
+ * Notifies the slave of sample rate changes in the master.
+ * @param sampleRate being applied by the master device.
+ */
+ public void notifySampleRate(RspSampleRate sampleRate)
+ {
+ if(mSlave != null)
+ {
+ try
+ {
+ mSlave.setSampleRate(sampleRate);
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting sample rate on RSPduo tuner 2 slave", se);
+ }
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner1Configuration.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner1Configuration.java
new file mode 100644
index 000000000..46eb9ca8c
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner1Configuration.java
@@ -0,0 +1,144 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rspDuo;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.github.dsheirer.sdrplay.parameter.tuner.RspDuoAmPort;
+import io.github.dsheirer.source.tuner.TunerType;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerConfiguration;
+
+/**
+ * RSPduo tuner 1 configuration
+ */
+public class RspDuoTuner1Configuration extends RspTunerConfiguration
+{
+ private RspDuoAmPort mAmPort = RspDuoAmPort.PORT_2; //50-ohm port is default.
+ private boolean mAmNotch;
+ private boolean mExternalReferenceOutput;
+ private boolean mRfDabNotch;
+ private boolean mRfNotch;
+
+ /**
+ * Constructs an instance
+ * @param uniqueId for the tuner
+ */
+ public RspDuoTuner1Configuration(String uniqueId)
+ {
+ super(uniqueId);
+ }
+
+ /**
+ * JAXB constructor
+ */
+ public RspDuoTuner1Configuration()
+ {
+ }
+
+ @Override
+ public TunerType getTunerType()
+ {
+ return TunerType.RSP_DUO_1;
+ }
+
+ /**
+ * Indicates if the RF Notch is enabled
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "rf_notch")
+ public boolean isRfNotch()
+ {
+ return mRfNotch;
+ }
+
+ /**
+ * Sets the enabled state of the RF Notch
+ */
+ public void setRfNotch(boolean enabled)
+ {
+ mRfNotch = enabled;
+ }
+
+ /**
+ * Indicates if the RF Digital Audio Broadcast (DAB) notch is enabled
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "dab_notch")
+ public boolean isRfDabNotch()
+ {
+ return mRfDabNotch;
+ }
+
+ /**
+ * Sets the enabled state of the RF Notch.
+ */
+ public void setRfDabNotch(boolean enabled)
+ {
+ mRfDabNotch = enabled;
+ }
+
+ /**
+ * Indicates if the external reference output is enabled
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "external_reference_output")
+ public boolean isExternalReferenceOutput()
+ {
+ return mExternalReferenceOutput;
+ }
+
+ /**
+ * Sets the enabled state of the external reference output
+ */
+ public void setExternalReferenceOutput(boolean enabled)
+ {
+ mExternalReferenceOutput = enabled;
+ }
+
+ /**
+ * Indicates if the AM Notch is enabled
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "am_notch")
+ public boolean isAmNotch()
+ {
+ return mAmNotch;
+ }
+
+ /**
+ * Sets the enabled state of the AM notch
+ */
+ public void setAmNotch(boolean amNotch)
+ {
+ mAmNotch = amNotch;
+ }
+
+ /**
+ * AM port setting
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "am_port")
+ public RspDuoAmPort getAmPort()
+ {
+ return mAmPort;
+ }
+
+ /**
+ * Sets the AM port
+ */
+ public void setAmPort(RspDuoAmPort amPort)
+ {
+ mAmPort = amPort;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner1Controller.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner1Controller.java
new file mode 100644
index 000000000..c08a98af2
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner1Controller.java
@@ -0,0 +1,147 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rspDuo;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import io.github.dsheirer.source.SourceException;
+import io.github.dsheirer.source.tuner.ITunerErrorListener;
+import io.github.dsheirer.source.tuner.TunerType;
+import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
+import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerConfiguration;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Tuner controller for RSPduo tuner 1
+ */
+public class RspDuoTuner1Controller extends RspTunerController
+{
+ private Logger mLog = LoggerFactory.getLogger(RspDuoTuner1Controller.class);
+
+ /**
+ * Constructs an instance
+ *
+ * @param device that is the RSP tuner
+ * @param tunerErrorListener to monitor errors produced from this tuner controller
+ */
+ public RspDuoTuner1Controller(IControlRspDuoTuner1 device, ITunerErrorListener tunerErrorListener)
+ {
+ super(device, tunerErrorListener);
+ }
+
+ @Override
+ public TunerType getTunerType()
+ {
+ return TunerType.RSP_DUO_1;
+ }
+
+ @Override
+ public void apply(TunerConfiguration config) throws SourceException
+ {
+ if(config instanceof RspDuoTuner1Configuration duo1)
+ {
+ super.apply(config);
+
+ try
+ {
+ getControlRsp().setRfNotch(duo1.isRfNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 1 RF notch enabled to " + duo1.isRfNotch());
+ }
+
+ try
+ {
+ getControlRsp().setRfDabNotch(duo1.isRfDabNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 1 RF DAB notch enabled to " + duo1.isRfDabNotch());
+ }
+
+ try
+ {
+ getControlRsp().setAmNotch(duo1.isAmNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 1 AM notch enabled to " + duo1.isAmNotch());
+ }
+
+ try
+ {
+ getControlRsp().setAmPort(duo1.getAmPort());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 1 AM port to " + duo1.getAmPort());
+ }
+
+ try
+ {
+ getControlRsp().setExternalReferenceOutput(duo1.isExternalReferenceOutput());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 1 external reference output enabled to " + duo1.isExternalReferenceOutput());
+ }
+ }
+ else
+ {
+ mLog.error("Invalid RSPduo tuner configuration type: " + config.getClass());
+ }
+ }
+
+ /**
+ * Overrides the default RSP controller to ensure the sample rate is compatible with the
+ * configuration of the RSP duo.
+ * @param rspSampleRate to apply
+ * @throws SDRPlayException
+ */
+ @Override
+ public void setSampleRate(RspSampleRate rspSampleRate) throws SDRPlayException
+ {
+ if(getControlRsp().getDeviceSelectionMode().isSingleTunerMode())
+ {
+ if(rspSampleRate.isDualTunerSampleRate())
+ {
+ super.setSampleRate(RspTunerConfiguration.DEFAULT_SINGLE_TUNER_SAMPLE_RATE);
+ }
+ else
+ {
+ super.setSampleRate(rspSampleRate);
+ }
+ }
+ else
+ {
+ if(rspSampleRate.isDualTunerSampleRate())
+ {
+ super.setSampleRate(rspSampleRate);
+ }
+ else
+ {
+ super.setSampleRate(RspTunerConfiguration.DEFAULT_DUAL_TUNER_SAMPLE_RATE);
+ }
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner1Editor.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner1Editor.java
new file mode 100644
index 000000000..7e4d2cf6d
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner1Editor.java
@@ -0,0 +1,441 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rspDuo;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.parameter.tuner.RspDuoAmPort;
+import io.github.dsheirer.eventbus.MyEventBus;
+import io.github.dsheirer.gui.preference.PreferenceEditorType;
+import io.github.dsheirer.gui.preference.ViewUserPreferenceEditorRequest;
+import io.github.dsheirer.preference.UserPreferences;
+import io.github.dsheirer.source.tuner.manager.TunerManager;
+import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
+import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerEditor;
+import net.miginfocom.swing.MigLayout;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSeparator;
+import javax.swing.SpinnerNumberModel;
+import java.util.EnumSet;
+
+/**
+ * RSPduo Tuner 1 Editor
+ */
+public class RspDuoTuner1Editor extends RspTunerEditor
+{
+ private static final Logger mLog = LoggerFactory.getLogger(RspDuoTuner1Editor.class);
+
+ private JComboBox mSampleRateCombo;
+ private JCheckBox mRfDabNotchCheckBox;
+ private JCheckBox mRfNotchCheckBox;
+ private JCheckBox mAmNotchCheckBox;
+ private JCheckBox mExternalReferenceOutputCheckBox;
+ private JComboBox mAmPortCombo;
+ private JButton mTunerPreferencesButton;
+
+ /**
+ * Constructs an instance
+ * @param userPreferences for settings
+ * @param tunerManager for state updates
+ * @param discoveredTuner to edit or control.
+ */
+ public RspDuoTuner1Editor(UserPreferences userPreferences, TunerManager tunerManager, DiscoveredRspTuner discoveredTuner)
+ {
+ super(userPreferences, tunerManager, discoveredTuner);
+ init();
+ tunerStatusUpdated();
+ }
+
+ private void init()
+ {
+ setLayout(new MigLayout("fill,wrap 3", "[right][grow,fill][fill]",
+ "[][][][][][][][][][][][][][][grow]"));
+
+ add(new JLabel("Tuner:"));
+ JPanel labelAndButtonPanel = new JPanel();
+ labelAndButtonPanel.setLayout(new MigLayout("insets 0"));
+ labelAndButtonPanel.add(getTunerIdLabel());
+ labelAndButtonPanel.add(getTunerPreferencesButton());
+ add(labelAndButtonPanel, "wrap");
+ add(new JLabel("Status:"));
+ add(getTunerStatusLabel(), "wrap");
+ add(getButtonPanel(), "span,align left");
+
+ add(new JSeparator(), "span,growx,push");
+
+ add(new JLabel("Frequency (MHz):"));
+ add(getFrequencyPanel(), "wrap");
+
+ add(new JLabel("Sample Rate:"));
+ add(getSampleRateCombo(), "wrap");
+
+ add(new JLabel("Gain:"));
+ add(getGainSlider());
+ add(getGainValueLabel());
+
+ add(new JSeparator(), "span,growx,push");
+
+ add(new JLabel());
+ add(getExternalReferenceOutputCheckBox(), "wrap");
+ add(new JLabel());
+ add(getAmNotchCheckBox(), "wrap");
+ add(new JLabel());
+ add(getRfDabNotchCheckBox(), "wrap");
+ add(new JLabel());
+ add(getRfNotchCheckBox(), "wrap");
+ add(new JLabel("AM Port:"));
+ add(getAmPortCombo(), "wrap");
+ }
+
+ /**
+ * Access tuner controller
+ */
+ private RspDuoTuner1Controller getTunerController()
+ {
+ if(hasTuner())
+ {
+ return (RspDuoTuner1Controller) getTuner().getTunerController();
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void tunerStatusUpdated()
+ {
+ setLoading(true);
+
+ getTunerIdLabel().setText(getDiscoveredTuner().getId());
+
+ String status = getDiscoveredTuner().getTunerStatus().toString();
+ if(getDiscoveredTuner().hasErrorMessage())
+ {
+ status += " - " + getDiscoveredTuner().getErrorMessage();
+ }
+ getTunerStatusLabel().setText(status);
+ getButtonPanel().updateControls();
+ getFrequencyPanel().updateControls();
+
+ clearSampleRates();
+ if(hasTuner())
+ {
+ setSampleRates(getTunerController().getControlRsp().getSupportedSampleRates());
+ }
+ getSampleRateCombo().setEnabled(hasTuner() && !getTuner().getTunerController().isLockedSampleRate());
+ getSampleRateCombo().setSelectedItem(hasTuner() ? getTunerController().getControlRsp().getSampleRateEnumeration() : null);
+
+ getGainSlider().setEnabled(hasTuner());
+ getGainValueLabel().setEnabled(hasTuner());
+ getGainSlider().setValue(hasTuner() ? getTunerController().getControlRsp().getGain() : 0);
+
+ getAmPortCombo().setEnabled(hasTuner() && !getTuner().getTunerController().isLockedSampleRate());
+ try
+ {
+ getAmPortCombo().setSelectedItem(hasTuner() ? getTunerController().getControlRsp().getAmPort() : null);
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 1 AM Port in editor");
+ }
+
+ getRfDabNotchCheckBox().setEnabled(hasTuner());
+ try
+ {
+ getRfDabNotchCheckBox().setSelected(hasTuner() && getTunerController().getControlRsp().isRfDabNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 1 RF DAB Notch enabled state in editor");
+ }
+
+ getRfNotchCheckBox().setEnabled(hasTuner());
+ try
+ {
+ getRfNotchCheckBox().setSelected(hasTuner() && getTunerController().getControlRsp().isRfNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 1 RF Notch enabled state in editor");
+ }
+
+ getAmNotchCheckBox().setEnabled(hasTuner());
+ try
+ {
+ getAmNotchCheckBox().setSelected(hasTuner() && getTunerController().getControlRsp().isAmNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 1 AM Notch enabled state in editor");
+ }
+
+ getExternalReferenceOutputCheckBox().setEnabled(hasTuner());
+ try
+ {
+ getExternalReferenceOutputCheckBox()
+ .setSelected(hasTuner() && getTunerController().getControlRsp().isExternalReferenceOutput());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 1 external reference output enabled state in editor");
+ }
+
+ setLoading(false);
+ }
+
+ @Override
+ public void save()
+ {
+ if(hasConfiguration() && !isLoading())
+ {
+ getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
+ getConfiguration().setFrequencyCorrection(value);
+ getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
+ getConfiguration().setSampleRate((RspSampleRate)getSampleRateCombo().getSelectedItem());
+ getConfiguration().setAmNotch(getAmNotchCheckBox().isSelected());
+ getConfiguration().setAmPort(getAmPortCombo().getSelectedItem() != null ? (RspDuoAmPort)getAmPortCombo().getSelectedItem() : null);
+ getConfiguration().setExternalReferenceOutput(getExternalReferenceOutputCheckBox().isSelected());
+ getConfiguration().setRfDabNotch(getRfDabNotchCheckBox().isSelected());
+ getConfiguration().setRfNotch(getRfNotchCheckBox().isSelected());
+ getConfiguration().setGain(getGainSlider().getValue());
+
+ saveConfiguration();
+ }
+ }
+
+ /**
+ * Updates the sample rates listed in the combobox.
+ * @param sampleRates to use.
+ */
+ private void setSampleRates(EnumSet sampleRates)
+ {
+ if(!sampleRates.isEmpty())
+ {
+ for(RspSampleRate sampleRate: sampleRates)
+ {
+ getSampleRateCombo().addItem(sampleRate);
+ }
+ }
+ }
+
+ /**
+ * Removes all sample rate options from the combo box.
+ */
+ private void clearSampleRates()
+ {
+ getSampleRateCombo().removeAllItems();
+ }
+
+ /**
+ * Sample rate selection combobox control
+ */
+ private JComboBox getSampleRateCombo()
+ {
+ if(mSampleRateCombo == null)
+ {
+ mSampleRateCombo = new JComboBox<>();
+ mSampleRateCombo.setEnabled(false);
+ mSampleRateCombo.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ RspSampleRate selected = (RspSampleRate)mSampleRateCombo.getSelectedItem();
+
+ try
+ {
+ getTunerController().setSampleRate(selected);
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting sample rate for RSPduo tuner 1", se);
+ }
+ }
+ });
+ }
+
+ return mSampleRateCombo;
+ }
+
+ /**
+ * AM port selection combobox control
+ */
+ private JComboBox getAmPortCombo()
+ {
+ if(mAmPortCombo == null)
+ {
+ mAmPortCombo = new JComboBox<>(RspDuoAmPort.values());
+ mAmPortCombo.setEnabled(false);
+ mAmPortCombo.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ RspDuoAmPort selected = (RspDuoAmPort)mAmPortCombo.getSelectedItem();
+
+ try
+ {
+ getTunerController().getControlRsp().setAmPort(selected);
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting AM port for RSPduo tuner 1", se);
+ }
+ }
+ });
+ }
+
+ return mAmPortCombo;
+ }
+
+ /**
+ * Checkbox control for RF DAB notch
+ */
+ private JCheckBox getRfDabNotchCheckBox()
+ {
+ if(mRfDabNotchCheckBox == null)
+ {
+ mRfDabNotchCheckBox = new JCheckBox("DAB Broadcast Band Filter (157-235 MHz)");
+ mRfDabNotchCheckBox.setEnabled(false);
+ mRfDabNotchCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setRfDabNotch(mRfDabNotchCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSPduo tuner 1 RF DAB notch enabled to " + mRfDabNotchCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mRfDabNotchCheckBox;
+ }
+
+ /**
+ * Checkbox control for RF notch
+ */
+ private JCheckBox getRfNotchCheckBox()
+ {
+ if(mRfNotchCheckBox == null)
+ {
+ mRfNotchCheckBox = new JCheckBox("FM Broadcast Band Filter (78-114 MHz)");
+ mRfNotchCheckBox.setEnabled(false);
+ mRfNotchCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setRfNotch(mRfNotchCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSPduo tuner 1 RF notch enabled to " + mRfNotchCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mRfNotchCheckBox;
+ }
+
+ /**
+ * Checkbox control for AM notch
+ */
+ private JCheckBox getAmNotchCheckBox()
+ {
+ if(mAmNotchCheckBox == null)
+ {
+ mAmNotchCheckBox = new JCheckBox("AM Broadcast Band Filter (415-1640 kHz)");
+ mAmNotchCheckBox.setEnabled(false);
+ mAmNotchCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setAmNotch(mAmNotchCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSPduo tuner 1 AM notch enabled to " + mAmNotchCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mAmNotchCheckBox;
+ }
+
+ /**
+ * Checkbox control for External Reference Output
+ */
+ private JCheckBox getExternalReferenceOutputCheckBox()
+ {
+ if(mExternalReferenceOutputCheckBox == null)
+ {
+ mExternalReferenceOutputCheckBox = new JCheckBox("External Reference Output");
+ mExternalReferenceOutputCheckBox.setEnabled(false);
+ mExternalReferenceOutputCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setExternalReferenceOutput(mExternalReferenceOutputCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSPduo tuner 1 external reference output notch enabled to " +
+ mExternalReferenceOutputCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mExternalReferenceOutputCheckBox;
+ }
+
+ /**
+ * Button to launch the User Preferences editor to show the RSPduo tuner preference selection.
+ * @return constructed button.
+ */
+ private JButton getTunerPreferencesButton()
+ {
+ if(mTunerPreferencesButton == null)
+ {
+ mTunerPreferencesButton = new JButton("RSPduo Preferences");
+ mTunerPreferencesButton.addActionListener(e -> MyEventBus.getGlobalEventBus()
+ .post(new ViewUserPreferenceEditorRequest(PreferenceEditorType.SOURCE_TUNERS)));
+ }
+
+ return mTunerPreferencesButton;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner2Configuration.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner2Configuration.java
new file mode 100644
index 000000000..7417ed61f
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner2Configuration.java
@@ -0,0 +1,126 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rspDuo;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import io.github.dsheirer.source.tuner.TunerType;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerConfiguration;
+
+/**
+ * RSPduo tuner 1 configuration
+ */
+public class RspDuoTuner2Configuration extends RspTunerConfiguration
+{
+ private boolean mBiasT;
+ private boolean mExternalReferenceOutput;
+ private boolean mRfDabNotch;
+ private boolean mRfNotch;
+
+ /**
+ * Constructs an instance
+ * @param uniqueId for the tuner
+ */
+ public RspDuoTuner2Configuration(String uniqueId)
+ {
+ super(uniqueId);
+ }
+
+ /**
+ * JAXB constructor
+ */
+ public RspDuoTuner2Configuration()
+ {
+ }
+
+
+ @Override
+ public TunerType getTunerType()
+ {
+ return TunerType.RSP_DUO_2;
+ }
+
+ /**
+ * Indicates if the RF Notch is enabled
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "rf_notch")
+ public boolean isRfNotch()
+ {
+ return mRfNotch;
+ }
+
+ /**
+ * Sets the enabled state of the RF Notch
+ */
+ public void setRfNotch(boolean enabled)
+ {
+ mRfNotch = enabled;
+ }
+
+ /**
+ * Indicates if the RF Digital Audio Broadcast (DAB) notch is enabled
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "dab_notch")
+ public boolean isRfDabNotch()
+ {
+ return mRfDabNotch;
+ }
+
+ /**
+ * Sets the enabled state of the RF Notch.
+ */
+ public void setRfDabNotch(boolean enabled)
+ {
+ mRfDabNotch = enabled;
+ }
+
+ /**
+ * Indicates if the external reference output is enabled
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "external_reference_output")
+ public boolean isExternalReferenceOutput()
+ {
+ return mExternalReferenceOutput;
+ }
+
+ /**
+ * Sets the enabled state of the external reference output
+ */
+ public void setExternalReferenceOutput(boolean enabled)
+ {
+ mExternalReferenceOutput = enabled;
+ }
+
+ /**
+ * Indicates if the Bias-T is enabled
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "bias_t")
+ public boolean isBiasT()
+ {
+ return mBiasT;
+ }
+
+ /**
+ * Sets the enabled state of the Bias-T
+ */
+ public void setBiasT(boolean enabled)
+ {
+ mBiasT = enabled;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner2Controller.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner2Controller.java
new file mode 100644
index 000000000..ef98d07d8
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner2Controller.java
@@ -0,0 +1,138 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rspDuo;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import io.github.dsheirer.source.SourceException;
+import io.github.dsheirer.source.tuner.ITunerErrorListener;
+import io.github.dsheirer.source.tuner.TunerType;
+import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
+import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerConfiguration;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Tuner controller for RSPduo tuner 2
+ */
+public class RspDuoTuner2Controller extends RspTunerController
+{
+ private Logger mLog = LoggerFactory.getLogger(RspDuoTuner2Controller.class);
+
+ /**
+ * Constructs an instance
+ *
+ * @param device that is the RSP tuner
+ * @param tunerErrorListener to monitor errors produced from this tuner controller
+ */
+ public RspDuoTuner2Controller(IControlRspDuoTuner2 device, ITunerErrorListener tunerErrorListener)
+ {
+ super(device, tunerErrorListener);
+ }
+
+ @Override
+ public TunerType getTunerType()
+ {
+ return TunerType.RSP_DUO_2;
+ }
+
+ @Override
+ public void apply(TunerConfiguration config) throws SourceException
+ {
+ if(config instanceof RspDuoTuner2Configuration duo2)
+ {
+ super.apply(config);
+
+ try
+ {
+ getControlRsp().setRfNotch(duo2.isRfNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 2 RF notch enabled to " + duo2.isRfNotch());
+ }
+
+ try
+ {
+ getControlRsp().setRfDabNotch(duo2.isRfDabNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 2 RF DAB notch enabled to " + duo2.isRfDabNotch());
+ }
+
+ try
+ {
+ getControlRsp().setBiasT(duo2.isBiasT());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 2 Bias-T enabled to " + duo2.isBiasT());
+ }
+
+ try
+ {
+ getControlRsp().setExternalReferenceOutput(duo2.isExternalReferenceOutput());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 2 external reference output enabled to " + duo2.isExternalReferenceOutput());
+ }
+ }
+ else
+ {
+ mLog.error("Invalid RSPduo tuner configuration type: " + config.getClass());
+ }
+ }
+
+ /**
+ * Overrides the default RSP controller to ensure the sample rate is compatible with the
+ * configuration of the RSP duo.
+ * @param rspSampleRate to apply
+ * @throws SDRPlayException
+ */
+ @Override
+ public void setSampleRate(RspSampleRate rspSampleRate) throws SDRPlayException
+ {
+ if(getControlRsp().getDeviceSelectionMode().isSingleTunerMode())
+ {
+ if(rspSampleRate.isDualTunerSampleRate())
+ {
+ super.setSampleRate(RspTunerConfiguration.DEFAULT_SINGLE_TUNER_SAMPLE_RATE);
+ }
+ else
+ {
+ super.setSampleRate(rspSampleRate);
+ }
+ }
+ else
+ {
+ if(rspSampleRate.isDualTunerSampleRate())
+ {
+ super.setSampleRate(rspSampleRate);
+ }
+ else
+ {
+ super.setSampleRate(RspTunerConfiguration.DEFAULT_DUAL_TUNER_SAMPLE_RATE);
+ }
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner2Editor.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner2Editor.java
new file mode 100644
index 000000000..5d691727c
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner2Editor.java
@@ -0,0 +1,423 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rspDuo;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import io.github.dsheirer.eventbus.MyEventBus;
+import io.github.dsheirer.gui.preference.PreferenceEditorType;
+import io.github.dsheirer.gui.preference.ViewUserPreferenceEditorRequest;
+import io.github.dsheirer.preference.UserPreferences;
+import io.github.dsheirer.source.tuner.manager.TunerManager;
+import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
+import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerEditor;
+import java.util.EnumSet;
+import net.miginfocom.swing.MigLayout;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSeparator;
+import javax.swing.SpinnerNumberModel;
+
+/**
+ * RSPduo Tuner 2 Editor
+ */
+public class RspDuoTuner2Editor extends RspTunerEditor
+{
+ private static final Logger mLog = LoggerFactory.getLogger(RspDuoTuner2Editor.class);
+
+ private JComboBox mSampleRateCombo;
+ private JCheckBox mBiasTCheckBox;
+ private JCheckBox mExternalReferenceOutputCheckBox;
+ private JCheckBox mRfDabNotchCheckBox;
+ private JCheckBox mRfNotchCheckBox;
+ private JButton mTunerPreferencesButton;
+
+ /**
+ * Constructs an instance
+ * @param userPreferences for settings
+ * @param tunerManager for state updates
+ * @param discoveredTuner to edit or control.
+ */
+ public RspDuoTuner2Editor(UserPreferences userPreferences, TunerManager tunerManager, DiscoveredRspTuner discoveredTuner)
+ {
+ super(userPreferences, tunerManager, discoveredTuner);
+ init();
+ tunerStatusUpdated();
+ }
+
+ private void init()
+ {
+ setLayout(new MigLayout("fill,wrap 3", "[right][grow,fill][fill]",
+ "[][][][][][][][][][][][][][][grow]"));
+
+ add(new JLabel("Tuner:"));
+ JPanel labelAndButtonPanel = new JPanel();
+ labelAndButtonPanel.setLayout(new MigLayout("insets 0"));
+ labelAndButtonPanel.add(getTunerIdLabel());
+ labelAndButtonPanel.add(getTunerPreferencesButton());
+ add(labelAndButtonPanel, "wrap");
+ add(new JLabel("Status:"));
+ add(getTunerStatusLabel(), "wrap");
+ add(getButtonPanel(), "span,align left");
+
+ add(new JSeparator(), "span,growx,push");
+
+ add(new JLabel("Frequency (MHz):"));
+ add(getFrequencyPanel(), "wrap");
+
+ add(new JLabel("Sample Rate:"));
+ add(getSampleRateCombo(), "wrap");
+
+ add(new JLabel("Gain:"));
+ add(getGainSlider());
+ add(getGainValueLabel());
+
+ add(new JSeparator(), "span,growx,push");
+
+ add(new JLabel());
+ add(getExternalReferenceOutputCheckBox(), "wrap");
+ add(new JLabel());
+ add(getBiasTCheckBox(), "wrap");
+ add(new JLabel());
+ add(getRfDabNotchCheckBox(), "wrap");
+ add(new JLabel());
+ add(getRfNotchCheckBox(), "wrap");
+ }
+
+ private DiscoveredRspTuner getDiscoveredRspTuner()
+ {
+ return (DiscoveredRspTuner)getDiscoveredTuner();
+ }
+
+ /**
+ * Access tuner controller
+ */
+ private RspDuoTuner2Controller getTunerController()
+ {
+ if(hasTuner())
+ {
+ return (RspDuoTuner2Controller) getTuner().getTunerController();
+ }
+
+ return null;
+ }
+
+ /**
+ * Indicates if this editor has a tuner and the tuner is configured for slave mode.
+ */
+ private boolean isSlaveMode()
+ {
+ return getDiscoveredRspTuner().getDeviceInfo().getDeviceSelectionMode().isSlaveMode();
+ }
+
+ @Override
+ protected void tunerStatusUpdated()
+ {
+ setLoading(true);
+
+ getTunerIdLabel().setText(getDiscoveredTuner().getId());
+
+ String status = getDiscoveredTuner().getTunerStatus().toString();
+ if(getDiscoveredTuner().hasErrorMessage())
+ {
+ status += " - " + getDiscoveredTuner().getErrorMessage();
+ }
+ getTunerStatusLabel().setText(status);
+ getButtonPanel().updateControls();
+
+ //If master/slave configuration, disable the slave's enable/disable button - user can disable
+ //the tuner via the master device.
+ if(isSlaveMode())
+ {
+ getEnabledButton().setEnabled(false);
+ }
+
+ getFrequencyPanel().updateControls();
+
+ clearSampleRates();
+ if(hasTuner())
+ {
+ setSampleRates(getTunerController().getControlRsp().getSupportedSampleRates());
+ }
+ getSampleRateCombo().setEnabled(hasTuner() && !isSlaveMode() && !getTuner().getTunerController().isLockedSampleRate());
+ getSampleRateCombo().setSelectedItem(hasTuner() ? getTunerController().getControlRsp().getSampleRateEnumeration() : null);
+
+ getGainSlider().setEnabled(hasTuner());
+ getGainValueLabel().setEnabled(hasTuner());
+ getGainSlider().setValue(hasTuner() ? getTunerController().getControlRsp().getGain() : 0);
+
+ getRfDabNotchCheckBox().setEnabled(hasTuner());
+ try
+ {
+ getRfDabNotchCheckBox().setSelected(hasTuner() && getTunerController().getControlRsp().isRfDabNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 2 RF DAB Notch enabled state in editor");
+ }
+
+ getRfNotchCheckBox().setEnabled(hasTuner());
+ try
+ {
+ getRfNotchCheckBox().setSelected(hasTuner() && getTunerController().getControlRsp().isRfNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 2 RF Notch enabled state in editor");
+ }
+
+ getBiasTCheckBox().setEnabled(hasTuner());
+ try
+ {
+ getBiasTCheckBox().setSelected(hasTuner() && getTunerController().getControlRsp().isBiasT());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 2 Bias-T enabled state in editor");
+ }
+
+ getExternalReferenceOutputCheckBox().setEnabled(hasTuner() && !isSlaveMode());
+ try
+ {
+ getExternalReferenceOutputCheckBox()
+ .setSelected(hasTuner() && !isSlaveMode() && getTunerController().getControlRsp().isExternalReferenceOutput());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPduo tuner 2 external reference output enabled state in editor");
+ }
+
+ setLoading(false);
+ }
+
+ @Override
+ public void save()
+ {
+ if(hasConfiguration() && !isLoading())
+ {
+ getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
+ getConfiguration().setFrequencyCorrection(value);
+ getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
+ if(getSampleRateCombo().getSelectedItem() != null)
+ {
+ getConfiguration().setSampleRate((RspSampleRate)getSampleRateCombo().getSelectedItem());
+ }
+ getConfiguration().setBiasT(getBiasTCheckBox().isSelected());
+ if(hasTuner() && !isSlaveMode())
+ {
+ getConfiguration().setExternalReferenceOutput(getExternalReferenceOutputCheckBox().isSelected());
+ }
+ getConfiguration().setRfDabNotch(getRfDabNotchCheckBox().isSelected());
+ getConfiguration().setRfNotch(getRfNotchCheckBox().isSelected());
+ getConfiguration().setGain(getGainSlider().getValue());
+
+ saveConfiguration();
+ }
+ }
+
+ /**
+ * Updates the sample rates listed in the combobox.
+ * @param sampleRates to use.
+ */
+ private void setSampleRates(EnumSet sampleRates)
+ {
+ if(!sampleRates.isEmpty())
+ {
+ for(RspSampleRate sampleRate: sampleRates)
+ {
+ getSampleRateCombo().addItem(sampleRate);
+ }
+ }
+ }
+
+ /**
+ * Removes all sample rate options from the combo box.
+ */
+ private void clearSampleRates()
+ {
+ getSampleRateCombo().removeAllItems();
+ }
+
+ /**
+ * Sample rate selection combobox control
+ */
+ private JComboBox getSampleRateCombo()
+ {
+ if(mSampleRateCombo == null)
+ {
+ mSampleRateCombo = new JComboBox<>();
+ mSampleRateCombo.setEnabled(false);
+ mSampleRateCombo.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ RspSampleRate selected = (RspSampleRate)mSampleRateCombo.getSelectedItem();
+
+ try
+ {
+ getTunerController().setSampleRate(selected);
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting sample rate for RSPduo tuner 2", se);
+ }
+ }
+ });
+ }
+
+ return mSampleRateCombo;
+ }
+
+ /**
+ * Checkbox control for RF DAB notch
+ */
+ private JCheckBox getRfDabNotchCheckBox()
+ {
+ if(mRfDabNotchCheckBox == null)
+ {
+ mRfDabNotchCheckBox = new JCheckBox("DAB Broadcast Band Filter (157-235 MHz)");
+ mRfDabNotchCheckBox.setEnabled(false);
+ mRfDabNotchCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setRfDabNotch(mRfDabNotchCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSPduo tuner 2 RF DAB notch enabled to " + mRfDabNotchCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mRfDabNotchCheckBox;
+ }
+
+ /**
+ * Checkbox control for RF notch
+ */
+ private JCheckBox getRfNotchCheckBox()
+ {
+ if(mRfNotchCheckBox == null)
+ {
+ mRfNotchCheckBox = new JCheckBox("FM Broadcast Band Filter (78-114 MHz)");
+ mRfNotchCheckBox.setEnabled(false);
+ mRfNotchCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setRfNotch(mRfNotchCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSPduo tuner 2 RF notch enabled to " + mRfNotchCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mRfNotchCheckBox;
+ }
+
+ /**
+ * Checkbox control for Bias-T
+ */
+ private JCheckBox getBiasTCheckBox()
+ {
+ if(mBiasTCheckBox == null)
+ {
+ mBiasTCheckBox = new JCheckBox("Bias-T Power");
+ mBiasTCheckBox.setEnabled(false);
+ mBiasTCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setBiasT(mBiasTCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSPduo tuner 2 AM notch enabled to " + mBiasTCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mBiasTCheckBox;
+ }
+
+ /**
+ * Checkbox control for External Reference Output
+ */
+ private JCheckBox getExternalReferenceOutputCheckBox()
+ {
+ if(mExternalReferenceOutputCheckBox == null)
+ {
+ mExternalReferenceOutputCheckBox = new JCheckBox("External Reference Output");
+ mExternalReferenceOutputCheckBox.setEnabled(false);
+ mExternalReferenceOutputCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setExternalReferenceOutput(mExternalReferenceOutputCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSPduo tuner 2 external reference output notch enabled to " +
+ mExternalReferenceOutputCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mExternalReferenceOutputCheckBox;
+ }
+
+ /**
+ * Button to launch the User Preferences editor to show the RSPduo tuner preference selection.
+ * @return constructed button.
+ */
+ private JButton getTunerPreferencesButton()
+ {
+ if(mTunerPreferencesButton == null)
+ {
+ mTunerPreferencesButton = new JButton("RSPduo Preferences");
+ mTunerPreferencesButton.addActionListener(e -> MyEventBus.getGlobalEventBus()
+ .post(new ViewUserPreferenceEditorRequest(PreferenceEditorType.SOURCE_TUNERS)));
+ }
+
+ return mTunerPreferencesButton;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/ControlRspDx.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/ControlRspDx.java
new file mode 100644
index 000000000..8c3c9ffbc
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/ControlRspDx.java
@@ -0,0 +1,201 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rspDx;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.device.RspDxDevice;
+import com.github.dsheirer.sdrplay.parameter.tuner.HdrModeBandwidth;
+import com.github.dsheirer.sdrplay.parameter.tuner.RspDxAntenna;
+import io.github.dsheirer.source.tuner.sdrplay.ControlRsp;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Control wrapper for an RSPdx Device
+ */
+public class ControlRspDx extends ControlRsp implements IControlRspDx
+{
+ private Logger mLog = LoggerFactory.getLogger(ControlRspDx.class);
+
+ /**
+ * Constructs an instance
+ * @param device for the device
+ */
+ public ControlRspDx(RspDxDevice device)
+ {
+ super(device);
+ }
+
+ @Override
+ public boolean isBiasT() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getDevice().getTuner().isBiasT();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setBiasT(boolean enabled) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().getTuner().setBiasT(enabled);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public boolean isRfNotch() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getDevice().getTuner().isRfNotch();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setRfNotch(boolean enabled) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().getTuner().setRfNotch(enabled);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public boolean isRfDabNotch() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getDevice().getTuner().isRfDabNotch();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setRfDabNotch(boolean enabled) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().getTuner().setRfDabNotch(enabled);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public boolean isHighDynamicRange() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getDevice().getTuner().isHdrMode();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setHighDynamicRange(boolean enabled) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().getTuner().setHdrMode(enabled);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public RspDxAntenna getAntenna() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getDevice().getTuner().getAntenna();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setAntenna(RspDxAntenna antenna) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().getTuner().setAntenna(antenna);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public void setHdrModeBandwidth(HdrModeBandwidth bandwidth) throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ getDevice().getTuner().setHdrModeBandwidth(bandwidth);
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+
+ @Override
+ public HdrModeBandwidth getHdrModeBandwidth() throws SDRPlayException
+ {
+ if(hasDevice())
+ {
+ return getDevice().getTuner().getHdrModeBandwidth();
+ }
+ else
+ {
+ throw new SDRPlayException("Device is not initialized");
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/DiscoveredRspDxTuner.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/DiscoveredRspDxTuner.java
new file mode 100644
index 000000000..0f8d927db
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/DiscoveredRspDxTuner.java
@@ -0,0 +1,40 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 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.sdrplay.rspDx;
+
+import com.github.dsheirer.sdrplay.device.DeviceInfo;
+import io.github.dsheirer.preference.source.ChannelizerType;
+import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
+
+/**
+ * RSPdx discovered tuner.
+ */
+public class DiscoveredRspDxTuner extends DiscoveredRspTuner
+{
+ /**
+ * Constructs an instance
+ * @param deviceInfo for the tuner
+ * @param channelizerType to use for the tuner once started
+ */
+ public DiscoveredRspDxTuner(DeviceInfo deviceInfo, ChannelizerType channelizerType)
+ {
+ super(deviceInfo, channelizerType);
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/IControlRspDx.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/IControlRspDx.java
new file mode 100644
index 000000000..038e7bd0f
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/IControlRspDx.java
@@ -0,0 +1,115 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rspDx;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.parameter.tuner.HdrModeBandwidth;
+import com.github.dsheirer.sdrplay.parameter.tuner.RspDxAntenna;
+import io.github.dsheirer.source.tuner.sdrplay.IControlRsp;
+
+/**
+ * Control interface for RSPdx device
+ */
+public interface IControlRspDx extends IControlRsp
+{
+ /**
+ * Indicates if the Bias-T power is enabled.
+ * @return true if enabled.
+ * @throws SDRPlayException if the device is no started/selected
+ */
+ boolean isBiasT() throws SDRPlayException;
+
+ /**
+ * Sets the enabled state of the Bias-T power.
+ * @param enabled true to power on the Bias-T
+ * @throws SDRPlayException if the device is not started (selected).
+ */
+ void setBiasT(boolean enabled) throws SDRPlayException;
+
+ /**
+ * Indicates the enabled state of high dynamic range mode
+ * @return true if enabled.
+ * @throws SDRPlayException if the device is not started (selected).
+ */
+ boolean isHighDynamicRange() throws SDRPlayException;
+
+ /**
+ * Sets the enabled state of the high dynamic range mode
+ * @param enabled true to enable.
+ * @throws SDRPlayException if the device is not started (selected).
+ */
+ void setHighDynamicRange(boolean enabled) throws SDRPlayException;
+
+ /**
+ * Indicates if the RF notch is enabled (FM broadcast band filter).
+ * @return true if enabled.
+ * @throws SDRPlayException if the device is not started (selected).
+ */
+ boolean isRfNotch() throws SDRPlayException;
+
+ /**
+ * Sets the enabled state of the RF notch
+ * @param enabled true to filter the FM broadcast band frequency range.
+ * @throws SDRPlayException if the device is not started (selected).
+ */
+ void setRfNotch(boolean enabled) throws SDRPlayException;
+
+ /**
+ * Indicates if the RF DAB notch is enabled (DAB broadcast band filter).
+ * @return true if enabled.
+ * @throws SDRPlayException if the device is not started (selected).
+ */
+ boolean isRfDabNotch() throws SDRPlayException;
+
+ /**
+ * Sets the enabled state of the RF DAB notch.
+ * @param enabled true to filter the DAB broadcast band frequency range.
+ * @throws SDRPlayException if the device is not started (selected).
+ */
+ void setRfDabNotch(boolean enabled) throws SDRPlayException;
+
+ /**
+ * Antenna selection
+ * @return currently selected antenna
+ * @throws SDRPlayException if the device is not started (selected)
+ */
+ RspDxAntenna getAntenna() throws SDRPlayException;
+
+ /**
+ * Sets the antenna selection
+ * @param antenna to select
+ * @throws SDRPlayException if the device is not started (selected)
+ */
+ void setAntenna(RspDxAntenna antenna) throws SDRPlayException;
+
+ /**
+ * Sets High Dynamic Range mode bandwidth
+ * @param bandwidth to apply
+ * @throws SDRPlayException if the device is not started (selected)
+ */
+ void setHdrModeBandwidth(HdrModeBandwidth bandwidth) throws SDRPlayException;
+
+ /**
+ * High Dynamic Range mode bandwidth
+ * @return bandwidth
+ * @throws SDRPlayException if the device is not started (selected)
+ */
+ HdrModeBandwidth getHdrModeBandwidth() throws SDRPlayException;
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/RspDxTunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/RspDxTunerConfiguration.java
new file mode 100644
index 000000000..c4775ca19
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/RspDxTunerConfiguration.java
@@ -0,0 +1,164 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rspDx;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.github.dsheirer.sdrplay.parameter.tuner.HdrModeBandwidth;
+import com.github.dsheirer.sdrplay.parameter.tuner.RspDxAntenna;
+import io.github.dsheirer.source.tuner.TunerType;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerConfiguration;
+
+/**
+ * RSPdx tuner configuration
+ */
+public class RspDxTunerConfiguration extends RspTunerConfiguration
+{
+ private boolean mBiasT;
+ private boolean mHdrMode = false;
+ private boolean mRfNotch;
+ private boolean mRfDabNotch;
+ private RspDxAntenna mAntenna = RspDxAntenna.ANTENNA_A;
+ private HdrModeBandwidth mHdrModeBandwidth = HdrModeBandwidth.BANDWIDTH_1_700;
+
+ /**
+ * Constructs an instance
+ * @param uniqueId for the tuner
+ */
+ public RspDxTunerConfiguration(String uniqueId)
+ {
+ super(uniqueId);
+ }
+
+ /**
+ * JAXB constructor
+ */
+ public RspDxTunerConfiguration()
+ {
+ }
+
+
+ @Override
+ public TunerType getTunerType()
+ {
+ return TunerType.RSP_DX;
+ }
+
+ /**
+ * Indicates if HDR mode is enabled
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "hdr_mode")
+ public boolean isHdrMode()
+ {
+ return mHdrMode;
+ }
+
+ /**
+ * Sets enabled state of HDR mode
+ */
+ public void setHdrMode(boolean enabled)
+ {
+ mHdrMode = enabled;
+ }
+
+ /**
+ * Indicates if RF notch is enabled
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "rf_notch")
+ public boolean isRfNotch()
+ {
+ return mRfNotch;
+ }
+
+ /**
+ * Sets enabled state of RF notch
+ */
+ public void setRfNotch(boolean enabled)
+ {
+ mRfNotch = enabled;
+ }
+
+ /**
+ * Indicates if RF Digital Audio Broadcast (DAB) notch is enabled
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "dab_notch")
+ public boolean isRfDabNotch()
+ {
+ return mRfDabNotch;
+ }
+
+ /**
+ * Sets enabled state of DAB notch
+ */
+ public void setRfDabNotch(boolean enabled)
+ {
+ mRfDabNotch = enabled;
+ }
+
+ /**
+ * Indicates if Bias-T is enabled
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "bias_t")
+ public boolean isBiasT()
+ {
+ return mBiasT;
+ }
+
+ /**
+ * Sets enabled state of Bias-T
+ */
+ public void setBiasT(boolean enabled)
+ {
+ mBiasT = enabled;
+ }
+
+ /**
+ * Antenna setting
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "antenna")
+ public RspDxAntenna getAntenna()
+ {
+ return mAntenna;
+ }
+
+ /**
+ * Sets the antenna.
+ */
+ public void setAntenna(RspDxAntenna antenna)
+ {
+ mAntenna = antenna;
+ }
+
+ /**
+ * HDR mode bandwidth setting.
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "hdr_mode_bandwidth")
+ public HdrModeBandwidth getHdrModeBandwidth()
+ {
+ return mHdrModeBandwidth;
+ }
+
+ /**
+ * Sets HDR mode bandwidth
+ */
+ public void setHdrModeBandwidth(HdrModeBandwidth hdrModeBandwidth)
+ {
+ mHdrModeBandwidth = hdrModeBandwidth;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/RspDxTunerController.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/RspDxTunerController.java
new file mode 100644
index 000000000..c0c9bc0c3
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/RspDxTunerController.java
@@ -0,0 +1,121 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rspDx;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import io.github.dsheirer.source.SourceException;
+import io.github.dsheirer.source.tuner.ITunerErrorListener;
+import io.github.dsheirer.source.tuner.TunerType;
+import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Tuner controller for RSPdx
+ */
+public class RspDxTunerController extends RspTunerController
+{
+ private Logger mLog = LoggerFactory.getLogger(RspDxTunerController.class);
+
+ /**
+ * Constructs an instance
+ *
+ * @param control interface for the RSPdx tuner
+ * @param tunerErrorListener to monitor errors produced from this tuner controller
+ */
+ public RspDxTunerController(IControlRspDx control, ITunerErrorListener tunerErrorListener)
+ {
+ super(control, tunerErrorListener);
+ }
+
+ @Override
+ public TunerType getTunerType()
+ {
+ return TunerType.RSP_DX;
+ }
+
+ @Override
+ public void apply(TunerConfiguration config) throws SourceException
+ {
+ if(config instanceof RspDxTunerConfiguration rtc)
+ {
+ super.apply(config);
+
+ try
+ {
+ getControlRsp().setAntenna(rtc.getAntenna());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPdx antenna to " + rtc.getAntenna());
+ }
+
+ try
+ {
+ getControlRsp().setBiasT(rtc.isBiasT());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPdx bias-T enabled to " + rtc.isBiasT());
+ }
+
+ try
+ {
+ getControlRsp().setHighDynamicRange(rtc.isHdrMode());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPdx high dynamic range mode enabled to " + rtc.isHdrMode());
+ }
+
+ try
+ {
+ getControlRsp().setRfNotch(rtc.isRfNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPdx RF Notch enabled to " + rtc.isRfNotch());
+ }
+
+ try
+ {
+ getControlRsp().setRfDabNotch(rtc.isRfDabNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPdx RF DAB Notch enabled to " + rtc.isRfDabNotch());
+ }
+
+ try
+ {
+ getControlRsp().setHdrModeBandwidth(rtc.getHdrModeBandwidth());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RSPdx HDR mode bandwdidth to " + rtc.getHdrModeBandwidth());
+ }
+ }
+ else
+ {
+ mLog.error("Invalid RSPdx tuner configuration type: " + config.getClass());
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/RspDxTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/RspDxTunerEditor.java
new file mode 100644
index 000000000..848991b64
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/RspDxTunerEditor.java
@@ -0,0 +1,423 @@
+/*
+ * *****************************************************************************
+ * 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.sdrplay.rspDx;
+
+import com.github.dsheirer.sdrplay.SDRPlayException;
+import com.github.dsheirer.sdrplay.parameter.tuner.HdrModeBandwidth;
+import com.github.dsheirer.sdrplay.parameter.tuner.RspDxAntenna;
+import io.github.dsheirer.preference.UserPreferences;
+import io.github.dsheirer.source.tuner.manager.TunerManager;
+import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
+import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
+import io.github.dsheirer.source.tuner.sdrplay.RspTunerEditor;
+import net.miginfocom.swing.MigLayout;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JSeparator;
+import javax.swing.SpinnerNumberModel;
+
+/**
+ * RSPdx Tuner Editor
+ */
+public class RspDxTunerEditor extends RspTunerEditor
+{
+ private static final Logger mLog = LoggerFactory.getLogger(RspDxTunerEditor.class);
+
+ private JComboBox mSampleRateCombo;
+ private JCheckBox mBiasTCheckBox;
+ private JCheckBox mRfDabNotchCheckBox;
+ private JCheckBox mRfNotchCheckBox;
+ private JComboBox mAntennaCombo;
+ private JCheckBox mHdrModeCheckBox;
+ private JComboBox mHdrModeBandwidthCombo;
+
+ /**
+ * Constructs an instance
+ * @param userPreferences for settings
+ * @param tunerManager for state updates
+ * @param discoveredTuner to edit or control.
+ */
+ public RspDxTunerEditor(UserPreferences userPreferences, TunerManager tunerManager, DiscoveredRspTuner discoveredTuner)
+ {
+ super(userPreferences, tunerManager, discoveredTuner);
+ init();
+ tunerStatusUpdated();
+ }
+
+ private void init()
+ {
+ setLayout(new MigLayout("fill,wrap 3", "[right][grow,fill][fill]",
+ "[][][][][][][][][][][][grow]"));
+
+ add(new JLabel("Tuner:"));
+ add(getTunerIdLabel(), "wrap");
+
+ add(new JLabel("Status:"));
+ add(getTunerStatusLabel(), "wrap");
+
+ add(getButtonPanel(), "span,align left");
+
+ add(new JSeparator(), "span,growx,push");
+
+ add(new JLabel("Frequency (MHz):"));
+ add(getFrequencyPanel(), "wrap");
+
+ add(new JLabel("Sample Rate:"));
+ add(getSampleRateCombo(), "wrap");
+
+ add(new JLabel("Gain:"));
+ add(getGainSlider());
+ add(getGainValueLabel());
+
+ add(new JSeparator(), "span,growx,push");
+
+ add(new JLabel());
+ add(getAntennaCombo(), "wrap");
+ add(new JLabel());
+ add(getBiasTCheckBox(), "wrap");
+ add(new JLabel());
+ add(getRfDabNotchCheckBox(), "wrap");
+ add(new JLabel());
+ add(getRfNotchCheckBox(), "wrap");
+
+ add(new JSeparator(), "span,growx,push");
+ add(new JLabel());
+ add(getHdrModeCheckBox(), "wrap");
+ add(new JLabel("HDR Mode Bandwidth"));
+ add(getHdrModeBandwidthCombo(), "wrap");
+ }
+
+ /**
+ * Access tuner controller
+ */
+ private RspDxTunerController getTunerController()
+ {
+ if(hasTuner())
+ {
+ return (RspDxTunerController) getTuner().getTunerController();
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void tunerStatusUpdated()
+ {
+ setLoading(true);
+
+ getTunerIdLabel().setText(getDiscoveredTuner().getId());
+
+ String status = getDiscoveredTuner().getTunerStatus().toString();
+ if(getDiscoveredTuner().hasErrorMessage())
+ {
+ status += " - " + getDiscoveredTuner().getErrorMessage();
+ }
+ getTunerStatusLabel().setText(status);
+ getButtonPanel().updateControls();
+ getFrequencyPanel().updateControls();
+
+ getSampleRateCombo().setEnabled(hasTuner() && !getTuner().getTunerController().isLockedSampleRate());
+ getSampleRateCombo().setSelectedItem(hasTuner() ? getTunerController().getControlRsp().getSampleRateEnumeration() : null);
+
+ getGainSlider().setEnabled(hasTuner());
+ getGainValueLabel().setEnabled(hasTuner());
+ getGainSlider().setValue(hasTuner() ? getTunerController().getControlRsp().getGain() : 0);
+
+ getBiasTCheckBox().setEnabled(hasTuner());
+ try
+ {
+ getBiasTCheckBox().setSelected(hasTuner() && getTunerController().getControlRsp().isBiasT());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting Bias-T enabled state in editor");
+ }
+
+ getHdrModeCheckBox().setEnabled(hasTuner());
+ try
+ {
+ getHdrModeCheckBox().setSelected(hasTuner() && getTunerController().getControlRsp().isHighDynamicRange());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting HDR mode enabled state in editor");
+ }
+
+ getRfNotchCheckBox().setEnabled(hasTuner());
+ try
+ {
+ getRfNotchCheckBox().setSelected(hasTuner() && getTunerController().getControlRsp().isRfNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RF Notch enabled state in editor");
+ }
+
+ getRfDabNotchCheckBox().setEnabled(hasTuner());
+ try
+ {
+ getRfDabNotchCheckBox().setSelected(hasTuner() && getTunerController().getControlRsp().isRfDabNotch());
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting RF DAB Notch enabled state in editor");
+ }
+
+ getAntennaCombo().setEnabled(hasTuner());
+ try
+ {
+ getAntennaCombo().setSelectedItem(hasTuner() ? getTunerController().getControlRsp().getAntenna() : null);
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting antenna selection in editor");
+ }
+
+ setLoading(false);
+ }
+
+ @Override
+ public void save()
+ {
+ if(hasConfiguration() && !isLoading())
+ {
+ getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
+ getConfiguration().setFrequencyCorrection(value);
+ getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
+ getConfiguration().setSampleRate((RspSampleRate)getSampleRateCombo().getSelectedItem());
+ getConfiguration().setBiasT(getBiasTCheckBox().isSelected());
+ getConfiguration().setHdrMode(getHdrModeCheckBox().isSelected());
+ getConfiguration().setRfDabNotch(getRfNotchCheckBox().isSelected());
+ getConfiguration().setRfNotch(getRfNotchCheckBox().isSelected());
+ getConfiguration().setAntenna((RspDxAntenna) getAntennaCombo().getSelectedItem());
+ getConfiguration().setGain(getGainSlider().getValue());
+
+ saveConfiguration();
+ }
+ }
+
+ /**
+ * Sample rate selection combobox control
+ */
+ private JComboBox getSampleRateCombo()
+ {
+ if(mSampleRateCombo == null)
+ {
+ RspSampleRate[] rspSampleRates = RspSampleRate.SINGLE_TUNER_SAMPLE_RATES.toArray(new RspSampleRate[RspSampleRate.SINGLE_TUNER_SAMPLE_RATES.size()]);
+ mSampleRateCombo = new JComboBox<>(rspSampleRates);
+ mSampleRateCombo.setEnabled(false);
+ mSampleRateCombo.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ RspSampleRate selected = (RspSampleRate)mSampleRateCombo.getSelectedItem();
+
+ try
+ {
+ getTunerController().setSampleRate(selected);
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting sample rate for RSP2 tuner", se);
+ }
+ }
+ });
+ }
+
+ return mSampleRateCombo;
+ }
+
+ /**
+ * Checkbox control for Bias-T
+ */
+ private JCheckBox getBiasTCheckBox()
+ {
+ if(mBiasTCheckBox == null)
+ {
+ mBiasTCheckBox = new JCheckBox("ANT B Bias-T Power");
+ mBiasTCheckBox.setEnabled(false);
+ mBiasTCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setBiasT(mBiasTCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSP2 Bias-T enabled to " + mBiasTCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mBiasTCheckBox;
+ }
+
+ /**
+ * Checkbox control for HDR mode
+ */
+ private JCheckBox getHdrModeCheckBox()
+ {
+ if(mHdrModeCheckBox == null)
+ {
+ mHdrModeCheckBox = new JCheckBox("HDR Mode (1 kHz - 2 MHz)");
+ mHdrModeCheckBox.setEnabled(false);
+ mHdrModeCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setHighDynamicRange(mHdrModeCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSPd HDR mode enabled to " + mHdrModeCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mHdrModeCheckBox;
+ }
+
+ /**
+ * Checkbox control for RF notch
+ */
+ private JCheckBox getRfNotchCheckBox()
+ {
+ if(mRfNotchCheckBox == null)
+ {
+ mRfNotchCheckBox = new JCheckBox("FM Broadcast Band Filter (77-115 MHz)");
+ mRfNotchCheckBox.setEnabled(false);
+ mRfNotchCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setRfNotch(mRfNotchCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSP2 RF notch enabled to " + mRfNotchCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mRfNotchCheckBox;
+ }
+
+ /**
+ * Checkbox control for RF DAB notch
+ */
+ private JCheckBox getRfDabNotchCheckBox()
+ {
+ if(mRfDabNotchCheckBox == null)
+ {
+ mRfDabNotchCheckBox = new JCheckBox("DAB Broadcast Band Filter (155-235 MHz)");
+ mRfDabNotchCheckBox.setEnabled(false);
+ mRfDabNotchCheckBox.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ try
+ {
+ getTunerController().getControlRsp().setRfDabNotch(mRfDabNotchCheckBox.isSelected());
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Unable to set RSPdx RF DAB notch enabled to " + mRfDabNotchCheckBox.isSelected(), se);
+ }
+ }
+ });
+ }
+
+ return mRfDabNotchCheckBox;
+ }
+
+ /**
+ * Antenna selection combobox control
+ */
+ private JComboBox getAntennaCombo()
+ {
+ if(mAntennaCombo == null)
+ {
+ mAntennaCombo = new JComboBox<>(RspDxAntenna.values());
+ mAntennaCombo.setEnabled(false);
+ mAntennaCombo.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ RspDxAntenna selected = (RspDxAntenna) mAntennaCombo.getSelectedItem();
+
+ try
+ {
+ getTunerController().getControlRsp().setAntenna(selected);
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting Antenna selection for RSPdx", se);
+ }
+ }
+ });
+ }
+
+ return mAntennaCombo;
+ }
+
+ /**
+ * HDR mode bandwidth selection combobox control
+ */
+ private JComboBox getHdrModeBandwidthCombo()
+ {
+ if(mHdrModeBandwidthCombo == null)
+ {
+ mHdrModeBandwidthCombo = new JComboBox<>(HdrModeBandwidth.values());
+ mHdrModeBandwidthCombo.setEnabled(false);
+ mHdrModeBandwidthCombo.addActionListener(e -> {
+ if(hasTuner() && !isLoading())
+ {
+ HdrModeBandwidth selected = (HdrModeBandwidth) mHdrModeBandwidthCombo.getSelectedItem();
+
+ try
+ {
+ getTunerController().getControlRsp().setHdrModeBandwidth(selected);
+ save();
+ }
+ catch(SDRPlayException se)
+ {
+ mLog.error("Error setting HDR mode bandwidth for RSPdx", se);
+ }
+ }
+ });
+ }
+
+ return mHdrModeBandwidthCombo;
+ }
+}
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 8bf71c9f2..0c43db36b 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
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2023 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
@@ -124,7 +124,14 @@ public void tunerStatusUpdated(DiscoveredTuner discoveredTuner, TunerStatus prev
//If this is the currently displayed tuner, set it again to re-render the editor
if(hasItem() && getItem().equals(discoveredTuner))
{
- setItem(discoveredTuner);
+ if(current == TunerStatus.REMOVED)
+ {
+ setItem(null);
+ }
+ else
+ {
+ setItem(discoveredTuner);
+ }
}
}
}
\ No newline at end of file
diff --git a/src/main/java/io/github/dsheirer/source/tuner/ui/DiscoveredTunerModel.java b/src/main/java/io/github/dsheirer/source/tuner/ui/DiscoveredTunerModel.java
index b8159f904..a809483cf 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/ui/DiscoveredTunerModel.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/ui/DiscoveredTunerModel.java
@@ -25,10 +25,13 @@
import io.github.dsheirer.source.tuner.manager.DiscoveredUSBTuner;
import io.github.dsheirer.source.tuner.manager.IDiscoveredTunerStatusListener;
import io.github.dsheirer.source.tuner.manager.TunerStatus;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.DiscoveredRspDuoTuner1;
+import io.github.dsheirer.source.tuner.sdrplay.rspDuo.DiscoveredRspDuoTuner2;
import java.awt.EventQueue;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -130,6 +133,35 @@ public DiscoveredTuner getDiscoveredTuner(int index)
return null;
}
+ /**
+ * Find a discovered tuner by ID
+ * @param id of the tuner to search for
+ * @return discovered tuner with matching ID or null.
+ */
+ public DiscoveredTuner getDiscoveredTuner(String id)
+ {
+ DiscoveredTuner discoveredTuner = null;
+
+ mLock.lock();
+
+ try
+ {
+ Optional result = mDiscoveredTuners.stream().filter(tuner -> tuner.getId().equals(id)).findFirst();
+
+ if(result.isPresent())
+ {
+ discoveredTuner = result.get();
+ }
+ }
+ finally
+ {
+ mLock.unlock();
+ }
+
+ return discoveredTuner;
+ }
+
+
/**
* Adds the Tuner to this model
*/
@@ -164,24 +196,23 @@ public void releaseDiscoveredTuners()
{
mLock.lock();
+ List discoveredTuners = new ArrayList<>(mDiscoveredTuners);
+
try
{
- List discoveredTuners = new ArrayList<>(mDiscoveredTuners);
-
- for(DiscoveredTuner discoveredTuner: discoveredTuners)
- {
- if(discoveredTuner.hasTuner())
- {
- discoveredTuner.getTuner().removeTunerEventListener(this);
- }
-
- removeDiscoveredTuner(discoveredTuner);
- }
+ mDiscoveredTuners.clear();
+ fireTableDataChanged();
}
finally
{
mLock.unlock();
}
+
+ for(DiscoveredTuner discoveredTuner: discoveredTuners)
+ {
+ discoveredTuner.stop();
+ discoveredTuner.removeTunerStatusListener(this);
+ }
}
/**
@@ -198,10 +229,39 @@ public void removeDiscoveredTuner(DiscoveredTuner discoveredTuner)
{
int index = mDiscoveredTuners.indexOf(discoveredTuner);
mDiscoveredTuners.remove(discoveredTuner);
- EventQueue.invokeLater(() -> fireTableRowsDeleted(index, index));
+
+ if(EventQueue.isDispatchThread())
+ {
+ try
+ {
+ fireTableRowsDeleted(index, index);
+ }
+ catch(Exception e)
+ {
+ mLog.info("Exception firing table rows deleted for index [" + index + "] on calling event dispatch thread", e);
+ }
+ }
+ else
+ {
+ EventQueue.invokeAndWait(() ->
+ {
+ try
+ {
+ fireTableRowsDeleted(index, index);
+ }
+ catch(Exception e)
+ {
+ mLog.info("Exception firing table rows deleted for index [" + index + "]", e);
+ }
+ });
+ }
discoveredTuner.stop();
}
}
+ catch(Exception e)
+ {
+ mLog.error("Unexpected error while shutting down discovered tuner", e);
+ }
finally
{
mLock.unlock();
@@ -297,47 +357,57 @@ public void broadcast(TunerEvent event)
}
}
- /**
- * Requests to display the first tuner in this model. Invoke this method
- * after all listeners have registered and tuners have been added to this
- * model, in order to inform the primary display to use the first tuner.
- */
- public void requestFirstTunerDisplay()
- {
-//TODO: move this out of the model ... is not part of the scope of this model
-// SystemProperties properties = SystemProperties.getInstance();
-// boolean enabled = properties.get(SpectralDisplayPanel.SPECTRAL_DISPLAY_ENABLED, true);
-//
-// if(enabled && mDiscoveredTuners.size() > 0)
-// {
-// //Hack: the airspy tuner would lockup aperiodically and refuse to produce
-// //transfer buffers ... delaying registering for buffers for 500 ms seems
-// //to allow the airspy to stabilize before we start asking for samples.
-// ThreadPool.SCHEDULED.schedule(new Runnable()
-// {
-// @Override
-// public void run()
-// {
-// broadcast(new TunerEvent(mDiscoveredTuners.get(0), Event.REQUEST_MAIN_SPECTRAL_DISPLAY));
-// }
-// }, 500, TimeUnit.MILLISECONDS);
-// }
-// else
-// {
-// broadcast(new TunerEvent(null, Event.CLEAR_MAIN_SPECTRAL_DISPLAY));
-// }
- }
-
@Override
public void tunerStatusUpdated(DiscoveredTuner discoveredTuner, TunerStatus previous, TunerStatus current)
{
if(current == TunerStatus.ENABLED && discoveredTuner.hasTuner())
{
discoveredTuner.getTuner().addTunerEventListener(this);
+ int row = mDiscoveredTuners.indexOf(discoveredTuner);
+ EventQueue.invokeLater(() -> fireTableRowsUpdated(row, row));
+ return;
}
- int row = mDiscoveredTuners.indexOf(discoveredTuner);
- EventQueue.invokeLater(() -> fireTableRowsUpdated(row, row));
+ if(current == TunerStatus.REMOVED)
+ {
+ mLog.info("Tuner removal detected - stopping and removing: " + discoveredTuner);
+
+ //Note: RSPduo only gets device removal indication if the device is streaming. There may be situation where
+ //master only is streaming, or slave only is streaming. Ensure we remove both devices when detected.
+
+ //Special handling for RSPduo Tuner 1 configured as master - remove the slave tuner also
+ if(discoveredTuner instanceof DiscoveredRspDuoTuner1 master1 &&
+ master1.getDeviceInfo().getDeviceSelectionMode().isMasterMode())
+ {
+ DiscoveredTuner slave2 = getDiscoveredTuner(master1.getSlaveId());
+
+ if(slave2 != null)
+ {
+ removeDiscoveredTuner(slave2);
+ }
+
+ removeDiscoveredTuner(discoveredTuner);
+ }
+ //Special handling for RSPduo Tuner 2 configured as slave - remove the master tuner also
+ else if(discoveredTuner instanceof DiscoveredRspDuoTuner2 slave2 &&
+ slave2.getDeviceInfo().getDeviceSelectionMode().isSlaveMode())
+ {
+ String masterId = slave2.getMasterId();
+
+ removeDiscoveredTuner(slave2);
+
+ DiscoveredTuner master1 = getDiscoveredTuner(masterId);
+
+ if(master1 != null)
+ {
+ removeDiscoveredTuner(master1);
+ }
+ }
+ else
+ {
+ removeDiscoveredTuner(discoveredTuner);
+ }
+ }
}
@Override
@@ -417,25 +487,6 @@ public Object getValueAt(int rowIndex, int columnIndex)
{
return "";
}
-// case COLUMN_TUNER_ID:
-// if(discoveredTuner.hasTuner())
-// {
-// return discoveredTuner.getTuner().getUniqueID();
-// }
-// else
-// {
-// return discoveredTuner.getId();
-// }
-// case COLUMN_SAMPLE_RATE:
-// if(discoveredTuner.hasTuner())
-// {
-// double sampleRate = discoveredTuner.getTuner().getTunerController().getSampleRate();
-// return mSampleRateFormat.format(sampleRate / 1E6D) + MHZ;
-// }
-// else
-// {
-// return "";
-// }
case COLUMN_FREQUENCY:
if(discoveredTuner.hasTuner())
{
@@ -456,40 +507,6 @@ public Object getValueAt(int rowIndex, int columnIndex)
{
return "";
}
-// case COLUMN_FREQUENCY_ERROR:
-// if(discoveredTuner.hasTuner())
-// {
-// double ppm = discoveredTuner.getTuner().getTunerController().getFrequencyCorrection();
-// return mFrequencyErrorPPMFormat.format(ppm);
-// }
-// else
-// {
-// return "";
-// }
-// case COLUMN_MEASURED_FREQUENCY_ERROR:
-// if(discoveredTuner.hasTuner())
-// {
-// if(discoveredTuner.getTuner().getTunerController().hasMeasuredFrequencyError())
-// {
-// StringBuilder sb = new StringBuilder();
-// sb.append(discoveredTuner.getTuner().getTunerController().getMeasuredFrequencyError());
-// sb.append("Hz (");
-// sb.append(mFrequencyErrorPPMFormat.format(discoveredTuner.getTuner().getTunerController().getPPMFrequencyError()));
-// sb.append("ppm)");
-// return sb.toString();
-// }
-// }
-// return "";
-// case COLUMN_ERROR_OR_SPECTRAL_DISPLAY_NEW:
-// if(discoveredTuner.hasErrorMessage())
-// {
-// return discoveredTuner.getErrorMessage();
-// }
-// else if(discoveredTuner.hasTuner())
-// {
-// return "New";
-// }
-// return "";
default:
break;
}
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 0fe7106e6..aab304341 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
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2023 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
@@ -35,6 +35,7 @@
import io.github.dsheirer.source.tuner.manager.TunerStatus;
import io.github.dsheirer.spectrum.SpectralDisplayPanel;
import io.github.dsheirer.util.SwingUtils;
+import io.github.dsheirer.util.ThreadPool;
import java.awt.EventQueue;
import java.text.CharacterIterator;
import java.text.DecimalFormat;
@@ -298,8 +299,8 @@ protected JButton getNewSpectrumButton()
if(tuner != null)
{
- mTunerManager.getDiscoveredTunerModel().broadcast(new TunerEvent(tuner,
- TunerEvent.Event.REQUEST_NEW_SPECTRAL_DISPLAY));
+ ThreadPool.CACHED.submit(() -> mTunerManager.getDiscoveredTunerModel().broadcast(new TunerEvent(tuner,
+ TunerEvent.Event.REQUEST_NEW_SPECTRAL_DISPLAY)));
}
});
}
@@ -324,8 +325,8 @@ protected JButton getViewSpectrumButton()
{
SystemProperties.getInstance().set(SpectralDisplayPanel.SPECTRAL_DISPLAY_ENABLED, true);
- mTunerManager.getDiscoveredTunerModel().broadcast(new TunerEvent(tuner,
- TunerEvent.Event.REQUEST_MAIN_SPECTRAL_DISPLAY));
+ ThreadPool.CACHED.submit(() -> mTunerManager.getDiscoveredTunerModel().broadcast(new TunerEvent(tuner,
+ TunerEvent.Event.REQUEST_MAIN_SPECTRAL_DISPLAY)));
}
});
}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/ui/TunerSpectralDisplayManager.java b/src/main/java/io/github/dsheirer/source/tuner/ui/TunerSpectralDisplayManager.java
index 5d9653616..a85db4229 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/ui/TunerSpectralDisplayManager.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/ui/TunerSpectralDisplayManager.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2023 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
@@ -67,20 +67,18 @@ public TunerSpectralDisplayManager(SpectralDisplayPanel panel, PlaylistManager p
*/
public Tuner showFirstTuner()
{
- if(!SystemProperties.getInstance().get(SpectralDisplayPanel.SPECTRAL_DISPLAY_ENABLED, true))
+ //Ensure spectral display is enabled before selecting first tuner
+ if(SystemProperties.getInstance().get(SpectralDisplayPanel.SPECTRAL_DISPLAY_ENABLED, true))
{
- //Spectral display is disabled, stop
- return null;
- }
-
- List availableTuners = mDiscoveredTunerModel.getAvailableTuners();
+ List availableTuners = mDiscoveredTunerModel.getAvailableTuners();
- for(DiscoveredTuner discoveredTuner: availableTuners)
- {
- if(discoveredTuner.hasTuner())
+ for(DiscoveredTuner discoveredTuner: availableTuners)
{
- mSpectralDisplayPanel.showTuner(discoveredTuner.getTuner());
- return discoveredTuner.getTuner();
+ if(discoveredTuner.hasTuner())
+ {
+ mSpectralDisplayPanel.showTuner(discoveredTuner.getTuner());
+ return discoveredTuner.getTuner();
+ }
}
}
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 8f425f3ec..fa1770a61 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
@@ -32,7 +32,6 @@
import java.util.List;
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.locks.ReentrantLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.usb4java.Context;
@@ -66,7 +65,6 @@ public abstract class USBTunerController extends TunerController
private TransferManager mTransferManager = new TransferManager();
private UsbEventProcessor mEventProcessor = new UsbEventProcessor();
private AtomicBoolean mStreaming = new AtomicBoolean();
- private ReentrantLock mListenerLock = new ReentrantLock();
private boolean mRunning = false;
//Troubleshooting libusb bug: https://github.com/DSheirer/sdrtrunk/issues/1253
@@ -469,7 +467,7 @@ public void addBufferListener(Listener listener)
{
if(isRunning())
{
- mListenerLock.lock();
+ mBufferListenerLock.lock();
try
{
@@ -484,7 +482,7 @@ public void addBufferListener(Listener listener)
}
finally
{
- mListenerLock.unlock();
+ mBufferListenerLock.unlock();
}
}
}
@@ -495,7 +493,7 @@ public void addBufferListener(Listener listener)
@Override
public void removeBufferListener(Listener listener)
{
- mListenerLock.lock();
+ mBufferListenerLock.lock();
try
{
@@ -508,7 +506,7 @@ public void removeBufferListener(Listener listener)
}
finally
{
- mListenerLock.unlock();
+ mBufferListenerLock.unlock();
}
}
diff --git a/src/main/java/io/github/dsheirer/spectrum/SpectralDisplayPanel.java b/src/main/java/io/github/dsheirer/spectrum/SpectralDisplayPanel.java
index 4bb4acbaa..7e825d8db 100644
--- a/src/main/java/io/github/dsheirer/spectrum/SpectralDisplayPanel.java
+++ b/src/main/java/io/github/dsheirer/spectrum/SpectralDisplayPanel.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2023 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
@@ -432,18 +432,22 @@ public void showTuner(Tuner tuner)
if(mTuner != null)
{
- //Register to receive frequency change events
- mTuner.getTunerController().addListener(this);
-
//Register the dft processor to receive samples from the tuner
mTuner.getTunerController().addBufferListener(mComplexDftProcessor);
- mSpectrumPanel.setSampleSize(mTuner.getSampleSize());
+ //Verify that the tuner is still non-null, in case it encountered an error on starting sample stream
+ if(mTuner != null)
+ {
+ //Register to receive frequency change events
+ mTuner.getTunerController().addListener(this);
+
+ mSpectrumPanel.setSampleSize(mTuner.getSampleSize());
- //Fire frequency and sample rate change events so that the spectrum
- //and overlay panels can synchronize
- process(SourceEvent.frequencyChange(null, mTuner.getTunerController().getFrequency()));
- process(SourceEvent.sampleRateChange(mTuner.getTunerController().getSampleRate()));
+ //Fire frequency and sample rate change events so that the spectrum
+ //and overlay panels can synchronize
+ process(SourceEvent.frequencyChange(null, mTuner.getTunerController().getFrequency()));
+ process(SourceEvent.sampleRateChange(mTuner.getTunerController().getSampleRate()));
+ }
}
}