void SDRPostThread::updateActiveDemodulators() { // In range? std::vector<DemodulatorInstance *>::iterator demod_i; nRunDemods = 0; long long centerFreq = wxGetApp().getFrequency(); for (demod_i = demodulators.begin(); demod_i != demodulators.end(); demod_i++) { DemodulatorInstance *demod = *demod_i; DemodulatorThreadInputQueue *demodQueue = demod->getIQInputDataPipe(); // not in range? if (demod->isDeltaLock()) { if (demod->getFrequency() != centerFreq + demod->getDeltaLockOfs()) { demod->setFrequency(centerFreq + demod->getDeltaLockOfs()); demod->updateLabel(demod->getFrequency()); demod->setFollow(false); demod->setTracking(false); } } if (abs(frequency - demod->getFrequency()) > (sampleRate / 2)) { // deactivate if active if (demod->isActive() && !demod->isFollow() && !demod->isTracking()) { demod->setActive(false); DemodulatorThreadIQData *dummyDataOut = new DemodulatorThreadIQData; dummyDataOut->frequency = frequency; dummyDataOut->sampleRate = sampleRate; demodQueue->push(dummyDataOut); } // follow if follow mode if (demod->isFollow() && centerFreq != demod->getFrequency()) { wxGetApp().setFrequency(demod->getFrequency()); demod->setFollow(false); } } else if (!demod->isActive()) { // in range, activate if not activated demod->setActive(true); if (wxGetApp().getDemodMgr().getLastActiveDemodulator() == NULL) { wxGetApp().getDemodMgr().setActiveDemodulator(demod); } } if (!demod->isActive()) { continue; } // Add to the current run if (nRunDemods == runDemods.size()) { runDemods.push_back(demod); demodChannel.push_back(-1); } else { runDemods[nRunDemods] = demod; demodChannel[nRunDemods] = -1; } nRunDemods++; } }
void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) { InteractiveCanvas::OnMouseMoved(event); DemodulatorInstance *demod = wxGetApp().getDemodMgr().getActiveDemodulator(); if (mouseTracker.mouseDown()) { if (demod == NULL) { return; } if (dragState == WF_DRAG_BANDWIDTH_LEFT || dragState == WF_DRAG_BANDWIDTH_RIGHT) { int bwDiff = (int) (mouseTracker.getDeltaMouseX() * (float) getBandwidth()) * 2; if (dragState == WF_DRAG_BANDWIDTH_LEFT) { bwDiff = -bwDiff; } int currentBW = dragBW; currentBW = currentBW + bwDiff; if (currentBW > CHANNELIZER_RATE_MAX) { currentBW = CHANNELIZER_RATE_MAX; } if (currentBW < MIN_BANDWIDTH) { currentBW = MIN_BANDWIDTH; } demod->setBandwidth(currentBW); dragBW = currentBW; } if (dragState == WF_DRAG_FREQUENCY) { long long bwTarget = getFrequencyAt(mouseTracker.getMouseX()) - dragOfs; long long currentFreq = demod->getFrequency(); long long bwDiff = bwTarget - currentFreq; int snap = wxGetApp().getFrequencySnap(); if (snap > 1) { bwDiff = roundf((float)bwDiff/(float)snap)*snap; } if (bwDiff) { demod->setFrequency(currentFreq + bwDiff); if (demod->isDeltaLock()) { demod->setDeltaLockOfs(demod->getFrequency() - wxGetApp().getFrequency()); } currentFreq = demod->getFrequency(); demod->updateLabel(currentFreq); } } } else if (mouseTracker.mouseRightDown()) { mouseZoom = mouseZoom + ((1.0 - (mouseTracker.getDeltaMouseY() * 4.0)) - mouseZoom) * 0.1; } else { updateHoverState(); } }
void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { InteractiveCanvas::OnMouseReleased(event); wxGetApp().getDemodMgr().updateLastState(); bool isNew = shiftDown || (wxGetApp().getDemodMgr().getLastActiveDemodulator() == NULL) || (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive()); mouseTracker.setVertDragLock(false); mouseTracker.setHorizDragLock(false); DemodulatorInstance *demod = isNew?NULL:wxGetApp().getDemodMgr().getLastActiveDemodulator(); DemodulatorInstance *activeDemod = isNew?NULL:wxGetApp().getDemodMgr().getActiveDemodulator(); DemodulatorMgr *mgr = &wxGetApp().getDemodMgr(); if (mouseTracker.getOriginDeltaMouseX() == 0 && mouseTracker.getOriginDeltaMouseY() == 0) { float pos = mouseTracker.getMouseX(); long long input_center_freq = getCenterFrequency(); long long freqTarget = input_center_freq - (long long) (0.5 * (float) getBandwidth()) + (long long) ((float) pos * (float) getBandwidth()); long long demodFreq = demod?demod->getFrequency():freqTarget; long long bwDiff = freqTarget - demodFreq; long long freq = demodFreq; int snap = wxGetApp().getFrequencySnap(); if (snap > 1) { if (demod) { bwDiff = roundf((double)bwDiff/(double)snap)*snap; freq += bwDiff; } else { freq = roundl((long double)freq/(double)snap)*snap; } } else { freq += bwDiff; } if (dragState == WF_DRAG_NONE) { if (!isNew && wxGetApp().getDemodMgr().getDemodulators().size()) { mgr->updateLastState(); demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); } else { isNew = true; demod = wxGetApp().getDemodMgr().newThread(); demod->setFrequency(freq); demod->setDemodulatorType(mgr->getLastDemodulatorType()); demod->setBandwidth(mgr->getLastBandwidth()); demod->setSquelchLevel(mgr->getLastSquelchLevel()); demod->setSquelchEnabled(mgr->isLastSquelchEnabled()); demod->setGain(mgr->getLastGain()); demod->setMuted(mgr->isLastMuted()); if (mgr->getLastDeltaLock()) { demod->setDeltaLock(true); demod->setDeltaLockOfs(wxGetApp().getFrequency()-freq); } else { demod->setDeltaLock(false); } demod->writeModemSettings(mgr->getLastModemSettings(mgr->getLastDemodulatorType())); demod->run(); wxGetApp().bindDemodulator(demod); } if (!demod) { dragState = WF_DRAG_NONE; return; } demod->updateLabel(freq); demod->setFrequency(freq); if (demod->isDeltaLock()) { demod->setDeltaLockOfs(demod->getFrequency() - wxGetApp().getFrequency()); } if (isNew) { setStatusText("New demodulator at frequency: %s", freq); } else { setStatusText("Moved demodulator to frequency: %s", freq); } wxGetApp().getDemodMgr().setActiveDemodulator(demod, false); SetCursor(wxCURSOR_SIZING); nextDragState = WF_DRAG_FREQUENCY; mouseTracker.setVertDragLock(true); mouseTracker.setHorizDragLock(false); } else { if (activeDemod) { wxGetApp().getDemodMgr().setActiveDemodulator(activeDemod, false); mgr->updateLastState(); activeDemod->setTracking(true); nextDragState = WF_DRAG_FREQUENCY; } else { nextDragState = WF_DRAG_NONE; } } } else if (dragState == WF_DRAG_RANGE) { float width = mouseTracker.getOriginDeltaMouseX(); float pos; std::string last_type = mgr->getLastDemodulatorType(); if (last_type == "LSB" || last_type == "USB") { float pos1 = mouseTracker.getOriginMouseX(); float pos2 = mouseTracker.getMouseX(); if (pos2 < pos1) { float tmp = pos1; pos1 = pos2; pos2 = tmp; } pos = (last_type == "LSB")?pos2:pos1; width *= 2; } else { pos = mouseTracker.getOriginMouseX() + width / 2.0; } long long input_center_freq = getCenterFrequency(); long long freq = input_center_freq - (long long) (0.5 * (float) getBandwidth()) + (long long) ((float) pos * (float) getBandwidth()); unsigned int bw = (unsigned int) (fabs(width) * (float) getBandwidth()); if (bw < MIN_BANDWIDTH) { bw = MIN_BANDWIDTH; } if (!bw) { dragState = WF_DRAG_NONE; return; } int snap = wxGetApp().getFrequencySnap(); if (snap > 1) { freq = roundl((long double)freq/(double)snap)*snap; } if (!isNew && wxGetApp().getDemodMgr().getDemodulators().size()) { mgr->updateLastState(); demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); } else { demod = wxGetApp().getDemodMgr().newThread(); demod->setFrequency(freq); demod->setDemodulatorType(mgr->getLastDemodulatorType()); demod->setBandwidth(bw); demod->setSquelchLevel(mgr->getLastSquelchLevel()); demod->setSquelchEnabled(mgr->isLastSquelchEnabled()); demod->setGain(mgr->getLastGain()); demod->setMuted(mgr->isLastMuted()); if (mgr->getLastDeltaLock()) { demod->setDeltaLock(true); demod->setDeltaLockOfs(wxGetApp().getFrequency()-freq); } else { demod->setDeltaLock(false); } demod->writeModemSettings(mgr->getLastModemSettings(mgr->getLastDemodulatorType())); demod->run(); wxGetApp().bindDemodulator(demod); } if (demod == NULL) { dragState = WF_DRAG_NONE; return; } setStatusText("New demodulator at frequency: %s", freq); demod->updateLabel(freq); demod->setFrequency(freq); demod->setBandwidth(bw); mgr->setActiveDemodulator(demod, false); mgr->updateLastState(); } dragState = WF_DRAG_NONE; }
void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) { InteractiveCanvas::OnMouseMoved(event); DemodulatorInstance *demod = wxGetApp().getDemodMgr().getActiveDemodulator(); if (mouseTracker.mouseDown()) { if (demod == NULL) { return; } if (dragState == WF_DRAG_BANDWIDTH_LEFT || dragState == WF_DRAG_BANDWIDTH_RIGHT) { int bwDiff = (int) (mouseTracker.getDeltaMouseX() * (float) getBandwidth()) * 2; if (dragState == WF_DRAG_BANDWIDTH_LEFT) { bwDiff = -bwDiff; } int currentBW = dragBW; currentBW = currentBW + bwDiff; if (currentBW > CHANNELIZER_RATE_MAX) { currentBW = CHANNELIZER_RATE_MAX; } if (currentBW < MIN_BANDWIDTH) { currentBW = MIN_BANDWIDTH; } demod->setBandwidth(currentBW); dragBW = currentBW; } if (dragState == WF_DRAG_FREQUENCY) { long long bwTarget = getFrequencyAt(mouseTracker.getMouseX()) - dragOfs; long long currentFreq = demod->getFrequency(); long long bwDiff = bwTarget - currentFreq; int snap = wxGetApp().getFrequencySnap(); if (snap > 1) { bwDiff = roundf((float)bwDiff/(float)snap)*snap; } if (bwDiff) { demod->setFrequency(currentFreq + bwDiff); currentFreq = demod->getFrequency(); demod->updateLabel(currentFreq); } } } else if (mouseTracker.mouseRightDown()) { mouseZoom = mouseZoom + ((1.0 - (mouseTracker.getDeltaMouseY() * 4.0)) - mouseZoom) * 0.1; } else { long long freqPos = getFrequencyAt(mouseTracker.getMouseX()); std::vector<DemodulatorInstance *> *demodsHover = wxGetApp().getDemodMgr().getDemodulatorsAt(freqPos, 15000); wxGetApp().getDemodMgr().setActiveDemodulator(NULL); if (altDown) { nextDragState = WF_DRAG_RANGE; mouseTracker.setVertDragLock(true); mouseTracker.setHorizDragLock(false); if (shiftDown) { setStatusText("Click and drag to create a new demodulator by range."); } else { setStatusText("Click and drag to set the current demodulator range."); } } else if (demodsHover->size() && !shiftDown) { long near_dist = getBandwidth(); DemodulatorInstance *activeDemodulator = NULL; for (int i = 0, iMax = demodsHover->size(); i < iMax; i++) { DemodulatorInstance *demod = (*demodsHover)[i]; long long freqDiff = demod->getFrequency() - freqPos; long halfBw = (demod->getBandwidth() / 2); long long currentBw = getBandwidth(); long long globalBw = wxGetApp().getSampleRate(); long dist = abs(freqDiff); double bufferBw = 10000.0 * ((double)currentBw / (double)globalBw); double maxDist = ((double)halfBw + bufferBw); if ((double)dist <= maxDist) { if ((freqDiff > 0 && demod->getDemodulatorType() == "USB") || (freqDiff < 0 && demod->getDemodulatorType() == "LSB")) { continue; } if (dist < near_dist) { activeDemodulator = demod; near_dist = dist; } long edge_dist = abs(halfBw - dist); if (edge_dist < near_dist) { activeDemodulator = demod; near_dist = edge_dist; } } } if (activeDemodulator == NULL) { nextDragState = WF_DRAG_NONE; SetCursor(wxCURSOR_CROSS); return; } wxGetApp().getDemodMgr().setActiveDemodulator(activeDemodulator); long long freqDiff = activeDemodulator->getFrequency() - freqPos; if (abs(freqDiff) > (activeDemodulator->getBandwidth() / 3)) { if (freqDiff > 0) { if (activeDemodulator->getDemodulatorType() != "USB") { nextDragState = WF_DRAG_BANDWIDTH_LEFT; SetCursor(wxCURSOR_SIZEWE); } } else { if (activeDemodulator->getDemodulatorType() != "LSB") { nextDragState = WF_DRAG_BANDWIDTH_RIGHT; SetCursor(wxCURSOR_SIZEWE); } } mouseTracker.setVertDragLock(true); mouseTracker.setHorizDragLock(false); setStatusText("Click and drag to change demodulator bandwidth. SPACE for direct frequency input. M for mute, D to delete, C to center."); } else { SetCursor(wxCURSOR_SIZING); nextDragState = WF_DRAG_FREQUENCY; mouseTracker.setVertDragLock(true); mouseTracker.setHorizDragLock(false); setStatusText("Click and drag to change demodulator frequency; SPACE for direct input. M for mute, D to delete, C to center."); } } else { SetCursor(wxCURSOR_CROSS); nextDragState = WF_DRAG_NONE; if (shiftDown) { setStatusText("Click to create a new demodulator or hold ALT to drag range, SPACE for direct center frequency input."); } else { setStatusText( "Click to move active demodulator frequency or hold ALT to drag range; hold SHIFT to create new. Right drag or wheel to Zoom. Arrow keys to navigate/zoom, C to center."); } } delete demodsHover; } }
bool AppFrame::loadSession(std::string fileName) { DataTree l; if (!l.LoadFromFileXML(fileName)) { return false; } wxGetApp().getDemodMgr().terminateAll(); try { DataNode *header = l.rootNode()->getNext("header"); std::string version(*header->getNext("version")); long long center_freq = *header->getNext("center_freq"); std::cout << "Loading " << version << " session file" << std::endl; std::cout << "\tCenter Frequency: " << center_freq << std::endl; wxGetApp().setFrequency(center_freq); DataNode *demodulators = l.rootNode()->getNext("demodulators"); while (demodulators->hasAnother("demodulator")) { DataNode *demod = demodulators->getNext("demodulator"); if (!demod->hasAnother("bandwidth") || !demod->hasAnother("frequency")) { continue; } long bandwidth = *demod->getNext("bandwidth"); long long freq = *demod->getNext("frequency"); int type = demod->hasAnother("type") ? *demod->getNext("type") : DEMOD_TYPE_FM; float squelch_level = demod->hasAnother("squelch_level") ? (float) *demod->getNext("squelch_level") : 0; int squelch_enabled = demod->hasAnother("squelch_enabled") ? (int) *demod->getNext("squelch_enabled") : 0; int stereo = demod->hasAnother("stereo") ? (int) *demod->getNext("stereo") : 0; std::string output_device = demod->hasAnother("output_device") ? string(*(demod->getNext("output_device"))) : ""; float gain = demod->hasAnother("gain") ? (float) *demod->getNext("gain") : 1.0; DemodulatorInstance *newDemod = wxGetApp().getDemodMgr().newThread(); newDemod->setDemodulatorType(type); newDemod->setBandwidth(bandwidth); newDemod->setFrequency(freq); newDemod->setGain(gain); newDemod->updateLabel(freq); if (squelch_enabled) { newDemod->setSquelchEnabled(true); newDemod->setSquelchLevel(squelch_level); } if (stereo) { newDemod->setStereo(true); } bool found_device = false; std::map<int, RtAudio::DeviceInfo>::iterator i; for (i = outputDevices.begin(); i != outputDevices.end(); i++) { if (i->second.name == output_device) { newDemod->setOutputDevice(i->first); found_device = true; } } if (!found_device) { std::cout << "\tWarning: named output device '" << output_device << "' was not found. Using default output."; } newDemod->run(); newDemod->setActive(false); wxGetApp().bindDemodulator(newDemod); std::cout << "\tAdded demodulator at frequency " << freq << " type " << type << std::endl; std::cout << "\t\tBandwidth: " << bandwidth << std::endl; std::cout << "\t\tSquelch Level: " << squelch_level << std::endl; std::cout << "\t\tSquelch Enabled: " << (squelch_enabled ? "true" : "false") << std::endl; std::cout << "\t\tStereo: " << (stereo ? "true" : "false") << std::endl; std::cout << "\t\tOutput Device: " << output_device << std::endl; } } catch (DataInvalidChildException &e) { std::cout << e.what() << std::endl; return false; } catch (DataTypeMismatchException &e) { std::cout << e.what() << std::endl; return false; } currentSessionFile = fileName; std::string filePart = fileName.substr(fileName.find_last_of(filePathSeparator) + 1); GetStatusBar()->SetStatusText(wxString::Format(wxT("Loaded session file: %s"), currentSessionFile.c_str())); SetTitle(wxString::Format(wxT("%s: %s"), CUBICSDR_TITLE, filePart.c_str())); return true; }