Merge pull request #78 from cjcliffe/keyboard_freq_input

Keyboard frequency input
This commit is contained in:
Charles J. Cliffe 2015-05-10 20:24:44 -04:00
commit fdc45b32ef
7 changed files with 213 additions and 20 deletions

View File

@ -227,6 +227,7 @@ SET (cubicsdr_sources
src/CubicSDR.cpp
src/AppFrame.cpp
src/AppConfig.cpp
src/FrequencyDialog.cpp
src/sdr/SDRThread.cpp
src/sdr/SDRPostThread.cpp
src/demod/DemodulatorPreThread.cpp
@ -269,6 +270,7 @@ SET (cubicsdr_headers
src/CubicSDR.h
src/AppFrame.h
src/AppConfig.h
src/FrequencyDialog.h
src/sdr/SDRThread.h
src/sdr/SDRPostThread.h
src/demod/DemodulatorPreThread.h

View File

@ -13,7 +13,7 @@
#endif
#include "CubicSDR.h"
#include "AppFrame.h"
#include "FrequencyDialog.h"
#ifdef _OSX_APP_
#include "CoreFoundation/CoreFoundation.h"
@ -92,7 +92,7 @@ bool CubicSDR::OnInit() {
t_PostSDR = new std::thread(&SDRPostThread::threadMain, sdrPostThread);
t_SDR = new std::thread(&SDRThread::threadMain, sdrThread);
AppFrame *appframe = new AppFrame();
appframe = new AppFrame();
#ifdef __APPLE__
int main_policy;
@ -271,3 +271,9 @@ int CubicSDR::getPPM() {
return ppm;
}
void CubicSDR::showFrequencyInput() {
FrequencyDialog fdialog(appframe, -1, demodMgr.getActiveDemodulator()?_("Set Demodulator Frequency"):_("Set Center Frequency"), demodMgr.getActiveDemodulator(), wxPoint(-100,-100), wxSize(320, 75 ));
fdialog.ShowModal();
}

View File

@ -15,6 +15,7 @@
#include "AudioThread.h"
#include "DemodulatorMgr.h"
#include "AppConfig.h"
#include "AppFrame.h"
#define NUM_DEMODULATORS 1
@ -56,7 +57,10 @@ public:
void setPPM(int ppm_in);
int getPPM();
void showFrequencyInput();
private:
AppFrame *appframe;
AppConfig config;
PrimaryGLContext *m_glContext;
std::vector<SDRDeviceInfo *> devs;

142
src/FrequencyDialog.cpp Normal file
View File

@ -0,0 +1,142 @@
#include "FrequencyDialog.h"
#include "wx/clipbrd.h"
#include <sstream>
#include <iomanip>
#include "CubicSDR.h"
wxBEGIN_EVENT_TABLE(FrequencyDialog, wxDialog) EVT_CHAR_HOOK(FrequencyDialog::OnChar)
wxEND_EVENT_TABLE()
FrequencyDialog::FrequencyDialog(wxWindow * parent, wxWindowID id, const wxString & title, DemodulatorInstance *demod, const wxPoint & position,
const wxSize & size, long style) :
wxDialog(parent, id, title, position, size, style) {
wxString freqStr;
activeDemod = demod;
if (activeDemod) {
freqStr = frequencyToStr(activeDemod->getFrequency());
} else {
freqStr = frequencyToStr(wxGetApp().getFrequency());
}
dialogText = new wxTextCtrl(this, wxID_FREQ_INPUT, freqStr, wxPoint(6, 1), wxSize(size.GetWidth() - 20, size.GetHeight() - 70),
wxTE_PROCESS_ENTER);
dialogText->SetFont(wxFont(20, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD));
Centre();
dialogText->SetSelection(-1, -1);
}
std::string& FrequencyDialog::filterChars(std::string& s, const std::string& allowed) {
s.erase(remove_if(s.begin(), s.end(), [&allowed](const char& c) {
return allowed.find(c) == std::string::npos;
}), s.end());
return s;
}
std::string FrequencyDialog::frequencyToStr(long long freq) {
long double freqTemp;
freqTemp = freq;
std::string suffix("");
std::stringstream freqStr;
if (freqTemp >= 1.0e9) {
freqTemp /= 1.0e9;
freqStr << std::setprecision(10);
suffix = std::string("GHz");
} else if (freqTemp >= 1.0e6) {
freqTemp /= 1.0e6;
freqStr << std::setprecision(7);
suffix = std::string("MHz");
} else if (freqTemp >= 1.0e3) {
freqTemp /= 1.0e3;
freqStr << std::setprecision(4);
suffix = std::string("KHz");
}
freqStr << freqTemp;
freqStr << suffix;
return freqStr.str();
}
long long FrequencyDialog::strToFrequency(std::string freqStr) {
std::string filterStr = filterChars(freqStr, std::string("0123456789.MKGmkg"));
int numLen = filterStr.find_first_not_of("0123456789.");
if (numLen == std::string::npos) {
numLen = freqStr.length();
}
std::string numPartStr = freqStr.substr(0, numLen);
std::string suffixStr = freqStr.substr(numLen);
std::stringstream numPartStream;
numPartStream.str(numPartStr);
long double freqTemp = 0;
numPartStream >> freqTemp;
if (suffixStr.length()) {
if (suffixStr.find_first_of("Gg") != std::string::npos) {
freqTemp *= 1.0e9;
} else if (suffixStr.find_first_of("Mm") != std::string::npos) {
freqTemp *= 1.0e6;
} else if (suffixStr.find_first_of("Kk") != std::string::npos) {
freqTemp *= 1.0e3;
}
} else if (numPartStr.find_first_of(".") != std::string::npos) {
freqTemp *= 1.0e6;
}
return (long long) freqTemp;
}
void FrequencyDialog::OnChar(wxKeyEvent& event) {
wxChar c = event.GetKeyCode();
long long freq;
switch (c) {
case WXK_RETURN:
case WXK_NUMPAD_ENTER:
// Do Stuff
freq = strToFrequency(dialogText->GetValue().ToStdString());
if (activeDemod) {
activeDemod->setTracking(true);
activeDemod->setFollow(true);
activeDemod->setFrequency(freq);
activeDemod->updateLabel(freq);
} else {
wxGetApp().setFrequency(freq);
}
Close();
break;
case WXK_ESCAPE:
Close();
break;
}
std::string allowed("0123456789.MKGHZmkghz");
if (allowed.find_first_of(c) != std::string::npos || c == WXK_DELETE || c == WXK_BACK || c == WXK_NUMPAD_DECIMAL
|| (c >= WXK_NUMPAD0 && c <= WXK_NUMPAD9)) {
event.DoAllowNextEvent();
} else if (event.ControlDown() && c == 'V') {
// Alter clipboard contents to remove unwanted chars
wxTheClipboard->Open();
wxTextDataObject data;
wxTheClipboard->GetData(data);
std::string clipText = data.GetText().ToStdString();
std::string pasteText = filterChars(clipText, std::string(allowed));
wxTheClipboard->SetData(new wxTextDataObject(pasteText));
wxTheClipboard->Close();
event.Skip();
} else if (c == WXK_RIGHT || c == WXK_LEFT || event.ControlDown()) {
event.Skip();
}
}

32
src/FrequencyDialog.h Normal file
View File

@ -0,0 +1,32 @@
#pragma once
#include "wx/dialog.h"
#include "wx/textctrl.h"
#include "wx/string.h"
#include "wx/button.h"
#include "DemodulatorInstance.h"
#define wxID_FREQ_INPUT 3001
class FrequencyDialog: public wxDialog
{
public:
FrequencyDialog ( wxWindow * parent, wxWindowID id, const wxString & title,
DemodulatorInstance *demod = NULL,
const wxPoint & pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize,
long style = wxDEFAULT_DIALOG_STYLE );
wxTextCtrl * dialogText;
long long strToFrequency(std::string freqStr);
std::string frequencyToStr(long long freq);
private:
DemodulatorInstance *activeDemod;
void OnEnter ( wxCommandEvent &event );
void OnChar ( wxKeyEvent &event );
std::string& filterChars(std::string& s, const std::string& allowed);
DECLARE_EVENT_TABLE()
};

View File

@ -271,21 +271,28 @@ void TuningCanvas::OnMouseMoved(wxMouseEvent& event) {
} else {
switch (hoverState) {
case TUNING_HOVER_FREQ:
setStatusText("Click, wheel or drag a digit to change frequency. Hold ALT to change PPM. Hold SHIFT to disable carry.");
setStatusText("Click, wheel or drag a digit to change frequency; SPACE for direct input. Hold ALT to change PPM. Hold SHIFT to disable carry.");
break;
case TUNING_HOVER_BW:
setStatusText("Click, wheel or drag a digit to change bandwidth. Hold SHIFT to disable carry.");
break;
case TUNING_HOVER_CENTER:
setStatusText("Click, wheel or drag a digit to change center frequency. Hold SHIFT to disable carry.");
setStatusText("Click, wheel or drag a digit to change center frequency; SPACE for direct input. Hold SHIFT to disable carry.");
break;
case TUNING_HOVER_PPM:
setStatusText("Click, wheel or drag a digit to change device PPM offset. Hold SHIFT to disable carry.");
break;
case TUNING_HOVER_NONE:
setStatusText("");
break;
}
}
if (hoverState == TUNING_HOVER_BW || hoverState == TUNING_HOVER_FREQ) {
wxGetApp().getDemodMgr().setActiveDemodulator(wxGetApp().getDemodMgr().getLastActiveDemodulator());
} else {
wxGetApp().getDemodMgr().setActiveDemodulator(NULL);
}
}
void TuningCanvas::OnMouseDown(wxMouseEvent& event) {
@ -339,6 +346,7 @@ void TuningCanvas::OnMouseLeftWindow(wxMouseEvent& event) {
SetCursor(wxCURSOR_CROSS);
hoverIndex = 0;
hoverState = TUNING_HOVER_NONE;
wxGetApp().getDemodMgr().setActiveDemodulator(NULL);
if (currentPPM != lastPPM) {
wxGetApp().saveConfig();
@ -359,6 +367,10 @@ void TuningCanvas::setHelpTip(std::string tip) {
void TuningCanvas::OnKeyDown(wxKeyEvent& event) {
InteractiveCanvas::OnKeyDown(event);
if (event.GetKeyCode() == WXK_SPACE && (hoverState == TUNING_HOVER_CENTER || hoverState == TUNING_HOVER_FREQ)) {
wxGetApp().showFrequencyInput();
}
}
void TuningCanvas::OnKeyUp(wxKeyEvent& event) {

View File

@ -141,7 +141,7 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
ColorTheme *currentTheme = ThemeMgr::mgr.currentTheme;
int last_type = wxGetApp().getDemodMgr().getLastDemodulatorType();
if (mouseTracker.mouseInView()) {
if (mouseTracker.mouseInView() || wxGetApp().getDemodMgr().getActiveDemodulator()) {
hoverAlpha += (1.0f-hoverAlpha)*0.1f;
if (hoverAlpha > 1.5f) {
hoverAlpha = 1.5f;
@ -193,6 +193,8 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
}
}
glContext->setHoverAlpha(0);
for (int i = 0, iMax = demods.size(); i < iMax; i++) {
if (activeDemodulator == demods[i] || lastActiveDemodulator == demods[i]) {
continue;
@ -299,16 +301,6 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
wxGetApp().getDemodMgr().deleteThread(activeDemod);
break;
case 'S':
if (!activeDemod) {
break;
}
if (activeDemod->isSquelchEnabled()) {
activeDemod->setSquelchEnabled(false);
} else {
activeDemod->squelchAuto();
}
break;
case WXK_SPACE:
if (!activeDemod) {
break;
}
@ -318,6 +310,9 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
activeDemod->setStereo(true);
}
break;
case WXK_SPACE:
wxGetApp().showFrequencyInput();
break;
default:
event.Skip();
return;
@ -720,23 +715,23 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
mouseTracker.setVertDragLock(true);
mouseTracker.setHorizDragLock(false);
setStatusText("Click and drag to change demodulator bandwidth. D to delete, SPACE for stereo.");
setStatusText("Click and drag to change demodulator bandwidth. SPACE for direct frequency input. D to delete, S for stereo.");
} else {
SetCursor(wxCURSOR_SIZING);
nextDragState = WF_DRAG_FREQUENCY;
mouseTracker.setVertDragLock(true);
mouseTracker.setHorizDragLock(false);
setStatusText("Click and drag to change demodulator frequency. D to delete, SPACE for stereo.");
setStatusText("Click and drag to change demodulator frequency; SPACE for direct input. D to delete, S for stereo.");
}
} else {
SetCursor(wxCURSOR_CROSS);
nextDragState = WF_DRAG_NONE;
if (shiftDown) {
setStatusText("Click to create a new demodulator or hold ALT to drag range.");
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 A / Z to Zoom. Arrow keys (+SHIFT) to move center frequency.");
"Click to move active demodulator frequency or hold ALT to drag range; hold SHIFT to create new. Right drag or A / Z to Zoom. Arrow keys (+SHIFT) to move center frequency; SPACE for direct input.");
}
}