[refactor](trx-backend-soapysdr): implement RigSdr trait for SoapySdrRig
Move 13 SDR-specific methods from impl RigCat into a new impl RigSdr block. Add as_sdr()/as_sdr_ref() overrides returning Some(self) so the SDR extension is accessible via the RigCat trait object. https://claude.ai/code/session_01XzurkeuUmamBuhQwxVy7T4 Signed-off-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@ use trx_core::radio::freq::{Band, Freq};
|
|||||||
use trx_core::rig::response::RigError;
|
use trx_core::rig::response::RigError;
|
||||||
use trx_core::rig::state::{RigFilterState, SpectrumData, VchanRdsEntry, WfmDenoiseLevel};
|
use trx_core::rig::state::{RigFilterState, SpectrumData, VchanRdsEntry, WfmDenoiseLevel};
|
||||||
use trx_core::rig::{
|
use trx_core::rig::{
|
||||||
AudioSource, Rig, RigAccessMethod, RigCapabilities, RigCat, RigInfo, RigStatusFuture,
|
AudioSource, Rig, RigAccessMethod, RigCapabilities, RigCat, RigInfo, RigSdr, RigStatusFuture,
|
||||||
};
|
};
|
||||||
use trx_core::{DynResult, RigMode};
|
use trx_core::{DynResult, RigMode};
|
||||||
|
|
||||||
@@ -518,6 +518,140 @@ impl RigCat for SoapySdrRig {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_mode<'a>(
|
||||||
|
&'a mut self,
|
||||||
|
mode: RigMode,
|
||||||
|
) -> Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
tracing::debug!("SoapySdrRig: set_mode -> {:?}", mode);
|
||||||
|
self.mode = mode.clone();
|
||||||
|
self.bandwidth_hz = Self::default_bandwidth_for_mode(&mode);
|
||||||
|
// Update the primary channel's demodulator in the live pipeline.
|
||||||
|
{
|
||||||
|
let dsps = self.pipeline.channel_dsps.read().unwrap();
|
||||||
|
if let Some(dsp_arc) = dsps.get(self.primary_channel_idx) {
|
||||||
|
let mut dsp = dsp_arc.lock().unwrap();
|
||||||
|
dsp.set_mode(&mode);
|
||||||
|
dsp.set_filter(self.bandwidth_hz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.apply_ais_channel_activity();
|
||||||
|
self.apply_ais_channel_filters();
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_signal_strength<'a>(
|
||||||
|
&'a mut self,
|
||||||
|
) -> Pin<Box<dyn std::future::Future<Output = DynResult<u8>> + Send + 'a>> {
|
||||||
|
// RSSI from real device pending SDR hardware wiring; return 0 for now.
|
||||||
|
Box::pin(async move { Ok(0u8) })
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- TX / unsupported methods -------------------------------------------
|
||||||
|
|
||||||
|
fn set_ptt<'a>(
|
||||||
|
&'a mut self,
|
||||||
|
_ptt: bool,
|
||||||
|
) -> Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
Err(Box::new(RigError::not_supported("set_ptt"))
|
||||||
|
as Box<dyn std::error::Error + Send + Sync>)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn power_on<'a>(
|
||||||
|
&'a mut self,
|
||||||
|
) -> Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
Err(Box::new(RigError::not_supported("power_on"))
|
||||||
|
as Box<dyn std::error::Error + Send + Sync>)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn power_off<'a>(
|
||||||
|
&'a mut self,
|
||||||
|
) -> Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
Err(Box::new(RigError::not_supported("power_off"))
|
||||||
|
as Box<dyn std::error::Error + Send + Sync>)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_tx_power<'a>(
|
||||||
|
&'a mut self,
|
||||||
|
) -> Pin<Box<dyn std::future::Future<Output = DynResult<u8>> + Send + 'a>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
Err(Box::new(RigError::not_supported("get_tx_power"))
|
||||||
|
as Box<dyn std::error::Error + Send + Sync>)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_tx_limit<'a>(
|
||||||
|
&'a mut self,
|
||||||
|
) -> Pin<Box<dyn std::future::Future<Output = DynResult<u8>> + Send + 'a>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
Err(Box::new(RigError::not_supported("get_tx_limit"))
|
||||||
|
as Box<dyn std::error::Error + Send + Sync>)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_tx_limit<'a>(
|
||||||
|
&'a mut self,
|
||||||
|
_limit: u8,
|
||||||
|
) -> Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
Err(Box::new(RigError::not_supported("set_tx_limit"))
|
||||||
|
as Box<dyn std::error::Error + Send + Sync>)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn toggle_vfo<'a>(
|
||||||
|
&'a mut self,
|
||||||
|
) -> Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
Err(Box::new(RigError::not_supported("toggle_vfo"))
|
||||||
|
as Box<dyn std::error::Error + Send + Sync>)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lock<'a>(
|
||||||
|
&'a mut self,
|
||||||
|
) -> Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
Err(Box::new(RigError::not_supported("lock"))
|
||||||
|
as Box<dyn std::error::Error + Send + Sync>)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unlock<'a>(
|
||||||
|
&'a mut self,
|
||||||
|
) -> Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
Err(Box::new(RigError::not_supported("unlock"))
|
||||||
|
as Box<dyn std::error::Error + Send + Sync>)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Override: this backend provides demodulated PCM audio.
|
||||||
|
fn as_audio_source(&self) -> Option<&dyn AudioSource> {
|
||||||
|
Some(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_sdr(&mut self) -> Option<&mut dyn RigSdr> {
|
||||||
|
Some(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_sdr_ref(&self) -> Option<&dyn RigSdr> {
|
||||||
|
Some(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// RigSdr — SDR-specific extension
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
impl RigSdr for SoapySdrRig {
|
||||||
fn set_center_freq<'a>(
|
fn set_center_freq<'a>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
freq: Freq,
|
freq: Freq,
|
||||||
@@ -541,24 +675,19 @@ impl RigCat for SoapySdrRig {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_mode<'a>(
|
fn set_bandwidth<'a>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
mode: RigMode,
|
bandwidth_hz: u32,
|
||||||
) -> Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
) -> std::pin::Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
tracing::debug!("SoapySdrRig: set_mode -> {:?}", mode);
|
tracing::debug!("SoapySdrRig: set_bandwidth -> {} Hz", bandwidth_hz);
|
||||||
self.mode = mode.clone();
|
self.bandwidth_hz = bandwidth_hz;
|
||||||
self.bandwidth_hz = Self::default_bandwidth_for_mode(&mode);
|
|
||||||
// Update the primary channel's demodulator in the live pipeline.
|
|
||||||
{
|
{
|
||||||
let dsps = self.pipeline.channel_dsps.read().unwrap();
|
let dsps = self.pipeline.channel_dsps.read().unwrap();
|
||||||
if let Some(dsp_arc) = dsps.get(self.primary_channel_idx) {
|
if let Some(dsp_arc) = dsps.get(self.primary_channel_idx) {
|
||||||
let mut dsp = dsp_arc.lock().unwrap();
|
dsp_arc.lock().unwrap().set_filter(bandwidth_hz);
|
||||||
dsp.set_mode(&mode);
|
|
||||||
dsp.set_filter(self.bandwidth_hz);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.apply_ais_channel_activity();
|
|
||||||
self.apply_ais_channel_filters();
|
self.apply_ais_channel_filters();
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
@@ -695,116 +824,6 @@ impl RigCat for SoapySdrRig {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_signal_strength<'a>(
|
|
||||||
&'a mut self,
|
|
||||||
) -> Pin<Box<dyn std::future::Future<Output = DynResult<u8>> + Send + 'a>> {
|
|
||||||
// RSSI from real device pending SDR hardware wiring; return 0 for now.
|
|
||||||
Box::pin(async move { Ok(0u8) })
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- TX / unsupported methods -------------------------------------------
|
|
||||||
|
|
||||||
fn set_ptt<'a>(
|
|
||||||
&'a mut self,
|
|
||||||
_ptt: bool,
|
|
||||||
) -> Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
|
||||||
Box::pin(async move {
|
|
||||||
Err(Box::new(RigError::not_supported("set_ptt"))
|
|
||||||
as Box<dyn std::error::Error + Send + Sync>)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn power_on<'a>(
|
|
||||||
&'a mut self,
|
|
||||||
) -> Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
|
||||||
Box::pin(async move {
|
|
||||||
Err(Box::new(RigError::not_supported("power_on"))
|
|
||||||
as Box<dyn std::error::Error + Send + Sync>)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn power_off<'a>(
|
|
||||||
&'a mut self,
|
|
||||||
) -> Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
|
||||||
Box::pin(async move {
|
|
||||||
Err(Box::new(RigError::not_supported("power_off"))
|
|
||||||
as Box<dyn std::error::Error + Send + Sync>)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_tx_power<'a>(
|
|
||||||
&'a mut self,
|
|
||||||
) -> Pin<Box<dyn std::future::Future<Output = DynResult<u8>> + Send + 'a>> {
|
|
||||||
Box::pin(async move {
|
|
||||||
Err(Box::new(RigError::not_supported("get_tx_power"))
|
|
||||||
as Box<dyn std::error::Error + Send + Sync>)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_tx_limit<'a>(
|
|
||||||
&'a mut self,
|
|
||||||
) -> Pin<Box<dyn std::future::Future<Output = DynResult<u8>> + Send + 'a>> {
|
|
||||||
Box::pin(async move {
|
|
||||||
Err(Box::new(RigError::not_supported("get_tx_limit"))
|
|
||||||
as Box<dyn std::error::Error + Send + Sync>)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_tx_limit<'a>(
|
|
||||||
&'a mut self,
|
|
||||||
_limit: u8,
|
|
||||||
) -> Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
|
||||||
Box::pin(async move {
|
|
||||||
Err(Box::new(RigError::not_supported("set_tx_limit"))
|
|
||||||
as Box<dyn std::error::Error + Send + Sync>)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn toggle_vfo<'a>(
|
|
||||||
&'a mut self,
|
|
||||||
) -> Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
|
||||||
Box::pin(async move {
|
|
||||||
Err(Box::new(RigError::not_supported("toggle_vfo"))
|
|
||||||
as Box<dyn std::error::Error + Send + Sync>)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lock<'a>(
|
|
||||||
&'a mut self,
|
|
||||||
) -> Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
|
||||||
Box::pin(async move {
|
|
||||||
Err(Box::new(RigError::not_supported("lock"))
|
|
||||||
as Box<dyn std::error::Error + Send + Sync>)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unlock<'a>(
|
|
||||||
&'a mut self,
|
|
||||||
) -> Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
|
||||||
Box::pin(async move {
|
|
||||||
Err(Box::new(RigError::not_supported("unlock"))
|
|
||||||
as Box<dyn std::error::Error + Send + Sync>)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_bandwidth<'a>(
|
|
||||||
&'a mut self,
|
|
||||||
bandwidth_hz: u32,
|
|
||||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = DynResult<()>> + Send + 'a>> {
|
|
||||||
Box::pin(async move {
|
|
||||||
tracing::debug!("SoapySdrRig: set_bandwidth -> {} Hz", bandwidth_hz);
|
|
||||||
self.bandwidth_hz = bandwidth_hz;
|
|
||||||
{
|
|
||||||
let dsps = self.pipeline.channel_dsps.read().unwrap();
|
|
||||||
if let Some(dsp_arc) = dsps.get(self.primary_channel_idx) {
|
|
||||||
dsp_arc.lock().unwrap().set_filter(bandwidth_hz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.apply_ais_channel_filters();
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_wfm_stereo<'a>(
|
fn set_wfm_stereo<'a>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
@@ -887,9 +906,4 @@ impl RigCat for SoapySdrRig {
|
|||||||
fn get_vchan_rds(&self) -> Option<Vec<VchanRdsEntry>> {
|
fn get_vchan_rds(&self) -> Option<Vec<VchanRdsEntry>> {
|
||||||
Some(self.channel_manager.rds_snapshots())
|
Some(self.channel_manager.rds_snapshots())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Override: this backend provides demodulated PCM audio.
|
|
||||||
fn as_audio_source(&self) -> Option<&dyn AudioSource> {
|
|
||||||
Some(self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user