From 814bed31f8800b4f690d4244fd377d28c1dc3ac4 Mon Sep 17 00:00:00 2001 From: Robert Stiles Date: Sun, 8 Feb 2015 08:40:44 -0600 Subject: [PATCH] Configure Script Engine * Add menu item "Scripts" and callback function. * Add scripting engine. * Update script engine for localization strings/messages. * Add hierarchy syntax * New file run_script.h * Hierarchy integration completed * Add command set * Add 'int find_index(char *)' to combo.cxx * Add menu item 'Generate Script' and code for generating a default config script file. * Add void loadRigXmlFile(void) to rigxml.cxx to support scripting calls. - Trim leading/trailing white spaces from portaudio device names. * Remove duplicate calling functions/method members. * Move command parameter specific verification to run_script.cxx basic testing remains in script_parsing.cxx * First Document Draft - Script commands - Add Misc NBEMS config commands - Add Notice - Program restart required. - Update Documentation with new commands * Removed Unused Variables (multiple locations) * Change behavior of floating point output for script generate. * Remove function qsy() use restriction on rig control availability. * Add strnlen, strncmp and strncpy checks to configure.ac * Add trim_white_spaces, strnlen, strncmp and strncpy routines to util.cxx * Add pa_set_dev() to soundconf.cxx for updating pa device names. * Add code to save macro(s) with content only. * Add config_script files to POTFILES.in for localization processing. * Flag command types. * Limit generate script output based on configure content. * Change script error dialog box to warning. * Change default rig.xml to rig-unassigned.xml. For testing purposes. (script generation) * Update Documents with Notes about script generation and executing. * Correct \ref and \section name duplicates in doxygen doc source * Add script commands for ID->RSID/Video/CW panel. * Move Script/Execute/Generate Menu Items to File Menu. - Move repetitive code into general functions. * Rename "Scripts" menu item to "Config Scripts" * Fix error introduced in last mods. Port Audio Gen Config --- configure.ac | 2 +- fldigi_doxygen/images/menu_script.png | Bin 0 -> 8727 bytes .../images/script_error_log_entry.png | Bin 0 -> 34419 bytes .../images/script_restart_notice.png | Bin 0 -> 12749 bytes .../images/script_warning_dialogbox.png | Bin 0 -> 12545 bytes fldigi_doxygen/user_src_docs/Doxyfile | 2 +- fldigi_doxygen/user_src_docs/MFSK.txt | 4 +- fldigi_doxygen/user_src_docs/Menus.txt | 14 + .../user_src_docs/TransceiverControl.txt | 12 +- fldigi_doxygen/user_src_docs/advanced_qsy.txt | 2 +- fldigi_doxygen/user_src_docs/configCW.txt | 10 +- .../user_src_docs/configure_scripting.txt | 1406 ++++++++ fldigi_doxygen/user_src_docs/index.txt | 1 + m4/macosx.m4 | 4 + po/POTFILES.in | 3 + src/Makefile.am | 5 + src/combo/combo.cxx | 26 +- src/config_script/create_default_script.cxx | 697 ++++ src/config_script/run_script.h | 168 + src/config_script/run_scripts.cxx | 2893 +++++++++++++++++ src/config_script/script_parsing.cxx | 2194 +++++++++++++ src/config_script/script_parsing.h | 470 +++ src/dialogs/fl_digi.cxx | 47 +- src/include/FreqControl.h | 1 + src/include/combo.h | 1 + src/include/fl_digi.h | 4 + src/include/macroedit.h | 1 + src/include/rigsupport.h | 4 + src/include/rigxml.h | 8 +- src/include/sound.h | 2 +- src/include/soundconf.h | 15 +- src/include/util.h | 4 + src/main.cxx | 2 +- src/misc/macroedit.cxx | 39 +- src/misc/util.cxx | 9 + src/misc/xmlrpc.cxx | 2 - src/rigcontrol/FreqControl.cxx | 20 +- src/rigcontrol/rigsupport.cxx | 28 +- src/rigcontrol/rigxml.cxx | 12 +- src/soundcard/sound.cxx | 28 +- src/soundcard/soundconf.cxx | 202 +- src/waterfall/waterfall.cxx | 2 +- src/widgets/FTextRXTX.cxx | 14 +- 43 files changed, 8176 insertions(+), 182 deletions(-) create mode 100644 fldigi_doxygen/images/menu_script.png create mode 100644 fldigi_doxygen/images/script_error_log_entry.png create mode 100644 fldigi_doxygen/images/script_restart_notice.png create mode 100644 fldigi_doxygen/images/script_warning_dialogbox.png create mode 100644 fldigi_doxygen/user_src_docs/configure_scripting.txt create mode 100644 src/config_script/create_default_script.cxx create mode 100644 src/config_script/run_script.h create mode 100644 src/config_script/run_scripts.cxx create mode 100644 src/config_script/script_parsing.cxx create mode 100644 src/config_script/script_parsing.h diff --git a/configure.ac b/configure.ac index 5d24872c..68c860c6 100644 --- a/configure.ac +++ b/configure.ac @@ -121,7 +121,7 @@ AC_FUNC_SELECT_ARGTYPES AC_TYPE_SIGNAL AC_FUNC_STRFTIME AC_FUNC_STRTOD -AC_CHECK_FUNCS([getaddrinfo gethostbyname hstrerror gmtime_r localtime_r memmove memset mkdir select setenv snprintf socket socketpair strcasecmp strcasestr strchr strdup strerror strlcpy strncasecmp strrchr strstr strtol uname unsetenv vsnprintf]) +AC_CHECK_FUNCS([getaddrinfo gethostbyname hstrerror gmtime_r localtime_r memmove memset mkdir select setenv snprintf socket socketpair strcasecmp strcasestr strchr strdup strerror strlcpy strnlen strncasecmp strrchr strstr strtol uname unsetenv vsnprintf]) # Check for O_CLOEXEC AC_FCNTL_FLAGS diff --git a/fldigi_doxygen/images/menu_script.png b/fldigi_doxygen/images/menu_script.png new file mode 100644 index 0000000000000000000000000000000000000000..5d19a8960b8f9e035c11aa89e6429ac63d4f06d6 GIT binary patch literal 8727 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 literal 0 HcmV?d00001 diff --git a/fldigi_doxygen/images/script_error_log_entry.png b/fldigi_doxygen/images/script_error_log_entry.png new file mode 100644 index 0000000000000000000000000000000000000000..ec08e8556b1ae7cdbf2d6a7fc2b37f4b157dd69f GIT binary patch literal 34419 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%0DGEz#vcpPoR`4>MwuB4dAx~ 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 literal 0 HcmV?d00001 diff --git a/fldigi_doxygen/images/script_restart_notice.png b/fldigi_doxygen/images/script_restart_notice.png new file mode 100644 index 0000000000000000000000000000000000000000..c6a5b168c5443ae2d963f0daf8f60c2e722f65e0 GIT binary patch literal 12749 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 Pcn`S9ik~aR4Zr_?M9v4P literal 0 HcmV?d00001 diff --git a/fldigi_doxygen/user_src_docs/Doxyfile b/fldigi_doxygen/user_src_docs/Doxyfile index 53fea2e5..3fd20468 100644 --- a/fldigi_doxygen/user_src_docs/Doxyfile +++ b/fldigi_doxygen/user_src_docs/Doxyfile @@ -49,7 +49,7 @@ INPUT = index.txt \ configRTTY.txt configThor.txt ConfigUI-browser.txt \ ConfigUI-contest.txt ConfigUI-general.txt ConfigUI-logging.txt \ ConfigUI-macros.txt configUITouch.txt ConfigUI-WF-controls.txt \ - ConfigWaterfall.txt kiss_io_command.txt \ + ConfigWaterfall.txt configure_scripting.txt kiss_io_command.txt \ SoundCardSetup.txt Contest-How-To.txt cabrilloreporter.txt \ Logbook.txt LogExports.txt working_logs.txt Macros.txt \ InlineMacroTags.txt atMacroTags.txt advanced_qsy.txt execmacro.txt CW.txt \ diff --git a/fldigi_doxygen/user_src_docs/MFSK.txt b/fldigi_doxygen/user_src_docs/MFSK.txt index de0f5a28..cb036f44 100644 --- a/fldigi_doxygen/user_src_docs/MFSK.txt +++ b/fldigi_doxygen/user_src_docs/MFSK.txt @@ -98,7 +98,7 @@ Received images are saved in the default folder $HOME/.fldigi/images (Linux) or \/fldigi.files/images (Windows).
-\section tx_image Transmitting an Image +\section mfsk_tx_image Transmitting an Image \image html Xmt-Pix.png "Xmit Picture Dialog box" @@ -183,7 +183,7 @@ waterfall clearly shows that the image transmission is within the bandwidth occupied by MFSK-16.
-\section picture_slant Picture with a slant +\section mfsk_picture_slant Picture with a slant If either the send, receive or both ends of the transmission are using an uncalibrated sound card whose sampling rate is not an exact multiple of diff --git a/fldigi_doxygen/user_src_docs/Menus.txt b/fldigi_doxygen/user_src_docs/Menus.txt index c976347f..3af29f62 100644 --- a/fldigi_doxygen/user_src_docs/Menus.txt +++ b/fldigi_doxygen/user_src_docs/Menus.txt @@ -104,6 +104,20 @@ Exit - exit the program closing down the various interfaces in a nice controlled manner.
+


+\subsection s_scripts Scripts + +Executing and Generating Scripts + +\image html menu_script.png "Scripts" +\image latex menu_script.png "Scripts" width=2.0in +
+ +Additional information: +
+\ref configure_script_page +
+
\subsection s_op_mode Op Mode diff --git a/fldigi_doxygen/user_src_docs/TransceiverControl.txt b/fldigi_doxygen/user_src_docs/TransceiverControl.txt index b4ab0f41..0342069a 100644 --- a/fldigi_doxygen/user_src_docs/TransceiverControl.txt +++ b/fldigi_doxygen/user_src_docs/TransceiverControl.txt @@ -71,9 +71,11 @@ mouse cursor on a digit and then use the mouse wheel to roll the frequency up and down.
-Manual entry of frequency can be accomplished by clicking on any digit and -then entering the numeric value in KHz. Don't forget the decimal -point if you are entering a fractional KHz value. +Manual entry of frequency can be accomplished by hovering the mouse pointer +over the frequency display and entering the desired frequency (in Khz) via +the keyboard. Pressing \ or \ on completion sets the +frequency to an active state, effecting rig control and future log entires. +Don't forget the decimal point if you are entering a fractional KHz value.
The Smeter / Power-meter display is only active if fldigi is configured for xmlrpc @@ -88,8 +90,8 @@ time fldigi is executed. The mode combobox, the bandwidth combobox and the frequency display also annunciate the current transceiver status. If you change operating mode on the transceiver, that will be annunciated in the -respective combobox and fldigi will adjust any internal parameters -accordingly. Fldigi queries the transceiver 10 times per second +respective combobox and FLDigi will adjust any internal parameters +accordingly. FLDigi queries the transceiver 10 times per second to maintain a lock step with the transceiver.
diff --git a/fldigi_doxygen/user_src_docs/advanced_qsy.txt b/fldigi_doxygen/user_src_docs/advanced_qsy.txt index 1feba495..2746ee82 100644 --- a/fldigi_doxygen/user_src_docs/advanced_qsy.txt +++ b/fldigi_doxygen/user_src_docs/advanced_qsy.txt @@ -43,7 +43,7 @@ until the operator finds an active one.

-\section freq_inc Frequencies with increments +\section s_freq_inc Frequencies with increments A frequency can come with an increment: This means an implicit range of frequencies from this one to the next frequency. If the last frequency diff --git a/fldigi_doxygen/user_src_docs/configCW.txt b/fldigi_doxygen/user_src_docs/configCW.txt index 0d1d06c5..4c49b172 100644 --- a/fldigi_doxygen/user_src_docs/configCW.txt +++ b/fldigi_doxygen/user_src_docs/configCW.txt @@ -151,17 +151,17 @@ time is explained below. A good setting for nice sounding CW at
  • Edge decreases pulse width, when checked will give a slightly narrower dot length as the edge timing is increased. This is useful when operating QSK and listening between the character elements.
  • -
  • The transmitted signal can be further wave shaped using a "Windowed-sinc" bandpass filter. It is enabled by checking the "BPF transmit audio" check box. The bandwidth of the filter can be adjusted from 10 to 1000 Hertz with the BPF bw -control. The filter will always be centered on the AFCW injection frequency -(waterfall TX cursor position). You should both visually observe and listen to +control. The filter will always be centered on the AFCW injection frequency +(waterfall TX cursor position). You should both visually observe and listen to the resulting CW signal. The easiest way to do this is to enable the "Send continuously", select a test character and then press the TX button on the main dialog. The -weight, dash/dot, edge shape selection, edge timing, BPF and bandwidth can be -changed with immediate effect. +weight, dash/dot, edge shape selection, edge timing, BPF and bandwidth can be +changed with immediate effect.
  • + This is what the A2 signal should look like with various settings of weight, Dash/Dot and Edge. The audio frequency is 400 Hz and diff --git a/fldigi_doxygen/user_src_docs/configure_scripting.txt b/fldigi_doxygen/user_src_docs/configure_scripting.txt new file mode 100644 index 00000000..f38c29b8 --- /dev/null +++ b/fldigi_doxygen/user_src_docs/configure_scripting.txt @@ -0,0 +1,1406 @@ +/** +\page configure_script_page Configure Scripting + +\tableofcontents +
    + +\section sConfigScript Configure Scripting + +\image html menu_script.png "Scripts" +\image latex menu_script.png "Scripts" width=1.25in + +\par WARNING: +If you do anything with this option, ensure FLDIGI is configured to your +preferences. Then generate a restore script. In doing so, any alterations +performed below can be returned to it's intended state. + +\par NOTICE: +Because of different hardware and Operating Systems it's advisable to avoid +commands that are hardware/OS dependent when creating standard +configuration scripts. + + +Configure scripting uses: +
      +
    • Configuring FLDigi to support a specific net operation.
    • +
    • Restore user data when issues with FLdigi requires the deletion or +reset of fldigi.prefs and fldigi_def.xml files.
    • +
    + +\par Net Operations +A script can be created for setting the rig frequency, waterfall offset, modem, +rig mode, and custom macros. See \ref sConfigScriptCmds for other available +options. + +\par Configuration Reset +After reset, a configure script can be executed to restore User Data. +The commands available do not support a full restore. Some option may need +manual entry. See \ref sConfigScriptCmds for limits. + + +\subsection ss_exec_script Executing Scripts + +From FLDigi's main window select menu item Scripts->Execute Script. This will +bring up a file browser. Search and select the file in question, then +press [Open]. At this point the script will execute. + +
    +\image html script_warning_dialogbox.png "Warning Report Dialog Box" +\image latex script_warning_dialogbox.png "Warning Report Dialog Box" width=2.3in + +If problems are encountered the above dialog box is used to inform the user. +To ascertain the extent of the issue(s), select menu item Help->Event Log. The +log entires will contain the reason and line number for each reported error. + +Some issues reported are the result of preset data that is specific to a +particular operating system. These can be safely ignored until configured +to operate on your system. + +
    +\image html script_error_log_entry.png "Error Report Log Entry" +\image latex script_error_log_entry.png "Error Report Log Entry" width=2.92in + +Some configuration options will required FLDigi restart. Ensure configuration +is saved prior to restarting. + +
    +\image html script_restart_notice.png "Restart FLDIGI notice" +\image latex script_restart_notice.png "Restart FLDIGI notice" width=2.92in + +\par NOTE: + Some script commands are specific to operating system and hardware + combination. If your system does not support these commands, they + will be ignored. The easiest way to determine what your system + supports is to generate a script and note it's content. + +\subsection ss_gen_script Generating Scripts + +To generate a script the operator selects FLdigi's menu items +Scripts->Generate Script. A file save dialog box is opened for the user to +select a name and where the file is saved. Pressing [Save] initiates +the process. + +To create custom scripts there are two ways of doing this. With a Text editor +(see \ref sScriptSyntax) or changing the content/settings of FLDigi prior to +the script generation. + +If the latter is used, your are advised to generate a script prior to +changing any of FLDigi's settings. Just in case restoration is needed. + +Prior to editing any script file, take the time to read the relavent sections +of this document. + +\par NOTE: + Generated script contents are specific to the operating system and + hardware available on the host machine. If a device is not supported on + your system, script code will not be generated for it. + +See \ref sScriptSyntax and \ref sExampleScript + +
    +

    +\section sConfigScriptCmds Configure Script Commands + +\ref ss_fldigi "FLDIGI"
    +\par +\ref sss_freq "FREQ"   \|   +\ref sss_mode "MODE"   \|   +\ref sss_wfhz "WFHZ"   \|   +\ref sss_rxid "RXID"   \|   +\ref sss_txid "TXID"   \|   +\ref sss_spot "SPOT"   \|   +\ref sss_rev "REV"   \|   +\ref sss_afc "AFC"   \|   +\ref sss_lock "LOCK"   \|   +\ref sss_sql "SQL"   \|   +\ref sss_kpsql "KPSQL"   \|   +\ref sss_modem "MODEM" + +\ref ss_operator "OPERATOR"
    +\par +\ref sss_callsign "CALLSIGN"   \|   +\ref sss_name "NAME"   \|   +\ref sss_qth "QTH"   \|   +\ref sss_loc "LOC"   \|   +\ref sss_ant "ANT" + +\ref ss_audio_device "AUDIO DEVICE"
    +\par +\ref sss_oss "OSS"   \|   +\ref sss_dev_path "OSS DEV"   \|   +\ref sss_portaudio "PA"   \|   +\ref sss_portaudio_playback "PA PLAYBACK"   \|   +\ref sss_portaudio_capture "PA CAPTURE"   \|   +\ref sss_pua "PUA"   \|   +\ref sss_pua_srvr "PUA SERVER" + +\ref ss_audio_settings "AUDIO SETTINGS"
    +\par +\ref sss_audio_capture_sample_rate "CAPTURE"   \|   +\ref sss_audio_playback_sample_rate "PLAYBACK"   \|   +\ref sss_audio_converter "CONVERTER"   \|   +\ref sss_rx_ppm "RX PPM"   \|   +\ref sss_tx_ppm "TX PPM"   \|   +\ref sss_tx_offset "TX OFFSET" + +\ref ss_audio_rt_channel "AUDIO RT CHANNEL"
    +\par +\ref sss_rt_mono "MONO AUDIO"   \|   +\ref sss_rt_mono_lr "MODEM LR"   \|   +\ref sss_rt_mono_rev "REV LR"   \|   +\ref sss_rt_mono_ptt "PTT RT CHAN"   \|   +\ref sss_rt_mono_qsk "QSK RT CHAN"   \|   +\ref sss_rt_mono_fsk "FSK RT CHAN" + +\ref ss_audio_wave_sr "AUDIO WAVE.SRATE" + +\ref ss_rig_hrdwr_ptt "RIG HRDWR PTT" +\par +\ref ss_hrdwr_ptt "PTT RT CHAN"   \|   +\ref ss_hrdwr_serial "SERIAL PORT"   \|   +\ref ss_hrdwr_device "DEVICE"   \|   +\ref ss_hrdwr_rts "RTS"   \|   +\ref ss_hrdwr_dtr "DTR"   \|   +\ref ss_hrdwr_rtsv "RTSV"   \|   +\ref ss_hrdwr_dtrv "DTRV"   \|   +\ref ss_hrdwr_spttd "START PTT DELAY"   \|   +\ref ss_hrdwr_epttd "END PTT DELAY"   \|   +\ref ss_hrdwr_uhr "UHROUTER"   \|   +\ref ss_hrdwr_pp "PARALLEL"   \|   +\ref ss_hrdwr_init "INIT" + +\ref ss_rigcat "RIGCAT" +\par +\ref ss_rigcat_state "STATE"   \|   +\ref ss_rigcat_df "DESC FILE"   \|   +\ref ss_rigcat_dp "DEV PATH"   \|   +\ref ss_rigcat_retry "RETRIES"   \|   +\ref ss_rigcat_rint "RETRY INT"   \|   +\ref ss_rigcat_wd "WDELAY"   \|   +\ref ss_rigcat_id "IDELAY"   \|   +\ref ss_rigcat_br "BRATE"   \|   +\ref ss_rigcat_sb "SBITS"   \|   +\ref ss_rigcat_echo "ECHO"   \|   +\ref ss_rigcat_trts "TOGGLE RTS PTT"   \|   +\ref ss_rigcat_tdtr "TOGGLE DTR PTT"   \|   +\ref ss_rigcat_restore "RESTORE"   \|   +\ref ss_rigcat_pttc "PTT COMMAND"   \|   +\ref ss_rigcat_rtsv "RTS 12V"   \|   +\ref ss_rigcat_dtrv "DTR 12V"   \|   +\ref ss_rigcat_hfc "HRDWR FC"   \|   +\ref ss_rigcat_vsp "VSP"   \|   +\ref ss_rigcat_init "INIT" + +\ref ss_hamlib "HAMLIB" +\par +\ref ss_hamlib_s "STATE"   \|   +\ref ss_hamlib_r "RIG"   \|   +\ref ss_hamlib_dp "DEV PATH"   \|   +\ref ss_hamlib_r "RETRIES"   \|   +\ref ss_hamlib_ri "RETRY INT"   \|   +\ref ss_hamlib_wd "WDELAY"   \|   +\ref ss_hamlib_pwd "PWDELAY"   \|   +\ref ss_hamlib_br "BRATE"   \|   +\ref ss_hamlib_sbits "SBITS"   \|   +\ref ss_hamlib_sband "SBAND"   \|   +\ref ss_hamlib_pttc "PTT COMMAND"   \|   +\ref ss_hamlib_dtrv "DTR 12V"   \|   +\ref ss_hamlib_rtsv "RTS 12V"   \|   +\ref ss_hamlib_hfc "HRDWR FC"   \|   +\ref ss_hamlib_sfc "SFTWR FC"   \|   +\ref ss_hamlib_ac "ADV CONF"   \|   +\ref ss_hamlib_init "INIT" + +\ref ss_xmlrpc_rc "XMLRPC RC" +\par +\ref ss_xmlrpc_s "STATE"   \|   +\ref ss_xmlrpc_bwd "BWDELAY"   \|   +\ref ss_xmlrpc_init "INIT" + +\ref ss_io "IO" +\par +\ref ss_io_lock "LOCK"   \|   +\ref ss_io_port "PORT"   \|   +\ref ss_io_csma "CSMA"   \|   +\ref ss_io_kiss "KISS"   \|   +\ref sss_io_kiss_ipa "KISS.IPA"   \|   +\ref sss_io_kiss_iopa "KISS.IOPN"   \|   +\ref sss_io_kiss_opn "KISS.OPN"   \|   +\ref sss_io_kiss_dp "KISS.DP"   \|   +\ref sss_io_kiss_busy "KISS.BUSY"   \|   +\ref sss_io_kiss_cont "KISS.CONT"   \|   +\ref sss_io_kiss_atten "KISS.ATTEN"   \|   +\ref ss_io_arq "ARQ"   \|   +\ref sss_io_arq_ipa "ARQ.IPA"   \|   +\ref sss_io_arq_iopn "ARQ.IOPN"   \|   +\ref ss_io_xmlrpc "XMLRPC"   \|   +\ref sss_io_xmlrpc_ipa "XMLRPC.IPA"   \|   +\ref sss_io_xmlrpc_iopn "XMLRPC.IOPN" + +\ref s_nbems "MISC NBEMS" +\par +\ref ss_nbems_timeout "TIMEOUT"   \|   +\ref ss_nbems_open_brwsr "OPEN BRWSR"   \|   +\ref ss_nbems_state "STATE"   \|   +\ref ss_nbems_open_msg "OPEN MSG"   \|   +\ref ss_nbems_open_flmsg "OPEN FLMSG"   \|   +\ref ss_nbems_flmsg_path "PATH" + + + +\ref ss_load_macro "MACRO" + +
    +

    +\section sScriptSyntax Scripting Syntax + +The script syntax is formated into a multi tier system using two variations. +The first is a structured syntax. The second uses a hierarchy +system employing dot '.' notation. The command text used closely mimics the +GUI configuration panel tabs hierarchy and contents to easily discern the +connection between commands and the effected settings. + +\subsection ssStucturedCommands Structured Commands + +Each command ends with a colon (':'). This separates the command section +with the paramater section. A command may or may not contain a paramater. The +structure statements are terminated using "END:" statement. + + +\:
    +   \:\
    +   \:\
    +END:
    +
    + +\subsection ssHierarchyCommands Dot Notation Commands + +Each command ends with a colon (':'). This separates the command section +with the paramater section. A command may or may not contain a paramater. The +inclusion of a period ('.') within the command section denotes the separation +of upper and lower tier segments. + + +\.\,...:\
    +\.\,...:\
    +
    + +\subsection ssParameters Parameters + +Parameter content varies on the command used. The various parameters types are: +
    +
      +
    • Integers (whole numbers, ie 0, 10, 100, 234).
    • +
    • Real Numbers (floating point numbers, ie 1.2, 10.3).
    • +
    • Characters Strings (one or more words, "Madison, AL", "Toney, AL").
    • +
    + +\subsection ssScriptFiles Script Files + +The script file name is expected to contain a .txt extension. The editing of +these files must utilize a true text editor¹. Preferably one that understands +the various line ending sequences used between the different Operating +Systems. + +
      +
    • The first line in the script file must contain \"FLDIGI_CONFIG\" tag. +This is used to verify the "text" file is a configuration script for +FLDIGI. If it's not present the file will not be processed.
    • + +
    • One command : parameter pair per line.
    • + +
    • Command indentations with spaces or tabs are not required (cosmetic).
    • + +
    • Parameters are separated by a comma ','.
    • + +
    • Parameters regardless of type can be encapsulated in quotes \(\" \"\). However, + if a parameter contains spaces or commas it must be encapsulated.
    • + +
    • One or more commands per file.
    • + +
    • One or more empty lines per file.
    • . + +
    • Any text entry after the '#' pound sign is considered a 'comment' and will be + ignored.
    • +
    + +\par Note: 1 +Windows: Notepad++, Geany
    +Macintosh: TextWrangler
    +Linux: Geany, Gedit, Pluma
    + +http://en.wikipedia.org/wiki/Category:Windows_text_editors
    +http://en.wikipedia.org/wiki/Category:Linux_text_editors
    + +
    +\section ss_fldigi FLDigi Commands + +See \ref operating_controls_page + +\subsection sss_freq Frequency Control + +Sets the RF Carrier frequency (effects rig control). + +FREQ:\ + +\ values are entered directly or as exponential notation. The +following frequencies represent the same frequency value. + +Frequency Value = Parameter Syntax + +
      +
    • 14.070 MHz = 14.070e+06
    • +
    • 14070.00 KHz = 14070.0e+03 - Using this exponent magnitude represents the + scale of the frequency display
    • +
    • 14070000 Hz = 14070000 - Directly in Hz
    • +
    + +\subsection sss_mode Mode + +Sets the rig modulation mode (ie. USB, LSB, FM, etc). The actual values are +dependent on the rig and the interface used. + +MODE:\ + +\subsection sss_wfhz Waterfall Offset (Hz) + +Sets the audio tone offset in the waterfall. + +WFHZ:\ + +Valid values range from 0 - 4000 +/- 50% of the bandwidth needed for the +selected modem. + +\subsection sss_rxid RxID + +Enable or disable the use of RSID reception. + +RXID:\ + +\subsection sss_txid TxID + +Enable or disable the use of RSID transmission. + +TXID:\ + +\subsection sss_spot Spot + +Enable or disable the use of the PSKreporter mechanism. + +SPOT:\ + +\subsection sss_rev Rev + +Enable or disable the use of upper and lower tone reversal. Allowing modems +like MFSK to receive/transmit LSB signal while the rig is in USB. RSID will +not decode when this option is selected and not all modems are supported. + +REV:\ + +\subsection sss_afc AFC + +Enable or disable the use of Automatic Frequency Control. + +AFC:\ + +\subsection sss_lock Lk + +Enable or disable the use of frequency lock. The behavior of this feature +can be altered depending on the settings of the \ref id_configuration_page +panel. + +LOCK:\ + +\subsection sss_sql SQL + +Enable or disable the use of the squelch. + +SQL:\ + +\subsection sss_kpsql KPSQL + +Enable or disable the use of the KISS power squelch. This option is only +available when KISS IO interface option is selected. + +See \ref config_io_page + +KPSQL:\ + +\subsection sss_modem MODEM Control + +Sets the desired modem to receive and transmit from. Some modems will not be +available if KISS IO interface option is selected. See \ref mode_table_page +under 'mode' column for proper modem parameter syntax. + +MODEM:\ + +\subsection sss_fldigi_examples Examples + +| Structured | Dot Notation | +|:-----------|:-------------| +| FLDIGI:
    FREQ:14.070e+06
    END:
    | FLDIGI.FREQ:3853.0e+03 | +| FLDIGI:
    MODE:DIG
    END:
    | FLDIGI.MODE:DIG | +| FLDIGI:
    WFHZ:1500
    END:
    | FLDIGI.WFHZ:700 | +| FLDIGI:
    RXID:ENABLE
    END:
    | FLDIGI.RXID:DISABLE | +| FLDIGI:
    TXID:DISABLE
    END:
    | FLDIGI.TXID:DISABLE | +| FLDIGI:
    SPOT:DISABLE
    END:
    | FLDIGI.SPOT:ENABLE | +| FLDIGI:
    REV:DISABLE
    END:
    | FLDIGI.REV:ENABLE | +| FLDIGI:
    AFC:DISABLE
    END:
    | FLDIGI.AFC:DISABLE | +| FLDIGI:
    LOCK:DISABLE
    END:
    | FLDIGI.LOCK:ENABLE | +| FLDIGI:
    SQL:DISABLE
    END:
    | FLDIGI.SQL:ENABLE | +| FLDIGI:
    KPSQL:DISABLE
    END:
    | FLDIGI.KPSQL:DISABLE | +| FLDIGI:
    MODEM:BPSK31
    END:
    | FLDIGI.MODEM:BPSK63 | + +
    +\section ss_operator Operator Commands + +See \ref operator_configuration_page + +\subsection sss_callsign Callsign: + +OPERATOR.CALLSIGN:\ + +\subsection sss_name Name: + +OPERATOR.NAME:\ + +\subsection sss_qth QTH: + +OPERATOR.QTH:\ + +\subsection sss_loc Locator: + +Maidenhead Grid Locator. A series of alpha +numerical characters representing a position on earth. + +OPERATOR.LOC:\ + +A: Uppercase characters
    +n: Numerical data (0-9)
    +a: Lowercase characters
    + +Additional Information: http://www.arrl.org/grid-squares, or http://en.wikipedia.org/wiki/Maidenhead_Locator_System + +\subsection sss_ant Operators Antenna Description + +OPERATOR.ANT:\ + +\subsection sss_op_examples Examples + +| Structured | Dot Notation | +|:-----------|:-------------| +| OPERATOR:
    CALLSIGN:KK5VD
    END:
    | OPERATOR.CALLSIGN:w1hkj | +| OPERATOR:
    NAME:Robert
    END:
    | OPERATOR.NAME:Dave | +| OPERATOR:
    QTH:"Madison, AL"
    END:
    | OPERATOR.QTH:"Toney, AL" | +| OPERATOR:
    LOC:EM64pr
    END:
    | OPERATOR.LOC:EM64 | +| OPERATOR:
    ANT:"Inverted 'V' @22FT AGL"
    END:
    | OPERATOR.ANT:"15 EL LP @ 200 FT AGL" | + +
    +\section ss_audio_device Audio Device Commands + +See \ref sound_card_configuration_page + +\subsection sss_oss OSS + +Enable or disable OSS. This option is not available on all operating systems. + +OSS:\ + +\subsection sss_dev_path Device: + +OSS DEV:\ + +Parameter:/dev/path + +\subsection sss_portaudio PortAudio + +Enable or disable Port Audio. This option may or may not be available to all +operating systems. + +PA:\ + +\subsection sss_portaudio_playback Playback: + +The device name is specific to the hardware installed. + +PA PLAYBACK:\,\ + +Parameter:Menu Index, Device Name + +\par Note: +Parameter Menu Index is specific to the fldigi/hardware combination. If the +device name is available on other systems it will be set to the first +occurrence of that device name. + +\subsection sss_portaudio_capture Capture: + +The device name is specific to the hardware installed. + +PA CAPTURE:\,\ + +\par Note: +Parameter Menu Index is specific to the fldigi/hardware combination. If the +device name is available on other systems it will be set to the first +occurrence of that device name. + +Parameter:Menu Index, Device Name + +\subsection sss_pua PulseAudio + +Enable or disable Pulse Audio. This option is not available on all operating systems. + +PUA:\ + +\subsection sss_pua_srvr Server string: + +PUA SERVER:\ + +Parameter: See Note: † below. + +\subsection sss_ad_examples Examples + +| Structured | Dot Notation | +|:-----------|:-------------| +| AUDIO DEVICE:
    OSS:ENABLE
    END:
    | AUDIO DEVICE.OSS:ENABLE | +| AUDIO DEVICE:
    OSS DEV:/dev/path
    END:
    | AUDIO DEVICE.OSS DEV:/dev/path | +| AUDIO DEVICE:
    PA:ENABLE
    END:
    | AUDIO DEVICE.PA:ENABLE | +| AUDIO DEVICE:
    PA CAPTURE:2,"USB Audio CODEC"
    END:
    | AUDIO DEVICE.PA CAPTURE:2,"USB Audio CODEC" | +| AUDIO DEVICE:
    PA PLAYBACK:3,"USB Audio CODEC"
    END:
    | AUDIO DEVICE.PA CAPTURE:3,"USB Audio CODEC" | +| AUDIO DEVICE:
    PUA:ENABLE
    END:
    | AUDIO DEVICE.PUA:ENABLE | +| AUDIO DEVICE:
    PUA SERVER:†
    END:
    | AUDIO DEVICE.PUA SERVER:† | + +\par Note: † Pulse Audio Server Strings +Pulse audio server string information can be found here: +
    +http://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/ServerStrings/ + +
    +\section ss_audio_settings Audio Settings + +See \ref sound_card_configuration_page + +\subsection sss_audio_capture_sample_rate Capture Audio Sample Rate + +Set the input signal sample rate. The sample rate availability is dependent +on the ADC hardware. + +Auto, Native, 8000,... + +CAPTURE:\ + +\subsection sss_audio_playback_sample_rate Playback Audio Sample Rate + +Set the output signal sample rate. The sample rate availability is dependent +on the DAC hardware. + +Auto, Native, 8000,... + +PLAYBACK:\ + +\subsection sss_audio_converter Converter + +CONVERTER:\ Best, Medium, Fastest, Linear + +\subsection sss_rx_ppm Receive Audio PPM Correction + +RX PPM:\ negative, 0, positive values + +\subsection sss_tx_ppm Transmit Audio PPM Correction + +TX PPM:\ negative, 0, positive values + +\subsection sss_tx_offset Transmit Audio Hertz Offset Correction + +TX OFFSET:\ negative, 0, positive values (Hertz) + +\subsection sss_as_examples Examples + +| Structured | Dot Notation | +|:-----------|:-------------| +| AUDIO SETTINGS:
    CAPTURE:48000
    END:
    | AUDIO SETTINGS.CAPTURE:Auto | +| AUDIO SETTINGS:
    PLAYBACK:8000
    END:
    | AUDIO SETTINGS.PLAYBACK:Native | +| AUDIO SETTINGS:
    CONVERTER:"Best"
    END:
    | AUDIO SETTINGS.CONVERTER:"Fastest" | +| AUDIO SETTINGS:
    RX PPM:17
    END:
    | AUDIO SETTINGS.RX PPM:17 | +| AUDIO SETTINGS:
    TX PPM:17
    END:
    | AUDIO SETTINGS.TX PPM:17 | +| AUDIO SETTINGS:
    TX OFFSET:17
    END:
    | AUDIO SETTINGS.TX OFFSET:17 | + +
    +\section ss_audio_rt_channel Audio Right Channel Commands + +See \ref right_chanel_audio + +\subsection sss_rt_mono Mono audio output + +Enable or disable monophonic signal output. + +MONO AUDIO:\ + +\subsection sss_rt_mono_lr Modem signal on left and right channels + +Enable or disable audio signal to both left and right channels + +MODEM LR:\ + +\subsection sss_rt_mono_rev Reverse Left/Right channels + +Enable or disable audio signal reversal on Left/Right channels. + +REV LR:\ + +\subsection sss_rt_mono_ptt PTT tone on right audio channel + +Enable or disable PTT use by suppling a signal on the right channel. + +PTT RT CHAN:\ + +\subsection sss_rt_mono_qsk CW QSK signal on right channel + +QSK RT CHAN:\ + +\subsection sss_rt_mono_fsk Pseudo-FSK on right audio channel + +FSK RT CHAN:\ + +\subsection sss_rtch_examples Examples + +| Structured | Dot Notation | +|:-----------|:-------------| +| AUDIO RT CHANNEL:
    MONO AUDIO:DISABLE
    END:
    | AUDIO RT CHANNEL.MONO AUDIO:DISABLE | +| AUDIO RT CHANNEL:
    MODEM LR:DISABLE
    END:
    | AUDIO RT CHANNEL.MODEM LR:DISABLE | +| AUDIO RT CHANNEL:
    CONVERTER:"Best"
    END:
    | AUDIO RT CHANNEL.CONVERTER:"Fastest" | +| AUDIO RT CHANNEL:
    REV LR:DISABLE
    END:
    | AUDIO RT CHANNEL.REV LR:DISABLE | +| AUDIO RT CHANNEL:
    PTT RT CHAN:DISABLE
    END:
    | AUDIO RT CHANNEL.PTT RT CHAN:DISABLE | +| AUDIO RT CHANNEL:
    QSK RT CHAN:DISABLE
    END:
    | AUDIO RT CHANNEL.QSK RT CHAN:DISABLE | +| AUDIO RT CHANNEL:
    FSK RT CHAN:DISABLE
    END:
    | AUDIO RT CHANNEL.FSK RT CHAN:DISABLE | + +
    +\section ss_audio_wave_sr Wav write sample rate + +See \ref wav_file_sample_rate + +Sets the record wave file sample rate. + +AUDIO WAVE.SRATE:\ + +Available Parameters: 8000, 11025, 16000, 22050, 24000, 44100, 48000 + +| Structured | Dot Notation | +|:-----------|:-------------| +| AUDIO WAVE:
    SRATE:16000
    END:
    | AUDIO WAVE.SRATE:16000 | + +
    +\section ss_rig_hrdwr_ptt Hardware PTT Option Commands + +See \ref rig_config + +\subsection ss_hrdwr_ptt PTT tone on right audio channel + +PTT RT CHAN:\ + +\subsection ss_hrdwr_serial Use separate serial port PTT + +SERIAL PORT:\ + +\subsection ss_hrdwr_device Device: + +DEVICE:\ + +Parameter: A device path (/dev/ptt) + +\subsection ss_hrdwr_rts Use RTS + +RTS:\ + +\subsection ss_hrdwr_dtr Use DTR + +DTR:\ + +\subsection ss_hrdwr_rtsv RTS = +V + +RTSV:\ + +\subsection ss_hrdwr_dtrv DTR = +V + +DTRV:\ + +\subsection ss_hrdwr_spttd PTT delays valid for all CAT/PTT types + +START PTT DELAY:\ + +\subsection ss_hrdwr_epttd PTT delays valid for all CAT/PTT types + +END PTT DELAY:\ + +\subsection ss_hrdwr_uhr Use uHRouter PTT + +UHROUTER:\ + +\subsection ss_hrdwr_pp Use parallel port PTT + +PARALLEL:\ + +\subsection ss_hrdwr_init Initialize Changes + +INIT: + +\subsection ss_hrdwr_examples Examples + +| Structured | Dot Notation | +|:-----------|:-------------| +| RIG HRDWR PTT:
    PTT RT CHAN:DISABLE
    END:
    | RIG HRDWR PTT.PTT RT CHAN:DISABLE | +| RIG HRDWR PTT:
    SERIAL PORT:DISABLE
    END:
    | RIG HRDWR PTT.SERIAL PORT:DISABLE | +| RIG HRDWR PTT:
    DEVICE:/dev/ptt
    END:
    | RIG HRDWR PTT.DEVICE:COM1 | +| RIG HRDWR PTT:
    RTS:DISABLE
    END:
    | RIG HRDWR PTT.RTS:DISABLE | +| RIG HRDWR PTT:
    RTSV:DISABLE
    END:
    | RIG HRDWR PTT.RTSV:DISABLE | +| RIG HRDWR PTT:
    DTR:DISABLE
    END:
    | RIG HRDWR PTT.DTR:DISABLE | +| RIG HRDWR PTT:
    DTRV:DISABLE
    END:
    | RIG HRDWR PTT.DTRV:DISABLE | +| RIG HRDWR PTT:
    PARALLEL:DISABLE
    END:
    | RIG HRDWR PTT.PARALLEL:DISABLE | +| RIG HRDWR PTT:
    UHROUTER:DISABLE
    END:
    | RIG HRDWR PTT.UHROUTER:DISABLE | +| RIG HRDWR PTT:
    START PTT DELAY:1
    END:
    | RIG HRDWR PTT.START PTT DELAY:1 | +| RIG HRDWR PTT:
    END PTT DELAY:1
    END:
    | RIG HRDWR PTT.END PTT DELAY:1 | +| RIG HRDWR PTT:
    INIT:
    END:
    | RIG HRDWR PTT.INIT: | + +
    +\section ss_rigcat RIGCAT Commands + +See \ref rig_cat_control + +\subsection ss_rigcat_state Use RigCAT + +STATE:\ + +\subsection ss_rigcat_df Rig description file: + +DESC FILE:\ + +Parameter:/directory/path/file.xml + +\subsection ss_rigcat_dp Device: + +DEV PATH:\ + +Parameter:/dev/path + +\subsection ss_rigcat_retry Retries + +RETRIES:\ + +\subsection ss_rigcat_rint Retry interval (ms) + +RETRY INT:\ + +\subsection ss_rigcat_wd Write delay (ms) + +WDELAY:\ + +\subsection ss_rigcat_id Init delay (ms) + +IDELAY:\ + +\subsection ss_rigcat_br Baud rate: + +BRATE:\ + +\subsection ss_rigcat_sb Stopbits + +SBITS:\ + +\subsection ss_rigcat_echo Commands are echoed + +ECHO:\ + +\subsection ss_rigcat_trts Toggle RTS for PTT + +TOGGLE RTS PTT:\ + +\subsection ss_rigcat_tdtr Toggle DTR for PTT + +TOGGLE DTR PTT:\ + +\subsection ss_rigcat_restore Restore Settings on Close + +RESTORE:\ + +\subsection ss_rigcat_pttc CAT command for PTT + +PTT COMMAND:\ + +\subsection ss_rigcat_rtsv RTS +12 v + +RTS 12V:\ + +\subsection ss_rigcat_dtrv DTR +12 v + +DTR 12V:\ + +\subsection ss_rigcat_hfc RTS/CTS flow control + +HRDWR FC:\ + +\subsection ss_rigcat_vsp VSP Enable + +VSP:\ + +\subsection ss_rigcat_init Initialize Changes + +INIT: + +\subsection ss_rigcat_examples Examples + +| Structured | Dot Notation | +|:-----------|:-------------| +| RIGCAT:
    STATE:ENABLE
    END:
    | RIG HRDWR PTT.STATE:ENABLE | +| RIGCAT:
    DEV PATH:/dev/tty.usbserial-RT071600
    END:
    | RIGCAT.DEV PATH:COM1 | +| RIGCAT:
    DESC FILE:/Users/.fldigi/rigs/FT-817.xml
    END:
    | RIGCAT.DESC FILE:/Users/.fldigi/rigs/FT-817.xml | +| RIGCAT:
    RETRIES:2
    END:
    | RIGCAT.RETRIES:2 | +| RIGCAT:
    RETRY INT:500
    END:
    | RIGCAT.RETRY INT:500 | +| RIGCAT:
    WDELAY:5
    END:
    | RIGCAT.WDELAY:5 | +| RIGCAT:
    IDELAY:0
    END:
    | RIGCAT.IDELAY:0 | +| RIGCAT:
    BRATE:4800
    END:
    | RIGCAT.BRATE:4800 | +| RIGCAT:
    SBITS:1
    END:
    | RIGCAT.SBITS:1 | +| RIGCAT:
    ECHO:DISABLE
    END:
    | RIGCAT.ECHO:DISABLE | +| RIGCAT:
    TOGGLE RTS PTT:DISABLE
    END:
    | RIGCAT.TOGGLE RTS PTT:DISABLE | +| RIGCAT:
    RESTORE:DISABLE
    END:
    | RIGCAT.RESTORE:DISABLE | +| RIGCAT:
    PTT COMMAND:DISABLE
    END:
    | RIGCAT.PTT COMMAND:DISABLE | +| RIGCAT:
    TOGGLE DTR PTT
    END:
    | RIGCAT.TOGGLE DTR PTT | +| RIGCAT:
    TOGGLE RTS PTT:DISABLE
    END:
    | RIGCAT.TOGGLE RTS PTT:DISABLE | +| RIGCAT:
    RTS 12V:DISABLE
    END:
    | RIGCAT.RTS 12V:DISABLE | +| RIGCAT:
    DTR 12V:DISABLE
    END:
    | RIGCAT.DTR 12V:DISABLE | +| RIGCAT:
    HRDWR FC:DISABLE
    END:
    | RIGCAT.HRDWR FC:DISABLE | +| RIGCAT:
    VSP:DISABLE
    END:
    | RIGCAT.VSP:DISABLE | +| RIGCAT:
    INIT:
    END:
    | RIGCAT.INIT: | + +
    +\section ss_hamlib HAMLIB Commands + +See \ref hamlib_cat_control + +\subsection ss_hamlib_s Use Hamlib + +Enable to disable Hamlib Rig Control interface. + +STATE:\ + +\subsection ss_hamlib_r Rig: + +Set the rig to control. The list of Rigs are derived from internal list +provided by HAMLIB. + +RIG:\ + +Parameter: HAMLIB Device Names + +\subsection ss_hamlib_dp Device: + +The device path for controlling the Rig. + +DEV PATH:\ + +Parameter:Device path + +\subsection ss_hamlib_retries Retries + +The number of tries at sending commands to the Rig + +RETRIES:\ + +\subsection ss_hamlib_ri Retry Interval (ms) + +RETRY INT:\ + +\subsection ss_hamlib_wd Write delay (ms) + +WDELAY:\ + +\subsection ss_hamlib_pwd Post write delay (ms) + +PWDELAY:\ + +\subsection ss_hamlib_br Baud rate: + +BRATE:\ + +\subsection ss_hamlib_sbits Stopbits + +SBITS:\ + +\subsection ss_hamlib_sband Sideband: + +SBAND:\ + +\subsection ss_hamlib_pttc PTT via Hamlib command + +PTT COMMAND:\ + +\subsection ss_hamlib_dtrv DTR +12 + +DTR 12V:\ + +\subsection ss_hamlib_rtsv RTS +12 + +RTS 12V:\ + +\subsection ss_hamlib_hfc RTS/CTS flow control + +HRDWR FC:\ + +\subsection ss_hamlib_sfc XON/XOFF flow control + +SFTWR FC:\ + +\subsection ss_hamlib_ac Advanced configuration: + +ADV CONF:\ + +\subsection ss_hamlib_init Initialize Changes + +INIT: + +Parameters: None + +\subsection ss_hamlib_examples Examples + +| Structured | Dot Notation | +|:-----------|:-------------| +| HAMLIB:
    STATE:DISABLE
    END:
    | HAMLIB.STATE:DISABLE | +| HAMLIB:
    RIG:"Yaesu FT-817 (Beta)"
    END:
    | HAMLIB.RIG:"Yaesu FT-817 (Beta)" +| HAMLIB:
    DEV PATH:/dev/tty.usbserial-RT071600
    END:
    | HAMLIB.DEV PATH:COM1 +| HAMLIB:
    RETRIES:2
    END:
    | HAMLIB.RETRIES:2 | +| HAMLIB:
    RETRY INT:10
    END:
    | HAMLIB.RETRY INT:10 | +| HAMLIB:
    WDELAY:0
    END:
    | HAMLIB.WDELAY:0 | +| HAMLIB:
    PWDELAY:5
    END:
    | HAMLIB.PWDELAY:5 | +| HAMLIB:
    BRATE:4800
    END:
    | HAMLIB.BRATE:4800 | +| HAMLIB:
    SBITS:1
    END:
    | HAMLIB.SBITS:1 | +| HAMLIB:
    SBAND:"Rig mode"
    END:
    | HAMLIB.SBAND:"Rig mode" | +| HAMLIB:
    PTT COMMAND:DISABLE
    END:
    | HAMLIB.PTT COMMAND:DISABLE | +| HAMLIB:
    DTR 12V:DISABLE
    END:
    | HAMLIB.DTR 12V:DISABLE | +| HAMLIB:
    RTS 12V:DISABLE
    END:
    | HAMLIB.RTS 12V:DISABLE | +| HAMLIB:
    HRDWR FC:DISABLE
    END:
    | HAMLIB.HRDWR FC:DISABLE | +| HAMLIB:
    SFTWR FC:DISABLE
    END:
    | HAMLIB.SFTWR FC:DISABLE | +| HAMLIB:
    ADV CONF:
    END:
    | HAMLIB.ADV CONF: | +| HAMLIB:
    INIT:
    END:
    | HAMLIB.INIT: | + + +
    +\section ss_xmlrpc_rc XMLRPC Rig Control Commands + +See \ref xml_rpc_cat + +\subsection ss_xmlrpc_s Use XML-RPC program + +STATE:\ + +\subsection ss_xmlrpc_bwd Mode/BW delay + +BWDELAY:\ + +\subsection ss_xmlrpc_init Initialize Changes + +INIT: + +Parameters: None + +\subsection ss_xmlrpc_example Examples + +| Structured | Dot Notation | +|:-----------|:-------------| +| XMLRPC RC:
    STATE:DISABLE
    END:
    | XMLRPC RC.STATE:DISABLE | +| XMLRPC RC:
    BWDELAY:0.5
    END:
    | XMLRPC RC.BWDELAY:0.5 | +| XMLRPC RC:
    INIT:
    END:
    | XMLRPC RC.INIT: | + + +
    +\section ss_io IO + +See \ref config_io_page + +\subsection ss_io_lock Lock + +Used to lock the panel from user GUI access. Has no effect on script commands. + +LOCK:\ + +\subsection ss_io_port Enable ARQ or KISS IO Access + +Select the active IO port for data operation between programs. + +PORT:\ + +Parameters: + +ARQ: Used to control the FL Suite of auxiliary programs. + +KISS: KISS protocol over UDP/IP interface + +\subsection ss_io_ax25d AX25 Decode + +Enable or disable Ax25 decoding. Only available when the KISS IO port is +active. + +AX25D:\ + +\subsection ss_io_csma Enable CSMA + +Enable or disable Carrier Sense Multiple Access. Only available when the +KISS IO port is active. + +CSMA:\ + +\subsection ss_io_kiss KISS Sub Command + +KISS related sub commands. + +\subsubsection sss_io_kiss_ipa IP Address + +IP address for program to program communication + +IPA:\ + +\subsubsection sss_io_kiss_iopa I/O + +IP address I/O port number for program to program communication + +IOPN:\ + +\subsubsection sss_io_kiss_opn O + +IP address Output port number for program to program communication. Required +when FLDigi and auxiliary programs reside on the same host. + +OPN:\ + +\subsubsection sss_io_kiss_dp Dual Port + +Enable or disable the use of dual port io. + +DP:\ + +\subsubsection sss_io_kiss_busy Enable Busy Channel + +Enable or disable busy channel. Allows for the cooperative use of the +frequency. + +BUSY:\ + +\subsubsection sss_io_kiss_cont Continue After (sec) + +The number of seconds the frequency must be clean clear before transmissions +resume. Enabled by busy channel activation. + +CONT:\ + +\subsubsection sss_io_kiss_atten KPSQL Attenuation + +Controls the gain sensitivity of the KISS Power Squelch (KPSQL). The +attenuation is measure in fractions. If the value is '4' then the gain is +reduced to 1/4th. Maximum gain (sensitivity) requires a value of 1. + +ATTEN:\ + +\subsection ss_io_arq ARQ Sub Command + +ARQ sub commands + +\subsubsection sss_io_arq_ipa IP Address + +IP address for program to program communication + +IPA:\ + +\subsubsection sss_io_arq_iopn Port + +IP address I/O port number for program to program communication + +IOPN:\ + +\subsection ss_io_xmlrpc XMLRPC Sub Command + +\subsubsection sss_io_xmlrpc_ipa IP Address + +IP address for program to program communication + +IPA:\ + +\subsubsection sss_io_xmlrpc_iopn Port + +IP address I/O port number for program to program communication + +IOPN:\ + +\subsection sss_io_example Examples + +| Structured | Dot Notation | +|:-----------|:-------------| +| IO:
    LOCK:ENABLE
    END:
    | IO.LOCK:ENABLE | +| IO:
    PORT:ARQ
    END:
    | IO.PORT:ARQ | +| IO:
    AX25D:DISABLE
    END:
    | IO.AX25D:DISABLE | +| IO:
    CSMA:DISABLE
    END:
    | IO.CSMA:DISABLE | + +
    +| Structured | Dot Notation | +|:-----------|:-------------| +| IO:
    KISS:
    IPA:127.0.0.1
    END:
    END:
    | IO.KISS.IPA:127.0.0.1 | +| IO:
    KISS:
    IOPN:7342
    END:
    END:
    | IO.KISS.IOPN:7342 | +| IO:
    KISS:
    OPN:7343
    END:
    END:
    | IO.KISS.OPN:7343 | +| IO:
    KISS:
    DP:DISABLE
    END:
    END:
    | IO.KISS.DP:DISABLE | +| IO:
    KISS:
    BUSY:DISABLE
    END:
    END:
    | IO.KISS.BUSY:DISABLE | +| IO:
    KISS:
    CONT:3
    END:
    END:
    | IO.KISS.CONT:3 | +| IO:
    KISS:
    ATTEN:2
    END:
    END:
    | IO.KISS.ATTEN:2 | + +
    +| Structured | Dot Notation | +|:-----------|:-------------| +| IO:
    ARQ:
    IPA:127.0.0.1
    END:
    END:
    | IO.ARQ.IPA:127.0.0.1 | +| IO:
    ARQ:
    IOPN:7322
    END:
    END:
    | IO.ARQ.IOPN:7322 | + +
    +| Structured | Dot Notation | +|:-----------|:-------------| +| IO:
    XMLRPC:
    IPA:127.0.0.1
    END:
    END:
    | IO.XMLRPC.IPA:127.0.0.1 | +| IO:
    XMLRPC:
    IOPN:7362
    END:
    END:
    | IO.XMLRPC.IOPN:7362 | + +
    +\section s_nbems Misc NBEMS Commands + +See \ref subsec_nbems_flxxx_interface + +\subsection ss_nbems_state Enable + +NBEMS data file interface + +STATE:\ + +\subsection ss_nbems_open_msg Open message folder + +OPEN MSG:\ + +\subsection ss_nbems_open_flmsg Open with flmsg + +OPEN FLMSG:\ + +\subsection ss_nbems_flmsg_path FLMsg executable path + +PATH:\ + +Parameter: Directory and file name to the executable file location. + +\subsection ss_nbems_open_brwsr Open in browser + +OPEN BRWSR:\ + +\subsection ss_nbems_timeout Timeout (secs) + +TIMEOUT:\ + +\subsection ss_nbems_examples Examples + +| Structured | Dot Notation | +|:-----------|:-------------| +| MISC NBEMS:
    STATE:DISABLE
    END:
    | MISC NBEMS.STATE:DISABLE | +| MISC NBEMS:
    OPEN MSG:DISABLE
    END:
    | MISC NBEMS.OPEN MSG:DISABLE | +| MISC NBEMS:
    OPEN FLMSG:ENABLE
    END:
    | MISC NBEMS.OPEN FLMSG:ENABLE | +| MISC NBEMS:
    OPEN BRWSR:DISABLE
    END:
    | MISC NBEMS.OPEN BRWSR:DISABLE | +| MISC NBEMS:
    TIMEOUT:4.0
    END:
    | MISC NBEMS.TIMEOUT:4.0 | +| MISC NBEMS:
    PATH:c:/applications/nbems/flmsg
    END:
    | MISC PATH:c:/applications/nbems/flmsg | + +
    +\section ss_load_macro Load Macro Command + +See \ref macro_page + +The Macro command is a structured command only, dot notation is not supported. + + +MACRO,row,column,label
    +\
    +END:
    +
    + +Parameters:
    +row - This is the macro bar number seen to the right of the macro buttons (1-4)
    +column - The physical macro button position from left to right (1-12).
    +label - The marco buttons label. See \ref macro_display_symbols for special +label glyphs. + +No syntax checking is performed for the macro content. User responsibility. + +\image html macrobuttons.png "Macro Bar" +\image latex macrobuttons.png "Macro Bar" width=4.0in + +The following example sets the first button in the first macro bar as seen above. + +\verbatim +MACRO:1,1,"CQ @>|" + +cq cq cq de pse k + +END: +\endverbatim + +
    +\section sExampleScript Example Script + +\par NOTE: +This example script may report errors if used as is. Modification is required +to meet your particular setup. + +\verbatim +FLDIGI_CONFIG +# Fldigi Generated Config Script +# Created: Wed Jan 21 15:44:14 2015 + +FLDIGI: + FREQ:1.407000000e+07 + MODE:USB + WFHZ:1500 + RXID:DISABLE + TXID:DISABLE + SPOT:ENABLE + REV:DISABLE + AFC:DISABLE + LOCK:DISABLE + SQL:DISABLE + KPSQL:DISABLE + MODEM:BPSK31 +END: +OPERATOR: + CALLSIGN:kk5vd + QTH:Robert + NAME:"Madison, AL" + LOC:EM64or + ANT:"Invert 'V' @ 22FT AGL" +END: +AUDIO DEVICE: + PA:ENABLE + PA CAPTURE:2,"USB Audio CODEC" + PA PLAYBACK:3,"USB Audio CODEC" +END: +AUDIO SETTINGS: + CAPTURE:Auto + PLAYBACK:Auto + CONVERTER:"Medium Sinc Interpolator" + RX PPM:17 + TX PPM:17 + TX OFFSET:0 +END: +AUDIO RT CHANNEL: + MONO AUDIO:DISABLE + MODEM LR:DISABLE + REV LR:DISABLE + PTT RT CHAN:DISABLE + QSK RT CHAN:DISABLE + FSK RT CHAN:DISABLE +END: +AUDIO WAVE: + SRATE:16000 +END: +RIG HRDWR PTT: + PTT RT CHAN:DISABLE + SERIAL PORT:DISABLE + DEVICE:/dev/ptt + RTS:DISABLE + RTSV:DISABLE + DTR:DISABLE + DTRV:DISABLE + PARALLEL:DISABLE + UHROUTER:DISABLE + START PTT DELAY:1 + END PTT DELAY:1 + INIT: +END: +RIGCAT: + STATE:ENABLE + DEV PATH:/dev/tty.usbserial-RT071600 + DESC FILE:/Users/.fldigi/rigs/FT-817.xml + RETRIES:2 + RETRY INT:500 + WDELAY:5 + IDELAY:0 + BRATE:4800 + SBITS:1 + ECHO:DISABLE + TOGGLE RTS PTT:DISABLE + RESTORE:DISABLE + PTT COMMAND:DISABLE + TOGGLE DTR PTT:DISABLE + TOGGLE RTS PTT:DISABLE + RTS 12V:DISABLE + DTR 12V:DISABLE + HRDWR FC:DISABLE + VSP:DISABLE + INIT: +END: +HAMLIB: + STATE:DISABLE + RIG:"Yaesu FT-817 (Beta)" + DEV PATH:/dev/tty.usbserial-RT071600 + RETRIES:2 + RETRY INT:10 + WDELAY:0 + PWDELAY:5 + BRATE:4800 + SBITS:1 + SBAND:"Rig mode" + PTT COMMAND:DISABLE + DTR 12V:DISABLE + RTS 12V:DISABLE + HRDWR FC:DISABLE + SFTWR FC:DISABLE + ADV CONF: + INIT: +END: +XMLRPC RC: + STATE:DISABLE + BWDELAY:0.500 + INIT: +END: +IO: + LOCK:ENABLE + PORT:ARQ + AX25D:DISABLE + CSMA:DISABLE + KISS: + IPA:127.0.0.1 + IOPN:7342 + OPN:7343 + DP:DISABLE + BUSY:DISABLE + CONT:3 + ATTEN:2 + END: + ARQ: + IPA:127.0.0.1 + IOPN:7322 + END: + XMLRPC: + IPA:127.0.0.1 + IOPN:7362 + END: +END: +MISC NBEMS: + STATE:ENABLE + OPEN MSG:DISABLE + OPEN FLMSG:ENABLE + PATH:/Applications/flmsg-2.0.6AB.app/Contents/MacOS/flmsg + OPEN BRWSR:ENABLE + TIMEOUT:2.000 +END: + +MACRO:1,1,"CQ" + +cq cq cq de /qrp pse k + +END: + +MACRO:1,2,"ANSWER" + de kn + +END: +\endverbatim + +
    +\ref configure_script_page "Return to Top of Page" +
    +\ref main_page "Return to Main Page" + +*/ diff --git a/fldigi_doxygen/user_src_docs/index.txt b/fldigi_doxygen/user_src_docs/index.txt index 2a44ee1c..514b6151 100644 --- a/fldigi_doxygen/user_src_docs/index.txt +++ b/fldigi_doxygen/user_src_docs/index.txt @@ -34,6 +34,7 @@
  • \ref operating_page
  • \ref logging_page
  • \ref macro_page
  • +
  • \ref configure_script_page
  • \ref developers_page
  • \ref license_page
  • \ref recognitions_page
  • diff --git a/m4/macosx.m4 b/m4/macosx.m4 index cacb0e6b..17545b8c 100644 --- a/m4/macosx.m4 +++ b/m4/macosx.m4 @@ -34,6 +34,10 @@ if test "x$target_darwin" = "xyes" && test "x$ac_cv_mac_universal" = "xyes"; the mac_arches="-arch i386 -arch ppc -arch x86_64 -arch ppc64" mac_sysroot="-isysroot /Developer/SDKs/MacOSX10.5.sdk" ;; + darwin10*) + mac_arches="-arch i386 -arch x86_64" + mac_sysroot="-isysroot /Developer/SDKs/MacOSX10.6.sdk" + ;; *) mac_arches="" mac_sysroot="" diff --git a/po/POTFILES.in b/po/POTFILES.in index 26fc04cf..72421a4f 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -29,6 +29,9 @@ src/waterfall/colorbox.cxx src/widgets/FTextRXTX.cxx src/widgets/FTextView.cxx src/widgets/flinput2.cxx +src/config_script/run_scripts.cxx +src/config_script/script_parsing.cxx +src/config_script/create_default_script.cxx # Generated by fluid src/dialogs/confdialog.cxx diff --git a/src/Makefile.am b/src/Makefile.am index 59961fff..6312d87f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -301,6 +301,11 @@ fldigi_SOURCES += \ filters/filters.cxx \ filters/viterbi.cxx \ globals/globals.cxx \ + config_script/create_default_script.cxx \ + config_script/run_scripts.cxx \ + config_script/run_script.h \ + config_script/script_parsing.cxx \ + config_script/script_parsing.h \ include/htmlstrings.h \ include/arq_io.h \ include/confdialog.h \ diff --git a/src/combo/combo.cxx b/src/combo/combo.cxx index a31ad6a1..4331100b 100644 --- a/src/combo/combo.cxx +++ b/src/combo/combo.cxx @@ -87,11 +87,11 @@ int Fl_PopBrowser::handle(int event) if (key == 0x1b || kbd == FL_Escape) { // kbd test for OS X pophide(); return 0; - } + } if (key >= ' ' || key <= 0x7f) { keystrokes += key; for (int i = 0; i < cbx->listsize; i++) { - if (strncasecmp(keystrokes.c_str(), + if (strncasecmp(keystrokes.c_str(), cbx->datalist[i]->s, keystrokes.length()) == 0) { popbrwsr->select(i+1); @@ -198,7 +198,7 @@ void Fl_PopBrowser::pophide () Fl::grab(0); Fl::focus(((Fl_ComboBox*)parent())->btn); -} +} void Fl_PopBrowser::popbrwsr_cb_i (Fl_Widget *v, long d) { @@ -401,7 +401,7 @@ int Fl_ComboBox::index() { } void * Fl_ComboBox::data() { - return retdata; + return retdata; } void Fl_ComboBox::insert(const char *str, void *d) @@ -448,7 +448,7 @@ void Fl_ComboBox::add( const char *s, void * d) str.erase(0, p+1); p = str.find("|"); } - if (str.length()) + if (str.length()) insert(str.c_str(), 0); } else insert( s, d ); @@ -457,7 +457,7 @@ void Fl_ComboBox::add( const char *s, void * d) void Fl_ComboBox::clear() { Brwsr->clear(); - + if (listsize == 0) return; for (int i = 0; i < listsize; i++) { delete [] datalist[i]->s; @@ -523,3 +523,17 @@ void Fl_ComboBox::color(Fl_Color c) val->color(c); if (Brwsr) Brwsr->color(c); } + +int Fl_ComboBox::find_index(const char *str) +{ + if((listsize < 1) || !str) + return -1; + + for (int i = 0; i < listsize; i++) { + if(datalist[i]->s) + if(strncmp(datalist[i]->s, str, FILENAME_MAX) == 0) + return i; + } + + return -1; +} diff --git a/src/config_script/create_default_script.cxx b/src/config_script/create_default_script.cxx new file mode 100644 index 00000000..20f417f4 --- /dev/null +++ b/src/config_script/create_default_script.cxx @@ -0,0 +1,697 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2015 +// Robert Stiles +// +// 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 this program. If not, see . +// ---------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#include + +#ifdef __WOE32__ +# ifdef __CYGWIN__ +# include +# else +# include +# endif +#endif + +#include +#include +#include +#include +#include +#include + +#ifndef __WOE32__ +#include +#endif + +#include "gettext.h" +#include "fl_digi.h" + +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "waterfall.h" +#include "raster.h" +#include "progress.h" +#include "Panel.h" + +#include "main.h" +#include "threads.h" +#include "trx.h" +#if USE_HAMLIB +#include "hamlib.h" +#endif +#include "timeops.h" +#include "rigio.h" +#include "nullmodem.h" +#include "psk.h" +#include "cw.h" +#include "mfsk.h" +#include "wefax.h" +#include "wefax-pic.h" +#include "navtex.h" +#include "mt63.h" +#include "view_rtty.h" +#include "olivia.h" +#include "contestia.h" +#include "thor.h" +#include "dominoex.h" +#include "feld.h" +#include "throb.h" +//#include "pkt.h" +#include "wwv.h" +#include "analysis.h" +#include "fftscan.h" +#include "ssb.h" + +#include "smeter.h" +#include "pwrmeter.h" + +#include "ascii.h" +#include "globals.h" +#include "misc.h" +#include "FTextRXTX.h" + +#include "confdialog.h" +#include "configuration.h" +#include "status.h" + +#include "macros.h" +#include "macroedit.h" +#include "logger.h" +#include "lookupcall.h" + +#include "font_browser.h" + +#include "icons.h" +#include "pixmaps.h" + +#include "rigsupport.h" + +#include "qrunner.h" + +#include "Viewer.h" +#include "soundconf.h" + +#include "htmlstrings.h" +# include "xmlrpc.h" +#if BENCHMARK_MODE +# include "benchmark.h" +#endif + +#include "debug.h" +#include "re.h" +#include "network.h" +#include "spot.h" +#include "dxcc.h" +#include "locator.h" +#include "notify.h" + +#include "logbook.h" + +#include "rx_extract.h" +#include "speak.h" +#include "flmisc.h" + +#include "arq_io.h" +#include "data_io.h" +#include "kmlserver.h" + +#include "notifydialog.h" +#include "macroedit.h" +#include "rx_extract.h" +#include "wefax-pic.h" +#include "charsetdistiller.h" +#include "charsetlist.h" +#include "outputencoder.h" +#include "record_loader.h" +#include "record_browse.h" +#include "fileselect.h" +#include "waterfall.h" +#include "util.h" + +#include "script_parsing.h" +#include "run_script.h" + + +void cb_create_default_script(void); + +static int create_default_script(char *file_name); +static int add_command(FILE *fd, char *cmd, int param, int indent_level); +static int add_command(FILE *fd, char *cmd, char * param, int indent_level); +static int add_command(FILE *fd, char *cmd, int indent_level); +static int add_command(FILE *fd, char *cmd, bool param, int indent_level); +static int add_command(FILE *fd, char *cmd, double param, int indent_level); +static int add_string(FILE *fd, char *cmd, int indent_level); +static void write_macro_list(FILE *fd); + +extern pthread_mutex_t mutex_script_io; + +/** ******************************************************** + * \brief Menu callback. Create default script based on the + * current settings. + * \param none + * \return void + ***********************************************************/ +void cb_create_default_script(void) +{ + pthread_mutex_lock(&mutex_script_io); + + static bool first_time = true; + static char script_filename[FL_PATH_MAX + 1]; + std::string new_path = ""; + + if(first_time) { + memset(script_filename, 0, sizeof(script_filename)); + strncpy(script_filename, ScriptsDir.c_str(), FL_PATH_MAX); + int len = strnlen(script_filename, FL_PATH_MAX); + + if(len > 0) { + len--; + if(script_filename[len] == PATH_CHAR_SEPERATOR); + else strncat(script_filename, PATH_SEPERATOR, FL_PATH_MAX); + } else { + return; + } + + strncat(script_filename, "default_script.txt", FL_PATH_MAX); + + first_time = false; + } + + const char *p = FSEL::saveas((char *)_("Script Files"), (char *)_("*.txt"), \ + script_filename); + + if(p) { + memset(script_filename, 0, sizeof(script_filename)); + strncpy(script_filename, p, FL_PATH_MAX); + + Fl::lock(); + create_default_script(script_filename); + Fl::unlock(); + + } + + pthread_mutex_unlock(&mutex_script_io); +} + +/** ******************************************************** + * \brief Create default script based on current settings. + * \param file_name Pointer to the file name and path. + * \return 0 OK, other Error + ***********************************************************/ +static int create_default_script(char *file_name) +{ + FILE *fd = (FILE *)0; + static char buffer[FL_PATH_MAX]; + std::string temp = ""; + + if(!file_name) { + LOG_INFO(_("Invalid File Name Pointer (NULL) in function %s:%d"), __FILE__, __LINE__); + return -1; + } + + fd = fopen(file_name, "w"); + + if(!fd) { + LOG_INFO(_("Unable to create file %s (Error No=%d) func %s:%d"), file_name, errno, __FILE__, __LINE__); + return -1; + } + + memset(buffer, 0, sizeof(buffer)); + + // Tag the text file as a FLDIGI script file + + fprintf(fd, _("%s\n# Fldigi Generated Config Script\n"), SCRIPT_FILE_TAG); + time_t thetime = time(0); + fprintf(fd, _("# Created: %s\n"), ctime(&thetime)); + + // FLDIGI Main Window + if(add_command(fd, (char *)CMD_FLDIGI, 0)) return fclose(fd); + if(add_command(fd, (char *)CMD_FLDIGI_FREQ, (double) qsoFreqDisp->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_FLDIGI_MODE, (char *) qso_opMODE->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_FLDIGI_WFHZ, (int) wf->Carrier(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_FLDIGI_RXID, (bool) btnRSID->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_FLDIGI_TXID, (bool) btnTxRSID->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_FLDIGI_SPOT, (bool) btnAutoSpot->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_FLDIGI_REV, (bool) wf->btnRev->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_FLDIGI_AFC, (bool) btnAFC->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_FLDIGI_LOCK, (bool) wf->xmtlock->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_FLDIGI_SQL, (bool) btnSQL->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_FLDIGI_KPSQL, (bool) btnPSQL->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_FLDIGI_MODEM, (char *) active_modem->get_mode_name(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_END_CMD, 0)) return fclose(fd); + + + // OPERATOR + if(add_command(fd, (char *)CMD_OPERATOR, 0)) return fclose(fd); + if(add_command(fd, (char *)CMD_CALLSIGN, (char *) inpMyCallsign->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_QTH, (char *) inpMyName->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_NAME, (char *) inpMyQth->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_LOCATOR, (char *) inpMyLocator->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_ANTENNA, (char *) inpMyAntenna->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_END_CMD, 0)) return fclose(fd); + + // AUDIO DEVICE + if(add_command(fd, (char *)CMD_AUDIO_DEVICE, 0)) return fclose(fd); +#if USE_OSS + // OSS + if(add_command(fd, (char *)CMD_OSS_AUDIO, (bool) btnAudioIO[0]->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_OSS_AUDIO_DEV_PATH, (char *) menuOSSDev->value(), 1)) return fclose(fd); +#endif // USE_OSS + +#if USE_PORTAUDIO + // PORT AUDIO + if(add_command(fd, (char *)CMD_PORT_AUDIO, (bool) btnAudioIO[1]->value(), 1)) return fclose(fd); + + if(menuPortInDev->value() > -1) { + memset(buffer, 0, sizeof(buffer)); + snprintf(buffer, sizeof(buffer)-1, "%s:%d,\"%s\"", CMD_PORTA_CAP, menuPortInDev->value(), menuPortInDev->text()); + if(add_string(fd, (char *)buffer, 1)) return fclose(fd); + } + + if(menuPortOutDev->value() > -1) { + memset(buffer, 0, sizeof(buffer)); + snprintf(buffer, sizeof(buffer)-1, "%s:%d,\"%s\"", CMD_PORTA_PLAY, menuPortOutDev->value(), menuPortOutDev->text()); + if(add_string(fd, (char *)buffer, 1)) return fclose(fd); + } +#endif // USE_PORTAUDIO + +#if USE_PULSEAUDIO + // PULSE AUDIO + if(add_command(fd, (char *)CMD_PULSEA, (bool) btnAudioIO[2]->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_PULSEA_SERVER, (char *) inpPulseServer->value(), 1)) return fclose(fd); +#endif // USE_PULSEAUDIO + + if(add_command(fd, (char *)CMD_END_CMD, 0)) return fclose(fd); + + + // AUDIO SETTINGS + if(add_command(fd, (char *)CMD_AUDIO_SETTINGS, 0)) return fclose(fd); + if(add_command(fd, (char *)CMD_CAPTURE_SAMPLE_RATE, (char *) menuInSampleRate->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_PLAYBACK_SAMPLE_RATE, (char *) menuOutSampleRate->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_AUDIO_CONVERTER, (char *) menuSampleConverter->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RX_PPM, (int) cntRxRateCorr->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_TX_PPM, (int) cntTxRateCorr->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_TX_OFFSET, (int) cntTxOffset->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_END_CMD, 0)) return fclose(fd); + + // AUDIO RIGHT CHANNEL + if(add_command(fd, (char *)CMD_AUDIO_RT_CHANNEL, 0)) return fclose(fd); + if(add_command(fd, (char *)CMD_MONO_AUDIO, (bool) chkForceMono->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_AUDIO_L_R, (bool) chkAudioStereoOut->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_AUDIO_REV_L_R, (bool) chkReverseAudio->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_PTT_RIGHT_CHAN, (bool) btnPTTrightchannel2->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_CW_QSK_RT_CHAN, (bool) btnQSK2->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_PSEUDO_FSK_RT_CHAN, (bool) chkPseudoFSK2->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_END_CMD, 0)) return fclose(fd); + + // AUDIO WAVE + if(add_command(fd, (char *)CMD_AUDIO_WAVE, 0)) return fclose(fd); + if(add_command(fd, (char *)CMD_WAVE_SR, (char *) listbox_wav_samplerate->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_END_CMD, 0)) return fclose(fd); + + // RIG HRDWR PTT + if(add_command(fd, (char *)CMD_HRDWR_PTT, 0)) return fclose(fd); + if(add_command(fd, (char *)CMD_HPPT_PTT_RT, (bool) btnPTTrightchannel->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HPTT_SP2, (bool) btnTTYptt->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HPTT_SP2_PATH, (char *) inpTTYdev->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HPTT_SP2_RTS, (bool) btnRTSptt->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HPTT_SP2_RTS_V, (bool) btnRTSplusV->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HPTT_SP2_DTR, (bool) btnDTRptt->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HPTT_SP2_DTR_V, (bool) btnDTRplusV->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HPTT_PARALLEL, (bool) btnUsePPortPTT->value(), 1)) return fclose(fd); +#if HAVE_UHROUTER + if(add_command(fd, (char *)CMD_HPTT_UHROUTER, (bool) btnUseUHrouterPTT->value(), 1)) return fclose(fd); +#endif + if(add_command(fd, (char *)CMD_HPTT_SP2_START_DELAY, (int) cntPTT_on_delay->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HPTT_SP2_END_DELAY, (int) cntPTT_off_delay->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HPTT_SP2_INITIALIZE, 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_END_CMD, 0)) return fclose(fd); + + // RIG CAT + if(add_command(fd, (char *)CMD_RIGCAT, 0)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_STATE, (bool) chkUSERIGCAT->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_DEV_PATH, (char *) inpXmlRigDevice->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_DESC_FILE, (char *) progdefaults.XmlRigFilename.c_str(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_RETRIES, (int) cntRigCatRetries->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_RETRY_INTERVAL, (int) cntRigCatTimeout->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_WRITE_DELAY, (int) cntRigCatWait->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_INTIAL_DELAY, (int) cntRigCatInitDelay->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_BAUD_RATE, (char *) listbox_xml_rig_baudrate->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_STOP_BITS, (int) valRigCatStopbits->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_ECHO, (bool) btnRigCatEcho->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_TOGGLE_RTS_PTT, (bool) btnRigCatRTSptt->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_RESTORE, (bool) chk_restore_tio->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_PTT_COMMAND, (bool) btnRigCatCMDptt->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_TOGGLE_DTR_PTT, (bool) btnRigCatDTRptt->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_TOGGLE_RTS_PTT, (bool) btnRigCatRTSptt->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_RTS_12V, (bool) btnRigCatRTSplus->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_DTR_12V, (bool) btnRigCatDTRplus->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_HRDWR_FLOW, (bool) chkRigCatRTSCTSflow->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_VSP, (bool) chkRigCatVSP->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RIGCAT_INITIALIZE, 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_END_CMD, 0)) return fclose(fd); +#if USE_HAMLIB + // HAMLIB + if(add_command(fd, (char *)CMD_HAMLIB, 0)) return fclose(fd); + if(add_command(fd, (char *)CMD_HAMLIB_STATE, (bool) chkUSEHAMLIB->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HAMLIB_RIG, (char *) cboHamlibRig->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HAMLIB_DEV_PATH, (char *) inpRIGdev->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HAMLIB_RETRIES, (int) cntHamlibRetries->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HAMLIB_RETRY_INTERVAL, (int) cntHamlibTimeout->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HAMLIB_WRITE_DELAY, (int) cntHamlibWriteDelay->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HAMLIB_POST_WRITE_DELAY, (int) cntHamlibWait->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HAMLIB_BAUD_RATE, (char *) listbox_baudrate->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HAMLIB_STOP_BITS, (int) valHamRigStopbits->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HAMLIB_SIDE_BAND, (char *) listbox_sideband->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HAMLIB_PTT_COMMAND, (bool) btnHamlibCMDptt->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HAMLIB_DTR_12V, (bool) btnHamlibDTRplus->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HAMLIB_RTS_12V, (bool) btnHamlibDTRplus->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HAMLIB_HRDWR_FLOW, (bool) chkHamlibRTSCTSflow->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HAMLIB_SFTWR_FLOW, (bool) chkHamlibXONXOFFflow->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HAMLIB_ADV_CONFIG, (char *) inpHamlibConfig->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_HAMLIB_INITIALIZE, 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_END_CMD, 0)) return fclose(fd); +#endif //#if USE_HAMLIB + + // XMLRPC RC + if(add_command(fd, (char *)CMD_RC_XMLRPC, 0)) return fclose(fd); + if(add_command(fd, (char *)CMD_RC_XMLRPC_STATE, (bool) chkUSEXMLRPC->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RC_XMLRPC_BW_DELAY, (double) mbw_delay->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_RC_XMLRPC_INITIALIZE, 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_END_CMD, 0)) return fclose(fd); + + // IO Config Panel + if(add_command(fd, (char *)CMD_IO, 0)) return fclose(fd); + if(add_command(fd, (char *)CMD_IO_LOCK, (bool) btnDisable_p2p_io_widgets->value(), 1)) return fclose(fd); + + if(btnEnable_arq->value()) { + if(add_command(fd, (char *)CMD_IO_ACT_PORT, (char *) PARM_ARQ, 1)) return fclose(fd); + } else if(btnEnable_kiss->value()) { + if(add_command(fd, (char *)CMD_IO_ACT_PORT, (char *) PARM_KISS, 1)) return fclose(fd); + } + + if(add_command(fd, (char *)CMD_IO_AX25_DECODE, (bool) btnEnable_ax25_decode->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_IO_CSMA, (bool) btnEnable_csma->value(), 1)) return fclose(fd); + + if(add_command(fd, (char *)CMD_IO_KISS, 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_IO_KISS_IPA, (char *) txtKiss_ip_address->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_IO_KISS_IOPN, (char *) txtKiss_ip_io_port_no->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_IO_KISS_OPN, (char *) txtKiss_ip_out_port_no->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_IO_KISS_DP, (bool) btnEnable_dual_port->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_IO_KISS_BUSY, (bool) btnEnableBusyChannel->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_IO_KISS_CONT, (int) cntBusyChannelSeconds->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_IO_KISS_ATTEN, (int) cntKPSQLAttenuation->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_END_CMD, 1)) return fclose(fd); + + if(add_command(fd, (char *)CMD_IO_ARQ, 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_IO_ARQ_IPA, (char *) txtArq_ip_address->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_IO_ARQ_IOPN, (char *) txtArq_ip_port_no->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_END_CMD, 1)) return fclose(fd); + + if(add_command(fd, (char *)CMD_IO_XMLRPC, 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_IO_XMLRPC_IPA, (char *) txtXmlrpc_ip_address->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_IO_XMLRPC_IOPN, (char *) txtXmlrpc_ip_port_no->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_END_CMD, 1)) return fclose(fd); + + if(add_command(fd, (char *)CMD_END_CMD, 0)) return fclose(fd); + + // NBEMS + if(add_command(fd, (char *)CMD_NBEMS, 0)) return fclose(fd); + if(add_command(fd, (char *)CMD_NBEMS_STATE, (bool) chkAutoExtract->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_NBEMS_MSG, (bool) chk_open_wrap_folder->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_NBEMS_FLMSG, (bool) chk_open_flmsg->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_NBEMS_FLMSG_PATH, (char *) txt_flmsg_pathname->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_NBEMS_BRWSR, (bool) chk_open_flmsg_print->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_NBEMS_TIMEOUT, (double) sldr_extract_timeout->value(), 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_END_CMD, 0)) return fclose(fd); + + // ID/RSID/VIDEO/CW + if(add_command(fd, (char *)CMD_ID, 0)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_RSID, 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_RSID_NOTIFY, (bool) chkRSidNotifyOnly->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_RSID_SRCH_BP, (bool) chkRSidWideSearch->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_RSID_MARK_PREV, (bool) chkRSidMark->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_RSID_DETECTOR, (bool) chkRSidAutoDisable->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_RSID_ALRT_DIALOG, (bool) chkRSidShowAlert->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_RSID_TX_FREQ_LOCK, (bool) chkRetainFreqLock->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_RSID_FREQ_CHANGE, (bool) chkDisableFreqChange->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_RSID_ALLOW_ERRORS, (char *) listbox_rsid_errors->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_RSID_SQL_OPEN, (int) sldrRSIDsquelch->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_RSID_PRETONE, (double) val_pretone->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_RSID_END_XMT_ID, (bool) btn_post_rsid->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_END_CMD, 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_VIDEO, 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_VIDEO_TX_ID_MODE, (bool) btnsendid->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_VIDEO_TX_VIDEO_TXT, (bool) btnsendvideotext->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_VIDEO_TX_TXT_INP, (char *) valVideotext->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_VIDEO_SMALL_FONT, (bool) chkID_SMALL->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_VIDEO_500_HZ, (bool) btn_vidlimit->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_VIDEO_WIDTH_LIMIT, (bool) btn_vidmodelimit->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_VIDEO_CHAR_ROW, (int) sldrVideowidth->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_END_CMD, 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_CW, 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_CW_TX_CALLSIGN, (bool) btnCWID->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_ID_CW_SPEED, (int) sldrCWIDwpm->value(), 2)) return fclose(fd); + if(add_command(fd, (char *)CMD_END_CMD, 1)) return fclose(fd); + if(add_command(fd, (char *)CMD_END_CMD, 0)) return fclose(fd); + + // MACROS + write_macro_list(fd); + + return fclose(fd); +} + +/** ******************************************************** + * \brief Write the current macro list in script format + * \param fd File descriptor + * \param cmd Pointer to the file name and path. + * \return 0 OK, other Error + ***********************************************************/ +static void write_macro_list(FILE *fd) +{ + if(!fd) return; + + int index = 0; + int row = 0; + int col = 0; + bool save_flag = false; + int count = 0; + char * cPtr = (char *)0; + + for(index = 0; index < MAXMACROS; index++) { + + // Do not save empty macros + count = macros.text[index].size(); + if(count < 1) continue; + cPtr = (char *) macros.text[index].c_str(); + while(count-- > 0) { + if(*cPtr++ > ' ') { + save_flag = true; + break; + } + } + + if(save_flag) { + col = (index / NUMMACKEYS) + 1; + row = (index % NUMMACKEYS) + 1; + fprintf(fd, "\n%s:%d,%d,\"%s\"\n", (char *) CMD_LOAD_MACRO, col, row, macros.name[index].c_str()); + fprintf(fd, "%s\n", macros.text[index].c_str()); + fprintf(fd, "%s:\n",(char *) CMD_END_CMD); + save_flag = false; + } + } +} + +/** ******************************************************** + * \brief Add command and paramter to script file + * \param fd File descriptor + * \param cmd Pointer to the file name and path. + * \return 0 OK, other Error + ***********************************************************/ +static int add_command(FILE *fd, char *cmd, double param, int indent_level) +{ + if(!fd || !cmd) + return -1; + + char buffer[32]; + memset(buffer, 0, sizeof(buffer)); + + if((param > -1000.0) && (param < 1000.0)) + snprintf(buffer, sizeof(buffer) - 1, "%1.3f", param); + else + snprintf(buffer, sizeof(buffer) - 1, "%1.9e", param); + + return add_command(fd, cmd, buffer, indent_level); +} + +/** ******************************************************** + * \brief Add command and paramter to script file + * \param fd File descriptor + * \param cmd Pointer to the file name and path. + * \return 0 OK, other Error + ***********************************************************/ +static int add_command(FILE *fd, char *cmd, bool param, int indent_level) +{ + if(!fd || !cmd) + return -1; + + char buffer[32]; + memset(buffer, 0, sizeof(buffer)); + + if(param) + strncpy(buffer, PARM_ENABLE, sizeof(buffer)-1); + else + strncpy(buffer, PARM_DISABLE, sizeof(buffer)-1); + + return add_command(fd, cmd, buffer, indent_level); +} + +/** ******************************************************** + * \brief Add command and paramter to script file + * \param fd File descriptor + * \param cmd Pointer to the file name and path. + * \return 0 OK, other Error + ***********************************************************/ +static int add_command(FILE *fd, char *cmd, int param, int indent_level) +{ + if(!fd || !cmd) + return -1; + + char buffer[32]; + memset(buffer, 0, sizeof(buffer)); + snprintf(buffer, sizeof(buffer) - 1, "%d", param); + + return add_command(fd, cmd, buffer, indent_level); +} + +/** ******************************************************** + * \brief Add command and paramter to script file + * \param fd File descriptor + * \param cmd Pointer to the file name and path. + * \return 0 OK, other Error + ***********************************************************/ +static int add_command(FILE *fd, char *cmd, char *param, int indent_level) +{ + if(!fd || !cmd || !param) + return -1; + + bool q_flag = false; + int size = strnlen(param, FILENAME_MAX); + + if(size < 1) return 0; + + for(int i = 0; i < size; i++) { + if(param[i] == 0) break; + if((param[i] == ',') || (param[i] <= ' ')) { + q_flag = true; + } + } + + std::string indent = ""; + for(int i = 0; i < indent_level; i++) + indent.append(" "); + + if(q_flag) + fprintf(fd, "%s%s:\"%s\"\n", indent.c_str(), cmd, param); + else + fprintf(fd, "%s%s:%s\n", indent.c_str(), cmd, param); + + return ferror(fd); +} + +/** ******************************************************** + * \brief Add command and paramter to script file + * \param fd File descriptor + * \param cmd Pointer to the file name and path. + * \return 0 OK, other Error + ***********************************************************/ +static int add_command(FILE *fd, char *cmd, int indent_level) +{ + if(!fd || !cmd) + return -1; + + std::string indent = ""; + for(int i = 0; i < indent_level; i++) + indent.append(" "); + + fprintf(fd, "%s%s:\n", indent.c_str(), cmd); + + return ferror(fd); +} + +/** ******************************************************** + * \brief Add command and paramter to script file + * \param fd File descriptor + * \param cmd Pointer to the file name and path. + * \return 0 OK, other Error + ***********************************************************/ +static int add_string(FILE *fd, char *cmd, int indent_level) +{ + if(!fd || !cmd) + return -1; + + std::string indent = ""; + for(int i = 0; i < indent_level; i++) + indent.append(" "); + + fprintf(fd, "%s%s\n", indent.c_str(), cmd); + + return ferror(fd); +} + diff --git a/src/config_script/run_script.h b/src/config_script/run_script.h new file mode 100644 index 00000000..d0e8cc91 --- /dev/null +++ b/src/config_script/run_script.h @@ -0,0 +1,168 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2015 +// Robert Stiles +// +// 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 this program. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef _run_script_h +#define _run_script_h + +extern int process_callsign_info(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_name_info(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_qth_info(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_locator_info(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_antenna_info(ScriptParsing *sp, SCRIPT_COMMANDS *sc); + +extern int process_use_oss_audio_device(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_oss_audio_device_path(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_use_port_audio_device(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_capture_path(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_playback_path(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_use_pulse_audio_device(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_pulse_audio_device_path(ScriptParsing *sp, SCRIPT_COMMANDS *sc); + +extern int process_audio_device_sample_rate_capture(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_audio_device_sample_rate_playback(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_audio_device_converter(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rx_ppm(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_tx_ppm(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_tx_offset(ScriptParsing *sp, SCRIPT_COMMANDS *sc); + +extern int process_mono_audio_output(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_modem_signal_left_right(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_reverse_left_right(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_ptt_tone_right_channel(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_cw_qsk_right_channel(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_pseudo_fsk_right_channel(ScriptParsing *sp, SCRIPT_COMMANDS *sc); + +extern int process_wave_file_sample_rate(ScriptParsing *sp, SCRIPT_COMMANDS *sc); + +extern int process_hrdw_ptt_right_audio_channel(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hrdw_ptt_sep_serial_port(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hrdw_ptt_sep_serial_port_path(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hrdw_ptt_sep_serial_port_rts(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hrdw_ptt_sep_serial_port_dtr(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hrdw_ptt_sep_serial_port_rts_v(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hrdw_ptt_sep_serial_port_dtr_v(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hrdw_ptt_start_delay(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hrdw_ptt_end_delay(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hrdw_ptt_uhrouter(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hrdw_ptt_initialize(ScriptParsing *sp, SCRIPT_COMMANDS *sc); + +extern int process_use_rigcat(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rigcat_desc_file(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rigcat_device_path(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rigcat_retries(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rigcat_retry_interval(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rigcat_write_delay(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rigcat_init_delay(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rigcat_baud_rate(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rigcat_stop_bits(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rigcat_commands_echoed(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rigcat_toggle_rts_ptt(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rigcat_restore_on_close(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rigcat_cat_command_ptt(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rigcat_dtr_12v(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rigcat_rts_12v(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rigcat_hrdwr_flow(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rigcat_vsp_enable(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rigcat_initialize(ScriptParsing *sp, SCRIPT_COMMANDS *sc); + +extern int process_use_hamlib(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hamlib_rig(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hamlib_device_path(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hamlib_retries(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hamlib_retry_interval(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hamlib_write_delay(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hamlib_post_write_delay(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hamlib_baud_rate(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hamlib_stop_bits(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hamlib_sideband(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hamlib_ptt_hl_command(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hamlib_dtr_12(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hamlib_rts_12(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hamlib_rts_cts_flow(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hamlib_xon_xoff_flow(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hamlib_advanced_config(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_hamlib_initialize(ScriptParsing *sp, SCRIPT_COMMANDS *sc); + +extern int process_use_xml_rpc(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_xml_rpc_mode_bw_delay(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_xml_rpc_initialize(ScriptParsing *sp, SCRIPT_COMMANDS *sc); + +extern int process_io_kiss_ip_address(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_io_kiss_io_port_no(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_io_kiss_o_port_no(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_io_kiss_dual_port(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_io_kiss_busy_channel(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_io_kiss_continue_after(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_io_kiss_kpsql_atten(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_io_arq_ip_address(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_io_arq_io_port_no(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_io_xmlrpc_ip_address(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_io_xmlrpc_io_port_no(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_io_lock(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_io_active_port(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_io_ax25_decode(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_io_csma(ScriptParsing *sp, SCRIPT_COMMANDS *sc); + +extern int process_misc_nbems_state(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_misc_nbems_open_flmsg(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_misc_nbems_open_msg(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_misc_nbems_open_brwsr(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_misc_nbems_flmsg_path(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_misc_nbems_timeout(ScriptParsing *sp, SCRIPT_COMMANDS *sc); + +extern int process_rsid_notify(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rsid_search_bp(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rsid_mark_prev(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rsid_detector(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rsid_alert_dialog(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rsid_tx_freq_lock(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rsid_freq_change(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rsid_allow_errors(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rsid_sql_open(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rsid_pretone(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rsid_end_xmt_id(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_video_tx_id_mode(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_video_tx_vid_txt(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_video_txt_input(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_video_small_font(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_video_500hz(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_video_width_limit(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rsid_char_per_row(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_cw_callsign(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_cw_speed(ScriptParsing *sp, SCRIPT_COMMANDS *sc); + +// FLDIGI main windows widgets + +extern int process_rig_freq(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rig_mode(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_wf_hz_offset(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rx_rsid(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_tx_rsid(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_spot(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_rev(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_afc(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_lock(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_sql(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_kpsql(ScriptParsing *sp, SCRIPT_COMMANDS *sc); +extern int process_modem(ScriptParsing *sp, SCRIPT_COMMANDS *sc); + +extern int process_load_macro(ScriptParsing *sp, SCRIPT_COMMANDS *sc); + +#endif diff --git a/src/config_script/run_scripts.cxx b/src/config_script/run_scripts.cxx new file mode 100644 index 00000000..365f4aa0 --- /dev/null +++ b/src/config_script/run_scripts.cxx @@ -0,0 +1,2893 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2015 +// Robert Stiles +// +// 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 this program. If not, see . +// ---------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#include + +#ifdef __WOE32__ +# ifdef __CYGWIN__ +# include +# else +# include +# endif +#endif + +#include +#include +#include +#include +#include +#include + +#ifndef __WOE32__ +#include +#endif + +#include "gettext.h" +#include "fl_digi.h" + +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "waterfall.h" +#include "raster.h" +#include "progress.h" +#include "Panel.h" + +#include "main.h" +#include "threads.h" +#include "trx.h" +#if USE_HAMLIB +#include "hamlib.h" +#endif +#include "timeops.h" +#include "rigio.h" +#include "nullmodem.h" +#include "psk.h" +#include "cw.h" +#include "mfsk.h" +#include "wefax.h" +#include "wefax-pic.h" +#include "navtex.h" +#include "mt63.h" +#include "view_rtty.h" +#include "olivia.h" +#include "contestia.h" +#include "thor.h" +#include "dominoex.h" +#include "feld.h" +#include "throb.h" +//#include "pkt.h" +#include "wwv.h" +#include "analysis.h" +#include "fftscan.h" +#include "ssb.h" + +#include "smeter.h" +#include "pwrmeter.h" + +#include "ascii.h" +#include "globals.h" +#include "misc.h" +#include "FTextRXTX.h" + +#include "confdialog.h" +#include "configuration.h" +#include "status.h" + +#include "macros.h" +#include "macroedit.h" +#include "logger.h" +#include "lookupcall.h" + +#include "font_browser.h" + +#include "icons.h" +#include "pixmaps.h" + +#include "rigsupport.h" + +#include "qrunner.h" + +#include "Viewer.h" +#include "soundconf.h" + +#include "htmlstrings.h" +# include "xmlrpc.h" +#if BENCHMARK_MODE +# include "benchmark.h" +#endif + +#include "debug.h" +#include "re.h" +#include "network.h" +#include "spot.h" +#include "dxcc.h" +#include "locator.h" +#include "notify.h" + +#include "logbook.h" + +#include "rx_extract.h" +#include "speak.h" +#include "flmisc.h" + +#include "arq_io.h" +#include "data_io.h" +#include "kmlserver.h" + +#include "notifydialog.h" +#include "macroedit.h" +#include "rx_extract.h" +#include "wefax-pic.h" +#include "charsetdistiller.h" +#include "charsetlist.h" +#include "outputencoder.h" +#include "record_loader.h" +#include "record_browse.h" +#include "fileselect.h" + +#include "script_parsing.h" +#include "run_script.h" + +pthread_mutex_t mutex_script_io = PTHREAD_MUTEX_INITIALIZER; + +extern std::string ScriptsDir; + +void script_execute(void *); +static void script_execute(const char *filename, bool queue_flag); + +/** ******************************************************** + * \brief Template for assigning bool values to various widget types. + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +template +static int assign_bool(widget_type * widget, ScriptParsing *sp, SCRIPT_COMMANDS *sc, bool &data) +{ + if(!sp || !sc) + return script_function_parameter_error; + + bool value = 0; + + int error = sp->check_bool(sc->args[0], value); + + if(error != script_no_errors) + return error; + + if(!widget) + return script_no_errors; + + widget->value(value); + widget->do_callback(); + + data = value; + + return script_no_errors; +} + +/** ******************************************************** + * \brief Template for assigning bool values to various widget types. + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +template +static int assign_bool(widget_type * widget, ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + bool data = false; + return assign_bool(widget, sp, sc, data); +} + +/** ******************************************************** + * \brief Template for assigning integer values to various widget types. + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +template +static int assign_integer(widget_type * widget, ScriptParsing *sp, SCRIPT_COMMANDS *sc, int &data) +{ + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + int value = 0; + int cnt = sscanf(str_data.c_str(), "%d", &value); + + if(cnt < 1) + return script_invalid_parameter; + + if(!widget) + return script_no_errors; + + int min = (int) widget->minimum(); + int max = (int) widget->maximum(); + + if((value < min) || (value > max)) + return script_invalid_parameter; + + widget->value(value); + widget->do_callback(); + + data = value; + + return script_no_errors; +} + +/** ******************************************************** + * \brief Template for assigning integer values to various widget types. + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +template +static int assign_integer(widget_type * widget, ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + int data = 0.0; + return assign_integer(widget, sp, sc, data); +} + +/** ******************************************************** + * \brief Template for assigning double values to various widget types. + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +template +static int assign_double(widget_type * widget, ScriptParsing *sp, SCRIPT_COMMANDS *sc, double &data) +{ + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + double value = 0; + int cnt = sscanf(str_data.c_str(), "%lf", &value); + + if(cnt < 1) + return script_invalid_parameter; + + if(!widget) + return script_no_errors; + + double min = (double) widget->minimum(); + double max = (double) widget->maximum(); + + if((value < min) || (value > max)) + return script_invalid_parameter; + + widget->value(value); + widget->do_callback(); + + data = value; + + return script_no_errors; +} + +/** ******************************************************** + * \brief Template for assigning double values to various widget types. + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +template +static int assign_double(widget_type * widget, ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + double data = 0.0; + return assign_double(widget, sp, sc, data); +} + +/** ******************************************************** + * \brief Template for assigning string values to various widget types. + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +template +static int assign_string(widget_type * widget, ScriptParsing *sp, SCRIPT_COMMANDS *sc, std::string &data) +{ + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + if(!widget) + return script_no_errors; + + widget->value(str_data.c_str()); + widget->do_callback(); + + data.assign(str_data); + + return script_no_errors; +} + +/** ******************************************************** + * \brief Template for assigning string values to various widget types. + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +template +static int assign_string(widget_type * widget, ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + std::string data = ""; + return assign_string(widget, sp, sc, data); +} + +/** ******************************************************** + * \brief Template for assigning index values to various widget types. + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +template +static int assign_index(widget_type * widget, ScriptParsing *sp, SCRIPT_COMMANDS *sc, int &data) +{ + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + if(!widget) + return script_no_errors; + + int index = widget->find_index(str_data.c_str()); + if(index < 0) + return script_invalid_parameter; + + widget->index(index); + widget->do_callback(); + + data = index; + + return script_no_errors; +} + +/** ******************************************************** + * \brief Template for assigning index values to various widget types. + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +template +static int assign_index(widget_type * widget, ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + int data = 0; + return assign_index(widget, sp, sc, data); +} + + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rsid_notify(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(chkRSidNotifyOnly, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rsid_search_bp(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(chkRSidWideSearch, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rsid_mark_prev(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(chkRSidMark, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rsid_detector(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(chkRSidAutoDisable, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rsid_alert_dialog(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(chkRSidShowAlert, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rsid_tx_freq_lock(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(chkRetainFreqLock, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rsid_freq_change(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(chkDisableFreqChange, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rsid_allow_errors(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_index(listbox_rsid_errors, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rsid_sql_open(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_integer(sldrRSIDsquelch, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rsid_pretone(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_double(val_pretone, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rsid_char_per_row(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_integer(sldrVideowidth, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rsid_end_xmt_id(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btn_post_rsid, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_video_tx_id_mode(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnsendid, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_video_tx_vid_txt(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnsendvideotext, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_video_txt_input(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_string(valVideotext, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_video_small_font(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(chkID_SMALL, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_video_500hz(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btn_vidlimit, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_video_width_limit(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btn_vidmodelimit, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_cw_callsign(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnCWID, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_cw_speed(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_integer(sldrCWIDwpm, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_misc_nbems_state(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(chkAutoExtract, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_misc_nbems_open_flmsg(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(chk_open_flmsg, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_misc_nbems_open_msg(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(chk_open_wrap_folder, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_misc_nbems_open_brwsr(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(chk_open_flmsg_print, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_misc_nbems_flmsg_path(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_string(txt_flmsg_pathname, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_misc_nbems_timeout(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_integer(sldr_extract_timeout, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rig_freq(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + if(!qsoFreqDisp) + return script_no_errors; + + double value = 0; + double max = (double) qsoFreqDisp->maximum(); + + int cnt = sscanf(str_data.c_str(), "%lf", &value); + + if(cnt < 1 || value < 0.0 || value > max) + return script_invalid_parameter; + + qsy((long int) value, active_modem ? active_modem->get_freq() : 1500); + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rig_mode(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_index(qso_opMODE, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_wf_hz_offset(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + if(!cntrWfwidth) + return script_no_errors; + + int value = 0; + int cnt = sscanf(str_data.c_str(), "%d", &value); + + int min = 0; + int max = cntrWfwidth->maximum(); + + if(cnt < 1 || value < min || value > max) + return script_invalid_parameter; + + active_modem->set_freq(value); + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rx_rsid(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnRSID, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_tx_rsid(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnTxRSID, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_spot(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnAutoSpot, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rev(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + if(!wf) return script_no_errors; + return assign_bool(wf->btnRev, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_afc(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnAFC, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_lock(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + if(!wf) return script_no_errors; + return assign_bool(wf->xmtlock, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_sql(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnSQL, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_kpsql(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnPSQL, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + **********************************************************/ +int process_modem(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + bool modem_found = false; + int index = 0; + + std::string value; + value.assign(sc->args[0]); + + if(value.empty()) + return script_parameter_error; + + sp->to_uppercase(value); + + for(index = 0; index < NUM_MODES; index++) { + if(strncmp(value.c_str(), mode_info[index].sname, 32) == 0) { + modem_found = true; + break; + } + } + + if(modem_found == false) + return script_invalid_parameter; + + if((data_io_enabled == KISS_IO) && (!(mode_info[index].iface_io & KISS_IO))) { + LOG_INFO(_("Invalid Modem for KISS IO")); + return script_invalid_parameter; + } + + REQ_SYNC(init_modem_sync, index, 0); + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_io_kiss_ip_address(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + if(!txtKiss_ip_address) + return script_no_errors; + + if(strncmp((const char *)str_data.c_str(), (const char *)txtKiss_ip_address->value(), 32) != 0) { + txtKiss_ip_address->value(str_data.c_str()); + txtKiss_ip_address->do_callback(); + sp->restart_flag(true); + } + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_io_kiss_io_port_no(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + if(!txtKiss_ip_io_port_no) + return script_no_errors; + + if(strncmp((const char *)str_data.c_str(), (const char *)txtKiss_ip_io_port_no->value(), 32) != 0) { + txtKiss_ip_io_port_no->value(str_data.c_str()); + txtKiss_ip_io_port_no->do_callback(); + sp->restart_flag(true); + } + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_io_kiss_o_port_no(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + if(!txtKiss_ip_out_port_no) + return script_no_errors; + + if(strncmp((const char *)str_data.c_str(), (const char *)txtKiss_ip_out_port_no->value(), 32) != 0) { + txtKiss_ip_out_port_no->value(str_data.c_str()); + txtKiss_ip_out_port_no->do_callback(); + sp->restart_flag(true); + } + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_io_kiss_dual_port(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnEnable_dual_port, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_io_kiss_busy_channel(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnEnableBusyChannel, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_io_kiss_continue_after(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_integer(cntBusyChannelSeconds, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_io_kiss_kpsql_atten(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_integer(cntKPSQLAttenuation, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_io_arq_ip_address(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + if(!txtArq_ip_address) + return script_no_errors; + + if(strncmp((const char *)str_data.c_str(), (const char *)txtArq_ip_address->value(), 32) != 0) { + txtArq_ip_address->value(str_data.c_str()); + txtArq_ip_address->do_callback(); + sp->restart_flag(true); + } + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_io_arq_io_port_no(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + if(!txtArq_ip_address) + return script_no_errors; + + if(strncmp((const char *)str_data.c_str(), (const char *)txtArq_ip_port_no->value(), 32) != 0) { + txtArq_ip_port_no->value(str_data.c_str()); + txtArq_ip_port_no->do_callback(); + sp->restart_flag(true); + } + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_io_xmlrpc_ip_address(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + if(!txtXmlrpc_ip_address) + return script_no_errors; + + if(strncmp((const char *)str_data.c_str(), (const char *)txtXmlrpc_ip_address->value(), 32) != 0) { + txtXmlrpc_ip_address->value(str_data.c_str()); + txtXmlrpc_ip_address->do_callback(); + sp->restart_flag(true); + } + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_io_xmlrpc_io_port_no(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + if(!txtXmlrpc_ip_port_no) + return script_no_errors; + + if(strncmp((const char *)str_data.c_str(), (const char *)txtXmlrpc_ip_port_no->value(), 32) != 0) { + txtXmlrpc_ip_port_no->value(str_data.c_str()); + txtXmlrpc_ip_port_no->do_callback(); + sp->restart_flag(true); + } + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_io_lock(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnDisable_p2p_io_widgets, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_io_active_port(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + std::string value; + value.assign(sc->args[0]); + + if(value.empty()) + return script_parameter_error; + + sp->to_uppercase(value); + + if(!btnEnable_kiss || !btnEnable_arq) + return script_no_errors; + + if(value.find(PARM_KISS) != std::string::npos) { + btnEnable_kiss->value(true); + btnEnable_kiss->do_callback(); + } else if(value.find(PARM_ARQ) != std::string::npos) { + btnEnable_arq->value(true); + btnEnable_arq->do_callback(); + } else { + return script_invalid_parameter; + } + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_io_ax25_decode(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnEnable_ax25_decode, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_io_csma(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnEnable_csma, sp, sc); +} + +/** ******************************************************** + * \brief Assign Call Sign. + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + * \par Note: + * This string storage can be assigned to anything. User + * should follow the limitations imposed by the rules + * of the host country. + ***********************************************************/ +int process_callsign_info(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_string(inpMyCallsign, sp, sc); +} + +/** ******************************************************** + * \brief Operator Name + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_name_info(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_string(inpMyName, sp, sc); +} + +/** ******************************************************** + * \brief QTH Location of Operator + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_qth_info(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_string(inpMyQth, sp, sc); +} + +/** ******************************************************** + * \brief Assign Locator + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_locator_info(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_string(inpMyLocator, sp, sc); +} + +/** ******************************************************** + * \brief Assign Antenna information + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_antenna_info(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_string(inpMyAntenna, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_use_oss_audio_device(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_OSS + return assign_bool(btnAudioIO[0], sp, sc); +#else + return script_no_errors; +#endif // USE_OSS +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_oss_audio_device_path(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx +#if USE_OSS + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data; + std::string valid_data; + + str_data.assign(sc->args[0]); + if(str_data.empty()) + return script_invalid_parameter; + + if(!menuOSSDev) + return script_no_errors; + + if(sp->check_dev_path(str_data.c_str())) + return script_device_path_not_found; + + int index = 0; + bool found = false; + int count = menuOSSDev->menubutton()->size(); + + for (index = 0; index < count; index++ ) { + const Fl_Menu_Item &item = menuOSSDev->menubutton()->menu()[index]; + valid_data.assign(item.label()); + if(!valid_data.empty()) { + if(strncmp(valid_data.c_str(), str_data.c_str(), FL_PATH_MAX) == 0) { + found = true; + break; + } + } + } + + if(!found) + return script_invalid_parameter; + + menuOSSDev->value(index); + menuOSSDev->do_callback(); + +#else + return script_no_errors; +#endif // USE_OSS +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_use_port_audio_device(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_PORTAUDIO + return assign_bool(btnAudioIO[1], sp, sc); +#else + return script_no_errors; +#endif // USE_PORTAUDIO +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_capture_path(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx +#if USE_PORTAUDIO + if(!sp || !sc) + return script_function_parameter_error; + + int value = 0; + std::string str_data = ""; + + if(sc->argc < 2) + return script_invalid_parameter; + + int cnt = sscanf(sc->args[0], "%d", &value); + + if(cnt < 1 || value < 0) + return script_invalid_parameter; + + str_data.assign(sc->args[1]); + if(str_data.empty()) + return script_invalid_parameter; + + if(!menuPortInDev) + return script_no_errors; + + cnt = pa_set_dev(menuPortInDev, str_data, value); + + if(cnt == PA_DEV_NOT_FOUND) + return script_invalid_parameter; + +#else + return script_no_errors; +#endif // USE_PORTAUDIO +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_playback_path(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx +#if USE_PORTAUDIO + + if(!sp || !sc) + return script_function_parameter_error; + + int value = 0; + std::string str_data = ""; + + if(sc->argc < 2) + return script_invalid_parameter; + + int cnt = sscanf(sc->args[0], "%d", &value); + + if(cnt < 1 || value < 0) + return script_invalid_parameter; + + str_data.assign(sc->args[1]); + if(str_data.empty()) + return script_invalid_parameter; + + if(!menuPortOutDev) + return script_no_errors; + + cnt = pa_set_dev(menuPortOutDev, str_data, value); + + if(cnt == PA_DEV_NOT_FOUND) + return script_invalid_parameter; + +#else + return script_no_errors; +#endif // USE_PORTAUDIO +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_use_pulse_audio_device(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_PULSEAUDIO + return assign_bool(btnAudioIO[2], sp, sc); +#else + return script_no_errors; +#endif // USE_PULSEAUDIO +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_pulse_audio_device_path(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_PULSEAUDIO + return assign_string(inpPulseServer, sp, sc); +#else + return script_no_errors; +#endif // USE_PULSEAUDIO +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_audio_device_sample_rate_capture(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + if(!menuInSampleRate) + return script_no_errors; + + int index = menuInSampleRate->find_index(str_data.c_str()); + if(index < 0) { + str_data.append(" (native)"); + index = menuInSampleRate->find_index(str_data.c_str()); + } + + if(index < 0) + return script_invalid_parameter; + + menuInSampleRate->index(index); + menuInSampleRate->do_callback(); + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_audio_device_sample_rate_playback(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + if(!menuOutSampleRate) + return script_no_errors; + + int index = menuOutSampleRate->find_index(str_data.c_str()); + if(index < 0) { + str_data.append(" (native)"); + index = menuOutSampleRate->find_index(str_data.c_str()); + } + + if(index < 0) + return script_invalid_parameter; + + menuOutSampleRate->index(index); + menuOutSampleRate->do_callback(); + + return script_no_errors; + +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_audio_device_converter(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data; + std::string append_string; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + append_string.assign(" Sinc Interpolator"); + if(str_data.find(append_string) != std::string::npos) + append_string.clear(); + + if(append_string.empty()) { + append_string.assign(" Interpolator"); + if(str_data.find(append_string) != std::string::npos) { + append_string.clear(); + } + } + + str_data.append(append_string); + + if(!menuSampleConverter) + return script_no_errors; + + int index = menuSampleConverter->find_index(str_data.c_str()); + if(index < 0) + return script_invalid_parameter; + + menuSampleConverter->index(index); + menuSampleConverter->do_callback(); + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rx_ppm(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_integer(cntRxRateCorr, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_tx_ppm(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_integer(cntTxRateCorr, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_tx_offset(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_integer(cntTxOffset, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_mono_audio_output(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(chkForceMono, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_modem_signal_left_right(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(chkAudioStereoOut, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_reverse_left_right(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(chkReverseAudio, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_ptt_tone_right_channel(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnPTTrightchannel2, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_cw_qsk_right_channel(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnQSK2, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_pseudo_fsk_right_channel(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(chkPseudoFSK2, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_wave_file_sample_rate(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + char buffer[32]; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + int value = 0; + int cnt = sscanf(str_data.c_str(), "%d", &value); + + if(cnt < 1) + return script_invalid_parameter; + + if((value < 8000) || (value > 48000)) + return script_invalid_parameter; + + memset(buffer, 0, sizeof(buffer)); + snprintf(buffer, sizeof(buffer) - 1, "%d", value); + + if(!listbox_wav_samplerate) + return script_no_errors; + + int index = listbox_wav_samplerate->find_index(buffer); + if(index < 0) + return script_invalid_parameter; + + listbox_wav_samplerate->index(index); + listbox_wav_samplerate->do_callback(); + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hrdw_ptt_right_audio_channel(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnPTTrightchannel, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hrdw_ptt_sep_serial_port(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnTTYptt, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + * \par NOTE: + * Fl_ComboBox (custom widget) + * find_index() located in combo.cxx and used here returns -1 + * on non-matching. + ***********************************************************/ +int process_hrdw_ptt_sep_serial_port_path(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_index(inpTTYdev, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hrdw_ptt_sep_serial_port_rts(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnRTSptt, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hrdw_ptt_sep_serial_port_dtr(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnDTRptt, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hrdw_ptt_sep_serial_port_rts_v(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnRTSplusV, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hrdw_ptt_sep_serial_port_dtr_v(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnDTRplusV, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hrdw_ptt_start_delay(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_integer(cntPTT_on_delay, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hrdw_ptt_end_delay(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_integer(cntPTT_off_delay, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hrdw_ptt_uhrouter(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if HAVE_UHROUTER + return assign_bool(btnUseUHrouterPTT, sp, sc); +#else + return script_no_errors; +#endif // HAVE_UHROUTER +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hrdw_ptt_parallel(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnUsePPortPTT, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hrdw_ptt_initialize(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + + if(!btnInitHWPTT) + return script_no_errors; + + btnInitHWPTT->do_callback(); + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_use_rigcat(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(chkUSERIGCAT, sp, sc); +} + +extern void loadRigXmlFile(void); +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rigcat_desc_file(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + if(str_data.find(DEFAULT_RIGXML_FILENAME) != std::string::npos) + return script_no_errors; + + if(sp->check_filename((char *) str_data.c_str())) + return script_file_not_found; + + if(!txtXmlRigFilename) + return script_no_errors; + + progdefaults.XmlRigFilename.assign(str_data); + txtXmlRigFilename->value(fl_filename_name(progdefaults.XmlRigFilename.c_str())); + loadRigXmlFile(); + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rigcat_device_path(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_index(inpXmlRigDevice, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rigcat_retries(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + int value = 0; + int error = assign_integer(cntRigCatRetries, sp, sc, value); + + if(!error && cntRigCatRetries) { + progdefaults.RigCatRetries = value; + progdefaults.changed = true; + } + return error; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rigcat_retry_interval(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + int value = 0; + int error = assign_integer(cntRigCatTimeout, sp, sc, value); + + if(!error && cntRigCatTimeout) { + progdefaults.RigCatTimeout = value; + progdefaults.changed = true; + } + + return error; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rigcat_write_delay(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + int value = 0; + int error = assign_integer(cntRigCatWait, sp, sc, value); + + if(!error && cntRigCatWait) { + progdefaults.RigCatTimeout = value; + progdefaults.changed = true; + } + + return error; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rigcat_init_delay(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + int value = 0; + int error = assign_integer(cntRigCatInitDelay, sp, sc, value); + + if(!error && cntRigCatInitDelay) { + progdefaults.RigCatInitDelay = value; + progdefaults.changed = true; + } + return error; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rigcat_baud_rate(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + int index = 0; + int error = assign_index(listbox_xml_rig_baudrate, sp, sc, index); + + if(!error && listbox_xml_rig_baudrate) { + progdefaults.XmlRigBaudrate = index; + progdefaults.changed = true; + } + + return error; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rigcat_cat_command_ptt(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return assign_bool(btnRigCatCMDptt, sp, sc); +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rigcat_stop_bits(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + int value = 0; + int error = assign_integer(valRigCatStopbits, sp, sc, value); + + if(!error && valRigCatStopbits) { + progdefaults.RigCatStopbits = value; + progdefaults.changed = true; + } + + return error; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rigcat_commands_echoed(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + bool value = 0; + int error = assign_bool(btnRigCatEcho, sp, sc, value); + + if(!error && btnRigCatEcho) { + progdefaults.RigCatECHO = value; + progdefaults.changed = true; + } + + return error; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rigcat_toggle_rts_ptt(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + bool value = 0; + int error = assign_bool(btnRigCatRTSptt, sp, sc, value); + + if(!error && btnRigCatRTSptt) { + progdefaults.RigCatRTSptt = value; + progdefaults.changed = true; + } + + return error; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rigcat_restore_on_close(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + bool value = 0; + int error = assign_bool(chk_restore_tio, sp, sc, value); + + if(!error && chk_restore_tio) { + progdefaults.RigCatRestoreTIO = value; + progdefaults.changed = true; + } + + return error; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rigcat_rts_12v(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + bool value = 0; + int error = assign_bool(btnRigCatRTSplus, sp, sc, value); + + if(!error && btnRigCatRTSplus) { + progdefaults.RigCatRTSplus = value; + progdefaults.changed = true; + } + + return error; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rigcat_dtr_12v(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + bool value = 0; + int error = assign_bool(btnRigCatDTRplus, sp, sc, value); + + if(!error && btnRigCatDTRplus) { + progdefaults.RigCatDTRplus = value; + progdefaults.changed = true; + } + + return error; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rigcat_hrdwr_flow(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + bool value = 0; + int error = assign_bool(chkRigCatRTSCTSflow, sp, sc, value); + + if(!error && chkRigCatRTSCTSflow) { + progdefaults.RigCatRTSCTSflow = value; + progdefaults.changed = true; + } + + return error; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rigcat_vsp_enable(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + bool value = 0; + int error = assign_bool(chkRigCatVSP, sp, sc, value); + + if(!error && chkRigCatVSP) { + progdefaults.RigCatVSP = value; + progdefaults.changed = true; + } + + return error; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_rigcat_initialize(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + if(!btnInitRIGCAT) + return script_no_errors; + + btnInitRIGCAT->do_callback(); + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_use_hamlib(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_HAMLIB + return assign_bool(chkUSEHAMLIB, sp, sc); +#endif // USE_HAMLIB + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hamlib_rig(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_HAMLIB + return assign_index(cboHamlibRig, sp, sc); +#else + return script_no_errors; +#endif // USE_HAMLIB +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hamlib_retries(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_HAMLIB + int value = 0; + int error = assign_integer(cntHamlibRetries, sp, sc, value); + + if(!error && cntHamlibRetries) { + progdefaults.HamlibRetries = value; + progdefaults.changed = true; + } + + return error; + +#else + return script_no_errors; +#endif // USE_HAMLIB + +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hamlib_retry_interval(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_HAMLIB + int value = 0; + int error = assign_integer(cntHamlibTimeout, sp, sc, value); + + if(!error && cntHamlibTimeout) { + progdefaults.HamlibTimeout = value; + progdefaults.changed = true; + } + + return error; +#else + return script_no_errors; +#endif // USE_HAMLIB +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hamlib_write_delay(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_HAMLIB + int value = 0; + int error = assign_integer(cntHamlibWriteDelay, sp, sc, value); + + if(!error && cntHamlibWriteDelay) { + progdefaults.HamlibWriteDelay = value; + progdefaults.changed = true; + } + + return error; +#else + return script_no_errors; +#endif // USE_HAMLIB +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hamlib_post_write_delay(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_HAMLIB + int value = 0; + int error = assign_integer(cntHamlibWait, sp, sc, value); + + if(!error && cntHamlibWait) { + progdefaults.HamlibWait = value; + progdefaults.changed = true; + } + + return error; +#else + return script_no_errors; +#endif // USE_HAMLIB +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + * \par Note: + * This string storage can be assigned to anything. User + * should follow the limitations imposed by the rules + * of the host country. + ***********************************************************/ +int process_hamlib_device_path(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_HAMLIB + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + std::string str_data = ""; + + if(sc->argc > 0) + str_data.assign(sc->args[0]); + + if(str_data.empty()) + return script_invalid_parameter; + + if(!inpRIGdev) + return script_no_errors; + + int index = inpRIGdev->find_index(str_data.c_str()); + if(index < 0) + return script_invalid_parameter; + + progdefaults.HamRigDevice.assign(str_data); + progdefaults.changed = true; + + inpRIGdev->value(str_data.c_str()); + inpRIGdev->do_callback(); + +#endif // USE_HAMLIB + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hamlib_baud_rate(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_HAMLIB + int index = 0; + int error = assign_index(listbox_baudrate, sp, sc, index); + + if(!error && listbox_baudrate) { + progdefaults.HamRigBaudrate = index; + progdefaults.changed = true; + } + return error; +#else + return script_no_errors; +#endif // USE_HAMLIB +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hamlib_stop_bits(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_HAMLIB + int value = 0; + int error = assign_integer(valHamRigStopbits, sp, sc, value); + + if(!error && valHamRigStopbits) { + progdefaults.HamRigStopbits = value; + progdefaults.changed = true; + } + return error; +#else + return script_no_errors; +#endif // USE_HAMLIB +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hamlib_sideband(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_HAMLIB + int index = 0; + int error = assign_index(listbox_sideband, sp, sc, index); + + if(!error && listbox_sideband) { + progdefaults.HamlibSideband = index; + progdefaults.changed = true; + } + return error; +#else + return script_no_errors; +#endif // USE_HAMLIB +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hamlib_ptt_hl_command(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_HAMLIB + bool value = 0; + int error = assign_bool(btnHamlibCMDptt, sp, sc, value); + + if(!error && btnHamlibCMDptt) { + progdefaults.HamlibCMDptt = value; + progdefaults.changed = true; + } + return error; +#else + return script_no_errors; +#endif // USE_HAMLIB +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hamlib_dtr_12(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_HAMLIB + bool value = 0; + int error = assign_bool(btnHamlibDTRplus, sp, sc, value); + + if(!error && btnHamlibDTRplus) { + progdefaults.HamlibDTRplus = value; + progdefaults.changed = true; + } + return error; +#else + return script_no_errors; +#endif // USE_HAMLIB +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hamlib_rts_12(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_HAMLIB + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + bool value = 0; + int error = sp->check_bool(sc->args[0], value); + + if(error != script_no_errors) + return error; + + if(!chkHamlibRTSCTSflow || !chkHamlibRTSplus) + return script_no_errors; + + if(chkHamlibRTSCTSflow->value()) + value = false; + + progdefaults.HamlibRTSplus = value; + progdefaults.changed = true; + + chkHamlibRTSplus->value(value); + chkHamlibRTSplus->do_callback(); + +#endif // USE_HAMLIB + + return script_no_errors; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hamlib_rts_cts_flow(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_HAMLIB + bool value = 0; + int error = assign_bool(chkHamlibRTSCTSflow, sp, sc, value); + + if(!error && chkHamlibRTSCTSflow) { + progdefaults.HamlibRTSCTSflow = value; + progdefaults.changed = true; + } + return error; +#else + return script_no_errors; +#endif // USE_HAMLIB +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hamlib_xon_xoff_flow(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_HAMLIB + bool value = 0; + int error = assign_bool(chkHamlibXONXOFFflow, sp, sc, value); + + if(!error && chkHamlibXONXOFFflow) { + progdefaults.HamlibXONXOFFflow = value; + progdefaults.changed = true; + } + return error; +#else + return script_no_errors; +#endif // USE_HAMLIB +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hamlib_advanced_config(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_HAMLIB + std::string value = ""; + int error = assign_string(inpHamlibConfig, sp, sc, value); + + if(!error && inpHamlibConfig) { + progdefaults.HamConfig.assign(value); + progdefaults.changed = true; + } + return error; +#else + return script_no_errors; +#endif // USE_HAMLIB +} + +/** ******************************************************** + * \brief Initialize HAMLIB Parameters + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_hamlib_initialize(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ +#if USE_HAMLIB + + if(!btnInitHAMLIB) + return script_no_errors; + + btnInitHAMLIB->do_callback(); + +#endif // USE_HAMLIB + + return script_no_errors; +} + +/** ******************************************************** + * \brief Set XMLRPC rig control to active use. + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_use_xml_rpc(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + bool value = 0; + int error = assign_bool(chkUSEXMLRPC, sp, sc, value); + + if(!error && chkUSEXMLRPC) { + progdefaults.chkUSEXMLRPCis = value; + progdefaults.changed = true; + } + + return error; +} + +/** ******************************************************** + * \brief + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_xml_rpc_mode_bw_delay(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + double value = 0; + int error = assign_double(mbw_delay, sp, sc, value); + + if(!error && mbw_delay) { + progdefaults.mbw = value; + progdefaults.changed = true; + } + + return error; +} + +/** ******************************************************** + * \brief Initialize Rig Control XMLRPC interface. + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_xml_rpc_initialize(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + + if(!btnInitXMLRPC) + return script_no_errors; + + btnInitXMLRPC->do_callback(); + + return script_no_errors; +} + +/** ******************************************************** + * \brief Assign Macro information to there respective + * macro button. + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_load_macro(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + // Not suitable for assign_xxxx + if(!sp || !sc) + return script_function_parameter_error; + + std::string macro_data = sp->macro_command(); + std::string macro_label = ""; + + int col = 0; + int row = 0; + int index = 0; + + if(sc->argc < 3) return script_invalid_parameter; + + if((!sc->args[0]) || (!sc->args[1]) || (!sc->args[2])) + return script_invalid_parameter; + + index = sscanf(sc->args[0], "%d", &col); + if(index < 1) + return script_invalid_parameter; + + index = sscanf(sc->args[1], "%d", &row); + if(index < 1) + return script_invalid_parameter; + + macro_label.assign(sc->args[2]); + if(macro_label.empty()) + return script_invalid_parameter; + + if(col > 0) col--; + if(row > 0) row--; + + index = (col * NUMMACKEYS) + row; + + if((index < 0) || (index > MAXMACROS)) + return script_invalid_parameter; + + if((col == 0) || ((col == altMacros) && (progdefaults.mbar_scheme > MACRO_SINGLE_BAR_MAX))) { + update_macro_button(index, macro_data.c_str(), macro_label.c_str()); + } else { + macros.text[index].assign(macro_data); + macros.name[index].assign(macro_label); + } + + return script_no_errors; +} + +/** ******************************************************** + * \brief Reset Configuration panel attributes + * \param sp Access to ScritpParsing members. + * \param sc Access to SCRIPT_COMMANDS structure variables. + * \return 0 (no error) Other (error) + ***********************************************************/ +int process_reset(ScriptParsing *sp, SCRIPT_COMMANDS *sc) +{ + return script_no_errors; +} + +/** ******************************************************** + * \brief Pass script file name to script passing class + * for execution. + * Called from the File->Execute Config Script menu item. + * \param void + ***********************************************************/ +static void script_execute(const char *filename, bool queue_flag) +{ + + ScriptParsing *sp = 0; + static std::string script_filename = ""; + + if(!filename) { + LOG_INFO(_("Script file name (path) null pointer")); + return; + } + + script_filename.assign(filename); + + if(script_filename.empty()) { + LOG_INFO(_("Script file name (path) invalid")); + return; + } + + sp = new ScriptParsing; + + if(!sp) { + LOG_INFO(_("Script Parsing Class Allocation Fail (%s)"), script_filename.c_str()); + return; + } + + LOG_INFO(_("Executing script file: %s"), script_filename.c_str()); + + sp->parse_commands((char *) script_filename.c_str()); + + if(sp->script_errors()) { + LOG_INFO(_("Issues reported in processing script file: %s"), script_filename.c_str()); + fl_alert("%s", _("Script file contains potential issues\nSee documentation and/or Log file for details.")); + } + + if(sp->restart_flag()) { + fl_alert("%s", _("Some changes made by the script requires program\nrestart before they become active.")); + } + + if(sp) + delete sp; +} + +/** ******************************************************** + * \brief Call back function when executing a configuration script. + * Called from the File->Execute Config Script menu item. + * \param void + ***********************************************************/ +void cb_scripts(bool reset_path = false) +{ + pthread_mutex_lock(&mutex_script_io); + + static bool first_time = true; + static char script_filename[FL_PATH_MAX + 1]; + std::string new_path = ""; + + if(reset_path || first_time) { + memset(script_filename, 0, sizeof(script_filename)); + strncpy(script_filename, ScriptsDir.c_str(), FL_PATH_MAX); + int len = strnlen(script_filename, FL_PATH_MAX); + + if(len > 0) { + len--; + if(script_filename[len] == PATH_CHAR_SEPERATOR); + else strncat(script_filename, PATH_SEPERATOR, FL_PATH_MAX); + } else { + return; + } + + first_time = false; + } + + const char *p = FSEL::select((char *)_("Script Files"), (char *)_("*.txt"), \ + script_filename); + + if(p) { + memset(script_filename, 0, sizeof(script_filename)); + strncpy(script_filename, p, FL_PATH_MAX); + + Fl::lock(); + script_execute(script_filename, false); + Fl::unlock(); + + } + + pthread_mutex_unlock(&mutex_script_io); +} diff --git a/src/config_script/script_parsing.cxx b/src/config_script/script_parsing.cxx new file mode 100644 index 00000000..47ded20c --- /dev/null +++ b/src/config_script/script_parsing.cxx @@ -0,0 +1,2194 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2015 +// Robert Stiles +// +// 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 this program. If not, see . +// ---------------------------------------------------------------------------- + +#include +#include "config.h" +#include "util.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "gettext.h" +#include "script_parsing.h" +#include "run_script.h" + +// Do not use directly. It's copied for each instance + +static const SCRIPT_COMMANDS default_operator_command_table[] = { + { CMD_CALLSIGN, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_callsign_info, 0, 0}, + { CMD_NAME, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_name_info, 0, 0}, + { CMD_QTH, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_qth_info, 0, 0}, + { CMD_LOCATOR, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_locator_info, 0, 0}, + { CMD_ANTENNA, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_antenna_info, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + +static const SCRIPT_COMMANDS default_audio_device_command_table[] = { + { CMD_OSS_AUDIO, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_use_oss_audio_device, 0, 0}, + { CMD_OSS_AUDIO_DEV_PATH, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_oss_audio_device_path, 0, 0}, + { CMD_PORT_AUDIO, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_use_port_audio_device, 0, 0}, + { CMD_PORTA_CAP, SCRIPT_COMMAND, 0, 2, {0}, { p_int, p_dev_name }, 0, 0, 0, process_capture_path, 0, 0}, + { CMD_PORTA_PLAY, SCRIPT_COMMAND, 0, 2, {0}, { p_int, p_dev_name }, 0, 0, 0, process_playback_path, 0, 0}, + { CMD_PULSEA, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_use_pulse_audio_device, 0, 0}, + { CMD_PULSEA_SERVER, SCRIPT_COMMAND, 0, 1, {0}, { p_dev_path }, 0, 0, 0, process_pulse_audio_device_path, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + +static const SCRIPT_COMMANDS default_audio_settings_command_table[] = { + { CMD_CAPTURE_SAMPLE_RATE, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_audio_device_sample_rate_capture, 0, 0}, + { CMD_PLAYBACK_SAMPLE_RATE, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_audio_device_sample_rate_playback, 0, 0}, + { CMD_AUDIO_CONVERTER, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_audio_device_converter, 0, 0}, + { CMD_RX_PPM, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_rx_ppm, 0, 0}, + { CMD_TX_PPM, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_tx_ppm, 0, 0}, + { CMD_TX_OFFSET, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_tx_offset, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + +static const SCRIPT_COMMANDS default_audio_rt_channel_command_table[] = { + { CMD_MONO_AUDIO, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_mono_audio_output, 0, 0}, + { CMD_AUDIO_L_R, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_modem_signal_left_right, 0, 0}, + { CMD_AUDIO_REV_L_R, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_reverse_left_right, 0, 0}, + { CMD_PTT_RIGHT_CHAN, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_ptt_tone_right_channel, 0, 0}, + { CMD_CW_QSK_RT_CHAN, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_cw_qsk_right_channel, 0, 0}, + { CMD_PSEUDO_FSK_RT_CHAN, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_pseudo_fsk_right_channel, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + +static const SCRIPT_COMMANDS default_audio_wave_command_table[] = { + { CMD_WAVE_SR, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_wave_file_sample_rate, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + +static const SCRIPT_COMMANDS default_rig_hrdwr_ptt_command_table[] = { + { CMD_HPPT_PTT_RT, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hrdw_ptt_right_audio_channel, 0, 0}, + { CMD_HPTT_SP2, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hrdw_ptt_sep_serial_port, 0, 0}, + { CMD_HPTT_SP2_PATH, SCRIPT_COMMAND, 0, 1, {0}, { p_dev_path }, 0, 0, 0, process_hrdw_ptt_sep_serial_port_path, 0, 0}, + { CMD_HPTT_SP2_RTS, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hrdw_ptt_sep_serial_port_rts, 0, 0}, + { CMD_HPTT_SP2_DTR, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hrdw_ptt_sep_serial_port_dtr, 0, 0}, + { CMD_HPTT_SP2_RTS_V, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hrdw_ptt_sep_serial_port_rts_v, 0, 0}, + { CMD_HPTT_SP2_DTR_V, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hrdw_ptt_sep_serial_port_dtr_v, 0, 0}, + { CMD_HPTT_SP2_START_DELAY, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_hrdw_ptt_start_delay, 0, 0}, + { CMD_HPTT_SP2_END_DELAY, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_hrdw_ptt_end_delay, 0, 0}, + { CMD_HPTT_UHROUTER, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hrdw_ptt_uhrouter, 0, 0}, + { CMD_HPTT_SP2_INITIALIZE, SCRIPT_COMMAND, 0, 0, {0}, { p_void }, 0, 0, 0, process_hrdw_ptt_initialize, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + +static const SCRIPT_COMMANDS default_rigcat_command_table[] = { + { CMD_RIGCAT_STATE, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_use_rigcat, 0, 0}, + { CMD_RIGCAT_DESC_FILE, SCRIPT_COMMAND, 0, 1, {0}, { p_filename }, 0, 0, 0, process_rigcat_desc_file, 0, 0}, + { CMD_RIGCAT_DEV_PATH, SCRIPT_COMMAND, 0, 1, {0}, { p_dev_path }, 0, 0, 0, process_rigcat_device_path, 0, 0}, + { CMD_RIGCAT_RETRIES, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_rigcat_retries, 0, 0}, + { CMD_RIGCAT_RETRY_INTERVAL, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_rigcat_retry_interval, 0, 0}, + { CMD_RIGCAT_WRITE_DELAY, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_rigcat_write_delay, 0, 0}, + { CMD_RIGCAT_INTIAL_DELAY, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_rigcat_init_delay, 0, 0}, + { CMD_RIGCAT_BAUD_RATE, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_rigcat_baud_rate, 0, 0}, + { CMD_RIGCAT_STOP_BITS, SCRIPT_COMMAND, 0, 1, {0}, { p_float }, 0, 0, 0, process_rigcat_stop_bits, 0, 0}, + { CMD_RIGCAT_ECHO, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rigcat_commands_echoed, 0, 0}, + { CMD_RIGCAT_TOGGLE_RTS_PTT, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rigcat_toggle_rts_ptt, 0, 0}, + { CMD_RIGCAT_RESTORE, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rigcat_restore_on_close, 0, 0}, + { CMD_RIGCAT_PTT_COMMAND, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rigcat_cat_command_ptt, 0, 0}, + { CMD_RIGCAT_RTS_12V, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rigcat_rts_12v, 0, 0}, + { CMD_RIGCAT_DTR_12V, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rigcat_dtr_12v, 0, 0}, + { CMD_RIGCAT_HRDWR_FLOW, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rigcat_hrdwr_flow, 0, 0}, + { CMD_RIGCAT_VSP, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rigcat_vsp_enable, 0, 0}, + { CMD_RIGCAT_INITIALIZE, SCRIPT_COMMAND, 0, 0, {0}, { p_void }, 0, 0, 0, process_rigcat_initialize, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + +static const SCRIPT_COMMANDS default_hamlib_command_table[] = { + { CMD_HAMLIB_STATE, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_use_hamlib, 0, 0}, + { CMD_HAMLIB_RIG, SCRIPT_COMMAND, 0, 1, {0}, { p_dev_name }, 0, 0, 0, process_hamlib_rig, 0, 0}, + { CMD_HAMLIB_DEV_PATH, SCRIPT_COMMAND, 0, 1, {0}, { p_dev_path }, 0, 0, 0, process_hamlib_device_path, 0, 0}, + { CMD_HAMLIB_RETRIES, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_hamlib_retries, 0, 0}, + { CMD_HAMLIB_RETRY_INTERVAL, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_hamlib_retry_interval, 0, 0}, + { CMD_HAMLIB_WRITE_DELAY, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_hamlib_write_delay, 0, 0}, + { CMD_HAMLIB_POST_WRITE_DELAY, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_hamlib_post_write_delay, 0, 0}, + { CMD_HAMLIB_BAUD_RATE, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_hamlib_baud_rate, 0, 0}, + { CMD_HAMLIB_STOP_BITS, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_hamlib_stop_bits, 0, 0}, + { CMD_HAMLIB_SIDE_BAND, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_hamlib_sideband, 0, 0}, + { CMD_HAMLIB_PTT_COMMAND, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hamlib_ptt_hl_command, 0, 0}, + { CMD_HAMLIB_DTR_12V, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hamlib_dtr_12, 0, 0}, + { CMD_HAMLIB_RTS_12V, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hamlib_rts_12, 0, 0}, + { CMD_HAMLIB_HRDWR_FLOW, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hamlib_rts_cts_flow, 0, 0}, + { CMD_HAMLIB_SFTWR_FLOW, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hamlib_xon_xoff_flow, 0, 0}, + { CMD_HAMLIB_ADV_CONFIG, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_hamlib_advanced_config, 0, 0}, + { CMD_HAMLIB_INITIALIZE, SCRIPT_COMMAND, 0, 0, {0}, { p_void }, 0, 0, 0, process_hamlib_initialize, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + +static const SCRIPT_COMMANDS default_rc_xmlrpc_command_table[] = { + { CMD_RC_XMLRPC_STATE, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_use_xml_rpc, 0, 0}, + { CMD_RC_XMLRPC_BW_DELAY, SCRIPT_COMMAND, 0, 1, {0}, { p_float }, 0, 0, 0, process_xml_rpc_mode_bw_delay, 0, 0}, + { CMD_RC_XMLRPC_INITIALIZE, SCRIPT_COMMAND, 0, 0, {0}, { p_void }, 0, 0, 0, process_xml_rpc_initialize, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + + +static const SCRIPT_COMMANDS default_kiss_command_table[] = { + { CMD_IO_KISS_IPA, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_io_kiss_ip_address, 0, 0}, + { CMD_IO_KISS_IOPN, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_io_kiss_io_port_no, 0, 0}, + { CMD_IO_KISS_OPN, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_io_kiss_o_port_no, 0, 0}, + { CMD_IO_KISS_DP, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_io_kiss_dual_port, 0, 0}, + { CMD_IO_KISS_BUSY, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_io_kiss_busy_channel, 0, 0}, + { CMD_IO_KISS_CONT, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_io_kiss_continue_after, 0, 0}, + { CMD_IO_KISS_ATTEN, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_io_kiss_kpsql_atten, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + +static const SCRIPT_COMMANDS default_arq_command_table[] = { + { CMD_IO_ARQ_IPA, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_io_arq_ip_address, 0, 0}, + { CMD_IO_ARQ_IOPN, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_io_arq_io_port_no, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + +static const SCRIPT_COMMANDS default_xmlrpc_command_table[] = { + { CMD_IO_XMLRPC_IPA, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_io_xmlrpc_ip_address, 0, 0}, + { CMD_IO_XMLRPC_IOPN, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_io_xmlrpc_io_port_no, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + +static const SCRIPT_COMMANDS default_io_command_table[] = { + { CMD_IO_LOCK, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_io_lock, 0, 0}, + { CMD_IO_ACT_PORT, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_io_active_port, 0, 0}, + { CMD_IO_AX25_DECODE, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_io_ax25_decode, 0, 0}, + { CMD_IO_CSMA, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_io_csma, 0, 0}, + { CMD_IO_KISS, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_kiss_command_table, sizeof(default_kiss_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_IO_ARQ, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_arq_command_table, sizeof(default_arq_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_IO_XMLRPC, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_xmlrpc_command_table, sizeof(default_xmlrpc_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + +static const SCRIPT_COMMANDS default_fldigi_command_table[] = { + { CMD_FLDIGI_FREQ, SCRIPT_COMMAND, 0, 1, {0}, { p_double }, 0, 0, 0, process_rig_freq, 0, 0}, + { CMD_FLDIGI_MODE, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_rig_mode, 0, 0}, + { CMD_FLDIGI_WFHZ, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_wf_hz_offset, 0, 0}, + { CMD_FLDIGI_RXID, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rx_rsid, 0, 0}, + { CMD_FLDIGI_TXID, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_tx_rsid, 0, 0}, + { CMD_FLDIGI_SPOT, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_spot, 0, 0}, + { CMD_FLDIGI_REV, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rev, 0, 0}, + { CMD_FLDIGI_AFC, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_afc, 0, 0}, + { CMD_FLDIGI_LOCK, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_lock, 0, 0}, + { CMD_FLDIGI_SQL, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_sql, 0, 0}, + { CMD_FLDIGI_KPSQL, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_kpsql, 0, 0}, + { CMD_FLDIGI_MODEM, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_modem, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + + +static const SCRIPT_COMMANDS default_nbems_command_table[] = { + { CMD_NBEMS_FLMSG_PATH, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_misc_nbems_flmsg_path, 0, 0}, + { CMD_NBEMS_TIMEOUT, SCRIPT_COMMAND, 0, 1, {0}, { p_double }, 0, 0, 0, process_misc_nbems_timeout, 0, 0}, + { CMD_NBEMS_STATE, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_misc_nbems_state, 0, 0}, + { CMD_NBEMS_MSG, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_misc_nbems_open_msg, 0, 0}, + { CMD_NBEMS_FLMSG, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_misc_nbems_open_flmsg, 0, 0}, + { CMD_NBEMS_BRWSR, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_misc_nbems_open_brwsr, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + +static const SCRIPT_COMMANDS default_id_rsid_command_table[] = { + { CMD_ID_RSID_NOTIFY, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rsid_notify, 0, 0}, + { CMD_ID_RSID_SRCH_BP, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rsid_search_bp, 0, 0}, + { CMD_ID_RSID_MARK_PREV, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rsid_mark_prev, 0, 0}, + { CMD_ID_RSID_DETECTOR, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rsid_detector, 0, 0}, + { CMD_ID_RSID_ALRT_DIALOG, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rsid_alert_dialog, 0, 0}, + { CMD_ID_RSID_TX_FREQ_LOCK, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rsid_tx_freq_lock, 0, 0}, + { CMD_ID_RSID_FREQ_CHANGE, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rsid_freq_change, 0, 0}, + { CMD_ID_RSID_ALLOW_ERRORS, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_rsid_allow_errors, 0, 0}, + { CMD_ID_RSID_SQL_OPEN, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_rsid_sql_open, 0, 0}, + { CMD_ID_RSID_PRETONE, SCRIPT_COMMAND, 0, 1, {0}, { p_double }, 0, 0, 0, process_rsid_pretone, 0, 0}, + { CMD_ID_RSID_END_XMT_ID, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rsid_end_xmt_id, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + +static const SCRIPT_COMMANDS default_id_video_command_table[] = { + { CMD_ID_VIDEO_TX_ID_MODE, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_video_tx_id_mode, 0, 0}, + { CMD_ID_VIDEO_TX_VIDEO_TXT, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_video_tx_vid_txt, 0, 0}, + { CMD_ID_VIDEO_TX_TXT_INP, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_video_txt_input, 0, 0}, + { CMD_ID_VIDEO_SMALL_FONT, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_video_small_font, 0, 0}, + { CMD_ID_VIDEO_500_HZ, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_video_500hz, 0, 0}, + { CMD_ID_VIDEO_WIDTH_LIMIT, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_video_width_limit, 0, 0}, + { CMD_ID_VIDEO_CHAR_ROW, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_rsid_char_per_row, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + +static const SCRIPT_COMMANDS default_id_cw_command_table[] = { + { CMD_ID_CW_TX_CALLSIGN, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_cw_callsign, 0, 0}, + { CMD_ID_CW_SPEED, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_cw_speed, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + +static const SCRIPT_COMMANDS default_id_command_table[] = { + { CMD_ID_RSID, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_id_rsid_command_table, sizeof(default_id_rsid_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_ID_VIDEO, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_id_video_command_table, sizeof(default_id_video_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_ID_CW, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_id_cw_command_table, sizeof(default_id_cw_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + +static const SCRIPT_COMMANDS default_top_level_command_table[] = { + { CMD_FLDIGI, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_fldigi_command_table, sizeof(default_fldigi_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_OPERATOR, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_operator_command_table, sizeof(default_operator_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_AUDIO_DEVICE, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_audio_device_command_table, sizeof(default_audio_device_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_AUDIO_SETTINGS, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_audio_settings_command_table, sizeof(default_audio_settings_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_AUDIO_RT_CHANNEL, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_audio_rt_channel_command_table, sizeof(default_audio_rt_channel_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_AUDIO_WAVE, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_audio_wave_command_table, sizeof(default_audio_wave_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_HRDWR_PTT, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_rig_hrdwr_ptt_command_table, sizeof(default_rig_hrdwr_ptt_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_RIGCAT, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_rigcat_command_table, sizeof(default_rigcat_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_HAMLIB, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_hamlib_command_table, sizeof(default_hamlib_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_RC_XMLRPC, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_rc_xmlrpc_command_table, sizeof(default_rc_xmlrpc_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_IO, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_io_command_table, sizeof(default_io_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_NBEMS, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_nbems_command_table, sizeof(default_nbems_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_ID, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_id_command_table, sizeof(default_id_command_table)/sizeof(SCRIPT_COMMANDS)}, + { CMD_LOAD_MACRO, SCRIPT_COMMAND | SCRIPT_STRUCTURED_ONLY, 0, 3, {0}, { p_int, p_int, p_string }, 0, 0, 0, process_load_macro, 0, 0}, + { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, + { {0} } +}; + + +/** ************************************************************** + * \brief Macro command requires special procesing. + * \param cmd Pointer to matching struct script_cmds script + * command. + * \return SCRIPT_CODES error see \ref script_codes + *****************************************************************/ +SCRIPT_CODES ScriptParsing::sc_macros(struct script_cmds *cmd) +{ + bool not_done = false; + std::string temp; + SCRIPT_CODES error = script_no_errors; + int line_number_start = line_number; + char *local_buffer = (char *)0; + + _macro_command.clear(); + temp.clear(); + + std::string search_cmd; + search_cmd.assign(CMD_END_CMD).append(":"); + + local_buffer = new char[MAX_READLINE_LENGTH]; + + if(!local_buffer) + return script_memory_allocation_error; + + while(!not_done) { + + if(ferror(fd)) { + error = script_file_read_error; + break; + } + + if(feof(fd)) { + error = script_unexpected_eof; + break; + } + + memset(local_buffer, 0, MAX_READLINE_LENGTH); + if (fgets(local_buffer, MAX_READLINE_LENGTH, fd)) + line_number++; + + temp.assign(local_buffer); + trim(temp); + + + if(temp.find(search_cmd) == std::string::npos) + _macro_command.append(local_buffer); + else + break; + } + + int pos = _macro_command.length() - 1; + bool lf_removed = false; + + // Remove the last new line in the macro command (script syntax requirement) + + if(pos > 1) { // Windows way + if(_macro_command[pos-1] == '\r' && _macro_command[pos] == '\n') { + _macro_command.erase(pos - 1, 2); + lf_removed = true; + } + } + + if((lf_removed == false) && (pos > 0)) { // Unix/Linux/MacOSX way + if(_macro_command[pos] == '\n') + _macro_command.erase(pos, 1); + } + + if(error == script_unexpected_eof) { + LOG_INFO(_("Missing command %s after line %d"), search_cmd.c_str(), line_number_start); + } + + delete [] local_buffer; + + return error; +} + +/** ************************************************************** + * \brief Used for initialization of the function vector table. + * \param cmd Pointer to matching struct script_cmds script + * command. + * \return SCRIPT_CODES error see \ref script_codes + *****************************************************************/ +SCRIPT_CODES ScriptParsing::sc_dummy(struct script_cmds *cmd) +{ + return script_no_errors; +} + +/** ************************************************************** + * \brief Convert error numbers into human readable form. + * \param error_no Error number to convert. + * \param ln The offending line number in the script file. + * \param cmd The script command is question. + * \return SCRIPT_CODES error see \ref script_codes + *****************************************************************/ +char * ScriptParsing::script_error_string(SCRIPT_CODES error_no, int ln, char *cmd) +{ + char *es = (char *) ""; + + memset(error_buffer, 0, sizeof(error_buffer)); + memset(error_cmd_buffer, 0, sizeof(error_cmd_buffer)); + memset(error_string, 0, sizeof(error_string)); + + if(cmd) { + strncpy(error_cmd_buffer, cmd, sizeof(error_cmd_buffer)-1); + } + + if(error_no < 0) { + _script_error_detected = true; + } + + switch(error_no) { + case script_command_not_found: + es = (char *) _("Command Not Found"); + break; + + case script_non_script_file: + es = (char *) _("Not a script file/tag not found"); + break; + + case script_parameter_error: + es = (char *) _("Invalid parameter"); + break; + + case script_function_parameter_error: + es = (char *) _("Invalid function parameter (internal non-script error)"); + break; + + case script_mismatched_quotes: + es = (char *) _("Missing paired quotes (\")"); + break; + + case script_general_error: + es = (char *) _("General Error"); + break; + + case script_no_errors: + es = (char *) _("No Errors"); + break; + + case script_char_match_not_found: + es = (char *) _("Character searched not found"); + break; + + case script_end_of_line_reached: + es = (char *) _("End of line reached"); + break; + + case script_file_not_found: + es = (char *) _("File not found"); + break; + + case script_path_not_found: + es = (char *) _("Directory path not found"); + break; + + case script_args_eol: + es = (char *) _("Unexpected end of parameter (args[]) list found"); + break; + + case script_param_check_eol: + es = (char *) _("Unexpected end of parameter check list found"); + break; + + case script_paramter_exceeds_length: + es = (char *) _("Character count in args[] parameter exceeds expectations"); + break; + + case script_memory_allocation_error: + es = (char *) _("Memory Allocation Error (internal non-script error)"); + break; + + case script_incorrectly_assigned_value: + es = (char *) _("Passed parameter is not of the expected type."); + break; + + case script_invalid_parameter: + es = (char *) _("Parameter is not valid."); + break; + + case script_command_seperator_missing: + es = (char *) _("Command missing ':'."); + break; + + case script_max_sub_script_reached: + es = (char *) _("Maximum open subscripts reached."); + break; + + case script_subscript_exec_fail: + es = (char *) _("Subscript execution fail (internal)."); + break; + + case script_device_path_not_found: + es = (char *) _("Script device path not found."); + break; + + case script_unexpected_eof: + es = (char *) _("Unexpected end of file reached."); + break; + + case script_file_read_error: + es = (char *) _("File read error"); + break; + + default: + es = (char *) _("Undefined error"); + } + + snprintf(error_buffer, sizeof(error_buffer)-1, _("Line: %d Error:%d %s (%s)"), + ln, error_no, es, error_cmd_buffer); + + return error_buffer; +} + +/** ************************************************************** + * \brief Search for first occurrence of a non white space + * \param data Data pointer to search. + * \param limit Number of bytes in the data buffer. + * \param error returned error code. + * \return Pointer to character if found. Otherwise, return null + * \par Note:
    + * The searched condition is ignored if the expected content is + * encapsulated in quotes \(\"\"\). + *****************************************************************/ +char * ScriptParsing::skip_white_spaces(char * data, char * limit, SCRIPT_CODES &error) +{ + char *cPtr = (char *) 0; + + if(!data || !limit) { + error = script_function_parameter_error; + return (char *)0; + } + + for(cPtr = data; cPtr < limit; cPtr++) { + if(*cPtr > ' ') { + error = script_no_errors; + return cPtr; + } + } + + error = script_end_of_line_reached; + + + return (char *)0; // End of line reached. +} + +/** ************************************************************** + * \brief Search for the first occurrence on a non number. + * \param data Data pointer to search. + * \param limit Number of bytes in the data buffer. + * \param error returned error code. + * \return Pointer to character if found. Otherwise, return null + * \par Note:
    + * The searched condition is ignored if the expected content is + * encapsulated in quotes \(\"\"\). + *****************************************************************/ +char * ScriptParsing::skip_numbers(char * data, char * limit, SCRIPT_CODES &error) +{ + char *cPtr = (char *) 0; + int q_flag = 0; + + if(!data || !limit) { + error = script_function_parameter_error; + return (char *)0; + } + + for(cPtr = data; cPtr < limit; cPtr++) { + if(*cPtr == '"') // Check for encapsulated strings ("") + q_flag++; + + if((q_flag & 0x1)) // Continue if string is encapsulated + continue; + + if(!isdigit(*cPtr)) { + error = script_no_errors; + return cPtr; + } + } + + if(q_flag & 0x1) { + error = script_mismatched_quotes; + } else { + error = script_end_of_line_reached; + } + + return (char *)0; // End of line reached. +} + +/** ************************************************************** + * \brief Skip characters until either a number or white space is + * found. + * \param data Data pointer to search. + * \param limit Number of bytes in the data buffer. + * \param error returned error code. + * \return Pointer to character if found. Otherwise, return null + * \par Note:
    + * The searched condition is ignored if the expected content is + * encapsulated in quotes \(\"\"\). + *****************************************************************/ +char * ScriptParsing::skip_characters(char * data, char * limit, SCRIPT_CODES &error) +{ + char *cPtr = (char *) 0; + int q_flag = 0; + + if(!data || !limit) { + error = script_function_parameter_error; + return (char *)0; + } + + for(cPtr = data; cPtr < limit; cPtr++) { + if(*cPtr == '"') // Check for encapsulated strings ("") + q_flag++; + + if((q_flag & 0x1)) // Continue if string is encapsulated + continue; + + if(isdigit(*cPtr) || *cPtr <= ' ') { + error = script_no_errors; + return cPtr; + } + } + + if(q_flag & 0x1) { + error = script_mismatched_quotes; + } else { + error = script_end_of_line_reached; + } + + return (char *)0; // End of line reached. +} + +/** ************************************************************** + * \brief Search for the first occurrence of a white space. + * \param data Data pointer to search. + * \param limit Number of bytes in the data buffer. + * \param error returned error code. + * \return Pointer to character if found. Otherwise, return null + * \par Note:
    + * The searched condition is ignored if the expected content is + * encapsulated in quotes \(\"\"\). + *****************************************************************/ +char * ScriptParsing::skip_alpha_numbers(char * data, char * limit, SCRIPT_CODES &error) +{ + char *cPtr = (char *) 0; + int q_flag = 0; + + if(!data || !limit) { + error = script_function_parameter_error; + return (char *)0; + } + + for(cPtr = data; cPtr < limit; cPtr++) { + + if(*cPtr == '"') // Check for encapsulated strings ("") + q_flag++; + + if((q_flag & 0x1)) // Continue if string is encapsulated + continue; + + if(*cPtr <= ' ') { + error = script_no_errors; + return cPtr; + } + } + + if(q_flag & 0x1) { + error = script_mismatched_quotes; + } else { + error = script_end_of_line_reached; + } + + return (char *)0; // End of line reached. +} + +/** ************************************************************** + * \brief Search for first occurrence of 'character' + * \param c Character to search for + * \param data Pointer to Data to search for character in. + * \param limit Number of bytes in the data buffer. + * \param error returned error code. + * \return Pointer to character if found. Otherwise, return null + * \par Note:
    + * The searched condition is ignored if the expected content is + * encapsulated in quotes \(\"\"\). + *****************************************************************/ +char * ScriptParsing::skip_to_character(char c, char * data, char * limit, SCRIPT_CODES &error) +{ + char *cPtr = (char *) 0; + int q_flag = 0; + + if(!data || !limit) { + error = script_function_parameter_error; + return (char *)0; + } + + for(cPtr = data; cPtr < limit; cPtr++) { + if(*cPtr == '"') // Check for encapsulated strings ("") + q_flag++; + + if((q_flag & 0x1)) // Continue if string is encapsulated + continue; + + if(*cPtr == c) { // Match found. Return pointer to it's location + error = script_no_errors; + return cPtr; + } + } + + if(q_flag & 0x1) { + error = script_mismatched_quotes; + } else { + error = script_end_of_line_reached; + } + + return (char *)0; // End of line reached. +} + +/** ************************************************************** + * \brief Replace CR, LF, and '#' with '0' (by value) + * \param data Search data pointer + * \param limit data buffer size + * \return void (none) + * \par Note:
    + * The searched condition is ignored if the remark character \(#\) + * is encapsulated in quotes \(\"\"\). + *****************************************************************/ +SCRIPT_CODES ScriptParsing::remove_crlf_comments(char *data, char *limit, size_t &count) +{ + char *cPtr = (char *) 0; + int q_flag = 0; + + SCRIPT_CODES error = script_no_errors; + + if(!data || !limit) + return script_function_parameter_error; + + count = 0; + + for(cPtr = data; cPtr < limit; cPtr++) { + if(*cPtr == '\r' || *cPtr == '\n') { + *cPtr = 0; + return script_no_errors; + } + + if(*cPtr == '"') + q_flag++; + + if((q_flag & 0x1)) + continue; + + if(*cPtr == '#') { + *cPtr = 0; + break; + } + + if(*cPtr > ' ') + count++; + + } + + // Remove trailing white spaces. + while(cPtr >= data) { + if(*cPtr <= ' ') *cPtr = 0; + else break; + cPtr--; + } + + if(q_flag & 0x1) { + error = script_mismatched_quotes; + } else { + error = script_end_of_line_reached; + } + + return error; +} + +/** ************************************************************** + * \brief Copy memory from address to address. + * \param buffer Destination buffer + * \param sPtr Start of the copy Address + * \param ePtr End of the copy Address + * \param limit Destination buffer size + * command. + * \return SCRIPT_CODES error see \ref script_codes + *****************************************************************/ +SCRIPT_CODES ScriptParsing::copy_string_uppercase(char *buffer, char *sPtr, char *ePtr, size_t limit) +{ + if(!buffer || !sPtr || !ePtr || limit < 1) { + return script_function_parameter_error; + } + + char *dPtr = buffer; + size_t index = 0; + + for(index = 0; index < limit; index++) { + *dPtr++ = toupper(*sPtr++); + if(sPtr >= ePtr) break; + } + + return script_no_errors; +} + +/** ************************************************************** + * \brief Parse the parameters and seperate into individual components. + * \param s char pointer to the start of the string. + * \param e char pointer to the end of the string. + * \param matching_command pointer to the data strucure of the matching + * command. See \ref SCRIPT_COMMANDS + * \return SCRIPT_CODES error see \ref script_codes + *****************************************************************/ +SCRIPT_CODES ScriptParsing::parse_parameters(char *s, char *e, SCRIPT_COMMANDS *matching_command) +{ + char *c = s; + char *d = (char *)0; + int index = 0; + int parameter_count = matching_command->argc; + int count = 0; + long tmp = 0; + + SCRIPT_CODES error = script_no_errors; + + // Clear the old pointers. + for(index = 0; index < MAX_CMD_PARAMETERS; index++) { + matching_command->args[index] = (char *)0; + } + + if(parameter_count > 0) { + count = parameter_count - 1; + for(index = 0; index < count; index++) { + c = skip_white_spaces(c, e, error); + + if(error != script_no_errors) + return script_parameter_error; + + d = skip_to_character(',', c, e, error); + + if(error != script_no_errors) + return script_parameter_error; + + *d = 0; + tmp = (long) (d - c); + if(tmp > 0) + trim(c, (size_t)(tmp)); + matching_command->args[index] = c; + c = d + 1; + } + + c = skip_white_spaces(c, e, error); + if(error) return error; + + d = skip_alpha_numbers(c, e, error); + if(error) return error; + + *d = 0; + tmp = (long) (d - c); + if(tmp > 0) + trim(c, (size_t)(tmp)); + + matching_command->args[index] = c; + } + +#ifdef TESTING + for(int i = 0; i < parameter_count; i++) + if(matching_command->args[i]) + printf("parameters %d (%s)\n", i, matching_command->args[i]); +#endif + + error = check_parameters(matching_command); + + if(error != script_no_errors) + return error; + + // If assigned then special processing is required. + if(matching_command->func) + error = (this->*matching_command->func)(matching_command); + if(error) return error; + + + return script_no_errors; +} + +/** ************************************************************** + * \brief Execute callback function. + * \param cb_data Pointer for making a copy of the data to prevent + * exterior alteration of source information. + * \return 0 = No error
    \< 0 = Error
    + *****************************************************************/ +int ScriptParsing::call_callback(SCRIPT_COMMANDS *cb_data) +{ + int argc = 0; + int error = 0; + int index = 0; + SCRIPT_COMMANDS *tmp = (SCRIPT_COMMANDS *)0; + size_t count = 0; + + if(!cb_data || !cb_data->cb) return -1; + + argc = cb_data->argc; + + tmp = new SCRIPT_COMMANDS; + + if(!tmp) return -1; + + memset(tmp, 0, sizeof(SCRIPT_COMMANDS)); + + for(index = 0; index < argc; index++) { + if(cb_data->args[index]) { + count = strnlen(cb_data->args[index], MAX_PARAMETER_LENGTH-1); + tmp->args[index] = new char[count+1]; + if(tmp->args[index]) { + memset(tmp->args[index], 0, count+1); + strncpy(tmp->args[index], cb_data->args[index], count); + } else { + error = -1; + break; + } + } else break; + } + + if(error > -1) { + // Fill SCRIPT_COMMANDS (tmp) struct with useful data. + tmp->flags = cb_data->flags; + tmp->command_length = cb_data->command_length; + tmp->argc = cb_data->argc; + strncpy(tmp->command, cb_data->command, MAX_COMMAND_LENGTH); + + // Initialize with do nothing functions + tmp->func = &ScriptParsing::sc_dummy; + tmp->cb = callback_dummy; + + error = (*cb_data->cb)(this, tmp); + } + + if(tmp) { + for(index = 0; index < argc; index++) { + if(tmp->args[index]) { + delete [] tmp->args[index]; + } + } + + delete tmp; + } + + return error; +} + +/** ************************************************************** + * \brief Parse a single line of data from the script file being read. + * \param data Pointer the the script scring in question + * \param buffer_size buffer size of the data pointer. + * command. + * \return SCRIPT_CODES error see \ref script_codes + *****************************************************************/ +SCRIPT_CODES ScriptParsing::parse_hierarchy_command(char *data, size_t buffer_size) +{ + char *buffer = (char *)0; + char *cPtr = (char *)0; + char *endPtr = (char *)0; + char *ePtr = (char *)0; + int allocated_buffer_size = MAX_COMMAND_LENGTH; + + SCRIPT_CODES error = script_no_errors; + SCRIPT_COMMANDS *local_list = _script_commands; + size_t local_limit = _script_command_count; + + cPtr = data; + endPtr = &data[buffer_size]; + + cPtr = skip_white_spaces(cPtr, endPtr, error); + if(error != script_no_errors) return error; + + ePtr = skip_to_character(':', cPtr, endPtr, error); + if(error != script_no_errors) return script_command_seperator_missing; + + buffer = new char [allocated_buffer_size]; + if(!buffer) { + LOG_INFO(_("Buffer allocation Error near File: %s Line %d"), __FILE__, __LINE__); + return script_memory_allocation_error; + } + + memset(buffer, 0, allocated_buffer_size); + error = copy_string_uppercase(buffer, cPtr, ePtr, allocated_buffer_size-1); + + if(error != script_no_errors) { + buffer[0] = 0; + delete [] buffer; + return error; + } + + int str_count = str_cnt(buffer, allocated_buffer_size); + trim(buffer, (size_t) str_count); + + char sub_command[MAX_COMMAND_LENGTH]; + + bool not_found = true; + char *endCmd = ePtr; + char *endCmdPtr = endPtr; + + cPtr = buffer; + endPtr = &buffer[str_count]; + + while(not_found) { + memset(sub_command, 0, sizeof(sub_command)); + + ePtr = skip_to_character('.', cPtr, endPtr, error); + + if(error == script_end_of_line_reached) { + ePtr = endPtr; + error = script_no_errors; + } + + if(error == script_no_errors) { + copy_string_uppercase(sub_command, cPtr, ePtr, MAX_COMMAND_LENGTH-1); + cPtr = ePtr + 1; + } + else + break; + + for(size_t i = 0; i < local_limit; i++) { + + if(local_list[i].command[0] == 0) { + not_found = false; + error = script_command_not_found; + break; + } + + if(strncmp(sub_command, local_list[i].command, MAX_COMMAND_LENGTH) == 0) { + + if((local_list[i].param_check[0] == p_list) && local_list[i].sub_commands) { + local_limit = local_list[i].sub_command_count; + local_list = local_list[i].sub_commands; + break; + } + + if((file_type() & local_list[i].flags) && !(SCRIPT_STRUCTURED_ONLY & local_list[i].flags)) { + error = parse_parameters(++endCmd, endCmdPtr, &local_list[i]); + + if(error) { + buffer[0] = 0; + delete [] buffer; + return error; + } + + if(local_list[i].cb) { + error = (SCRIPT_CODES) call_callback(&local_list[i]); + if(error < script_no_errors) + LOG_INFO(_("Call back for script command %s reported an Error"), local_list[local_limit].command); + not_found = false; + error = script_command_handled; + break; + } + } else { + LOG_INFO(_("Command %s ignored, dot notation not supported"), buffer); + not_found = false; + error = script_general_error; + break; + } + } + } + } + + buffer[0] = 0; + delete [] buffer; + + return error; +} + +/** ************************************************************** + * \brief Parse a single line of data from the script file being read. + * \param data Pointer the the script scring in question + * \param buffer_size buffer size of the data pointer. + * command. + * \return SCRIPT_CODES error see \ref script_codes + *****************************************************************/ +SCRIPT_CODES ScriptParsing::parse_single_command(FILE *fd, SCRIPT_COMMANDS *cur_list, size_t limit, char *data, size_t buffer_size) +{ + char *buffer = (char *)0; + char *cPtr = (char *)0; + char *endPtr = (char *)0; + char *ePtr = (char *)0; + int allocated_buffer_size = MAX_COMMAND_LENGTH; + + size_t cmd_size = 0; + size_t cmp_results = 0; + size_t index = 0; + size_t size = 0; + bool dot_notation = false; + + SCRIPT_CODES error = script_no_errors; + SCRIPT_COMMANDS *local_list = cur_list; + size_t local_limit = limit; + + cPtr = data; + endPtr = &data[buffer_size]; + + cPtr = skip_white_spaces(cPtr, endPtr, error); + if(error != script_no_errors) return error; + + ePtr = skip_to_character(':', cPtr, endPtr, error); + if(error != script_no_errors) return script_command_seperator_missing; + + buffer = new char [allocated_buffer_size]; + if(!buffer) { + LOG_INFO(_("Buffer allocation Error near File: %s Line %d"), __FILE__, __LINE__); + return script_memory_allocation_error; + } + + memset(buffer, 0, allocated_buffer_size); + error = copy_string_uppercase(buffer, cPtr, ePtr, allocated_buffer_size-1); + if(error != script_no_errors) { + buffer[0] = 0; + delete [] buffer; + return error; + } + + int str_count = str_cnt(buffer, allocated_buffer_size); + trim(buffer, (size_t) str_count); + + + for(int i = 0; i < str_count; i++) { + if(buffer[i] == '.') { + error = parse_hierarchy_command(data, buffer_size); + if(error == script_no_errors) + dot_notation = true; + break; + } + } + + if(dot_notation == false && error == script_no_errors) { + for(index = 0; index < local_limit; index++) { + size = strnlen(local_list[index].command, MAX_COMMAND_LENGTH); + cmd_size = strnlen(buffer, MAX_COMMAND_LENGTH); + cmp_results = memcmp(buffer, local_list[index].command, size); + + if(cmp_results == 0 && (cmd_size == size)) { + + if(local_list[index].param_check[0] == p_list_end) { + return script_end_of_list_reached; + } + + if(local_list[index].sub_commands && local_list[index].param_check[0] == p_list) { + if(recursive_count <= RECURSIVE_LIMIT) { + read_file(fd, local_list[index].sub_commands, local_list[index].sub_command_count); + } else { + error = script_recursive_limit_reached; + } + break; + } + + if((file_type() & local_list[index].flags) && !(SCRIPT_DOT_NOTATION_ONLY & local_list[index].flags)) { + if(local_list[index].argc > 0) { + error = parse_parameters(++ePtr, endPtr, &local_list[index]); + if(error) { + buffer[0] = 0; + delete [] buffer; + return error; + } + } + + if(local_list[index].cb) { + error = (SCRIPT_CODES) call_callback(&local_list[index]); + if(error < script_no_errors) + LOG_INFO(_("Call back for script command %s reported an Error"), local_list[index].command); + } + + } else { + LOG_INFO(_("Command %s ignored, structured command not supported"), buffer); + error = script_general_error; + } + break; + } + } + } + buffer[0] = 0; + delete [] buffer; + + return error; +} + +/** ************************************************************** + * \brief Script entry point for parsing the script file. + * \param file_name_path path and file name for the script to parse. + * \return SCRIPT_CODES error see \ref script_codes + *****************************************************************/ +SCRIPT_CODES ScriptParsing::read_file(FILE *fd, SCRIPT_COMMANDS *cur_list, size_t limit) +{ + SCRIPT_CODES return_code = script_no_errors; + SCRIPT_COMMANDS *local_list = cur_list; + + size_t count = 0; + bool errors_reported = false; + + recursive_count++; + + if(recursive_count > RECURSIVE_LIMIT) + return script_recursive_limit_reached; + + while(1) { + if(ferror(fd) || feof(fd)) break; + + memset(line_buffer, 0, sizeof(line_buffer)); + if (fgets(line_buffer, sizeof(line_buffer) - 1, fd)) + line_number++; + +#ifdef TESTING + printf("Reading: %s", line_buffer); +#endif + + return_code = remove_crlf_comments(line_buffer, &line_buffer[sizeof(line_buffer)], count); + + if(count < 1) { + continue; + } + + if(return_code >= script_no_errors) { + return_code = parse_single_command(fd, local_list, limit, line_buffer, sizeof(line_buffer) - 1); + } + + if(return_code == script_end_of_list_reached) + break; + + if(return_code < script_no_errors) { + LOG_INFO("%s", script_error_string(return_code, line_number, line_buffer)); + errors_reported = true; + } + } + + recursive_count--; + + if(errors_reported) + return script_errors_reported; + + return script_no_errors; +} + +/** ************************************************************** + * \brief Script entry point for parsing the script file. + * \param file_name_path path and file name for the script to parse. + * \return SCRIPT_CODES error see \ref script_codes + *****************************************************************/ +SCRIPT_CODES ScriptParsing::parse_commands(char *file_name_path) +{ + char *cPtr = (char *)0; + SCRIPT_CODES error_code = script_no_errors; + size_t tmp = 0; + SCRIPT_COMMANDS *local_script_commands = _script_commands; + size_t local_script_command_count = _script_command_count; + + if(!file_name_path) { + LOG_INFO(_("Invalid function parameter 'char *file_name_path' (null)")); + return script_function_parameter_error; + } + + fd = fopen(file_name_path, "r"); + line_number = 0; + + if(!fd) { + LOG_INFO(_("Unable to open file %s"), file_name_path); + return script_file_not_found; + } + + memset(line_buffer, 0, sizeof(line_buffer)); + + char *retval = fgets(line_buffer, sizeof(line_buffer) - 1, fd); + line_number++; + + tmp = strlen(SCRIPT_FILE_TAG); + line_buffer[tmp] = 0; + tmp = strncmp(SCRIPT_FILE_TAG, line_buffer, tmp); + + if(!retval || tmp) { + cPtr = script_error_string(script_non_script_file, line_number, line_buffer); + LOG_INFO("%s", cPtr); + fclose(fd); + return script_non_script_file; + } + + error_code = read_file(fd, local_script_commands, local_script_command_count); + + fclose(fd); + + return error_code; +} +/** ************************************************************** + * \brief Assign a list of valid parameters for verification checks. + * \param array An Array of pointers to each element. + * \param array_count Number of entries in the array. + * \return the array count or '0' if error. + * \par Note: + * This array is limited to the first parameter of the command + * used in it's comparison. + *****************************************************************/ +int ScriptParsing::assign_valid_parameters(const char *command, const char **array, const int array_count) +{ + if(!array || array_count < 1 || !command) return 0; + + int index = 0; + int count = 0; + + SCRIPT_COMMANDS * cmd_sc = search_command(_script_commands, 0, command); + + if(!cmd_sc) { + return 0; + } + + for(index = 0; index < array_count; index++) { + if(*array[index]) count++; + } + + if(count != array_count) return 0; + + cmd_sc->valid_values = array; + cmd_sc->valid_value_count = array_count; + + return array_count; +} + +/** ************************************************************** + * \brief Return true state if string is matched. + * \param state Referenced value to assign results to. + * \param string Pointer to the data string. + * \param true_state Pointer to the data to match with. + * \return SCRIPT_CODES error code. + *****************************************************************/ +inline SCRIPT_CODES ScriptParsing::test_on_off_state(bool &state, char *string, char *true_state=(char *)"ON") +{ + if(!string || !true_state) { + return script_function_parameter_error; + } + + bool flag = false; + + if(strncmp(string, true_state, MAX_PARAMETER_LENGTH) == 0) + flag = true; + + state = flag; + + return script_no_errors; +} + +/** ************************************************************** + * \brief Validate if file is located in the specified location. + * \param filename Pointer to a series of charcters + * \return SCRIPT_CODES error code. + *****************************************************************/ +SCRIPT_CODES ScriptParsing::check_filename(char *filename) +{ + SCRIPT_CODES error = script_no_errors; + + if(!filename) { + return script_function_parameter_error; + } + + FILE *fd = (FILE *)0; + + fd = fopen(filename, "r"); + + if(!fd) { + error = script_file_not_found; + } else { + fclose(fd); + } + + return error; +} + +/** ************************************************************** + * \brief Validate if path is present. + * \param path The path to verify. + * \return SCRIPT_CODES error code. + *****************************************************************/ +SCRIPT_CODES ScriptParsing::check_path(const char *path) +{ + if(!path) { + return script_function_parameter_error; + } + + struct stat st; + memset(&st, 0, sizeof(struct stat)); + + if(stat(path, &st) == 0) { + if(st.st_mode & S_IFDIR) + return script_no_errors; + } + + return script_path_not_found; +} + +/** ************************************************************** + * \brief Validate if device path is present. + * \param path The path to verify. + * \return SCRIPT_CODES error code. + *****************************************************************/ +SCRIPT_CODES ScriptParsing::check_dev_path(const char *path) +{ + if(!path) { + return script_function_parameter_error; + } + + struct stat st; + memset(&st, 0, sizeof(struct stat)); + +#ifdef __WIN32__ + std::string alt_path; + int value = 0; + int cnt = 0; + + alt_path.assign(path); + + if(!alt_path.empty()) { + if(alt_path.find("COM") != std::string::npos) { + cnt = sscanf(alt_path.c_str(), "COM%d", &value); + if(cnt && (value > 0)) + return script_no_errors; + } + } +#endif + + if(stat(path, &st) == 0) { + if(st.st_mode & S_IFCHR) + return script_no_errors; + } + + return script_device_path_not_found; +} + +/** ************************************************************** + * \brief Validate bool representation. + * \param value String data or + * \param flag Depending on string content a value of true or false assigned + * \return SCRIPT_CODES error code. + *****************************************************************/ +SCRIPT_CODES ScriptParsing::check_bool(const char *value, bool &flag) +{ + if(!value) { + return script_function_parameter_error; + } + + flag = false; + std::string uc_value; + + uc_value.assign(value); + to_uppercase(uc_value); + + static char *bool_true_flags[] = { + (char *)PARM_ENABLE, (char *)PARM_YES, (char *)_("1"), (char *)0 + }; + + static char *bool_false_flags[] = { + (char *) PARM_DISABLE, (char *)PARM_NO, (char *)_("0"), (char *)0 + }; + + for(size_t i = 0; i < sizeof(bool_true_flags)/sizeof(char *); i++) { + if(bool_true_flags[i] == (char *)0) break; + if(strncmp(uc_value.c_str(), bool_true_flags[i], 7) == 0) { + flag = true; + return script_no_errors; + } + } + + for(size_t i = 0; i < sizeof(bool_false_flags)/sizeof(char *); i++) { + if(bool_false_flags[i] == (char *)0) break; + if(strncmp(uc_value.c_str(), bool_false_flags[i], 7) == 0) { + flag = false; + return script_no_errors; + } + } + + flag = false; + return script_invalid_parameter; +} + +/** ************************************************************** + * \brief Validate if the parameter is a value. + * \param value The string in question. + * \param p format verification. + * \return SCRIPT_CODES error code. + *****************************************************************/ +SCRIPT_CODES ScriptParsing::check_numbers(char *value, paramter_types p) +{ + SCRIPT_CODES error = script_no_errors; + size_t length = 0; + size_t index = 0; + int data_count = 0; + int signed_value = 0; + int decimal_point = 0; + + if(!value) + return script_function_parameter_error; + + length = strnlen(value, MAX_PARAMETER_LENGTH); + + if(length < 1) + return script_parameter_error; + + // Skip any leading white spaces. + for(index = 0; index < length; index++) { + if(value[index] > ' ') + break; + } + + if((index >= length)) + return script_parameter_error; + + switch(p) { + case p_int: + case p_long: + + if(value[0] == '-' || value[0] == '+') { + index++; + signed_value++; + } + + case p_unsigned_int: + case p_unsigned_long: + + for(; index< length; index++) { + if(isdigit(value[index])) + data_count++; + else + break; + } + break; + + if(data_count) + return script_no_errors; + + case p_float: + case p_double: + if(value[0] == '-' || value[0] == '+') { + index++; + signed_value++; + } + + for(; index< length; index++) { + if(isdigit(value[index])) + data_count++; + + if(value[index] == '.') + decimal_point++; + + if(decimal_point > 1) + return script_parameter_error; + } + + if(data_count) + return script_no_errors; + + break; + + default:; + + } + + return error; +} + +/** ************************************************************** + * \brief Validate the script parameter(s) are of the expected format. + * \param cmd Matching command data structure. + * \param p A table of expected parameters types (null terminated). + * \param p_count the number of 'p[]' items in the table (includes null termination). + * \return SCRIPT_CODES error code. + *****************************************************************/ +SCRIPT_CODES ScriptParsing::check_parameters(struct script_cmds *cmd) +{ + SCRIPT_CODES error = script_no_errors; + int count = 0; + int index = 0; + size_t size = 0; + bool flag = false; + + if(!cmd) + return script_function_parameter_error; + + count = cmd->argc; + + if(count < 1) + return script_no_errors; + + for(index = 0; index < count; index++) { + + if(!cmd->args[index]) { + return script_args_eol; + } + + if(cmd->param_check[index] == p_null) { + size = 0; + } else { + size = strnlen(cmd->args[index], MAX_COMMAND_LENGTH); + } + + switch(cmd->param_check[index]) { + case p_null: + error = script_param_check_eol; + break; + + case p_char: + if(size > 1) + error = script_paramter_exceeds_length; + break; + + case p_bool: + error = check_bool(cmd->args[index], flag); + break; + + case p_int: + case p_long: + case p_unsigned_int: + case p_unsigned_long: + case p_float: + case p_double: + error = check_numbers(cmd->args[index], cmd->param_check[index]); + break; + + case p_dev_path: + error = check_dev_path(cmd->args[index]); + break; + + case p_dev_name: + case p_string: + if(size < 1) + error = script_parameter_error; + break; + + case p_path: + error = check_path(cmd->args[index]); + break; + + case p_filename: + error = check_filename(cmd->args[index]); + break; + + case p_list: + case p_list_end: + case p_void: + break; + } + + if(error != script_no_errors) + break; + } + + return error; +} + +/** ************************************************************** + * \brief Search the content of SCRIPT_COMMANDS structure table + * for the specified command. + * \param command The command to search for. + * \return Pointer to the matching SCRIPT_COMMANDS entry. Null if + * not found. + *****************************************************************/ +SCRIPT_COMMANDS * ScriptParsing::search_command(SCRIPT_COMMANDS * table, size_t limit, const char *command) +{ + char *cmd_buffer = (char *)0; + int diff = 0; + SCRIPT_COMMANDS * found = (SCRIPT_COMMANDS *) 0; + size_t count = limit; + size_t index = 0; + + if(!command) return found; + + cmd_buffer = new char [MAX_COMMAND_LENGTH]; + + if(!cmd_buffer) { + LOG_INFO(_("cmd_buffer allocation error near line %d"), __LINE__); + return found; + } + + memset(cmd_buffer, 0, MAX_COMMAND_LENGTH); + strncpy(cmd_buffer, command, MAX_COMMAND_LENGTH-1); + + to_uppercase(cmd_buffer, (int) MAX_COMMAND_LENGTH); + trim(cmd_buffer, (size_t) MAX_COMMAND_LENGTH); + + for(index = 0; index < count; index++) { + diff = strncmp(cmd_buffer, table[index].command, MAX_COMMAND_LENGTH); + if(diff == 0) { + found = &table[index]; + break; + } + } + + cmd_buffer[0] = 0; + delete [] cmd_buffer; + + return found; +} + +/** ************************************************************** + * \brief Convert string to uppercase characters.
    + * \par str Pointer to data. + * \par limit data buffer size + * \return void + *****************************************************************/ +void ScriptParsing::to_uppercase(char *str, int limit) +{ + if(!str || limit < 1) return; + + int character = 0; + int count = 0; + int index = 0; + + count = (int) strnlen(str, limit); + + for(index = 0; index < count; index++) { + character = str[index]; + if(character == 0) break; + character = (char) toupper(character); + str[index] = character; + } +} + +/** ************************************************************** + * \brief Convert string to uppercase characters.
    + * \par str String storage passed by reference. + * \return void + *****************************************************************/ +void ScriptParsing::to_uppercase(std::string &str) +{ + int character = 0; + int count = 0; + int index = 0; + + count = (int) str.length(); + + for(index = 0; index < count; index++) { + character = str[index]; + if(character == 0) break; + character = (char) toupper(character); + str[index] = character; + } +} + +#if 0 +/** ************************************************************** + * \brief Assign Call back function to a given script command.
    + * \param scriptCommand Script command string
    + * \param cb Pointer to call back function. int (*cb)(ScriptParsing *sp, SCRIPT_COMMANDS *sc) + *****************************************************************/ +int ScriptParsing::assign_callback(const char *scriptCommand, int (*cb)(ScriptParsing *sp, SCRIPT_COMMANDS *sc)) +{ + char *cmd_buffer = (char *)0; + int diff = 0; + size_t count = _script_command_count; + size_t index = 0; + + if(!scriptCommand || !cb) return 0; + + cmd_buffer = new char[MAX_COMMAND_LENGTH]; + + if(!cmd_buffer) { + LOG_INFO(_("cmd_buffer allocation error near line %d"), __LINE__); + return 0; + } + + memset(cmd_buffer, 0, MAX_COMMAND_LENGTH); + strncpy(cmd_buffer, scriptCommand, MAX_COMMAND_LENGTH-1); + + to_uppercase(cmd_buffer, (int) MAX_COMMAND_LENGTH); + trim(cmd_buffer, (size_t) MAX_COMMAND_LENGTH); + + for(index = 0; index < count; index++) { + diff = strncmp(cmd_buffer, _script_commands[index].command, MAX_COMMAND_LENGTH); + if(diff == 0) { + if(_script_commands[index].cb) + LOG_INFO(_("Over writing call back funcion for \"%s\""), cmd_buffer); + _script_commands[index].cb = cb; + break; + } + } + + cmd_buffer[0] = 0; + delete [] cmd_buffer; + + return 0; +} +#endif // #if 0 + +/** ************************************************************** + * \brief Assign member calling function to a command + * \param top_command Top Command + * \param sub_command Sub command + * \param func Assigned calling function member + * \return void (nothing) + *****************************************************************/ +SCRIPT_CODES ScriptParsing::assign_member_func(char *cmd, SCRIPT_CODES (ScriptParsing::*func)(struct script_cmds *)) +{ + char *buffer = (char *)0; + char *cPtr = (char *)0; + char *endPtr = (char *)0; + char *ePtr = (char *)0; + int allocated_buffer_size = MAX_COMMAND_LENGTH; + size_t size = 0; + + SCRIPT_CODES error = script_no_errors; + SCRIPT_COMMANDS *local_list = _script_commands; + size_t local_limit = _script_command_count; + + if(!cmd || !func) + return script_invalid_parameter; + + size = strnlen(cmd, MAX_COMMAND_LENGTH); + cPtr = cmd; + endPtr = &cmd[size]; + size = 0; + + cPtr = skip_white_spaces(cPtr, endPtr, error); + if(error != script_no_errors) return error; + + ePtr = skip_to_character(':', cPtr, endPtr, error); + if(error != script_no_errors) return script_command_seperator_missing; + + buffer = new char [allocated_buffer_size]; + if(!buffer) { + LOG_INFO(_("Buffer allocation Error near File: %s Line %d"), __FILE__, __LINE__); + return script_memory_allocation_error; + } + + memset(buffer, 0, allocated_buffer_size); + error = copy_string_uppercase(buffer, cPtr, ePtr, allocated_buffer_size-1); + + if(error != script_no_errors) { + buffer[0] = 0; + delete [] buffer; + return error; + } + + int str_count = str_cnt(buffer, allocated_buffer_size); + trim(buffer, (size_t) str_count); + + char sub_command[MAX_COMMAND_LENGTH]; + + bool not_found = true; + + cPtr = buffer; + endPtr = &buffer[str_count]; + + while(not_found) { + memset(sub_command, 0, sizeof(sub_command)); + + ePtr = skip_to_character('.', cPtr, endPtr, error); + + if(error == script_end_of_line_reached) { + ePtr = endPtr; + error = script_no_errors; + } + + if(error == script_no_errors) { + copy_string_uppercase(sub_command, cPtr, ePtr, MAX_COMMAND_LENGTH-1); + cPtr = ePtr + 1; + } + else + break; + + for(size_t i = 0; i < local_limit; i++) { + + if(local_list[i].command[0] == 0) { + not_found = false; + error = script_command_not_found; + break; + } + + if(strncmp(sub_command, local_list[i].command, MAX_COMMAND_LENGTH) == 0) { + + if((local_list[i].param_check[0] == p_list) && local_list[i].sub_commands) { + local_limit = local_list[i].sub_command_count; + local_list = local_list[i].sub_commands; + break; + } + + local_list[i].func = func; + local_list[i].command_length = strnlen(local_list[i].command, MAX_COMMAND_LENGTH); + not_found = false; + error = script_no_errors; + break; + } + } + } + + buffer[0] = 0; + delete [] buffer; + + return error; + +} + +#if 0 +/** ************************************************************** + * \brief Assign member calling function to a command + * \param top_command Top Command + * \param sub_command Sub command + * \param func Assigned calling function member + * \return void (nothing) + *****************************************************************/ +void ScriptParsing::assign_member_func(char *cmd, SCRIPT_CODES (ScriptParsing::*func)(struct script_cmds *)) +{ + if(!top_command || !func) return; + + SCRIPT_COMMANDS *top_table = (SCRIPT_COMMANDS *)0; + SCRIPT_COMMANDS *modify_table = (SCRIPT_COMMANDS *)0; + + if(top_cache) { + if(strncmp(top_cache->command, top_command, MAX_COMMAND_LENGTH) == 0) { + top_table = top_cache; + } + } + + if(!top_table) { + for(int i = 0; i < _script_command_count; i++) { + if(strncmp(_script_commands[i].command, top_command, MAX_COMMAND_LENGTH) == 0) { + top_cache = &_script_commands[i]; + top_table = top_cache; + break; + } + } + } + + if(!top_table) + return; + + if(!sub_command) + modify_table = top_table; + + if(modify_table == (SCRIPT_COMMANDS *)0) { + if(top_table->sub_commands) { + for(int i = 0; i < top_table->sub_command_count; i++) { + if(strncmp(sub_command, top_table->sub_commands[i].command, MAX_COMMAND_LENGTH) == 0) { + modify_table = &top_table->sub_commands[i]; + break; + } + } + } + } + + if(modify_table != (SCRIPT_COMMANDS *)0) { + modify_table->func = func; + modify_table->command_length = strnlen(modify_table->command, MAX_COMMAND_LENGTH); + } +} +#endif // #if 0 + +/** ************************************************************** + * \brief Initialize variables + * \return void (nothing) + *****************************************************************/ +void ScriptParsing::clear_script_parameters(bool all) +{ + _path.clear(); + _file_type = SCRIPT_COMMAND; + _macro_command.clear(); +} + + +/** ************************************************************** + * \brief Initialize callable members. + * \return void (nothing) + *****************************************************************/ +void ScriptParsing::initialize_function_members(void) +{ + std::string cmd; + + cmd.assign(CMD_LOAD_MACRO).append(":"); // For localization + assign_member_func((char *) cmd.c_str(), &ScriptParsing::sc_macros); +} + +/** ************************************************************** + * \brief Copy environment to the sub ScriptParsing class + * \param src Source Class pointer to copy from. + *****************************************************************/ +int ScriptParsing::CopyScriptParsingEnv(ScriptParsing *src) +{ + if(!src || (src == this)) return -1; + + + parent(src); + script_commands(src->script_commands()); + script_command_count(src->script_command_count()); + initialize_function_members(); + + return 0; +} +/** ************************************************************** + * \brief Constructor: Copy and initialize.
    + *****************************************************************/ +int ScriptParsing::copy_tables(struct script_cmds * subcmds, size_t count) +{ + size_t index = 0; + size_t table_count = 0; + + SCRIPT_COMMANDS * dst_table = 0; + SCRIPT_COMMANDS * src_table = 0; + + recursive_count++; + if(recursive_count > RECURSIVE_LIMIT) return 0; + + for(index = 0; index < count; index++) { + src_table = subcmds[index].sub_commands; + table_count = subcmds[index].sub_command_count; + + if(src_table && table_count) { + dst_table = new SCRIPT_COMMANDS[table_count]; + if(dst_table) { + add_to_delete_list(dst_table); + memcpy(dst_table, src_table, sizeof(SCRIPT_COMMANDS) * table_count); + subcmds[index].sub_commands = dst_table; + subcmds[index].sub_command_count = table_count; + copy_tables(dst_table, table_count); + } + } + } + + recursive_count--; + return 0; +} + +/** ************************************************************** + * \brief Constructor: Copy and initialize function arrays.
    + *****************************************************************/ +ScriptParsing::ScriptParsing() +{ + size_t count = 0; + + clear_script_parameters(true); + + memset(line_buffer, 0, sizeof(line_buffer)); + memset(error_cmd_buffer, 0, sizeof(error_cmd_buffer)); + memset(error_string, 0, sizeof(error_string)); + memset(error_buffer, 0, sizeof(error_buffer)); + + memset(memory_delete_list, 0, sizeof(memory_delete_list)); + delete_list_count = 0; + + top_cache = 0; + recursive_count = 0; + _script_error_detected = false; + _restart_flag = false; + + fd = 0; + + count = sizeof(default_top_level_command_table)/sizeof(SCRIPT_COMMANDS); + + _script_commands = new SCRIPT_COMMANDS[count]; + + if(_script_commands) { + add_to_delete_list(_script_commands); + _script_command_count = count; + memcpy(_script_commands, default_top_level_command_table, sizeof(SCRIPT_COMMANDS) * _script_command_count); + copy_tables(_script_commands, _script_command_count); + } + + recursive_count = 0; + initialize_function_members(); + +} + +/** ************************************************************** + * \brief Destructor + *****************************************************************/ +ScriptParsing::~ScriptParsing() +{ + int index = 0; + for(index = 0; index < MAX_DELETE_LIST_COUNT; index++) { + if(memory_delete_list[index]) { + delete [] memory_delete_list[index]; + } + } +} + +/** ************************************************************** + * \brief Keep track of memory allocation for easy deallocation. + *****************************************************************/ +void ScriptParsing::add_to_delete_list(SCRIPT_COMMANDS *ptr) +{ + if(!ptr) return; + + if(delete_list_count < MAX_DELETE_LIST_COUNT) { + memory_delete_list[delete_list_count] = ptr; + delete_list_count++; + } +} + +/** ************************************************************** + * \brief Dummy callback function for initialization of + * function pointers. + * \param sp The calling ScriptParsing Class + * \param sc Command data structure pointer to the matching script + * command. + * \return 0 = No error
    \< 0 = Error
    + *****************************************************************/ +int callback_dummy(ScriptParsing *sp, struct script_cmds *sc) +{ + return 0; +} + +/** ******************************************************** + * \brief Determine the length of the string with a count + * limitation. + * \return signed integer. The number of characters in the + * array not to excede count limit. + ***********************************************************/ +int ScriptParsing::str_cnt(char * str, int count_limit) +{ + if(!str || (count_limit < 1)) + return 0; + + int value = 0; + + for(int index = 0; index < count_limit; index++) { + if(str[index] == 0) break; + value++; + } + + return value; +} + +/** ******************************************************** + * \brief Trim leading and trailing spaces from string. + * \param s String to modify + * \return s modified string. + ***********************************************************/ +std::string &ScriptParsing::trim(std::string &s) { + char *buffer = (char *)0; + char *dst = (char *)0; + char *end = (char *)0; + char *src = (char *)0; + long count = s.size(); + + buffer = new char[count + 1]; + if(!buffer) return s; + + memcpy(buffer, s.c_str(), count); + buffer[count] = 0; + + dst = src = buffer; + end = &buffer[count]; + + while(src < end) { + if(*src > ' ') break; + src++; + } + + if(src > dst) { + while((dst < end) && (src < end)) + *dst++ = *src++; + *dst = 0; + } + + while(end >= buffer) { + if(*end > ' ') break; + *end-- = 0; + } + + s.assign(buffer); + + delete [] buffer; + + return s; +} + +/** ************************************************************** + * \brief Remove leading/trailing white spaces and quotes. + * \param buffer Destination buffer + * \param limit passed buffer size + * \return void + *****************************************************************/ +void ScriptParsing::trim(char *buffer, size_t limit) +{ + char *s = (char *)0; + char *e = (char *)0; + char *dst = (char *)0; + size_t count = 0; + + if(!buffer || limit < 1) { + return; + } + + for(count = 0; count < limit; count++) + if(buffer[count] == 0) break; + + if(count < 1) return; + + s = buffer; + e = &buffer[count-1]; + + for(size_t i = 0; i < count; i++) { + if((*s <= ' ') || (*s == '"')) s++; + else break; + } + + while(e > s) { + if((*e <= ' ') || (*e == '"')) + *e = 0; + else + break; + e--; + } + + dst = buffer; + for(; s <= e; s++) { + *dst++ = *s; + } + *dst = 0; +} diff --git a/src/config_script/script_parsing.h b/src/config_script/script_parsing.h new file mode 100644 index 00000000..8a075728 --- /dev/null +++ b/src/config_script/script_parsing.h @@ -0,0 +1,470 @@ +//====================================================================== +// script_parsing.h (FLDIGI) +// +// Author(s): +// +// Robert Stiles, KK5VD, Copyright (C) 2014 +// +// This 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. +// +// This software 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 this program. If not, see . +// ===================================================================== + +#ifndef __script_parsing__ +#define __script_parsing__ + +#include +#include + +#ifdef __WIN32__ +#define PATH_SEPERATOR "\\" +#define PATH_CHAR_SEPERATOR '\\' +#include +#define get_current_dir _getcwd +#else +#define PATH_SEPERATOR "/" +#define PATH_CHAR_SEPERATOR '/' +#include +#define get_current_dir getcwd +#endif + +#define MAX_CMD_PARAMETERS 5 +#define MAX_COMMAND_LENGTH 128 +#define MAX_PARAMETER_LENGTH FILENAME_MAX +#define MAX_READLINE_LENGTH (FILENAME_MAX+FILENAME_MAX) +#define MAX_SUB_SCRIPTS 5 + +#define SCRIPT_FILE_TAG ((char *)"FLDIGI_CONFIG") +#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember)) + +#define RESET_ALL 0x01 +#define RESET_PARTIAL 0X02 + +#undef __LOCALIZED_SCRIPT_COMMANDS +#ifdef __LOCALIZED_SCRIPT_COMMANDS +#pragma message ( \ +"\n" \ +"************************************************************************\n" \ +"* Defining __LOCALIZED_SCRIPT_COMMANDS breaks script compatibility. In *\n" \ +"* doing so, FLDIGI development team does not assume responsibility for *\n" \ +"* maintaining the code sections that are altered/effected as a result. *\n" \ +"************************************************************************\n" ) +#define F_LOC(a) _(a) +#else +#define F_LOC(a) a +#endif + +#define CMD_OPERATOR F_LOC("OPERATOR") +#define CMD_CALLSIGN F_LOC("CALLSIGN") +#define CMD_NAME F_LOC("NAME") +#define CMD_QTH F_LOC("QTH") +#define CMD_LOCATOR F_LOC("LOC") +#define CMD_ANTENNA F_LOC("ANT") + +#define CMD_AUDIO_DEVICE F_LOC("AUDIO DEVICE") +#define CMD_OSS_AUDIO F_LOC("OSS") +#define CMD_OSS_AUDIO_DEV_PATH F_LOC("OSS DEV") +#define CMD_PORT_AUDIO F_LOC("PA") +#define CMD_PORTA_CAP F_LOC("PA CAPTURE") +#define CMD_PORTA_PLAY F_LOC("PA PLAYBACK") +#define CMD_PULSEA F_LOC("PUA") +#define CMD_PULSEA_SERVER F_LOC("PUA SERVER") + +#define CMD_AUDIO_SETTINGS F_LOC("AUDIO SETTINGS") +#define CMD_CAPTURE_SAMPLE_RATE F_LOC("CAPTURE") +#define CMD_PLAYBACK_SAMPLE_RATE F_LOC("PLAYBACK") +#define CMD_AUDIO_CONVERTER F_LOC("CONVERTER") +#define CMD_RX_PPM F_LOC("RX PPM") +#define CMD_TX_PPM F_LOC("TX PPM") +#define CMD_TX_OFFSET F_LOC("TX OFFSET") + +#define CMD_AUDIO_RT_CHANNEL F_LOC("AUDIO RT CHANNEL") +#define CMD_MONO_AUDIO F_LOC("MONO AUDIO") +#define CMD_AUDIO_L_R F_LOC("MODEM LR") +#define CMD_AUDIO_REV_L_R F_LOC("REV LR") +#define CMD_PTT_RIGHT_CHAN F_LOC("PTT RT CHAN") +#define CMD_CW_QSK_RT_CHAN F_LOC("QSK RT CHAN") +#define CMD_PSEUDO_FSK_RT_CHAN F_LOC("FSK RT CHAN") + +#define CMD_AUDIO_WAVE F_LOC("AUDIO WAVE") +#define CMD_WAVE_SR F_LOC("SRATE") + +#define CMD_HRDWR_PTT F_LOC("RIG HRDWR PTT") +#define CMD_HPPT_PTT_RT F_LOC("PTT RT CHAN") +#define CMD_HPTT_SP2 F_LOC("SERIAL PORT") +#define CMD_HPTT_SP2_PATH F_LOC("DEVICE") +#define CMD_HPTT_SP2_RTS F_LOC("RTS") +#define CMD_HPTT_SP2_DTR F_LOC("DTR") +#define CMD_HPTT_SP2_RTS_V F_LOC("RTSV") +#define CMD_HPTT_SP2_DTR_V F_LOC("DTRV") +#define CMD_HPTT_SP2_START_DELAY F_LOC("START PTT DELAY") +#define CMD_HPTT_SP2_END_DELAY F_LOC("END PTT DELAY") +#define CMD_HPTT_UHROUTER F_LOC("UHROUTER") +#define CMD_HPTT_PARALLEL F_LOC("PARALLEL") +#define CMD_HPTT_SP2_INITIALIZE F_LOC("INIT") + +#define CMD_RIGCAT F_LOC("RIGCAT") +#define CMD_RIGCAT_STATE F_LOC("STATE") +#define CMD_RIGCAT_DESC_FILE F_LOC("DESC FILE") +#define CMD_RIGCAT_DEV_PATH F_LOC("DEV PATH") +#define CMD_RIGCAT_RETRIES F_LOC("RETRIES") +#define CMD_RIGCAT_RETRY_INTERVAL F_LOC("RETRY INT") +#define CMD_RIGCAT_WRITE_DELAY F_LOC("WDELAY") +#define CMD_RIGCAT_INTIAL_DELAY F_LOC("IDELAY") +#define CMD_RIGCAT_BAUD_RATE F_LOC("BRATE") +#define CMD_RIGCAT_STOP_BITS F_LOC("SBITS") +#define CMD_RIGCAT_ECHO F_LOC("ECHO") +#define CMD_RIGCAT_TOGGLE_RTS_PTT F_LOC("TOGGLE RTS PTT") +#define CMD_RIGCAT_TOGGLE_DTR_PTT F_LOC("TOGGLE DTR PTT") +#define CMD_RIGCAT_RESTORE F_LOC("RESTORE") +#define CMD_RIGCAT_PTT_COMMAND F_LOC("PTT COMMAND") +#define CMD_RIGCAT_RTS_12V F_LOC("RTS 12V") +#define CMD_RIGCAT_DTR_12V F_LOC("DTR 12V") +#define CMD_RIGCAT_HRDWR_FLOW F_LOC("HRDWR FC") +#define CMD_RIGCAT_VSP F_LOC("VSP") +#define CMD_RIGCAT_INITIALIZE F_LOC("INIT") + +#define CMD_HAMLIB F_LOC("HAMLIB") +#define CMD_HAMLIB_STATE F_LOC("STATE") +#define CMD_HAMLIB_RIG F_LOC("RIG") +#define CMD_HAMLIB_DEV_PATH F_LOC("DEV PATH") +#define CMD_HAMLIB_RETRIES F_LOC("RETRIES") +#define CMD_HAMLIB_RETRY_INTERVAL F_LOC("RETRY INT") +#define CMD_HAMLIB_WRITE_DELAY F_LOC("WDELAY") +#define CMD_HAMLIB_POST_WRITE_DELAY F_LOC("PWDELAY") +#define CMD_HAMLIB_BAUD_RATE F_LOC("BRATE") +#define CMD_HAMLIB_STOP_BITS F_LOC("SBITS") +#define CMD_HAMLIB_SIDE_BAND F_LOC("SBAND") +#define CMD_HAMLIB_PTT_COMMAND F_LOC("PTT COMMAND") +#define CMD_HAMLIB_DTR_12V F_LOC("DTR 12V") +#define CMD_HAMLIB_RTS_12V F_LOC("RTS 12V") +#define CMD_HAMLIB_HRDWR_FLOW F_LOC("HRDWR FC") +#define CMD_HAMLIB_SFTWR_FLOW F_LOC("SFTWR FC") +#define CMD_HAMLIB_ADV_CONFIG F_LOC("ADV CONF") +#define CMD_HAMLIB_INITIALIZE F_LOC("INIT") + +#define CMD_RC_XMLRPC F_LOC("XMLRPC RC") +#define CMD_RC_XMLRPC_STATE F_LOC("STATE") +#define CMD_RC_XMLRPC_BW_DELAY F_LOC("BWDELAY") +#define CMD_RC_XMLRPC_INITIALIZE F_LOC("INIT") + +#define CMD_FLDIGI F_LOC("FLDIGI") +#define CMD_FLDIGI_FREQ F_LOC("FREQ") +#define CMD_FLDIGI_MODE F_LOC("MODE") +#define CMD_FLDIGI_WFHZ F_LOC("WFHZ") +#define CMD_FLDIGI_RXID F_LOC("RXID") +#define CMD_FLDIGI_TXID F_LOC("TXID") +#define CMD_FLDIGI_SPOT F_LOC("SPOT") +#define CMD_FLDIGI_REV F_LOC("REV") +#define CMD_FLDIGI_LOCK F_LOC("LOCK") +#define CMD_FLDIGI_AFC F_LOC("AFC") +#define CMD_FLDIGI_SQL F_LOC("SQL") +#define CMD_FLDIGI_KPSQL F_LOC("KPSQL") +#define CMD_FLDIGI_MODEM F_LOC("MODEM") + +#define CMD_IO F_LOC("IO") +#define CMD_IO_LOCK F_LOC("LOCK") +#define CMD_IO_ACT_PORT F_LOC("PORT") +#define CMD_IO_AX25_DECODE F_LOC("AX25D") +#define CMD_IO_CSMA F_LOC("CSMA") +#define CMD_IO_KISS F_LOC("KISS") +#define CMD_IO_KISS_IPA F_LOC("IPA") +#define CMD_IO_KISS_IOPN F_LOC("IOPN") +#define CMD_IO_KISS_OPN F_LOC("OPN") +#define CMD_IO_KISS_DP F_LOC("DP") +#define CMD_IO_KISS_BUSY F_LOC("BUSY") +#define CMD_IO_KISS_CONT F_LOC("CONT") +#define CMD_IO_KISS_ATTEN F_LOC("ATTEN") +#define CMD_IO_ARQ F_LOC("ARQ") +#define CMD_IO_ARQ_IPA F_LOC("IPA") +#define CMD_IO_ARQ_IOPN F_LOC("IOPN") +#define CMD_IO_XMLRPC F_LOC("XMLRPC") +#define CMD_IO_XMLRPC_IPA F_LOC("IPA") +#define CMD_IO_XMLRPC_IOPN F_LOC("IOPN") + +#define CMD_NBEMS F_LOC("MISC NBEMS") +#define CMD_NBEMS_STATE F_LOC("STATE") +#define CMD_NBEMS_MSG F_LOC("OPEN MSG") +#define CMD_NBEMS_FLMSG F_LOC("OPEN FLMSG") +#define CMD_NBEMS_FLMSG_PATH F_LOC("PATH") +#define CMD_NBEMS_BRWSR F_LOC("OPEN BRWSR") +#define CMD_NBEMS_TIMEOUT F_LOC("TIMEOUT") + +#define CMD_ID F_LOC("ID") +#define CMD_ID_RSID F_LOC("RSID") +#define CMD_ID_RSID_NOTIFY F_LOC("NOTIFY") +#define CMD_ID_RSID_SRCH_BP F_LOC("SRCH BP") +#define CMD_ID_RSID_MARK_PREV F_LOC("MARK PREV") +#define CMD_ID_RSID_DETECTOR F_LOC("DETECTOR") +#define CMD_ID_RSID_ALRT_DIALOG F_LOC("ALRT DIALOG") +#define CMD_ID_RSID_TX_FREQ_LOCK F_LOC("TX FREQ LOCK") +#define CMD_ID_RSID_FREQ_CHANGE F_LOC("FREQ CHANGE") +#define CMD_ID_RSID_ALLOW_ERRORS F_LOC("ALLOW ERRORS") +#define CMD_ID_RSID_SQL_OPEN F_LOC("SQL OPEN") +#define CMD_ID_RSID_PRETONE F_LOC("PRETONE") +#define CMD_ID_RSID_END_XMT_ID F_LOC("END XMT ID") +#define CMD_ID_VIDEO F_LOC("VIDEO") +#define CMD_ID_VIDEO_TX_ID_MODE F_LOC("ID MODE") +#define CMD_ID_VIDEO_TX_VIDEO_TXT F_LOC("VIDEO TXT") +#define CMD_ID_VIDEO_TX_TXT_INP F_LOC("TEXT INPUT") +#define CMD_ID_VIDEO_SMALL_FONT F_LOC("SMALL FONT") +#define CMD_ID_VIDEO_500_HZ F_LOC("500HZ") +#define CMD_ID_VIDEO_WIDTH_LIMIT F_LOC("WIDTH LIMIT") +#define CMD_ID_VIDEO_CHAR_ROW F_LOC("CHAR ROW") +#define CMD_ID_CW F_LOC("CW") +#define CMD_ID_CW_TX_CALLSIGN F_LOC("TX CALL") +#define CMD_ID_CW_SPEED F_LOC("SPEED") + + +#define CMD_LOAD_MACRO F_LOC("MACRO") +#define CMD_END_CMD F_LOC("END") + +// Parameters localized - no restrictions. + +#define PARM_ENABLE _("ENABLE") +#define PARM_YES _("YES") +#define PARM_DISABLE _("DISABLE") +#define PARM_NO _("NO") +#define PARM_KISS _("KISS") +#define PARM_ARQ _("ARQ") + +#define SCRIPT_COMMAND 0x0001 +#define SCRIPT_DOT_NOTATION_ONLY 0x0002 +#define SCRIPT_STRUCTURED_ONLY 0x0004 + +#define RECURSIVE_LIMIT 3 +#define MAX_DELETE_LIST_COUNT 100 + +//! @enum script_codes +//! Error codes. + +//! @typedef SCRIPT_CODES +//! @see script_codes + +typedef enum script_codes { + script_recursive_limit_reached = -100, //!< Reached command recursive limit. + script_command_not_found = -100, //!< Script command not found. + script_unexpected_eof, //!< Unexspected end of file reached. + script_file_read_error, //!< File read error + script_errors_reported, //!< Script Errors found during parsing of file. + script_file_not_found, //!< Script file not found. + script_path_not_found, //!< Script directory path not found. + script_device_path_not_found, //!< Script device path not found. + script_non_script_file, //!< Opened file not a Script file. + script_max_sub_script_reached, //!< Maximum open subscripts reached. + script_subscript_exec_fail, //!< Subscript execution fail (internal). + script_incorrectly_assigned_value, //!< Incorrect parameter type. + script_invalid_parameter, //!< Parameter is not valid. + script_parameter_error, //!< Script parameter invalid. + script_function_parameter_error, //!< Function parameter error (internal, non script error). + script_mismatched_quotes, //!< Opening or closing quotes missing prior to reaching end if line. + script_command_seperator_missing, //!< Command missing ':' + script_args_eol, //!< Reached end of args list sooner then expected + script_param_check_eol, //!< Reached end of parameter check list sooner then expected + script_paramter_exceeds_length, //!< Data length exceeds expectations + script_memory_allocation_error, //!< Memory Allocation Error (Non-Script internal Error). + script_general_error = -1, //!< General purpose error (undefined erros). + script_no_errors, //!< No Errors + script_char_match_not_found, //!< Search char not found (Warning) + script_end_of_line_reached, //!< End of line reached (Warning) + script_end_of_list_reached, //!< End of list reached (Info) + script_list, //!< List command (Info) + script_command_handled, //!< Command was procedded and handled (Info) +} SCRIPT_CODES; + + +//! @enum paramter_types +//! Parameter type flags. Used to validate the informarion. + +//! @typedef PARAM_TYPES +//! @see paramter_types + +typedef enum paramter_types { + p_null = 0, + p_void, + p_bool, + p_char, + p_int, + p_unsigned_int, + p_long, + p_unsigned_long, + p_float, + p_double, + p_string, + p_path, + p_filename, + p_dev_path, + p_dev_name, + p_list, + p_list_end +} PARAM_TYPES; + +class ScriptParsing; + +//! @struct script_cmds +//! Vector table of script command string and executing function member. + +//! @typedef SCRIPT_COMMANDS +//! @see script_cmds +typedef struct script_cmds { + char command[MAX_COMMAND_LENGTH]; //!< Command matching string. + int flags; //!< General purpose flags + size_t command_length; //!< Number of chacters in the command string. + int argc; //!< Number of required prarmeters for the command + char *args[MAX_CMD_PARAMETERS+1]; //!< String vector table of parameters + enum paramter_types param_check[MAX_CMD_PARAMETERS+1]; //!< Flags to determine type of parameter. + const char **valid_values; //!< A list of valid paramters. + int valid_value_count; //!< The number of valid paramters. + SCRIPT_CODES (ScriptParsing::*func)(struct script_cmds *); //!< The function (member) to execute on positive match + int (*cb)(ScriptParsing *sp, struct script_cmds *sd); //!< Call back function for script command + struct script_cmds * sub_commands; //!< List of sub commands + size_t sub_command_count; //!< Number of table entires in the sub table. +} SCRIPT_COMMANDS; + +//! @class script_parsing_class +class ScriptParsing { + +public: + +private: + pthread_mutex_t ac; // (v)); - if (progdefaults.mbar_scheme > 2) { + if (progdefaults.mbar_scheme > MACRO_SINGLE_BAR_MAX) { if (b >= NUMMACKEYS) b += (altMacros - 1) * NUMMACKEYS; } else { b += altMacros * NUMMACKEYS; @@ -1579,7 +1579,7 @@ void altmacro_cb(Fl_Widget *w, void *v) else altMacros = altMacros + (Fl::event_button() == FL_RIGHT_MOUSE ? -1 : 1); - if (progdefaults.mbar_scheme > 2) { // alternate set + if (progdefaults.mbar_scheme > MACRO_SINGLE_BAR_MAX) { // alternate set altMacros = WCLAMP(altMacros, 1, 3); alt_text[0] = '1' + altMacros; for (int i = 0; i < NUMMACKEYS; i++) { @@ -2249,7 +2249,7 @@ void cb_mnuContest(Fl_Menu_ *m, void *) { void set_macroLabels() { - if (progdefaults.mbar_scheme > 2) { + if (progdefaults.mbar_scheme > MACRO_SINGLE_BAR_MAX) { altMacros = 1; for (int i = 0; i < NUMMACKEYS; i++) { btnMacro[i]->label(macros.name[i].c_str()); @@ -2415,7 +2415,7 @@ void cb_loc(Fl_Widget* w, void*) for (int i = 0; i < len; i++) { if (ok) switch (i) { - case 0 : + case 0 : case 1 : case 4 : case 5 : @@ -2441,7 +2441,7 @@ void cb_loc(Fl_Widget* w, void*) char az[4]; snprintf(az, sizeof(az), "%3.0f", azimuth); inpAZ->value(az); - } else + } else inpAZ->value(""); restoreFocus(w); } @@ -2969,8 +2969,8 @@ bool clean_exit(bool ask) { } } } else { - if (ask && - progdefaults.confirmExit && + if (ask && + progdefaults.confirmExit && (!(progdefaults.changed && progdefaults.SaveConfig) || !(macros.changed && progdefaults.SaveMacros) || !(!oktoclear && progdefaults.NagMe))) { @@ -3370,7 +3370,7 @@ void UI_select() int HTh; if (cnt_macro_height) { - if (progdefaults.mbar_scheme > 2) { // 2 bars + if (progdefaults.mbar_scheme > MACRO_SINGLE_BAR_MAX) { // 2 bars cnt_macro_height->minimum(44); if (progdefaults.macro_height < 44) progdefaults.macro_height = 44; } else { @@ -3548,6 +3548,21 @@ void cb_toggle_smeter(Fl_Widget *w, void *v) toggle_smeter(); } +extern void cb_scripts(bool); + +void cb_menu_scripts(Fl_Widget*, void*) +{ + cb_scripts(false); +} + +extern void cb_create_default_script(void); + +void cb_menu_make_default_scripts(Fl_Widget*, void*) +{ + cb_create_default_script(); +} + + static void cb_opmode_show(Fl_Widget* w, void*); static Fl_Menu_Item menu_[] = { @@ -3565,6 +3580,11 @@ static Fl_Menu_Item menu_[] = { { icons::make_icon_label(_("Save ..."), save_as_icon), 0, (Fl_Callback*)cb_mnuSaveMacro, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, +{ icons::make_icon_label(_("Config Scripts")), 0, 0, 0, FL_MENU_DIVIDER | FL_SUBMENU, _FL_MULTI_LABEL, 0, 14, 0}, +{ _("Execute"), 0, (Fl_Callback*)cb_menu_scripts, 0, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, +{ _("Generate"), 0, (Fl_Callback*)cb_menu_make_default_scripts, 0, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, +{ 0,0,0,0,0,0,0,0,0}, + { icons::make_icon_label(_("Text Capture")), 0, 0, 0, FL_MENU_DIVIDER | FL_SUBMENU, _FL_MULTI_LABEL, 0, 14, 0}, { LOG_TO_FILE_MLABEL, 0, cb_logfile, 0, FL_MENU_TOGGLE, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, @@ -3579,6 +3599,7 @@ static Fl_Menu_Item menu_[] = { { icons::make_icon_label(_("Exit"), log_out_icon), 'x', (Fl_Callback*)cb_E, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, + { OPMODES_MLABEL, 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_CW].name, 0, cb_init_mode, (void *)MODE_CW, 0, FL_NORMAL_LABEL, 0, 14, 0}, @@ -5140,15 +5161,15 @@ void create_fl_digi_main_primary() { inpRstOut1->align(FL_ALIGN_LEFT); inpCall1 = new Fl_Input2( - inpFreq1->x(), y2, + inpFreq1->x(), y2, inpTimeOn1->x() + inpTimeOn1->w() - inpFreq1->x(), Hentry, _("Call")); inpCall1->tooltip(_("call sign")); inpCall1->align(FL_ALIGN_LEFT); inpName1 = new Fl_Input2( - next_to(inpCall1) + 20, y2, - 130, + next_to(inpCall1) + 20, y2, + 130, Hentry, _("Op")); inpName1->tooltip(_("Operator name")); inpName1->align(FL_ALIGN_LEFT); @@ -7396,8 +7417,8 @@ void qsy(long long rfc, int fmid) else if (progdefaults.chkUSEXMLRPCis) REQ(xmlrpc_set_qsy, rfc); else - - LOG_VERBOSE("Ignoring rfcarrier change request (no rig control)"); + qso_selectFreq((long int) rfc, fmid); + //LOG_VERBOSE("Ignoring rfcarrier change request (no rig control)"); } map qrg_marks; diff --git a/src/include/FreqControl.h b/src/include/FreqControl.h index adab6488..8e1051b3 100644 --- a/src/include/FreqControl.h +++ b/src/include/FreqControl.h @@ -62,6 +62,7 @@ public: void updatevalue(); void value(long lv); long value(){return val;}; + long int maximum(void); void font(Fl_Font fnt); void SetONCOLOR (uchar r, uchar g, uchar b); void SetOFFCOLOR (uchar r, uchar g, uchar b); diff --git a/src/include/combo.h b/src/include/combo.h index 9f804458..10190b08 100644 --- a/src/include/combo.h +++ b/src/include/combo.h @@ -110,6 +110,7 @@ public: void sort (); int index (); void index (int i); + int find_index(const char *str); void *data (); void textfont (int); void textsize (uchar); diff --git a/src/include/fl_digi.h b/src/include/fl_digi.h index df34018f..37a7920a 100644 --- a/src/include/fl_digi.h +++ b/src/include/fl_digi.h @@ -130,6 +130,7 @@ extern Fl_Light_Button *btnPSQL; extern Fl_Light_Button *btnRSID; extern Fl_Light_Button *btnTxRSID; extern Fl_Light_Button *btnTune; +extern Fl_Light_Button *btnAutoSpot; extern bool bWF_only; extern bool withnoise; @@ -252,6 +253,9 @@ extern void put_rx_data(int *data, int len); #define GET_TX_CHAR_NODATA -1 // no data available #define GET_TX_CHAR_ETX -3 // end of transmission requested +// Last single macro bar option index +#define MACRO_SINGLE_BAR_MAX 2 + extern int get_tx_char(); extern int get_secondary_char(); extern void put_echo_char(unsigned int data, int style = FTextBase::XMIT); diff --git a/src/include/macroedit.h b/src/include/macroedit.h index b5859b90..a80546e0 100644 --- a/src/include/macroedit.h +++ b/src/include/macroedit.h @@ -46,5 +46,6 @@ extern Fl_Double_Window* make_macroeditor(); enum { MACRO_EDIT_BUTTON, MACRO_EDIT_INPUT }; extern void editMacro(int b, int t = MACRO_EDIT_BUTTON, Fl_Input* in = 0); +extern void update_macro_button(int iMacro, const char *text, const char *name); #endif diff --git a/src/include/rigsupport.h b/src/include/rigsupport.h index 67d20cf1..03aedcdf 100644 --- a/src/include/rigsupport.h +++ b/src/include/rigsupport.h @@ -34,6 +34,8 @@ #include "xmlrpcpp/XmlRpc.h" #include "xmlrpcpp/XmlRpcValue.h" +#define DEFAULT_RIGXML_FILENAME "rig-not-assigned.xml" + extern std::string windowTitle; extern Cserial rigio; @@ -51,7 +53,9 @@ extern void setTitle(); extern void qso_addFreq(); extern void qso_delFreq(); extern void qso_selectFreq(); +extern void qso_selectFreq(long int rfcarrier, int carrier); extern void qso_setFreq(); +extern void qso_setFreq(long int f); extern void qso_clearList(); extern void saveFreqList(); diff --git a/src/include/rigxml.h b/src/include/rigxml.h index ae0b410c..c13c2301 100644 --- a/src/include/rigxml.h +++ b/src/include/rigxml.h @@ -72,13 +72,13 @@ struct XMLIOS { std::string info; std::string ok; std::string bad; - void clear() { + void clear() { SYMBOL.clear(); str1.clear(); str2.clear(); info.clear(); ok.clear(); - bad.clear(); + bad.clear(); size = fill1 = fill2 = 0; data.clear(); }; @@ -126,7 +126,7 @@ struct XMLRIG { rigTitle = ""; } }; - + extern std::list commands; extern std::list reply; extern std::list lmodes; @@ -140,6 +140,6 @@ extern XMLRIG xmlrig; extern bool readRigXML(); extern void selectRigXmlFilename(); - +extern void loadRigXmlFile(void); #endif diff --git a/src/include/sound.h b/src/include/sound.h index 0438b93c..df0893e3 100644 --- a/src/include/sound.h +++ b/src/include/sound.h @@ -220,7 +220,7 @@ private: void src_data_reset(unsigned dir); static long src_read_cb(void* arg, float** data); size_t resample_write(float* buf, size_t count); - device_iterator name_to_device(const std::string& name, unsigned dir); + device_iterator name_to_device(std::string& name, unsigned dir); void init_stream(unsigned dir); void start_stream(unsigned dir); void pause_stream(unsigned dir); diff --git a/src/include/soundconf.h b/src/include/soundconf.h index d4cda5d6..d0459649 100644 --- a/src/include/soundconf.h +++ b/src/include/soundconf.h @@ -1,6 +1,6 @@ // ---------------------------------------------------------------------------- -// Copyright (C) 2014 -// David Freese, W1HKJ +// Copyright (C) 2014 David Freese, W1HKJ +// Copyright (C) 2015 Robert Stiles, KK5VD // // This file is part of fldigi // @@ -34,10 +34,21 @@ enum { #endif FLDIGI_NUM_SRC }; + +enum { + PA_DEV_NOT_FOUND = 0, + PA_DEV_FOUND, + PA_EXACT_DEV_FOUND +}; + extern int sample_rate_converters[FLDIGI_NUM_SRC]; void sound_init(void); void sound_close(void); void sound_update(unsigned idx); +#include +class Fl_Choice; +int pa_set_dev(Fl_Choice *choice, std::string dev_name, int dev_index); + #endif // SOUNDCONF_H diff --git a/src/include/util.h b/src/include/util.h index b3b6c08c..3b3de1f1 100644 --- a/src/include/util.h +++ b/src/include/util.h @@ -133,6 +133,10 @@ extern "C" { const__ uint32_t ceil2(uint32_t n); const__ uint32_t floor2(uint32_t n); +#if !HAVE_STRNLEN +size_t strnlen(const char* str, size_t len); +#endif + #if !HAVE_STRCASESTR char* strcasestr(const char* haystack, const char* needle); #endif diff --git a/src/main.cxx b/src/main.cxx index 1ebacb3f..fda2165d 100644 --- a/src/main.cxx +++ b/src/main.cxx @@ -576,7 +576,7 @@ int main(int argc, char ** argv) bool have_config = progdefaults.readDefaultsXML(); xmlfname = HomeDir; - xmlfname.append("rig.xml"); + xmlfname.append(DEFAULT_RIGXML_FILENAME); checkTLF(); diff --git a/src/misc/macroedit.cxx b/src/misc/macroedit.cxx index 6ca20283..138c77e8 100644 --- a/src/misc/macroedit.cxx +++ b/src/misc/macroedit.cxx @@ -294,28 +294,33 @@ void cbMacroEditOK(Fl_Widget *w, void *) } if (iType == MACRO_EDIT_BUTTON) { - macros.text[iMacro] = macrotext->value(); - macros.name[iMacro] = labeltext->value(); - - if (progdefaults.mbar_scheme > 2) { - if (iMacro < NUMMACKEYS) { - btnMacro[iMacro % NUMMACKEYS]->label( macros.name[iMacro].c_str() ); - btnMacro[iMacro % NUMMACKEYS]->redraw_label(); - } else { - btnMacro[(iMacro % NUMMACKEYS) + NUMMACKEYS]->label( macros.name[iMacro].c_str() ); - btnMacro[(iMacro % NUMMACKEYS) + NUMMACKEYS]->redraw_label(); - } - } else { - btnMacro[iMacro % NUMMACKEYS]->label( macros.name[iMacro].c_str() ); - btnMacro[iMacro % NUMMACKEYS]->redraw_label(); - } - - macros.changed = true; + update_macro_button(iMacro, macrotext->value(), labeltext->value()); } else if (iType == MACRO_EDIT_INPUT) iInput->value(macrotext->value()); } +void update_macro_button(int iMacro, const char *text, const char *name) +{ + macros.text[iMacro].assign(text); + macros.name[iMacro].assign(name); + + if (progdefaults.mbar_scheme > MACRO_SINGLE_BAR_MAX) { + if (iMacro < NUMMACKEYS) { + btnMacro[iMacro % NUMMACKEYS]->label( macros.name[iMacro].c_str() ); + btnMacro[iMacro % NUMMACKEYS]->redraw_label(); + } else { + btnMacro[(iMacro % NUMMACKEYS) + NUMMACKEYS]->label( macros.name[iMacro].c_str() ); + btnMacro[(iMacro % NUMMACKEYS) + NUMMACKEYS]->redraw_label(); + } + } else { + btnMacro[iMacro % NUMMACKEYS]->label( macros.name[iMacro].c_str() ); + btnMacro[iMacro % NUMMACKEYS]->redraw_label(); + } + + macros.changed = true; +} + void cbInsertMacro(Fl_Widget *, void *) { int nbr = macroDefs->value(); diff --git a/src/misc/util.cxx b/src/misc/util.cxx index 051571a6..6f884bd5 100644 --- a/src/misc/util.cxx +++ b/src/misc/util.cxx @@ -78,6 +78,15 @@ unsigned long ver2int(const char* version) return v; } +#if !HAVE_STRNLEN +size_t strnlen(const char* str, size_t len) +{ + size_t n = strlen(str); + if (n > len) n = len; + return n; +} +#endif + #if !HAVE_STRCASESTR # include // from git 1.6.1.2 compat/strcasestr.c diff --git a/src/misc/xmlrpc.cxx b/src/misc/xmlrpc.cxx index 2f3e537b..a44aac38 100644 --- a/src/misc/xmlrpc.cxx +++ b/src/misc/xmlrpc.cxx @@ -3035,8 +3035,6 @@ public: // ============================================================================= -extern Fl_Button* btnAutoSpot; // FIXME: export in fl_digi.h - class Spot_get_auto : public xmlrpc_c::method { public: diff --git a/src/rigcontrol/FreqControl.cxx b/src/rigcontrol/FreqControl.cxx index 93f7f0d1..d52c0672 100644 --- a/src/rigcontrol/FreqControl.cxx +++ b/src/rigcontrol/FreqControl.cxx @@ -130,7 +130,7 @@ cFreqControl::cFreqControl(int x, int y, int w, int h, const char *lbl): minVal = 0; double fmaxval = (pow(10, nD) - 1) * precision; - long int UMAX = (long int)(pow(2, 31) - 1); + long int UMAX = maximum(); if (fmaxval > UMAX) fmaxval = UMAX; maxVal = fmaxval; fmaxval /= 1000.0; @@ -153,7 +153,7 @@ cFreqControl::cFreqControl(int x, int y, int w, int h, const char *lbl): fcWidth, fcHeight, " "); - Digit[n]->box(FL_FLAT_BOX); + Digit[n]->box(FL_FLAT_BOX); Digit[n]->labelfont(font_number); Digit[n]->labelcolor(ONCOLOR); Digit[n]->color(OFFCOLOR, SELCOLOR); @@ -179,7 +179,7 @@ cFreqControl::cFreqControl(int x, int y, int w, int h, const char *lbl): fcWidth, fcHeight, " "); - Digit[n]->box(FL_FLAT_BOX); + Digit[n]->box(FL_FLAT_BOX); Digit[n]->labelfont(font_number); Digit[n]->labelcolor(ONCOLOR); Digit[n]->color(OFFCOLOR, SELCOLOR); @@ -273,7 +273,7 @@ void cFreqControl::SetONOFFCOLOR( Fl_Color ONcolor, Fl_Color OFFcolor) redraw(); } -void cFreqControl::SetONCOLOR (uchar r, uchar g, uchar b) +void cFreqControl::SetONCOLOR (uchar r, uchar g, uchar b) { ONCOLOR = fl_rgb_color (r, g, b); REVOFFCOLOR = ONCOLOR; @@ -299,7 +299,7 @@ void cFreqControl::SetONCOLOR (uchar r, uchar g, uchar b) redraw(); } -void cFreqControl::SetOFFCOLOR (uchar r, uchar g, uchar b) +void cFreqControl::SetOFFCOLOR (uchar r, uchar g, uchar b) { OFFCOLOR = fl_rgb_color (r, g, b); REVONCOLOR = OFFCOLOR; @@ -337,6 +337,12 @@ void cFreqControl::value(long lv) updatevalue(); } +long int cFreqControl::maximum(void) +{ + return (long int)(pow(2, 31) - 1); +} + + void cFreqControl::restore_colors() { enable_arrow_keys = false; @@ -626,7 +632,7 @@ void cFreqControl::set_ndigits(int nbr) fcWidth, fcHeight, " "); - Digit[n]->box(FL_FLAT_BOX); + Digit[n]->box(FL_FLAT_BOX); Digit[n]->labelfont(font_number); Digit[n]->labelcolor(ONCOLOR); Digit[n]->color(OFFCOLOR, SELCOLOR); @@ -654,7 +660,7 @@ void cFreqControl::set_ndigits(int nbr) fcWidth, fcHeight, " "); - Digit[n]->box(FL_FLAT_BOX); + Digit[n]->box(FL_FLAT_BOX); Digit[n]->labelfont(font_number); Digit[n]->labelcolor(ONCOLOR); Digit[n]->color(OFFCOLOR, SELCOLOR); diff --git a/src/rigcontrol/rigsupport.cxx b/src/rigcontrol/rigsupport.cxx index 46b40974..04f61edc 100644 --- a/src/rigcontrol/rigsupport.cxx +++ b/src/rigcontrol/rigsupport.cxx @@ -370,6 +370,20 @@ void qso_movFreq(Fl_Widget* w, void *data) return; } +void qso_selectFreq(long int rfcarrier, int carrier) +{ + if (rfcarrier > 0) { + qsoFreqDisp1->value(rfcarrier); + qsoFreqDisp2->value(rfcarrier); + qsoFreqDisp3->value(rfcarrier); + sendFreq(rfcarrier); + } + + if (carrier > 0) { + active_modem->set_freq(carrier); + } +} + void qso_selectFreq() { int n = qso_opBrowser->value(); @@ -397,6 +411,15 @@ void qso_selectFreq() } } +void qso_setFreq(long int f) +{ + // transceiver frequency + if (f > 0) { + qsoFreqDisp->value(f); + sendFreq(f); + } +} + void qso_setFreq() { int n = qso_opBrowser->value(); @@ -404,10 +427,7 @@ void qso_setFreq() n -= 1; // transceiver frequency - if (freqlist[n].rfcarrier > 0) { - qsoFreqDisp->value(freqlist[n].rfcarrier); - sendFreq(freqlist[n].rfcarrier); - } + qso_setFreq(freqlist[n].rfcarrier); } void qso_delFreq() diff --git a/src/rigcontrol/rigxml.cxx b/src/rigcontrol/rigxml.cxx index b053c366..944c7f37 100644 --- a/src/rigcontrol/rigxml.cxx +++ b/src/rigcontrol/rigxml.cxx @@ -150,7 +150,7 @@ TAGS rigdeftags[] = { {"value(fl_filename_name(p)); - rigCAT_close(); - readRigXML(); - rigCAT_defaults(); + loadRigXmlFile(); } } +void loadRigXmlFile(void) +{ + rigCAT_close(); + readRigXML(); + rigCAT_defaults(); +} diff --git a/src/soundcard/sound.cxx b/src/soundcard/sound.cxx index 6d2d85ae..fcaebba0 100644 --- a/src/soundcard/sound.cxx +++ b/src/soundcard/sound.cxx @@ -72,9 +72,16 @@ #include "qrunner.h" #include "icons.h" #include "macros.h" +#include "util.h" #include "estrings.h" +inline void trim_white_spaces(std::string &s) +{ + while (s[0] == ' ') s.erase(0,1); + while (s[s.length() -1] == ' ') s.erase(s.length() - 1); +} + #define SND_BUF_LEN 65536 #define SND_RW_LEN (8 * SND_BUF_LEN) // #define SRC_BUF_LEN (8*SND_BUF_LEN) @@ -422,7 +429,7 @@ void SoundBase::write_file(SNDFILE* file, double* buf, size_t count) bool SoundBase::format_supported(int format) { - SF_INFO info = { + SF_INFO info = { 0, sndfile_samplerate[progdefaults.wavSampleRate], SNDFILE_CHANNELS, @@ -1524,12 +1531,25 @@ long SoundPort::src_read_cb(void* arg, float** data) return vec[0].len / sd[0].params.channelCount; } -SoundPort::device_iterator SoundPort::name_to_device(const string& name, unsigned dir) +SoundPort::device_iterator SoundPort::name_to_device(std::string &name, unsigned dir) { device_iterator i; - for (i = devs.begin(); i != devs.end(); ++i) - if (name == (*i)->name && (dir ? (*i)->maxOutputChannels : (*i)->maxInputChannels)) + std::string device_name; + bool match_found = false; + + trim_white_spaces(name); + + for (i = devs.begin(); i != devs.end(); ++i) { + + device_name.assign((*i)->name); + trim_white_spaces(device_name); + + if(strncmp(device_name.c_str(), name.c_str(), 32) == 0) + match_found = true; + + if (match_found && (dir ? (*i)->maxOutputChannels : (*i)->maxInputChannels)) break; + } return i; } diff --git a/src/soundcard/soundconf.cxx b/src/soundcard/soundconf.cxx index 64129511..076dce7f 100644 --- a/src/soundcard/soundconf.cxx +++ b/src/soundcard/soundconf.cxx @@ -1,8 +1,9 @@ // ---------------------------------------------------------------------------- // soundconf.cxx // -// Copyright (C) 2008-2010 -// Stelios Bounanos, M0GLD +// Copyright (C) 2008-2010, Stelios Bounanos, M0GLD +// Copyright (C) 2014 David Freese, W1HKJ +// Copyright (C) 2015 Robert Stiles, KK5VD // // This file is part of fldigi. // @@ -29,6 +30,7 @@ #include #include +#include #if USE_OSS # include #endif @@ -39,13 +41,20 @@ #include "configuration.h" #include "confdialog.h" #include "debug.h" +#include "util.h" LOG_FILE_SOURCE(debug::LOG_AUDIO); using namespace std; +inline void trim_white_spaces(std::string &s) +{ + while (s[0] == ' ') s.erase(0,1); + while (s[s.length() -1] == ' ') s.erase(s.length() - 1); +} + double std_sample_rates[] = { 8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, - 32000.0, 44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1.0 }; + 32000.0, 44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1.0 }; static void init_oss(void) { @@ -70,13 +79,13 @@ struct padev { public: padev(const PaDeviceInfo* dev_, PaDeviceIndex idx_, PaHostApiTypeId api_) - : dev(dev_), idx(idx_), api(api_) { } + : dev(dev_), idx(idx_), api(api_) { } bool operator<(const padev& rhs) const { return pa_api_prio.find(api) != pa_api_prio.end() && - pa_api_prio.find(rhs.api) != pa_api_prio.end() && - pa_api_prio[api] < pa_api_prio[rhs.api]; + pa_api_prio.find(rhs.api) != pa_api_prio.end() && + pa_api_prio[api] < pa_api_prio[rhs.api]; } const PaDeviceInfo* dev; @@ -100,7 +109,7 @@ static PaDeviceIndex get_default_portaudio_device(int dir) goto ret_def; LOG_DEBUG("Default host API is %s, trying default ALSA %s device instead", - host_api->name, (dir == 0 ? "input" : "output")); + host_api->name, (dir == 0 ? "input" : "output")); api_idx = Pa_GetHostApiCount(); if (api_idx < 0) goto ret_def; @@ -124,7 +133,7 @@ static void init_portaudio(void) if (e.error() == ENODEV) // don't complain if there are no devices return; LOG_ERROR("%s", e.what()); - AudioPort->deactivate(); + AudioPort->deactivate(); btnAudioIO[SND_IDX_PORT]->deactivate(); if (progdefaults.btnAudioIOis == SND_IDX_PORT) progdefaults.btnAudioIOis = SND_IDX_NULL; @@ -148,14 +157,14 @@ static void init_portaudio(void) list devlist; for (SoundPort::device_iterator idev = SoundPort::devices().begin(); - idev != SoundPort::devices().end(); ++idev) + idev != SoundPort::devices().end(); ++idev) devlist.push_back( padev(*idev, idev - SoundPort::devices().begin(), - Pa_GetHostApiInfo((*idev)->hostApi)->type) ); + Pa_GetHostApiInfo((*idev)->hostApi)->type) ); devlist.sort(); PaHostApiTypeId first_api = devlist.begin()->api; for (list::const_iterator ilist = devlist.begin(); - ilist != devlist.end(); ilist++) { + ilist != devlist.end(); ilist++) { string menu_item; string::size_type i = 0; if (ilist->api != first_api) { // add a submenu @@ -169,12 +178,19 @@ static void init_portaudio(void) i += 2; } // add to menu - if (ilist->dev->maxInputChannels > 0) + if (ilist->dev->maxInputChannels > 0) { + trim_white_spaces(menu_item); + menu_item.assign(menu_item); menuPortInDev->add(menu_item.c_str(), 0, NULL, - reinterpret_cast(ilist->idx), 0); - if (ilist->dev->maxOutputChannels > 0) + reinterpret_cast(ilist->idx), 0); + } + + if (ilist->dev->maxOutputChannels > 0) { + trim_white_spaces(menu_item); + menu_item.assign(menu_item); menuPortOutDev->add(menu_item.c_str(), 0, NULL, - reinterpret_cast(ilist->idx), 0); + reinterpret_cast(ilist->idx), 0); + } } if (progdefaults.PortInDevice.length() == 0) { @@ -202,43 +218,41 @@ static void init_portaudio(void) } // select the correct menu items - - const Fl_Menu_Item* menu; - int size; - int idx; - - idx = -1; - menu = menuPortInDev->menu(); - size = menuPortInDev->size(); - for (int i = 0; i < size - 1; i++, menu++) { - if (menu->label() && progdefaults.PortInDevice == menu->label()) { - idx = i; // near match - if (reinterpret_cast(menu->user_data()) == progdefaults.PortInIndex || - progdefaults.PortInIndex == -1) // exact match, or index was never saved - break; - } - } - if (idx >= 0) { - menuPortInDev->value(idx); - menuPortInDev->set_changed(); - } - - idx = -1; - menu = menuPortOutDev->menu(); - size = menuPortOutDev->size(); - for (int i = 0; i < size - 1; i++, menu++) { - if (menu->label() && progdefaults.PortOutDevice == menu->label()) { - idx = i; - if (reinterpret_cast(menu->user_data()) == progdefaults.PortOutIndex || - progdefaults.PortOutIndex == -1) - break; - } - } - if (idx >= 0) { - menuPortOutDev->value(idx); - menuPortOutDev->set_changed(); - } + pa_set_dev(menuPortInDev, progdefaults.PortInDevice, progdefaults.PortInIndex); + pa_set_dev(menuPortOutDev, progdefaults.PortOutDevice, progdefaults.PortOutIndex); } + +int pa_set_dev(Fl_Choice *choice, std::string dev_name, int dev_index) +{ + const Fl_Menu_Item *menu = (Fl_Menu_Item *)0; + int size = 0; + int dev_found = PA_DEV_NOT_FOUND; + int idx = -1; + + if(!choice) return dev_found; + + menu = choice->menu(); + size = choice->size(); + + for (int i = 0; i < size - 1; i++, menu++) { + if (menu->label() && dev_name == menu->label()) { + idx = i; + dev_found = PA_DEV_FOUND; + if (reinterpret_cast(menu->user_data()) == dev_index || + dev_index == -1) { // exact match, or index was never saved + dev_found = PA_EXACT_DEV_FOUND; + } + } + } + + if (idx > 0) { + choice->value(idx); + choice->set_changed(); + } + + return dev_found; +} + #else static void init_portaudio(void) { } #endif // USE_PORTAUDIO @@ -271,9 +285,9 @@ int sample_rate_converters[FLDIGI_NUM_SRC] = { static void sound_init_options(void) { build_srate_listbox(menuInSampleRate, std_sample_rates, - sizeof(std_sample_rates)/sizeof(*std_sample_rates) - 1); + sizeof(std_sample_rates)/sizeof(*std_sample_rates) - 1); build_srate_listbox(menuOutSampleRate, std_sample_rates, - sizeof(std_sample_rates)/sizeof(*std_sample_rates) - 1); + sizeof(std_sample_rates)/sizeof(*std_sample_rates) - 1); for (int i = 0; i < FLDIGI_NUM_SRC; i++) menuSampleConverter->add(src_get_name(sample_rate_converters[i])); @@ -281,14 +295,14 @@ static void sound_init_options(void) if (progdefaults.sample_converter == SRC_ZERO_ORDER_HOLD) { progdefaults.sample_converter = SRC_LINEAR; LOG_WARN("The Zero Order Hold sample rate converter should not be used! " - "Your setting has been changed to Linear."); + "Your setting has been changed to Linear."); } #if defined(__ppc__) || defined(__powerpc__) || defined(__PPC__) // SRC_LINEAR may crash with 11025Hz modems. Change to SINC_FASTEST. if (progdefaults.sample_converter == SRC_LINEAR) { progdefaults.sample_converter = SRC_SINC_FASTEST; LOG_WARN("Linear sample rate converter may not work on this architecture. " - "Your setting has been changed to Fastest Sinc"); + "Your setting has been changed to Fastest Sinc"); } #endif for (int i = 0; i < FLDIGI_NUM_SRC; i++) { @@ -344,7 +358,7 @@ static void sound_init_options(void) # if PA_API_VERSION < 12 static inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x) { return x == PA_CONTEXT_CONNECTING || x == PA_CONTEXT_AUTHORIZING || - x == PA_CONTEXT_SETTING_NAME || x == PA_CONTEXT_READY; + x == PA_CONTEXT_SETTING_NAME || x == PA_CONTEXT_READY; } # endif @@ -360,7 +374,7 @@ static bool probe_pulseaudio(void) pa_context_state_t state; do { // iterate main loop until the context connection fails or becomes ready if (!(ok = (pa_mainloop_iterate(loop, 1, NULL) >= 0 && - PA_CONTEXT_IS_GOOD(state = pa_context_get_state(context))))) + PA_CONTEXT_IS_GOOD(state = pa_context_get_state(context))))) break; } while (state != PA_CONTEXT_READY); } @@ -383,7 +397,7 @@ void sound_init(void) init_portaudio(); -// set the Sound Card configuration tab to the correct initial values + // set the Sound Card configuration tab to the correct initial values #if !USE_OSS AudioOSS->deactivate(); btnAudioIO[SND_IDX_OSS]->deactivate(); @@ -397,7 +411,7 @@ void sound_init(void) btnAudioIO[SND_IDX_PULSE]->deactivate(); #endif if (progdefaults.btnAudioIOis == SND_IDX_UNKNOWN || - !btnAudioIO[progdefaults.btnAudioIOis]->active()) { // or saved sound api now disabled + !btnAudioIO[progdefaults.btnAudioIOis]->active()) { // or saved sound api now disabled int io[4] = { SND_IDX_PORT, SND_IDX_PULSE, SND_IDX_OSS, SND_IDX_NULL }; if (probe_pulseaudio()) { // prefer pulseaudio io[0] = SND_IDX_PULSE; @@ -443,20 +457,20 @@ void sound_update(unsigned idx) progdefaults.btnAudioIOis = idx; switch (idx) { #if USE_OSS - case SND_IDX_OSS: - menuOSSDev->activate(); - scDevice[0] = scDevice[1] = menuOSSDev->value(); - break; + case SND_IDX_OSS: + menuOSSDev->activate(); + scDevice[0] = scDevice[1] = menuOSSDev->value(); + break; #endif #if USE_PORTAUDIO - case SND_IDX_PORT: - menuPortInDev->activate(); - menuPortOutDev->activate(); - if (menuPortInDev->text()) - scDevice[0] = menuPortInDev->text(); - if (menuPortOutDev->text()) - scDevice[1] = menuPortOutDev->text(); + case SND_IDX_PORT: + menuPortInDev->activate(); + menuPortOutDev->activate(); + if (menuPortInDev->text()) + scDevice[0] = menuPortInDev->text(); + if (menuPortOutDev->text()) + scDevice[1] = menuPortOutDev->text(); { Fl_ListBox* listbox[2] = { menuInSampleRate, menuOutSampleRate }; @@ -465,43 +479,43 @@ void sound_update(unsigned idx) const vector& srates = SoundPort::get_supported_rates(scDevice[i], i); switch (srates.size()) { - case 0: // startup; no devices initialised yet - build_srate_listbox(listbox[i], std_sample_rates, - sizeof(std_sample_rates)/sizeof(*std_sample_rates) - 1); - break; - case 1: // default sample rate only, build menu with all std rates - build_srate_listbox(listbox[i], std_sample_rates, - sizeof(std_sample_rates)/sizeof(*std_sample_rates) - 1, srates[0]); - - break; - default: // first element is default sample rate, build menu with rest - build_srate_listbox(listbox[i], &srates[0] + 1, srates.size() - 1, srates[0]); - break; + case 0: // startup; no devices initialised yet + build_srate_listbox(listbox[i], std_sample_rates, + sizeof(std_sample_rates)/sizeof(*std_sample_rates) - 1); + break; + case 1: // default sample rate only, build menu with all std rates + build_srate_listbox(listbox[i], std_sample_rates, + sizeof(std_sample_rates)/sizeof(*std_sample_rates) - 1, srates[0]); + + break; + default: // first element is default sample rate, build menu with rest + build_srate_listbox(listbox[i], &srates[0] + 1, srates.size() - 1, srates[0]); + break; } - + for (int j = 0; j < listbox[i]->lsize(); j++) { listbox[i]->index(j); if (strstr(listbox[i]->value(), label)) break; } free(label); - + listbox[i]->activate(); } } - break; + break; #endif - + #if USE_PULSEAUDIO - case SND_IDX_PULSE: - inpPulseServer->activate(); - scDevice[0] = scDevice[1] = inpPulseServer->value(); - break; + case SND_IDX_PULSE: + inpPulseServer->activate(); + scDevice[0] = scDevice[1] = inpPulseServer->value(); + break; #endif - - case SND_IDX_NULL: - scDevice[0] = scDevice[1] = ""; - break; + + case SND_IDX_NULL: + scDevice[0] = scDevice[1] = ""; + break; }; } diff --git a/src/waterfall/waterfall.cxx b/src/waterfall/waterfall.cxx index bb4e66b8..363b2753 100644 --- a/src/waterfall/waterfall.cxx +++ b/src/waterfall/waterfall.cxx @@ -1772,7 +1772,7 @@ int waterfall::handle(int event) // as above; handle wheel events for the macro bar extern void altmacro_cb(Fl_Widget *w, void *v); if (progdefaults.macro_wheel) { - if (progdefaults.mbar_scheme > 2) { + if (progdefaults.mbar_scheme > MACRO_SINGLE_BAR_MAX) { if (Fl::event_inside(macroFrame2)) { altmacro_cb(btnAltMacros2, reinterpret_cast(d)); return 1; diff --git a/src/widgets/FTextRXTX.cxx b/src/widgets/FTextRXTX.cxx index 0061386d..41bab824 100644 --- a/src/widgets/FTextRXTX.cxx +++ b/src/widgets/FTextRXTX.cxx @@ -337,7 +337,7 @@ void FTextRX::add(unsigned int c, int attr) } // test for bottom of text visibility - if (// !mFastDisplay && + if (// !mFastDisplay && (mVScrollBar->value() >= mNBufferLines - mNVisibleLines + mVScrollBar->linesize() - 1)) show_insert_position(); } @@ -959,15 +959,15 @@ int FTextTX::handle_key_shortcuts(int key) default: break; } - + // Add text + space if length is > 0 if (etag.length()) add_text(etag + std::string(" ")); - + return 1; } break; - + default: break; } @@ -1031,7 +1031,7 @@ int FTextTX::handle_key(int key) else if (!(Fl::event_state() & (FL_META | FL_ALT))) break; // fall through to (un)pause for M-r or A-r - + case FL_Pause: if (trx_state != STATE_TX) { start_tx(); @@ -1106,7 +1106,7 @@ int FTextTX::handle_key(int key) if (Fl::event_state() & FL_ALT) { static char lbl[2] = "1"; altMacros = key - '1'; - if (progdefaults.mbar_scheme > 2) { + if (progdefaults.mbar_scheme > MACRO_SINGLE_BAR_MAX) { if (!altMacros) altMacros = 1; for (int i = 0; i < NUMMACKEYS; i++) { btnMacro[NUMMACKEYS + i]->label( @@ -1164,7 +1164,7 @@ int FTextTX::handle_key_macro(int key) if (key > 11) return 0; - if (progdefaults.mbar_scheme > 2) { + if (progdefaults.mbar_scheme > MACRO_SINGLE_BAR_MAX) { if (Fl::event_state(FL_SHIFT)) key += altMacros * NUMMACKEYS; } else {