MCPcopy Create free account
hub / github.com/aethersdr/AetherSDR / wireExternalControllers

Method wireExternalControllers

src/gui/MainWindow_Controllers.cpp:2205–2841  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

2203// routing, and the RC-28 deferred press/hold logic (#3323).
2204
2205void MainWindow::wireExternalControllers()
2206{
2207 // ── External controllers run on a dedicated worker thread (#502) ────
2208 // FlexControl, SerialPort, and MIDI controllers are created on the
2209 // worker thread so their I/O (serial port, RtMidi callbacks, poll timers)
2210 // never competes with paintEvent. Signals auto-queue to main thread.
2211 m_extCtrlThread = new QThread(this);
2212 m_extCtrlThread->setObjectName("ExtControllers");
2213
2214 // Shared FlexControl coalescing for the USB device and the virtual
2215 // FlexControl dialog. The timer stays on the main thread because it
2216 // reads the active slice and updates UI state.
2217 m_flexCoalesceTimer.setSingleShot(true);
2218 m_flexCoalesceTimer.setInterval(20);
2219 connect(&m_flexCoalesceTimer, &QTimer::timeout, this, [this]() {
2220 if (m_flexTargetMhz < 0.0) return;
2221 auto* s = activeSlice();
2222 if (!s) { m_flexTargetMhz = -1.0; return; }
2223 if (s->isLocked()) {
2224 s->notifyTuneBlockedByLock();
2225 // Drop queued tuning so unlock does not replay stale wheel input.
2226 m_flexTargetMhz = -1.0;
2227 return;
2228 }
2229 const double target = m_flexTargetMhz;
2230 applyTuneRequest(s, target, TuneIntent::IncrementalTune, "flexcontrol");
2231 });
2232
2233#ifdef HAVE_SERIALPORT
2234 m_serialPort = new SerialPortController; // no parent — moved to thread
2235 m_serialPort->moveToThread(m_extCtrlThread);
2236 m_flexControl = new FlexControlManager;
2237 m_flexControl->moveToThread(m_extCtrlThread);
2238
2239 // Serial port signals (auto-queued from worker → main)
2240 connect(m_serialPort, &SerialPortController::externalPttChanged,
2241 this, [this](bool active) {
2242 m_radioModel.setTransmit(active);
2243 });
2244 connect(m_serialPort, &SerialPortController::cwKeyChanged,
2245 this, [this](bool down) {
2246 m_radioModel.sendCwKey(down);
2247 });
2248 connect(m_serialPort, &SerialPortController::cwPaddleChanged,
2249 this, [this](bool dit, bool dah) {
2250 m_lastCwPaddleTraceId.store(0, std::memory_order_relaxed);
2251 m_lastCwPaddleSourceMs.store(0, std::memory_order_relaxed);
2252 // When the local iambic keyer is running, feed it the raw paddle
2253 // state — it forwards to the radio AND drives the sidetone gate
2254 // directly. Otherwise pass straight through to the radio (radio's
2255 // RF iambic is still authoritative for the on-air signal).
2256 if (m_iambicKeyer && m_iambicKeyer->isRunning()) {
2257 m_iambicKeyer->setPaddleState(dit, dah);
2258 } else {
2259 m_radioModel.sendCwPaddle(dit, dah);
2260 }
2261 });
2262

Callers

nothing calls this directly

Calls 15

cwTraceNowMsFunction · 0.85
isCwMomentaryActionIdFunction · 0.85
tmate2KeyDefaultActionFunction · 0.85
tmate2PushDefaultActionFunction · 0.85
setTransmitMethod · 0.80
sendCwKeyMethod · 0.80
setPaddleStateMethod · 0.80
sendCwPaddleMethod · 0.80
isTMate2Method · 0.80
reflectButtonPressMethod · 0.80

Tested by

no test coverage detected