From: drowe67 Date: Wed, 11 Jun 2014 23:36:48 +0000 (+0000) Subject: added UDP control port that can process a few commands, made options dialog non model... X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=3a21e9cd4a96f2b5104cbea1a22916a923b3a982;p=freetel-svn-tracking.git added UDP control port that can process a few commands, made options dialog non model, mostly working but a few corner cases to cover git-svn-id: https://svn.code.sf.net/p/freetel/code@1645 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/fdmdv2/src/dlg_options.cpp b/fdmdv2/src/dlg_options.cpp index e19c2085..51d9ed4f 100644 --- a/fdmdv2/src/dlg_options.cpp +++ b/fdmdv2/src/dlg_options.cpp @@ -107,6 +107,19 @@ OptionsDlg::OptionsDlg(wxWindow* parent, wxWindowID id, const wxString& title, c bSizer30->Add(sbSizer_events,0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 3); + //------------------------------ + // UDP control port + //------------------------------ + + wxStaticBoxSizer* sbSizer_udp; + sbSizer_udp = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("UDP Control Port")), wxHORIZONTAL); + m_ckbox_udp_enable = new wxCheckBox(this, wxID_ANY, _("Enable UDP Control Port UDP Port Nnumber:"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE); + sbSizer_udp->Add(m_ckbox_udp_enable, 0, wxALIGN_CENTER_HORIZONTAL, 5); + m_txt_udp_port = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(100,-1), 0, wxTextValidator(wxFILTER_DIGITS)); + sbSizer_udp->Add(m_txt_udp_port, 0, wxALIGN_CENTER_HORIZONTAL, 5); + + bSizer30->Add(sbSizer_udp,0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 3); + //------------------------------ // Cancel - OK Buttons //------------------------------ @@ -164,6 +177,9 @@ void OptionsDlg::ExchangeData(int inout, bool storePersistent) m_ckbox_events->SetValue(wxGetApp().m_events); m_txt_events_regexp_match->SetValue(wxGetApp().m_events_regexp_match); m_txt_events_regexp_replace->SetValue(wxGetApp().m_events_regexp_replace); + + m_ckbox_udp_enable->SetValue(wxGetApp().m_udp_enable); + m_txt_udp_port->SetValue(wxString::Format(wxT("%i"),wxGetApp().m_udp_port)); if (wxGetApp().m_textEncoding == 1) m_rb_textEncoding1->SetValue(true); @@ -173,13 +189,18 @@ void OptionsDlg::ExchangeData(int inout, bool storePersistent) if(inout == EXCHANGE_DATA_OUT) { - wxGetApp().m_callSign = m_txtCtrlCallSign->GetValue(); - wxGetApp().m_testFrames = m_ckboxTestFrame->GetValue(); + wxGetApp().m_callSign = m_txtCtrlCallSign->GetValue(); + wxGetApp().m_testFrames = m_ckboxTestFrame->GetValue(); wxGetApp().m_events = m_ckbox_events->GetValue(); wxGetApp().m_events_regexp_match = m_txt_events_regexp_match->GetValue(); wxGetApp().m_events_regexp_replace = m_txt_events_regexp_replace->GetValue(); + wxGetApp().m_udp_enable = m_ckbox_udp_enable->GetValue(); + long port; + m_txt_udp_port->GetValue().ToLong(&port); + wxGetApp().m_udp_port = (int)port; + if (m_rb_textEncoding1->GetValue()) wxGetApp().m_textEncoding = 1; if (m_rb_textEncoding2->GetValue()) @@ -191,6 +212,10 @@ void OptionsDlg::ExchangeData(int inout, bool storePersistent) pConfig->Write(wxT("/Events/enable"), wxGetApp().m_events); pConfig->Write(wxT("/Events/regexp_match"), wxGetApp().m_events_regexp_match); pConfig->Write(wxT("/Events/regexp_replace"), wxGetApp().m_events_regexp_replace); + + pConfig->Write(wxT("/UDP/enable"), wxGetApp().m_udp_enable); + pConfig->Write(wxT("/UDP/port"), wxGetApp().m_udp_port); + pConfig->Flush(); } } @@ -202,7 +227,8 @@ void OptionsDlg::ExchangeData(int inout, bool storePersistent) //------------------------------------------------------------------------- void OptionsDlg::OnCancel(wxCommandEvent& event) { - this->EndModal(wxID_CANCEL); + //this->EndModal(wxID_CANCEL); + this->Show(false); } //------------------------------------------------------------------------- @@ -211,7 +237,8 @@ void OptionsDlg::OnCancel(wxCommandEvent& event) void OptionsDlg::OnOK(wxCommandEvent& event) { ExchangeData(EXCHANGE_DATA_OUT, true); - this->EndModal(wxID_OK); + //this->EndModal(wxID_OK); + this->Show(false); } //------------------------------------------------------------------------- @@ -219,7 +246,8 @@ void OptionsDlg::OnOK(wxCommandEvent& event) //------------------------------------------------------------------------- void OptionsDlg::OnClose(wxCloseEvent& event) { - this->EndModal(wxID_OK); + //this->EndModal(wxID_OK); + this->Show(false); } //------------------------------------------------------------------------- diff --git a/fdmdv2/src/dlg_options.h b/fdmdv2/src/dlg_options.h index 767ce364..45d62351 100644 --- a/fdmdv2/src/dlg_options.h +++ b/fdmdv2/src/dlg_options.h @@ -61,6 +61,9 @@ class OptionsDlg : public wxDialog wxTextCtrl *m_txt_events_in; wxTextCtrl *m_txt_events_out; + wxCheckBox *m_ckbox_udp_enable; + wxTextCtrl *m_txt_udp_port; + wxButton* m_sdbSizer5OK; wxButton* m_sdbSizer5Cancel; diff --git a/fdmdv2/src/fdmdv2_main.cpp b/fdmdv2/src/fdmdv2_main.cpp index 0c505563..da98a433 100644 --- a/fdmdv2/src/fdmdv2_main.cpp +++ b/fdmdv2/src/fdmdv2_main.cpp @@ -140,7 +140,7 @@ bool MainApp::OnInit() #ifdef _WXMSW_ // Force use of file-based configuration persistance on Windows platforma wxConfig *pConfig = new wxConfig(); - wxFileConfig *pFConfig = new wxFileConfig(wxT("FreeDV"), wxT("CODEC2-Project"), wxT("freedv.conf"), wxT("freedv.conf"), wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH); + wxFileConfig *pFConfig = new wxFileConfig(wxT("FreeDV"), wxT("CODEC2-Project"), wxT("FreeDV.conf"), wxT("FreeDV.conf"), wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH); pConfig->Set(pFConfig); pConfig->SetRecordDefaults(); #else @@ -376,6 +376,9 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent) wxGetApp().m_events_regexp_replace = pConfig->Read("/Events/regexp_replace", wxT("curl http://qso.freedv.org/cgi-bin/onspot.cgi?s=\\1")); + wxGetApp().m_udp_enable = (float)pConfig->Read(wxT("/UDP/enable"), f); + wxGetApp().m_udp_port = (float)pConfig->Read(wxT("/UDP/port"), 3000); + pConfig->SetPath(wxT("/")); // this->Connect(m_menuItemHelpUpdates->GetId(), wxEVT_UPDATE_UI, wxUpdateUIEventHandler(TopFrame::OnHelpCheckUpdatesUI)); @@ -417,7 +420,7 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent) #ifdef _USE_ONIDLE Connect(wxEVT_IDLE, wxIdleEventHandler(MainFrame::OnIdle), NULL, this); -#endif //_USE_TIMER +#endif //_USE_ONIDLE g_sfPlayFile = NULL; g_playFileToMicIn = false; @@ -458,10 +461,17 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent) g_total_bits = 0; wxGetApp().m_testFrames = false; - for(int i=0; iWrite(wxT("/Events/regexp_match"), wxGetApp().m_events_regexp_match); pConfig->Write(wxT("/Events/regexp_replace"), wxGetApp().m_events_regexp_replace); + pConfig->Write(wxT("/UDP/enable"), wxGetApp().m_udp_enable); + pConfig->Write(wxT("/UDP/port"), wxGetApp().m_udp_port); + pConfig->Write(wxT("/Filter/MicInEQEnable"), wxGetApp().m_MicInEQEnable); pConfig->Write(wxT("/Filter/SpkOutEQEnable"), wxGetApp().m_SpkOutEQEnable); } @@ -702,6 +722,10 @@ bool MainFrame::openComPort(const char *name) return true; } +#ifdef _USE_ONIDLE +void MainFrame::OnIdle(wxIdleEvent &evt) { +} +#endif //---------------------------------------------------------------- // (raise|lower)(RTS|DTR)() @@ -946,7 +970,7 @@ void MainFrame::OnTimer(wxTimerEvent &evt) wxString s; if (ret && (checksum_tx == checksum_rx)) { m_callsign[strlen(m_callsign)-2] = 0; - s.Printf("%s", m_callsign); + s.Printf("rx_txtmsg %s", m_callsign); m_txtCtrlCallSign->SetValue(s); processTxtEvent(m_callsign); @@ -1016,25 +1040,21 @@ void MainFrame::OnTimer(wxTimerEvent &evt) } m_panelTestFrameErrors->Refresh(); - } - + } delete error_pattern; } + // command from UDP thread best processed in main thread + + if (m_schedule_restore) { + Restore(); + m_schedule_restore = false; + } } #endif -#ifdef _USE_ONIDLE -//---------------------------------------------------------------- -// OnIdle() -//---------------------------------------------------------------- -void MainFrame::OnIdle(wxIdleEvent& event) -{ -} -#endif // _USE_TIMER - //------------------------------------------------------------------------- // OnCloseFrame() //------------------------------------------------------------------------- @@ -1194,6 +1214,7 @@ void MainFrame::togglePTT(void) { // rx-> tx transition, swap to Mic In page to monitor speech wxGetApp().m_rxNbookCtrl = m_auiNbookCtrl->GetSelection(); m_auiNbookCtrl->ChangeSelection(m_auiNbookCtrl->GetPageIndex((wxWindow *)m_panelSpeechIn)); + char e[80]; sprintf(e,"ptt"); processTxtEvent(e); } g_tx = m_btnTogPTT->GetValue(); @@ -1688,12 +1709,19 @@ void MainFrame::OnToolsFilter(wxCommandEvent& event) void MainFrame::OnToolsOptions(wxCommandEvent& event) { wxUnusedVar(event); - optionsDlg = new OptionsDlg(NULL); m_modal=true; - optionsDlg->ShowModal(); + optionsDlg->Show(); m_modal=false; - delete optionsDlg; - optionsDlg = NULL; + + // start/stop UDP thread + + if (!wxGetApp().m_udp_enable) { + stopUDPThread(); + } + + if (wxGetApp().m_udp_enable && (m_UDPThread == NULL)) { + startUDPThread(wxGetApp().m_udp_port); + } } //------------------------------------------------------------------------- @@ -1978,6 +2006,7 @@ void MainFrame::OnTogBtnOnOff(wxCommandEvent& event) m_plotTimer.Start(_REFRESH_TIMER_PERIOD, wxTIMER_CONTINUOUS); #endif // _USE_TIMER } + char e[80]; sprintf(e,"start"); processTxtEvent(e); } // Stop was pressed or start up failed @@ -2031,6 +2060,7 @@ void MainFrame::OnTogBtnOnOff(wxCommandEvent& event) m_rb1400->Enable(); m_rb2000->Enable(); #endif + char e[80]; sprintf(e,"stop"); processTxtEvent(e); } } @@ -2303,7 +2333,7 @@ void MainFrame::startRxStream() g_rxUserdata->micInEQEnable = wxGetApp().m_MicInEQEnable; g_rxUserdata->spkOutEQEnable = wxGetApp().m_SpkOutEQEnable; - // optional tone in left channel to reliably trigger vox + // otional tone in left channel to reliably trigger vox g_rxUserdata->leftChannelVoxTone = wxGetApp().m_leftChannelVoxTone; g_rxUserdata->voxTonePhase = 0; @@ -2525,6 +2555,9 @@ fprintf(stderr, "Err: %d\n", m_txErr); void MainFrame::processTxtEvent(char event[]) { + printf("processTxtEvent:\n"); + printf(" event: %s\n", event); + // process with regexp and issue system command // Each regexp in our list is separated by a newline. We want to try all of them. @@ -2535,23 +2568,28 @@ void MainFrame::processTxtEvent(char event[]) { wxString regexp_match_list = wxGetApp().m_events_regexp_match; wxString regexp_replace_list = wxGetApp().m_events_regexp_replace; + bool found_match = false; + while ((match_end = regexp_match_list.Find('\n')) != wxNOT_FOUND) { - printf("match_end: %d\n", match_end); + //printf("match_end: %d\n", match_end); if ((replace_end = regexp_replace_list.Find('\n')) != wxNOT_FOUND) { - printf("replace_end = %d\n", replace_end); + //printf("replace_end = %d\n", replace_end); // candidate match and replace regexps strings exist, so lets try them wxString regexp_match = regexp_match_list.SubString(0, match_end-1); wxString regexp_replace = regexp_replace_list.SubString(0, replace_end-1); - printf("match: %s replace: %s\n", (const char *)regexp_match.c_str(), (const char *)regexp_replace.c_str()); + //printf("match: %s replace: %s\n", (const char *)regexp_match.c_str(), (const char *)regexp_replace.c_str()); wxRegEx re(regexp_match); + printf(" checking for match against: %s\n", (const char *)regexp_match.c_str()); // if we found a match, lets run the replace regexp and issue the system command wxString event_str_rep = event_str; if (re.Replace(&event_str_rep, regexp_replace) != 0) { - printf("found match!\n"); + printf(" found match!\n"); + found_match = true; + bool enableSystem = false; if (wxGetApp().m_events) enableSystem = true; @@ -2576,9 +2614,8 @@ void MainFrame::processTxtEvent(char event[]) { event_out_with_return_code.Printf(_T("%s)"), event_out); // update event log GUI if currently displayed - printf("hello\n"); - if (optionsDlg != NULL) { - printf("hello\n"); + + if (optionsDlg != NULL) { optionsDlg->updateEventLog(wxString(event), event_out_with_return_code); } } @@ -2586,6 +2623,10 @@ void MainFrame::processTxtEvent(char event[]) { regexp_match_list = regexp_match_list.SubString(match_end+1, regexp_match_list.length()); regexp_replace_list = regexp_replace_list.SubString(replace_end+1, regexp_replace_list.length()); } + + if ((optionsDlg != NULL) && !found_match) { + optionsDlg->updateEventLog(wxString(event), _("")); + } } @@ -3652,3 +3693,88 @@ void MainFrame::CloseSerialPort(void) closeComPort(); } } + + +//---------------------------------------------------------------- +// PollUDP() - see if any commands on UDP port +//---------------------------------------------------------------- + +// test this puppy with netcat: +// $ echo "hello" | nc -u -q1 localhost 3000 + +int MainFrame::PollUDP(void) +{ + // this will block until message received, so we put it in it's own thread + + char buf[1024]; + char reply[80]; + size_t n = m_udp_sock->RecvFrom(m_udp_addr, buf, sizeof(buf)).LastCount(); + + if (n) { + wxString bufstr = wxString::From8BitData(buf, n); + bufstr.Trim(); + wxString ipaddr = m_udp_addr.IPAddress(); + printf("Received: \"%s\" from %s:%u\n", + (const char *)bufstr.c_str(), + (const char *)ipaddr.c_str(), m_udp_addr.Service()); + + // for security only accept commands from local host + + sprintf(reply,"nope\n"); + if (ipaddr.Cmp(_("127.0.0.1")) == 0) { + + // process commands + + if (bufstr.Cmp(_("restore")) == 0) { + m_schedule_restore = true; // Make Restore happen in main thread to avoid crashing + sprintf(reply,"ok\n"); + } + + wxString itemToSet, val; + if (bufstr.StartsWith(_("set "), &itemToSet)) { + if (itemToSet.StartsWith("txtmsg ", &val)) { + // note: if options dialog is open this will get overwritten + wxGetApp().m_callSign = val; + } + sprintf(reply,"ok\n"); + } + + } + else { + printf("We only accept messages from locahost!\n"); + } + + if ( m_udp_sock->SendTo(m_udp_addr, reply, strlen(reply)).LastCount() != strlen(reply)) { + printf("ERROR: failed to send data\n"); + } + } + + return n; +} + +void MainFrame::startUDPThread(int port) { + printf("starting UDP thread!\n"); + m_udp_addr.Service(port); + m_udp_sock = new wxDatagramSocket(m_udp_addr, wxSOCKET_NOWAIT); + m_UDPThread = new UDPThread; + m_UDPThread->mf = this; + if (m_UDPThread->Create() != wxTHREAD_NO_ERROR ) { + wxLogError(wxT("Can't create thread!")); + } + if (m_UDPThread->Run() != wxTHREAD_NO_ERROR ) { + wxLogError(wxT("Can't start thread!")); + delete m_UDPThread; + delete m_udp_sock; + } +} + +void MainFrame::stopUDPThread(void) { + printf("stopping UDP thread!\n"); + if ((m_UDPThread != NULL) && m_UDPThread->m_run) { + m_UDPThread->m_run = 0; + m_UDPThread->Wait(); + delete m_UDPThread; + delete m_udp_sock; + m_UDPThread = NULL; + } +} diff --git a/fdmdv2/src/fdmdv2_main.h b/fdmdv2/src/fdmdv2_main.h index 8a234573..b33e8ca8 100644 --- a/fdmdv2/src/fdmdv2_main.h +++ b/fdmdv2/src/fdmdv2_main.h @@ -49,6 +49,7 @@ #include #include #include +#include #include @@ -221,6 +222,10 @@ class MainApp : public wxApp // optional vox trigger tone bool m_leftChannelVoxTone; + // UDP control port + bool m_udp_enable; + int m_udp_port; + // notebook display after tx->rxtransition int m_rxNbookCtrl; @@ -322,6 +327,7 @@ private: }; class txRxThread; +class UDPThread; //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-= // Class MainFrame @@ -400,6 +406,14 @@ class MainFrame : public TopFrame void togglePTT(void); + wxIPV4address m_udp_addr; + wxDatagramSocket *m_udp_sock; + UDPThread *m_UDPThread; + void startUDPThread(int port); + void stopUDPThread(void); + int PollUDP(); + bool m_schedule_restore; + protected: #ifdef _WIN32 @@ -476,6 +490,7 @@ class MainFrame : public TopFrame #ifdef _USE_ONIDLE void OnIdle(wxIdleEvent &evt); #endif + private: bool m_useMemory; wxTextCtrl* m_tc; @@ -489,7 +504,6 @@ class MainFrame : public TopFrame unsigned int m_checksumBad; // Events - char m_event_log[MAX_EVENT_LOG][MAX_CALLSIGN]; void processTxtEvent(char event[]); class OptionsDlg *optionsDlg; @@ -535,6 +549,35 @@ public: bool m_run; }; +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-= +// class UDPThread - waits for UDP messages +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-= +class UDPThread : public wxThread +{ +public: + UDPThread(void) : wxThread(wxTHREAD_JOINABLE) { m_run = 1; } + + // thread execution starts here + void *Entry() + { + while (m_run) + { + if (mf->PollUDP() == 0) { + wxThread::Sleep(20); + } + } + return NULL; + } + + // called when the thread exits - whether it terminates normally or is + // stopped with Delete() (but not when it is Kill()ed!) + void OnExit() { } + +public: + MainFrame *mf; + bool m_run; +}; + void resample_for_plot(struct FIFO *plotFifo, short buf[], int length); int resample(SRC_STATE *src, diff --git a/fdmdv2/src/topFrame.h b/fdmdv2/src/topFrame.h index bf556d9b..86ddb388 100644 --- a/fdmdv2/src/topFrame.h +++ b/fdmdv2/src/topFrame.h @@ -123,6 +123,7 @@ class TopFrame : public wxFrame virtual void OnToolsFilter( wxCommandEvent& event ) { event.Skip(); } virtual void OnToolsFilterUI( wxUpdateUIEvent& event ) { event.Skip(); } virtual void OnToolsOptions( wxCommandEvent& event ) { event.Skip(); } + virtual void OnToolsUDP( wxCommandEvent& event ) { event.Skip(); } virtual void OnToolsOptionsUI( wxUpdateUIEvent& event ) { event.Skip(); } virtual void OnToolsComCfg( wxCommandEvent& event ) { event.Skip(); } virtual void OnToolsComCfgUI( wxUpdateUIEvent& event ) { event.Skip(); } diff --git a/fdmdv2/src/varicode.c b/fdmdv2/src/varicode.c index 540680be..26de09a6 100644 --- a/fdmdv2/src/varicode.c +++ b/fdmdv2/src/varicode.c @@ -233,9 +233,6 @@ static int decode_two_bits(struct VARICODE_DEC *s, char *single_ascii, short var int found=0, i; unsigned short byte1; - //printf("decode_one_bit : state: %d varicode_in: %d packed: 0x%x n_zeros: %d\n", - // s->state, varicode_in, s->packed, s->n_zeros); - if (s->state == 0) { if (!(varicode_in1 || varicode_in2)) return 0;