// ---------------------------------------------------------------------------- // configuration.cxx // // Copyright (C) 2006-2010 // Dave Freese, W1HKJ // Copyright (C) 2007-2008 // Leigh L. Klotz, Jr., WA5ZNU // Copyright (C) 2007-2010 // Stelios Bounanos, M0GLD // // This file is part of fldigi. // // Fldigi is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Fldigi is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with fldigi. If not, see . // ---------------------------------------------------------------------------- #include #include "configuration.h" #include "confdialog.h" #include "xmlreader.h" #include "soundconf.h" #include "fl_digi.h" #include "main.h" #include "gettext.h" #include "nls.h" #include "icons.h" #if USE_HAMLIB #include "hamlib.h" #include "rigclass.h" #endif #include "rigMEM.h" #include "rigio.h" #include "rigxml.h" #include "debug.h" #include #include #include #include #include #include #ifdef __linux__ # include # include # include #endif #ifdef __APPLE__ # include #endif #ifndef __CYGWIN__ # include #else # include #endif // this tests depends on a modified FL/filename.H in the Fltk-1.3.0 // change //# if defined(WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) // to //# if defined(WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) && !defined(__WOE32__) #ifdef __MINGW32__ # if FLDIGI_FLTK_API_MAJOR == 1 && FLDIGI_FLTK_API_MINOR < 3 # undef dirent # include # else # include # endif #else # include #endif using namespace std; const char *szBaudRates[] = { "", "300","600","1200","2400", "4800","9600","19200","38400", "57600","115200","230400","460800"}; const char *szBands[] = { "", "1830", "3580", "7030", "7070", "10138", "14070", "18100", "21070", "21080", "24920", "28070", "28120", 0}; #if FLDIGI_FLTK_API_MAJOR == 1 && FLDIGI_FLTK_API_MINOR == 1 // Define stream I/O operators for non-builtin types. // Right now we have: Fl_Color, Fl_Font, RGB, and RGBI ostream& operator<<(ostream& out, const Fl_Color& c) { return out << static_cast(c); } istream& operator>>(istream& in, Fl_Color& c) { int i; in >> i; c = static_cast(i); return in; } ostream& operator<<(ostream& out, const Fl_Font& f) { return out << static_cast(f); } istream& operator>>(istream& in, Fl_Font& f) { int i; in >> i; f = static_cast(i); return in; } #endif ostream& operator<<(ostream& out, const RGB& rgb) { return out << (int)rgb.R << ' ' << (int)rgb.G << ' ' << (int)rgb.B; } istream& operator>>(istream& in, RGB& rgb) { int i; in >> i; rgb.R = i; in >> i; rgb.G = i; in >> i; rgb.B = i; return in; } ostream& operator<<(ostream& out, const RGBI& rgbi) { return out << (int)rgbi.R << ' ' << (int)rgbi.G << ' ' << (int)rgbi.B; } istream& operator>>(istream& in, RGBI& rgbi) { int i; in >> i; rgbi.R = i; in >> i; rgbi.G = i; in >> i; rgbi.B = i; return in; } // This allows to put tag elements into containers class tag_base { public: tag_base(const char* t, const char* d = "") : tag(t), doc(d) { } virtual void write(ostream& out) const = 0; virtual void read(const char* data) = 0; virtual ~tag_base() { } const char* tag; const char* doc; }; // This will handle every type that has << and >> stream operators template class tag_elem : public tag_base { public: tag_elem(const char* t, const char* d, T& v) : tag_base(t, d), var(v) { } void write(ostream& out) const { out << "\n" << '<' << tag << '>' << var << "\n\n"; } void read(const char* data) { istringstream iss(data); iss >> var; } T& var; }; // Instantiate an explicit tag_elem for types that require unusual handling. // Special handling for strings template <> class tag_elem : public tag_base { public: tag_elem(const char* t, const char* d, string& s) : tag_base(t, d), str(s) { } void write(ostream& out) const { string s = str; string s2 = doc; string::size_type i = s.find('&'); while (i != string::npos) { s.replace(i, 1, "&"); i = s.find('&', i + 1); } while ((i = s.find('<')) != string::npos) s.replace(i, 1, "<"); while ((i = s.find('>')) != string::npos) s.replace(i, 1, ">"); while ((i = s.find('"')) != string::npos) s.replace(i, 1, """); while ((i = s.find('\'')) != string::npos) s.replace(i, 1, "'"); i = s2.find('&'); while (i != string::npos) { s2.replace(i, 1, "&"); i = s2.find('&', i + 1); } while ((i = s2.find('<')) != string::npos) s2.replace(i, 1, "<"); while ((i = s2.find('>')) != string::npos) s2.replace(i, 1, ">"); while ((i = s2.find('"')) != string::npos) s2.replace(i, 1, """); while ((i = s2.find('\'')) != string::npos) s2.replace(i, 1, "'"); out << "\n" << '<' << tag << '>' << s << "\n\n"; } void read(const char* data) { str = data; } string& str; }; #include "re.h" // Special handling for mode bitsets template <> class tag_elem : public tag_base { public: tag_elem(const char* t, const char* d, mode_set_t& m) : tag_base(t, d), modes(m) { } void write(ostream& out) const { out << "\n" << '<' << tag << '>'; for (size_t i = 0; i < modes.size(); i++) if (!modes.test(i)) out << mode_info[i].name << ','; out << ",\n\n"; } void read(const char* data) { re_t mode_name_re("([^,]+)", REG_EXTENDED); int end; modes.set(); while (mode_name_re.match(data)) { const char* name = mode_name_re.submatch(1).c_str(); for (size_t i = 0; i < modes.size(); i++) { if (!strcmp(mode_info[i].name, name)) { modes.set(i, 0); break; } } mode_name_re.suboff(0, NULL, &end); data += end; } } mode_set_t& modes; }; // By redefining the ELEM_ macro, we can control what the CONFIG_LIST macro // will expand to, and accomplish several things: // 1) Declare "struct configuration". See ELEM_DECLARE_CONFIGURATION // in configuration.h. // 2) Define progdefaults, the configuration struct that is initialised with // fldigi's default options #define ELEM_PROGDEFAULTS(type_, var_, tag_, doc_, ...) __VA_ARGS__, // 3) Define an array of tag element pointers #define ELEM_TAG_ARRAY(type_, var_, tag_, doc_, ...) \ (*tag_ ? new tag_elem(tag_, "type: " #type_ "; default: " #__VA_ARGS__ "\n" doc_, \ progdefaults.var_) : 0), // First define the default config #undef ELEM_ #define ELEM_ ELEM_PROGDEFAULTS configuration progdefaults = { CONFIG_LIST }; void configuration::writeDefaultsXML() { string deffname(HomeDir); deffname.append("fldigi_def.xml"); string deffname_backup(deffname); deffname_backup.append("-old"); rename(deffname.c_str(), deffname_backup.c_str()); ofstream f(deffname.c_str()); if (!f) { LOG_ERROR("Could not write %s", deffname.c_str()); return; } // create an array #undef ELEM_ #define ELEM_ ELEM_TAG_ARRAY tag_base* tag_list[] = { CONFIG_LIST }; // write all variables with non-empty tags to f f << "\n\n"; for (size_t i = 0; i < sizeof(tag_list)/sizeof(*tag_list); i++) { if (tag_list[i]) { tag_list[i]->write(f); delete tag_list[i]; } } f << "\n"; f.close(); } static void log_excluded_modes(void) { struct { mode_set_t* modes; const char* msgstr; } excluded[] = { { &progdefaults.rsid_rx_modes, "RSID (rx)" }, { &progdefaults.rsid_tx_modes, "RSID (tx)" }, { &progdefaults.cwid_modes, "CWID" }, { &progdefaults.videoid_modes, "VIDEOID" } }; string buf; for (size_t i = 0; i < sizeof(excluded)/sizeof(*excluded); i++) { size_t n = excluded[i].modes->size(); if (excluded[i].modes->count() == n) continue; buf.erase(); for (size_t j = 0; j < n; j++) { if (!excluded[i].modes->test(j)) { if (!buf.empty()) buf += ' '; buf += mode_info[j].sname; } } LOG(debug::QUIET_LEVEL, debug::LOG_OTHER, "%-10s: %s", excluded[i].msgstr, buf.c_str()); } } bool configuration::readDefaultsXML() { // Decode all RSID modes rsid_rx_modes.set(); // Don't transmit RSID or VideoID for CW, PSK31, RTTY rsid_tx_modes.set().reset(MODE_CW).reset(MODE_PSK31).reset(MODE_RTTY); videoid_modes = rsid_tx_modes; // Don't transmit CWID for CW cwid_modes.set().reset(MODE_CW); // Show all op modes visible_modes.set(); string deffname = HomeDir; deffname.append("fldigi_def.xml"); ifstream f(deffname.c_str()); if (!f) return false; string xmlbuf; f.seekg(0, ios::end); xmlbuf.reserve(f.tellg()); // reserve some space to avoid reallocations f.seekg(0, ios::beg); char line[2048]; while (f.getline(line, sizeof(line))) xmlbuf.append(line).append("\n"); f.close(); IrrXMLReader* xml = createIrrXMLReader(new IIrrXMLStringReader(xmlbuf)); if (!xml) return false; // create a TAG_NAME -> ELEMENT map typedef map tag_map_t; tag_map_t tag_map; tag_base* tag_list[] = { CONFIG_LIST }; for (size_t i = 0; i < sizeof(tag_list)/sizeof(*tag_list); i++) if (tag_list[i]) tag_map[tag_list[i]->tag] = tag_list[i]; // parse the xml buffer tag_map_t::const_iterator i; while(xml->read()) { switch(xml->getNodeType()) { case EXN_TEXT: case EXN_CDATA: if (i != tag_map.end()) // do we know about this tag? i->second->read(xml->getNodeData()); break; case EXN_ELEMENT_END: i = tag_map.end(); // ignore the next EXN_CDATA break; case EXN_ELEMENT: i = tag_map.find(xml->getNodeName()); break; case EXN_NONE: case EXN_COMMENT: case EXN_UNKNOWN: break; } } delete xml; // delete the tag objects for (size_t i = 0; i < sizeof(tag_list)/sizeof(*tag_list); i++) delete tag_list[i]; log_excluded_modes(); return true; } void configuration::loadDefaults() { // RTTY if (rtty_shift > 0) { selShift->value(rtty_shift); selCustomShift->deactivate(); } else { // Custom shift selShift->value(selShift->size() - 2); selShift->activate(); } selBaud->value(rtty_baud); selBits->value(rtty_bits); selParity->value(rtty_parity); // chkMsbFirst->value(rtty_msbfirst); selStopBits->value(rtty_stop); btnCRCRLF->value(rtty_crcrlf); btnAUTOCRLF->value(rtty_autocrlf); cntrAUTOCRLF->value(rtty_autocount); chkPseudoFSK->value(PseudoFSK); chkUOSrx->value(UOSrx); chkUOStx->value(UOStx); chkXagc->value(Xagc); mnuRTTYAFCSpeed->value(rtty_afcspeed); btnPreferXhairScope->value(PreferXhairScope); // OLIVIA mnuOlivia_Tones->value(oliviatones); mnuOlivia_Bandwidth->value(oliviabw); cntOlivia_smargin->value(oliviasmargin); cntOlivia_sinteg->value(oliviasinteg); btnOlivia_8bit->value(olivia8bit); // CONTESTIA mnuContestia_Tones->value(contestiatones); mnuContestia_Bandwidth->value(contestiabw); cntContestia_smargin->value(contestiasmargin); cntContestia_sinteg->value(contestiasinteg); btnContestia_8bit->value(contestia8bit); chkDominoEX_FEC->value(DOMINOEX_FEC); btnmt63_interleave->value(mt63_interleave == 64); Fl_Tooltip::enable(tooltips); } void configuration::saveDefaults() { ENSURE_THREAD(FLMAIN_TID); memcpy(&cfgpal0, &palette[0], sizeof(cfgpal0)); memcpy(&cfgpal1, &palette[1], sizeof(cfgpal1)); memcpy(&cfgpal2, &palette[2], sizeof(cfgpal2)); memcpy(&cfgpal3, &palette[3], sizeof(cfgpal3)); memcpy(&cfgpal4, &palette[4], sizeof(cfgpal4)); memcpy(&cfgpal5, &palette[5], sizeof(cfgpal5)); memcpy(&cfgpal6, &palette[6], sizeof(cfgpal6)); memcpy(&cfgpal7, &palette[7], sizeof(cfgpal7)); memcpy(&cfgpal8, &palette[8], sizeof(cfgpal8)); RxFontName = Fl::get_font_name(RxFontnbr); TxFontName = Fl::get_font_name(TxFontnbr); WaterfallFontName = Fl::get_font_name(WaterfallFontnbr); ViewerFontName = Fl::get_font_name(ViewerFontnbr); FreqControlFontName = Fl::get_font_name(FreqControlFontnbr); #if ENABLE_NLS && defined(__WOE32__) set_ui_lang(mnuLang->value()); #endif writeDefaultsXML(); changed = false; } #if USE_HAMLIB static int fill_hamlib_menu(const char* rigname) { cboHamlibRig->add(rigname); return 1; } #endif int configuration::setDefaults() { ENSURE_THREAD(FLMAIN_TID); #if USE_HAMLIB hamlib_get_rigs(); hamlib_get_rig_str(fill_hamlib_menu); if (HamRigModel == 0 && !HamRigName.empty()) { // compatibility with < 3.04 HamRigModel = hamlib_get_rig_model_compat(HamRigName.c_str()); LOG_VERBOSE("Found rig model %d for \"%s\"", HamRigModel, HamRigName.c_str()); } #endif inpMyCallsign->value(myCall.c_str()); inpMyName->value(myName.c_str()); inpMyQth->value(myQth.c_str()); inpMyLocator->value(myLocator.c_str()); inpMyAntenna->value(myAntenna.c_str()); UseLeadingZeros = btnUseLeadingZeros->value(); ContestStart = (int)nbrContestStart->value(); ContestDigits = (int)nbrContestDigits->value(); txtSecondary->value(secText.c_str()); txtTHORSecondary->value(THORsecText.c_str()); valTHOR_BW->value(THOR_BW); valTHOR_FILTER->value(THOR_FILTER); valTHOR_PATHS->value(THOR_PATHS); valThorCWI->value(ThorCWI); valDominoEX_BW->value(DOMINOEX_BW); valDominoEX_FILTER->value(DOMINOEX_FILTER); chkDominoEX_FEC->value(DOMINOEX_FEC); valDominoEX_PATHS->value(DOMINOEX_PATHS); valDomCWI->value(DomCWI); btnMEMMAPptt->value(MEMMAPptt); btnRigCatCMDptt->value(RigCatCMDptt); btnTTYptt->value(TTYptt); btnUsePPortPTT->value(progdefaults.UsePPortPTT); btnUseUHrouterPTT->value(progdefaults.UseUHrouterPTT); #if USE_HAMLIB mnuSideband->add(_("Rig mode")); mnuSideband->add(_("Always LSB")); mnuSideband->add(_("Always USB")); mnuSideband->value(HamlibSideband); btnHamlibCMDptt->value(HamlibCMDptt); inpRIGdev->show(); mnuBaudRate->show(); cboHamlibRig->show(); cboHamlibRig->value(HamRigName.c_str()); #else tabHamlib->parent()->remove(*tabHamlib); #endif btnRTSptt->value(RTSptt); btnDTRptt->value(DTRptt); btnRTSplusV->value(RTSplus); btnDTRplusV->value(DTRplus); inpTTYdev->value(PTTdev.c_str()); if(chkUSEMEMMAPis) { chkUSEMEMMAP->value(1); chkUSEHAMLIB->value(0); chkUSERIGCAT->value(0); chkUSEXMLRPC->value(0); } else if (chkUSEHAMLIBis) { chkUSEHAMLIB->value(1); chkUSEMEMMAP->value(0); chkUSERIGCAT->value(0); chkUSEXMLRPC->value(0); } else if (chkUSERIGCATis) { chkUSERIGCAT->value(1); chkUSEMEMMAP->value(0); chkUSEHAMLIB->value(0); chkUSEXMLRPC->value(0); } else if (chkUSEXMLRPCis) { chkUSEXMLRPC->value(1); chkUSEMEMMAP->value(0); chkUSEHAMLIB->value(0); chkUSERIGCAT->value(0); } else { chkUSEMEMMAP->value(0); chkUSEHAMLIB->value(0); chkUSERIGCAT->value(0); chkUSEHAMLIB->value(0); chkUSEXMLRPC->value(0); } if (!XmlRigFilename.empty()) readRigXML(); inpRIGdev->value(HamRigDevice.c_str()); mnuBaudRate->value(HamRigBaudrate); #if !USE_XMLRPC tabXMLRPC->parent()->remove(*tabXMLRPC); #endif inpXmlRigDevice->value(XmlRigDevice.c_str()); mnuXmlRigBaudrate->value(XmlRigBaudrate); valCWsweetspot->value(CWsweetspot); valRTTYsweetspot->value(RTTYsweetspot); valPSKsweetspot->value(PSKsweetspot); btnWaterfallHistoryDefault->value(WaterfallHistoryDefault); btnWaterfallQSY->value(WaterfallQSY); inpWaterfallClickText->input_type(FL_MULTILINE_INPUT); inpWaterfallClickText->value(WaterfallClickText.c_str()); if (!WaterfallClickInsert) inpWaterfallClickText->deactivate(); for (size_t i = 0; i < sizeof(waterfall::wf_wheel_action)/sizeof(*waterfall::wf_wheel_action); i++) mnuWaterfallWheelAction->add(waterfall::wf_wheel_action[i]); mnuWaterfallWheelAction->value(WaterfallWheelAction); btnStartAtSweetSpot->value(StartAtSweetSpot); btnPSKmailSweetSpot->value(PSKmailSweetSpot); cntSearchRange->value(SearchRange); cntServerOffset->value(ServerOffset); cntACQsn->value(ACQsn); btnCursorBWcolor->color( fl_rgb_color(cursorLineRGBI.R, cursorLineRGBI.G, cursorLineRGBI.B) ); btnCursorCenterLineColor->color( fl_rgb_color(cursorCenterRGBI.R, cursorCenterRGBI.G, cursorCenterRGBI.B) ); btnBwTracksColor->color( fl_rgb_color(bwTrackRGBI.R, bwTrackRGBI.G, bwTrackRGBI.B) ); cntCWweight->value(CWweight); sldrCWxmtWPM->value(CWspeed); cntCWdefWPM->value(defCWspeed); sldrCWbandwidth->value(CWbandwidth); btnCWrcvTrack->value(CWtrack); cntCWrange->value(CWrange); cntCWlowerlimit->value(CWlowerlimit); cntCWupperlimit->value(CWupperlimit); cntCWlowerlimit->maximum(CWupperlimit - 20); cntCWupperlimit->minimum(CWlowerlimit + 20); cntCWrisetime->value(CWrisetime); cntCWdash2dot->value(CWdash2dot); mnuQSKshape->value(QSKshape); sldrCWxmtWPM->minimum(CWlowerlimit); sldrCWxmtWPM->maximum(CWupperlimit); btnQSK->value(QSK); cntPreTiming->value(CWpre); cntPostTiming->value(CWpost); btnCWID->value(CWid); selHellFont->value(feldfontnbr); btnFeldHellIdle->value(HellXmtIdle); btnTxRSID->value(TransmitRSid); btnRSID->value(rsid); chkRSidWideSearch->value(rsidWideSearch); chkSlowCpu->value(slowcpu); Fl_Button* qrzb = btnQRZXMLnotavailable; Fl_Button* qrzb2 = btnQRZWEBnotavailable; switch (QRZXML) { case QRZCD: qrzb = btnQRZcdrom; break; case QRZNET: qrzb = btnQRZsub; break; case HAMCALLNET: qrzb = btnHamcall; break; case CALLOOK: qrzb = btnCALLOOK; break; case HAMQTH: qrzb = btnHamQTH; break; case QRZXMLNONE: default : break; } switch (QRZWEB) { case QRZHTML: qrzb2 = btnQRZonline; break; case HAMCALLHTML: qrzb2 = btnHAMCALLonline; break; case HAMQTHHTML: qrzb2 = btnHamQTHonline; break; case QRZWEBNONE: default : break; } set_qrzxml_buttons(qrzb); set_qrzweb_buttons(qrzb2); txtQRZpathname->value(QRZpathname.c_str()); btnsendid->value(sendid); btnsendvideotext->value(sendtextid); chkID_SMALL->value(ID_SMALL); wf->setPrefilter(wfPreFilter); valLatency->value(latency); btnWFaveraging->value(WFaveraging); memcpy(&palette[0], &cfgpal0, sizeof(palette[0])); memcpy(&palette[1], &cfgpal1, sizeof(palette[1])); memcpy(&palette[2], &cfgpal2, sizeof(palette[2])); memcpy(&palette[3], &cfgpal3, sizeof(palette[3])); memcpy(&palette[4], &cfgpal4, sizeof(palette[4])); memcpy(&palette[5], &cfgpal5, sizeof(palette[5])); memcpy(&palette[6], &cfgpal6, sizeof(palette[6])); memcpy(&palette[7], &cfgpal7, sizeof(palette[7])); memcpy(&palette[8], &cfgpal8, sizeof(palette[8])); wf->setcolors(); setColorButtons(); #if !HAVE_UHROUTER btnUseUHrouterPTT->hide(); #endif #if !HAVE_PARPORT btnUsePPortPTT->hide(); #endif #if ENABLE_NLS && defined(__WOE32__) ostringstream ss; for (lang_def_t* p = ui_langs; p->lang; p++) { ss.str(""); ss << p->native_name << " (" << p->percent_done << "%)"; mnuLang->add(ss.str().c_str()); } mnuLang->value(get_ui_lang()); mnuLang->show(); #else mnuLang->hide(); #endif return 1; } void configuration::resetDefaults(void) { if (!fl_choice2(_("\ Reset all options to their default values?\n\n\ Reset options will take effect at the next start\n\ Files: fldigi_def.xml and fldigi.prefs will be deleted!\n"), _("OK"), _("Cancel"), NULL) && Fl::event_key() != FL_Escape) { if (!fl_choice2(_("Confirm RESET"), _("Yes"), _("No"), NULL) && Fl::event_key() != FL_Escape) { reset(); atexit(reset); } } } void configuration::reset(void) { remove(string(HomeDir).append("fldigi_def.xml").c_str()); remove(string(HomeDir).append("fldigi.prefs").c_str()); } #include "rigio.h" void configuration::initInterface() { ENSURE_THREAD(FLMAIN_TID); // close down any possible rig interface threads #if USE_HAMLIB hamlib_close(); // MilliSleep(100); #endif rigMEM_close(); // MilliSleep(100); rigCAT_close(); // MilliSleep(100); MEMMAPptt = btnMEMMAPptt->value(); RigCatCMDptt = btnRigCatCMDptt->value(); TTYptt = btnTTYptt->value(); RTSptt = btnRTSptt->value(); DTRptt = btnDTRptt->value(); RTSplus = btnRTSplusV->value(); DTRplus = btnDTRplusV->value(); PTTdev = inpTTYdev->value(); #if USE_HAMLIB chkUSEHAMLIBis = chkUSEHAMLIB->value(); HamlibCMDptt = btnHamlibCMDptt->value(); #endif chkUSEMEMMAPis = chkUSEMEMMAP->value(); chkUSERIGCATis = chkUSERIGCAT->value(); #if USE_HAMLIB if (*cboHamlibRig->value() == '\0') // no selection at start up cboHamlibRig->index(hamlib_get_index(HamRigModel)); else HamRigModel = hamlib_get_rig_model(cboHamlibRig->index()); HamRigDevice = inpRIGdev->value(); HamRigBaudrate = mnuBaudRate->value(); #else cboHamlibRig->hide(); inpRIGdev->hide(); mnuBaudRate->hide(); #endif bool riginitOK = false; if (chkUSEMEMMAPis) {// start the memory mapped i/o thread if (rigMEM_init()) { wf->setQSY(1); riginitOK = true; } } else if (chkUSERIGCATis) { // start the rigCAT thread if (rigCAT_init(true)) { wf->USB(true); wf->setQSY(1); riginitOK = true; } #if USE_HAMLIB } else if (chkUSEHAMLIBis) { // start the hamlib thread if (hamlib_init(HamlibCMDptt)) { wf->USB(true); wf->setQSY(1); riginitOK = true; } #endif } else if (chkUSEXMLRPCis) { wf->setXMLRPC(1); rigCAT_init(false); wf->USB(true); wf->setQSY(0); riginitOK = true; } if (riginitOK == false) { rigCAT_init(false); wf->USB(true); wf->setQSY(0); } if (HamlibCMDptt && chkUSEHAMLIBis) push2talk->reset(PTT::PTT_HAMLIB); else if (MEMMAPptt && chkUSEMEMMAPis) push2talk->reset(PTT::PTT_MEMMAP); else if ((RigCatCMDptt || RigCatRTSptt || RigCatDTRptt) && chkUSERIGCATis) push2talk->reset(PTT::PTT_RIGCAT); else if (TTYptt) push2talk->reset(PTT::PTT_TTY); else if (UsePPortPTT) push2talk->reset(PTT::PTT_PARPORT); else if (UseUHrouterPTT) push2talk->reset(PTT::PTT_UHROUTER); else push2talk->reset(PTT::PTT_NONE); wf->setRefLevel(); wf->setAmpSpan(); cntLowFreqCutoff->value(LowFreqCutoff); } const char* configuration::strBaudRate() { return (szBaudRates[HamRigBaudrate + 1]); } int configuration::nBaudRate(const char *szBR) { for (size_t i = 1; i < sizeof(szBaudRates); i++) if (strcmp(szBaudRates[i], szBR) == 0) return i - 1; return 0; } int configuration::BaudRate(size_t n) { if (n > sizeof(szBaudRates) + 1) return 1200; return (atoi(szBaudRates[n + 1])); } #ifdef __WOE32__ static bool open_serial(const char* dev) { bool ret = false; #ifdef __CYGWIN__ int fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY); if (fd != -1) { close(fd); ret = true; } #elif defined(__MINGW32__) HANDLE fd = CreateFile(dev, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if (fd != INVALID_HANDLE_VALUE) { CloseHandle(fd); ret = true; } #endif return ret; } #endif // __WOE32__ void configuration::testCommPorts() { int retval; inpTTYdev->clear(); inpRIGdev->clear(); inpXmlRigDevice->clear(); #ifndef PATH_MAX # define PATH_MAX 1024 #endif #ifndef __WOE32__ struct stat st; #endif #ifndef __APPLE__ char ttyname[PATH_MAX + 1]; #endif #ifdef __linux__ bool ret = false; DIR* sys = NULL; char cwd[PATH_MAX] = { '.', '\0' }; if (getcwd(cwd, sizeof(cwd)) == NULL || chdir("/sys/class/tty") == -1 || (sys = opendir(".")) == NULL) goto out; ssize_t len; struct dirent* dp; while ((dp = readdir(sys))) { # ifdef _DIRENT_HAVE_D_TYPE if (dp->d_type != DT_LNK) continue; # endif if ((len = readlink(dp->d_name, ttyname, sizeof(ttyname)-1)) == -1) continue; ttyname[len] = '\0'; if (!strstr(ttyname, "/devices/virtual/")) { snprintf(ttyname, sizeof(ttyname), "/dev/%s", dp->d_name); if (stat(ttyname, &st) == -1 || !S_ISCHR(st.st_mode)) continue; LOG_VERBOSE("Found serial port %s", ttyname); inpTTYdev->add(ttyname); #if USE_HAMLIB inpRIGdev->add(ttyname); #endif inpXmlRigDevice->add(ttyname); } } ret = true; out: if (sys) closedir(sys); retval = chdir(cwd); if (ret) // do we need to fall back to the probe code below? return; #endif // __linux__ // TODO: will the mingw probing work for cygwin too? const char* tty_fmt[] = { #if defined(__linux__) "/dev/ttyS%u", "/dev/ttyUSB%u", "/dev/usb/ttyUSB%u" #elif defined(__FreeBSD__) "/dev/ttyd%u" #elif defined(__CYGWIN__) "/dev/ttyS%u" #elif defined(__MINGW32__) "//./COM%u" #elif defined(__APPLE__) "/dev/cu.*", "/dev/tty.*" #endif }; #if defined(__WOE32__) # define TTY_MAX 255 #elif defined(__APPLE__) glob_t gbuf; #else # define TTY_MAX 8 #endif for (size_t i = 0; i < sizeof(tty_fmt)/sizeof(*tty_fmt); i++) { #ifndef __APPLE__ for (unsigned j = 0; j < TTY_MAX; j++) { snprintf(ttyname, sizeof(ttyname), tty_fmt[i], j); # ifndef __WOE32__ if ( !(stat(ttyname, &st) == 0 && S_ISCHR(st.st_mode)) ) continue; # else // __WOE32__ if (!open_serial(ttyname)) continue; # ifdef __CYGWIN__ snprintf(ttyname, sizeof(ttyname), "COM%u", j+1); # else snprintf(ttyname, sizeof(ttyname), "COM%u", j); # endif # endif // __WOE32__ LOG_VERBOSE("Found serial port %s", ttyname); inpTTYdev->add(ttyname); # if USE_HAMLIB inpRIGdev->add(ttyname); # endif inpXmlRigDevice->add(ttyname); } #else // __APPLE__ glob(tty_fmt[i], 0, NULL, &gbuf); for (size_t j = 0; j < gbuf.gl_pathc; j++) { if ( !(stat(gbuf.gl_pathv[j], &st) == 0 && S_ISCHR(st.st_mode)) || strstr(gbuf.gl_pathv[j], "modem") ) continue; LOG_VERBOSE("Found serial port %s", gbuf.gl_pathv[j]); inpTTYdev->add(gbuf.gl_pathv[j]); # if USE_HAMLIB inpRIGdev->add(gbuf.gl_pathv[j]); # endif inpXmlRigDevice->add(gbuf.gl_pathv[j]); } globfree(&gbuf); #endif // __APPLE__ } #if HAVE_UHROUTER if (stat(UHROUTER_FIFO_PREFIX "Read", &st) != -1 && S_ISFIFO(st.st_mode) && stat(UHROUTER_FIFO_PREFIX "Write", &st) != -1 && S_ISFIFO(st.st_mode)) inpTTYdev->add(UHROUTER_FIFO_PREFIX); #endif // HAVE_UHROUTER } Fl_Font font_number(const char* name) { int n = (int)Fl::set_fonts(0); for (int i = 0; i < n; i++) { if (strcmp(Fl::get_font_name((Fl_Font)i), name) == 0) return (Fl_Font)i; } return FL_HELVETICA; } void configuration::initFonts(void) { if (!RxFontName.empty()) RxFontnbr = font_number(RxFontName.c_str()); if (!TxFontName.empty()) TxFontnbr = font_number(TxFontName.c_str()); if (!WaterfallFontName.empty()) WaterfallFontnbr = font_number(WaterfallFontName.c_str()); if (!ViewerFontName.empty()) ViewerFontnbr = font_number(ViewerFontName.c_str()); if (!FreqControlFontName.empty()) FreqControlFontnbr = font_number(FreqControlFontName.c_str()); }