10 KiB
Configuration System
This document describes CubicSDR's configuration persistence, the AppConfig/DeviceConfig classes, session management, and the DataTree serialization format.
Overview
CubicSDR persists its configuration using XML files stored in the platform's standard user data directory. The configuration system is built on DataTree, a hierarchical data structure backed by TinyXML.
AppConfig (global settings)
|
+-- DeviceConfig (per-device settings, keyed by device ID)
|
+-- Manual device definitions
+-- Hamlib rig settings (optional)
SessionMgr (session state)
|
+-- Demodulator instances
+-- View state
File Locations
Config Directory
AppConfig::getConfigDir() returns the platform-specific user data directory via wxStandardPaths::Get().GetUserDataDir():
| Platform | Path |
|---|---|
| Windows | %APPDATA%/CubicSDR |
| macOS | ~/Library/Application Support/CubicSDR |
| Linux | ~/.cubicsdr |
The directory is created automatically if it doesn't exist.
Config Files
| File | Purpose |
|---|---|
config.xml |
Default configuration file |
config-{name}.xml |
Named configuration (for -c command line option) |
bookmarks.xml |
Bookmark data |
bookmarks.xml.backup |
Bookmark backup |
bookmarks.xml.lastloaded |
Last successfully loaded bookmarks |
AppConfig (src/AppConfig.h)
Global application configuration. Singleton accessed via wxGetApp().getConfig().
Window Settings
| Property | Type | Config Key | Description |
|---|---|---|---|
winX, winY |
int |
window/x, window/y |
Window position |
winW, winH |
int |
window/w, window/h |
Window size |
winMax |
bool |
window/max |
Maximized state |
showTips |
bool |
window/tips |
Show tooltips |
modemPropsCollapsed |
bool |
window/modemprops_collapsed |
Modem properties panel collapsed |
perfMode |
PerfModeEnum |
window/perf_mode |
Performance mode (0=low, 1=normal, 2=high) |
Display Settings
| Property | Type | Config Key | Default | Description |
|---|---|---|---|---|
themeId |
int |
window/theme |
0 | Color theme index |
fontScale |
int |
window/font_scale |
0 | Font scale (0=normal, 1=medium, 2=large) |
snap |
long long |
window/snap |
0 | Frequency snap value in Hz |
centerFreq |
long long |
window/center_freq |
0 | Center frequency |
waterfallLinesPerSec |
int |
window/waterfall_lps |
30 | Waterfall refresh rate |
spectrumAvgSpeed |
float |
window/spectrum_avg |
— | Spectrum averaging speed |
dbOffset |
int |
window/db_offset |
0 | dB display offset |
Layout Settings
| Property | Type | Config Key | Description |
|---|---|---|---|
mainSplit |
float |
window/main_split |
Main splitter position |
visSplit |
float |
window/vis_split |
Visualization splitter position |
bookmarkSplit |
float |
window/bookmark_split |
Bookmark panel splitter position |
bookmarksVisible |
bool |
window/bookmark_visible |
Bookmark panel visibility |
Recording Settings
| Property | Type | Config Key | Description |
|---|---|---|---|
recordingPath |
string |
recording/path |
Output directory for recordings |
recordingSquelchOption |
int |
recording/squelch |
Squelch handling (0=silence, 1=skip, 2=always) |
recordingFileTimeLimitSeconds |
int |
recording/file_time_limit |
Max file duration in seconds (0=unlimited) |
Hamlib Settings (conditional on USE_HAMLIB)
| Property | Type | Config Key | Description |
|---|---|---|---|
rigEnabled |
bool |
rig/enabled |
Hamlib enabled |
rigModel |
int |
rig/model |
Hamlib rig model ID |
rigRate |
int |
rig/rate |
Serial baud rate |
rigPort |
string |
rig/port |
Serial port path |
rigControlMode |
bool |
rig/control |
Control rig frequency |
rigFollowMode |
bool |
rig/follow |
Follow rig frequency |
rigCenterLock |
bool |
rig/center_lock |
Lock center frequency to rig |
rigFollowModem |
bool |
rig/follow_modem |
Follow active modem frequency |
Manual Devices
Stored as a list under manual_devices/device:
<manual_devices>
<device>
<factory>remote</factory>
<params>driver=rtlsdr</params>
</device>
</manual_devices>
DeviceConfig (src/AppConfig.h)
Per-device configuration, keyed by device ID string. Stored under devices/device in the config XML.
Properties
| Property | Type | Config Key | Description |
|---|---|---|---|
deviceId |
string |
id |
Device identifier |
deviceName |
string |
name |
Human-readable device name |
ppm |
int |
ppm |
Parts per million frequency correction |
offset |
long long |
offset |
Frequency offset in Hz |
sampleRate |
long |
sample_rate |
Configured sample rate |
agcMode |
bool |
agc_mode |
AGC enabled |
antennaName |
string |
antenna |
Selected antenna port |
streamOpts |
map<string,string> |
streamOpts/* |
SoapySDR stream options |
settings |
map<string,string> |
settings/* |
Driver-specific settings |
gains |
map<string,float> |
gains/gain/* |
Per-stage gain values |
rigIF |
map<int,long long> |
rig_ifs/rig_if/* |
Rig IF frequency per model |
Device Config XML Structure
<device>
<id>remote=0:driver=rtlsdr</id>
<name>RTL-SDR</name>
<ppm>0</ppm>
<offset>0</offset>
<sample_rate>2400000</sample_rate>
<agc_mode>1</agc_mode>
<antenna>antenna0</antenna>
<streamOpts>
<buflen>16384</buflen>
</streamOpts>
<settings>
<bias_tee>0</bias_tee>
</settings>
<gains>
<gain>
<id>LNA</id>
<value>40.0</value>
</gain>
</gains>
<rig_ifs>
<rig_if>
<model>1</model>
<sdr_if>145000000</sdr_if>
</rig_if>
</rig_ifs>
</device>
Config File Format
Root Structure
<cubicsdr_config>
<window>...</window>
<recording>...</recording>
<devices>...</devices>
<manual_devices>...</manual_devices>
<rig>...</rig>
</cubicsdr_config>
Save/Load Lifecycle
Save (AppConfig::save()):
- Create a
DataTreewith root node namedcubicsdr_config - Populate window, recording, device, manual device, and rig nodes
- Get config file path from
getConfigFileName() - Call
DataTree::SaveToFileXML()
Load (AppConfig::load()):
- Determine config file path
- If named config doesn't exist, copy from default
config.xml - Call
DataTree::LoadFromFileXML() - Parse each section: window, recording, devices, manual_devices, rig
- Missing sections use defaults
Named Configurations
When launched with -c {name}, CubicSDR uses config-{name}.xml instead of config.xml. This allows multiple independent configurations.
Session Management (src/SessionMgr.h)
Sessions capture the complete demodulator state for save/restore.
Session File Format
<cubicsdr_session>
<header>
<version>0.2.8</version>
<center_freq>145000000</center_freq>
<sample_rate>2400000</sample_rate>
<solo_mode>0</solo_mode>
<view_state>
<center_freq>145000000</center_freq>
<bandwidth>2400000</bandwidth>
</view_state>
</header>
<demodulators>
<demodulator>
<frequency>145300000</frequency>
<bandwidth>12500</bandwidth>
<type>NBFM</type>
...
</demodulator>
<!-- more demodulators -->
</demodulators>
</cubicsdr_session>
Save Flow (SessionMgr::saveSession())
- Create
DataTreewith rootcubicsdr_session - Write header: version, center frequency, sample rate, solo mode, view state
- Iterate all demodulator instances, call
DemodulatorMgr::saveInstance()for each - Ensure filename ends in
.xml - Save to file
Load Flow (SessionMgr::loadSession())
- Load
DataTreefrom file - Validate root node name is
cubicsdr_session - Terminate all existing demodulators
- Parse header: version, sample rate (clamped to device limits), solo mode
- Parse demodulators: create each via
DemodulatorMgr::loadInstance(), callrun(), set active - Restore center frequency and view state
- Set active demodulator
DataTree (src/util/DataTree.h)
The serialization framework underlying all configuration and session files.
Architecture
DataTree
|
+-- rootNode: DataNode (named, has children)
|
+-- DataElement (typed value: char, int, float, double, string, wstring, vectors)
|
+-- child DataNodes (recursive tree)
DataNode Operations
| Method | Purpose |
|---|---|
setName() / getName() |
Node name (maps to XML element name) |
newChild(name) |
Create and append a child node |
child(index) |
Get child by index |
child(name) |
Get first child by name |
numChildren() |
Number of children |
hasAnother(name) |
Check if another child with name exists (iterator) |
getNext(name) |
Get next child with name (iterator) |
element() |
Get the DataElement value |
DataElement Types
Supported scalar types:
char,short,int,long,long longfloat,doublestd::string,std::wstring
Supported vector types:
std::vector<int>,std::vector<float>,std::vector<double>
XML Serialization
DataTree::SaveToFileXML() and DataTree::LoadFromFileXML() use TinyXML for XML I/O. The XML structure maps directly to the DataNode tree:
- Element names →
DataNode::getName() - Element text content →
DataElementvalue - Child elements → child
DataNodes
Thread Safety
DataTree and DataNode are not thread-safe. Config save/load happens on the main thread during UI events. The DeviceConfig class uses busy_lock (a std::mutex) to protect concurrent access to individual device config data.
Config Save Triggers
- On exit:
CubicSDR::OnExit()callsconfig->save() - On window move/resize: debounced save of window geometry
- On setting change: various UI actions update config immediately
- Session save: explicit user action via File menu