diff --git a/ChangeLog b/ChangeLog index a97034aa..72c01f46 100644 --- a/ChangeLog +++ b/ChangeLog @@ -37,6 +37,17 @@ Change Log: "<=== %x %H:%M ====>" for the RX divider line. 14) Deprecated the "rtty is USB" configuration item. fldigi adjusts all tone inversion sensitive modes for USB / LSB operation. + 15) Changes to command parsing used by the ARQ interface(s); TLF, SysV + and ARQ socket. + 16) Reduced the minimum main window height. + 17) Added fldigi-shell time command + Try this "stress test": + time eval for (1..50) + { execute("modem.set_by_name BPSK31"); \ + execute("modem.set_by_name RTTY"); } + 18) Added brief message to the opening Rx text area indicating which + macro file was loaded on start up. Also added name of the working + macro file to the title bar of the macro editor. 3.03 1) Changes to socket server to correct shutdown process diff --git a/configure.ac b/configure.ac index 0bd12512..ff480c7e 100644 --- a/configure.ac +++ b/configure.ac @@ -9,7 +9,7 @@ dnl major and minor must be integers; patch may dnl contain other characters or be empty m4_define(FLDIGI_MAJOR, [3]) m4_define(FLDIGI_MINOR, [0]) -m4_define(FLDIGI_PATCH, [4AI]) +m4_define(FLDIGI_PATCH, [4AJ]) AC_INIT([fldigi], FLDIGI_MAJOR.FLDIGI_MINOR[FLDIGI_PATCH], [w1hkj AT w1hkj DOT com]) @@ -39,6 +39,7 @@ AC_CONFIG_MACRO_DIR([m4]) AC_DEFINE([PACKAGE_HOME], ["http://www.w1hkj.com/Fldigi.html"], [Home page]) +AC_DEFINE([PACKAGE_PROJ], ["http://developer.berlios.de/project/showfiles.php?group_id=9149"], [BerliOS page]) AC_DEFINE([PACKAGE_DOCS], ["http://www.w1hkj.com/FldigiHelp/index.html"], [Docs index]) diff --git a/scripts/fldigi-shell b/scripts/fldigi-shell index d07d4acd..2e8ac7fe 100644 --- a/scripts/fldigi-shell +++ b/scripts/fldigi-shell @@ -33,6 +33,7 @@ use POSIX qw(:termios_h); use IO::Handle; use Getopt::Std; use Data::Dumper; +use Time::HiRes qw(gettimeofday tv_interval); ################################################################################ @@ -284,6 +285,13 @@ sub wait_for_state sleep(1) while (defined($r = req("main.get_tx_status")) && $r->value ne $_[0]); } +sub time_cmd +{ + my $t0 = [gettimeofday()]; + execute("@_"); + print tv_interval($t0), " seconds\n"; +} + ################################################################################ @@ -302,7 +310,8 @@ our %opts = ( "u" => "http://localhost:7362/RPC2", "d" => 0 ); "recvtext" => [ "s:n", "Get all received text", \&get_recv_text ], "sendfile" => [ "n:s", "Send text from file ``s''", \&send_file ], "sendstr" => [ "n:s", "Send string ``s''", sub { send_line(@_); } ], - "wait" => [ "n:s", "Wait for trx state to become ``s''", \&wait_for_state ] + "wait" => [ "n:s", "Wait for trx state to become ``s''", \&wait_for_state ], + "time" => [ "s:s", "Time a command", \&time_cmd ] ); %encoders = ( "b" => \&RPC_BOOLEAN, "6" => \&RPC_BASE64, diff --git a/src/Makefile.am b/src/Makefile.am index 96153f20..134ece97 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -199,6 +199,7 @@ fldigi_SOURCES += \ include/morse.h \ include/mt63base.h \ include/mt63.h \ + include/network.h \ include/dsp.h \ include/newinstall.h \ include/olivia.h \ @@ -263,6 +264,7 @@ fldigi_SOURCES += \ misc/macroedit.cxx \ misc/macros.cxx \ misc/misc.cxx \ + misc/network.cxx \ misc/newinstall.cxx \ misc/arq_io.cxx \ misc/qrzcall.cxx \ diff --git a/src/dialogs/fl_digi.cxx b/src/dialogs/fl_digi.cxx index f2fd4515..f805fbe8 100644 --- a/src/dialogs/fl_digi.cxx +++ b/src/dialogs/fl_digi.cxx @@ -108,6 +108,8 @@ # include "xmlrpc.h" #endif #include "debug.h" +#include "re.h" +#include "network.h" Fl_Double_Window *fl_digi_main=(Fl_Double_Window *)0; Fl_Help_Dialog *help_dialog = (Fl_Help_Dialog *)0; @@ -181,6 +183,7 @@ int Hwfall = DEFAULT_HWFALL; int HNOM = DEFAULT_HNOM; int WNOM = DEFAULT_WNOM; +bool clean_exit(void); void cb_init_mode(Fl_Widget *, void *arg); @@ -432,70 +435,6 @@ void cb_mnuSaveMacro(Fl_Menu_*, void*) { restoreFocus(); } -//bool logging = false; -//void cb_mnuLogFile(Fl_Menu_ *, void *) { -// logging = !logging; -// restoreFocus(); -//} - -bool clean_exit() { - arq_close(); - - if (progdefaults.changed == true) { - switch (fl_choice("Save changed configuration before exiting?", "Cancel", "Save", "Don't save")) { - case 0: - return false; - case 1: - progdefaults.saveDefaults(); - // fall through - case 2: - break; - } - } - if (macros.changed == true) { - switch (fl_choice("Save changed macros before exiting?", "Cancel", "Save", "Don't save")) { - case 0: - return false; - case 1: - macros.saveMacroFile(); - // fall through - case 2: - break; - } - } - if (Maillogfile) - Maillogfile->log_to_file_stop(); - if (logfile) - logfile->log_to_file_stop(); - - if (bSaveFreqList) - saveFreqList(); - - progStatus.saveLastState(); - -#if USE_HAMLIB - hamlib_close(); -#endif - rigCAT_close(); - rigMEM_close(); - - if (mixer) - mixer->closeMixer(); - - if (trx_state == STATE_RX || trx_state == STATE_TX || trx_state == STATE_TUNE) - trx_state = STATE_ABORT; - else { - LOG_ERROR("trx in unexpected state %d", trx_state); - exit(1); - } - while (trx_state != STATE_ENDED) { - REQ_FLUSH(GET_THREAD_ID()); - MilliSleep(10); - } - - return true; -} - void cb_E(Fl_Menu_*, void*) { fl_digi_main->do_callback(); } @@ -646,17 +585,12 @@ void init_modem(trx_mode mode) void init_modem_sync(trx_mode m) { + ENSURE_THREAD(FLMAIN_TID); + if (trx_state != STATE_RX) - return; + TRX_WAIT(STATE_RX, abort_tx()); -#ifndef NDEBUG - if (GET_THREAD_ID() == TRX_TID) - LOG_ERROR("trx thread called init_modem_sync!"); -#endif - - wait_modem_ready_prep(); - init_modem(m); - wait_modem_ready_cmpl(); + TRX_WAIT(STATE_RX, init_modem(m)); REQ_FLUSH(TRX_TID); } @@ -855,13 +789,6 @@ void cb_mnuSaveConfig(Fl_Menu_ *, void *) { restoreFocus(); } -void cb_mnuAbout(Fl_Widget*, void*) -{ - fl_message ("%s @@W1HKJ\n\n%s\n\n%s\n\nVersion %s", PACKAGE_NAME, - PACKAGE_BUGREPORT, PACKAGE_HOME, PACKAGE_VERSION); - restoreFocus(); -} - void cb_mnuVisitURL(Fl_Widget*, void* arg) { const char* url = reinterpret_cast(arg); @@ -924,6 +851,57 @@ void cb_mnuBeginnersURL(Fl_Widget*, void*) #endif } +void cb_mnuCheckUpdate(Fl_Widget* w, void*) +{ + struct { + const char* url; + const char* re; + string version_str; + long version; + } sites[] = { + { PACKAGE_HOME, "fldigi-distro/fldigi-([0-9.]+).tar.gz", "", 0 }, + { PACKAGE_PROJ, "fldigi/fldigi-([0-9.]+).tar.gz", "", 0 } + }, *latest; + string reply; + + w->window()->cursor(FL_CURSOR_WAIT); + put_status("Checking for updates..."); + for (size_t i = 0; i < sizeof(sites)/sizeof(*sites); i++) { // fetch .url, grep for .re + Fl::check(); + reply.clear(); + if (!fetch_http(sites[i].url, reply, 20.0)) + continue; + re_t re(sites[i].re, REG_EXTENDED | REG_ICASE | REG_NEWLINE); + if (!re.match(reply.c_str()) || re.nsub() != 2) + continue; + + sites[i].version = ver2int((sites[i].version_str = re.submatch(1)).c_str()); + } + w->window()->cursor(FL_CURSOR_DEFAULT); + put_status(""); + + latest = sites[1].version > sites[0].version ? &sites[1] : &sites[0]; + if (sites[0].version == 0 && sites[1].version == 0) { + fl_message("Could not check for updates:\n%s", reply.c_str()); + return; + } + if (latest->version > ver2int(PACKAGE_VERSION)) { + switch (fl_choice("Version %s is available at\n\n%s\n\nWhat would you like to do?", + "Close", "Visit URL", "Copy URL", + latest->version_str.c_str(), latest->url)) { + case 1: + cb_mnuVisitURL(NULL, (void*)latest->url); + break; + case 2: + size_t n = strlen(latest->url); + Fl::copy(latest->url, n, 0); + Fl::copy(latest->url, n, 1); + } + } + else + fl_message("You are running the latest version"); +} + void cb_mnuAboutURL(Fl_Widget*, void*) { if (!help_dialog) @@ -1116,65 +1094,47 @@ void cb_sldrSquelch(Fl_Slider* o, void*) { restoreFocus(); } -char *zuluTime() +const char *zuluTime() { - struct tm *tm; time_t t; - static char logtime[10]; - time(&t); - tm = gmtime(&t); - strftime(logtime, sizeof(logtime), "%H%M", tm); + struct tm tm; + static char logtime[5]; + if ((t = time(NULL)) != (time_t)-1 && gmtime_r(&t, &tm) && + strftime(logtime, sizeof(logtime), "%H%M", &tm)) return logtime; + else + return NULL; } -bool oktoclear = false; +bool oktoclear = true; void qsoTime_cb(Fl_Widget *b, void *) { - FL_LOCK_D(); inpTime->value(zuluTime()); - FL_UNLOCK_D(); - FL_AWAKE_D(); oktoclear = false; restoreFocus(); } void clearQSO() { - FL_LOCK_D(); + Fl_Input* in[] = { inpCall, inpName, inpRstIn, inpRstOut, + inpQth, inpNotes, inpLoc, inpAZ }; + for (size_t i = 0; i < sizeof(in)/sizeof(*in); i++) + in[i]->value(""); inpTime->value(zuluTime()); - inpCall->value(""); - inpName->value(""); - inpRstIn->value(""); - inpRstOut->value(""); - inpQth->value(""); - inpLoc->value(""); - inpAZ->value(""); // WA5ZNU - inpNotes->value(""); - FL_UNLOCK_D(); } -void cb_log(Fl_Widget *b, void *) +void cb_log(Fl_Widget*, void*) { oktoclear = false; } -void cb_callsign(Fl_Widget *b, void *) -{ - oktoclear = false; - restoreFocus(); -} - void qsoClear_cb(Fl_Widget *b, void *) { - if (oktoclear) { + if (oktoclear || fl_choice("Clear log fields?", "Cancel", "OK", NULL) == 1) { clearQSO(); - FL_AWAKE_D(); - } else if (fl_choice ("Clear log fields?", "Cancel", "OK", NULL) == 1) { - clearQSO(); - FL_AWAKE_D(); - } oktoclear = true; + } restoreFocus(); } @@ -1300,6 +1260,75 @@ int default_handler(int event) return 0; } +bool clean_exit(void) { + arq_close(); + + if (progdefaults.changed) { + switch (fl_choice("Save changed configuration before exiting?", "Cancel", "Save", "Don't save")) { + case 0: + return false; + case 1: + progdefaults.saveDefaults(); + // fall through + case 2: + break; + } + } + if (!oktoclear) { + switch (fl_choice("Save log before exiting?", "Cancel", "Save", "Don't save")) { + case 0: + return false; + case 1: + qsoSave_cb(0, 0); + // fall through + case 2: + break; + } + } + if (macros.changed) { + switch (fl_choice("Save changed macros before exiting?", "Cancel", "Save", "Don't save")) { + case 0: + return false; + case 1: + macros.saveMacroFile(); + // fall through + case 2: + break; + } + } + if (Maillogfile) + Maillogfile->log_to_file_stop(); + if (logfile) + logfile->log_to_file_stop(); + + if (bSaveFreqList) + saveFreqList(); + + progStatus.saveLastState(); + +#if USE_HAMLIB + hamlib_close(); +#endif + rigCAT_close(); + rigMEM_close(); + + if (mixer) + mixer->closeMixer(); + + if (trx_state == STATE_RX || trx_state == STATE_TX || trx_state == STATE_TUNE) + trx_state = STATE_ABORT; + else { + LOG_ERROR("trx in unexpected state %d", trx_state); + exit(1); + } + while (trx_state != STATE_ENDED) { + REQ_FLUSH(GET_THREAD_ID()); + MilliSleep(10); + } + + return true; +} + // XPM Calendar Label static const char *cal_16[] = { // width height num_colors chars_per_pixel @@ -1469,12 +1498,13 @@ Fl_Menu_Item menu_[] = { {"@-1circle Create sunspots", 0, cb_mnuFun, 0, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, #endif {"Beginners' Guide", 0, cb_mnuBeginnersURL, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{"Online documentation", 0, cb_mnuVisitURL, (void *)PACKAGE_DOCS, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{"Home page", 0, cb_mnuVisitURL, (void *)PACKAGE_HOME, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, +{"Online documentation...", 0, cb_mnuVisitURL, (void *)PACKAGE_DOCS, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{"Fldigi web site...", 0, cb_mnuVisitURL, (void *)PACKAGE_HOME, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, {"Command line options", 0, cb_mnuCmdLineHelp, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"Audio device info", 0, cb_mnuAudioInfo, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"Build info", 0, cb_mnuBuildInfo, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"Event log", 0, cb_mnuDebug, 0, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, +{"Check for updates...", 0, cb_mnuCheckUpdate, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"About", 0, cb_mnuAboutURL, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, @@ -1613,18 +1643,13 @@ int below(Fl_Widget* w) return (a & FL_ALIGN_BOTTOM) ? w->y() + w->h() + FL_NORMAL_SIZE : w->y() + w->h(); } -char main_window_title[256]; -void update_main_title() { - string macrotitle = " -- "; - macrotitle.append(progStatus.LastMacroFile); - - snprintf(main_window_title, sizeof(main_window_title), - "%s %s -- %s %s", - PACKAGE_NAME, PACKAGE_VERSION, - progdefaults.myCall.empty() ? "NO CALLSIGN SET" : progdefaults.myCall.c_str(), - macrotitle.c_str()); +string main_window_title; +void update_main_title() +{ + main_window_title = PACKAGE_TARNAME " - "; + main_window_title += (progdefaults.myCall.empty() ? "NO CALLSIGN SET" : progdefaults.myCall.c_str()); if (fl_digi_main != NULL) - fl_digi_main->label(main_window_title); + fl_digi_main->label(main_window_title.c_str()); } @@ -1635,7 +1660,7 @@ void create_fl_digi_main() { if (twoscopes) WNOM -= 2*DEFAULT_SW; update_main_title(); - fl_digi_main = new Fl_Double_Window(WNOM, HNOM, main_window_title); + fl_digi_main = new Fl_Double_Window(WNOM, HNOM, main_window_title.c_str()); mnu = new Fl_Menu_Bar(0, 0, WNOM - 150 - pad, Hmenu); // FL_NORMAL_SIZE may have changed; update the menu items for (size_t i = 0; i < sizeof(menu_)/sizeof(menu_[0]); i++) @@ -1650,7 +1675,7 @@ void create_fl_digi_main() { Fl_Tooltip::font(FL_HELVETICA); Fl_Tooltip::size(FL_NORMAL_SIZE); - btnRSID = new Fl_Light_Button(WNOM - 150 - pad, 0, 50, Hmenu, "RSID ?"); + btnRSID = new Fl_Light_Button(WNOM - 150 - pad, 0, 50, Hmenu, "RSID"); btnRSID->selection_color(FL_GREEN); btnRSID->callback(cbRSID, 0); @@ -1673,11 +1698,9 @@ void create_fl_digi_main() { Fl_Group *qsoFrame = new Fl_Group(0, Y, WNOM, Hqsoframe); inpFreq = new Fl_Input(pad, Y + Hqsoframe/2 - pad, 85, Hqsoframe/2, "Frequency"); inpFreq->align(FL_ALIGN_TOP | FL_ALIGN_LEFT); - inpFreq->callback(cb_log, 0); inpTime = new Fl_Input(rightof(inpFreq) + pad, Y + Hqsoframe/2 - pad, 45, Hqsoframe/2, "Time"); inpTime->align(FL_ALIGN_TOP | FL_ALIGN_LEFT); - inpTime->callback(cb_log, 0); qsoTime = new Fl_Button(rightof(inpTime) + pad, Y + Hqsoframe/2 - pad, 24, Hqsoframe/2); Fl_Image *pixmap = new Fl_Pixmap(cal_16); @@ -1686,20 +1709,15 @@ void create_fl_digi_main() { inpCall = new Fl_Input(rightof(qsoTime) + pad, Y + Hqsoframe/2 - pad, 80, Hqsoframe/2, "Call"); inpCall->align(FL_ALIGN_TOP | FL_ALIGN_LEFT); - inpCall->callback(cb_callsign, 0); - inpCall->when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED); inpName = new Fl_Input(rightof(inpCall) + pad, Y + Hqsoframe/2 - pad, 100, Hqsoframe/2, "Name"); inpName->align(FL_ALIGN_TOP | FL_ALIGN_LEFT); - inpName->callback(cb_log, 0); inpRstIn = new Fl_Input(rightof(inpName) + pad, Y + Hqsoframe/2 - pad, 35, Hqsoframe/2, "RST In "); inpRstIn->align(FL_ALIGN_TOP | FL_ALIGN_RIGHT); - inpRstIn->callback(cb_log, 0); inpRstOut = new Fl_Input(rightof(inpRstIn) + pad, Y + Hqsoframe/2 - pad, 35, Hqsoframe/2, "Out"); inpRstOut->align(FL_ALIGN_TOP | FL_ALIGN_LEFT); - inpRstOut->callback(cb_log, 0); btnQRZ = new Fl_Button(WNOM - 40 - pad, Y + 1, 40, Hqsoframe/2 - pad, "QRZ"); btnQRZ->callback(cb_QRZ, 0); @@ -1707,7 +1725,6 @@ void create_fl_digi_main() { inpQth = new Fl_Input(rightof(inpRstOut) + pad, Y + Hqsoframe/2 - pad, leftof(btnQRZ) - rightof(inpRstOut) - 2*pad, Hqsoframe/2, "QTH"); inpQth->align(FL_ALIGN_TOP | FL_ALIGN_LEFT); - inpQth->callback(cb_log, 0); qsoFrame->resizable(inpQth); qsoClear = new Fl_Button(WNOM - 40 - pad, Y + Hqsoframe/2 + 1, 40, Hqsoframe/2 - pad, "Clear"); @@ -1722,17 +1739,14 @@ void create_fl_digi_main() { inpAZ = new Fl_Input(leftof(qsoSave) - 40 - pad, Y, 40, Hnotes, "Az"); // WA5ZNU inpAZ->align(FL_ALIGN_LEFT); - inpAZ->callback(cb_log, 0); inpLoc = new Fl_Input(leftof(inpAZ) - pad - pad - 70, Y, 70, Hnotes, "Loc"); inpLoc->align(FL_ALIGN_LEFT); - inpLoc->callback(cb_log, 0); // align this vertically with the Call field inpNotes = new Fl_Input(leftof(inpLoc) - pad - (leftof(inpLoc) - leftof(inpCall)), Y, leftof(inpLoc) - leftof(inpCall) - 2*pad, Hnotes, "Notes"); inpNotes->align(FL_ALIGN_LEFT); - inpNotes->callback(cb_log, 0); qsoFrame2->resizable(inpNotes); btnSideband = new Fl_Button(leftof(inpNotes) - 2*pad - (Hnotes-2), Y+1, Hnotes-2, Hnotes-2, "U"); @@ -1743,6 +1757,11 @@ void create_fl_digi_main() { qsoFrame2->end(); Y += Hnotes; + Fl_Widget* logfields[] = { inpFreq, inpTime, inpCall, inpName, inpRstIn, + inpRstOut, inpQth, inpAZ, inpLoc, inpNotes }; + for (size_t i = 0; i < sizeof(logfields)/sizeof(*logfields); i++) + logfields[i]->callback(cb_log); + int sw = DEFAULT_SW; MixerFrame = new Fl_Group(0,Y,sw, Hrcvtxt + Hxmttxt); valRcvMixer = new Fl_Value_Slider(0, Y, sw, (Htext)/2, ""); @@ -1789,6 +1808,10 @@ void create_fl_digi_main() { ReceiveText->setFontColor(progdefaults.CTRLcolor, FTextBase::CTRL); ReceiveText->setFontColor(progdefaults.SKIPcolor, FTextBase::SKIP); ReceiveText->setFontColor(progdefaults.ALTRcolor, FTextBase::ALTR); + string Macroset = "<<<===== Macro File "; + Macroset.append(progStatus.LastMacroFile); + Macroset.append(" Loaded =====>>>\n\n"); + ReceiveText->add(Macroset.c_str()); TiledGroup->add_resize_check(FTextView::wheight_mult_tsize, ReceiveText); FHdisp = new Raster(sw, Y, WNOM-sw, minRxHeight); @@ -1982,7 +2005,6 @@ void create_fl_digi_main() { Fl_Group::current()->resizable(StatusBar); hpack->end(); - fl_digi_main->size_range(WNOM, HNOM); fl_digi_main->end(); fl_digi_main->callback(cb_wMain); @@ -1994,7 +2016,7 @@ void create_fl_digi_main() { #endif fl_digi_main->xclass(PACKAGE_NAME); -// Fl::set_atclose(clean_exit); + fl_digi_main->size_range(WNOM, (HNOM < 400 ? HNOM : 400)); scopeview = new Fl_Double_Window(0,0,140,140, "Scope"); scopeview->xclass(PACKAGE_NAME); diff --git a/src/dialogs/htmlstrings.cxx b/src/dialogs/htmlstrings.cxx index e0e9d06d..cf4593ea 100644 --- a/src/dialogs/htmlstrings.cxx +++ b/src/dialogs/htmlstrings.cxx @@ -553,7 +553,7 @@ char szAbout[] = \ \
\ -

Fldigi

\ +

Fldigi " PACKAGE_VERSION "

\
\
\

Digital modem program for


\ @@ -561,7 +561,7 @@ char szAbout[] =      Linux
\      FreeBSD
\      OS X
\ -     Windows (XP)
\ +     Windows
\
\

Programmers:


\

\ diff --git a/src/globals/globals.cxx b/src/globals/globals.cxx index d7782596..a9641272 100644 --- a/src/globals/globals.cxx +++ b/src/globals/globals.cxx @@ -34,15 +34,6 @@ using namespace std; -const char *state_names[] = { - "PAUSED", - "RECEIVE", - "TRANSMIT", - "TUNING", - "ABORTED", - "FLUSHING" -}; - // Elements are in enum trx_mode order. Mode name video-id uses the // first string (sname), so its length should be a multiple of 2. const struct mode_info_t mode_info[NUM_MODES] = { diff --git a/src/include/globals.h b/src/include/globals.h index 1846675d..2684c828 100644 --- a/src/include/globals.h +++ b/src/include/globals.h @@ -44,7 +44,6 @@ enum state_t { STATE_IDLE, STATE_NEW_MODEM }; -extern const char *state_names[]; enum { MODE_PREV = -2, diff --git a/src/include/modem.h b/src/include/modem.h index 2c0910e2..4bdc800b 100644 --- a/src/include/modem.h +++ b/src/include/modem.h @@ -91,9 +91,9 @@ public: // void set_mode(trx_mode); trx_mode get_mode(); const char *get_mode_name() { return mode_info[get_mode()].sname;} - void set_state(state_t); - void set_state_wait(state_t); - state_t get_state(); +// void set_state(state_t); +// void set_state_wait(state_t); +// state_t get_state(); void set_freq(double); int get_freq(); void init_freqlock(); diff --git a/src/include/network.h b/src/include/network.h new file mode 100644 index 00000000..97df9e2a --- /dev/null +++ b/src/include/network.h @@ -0,0 +1,10 @@ +#ifndef NETWORK_H_ +#define NETWORK_H_ + +#include + +bool request_reply(const std::string& node, const std::string& service, + const std::string& request, std::string& reply, double timeout = 0.0); +bool fetch_http(const std::string& url, std::string& reply, double timeout = 0.0); + +#endif // NETWORK_H_ diff --git a/src/include/rigxml.h b/src/include/rigxml.h index 70b51b3f..d9bb9f62 100644 --- a/src/include/rigxml.h +++ b/src/include/rigxml.h @@ -9,21 +9,21 @@ #include struct MODE { - string SYMBOL; - string BYTES; - MODE(string nm, string b) { SYMBOL = nm; BYTES = b;} - MODE(string nm, char c) { SYMBOL = nm; BYTES += c;} + std::string SYMBOL; + std::string BYTES; + MODE(std::string nm, std::string b) { SYMBOL = nm; BYTES = b;} + MODE(std::string nm, char c) { SYMBOL = nm; BYTES += c;} }; struct BW { - string SYMBOL; - string BYTES; - BW(string nm, string b) { SYMBOL = nm; BYTES = b;} - BW(string nm, char c) { SYMBOL = nm; BYTES += c;} + std::string SYMBOL; + std::string BYTES; + BW(std::string nm, std::string b) { SYMBOL = nm; BYTES = b;} + BW(std::string nm, char c) { SYMBOL = nm; BYTES += c;} }; struct DATA { - string dtype; + std::string dtype; int size; int max; int min; @@ -44,16 +44,16 @@ struct DATA { }; struct XMLIOS { - string SYMBOL; + std::string SYMBOL; int size; - string str1; - string str2; + std::string str1; + std::string str2; DATA data; int fill1; int fill2; - string info; - string ok; - string bad; + std::string info; + std::string ok; + std::string bad; void clear() { SYMBOL = str1 = str2 = info = ok = bad = ""; size = fill1 = fill2 = 0; @@ -64,8 +64,8 @@ struct XMLIOS { struct TAGS { const char *tag; void (*fp)(size_t &);}; struct XMLRIG { - string SYMBOL; - string port; + std::string SYMBOL; + std::string port; int baud; bool echo; int timeout; @@ -92,15 +92,15 @@ struct XMLRIG { } }; -extern list commands; -extern list reply; -extern list lmodes; -extern list lmodeCMD; -extern list lmodeREPLY; -extern list lbws; -extern list lbwCMD; -extern list lbwREPLY; -extern list LSBmodes; +extern std::list commands; +extern std::list reply; +extern std::list lmodes; +extern std::list lmodeCMD; +extern std::list lmodeREPLY; +extern std::list lbws; +extern std::list lbwCMD; +extern std::list lbwREPLY; +extern std::list LSBmodes; extern XMLRIG rig; extern bool readRigXML(); diff --git a/src/include/serial.h b/src/include/serial.h index c6949f67..922e34e2 100644 --- a/src/include/serial.h +++ b/src/include/serial.h @@ -5,18 +5,10 @@ #ifndef SERIALCOMMH #define SERIALCOMMH -#include -#include -#include -#include #include -#include -#include - -#include #include -using namespace std; +void adjust_port(std::string& port); class Cserial { public: @@ -29,8 +21,8 @@ public: bool IsOpen() { return fd < 0 ? 0 : 1; }; void ClosePort(); - void Device (string dev) { device = dev;}; - string Device() { return device;}; + void Device (std::string dev) { device = dev;}; + std::string Device() { return device;}; void Baud(int b) { baud = b;}; int Baud() { return baud;}; @@ -64,7 +56,7 @@ public: private: //Members - string device; + std::string device; int fd; int baud; int speed; diff --git a/src/include/socket.h b/src/include/socket.h index 95ce996d..4775a9b4 100644 --- a/src/include/socket.h +++ b/src/include/socket.h @@ -136,6 +136,7 @@ public: void set_nonblocking(bool v = true); void set_nodelay(bool v = true); void set_timeout(const struct timeval& t); + void set_timeout(double t); void set_autoclose(bool v) const; void set_close_on_exec(bool v, int fd = -1); diff --git a/src/include/threads.h b/src/include/threads.h index f71cae9f..fa5b68a5 100644 --- a/src/include/threads.h +++ b/src/include/threads.h @@ -15,7 +15,7 @@ int sem_timedwait_rel(sem_t* sem, double rel_timeout); int pthread_cond_timedwait_rel(pthread_cond_t* cond, pthread_mutex_t* mutex, double rel_timeout); // 3 threads use qrunner -enum { UNKNOWN_TID = -1, TRX_TID, QRZ_TID, RIGCTL_TID, +enum { INVALID_TID = -1, TRX_TID, QRZ_TID, RIGCTL_TID, #if USE_XMLRPC XMLRPC_TID, #endif @@ -25,16 +25,39 @@ enum { UNKNOWN_TID = -1, TRX_TID, QRZ_TID, RIGCTL_TID, #if USE_TLS # define THREAD_ID_TYPE __thread int -# define CREATE_THREAD_ID() thread_id_ = UNKNOWN_TID +# define CREATE_THREAD_ID() thread_id_ = INVALID_TID # define SET_THREAD_ID(x) thread_id_ = (x) # define GET_THREAD_ID() thread_id_ #else # define THREAD_ID_TYPE pthread_key_t -# define CREATE_THREAD_ID() pthread_key_create(&thread_id_, 0); +# define CREATE_THREAD_ID() pthread_key_create(&thread_id_, 0) # define SET_THREAD_ID(x) pthread_setspecific(thread_id_, (void *)(x)) # define GET_THREAD_ID() (int)pthread_getspecific(thread_id_) #endif // USE_TLS + +#ifndef NDEBUG +# include "debug.h" +bool thread_in_list(int id, const int* list); +# define ENSURE_THREAD(...) \ + do { \ + int id_ = GET_THREAD_ID(); \ + int t_[] = { __VA_ARGS__, INVALID_TID }; \ + if (!thread_in_list(id_, t_)) \ + LOG_ERROR("bad thread context: %d", id_); \ + } while (0) +# define ENSURE_NOT_THREAD(...) \ + do { \ + int id_ = GET_THREAD_ID(); \ + int t_[] = { __VA_ARGS__, INVALID_TID }; \ + if (thread_in_list(id_, t_)) \ + LOG_ERROR("bad thread context: %d", id_); \ + } while (0) +#else +# define ENSURE_THREAD(...) ((void)0) +# define ENSURE_NOT_THREAD(...) ((void)0) +#endif // ! NDEBUG + extern THREAD_ID_TYPE thread_id_; #include "fl_lock.h" diff --git a/src/include/trx.h b/src/include/trx.h index 7dd00f1b..b5bd8e8b 100644 --- a/src/include/trx.h +++ b/src/include/trx.h @@ -48,9 +48,9 @@ extern void trx_receive(); extern void trx_reset(void); extern void trx_start_macro_timer(); -extern void wait_modem_ready_prep(void); -extern void wait_modem_ready_cmpl(void); -extern void signal_modem_ready(void); +extern void wait_trx_state_prep(void); +extern void wait_trx_state_wait(void); +extern void wait_trx_state_cmpl(void); extern void macro_timer(void *); @@ -62,4 +62,14 @@ extern SoundBase *scard; extern bool bHistory; +#define TRX_WAIT(s_, code_) \ + do { \ + ENSURE_NOT_THREAD(TRX_TID); \ + wait_trx_state_prep(); \ + code_; \ + while (trx_state != s_) \ + wait_trx_state_wait(); \ + wait_trx_state_cmpl(); \ + } while (0) + #endif diff --git a/src/include/util.h b/src/include/util.h index 99731d7d..6dfe2ad1 100644 --- a/src/include/util.h +++ b/src/include/util.h @@ -106,6 +106,8 @@ char* strcasestr(const char* haystack, const char* needle); int set_cloexec(int fd, unsigned char v); +long ver2int(const char* version); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/misc/arq_io.cxx b/src/misc/arq_io.cxx index 28721293..1b47b4f0 100644 --- a/src/misc/arq_io.cxx +++ b/src/misc/arq_io.cxx @@ -55,11 +55,14 @@ using namespace std; static string arqtext; -string::iterator pText; +//string::iterator pText; +size_t pText; bool arq_text_available = false; +string txstring; extern void send0x06(); +extern void parse_arqtext(string &toparse); static void set_button(Fl_Button* button, bool value) { @@ -78,15 +81,16 @@ void ParseMode(string src) int msecs = 100; if (src.length() > 7) sscanf( src.substr(7, src.length() - 7).c_str(), "%d", &msecs); - push2talk->set(true); + REQ_SYNC(&PTT::set, push2talk, true);//push2talk->set(true); MilliSleep(msecs); - push2talk->set(false); + REQ_SYNC(&PTT::set, push2talk, false);//push2talk->set(false); LOG_DEBUG("ARQ ptt toggled"); return; } for (size_t i = 0; i < NUM_MODES; ++i) { if (strlen(mode_info[i].pskmail_name) > 0) { if (src == mode_info[i].pskmail_name) { + while (trx_state != STATE_RX) MilliSleep(50); REQ_SYNC(init_modem_sync, mode_info[i].mode); LOG_DEBUG("ARQ new modem set to %s", mode_info[i].pskmail_name); break; @@ -95,18 +99,19 @@ LOG_DEBUG("ARQ new modem set to %s", mode_info[i].pskmail_name); } } -void parse_arqtext() +void parse_arqtext(string &toparse) { string strCmdText; string strSubCmd; unsigned long int idxCmd, idxCmdEnd, idxSubCmd, idxSubCmdEnd; - idxCmd = arqtext.find(""); - idxCmdEnd = arqtext.find(""); + idxCmd = toparse.find(""); + idxCmdEnd = toparse.find(""); if ( idxCmd != string::npos && idxCmdEnd != string::npos && idxCmdEnd > idxCmd ) { -LOG_DEBUG("Command string: %s", arqtext.substr(idxCmd, idxCmdEnd + 6).c_str()); - strCmdText = arqtext.substr(idxCmd + 5, idxCmdEnd - idxCmd - 5); + +LOG_DEBUG("Command string: %s", toparse.substr(idxCmd, idxCmdEnd + 6).c_str()); + strCmdText = toparse.substr(idxCmd + 5, idxCmdEnd - idxCmd - 5); if (strCmdText == "server" && mailserver == false && mailclient == false) { mailserver = true; mailclient = false; @@ -149,9 +154,9 @@ LOG_DEBUG("ARQ is reset to normal ops"); } } } - arqtext.erase(idxCmd, idxCmdEnd - idxCmd + 6); - if (arqtext.length() == 1 && arqtext[0] == '\n') - arqtext = ""; + toparse.erase(idxCmd, idxCmdEnd - idxCmd + 6); + if (toparse.length() == 1 && toparse[0] == '\n') + toparse = ""; } } @@ -170,19 +175,19 @@ void process_msgque() memset(txmsgst.buffer, ARQBUFSIZ, 0); int nbytes = msgrcv (txmsgid, (void *)&txmsgst, ARQBUFSIZ, 0, IPC_NOWAIT); if (nbytes > 0) { - arqtext.clear(); - arqtext = txmsgst.buffer; - parse_arqtext(); - if (arqtext.length() > 0) { + txstring.append(txmsgst.buffer); + parse_arqtext(txstring); + + if (arqtext.empty() && !txstring.empty()) { + arqtext = txstring; if (mailserver && progdefaults.PSKmailSweetSpot) active_modem->set_freq(progdefaults.PSKsweetspot); - - pText = arqtext.begin(); + pText = 0; arq_text_available = true; - active_modem->set_stopflag(false); - start_tx(); +LOG_DEBUG("SYSV ARQ string: %s", txstring.c_str()); + txstring.clear(); } } } @@ -243,9 +248,8 @@ bool TLF_arqRx() while (!autofile.eof()) { memset(mailline,0,1000); autofile.getline(mailline, 998); // leave space for "\n" and null byte - arqtext.append(mailline); - arqtext.append("\n"); - FL_AWAKE(); + txstring.append(mailline); + txstring.append("\n"); time(&prog_time); if (prog_time - start_time > TIMEOUT) { LOG_ERROR("TLF file_i/o failure"); @@ -257,17 +261,19 @@ bool TLF_arqRx() autofile.close(); std::remove (sAutoFile.c_str()); - parse_arqtext(); - if (arqtext.length() > 0) { + parse_arqtext(txstring); + if (arqtext.empty() && !txstring.empty()) { + arqtext = txstring; if (mailserver && progdefaults.PSKmailSweetSpot) active_modem->set_freq(progdefaults.PSKsweetspot); - - pText = arqtext.begin(); + pText = 0; arq_text_available = true; - active_modem->set_stopflag(false); start_tx(); +LOG_DEBUG("TLF string: %s", txstring.c_str()); + txstring.clear(); } + } return true; } @@ -292,13 +298,12 @@ extern void arq_run(Socket s); extern void arq_stop(); string errstring; -string txstring; string cmdstring; string response; bool isTxChar = false; bool isCmdChar = false; -bool isPskMail = false; +bool isNotMULTIPSK = false; static pthread_t* arq_socket_thread = 0; ARQ_SOCKET_Server* ARQ_SOCKET_Server::inst = 0; @@ -410,13 +415,18 @@ void WriteARQsocket(unsigned int data) string response; - if (data == 0x06) { + if (isNotMULTIPSK) { + response = ""; + response += data; + } else { + if (data == 0x06) { response = MPSK_ISCMD; response.append("RX_AFTER_TX OK"); response += MPSK_CMDEND; - } else { - response = MPSK_ISRX; - response += data; + } else { + response = MPSK_ISRX; + response += data; + } } try { arqclient.send(response); @@ -436,45 +446,46 @@ bool Socket_arqRx() try { size_t n = arqclient.recv(instr); - if ( n == 0) return false; - - for (size_t i = 0; i < n; i++) { - cs = instr[i]; - if (cs == MPSK_BYTE) { - isTxChar = true; - continue; - } - if (cs == MPSK_CMD) { - isCmdChar = true; - continue; - } - if (isCmdChar) { - if (cs == MPSK_END) - isCmdChar = false; - else - cmdstring += cs; - continue; - } - if (isPskMail) { - txstring += cs; - continue; - } - if (isTxChar) { - txstring += cs; - isTxChar = false; - continue; + if ( n > 0) { + for (size_t i = 0; i < n; i++) { + cs = instr[i]; + if (cs == MPSK_BYTE) { + isTxChar = true; + continue; + } + if (cs == MPSK_CMD) { + isCmdChar = true; + continue; + } + if (isCmdChar) { + if (cs == MPSK_END) + isCmdChar = false; + else + cmdstring += cs; + continue; + } + if (isNotMULTIPSK) { + txstring += cs; + continue; + } + if (isTxChar) { + txstring += cs; + isTxChar = false; + continue; + } } } - - if (cmdstring.find("PSKMAIL-ON") != string::npos) { - isPskMail = true; + if (cmdstring.find("MULTIPSK-OFF") != string::npos) { + isNotMULTIPSK = true; txstring.clear(); LOG_DEBUG (cmdstring.c_str()); + cmdstring.clear(); } - if (cmdstring.find("PSKMAIL-OFF") != string::npos) { - isPskMail = false; + if (cmdstring.find("MULTIPSK-ON") != string::npos) { + isNotMULTIPSK = false; txstring.clear(); LOG_DEBUG (cmdstring.c_str()); + cmdstring.clear(); } if (progdefaults.rsid == true) { @@ -487,22 +498,18 @@ LOG_DEBUG (cmdstring.c_str()); if (arqtext.empty() && !txstring.empty()) { arqtext = txstring; - parse_arqtext(); + parse_arqtext(arqtext); if (!arqtext.empty()) { if (mailserver && progdefaults.PSKmailSweetSpot) active_modem->set_freq(progdefaults.PSKsweetspot); - pText = arqtext.begin(); + pText = 0;//arqtext.begin(); arq_text_available = true; active_modem->set_stopflag(false); start_tx(); +LOG_DEBUG("ARQ string: %s", txstring.c_str()); } -LOG_DEBUG("ARQ string: %s", txstring.c_str()); - } else if (!txstring.empty()) { - arqtext.append(txstring); -LOG_DEBUG("ARQ string: %s", txstring.c_str()); + txstring.clear(); } - - txstring.clear(); cmdstring.clear(); return true; } @@ -542,7 +549,7 @@ void WriteARQ( unsigned int data) void AbortARQ() { if (arq_text_available) { arqtext.clear(); - pText = arqtext.begin(); + pText = 0;//arqtext.begin(); arq_text_available = false; WriteARQ(0x06); } @@ -556,18 +563,21 @@ void send0x06() { if (trx_state == STATE_RX) { bSend0x06 = false; + arq_text_available = false; WriteARQ(0x06); } } char arq_get_char() { - if (pText != arqtext.end()) - return *pText++; + if (pText != arqtext.length()-1) //arqtext.end()) + return arqtext[pText++]; +// return *pText++; arqtext.clear(); + pText = 0; bSend0x06 = true; - arq_text_available = false; +// arq_text_available = false; return 0x03; // tells psk modem to return to rx } @@ -614,6 +624,9 @@ void arq_init() { arq_enabled = false; + txstring.clear(); + cmdstring.clear(); + if (!ARQ_SOCKET_Server::start( progdefaults.arq_address.c_str(), progdefaults.arq_port.c_str() )) return; diff --git a/src/misc/macroedit.cxx b/src/misc/macroedit.cxx index 5d83754a..43c46e17 100644 --- a/src/misc/macroedit.cxx +++ b/src/misc/macroedit.cxx @@ -9,6 +9,7 @@ #include "macros.h" #include "macroedit.h" #include "globals.h" +#include "status.h" #include @@ -138,10 +139,13 @@ void cbInsertMacro(Fl_Widget *, void *) macrotext->take_focus(); } -Fl_Double_Window* make_macroeditor() { - Fl_Double_Window* w; - { Fl_Double_Window* o = new Fl_Double_Window(700, 230, "Edit User Macro"); - w = o; +static string editor_label; + +Fl_Double_Window* make_macroeditor(void) +{ + editor_label.append("Macro editor - ").append(progStatus.LastMacroFile); + + Fl_Double_Window* w = new Fl_Double_Window(700, 230, editor_label.c_str()); labeltext = new Fl_Input(114, 15, 95, 25, "Label:"); btnMacroEditOK = new Fl_Button(500, 15, 75, 25, "OK"); @@ -160,8 +164,7 @@ Fl_Double_Window* make_macroeditor() { macroDefs = new Fl_Hold_Browser(490, 60, 200, 165); macroDefs->column_widths(widths); loadBrowser(macroDefs); - o->end(); - } + w->end(); return w; } diff --git a/src/misc/network.cxx b/src/misc/network.cxx new file mode 100644 index 00000000..eb8ad4c5 --- /dev/null +++ b/src/misc/network.cxx @@ -0,0 +1,44 @@ +#include +#include +#include + +#include "network.h" +#include "socket.h" +#include "re.h" + +using namespace std; + +bool request_reply(const string& node, const string& service, const string& request, string& reply, double timeout) +{ + try { + Socket s(Address(node, service)); + s.connect(); + s.set_nonblocking(); + s.set_timeout(timeout); + + if (s.send(request) != request.length() || s.recv(reply) == 0) { + reply = "Request timed out"; + return false; + } + } + catch (const SocketException& e) { + reply = e.what(); + return false; + } + + return true; +} + +bool fetch_http(const string& url, string& reply, double timeout) +{ + re_t http_re("http://([^/]+)(.+)", REG_EXTENDED | REG_ICASE); + + if (!http_re.match(url.c_str()) || http_re.nsub() != 3) + return false; + + string request; + request.append("GET ").append(http_re.submatch(2)).append(" HTTP/1.0\n") + .append("Host: ").append(http_re.submatch(1)).append("\nConnection: close\n\n"); + + return request_reply(http_re.submatch(1), "http", request, reply, timeout); +} diff --git a/src/misc/qrzcall.cxx b/src/misc/qrzcall.cxx index ec3a14a2..f24d5a8c 100644 --- a/src/misc/qrzcall.cxx +++ b/src/misc/qrzcall.cxx @@ -49,6 +49,7 @@ #include "xmlreader.h" #include "debug.h" +#include "network.h" using namespace std; @@ -73,8 +74,6 @@ string qrzlatd; string qrzlond; string qrznotes; -const char* error_string; - enum QUERYTYPE { NONE, QRZCD, QRZNET, HAMCALLNET }; QUERYTYPE DB_query = NONE; @@ -93,8 +92,6 @@ static void *CALLSIGNloop(void *args); bool parseSessionKey(); bool parse_xml(); -bool request_reply(const string& node, const string& service, const string& request, string& reply); - bool getSessionKey(string& sessionpage); bool QRZGetXML(string& xmlpage); int bearing(const char *, const char *); @@ -303,32 +300,6 @@ bool parse_xml(const string& xmlpage) return true; } -bool request_reply(const string& node, const string& service, const string& request, string& reply) -{ - try { - Socket s(Address(node, service)); - s.connect(); - s.set_nonblocking(); - struct timeval timeout = { 5, 0 }; // timeout = 5 seconds - s.set_timeout(timeout); - - if (s.send(request) != request.length()) { - error_string = "Request timed out"; - return false; - } - if (s.recv(reply) == 0) { - error_string = "Request timed out"; - return false; - } - } - catch (const SocketException& e) { - error_string = e.what(); - return false; - } - - return true; -} - bool getSessionKey(string& sessionpage) { @@ -348,7 +319,7 @@ bool getSessionKey(string& sessionpage) detail += "Connection: close\n"; detail += "\n"; - return request_reply(qrzhost, "http", detail, sessionpage); + return request_reply(qrzhost, "http", detail, sessionpage, 5.0); } bool QRZGetXML(string& xmlpage) @@ -365,7 +336,7 @@ bool QRZGetXML(string& xmlpage) detail += "Connection: close\n"; detail += "\n"; - return request_reply(qrzhost, "http", detail, xmlpage); + return request_reply(qrzhost, "http", detail, xmlpage, 5.0); } int bearing(const char *myqra, const char *dxqra) { @@ -607,7 +578,7 @@ void QRZquery() } if (!ok) { FL_LOCK(); - inpNotes->value(error_string); + inpNotes->value(qrzpage.c_str()); FL_UNLOCK(); } } @@ -674,7 +645,7 @@ bool HAMCALLget(string& htmlpage) url_detail += VERSION; url_detail += "\r\n"; - return request_reply("www.hamcall.net", "http", url_detail, htmlpage); + return request_reply("www.hamcall.net", "http", url_detail, htmlpage, 5.0); } void HAMCALLquery() @@ -687,7 +658,7 @@ void HAMCALLquery() QRZ_disp_result(); } else { FL_LOCK(); - inpNotes->value(error_string); + inpNotes->value(htmlpage.c_str()); FL_UNLOCK(); } } diff --git a/src/misc/re.cxx b/src/misc/re.cxx index 73d0fa7c..2b311e39 100644 --- a/src/misc/re.cxx +++ b/src/misc/re.cxx @@ -97,7 +97,7 @@ bool re_t::match(const char* str, int eflags_) if (found && !nosub) { for (vector::iterator i = suboff.begin(); i != suboff.end(); i++) if (i->rm_so != -1) - substr.push_back(string(str + i->rm_so, i->rm_eo)); + substr.push_back(string(str + i->rm_so, i->rm_eo - i->rm_so)); } return found; @@ -105,5 +105,5 @@ bool re_t::match(const char* str, int eflags_) const char* re_t::submatch(size_t n) { - return n < substr.size() ? substr[n].c_str() : 0; + return n < nsub() ? substr[n].c_str() : 0; } diff --git a/src/misc/socket.cxx b/src/misc/socket.cxx index 0228fc21..2c7197b8 100644 --- a/src/misc/socket.cxx +++ b/src/misc/socket.cxx @@ -38,6 +38,7 @@ #include #include #include +#include #include "debug.h" #include "socket.h" @@ -583,7 +584,7 @@ Socket Socket::accept1(void) } /// -/// Connects the socket to the address that associated with the object +/// Connects the socket to the address that is associated with the object /// void Socket::connect(void) { @@ -737,6 +738,11 @@ void Socket::set_timeout(const struct timeval& t) timeout.tv_sec = t.tv_sec; timeout.tv_usec = t.tv_usec; } +void Socket::set_timeout(double t) +{ + timeout.tv_sec = (time_t)floor(t); + timeout.tv_usec = (suseconds_t)((t - timeout.tv_sec) * 1e6); +} /// /// Sets the socket's autoclose mode. diff --git a/src/misc/threads.cxx b/src/misc/threads.cxx index ccb81371..7304532c 100644 --- a/src/misc/threads.cxx +++ b/src/misc/threads.cxx @@ -54,3 +54,13 @@ int pthread_cond_timedwait_rel(pthread_cond_t* cond, pthread_mutex_t* mutex, dou return pthread_cond_timedwait(cond, mutex, &t); } + +#ifndef NDEBUG +bool thread_in_list(int id, const int* list) +{ + while (*list != INVALID_TID) + if (id == *list++) + return true; + return false; +} +#endif diff --git a/src/misc/util.cxx b/src/misc/util.cxx index 0040b704..70e88469 100644 --- a/src/misc/util.cxx +++ b/src/misc/util.cxx @@ -27,8 +27,26 @@ uint32_t floor2(uint32_t n) return n - (n >> 1); } -#if !HAVE_STRCASESTR # include +#include "re.h" +long ver2int(const char* version) +{ + const char version_re[] = "([0-9])\\.([0-9]+)\\.?([0-9]+)?"; + re_t re(version_re, REG_EXTENDED); + long v = 0; + + if (!re.match(version)) + return 0; + + if (re.nsub() == 4) + v += strtol(re.submatch(3), NULL, 10); + v += strtol(re.submatch(2), NULL, 10) * 1000L; + v += strtol(re.submatch(1), NULL, 10) * 1000000L; + + return v; +} + +#if !HAVE_STRCASESTR # include # include // a simple inefficient implementation of strcasestr diff --git a/src/misc/xmlrpc.cxx b/src/misc/xmlrpc.cxx index 42fb4ab3..20e69802 100644 --- a/src/misc/xmlrpc.cxx +++ b/src/misc/xmlrpc.cxx @@ -73,7 +73,7 @@ struct rpc_method typedef list methods_t; methods_t* methods = 0; -static pthread_t* server_thread; +static pthread_t* server_thread = 0; XML_RPC_Server* XML_RPC_Server::inst = 0; @@ -111,6 +111,10 @@ void XML_RPC_Server::start(const char* node, const char* service) } catch (const SocketException& e) { LOG_ERROR("Could not start XML-RPC server (%s)", e.what()); + delete server_thread; + server_thread = 0; + delete inst; + inst = 0; return; } diff --git a/src/rigcontrol/hamlib.cxx b/src/rigcontrol/hamlib.cxx index 2e9bb4cc..e5f2b82e 100644 --- a/src/rigcontrol/hamlib.cxx +++ b/src/rigcontrol/hamlib.cxx @@ -26,7 +26,9 @@ #include "rigdialog.h" #include "stacktrace.h" -#include "re.h" +#ifdef CYGWIN +# include "serial.h" +#endif #include "debug.h" using namespace std; @@ -59,27 +61,6 @@ void show_error(const char* msg1, const char* msg2 = 0) LOG_ERROR("%s", error.c_str()); } -#ifdef __CYGWIN__ -// convert COMx to /dev/ttySy with y = x - 1 -static void adjust_port(string& port) -{ - re_t re("com([0-9]+)", REG_EXTENDED | REG_ICASE); - const char* s; - if (!(re.match(port.c_str()) && (s = re.submatch(1)))) - return; - stringstream ss; - int n; - ss << s; - ss >> n; - if (--n < 0) - n = 0; - ss.clear(); ss.str(""); - ss << "/dev/ttyS" << n; - ss.seekp(0); - port = ss.str(); -} -#endif - bool hamlib_init(bool bPtt) { rig_model_t model; diff --git a/src/rigcontrol/rigdialog.cxx b/src/rigcontrol/rigdialog.cxx index d4be0639..8a75a4b3 100644 --- a/src/rigcontrol/rigdialog.cxx +++ b/src/rigcontrol/rigdialog.cxx @@ -2,8 +2,10 @@ #include "rigdialog.h" #include +#include #include #include "rigsupport.h" +using namespace std; cFreqControl *FreqDisp=(cFreqControl *)0; diff --git a/src/rigcontrol/rigdialog.fl b/src/rigcontrol/rigdialog.fl index 00d2d4c3..44d8df11 100644 --- a/src/rigcontrol/rigdialog.fl +++ b/src/rigcontrol/rigdialog.fl @@ -4,10 +4,14 @@ header_name {.h} code_name {.cxx} decl {\#include } {} +decl {\#include } {} + decl {\#include } {} decl {\#include "rigsupport.h"} {} +decl {using namespace std;} {} + Function {rig_dialog()} {open } { Fl_Window {} { diff --git a/src/rigcontrol/serial.cxx b/src/rigcontrol/serial.cxx index 7860577d..67466732 100644 --- a/src/rigcontrol/serial.cxx +++ b/src/rigcontrol/serial.cxx @@ -7,24 +7,34 @@ //----------------------------------------------------------------------------- #include + +#include +#include +#include +#include +#include +#include + +#include #include -#include #include "serial.h" -#include "re.h" #include "debug.h" +using namespace std; + #ifdef __CYGWIN__ +#include +#include "re.h" // convert COMx to /dev/ttySy with y = x - 1 -static void adjust_port(string& port) +void adjust_port(string& port) { re_t re("com([0-9]+)", REG_EXTENDED | REG_ICASE); - const char* s; - if (!(re.match(port.c_str()) && (s = re.submatch(1)))) + if (!(re.match(port.c_str()) && re.nsub() == 2)) return; stringstream ss; int n; - ss << s; + ss << re.submatch(1); ss >> n; if (--n < 0) n = 0; diff --git a/src/soundcard/soundconf.cxx b/src/soundcard/soundconf.cxx index 912166ec..f814179d 100644 --- a/src/soundcard/soundconf.cxx +++ b/src/soundcard/soundconf.cxx @@ -92,8 +92,8 @@ static void init_portaudio(void) #elif defined(__CYGWIN__) pa_api_prio[paASIO] = 0; pa_api_prio[paWASAPI] = 1; - pa_api_prio[paDirectSound] = 2; - pa_api_prio[paMME] = 3; + pa_api_prio[paMME] = 2; + pa_api_prio[paDirectSound] = 3; #else pa_api_prio[paALSA] = 0; pa_api_prio[paJACK] = 1; diff --git a/src/trx/trx.cxx b/src/trx/trx.cxx index 1fc91447..4742b170 100644 --- a/src/trx/trx.cxx +++ b/src/trx/trx.cxx @@ -52,6 +52,7 @@ void trx_start_modem_loop(); void trx_receive_loop(); void trx_transmit_loop(); void trx_tune_loop(); +static void signal_trx_state(void); //#define DEBUG @@ -321,7 +322,13 @@ void *trx_loop(void *args) { SET_THREAD_ID(TRX_TID); + state_t old_state = STATE_NOOP; + for (;;) { + if (unlikely(old_state != trx_state)) { + old_state = trx_state; + signal_trx_state(); + } switch (trx_state) { case STATE_ABORT: delete scard; @@ -351,32 +358,21 @@ void *trx_loop(void *args) } //============================================================================= -modem *trx_m; +modem* new_modem; void trx_start_modem_loop() { - if (trx_m == active_modem) { - trx_state = STATE_RX; + if (new_modem == active_modem) { active_modem->restart(); - signal_modem_ready(); + trx_state = STATE_RX; return; } modem* old_modem = active_modem; - if (old_modem == trx_m) { - trx_state = STATE_RX; - signal_modem_ready(); - return; - } - - if (old_modem) - old_modem->shutdown(); - - active_modem = trx_m; - active_modem->init(); + new_modem->init(); + active_modem = new_modem; trx_state = STATE_RX; - signal_modem_ready(); REQ(&waterfall::opmode, wf); if (old_modem) { @@ -388,7 +384,7 @@ void trx_start_modem_loop() //============================================================================= void trx_start_modem(modem *m) { - trx_m = m; + new_modem = m; trx_state = STATE_NEW_MODEM; } @@ -538,36 +534,24 @@ void trx_tune(void) { trx_state = STATE_TUNE; } void trx_receive(void) { trx_state = STATE_RX; } //============================================================================= -void wait_modem_ready_prep(void) -{ -#ifndef NDEBUG - if (GET_THREAD_ID() == TRX_TID) - LOG_ERROR("trx thread called wait_modem_ready_prep!"); -#endif +void wait_trx_state_prep(void) +{ pthread_mutex_lock(&trx_cond_mutex); } - -void wait_modem_ready_cmpl(void) +void wait_trx_state_wait(void) { -#ifndef NDEBUG - if (GET_THREAD_ID() == TRX_TID) - LOG_ERROR("trx thread called wait_modem_ready_cmpl!"); -#endif - pthread_cond_wait(&trx_cond, &trx_cond_mutex); +} +void wait_trx_state_cmpl(void) +{ pthread_mutex_unlock(&trx_cond_mutex); } -void signal_modem_ready(void) +static void signal_trx_state(void) { -#ifndef NDEBUG - if (GET_THREAD_ID() != TRX_TID) - LOG_ERROR("thread %d called signal_modem_ready!", GET_THREAD_ID()); -#endif - + ENSURE_THREAD(TRX_TID); pthread_mutex_lock(&trx_cond_mutex); pthread_cond_broadcast(&trx_cond); pthread_mutex_unlock(&trx_cond_mutex); } - diff --git a/src/waterfall/waterfall.cxx b/src/waterfall/waterfall.cxx index 2b683429..9c00d30a 100644 --- a/src/waterfall/waterfall.cxx +++ b/src/waterfall/waterfall.cxx @@ -1516,7 +1516,8 @@ int WFdisp::handle(int event) } if (progdefaults.WaterfallHistoryDefault) bHistory = true; - newcarrier = cursorFreq(xpos); + if ((newcarrier = cursorFreq(xpos)) > wf->wfcarrier->maximum()) + break; active_modem->set_freq(newcarrier); if (!(Fl::event_state() & FL_SHIFT)) active_modem->set_sigsearch(SIGSEARCH);