diff --git a/ChangeLog b/ChangeLog index adfcaf6e..c0b5271f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -28,6 +28,8 @@ Change Log: 14) New sound callback code implementation. 15) Two-colour squelch button shows Yellow Squelch enabled but not open, Light Green enabled and open. + 16) Experimental RTTY mark/space cross hair display using mark / space + filters. 2.10.3) 1) Corrected memory leak bug. diff --git a/INSTALL b/INSTALL index 02da7c1a..e5535e45 100644 --- a/INSTALL +++ b/INSTALL @@ -13,7 +13,7 @@ To compile fldigi you will need: * The samplerate (a.k.a. secret rabbit code) library. - * The Independent JPEG Group's JPEG library. + * The Independent JPEG Group's JPEG library, or the PNG library. You should also install the libraries and headers for PortAudio, the Portable audio I/O library. diff --git a/configure.ac b/configure.ac index f1471541..d2239ac9 100644 --- a/configure.ac +++ b/configure.ac @@ -9,7 +9,7 @@ dnl major and minor must be integers; patch may dnl contain other characters or be empty m4_define(FLDIGI_MAJOR, [2]) m4_define(FLDIGI_MINOR, [11]) -m4_define(FLDIGI_PATCH, [O]) +m4_define(FLDIGI_PATCH, [P]) AC_INIT([fldigi], FLDIGI_MAJOR.FLDIGI_MINOR[FLDIGI_PATCH], [w1hkj AT w1hkj DOT com]) @@ -49,7 +49,7 @@ AC_PROG_CC # Checks for header files. AC_HEADER_STDC AC_HEADER_DIRENT -AC_CHECK_HEADERS([arpa/inet.h execinfo.h fcntl.h jpeglib.h limits.h memory.h netdb.h netinet/in.h regex.h stdint.h stdlib.h string.h strings.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h termios.h unistd.h values.h]) +AC_CHECK_HEADERS([arpa/inet.h execinfo.h fcntl.h limits.h memory.h netdb.h netinet/in.h regex.h stdint.h stdlib.h string.h strings.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h termios.h unistd.h values.h]) # Checks for typedefs, structures, and compiler characteristics. AC_HEADER_STDBOOL @@ -135,11 +135,23 @@ AC_FLDIGI_BIND # Set HAVE_FLUID Makefile conditional AC_FLDIGI_FLTK -### JPEG -# Test if we can compile a program that includes jpeglib.h -# and link it with the FLTK flags set above. -# Set ac_cv_have_jpeg to yes/no -AC_FLDIGI_FLTK_JPEG +### Image libraries +# JPEG: +# Test if we can compile a program that includes jpeglib.h +# and link it either using the FLTK flags set above, or +# with -ljpeg. +# Set ac_cv_libjpeg to yes/no +# Define LIBJPEG_CFLAGS and LIBJPEG_CFLAGS and add them to +# IMAGE_CFLAGS and IMAGE_LIBS. +# Define USE_LIBJPEG in config.h +# PNG: +# Check with the AC_FLDIGI_PKG_CHECK macro +# Set ac_cv_libpng to yes/no +# Define LIBJPEG_CFLAGS and LIBJPEG_CFLAGS and add them to +# IMAGE_CFLAGS and IMAGE_LIBS. +# Define USE_LIBPNG in config.h +# Substitute IMAGE_CFLAGS and IMAGE_LIBS in Makefile +AC_FLDIGI_IMAGES ### OSS # Set ac_cv_oss to yes/no @@ -150,27 +162,27 @@ AC_FLDIGI_OSS # Set ac_cv_samplerate to yes/no (not used because we require samplerate) # Define USE_SAMPLERATE in config.h (as above) # Substitute SAMPLERATE_CFLAGS and SAMPLERATE_LIBS in Makefile -AC_FLDIGI_PKG_CHECK([samplerate], [samplerate >= 0.1.1], [], [], [SAMPLERATE], []) +AC_FLDIGI_PKG_CHECK([samplerate], [samplerate >= 0.1.1], [no], [no]) ### libsndfile # Set ac_cv_sndfile to yes/no # Define USE_SNDFILE in config.h # Substitute SNDFILE_CFLAGS and SNDFILE_LIBS in Makefile -AC_FLDIGI_PKG_CHECK([sndfile], [sndfile >= 1.0.10], [yes], [with], [SNDFILE], +AC_FLDIGI_PKG_CHECK([sndfile], [sndfile >= 1.0.10], [yes], [yes], [enable reading/writing of audio files via libsndfile @<:@autodetect@:>@] ) ### portaudio # Set ac_cv_portaudio to yes/no # Define USE_PORTAUDIO in config.h # Substitute PORTAUDIO_CFLAGS and PORTAUDIO_LIBS in Makefile -AC_FLDIGI_PKG_CHECK([portaudio], [portaudio-2.0 >= 19], [yes], [with], [PORTAUDIO], +AC_FLDIGI_PKG_CHECK([portaudio], [portaudio-2.0 >= 19], [yes], [yes], [enable support for PortAudio @<:@autodetect@:>@] ) ### pulseaudio # Set ac_cv_pulseaudio to yes/no # Define USE_PULSEAUDIO in config.h # Substitute PULSEAUDIO_CFLAGS and PULSEAUDIO_LIBS in Makefile -AC_FLDIGI_PKG_CHECK([pulseaudio], [libpulse-simple >= 0.9.7], [yes], [with], [PULSEAUDIO], +AC_FLDIGI_PKG_CHECK([pulseaudio], [libpulse-simple >= 0.9.7], [yes], [yes], [enable support for PulseAudio @<:@autodetect@:>@] ) if test "x$ac_cv_oss" = "xno" && \ @@ -184,7 +196,7 @@ fi # Define USE_HAMLIB in config.h # Substitute HAMLIB_CFLAGS and HAMLIB_LIBS in Makefile # Set ENABLE_HAMLIB Makefile conditional -AC_FLDIGI_PKG_CHECK([hamlib], [hamlib >= 1.2.4], [yes], [with], [HAMLIB], +AC_FLDIGI_PKG_CHECK([hamlib], [hamlib >= 1.2.4], [yes], [yes], [use hamradio control libraries @<:@autodetect@:>@], [ENABLE_HAMLIB]) @@ -209,7 +221,7 @@ Configuration summary: Version ............................. $VERSION Static linking ...................... $ac_cv_static - Optimizations ....................... $ac_cv_opt + CPU optimizations ................... $ac_cv_opt Debugging ........................... $ac_cv_debug sndfile ............................. $ac_cv_sndfile diff --git a/m4/images.m4 b/m4/images.m4 new file mode 100644 index 00000000..b23302ae --- /dev/null +++ b/m4/images.m4 @@ -0,0 +1,125 @@ +AC_DEFUN([AC_FLDIGI_JPEG_HDR], [ + CXXFLAGS_saved="$CXXFLAGS" + m4_ifval([$1], [CXXFLAGS="$CXXFLAGS $1"], [:]) + AC_CHECK_HEADER([jpeglib.h]) + CXXFLAGS="$CXXFLAGS_saved" +]) + +AC_DEFUN([AC_FLDIGI_JPEG_LIB], [ + CXXFLAGS_saved="$CXXFLAGS" + LDFLAGS_saved="$LDFLAGS" + m4_ifval([$1], [CXXFLAGS="$CXXFLAGS $1"], [:]) + m4_ifval([$2], [LDFLAGS="$LDFLAGS $2"], [:]) + AC_LANG_PUSH(C++) + AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#include + #include + struct jpeg_compress_struct cinfo;]], + [] ) + ], + [ac_cv_libjpeg=yes], [ac_cv_libjpeg=no] ) + AC_LANG_POP(C++) + CXXFLAGS="$CXXFLAGS_saved" + LDFLAGS="$LDFLAGS_saved" +]) + +AC_DEFUN([AC_FLDIGI_JPEG], [ + AC_ARG_VAR([LIBJPEG_CFLAGS], [C compiler flags for JPEG]) + AC_ARG_VAR([LIBJPEG_LIBS], [linker flags for JPEG]) + + AC_FLDIGI_JPEG_HDR([$LIBJPEG_CFLAGS]) + if test "x$ac_cv_header_jpeglib_h" != "xyes"; then + ac_cv_libjpeg=no + else + AC_MSG_CHECKING([for libjpeg]) + if test "x$LIBJPEG_CFLAGS" != "x" || test "x$LIBJPEG_LIBS" != "x"; then + AC_FLDIGI_JPEG_LIB([$LIBJPEG_CFLAGS], [$LIBJPEG_LIBS]) + else + AC_FLDIGI_JPEG_LIB([$FLTK_CFLAGS], [$FLTK_LIBS]) + if test "x$ac_cv_libjpeg" != "xyes"; then + LIBJPEG_LIBS="-ljpeg" + AC_FLDIGI_JPEG_LIB([$LIBJPEG_CFLAGS], [$LIBJPEG_LIBS]) + fi + fi + AC_MSG_RESULT([$ac_cv_libjpeg]) + fi + if test "x$ac_cv_libjpeg" = "xyes"; then + AC_DEFINE([USE_LIBJPEG], 1, [Define to 1 if we are using libjpeg]) + else + AC_DEFINE([USE_LIBJPEG], 0, [Define to 1 if we are using libjpeg]) + fi +]) + + +AC_DEFUN([AC_FLDIGI_PNG_HDR], [ + CXXFLAGS_saved="$CXXFLAGS" + m4_ifval([$1], [CXXFLAGS="$CXXFLAGS $1"], [:]) + AC_CHECK_HEADER([png.h]) + CXXFLAGS="$CXXFLAGS_saved" +]) + +AC_DEFUN([AC_FLDIGI_PNG_LIB], [ + CXXFLAGS_saved="$CXXFLAGS" + LDFLAGS_saved="$LDFLAGS" + m4_ifval([$1], [CXXFLAGS="$CXXFLAGS $1"], [:]) + m4_ifval([$2], [LDFLAGS="$LDFLAGS $2"], [:]) + AC_LANG_PUSH(C++) + AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#include + png_structp png = png_create_write_struct(0, 0, 0, 0);]], + [] ) + ], + [ac_cv_libpng=yes], [ac_cv_libpng=no] ) + AC_LANG_POP(C++) + CXXFLAGS="$CXXFLAGS_saved" + LDFLAGS="$LDFLAGS_saved" +]) + +AC_DEFUN([AC_FLDIGI_PNG], [ + AC_ARG_VAR([LIBPNG_CFLAGS], [C compiler flags for PNG]) + AC_ARG_VAR([LIBPNG_LIBS], [linker flags for PNG]) + + if test "x$LIBPNG_CFLAGS" != "x" || test "x$LIBPNG_LIBS" != "x"; then + AC_FLDIGI_PKG_CHECK([libpng], [libpng >= 1.2.8], [no], [yes]) + else + AC_FLDIGI_PNG_HDR([$LIBPNG_CFLAGS]) + if test "x$ac_cv_header_png_h" != "xyes"; then + AC_FLDIGI_PKG_CHECK([libpng], [libpng >= 1.2.8], [no], [yes]) + else + AC_MSG_CHECKING([for libpng in fltk libs]) + AC_FLDIGI_PNG_LIB([$FLTK_CFLAGS], [$FLTK_LIBS]) + AC_MSG_RESULT([$ac_cv_libpng]) + if test "x$ac_cv_libpng" != "xyes"; then + AC_FLDIGI_PKG_CHECK([libpng], [libpng >= 1.2.8], [no], [yes]) + fi + fi + fi + + if test "x$ac_cv_libpng" = "xyes"; then + AC_DEFINE([USE_LIBPNG], 1, [Define to 1 if we are using libpng]) + else + AC_DEFINE([USE_LIBPNG], 0, [Define to 1 if we are using libpng]) + fi +]) + + +AC_DEFUN([AC_FLDIGI_IMAGES], [ + AC_REQUIRE([AC_FLDIGI_FLTK]) + + AC_FLDIGI_JPEG + if test "x$ac_cv_libjpeg" = "xyes"; then + IMAGE_CFLAGS="$IMAGE_CFLAGS $LIBJPEG_CFLAGS" + IMAGE_LIBS="$IMAGE_LIBS $LIBJPEG_LIBS" + fi + + AC_FLDIGI_PNG + if test "x$ac_cv_libpng" = "xyes"; then + IMAGE_CFLAGS="$IMAGE_CFLAGS $LIBPNG_CFLAGS" + IMAGE_LIBS="$IMAGE_LIBS $LIBPNG_LIBS" + fi + + if test "x$ac_cv_libjpeg" != "xyes" && test "x$ac_cv_libpng" != "xyes"; then + AC_MSG_WARN([No image libraries were found]) + fi + + AC_SUBST([IMAGE_CFLAGS]) + AC_SUBST([IMAGE_LIBS]) +]) diff --git a/m4/jpeg.m4 b/m4/jpeg.m4 deleted file mode 100644 index 38db48b1..00000000 --- a/m4/jpeg.m4 +++ /dev/null @@ -1,32 +0,0 @@ -AC_DEFUN([AC_FLDIGI_FLTK_JPEG], [ - AC_REQUIRE([AC_FLDIGI_FLTK]) - if test "x$ac_cv_header_jpeglib_h" != "xyes"; then - AC_MSG_ERROR([ - *** The jpeglib.h header could not be found. Please install the development - *** headers and libraries for JPEG.]) - fi - - AC_MSG_CHECKING([whether we have a working libjpeg]) - CXXFLAGS_saved="$CXXFLAGS" - LDFLAGS_saved="$LDFLAGS" - CXXFLAGS="$CXXFLAGS $FLTK_CFLAGS" - LDFLAGS="$LDFLAGS $FLTK_LIBS" - AC_LANG_PUSH(C++) - AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#include - #include - struct jpeg_compress_struct cinfo;]], - [] ) - ], - [ac_cv_have_jpeg=yes], [ac_cv_have_jpeg=no] ) - AC_LANG_POP(C++) - CXXFLAGS="$CXXFLAGS_saved" - LDFLAGS="$LDFLAGS_saved" - AC_MSG_RESULT([$ac_cv_have_jpeg]) - - if test "x$ac_cv_have_jpeg" != "xyes"; then - AC_MSG_FAILURE([ - *** A test jpeg program could not be linked using the FLTK linker flags, - *** even though jpeglib.h is present. Please report this error to - *** ${PACKAGE_BUGREPORT}, including any relevant output from config.log.]) - fi -]) diff --git a/m4/pkg-config.m4 b/m4/pkg-config.m4 index ec591f34..082b9a97 100644 --- a/m4/pkg-config.m4 +++ b/m4/pkg-config.m4 @@ -1,41 +1,43 @@ -# name, version, optional?, opt-prefix, subst-var-prefix, help-text, [am-cond] +# name, version, show-in-help?, optional?, help-text, [am-cond] AC_DEFUN([AC_FLDIGI_PKG_CHECK], [ -m4_ifval([$3], - [ AC_ARG_WITH($1, AC_HELP_STRING([--[]$4-[]$1], [$6]), +m4_define([PKG_NAME_UC], m4_translit([$1], [a-z], [A-Z])) + +m4_if([$3], [yes], + [ AC_ARG_WITH($1, AC_HELP_STRING([--with-[]$1], [$5]), [case "${withval}" in yes|no) ac_cv_want_[]$1="${withval}" ;; - *) AC_MSG_ERROR([bad value "${withval}" for --[]$4-[]$1]) ;; + *) AC_MSG_ERROR([bad value "${withval}" for --with-[]$1]) ;; esac], [ac_cv_want_[]$1=check]) - ], - [ac_cv_want_[]$1=yes] ) + ]) +m4_if([$4], [yes], [ac_cv_want_[]$1=check], [ac_cv_want_[]$1=yes]) if test "x$ac_cv_want_[]$1" = "xno"; then - AC_DEFINE([USE_][$5], 0) + AC_DEFINE([USE_]PKG_NAME_UC, 0) ac_cv_[]$1=no else PKG_CHECK_EXISTS([$2], ac_cv_[]$1=yes, ac_cv_[]$1=no) if test "x$ac_cv_want_[]$1" = "xcheck"; then - PKG_CHECK_MODULES([$5], [$2], [:], [:]) + PKG_CHECK_MODULES(PKG_NAME_UC, [$2], [:], [:]) if test "x$ac_cv_[]$1" = "xyes"; then - AC_DEFINE([USE_][$5], 1, [Define to 1 if we are using [$1]]) + AC_DEFINE([USE_]PKG_NAME_UC, 1, [Define to 1 if we are using $1]) else - AC_DEFINE([USE_][$5], 0, [Define to 1 if we are using [$1]]) + AC_DEFINE([USE_]PKG_NAME_UC, 0, [Define to 1 if we are using $1]) fi else # $ac_cv_want_[]$1 is yes if test "x$ac_cv_[]$1" = "xno"; then if test "x$3" = "xyes"; then - AC_MSG_NOTICE([--[]$4-[]$1 was given, but test for [$1] failed]) + AC_MSG_NOTICE([--with-[]$1 was given, but test for $1 failed]) fi else - AC_DEFINE([USE_][$5], 1, [Define to 1 if we are using [$1]]) + AC_DEFINE([USE_]PKG_NAME_UC, 1, [Define to 1 if we are using $1]) fi - PKG_CHECK_MODULES([$5], [$2]) # for the error message + PKG_CHECK_MODULES(PKG_NAME_UC, $2) # for the error message fi fi -AC_SUBST([$5][_CFLAGS]) -AC_SUBST([$5][_LIBS]) +AC_SUBST(PKG_NAME_UC[_CFLAGS]) +AC_SUBST(PKG_NAME_UC[_LIBS]) -m4_ifval([$7], [ AM_CONDITIONAL([$7], [test "x$ac_cv_[]$1" = "xyes"]) ], [:]) +m4_ifval([$6], [ AM_CONDITIONAL([$6], [test "x$ac_cv_[]$1" = "xyes"]) ], [:]) ]) diff --git a/src/Makefile.am b/src/Makefile.am index d0f9a90f..9368d8b4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,14 +8,14 @@ AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/include -I$(srcdir)/irrxml -Ifileselector AM_CXXFLAGS = @PORTAUDIO_CFLAGS@ @FLTK_CFLAGS@ @SNDFILE_CFLAGS@ \ @SAMPLERATE_CFLAGS@ @PULSEAUDIO_CFLAGS@ @HAMLIB_CFLAGS@ \ - @MAC_UNIVERSAL_CFLAGS@ \ + @IMAGE_CFLAGS@ @MAC_UNIVERSAL_CFLAGS@ \ -pipe -Wall -fexceptions @OPT_CFLAGS@ @DEBUG_CFLAGS@ AM_CFLAGS = $(AM_CXXFLAGS) AM_LDFLAGS = @MAC_UNIVERSAL_LDFLAGS@ LDADD = @PORTAUDIO_LIBS@ @BOOST_LDFLAGS@ @FLTK_LIBS@ @SNDFILE_LIBS@ \ - @SAMPLERATE_LIBS@ @PULSEAUDIO_LIBS@ @HAMLIB_LIBS@ @RTLIB@ + @SAMPLERATE_LIBS@ @PULSEAUDIO_LIBS@ @HAMLIB_LIBS@ @IMAGE_LIBS@ @RTLIB@ HAMLIB_SRC = include/hamlib.h rigcontrol/hamlib.cxx include/rigclass.h rigcontrol/rigclass.cxx diff --git a/src/cw_rtty/rtty.cxx b/src/cw_rtty/rtty.cxx index f73c36dd..6b6aaa63 100644 --- a/src/cw_rtty/rtty.cxx +++ b/src/cw_rtty/rtty.cxx @@ -82,6 +82,9 @@ rtty::~rtty() if (hilbert) delete hilbert; // if (wfid) delete wfid; if (bitfilt) delete bitfilt; + if (markfilt) delete markfilt; + if (spacefilt) delete spacefilt; + if (bpfilt) delete bpfilt; } void rtty::restart() @@ -111,14 +114,19 @@ void rtty::restart() symbollen = (int) (samplerate / rtty_baud + 0.5); set_bandwidth(shift); - fhi = (shift / 2 + rtty_baud * 1.1) / samplerate; - flo = (shift / 2 - rtty_baud * 1.1) / samplerate; - + fhi = (shift / 2 + rtty_baud* 1.1) / samplerate; + flo = (shift / 2 - rtty_baud* 1.1) / samplerate; if (bpfilt) bpfilt->create_filter(flo, fhi); else bpfilt = new fftfilt(flo, fhi, 1024); + f1 = 0.0 * rtty_baud / samplerate; + f2 = 1.0 * rtty_baud / samplerate; + + if (!markfilt) markfilt = new fftfilt(f1, f2, 1024); + if (!spacefilt) spacefilt = new fftfilt(f1, f2, 1024); + if (bitfilt) bitfilt->setLength(symbollen / 4);//6); else @@ -143,6 +151,10 @@ void rtty::restart() snprintf(msg2, sizeof(msg2), "Baud %-4.1f", rtty_baud); put_Status2(msg2); put_MODEstatus(mode); + for (int i = 0; i < 1024; i++) QI[i].re = QI[i].im = 0.0; + QIptr = 0; + markphase = spacephase = 0.0; + marksig = spacesig = 0.0; } rtty::rtty(trx_mode tty_mode) @@ -153,6 +165,9 @@ rtty::rtty(trx_mode tty_mode) fragmentsize = 256; bpfilt = (fftfilt *)0; +// markfilt = (fftfilt *)0; +// spacefilt = (fftfilt *)0; + bitfilt = (Cmovavg *)0; hilbert = new C_FIR_filter(); @@ -163,12 +178,11 @@ rtty::rtty(trx_mode tty_mode) void rtty::update_syncscope() { - double data[RTTYMaxSymLen]; + double data[2*symbollen]; int i; - - for (i = 0; i < symbollen; i++) + for (i = 0; i < 2*symbollen; i++) data[i] = pipe[i]; - set_scope(data, symbollen, false); + set_scope(data, 2*symbollen, false); } void rtty::clear_syncscope() @@ -192,6 +206,35 @@ complex rtty::mixer(complex in) return z; } +void rtty::MarkSpace(complex in) +{ + complex z, zm, zs, *zmp, *zsp; + + z.re = cos(markphase); + z.im = sin(markphase); + zm = z * in; + markphase -= twopi * (frequency - (shift + rtty_baud) / 2.0) / samplerate; + if (markphase > M_PI) markphase -= twopi; + if (markphase < M_PI) markphase += twopi; + + z.re = cos(spacephase); + z.im = sin(spacephase); + zs = z * in; + spacephase -= twopi * (frequency + (shift + rtty_baud) / 2.0) / samplerate; + if (spacephase > M_PI) spacephase -= twopi; + if (spacephase < M_PI) spacephase += twopi; + + int n = markfilt->run(zm, &zmp); + spacefilt->run(zs, &zsp); + if (n) { + for (int i = 0; i < n; i++) { + QI[i].re = zmp[i].re; + QI[i].im = zsp[i].re; + } + set_zdata(QI, n); + } +} + unsigned char rtty::bitreverse(unsigned char in, int n) { unsigned char out = 0; @@ -397,6 +440,8 @@ int rtty::rx_process(const double *buf, int len) z.re = z.im = *buf++; hilbert->run(z, z); + + MarkSpace(z); // mix it with the audio carrier frequency to create a baseband signal @@ -413,7 +458,7 @@ int rtty::rx_process(const double *buf, int len) fin = (prevsmpl % zp[i]).arg() * samplerate / twopi; prevsmpl = zp[i]; - + // filter the result with a moving average filter f = bitfilt->run(fin); @@ -440,7 +485,7 @@ int rtty::rx_process(const double *buf, int len) if (--dspcnt % (nbits + 2) == 0) { pipe[pipeptr] = f / shift; // display filtered signal - pipeptr = (pipeptr + 1) % symbollen; + pipeptr = (pipeptr + 1) % (2*symbollen); } if (!progdefaults.RTTY_USB) diff --git a/src/dialogs/Viewer.cxx b/src/dialogs/Viewer.cxx index bbe2c964..e8e3e8db 100644 --- a/src/dialogs/Viewer.cxx +++ b/src/dialogs/Viewer.cxx @@ -107,26 +107,6 @@ bool re_find(const char* haystack) { return seek_re && !regexec(seek_re, haystack, 0, 0, REG_NOTBOL | REG_NOTEOL); } -#if !HAVE_STRCASESTR -// a simple inefficient implementation of strcasestr -char* strcasestr(const char* haystack, const char* needle) -{ - char *h = NULL, *n = NULL, *p; - if ((h = strdup(haystack)) == NULL || (n = strdup(needle)) == NULL) { - free(h); - free(n); - return NULL; - } - for (p = h; *p; p++) - *p = tolower(*p); - for (p = n; *p; p++) - *p = tolower(*p); - p = strstr(h, n); - free(h); - free(n); - return p; -} -#endif // !HAVE_STRCASESTR #endif // HAVE_REGEX_H void pskBrowser::resize(int x, int y, int w, int h) { @@ -302,8 +282,8 @@ static void cb_brwsViewer(Fl_Hold_Browser*, void*) { switch (Fl::event_button()) { case FL_LEFT_MOUSE: - ReceiveText->addchr('\n', ReceiveWidget::ALTR); - ReceiveText->addstr(bwsrline[sel - 1].c_str(), ReceiveWidget::ALTR); + ReceiveText->addchr('\n', FTextBase::ALTR); + ReceiveText->addstr(bwsrline[sel - 1].c_str(), FTextBase::ALTR); active_modem->set_freq(brwsFreq[sel - 1]); break; case FL_MIDDLE_MOUSE: // copy from modem diff --git a/src/dialogs/confdialog.cxx b/src/dialogs/confdialog.cxx index 80bb03ef..ed34369b 100644 --- a/src/dialogs/confdialog.cxx +++ b/src/dialogs/confdialog.cxx @@ -760,13 +760,6 @@ static void cb_btnStartAtSweetSpot(Fl_Check_Button* o, void*) { progdefaults.changed = true; } -Fl_Check_Button *btntextwidgets=(Fl_Check_Button *)0; - -static void cb_btntextwidgets(Fl_Check_Button* o, void*) { - progdefaults.alt_text_widgets = o->value(); -progdefaults.changed = true; -} - Fl_Group *tabModems=(Fl_Group *)0; Fl_Tabs *tabsModems=(Fl_Tabs *)0; @@ -1850,19 +1843,12 @@ l with your sound hardware."); } o->end(); } - { Fl_Check_Button* o = btntextwidgets = new Fl_Check_Button(50, 155, 180, 20, "Alternative text widgets"); - o->tooltip("These widgets have full editing support but are slower.\nThis option takes ef\ -fect after a restart."); - o->down_box(FL_DOWN_BOX); - o->value(1); - o->callback((Fl_Callback*)cb_btntextwidgets); - o->hide(); - } o->end(); } { Fl_Group* o = tabModems = new Fl_Group(0, 25, 401, 195, "Modem"); o->color((Fl_Color)51); o->selection_color((Fl_Color)51); + o->hide(); { Fl_Tabs* o = tabsModems = new Fl_Tabs(0, 25, 401, 195); o->color((Fl_Color)51); o->selection_color((Fl_Color)10); diff --git a/src/dialogs/confdialog.fl b/src/dialogs/confdialog.fl index e097cbcc..c03bf9b9 100644 --- a/src/dialogs/confdialog.fl +++ b/src/dialogs/confdialog.fl @@ -902,13 +902,6 @@ progdefaults.changed = true;} code0 {o->value(progdefaults.StartAtSweetSpot);} } } - Fl_Check_Button btntextwidgets { - label {Alternative text widgets} - callback {progdefaults.alt_text_widgets = o->value(); -progdefaults.changed = true;} - tooltip {These widgets have full editing support but are slower. -This option takes effect after a restart.} xywh {50 155 180 20} down_box DOWN_BOX value 1 hide - } } Fl_Group tabModems { label Modem open diff --git a/src/dialogs/fl_digi.cxx b/src/dialogs/fl_digi.cxx index ee1d11f0..cbe3877b 100644 --- a/src/dialogs/fl_digi.cxx +++ b/src/dialogs/fl_digi.cxx @@ -107,12 +107,11 @@ MixerBase* mixer = 0; bool useCheckButtons = false; bool twoscopes = false; + Fl_Button *btnTune = (Fl_Button *)0; -Fl_Tile_check *TiledGroup = 0; -ReceiveWidget *ReceiveText = 0; -TransmitWidget *TransmitText = 0; -Fl_Text_Buffer *rcvBuffer = (Fl_Text_Buffer *)0; -Fl_Text_Buffer *xmtBuffer = (Fl_Text_Buffer *)0; +Fl_Tile_check *TiledGroup = 0; +FTextView *ReceiveText = 0; +FTextEdit *TransmitText = 0; Raster *FHdisp; Fl_Box *StatusBar = (Fl_Box *)0; Fl_Box *Status2 = (Fl_Box *)0; @@ -248,11 +247,11 @@ void startup_modem(modem *m) m == feld_FMmodem || m == feld_FM105modem || m == feld_80modem ) { - ReceiveText->Hide(); + ReceiveText->hide(); FHdisp->show(); sldrHellBW->value(m->get_bandwidth()); } else { - ReceiveText->Show(); + ReceiveText->show(); FHdisp->hide(); } FL_UNLOCK_D(); @@ -1652,6 +1651,14 @@ void set_video(double *data, int len) wfscope->video(data, len); } +void set_zdata(complex *zarray, int len) +{ + if (digiscope) + digiscope->zdata(zarray, len); + if (wfscope) + digiscope->zdata(zarray, len); +} + Fl_Menu_Item *mnuLogging = (Fl_Menu_Item *)0; void put_rx_char(unsigned int data) @@ -1671,21 +1678,21 @@ void put_rx_char(unsigned int data) active_modem->get_mode() == MODE_CW) asc = ascii; - int style = ReceiveWidget::RECV; + int style = FTextBase::RECV; if (asc == ascii2 && iscntrl(data)) - style = ReceiveWidget::CTRL; + style = FTextBase::CTRL; if (wf->tmp_carrier()) - style = ReceiveWidget::ALTR; + style = FTextBase::ALTR; switch (data) { case '\n': if (last == '\r') break; case '\r': - REQ(&ReceiveWidget::addchr, ReceiveText, '\n', style); + REQ(&FTextBase::addchr, ReceiveText, '\n', style); break; default: - REQ(&ReceiveWidget::addchr, ReceiveText, data, style); + REQ(&FTextBase::addchr, ReceiveText, data, style); } last = data; @@ -1848,7 +1855,7 @@ int get_tx_char(void) case 'r': case 'R': if (state != STATE_CTRL) break; - REQ_SYNC(&TransmitWidget::clear_sent, TransmitText); + REQ_SYNC(&FTextEdit::clear_sent, TransmitText); state = STATE_CHAR; c = 3; // ETX break; @@ -1882,10 +1889,10 @@ void put_echo_char(unsigned int data) last = data; - int style = ReceiveWidget::XMIT; + int style = FTextBase::XMIT; if (asc == ascii2 && iscntrl(data)) - style = ReceiveWidget::CTRL; - REQ(&ReceiveWidget::addchr, ReceiveText, data, style); + style = FTextBase::CTRL; + REQ(&FTextBase::addchr, ReceiveText, data, style); string s = iscntrl(data) ? ascii2[data & 0x7F] : string(1, data); if (Maillogfile) diff --git a/src/fileselector/fileselect.cxx b/src/fileselector/fileselect.cxx index 159e1d5b..243e3f30 100644 --- a/src/fileselector/fileselect.cxx +++ b/src/fileselector/fileselect.cxx @@ -21,7 +21,7 @@ static const char* get_file(void) } } -const char* file_select(const char* title, const char* filter, const char* def) +const char* file_select(const char* title, const char* filter, const char* def, int* fsel) { if (!chooser) chooser = new Fl_Native_File_Chooser; @@ -33,10 +33,13 @@ const char* file_select(const char* title, const char* filter, const char* def) chooser->options(Fl_Native_File_Chooser::PREVIEW); chooser->type(Fl_Native_File_Chooser::BROWSE_FILE); - return get_file(); + const char* fn = get_file(); + if (fsel) + *fsel = chooser->filter_value(); + return fn; } -const char* file_saveas(const char* title, const char* filter, const char* def) +const char* file_saveas(const char* title, const char* filter, const char* def, int* fsel) { if (!chooser) chooser = new Fl_Native_File_Chooser; @@ -50,7 +53,10 @@ const char* file_saveas(const char* title, const char* filter, const char* def) Fl_Native_File_Chooser::PREVIEW); chooser->type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); - return get_file(); + const char* fn = get_file(); + if (fsel) + *fsel = chooser->filter_value(); + return fn; } const char* dir_select(const char* title, const char* filter, const char* def) diff --git a/src/filters/filters.cxx b/src/filters/filters.cxx index 11b62011..b2e04974 100644 --- a/src/filters/filters.cxx +++ b/src/filters/filters.cxx @@ -396,7 +396,7 @@ void Cmovavg::reset() // require the store of the history associated with those bins over the // kernel length. // -// Use in the MFSK modem for extraction of the frequency spectra +// Use in the MFSK / DOMINO modem for extraction of the frequency spectra // //===================================================================== diff --git a/src/globals/globals.cxx b/src/globals/globals.cxx index 61591c56..5bcc0c66 100644 --- a/src/globals/globals.cxx +++ b/src/globals/globals.cxx @@ -45,51 +45,51 @@ const char *state_names[] = { const struct mode_info_t mode_info[NUM_MODES] = { { MODE_CW, &cw_modem, "CW", "CW", "CW" }, - { MODE_DOMINOEX4, &dominoex4_modem, "DomEX4", "DominoEX 4", "DOMINOEX4" }, - { MODE_DOMINOEX5, &dominoex5_modem, "DomEX5", "DominoEX 5", "DOMINOEX5" }, - { MODE_DOMINOEX8, &dominoex8_modem, "DomEX8", "DominoEX 8", "DOMINOEX8" }, - { MODE_DOMINOEX11, &dominoex11_modem, "DomX11", "DominoEX 11", "DOMINOEX11" }, - { MODE_DOMINOEX16, &dominoex16_modem, "DomX16", "DominoEX 16", "DOMINOEX16" }, - { MODE_DOMINOEX22, &dominoex22_modem, "DomX22", "DominoEX 22", "DOMINOEX22" }, + { MODE_DOMINOEX4, &dominoex4_modem, "DomEX4", "DominoEX 4", "DOMINOEX4", "DOMINO" }, // These aren't Domino FEC, right? + { MODE_DOMINOEX5, &dominoex5_modem, "DomEX5", "DominoEX 5", "DOMINOEX5", "DOMINO" }, + { MODE_DOMINOEX8, &dominoex8_modem, "DomEX8", "DominoEX 8", "DOMINOEX8", "DOMINO" }, + { MODE_DOMINOEX11, &dominoex11_modem, "DomX11", "DominoEX 11", "DOMINOEX11", "DOMINO" }, + { MODE_DOMINOEX16, &dominoex16_modem, "DomX16", "DominoEX 16", "DOMINOEX16", "DOMINO" }, + { MODE_DOMINOEX22, &dominoex22_modem, "DomX22", "DominoEX 22", "DOMINOEX22", "DOMINO" }, - { MODE_FELDHELL, &feld_modem, "FELDHELL", "Feld Hell", "" }, - { MODE_SLOWHELL, &feld_slowmodem, "SLOWHELL", "Slow Hell", "" }, - { MODE_HELLX5, &feld_x5modem, "HELLX5", "Feld Hell X5", "" }, - { MODE_HELLX9, &feld_x9modem, "HELLX9", "Feld Hell X9", "" }, - { MODE_FSKHELL, &feld_FMmodem, "FSK-HELL", "FSK Hell", "" }, - { MODE_FSKH105, &feld_FM105modem, "FSK-H105", "FSK Hell-105", "" }, - { MODE_HELL80, &feld_80modem, "HELL80", "Hell 80", "" }, + { MODE_FELDHELL, &feld_modem, "FELDHELL", "Feld Hell", "", "HELL" }, + { MODE_SLOWHELL, &feld_slowmodem, "SLOWHELL", "Slow Hell", "", "HELL" }, // Not sure about these after the first one + { MODE_HELLX5, &feld_x5modem, "HELLX5", "Feld Hell X5", "", "HELL" }, + { MODE_HELLX9, &feld_x9modem, "HELLX9", "Feld Hell X9", "", "HELL"}, + { MODE_FSKHELL, &feld_FMmodem, "FSK-HELL", "FSK Hell", "", "FMHELL" }, + { MODE_FSKH105, &feld_FM105modem, "FSK-H105", "FSK Hell-105", "", "FMHELL" }, + { MODE_HELL80, &feld_80modem, "HELL80", "Hell 80", "", "HELL80" }, - { MODE_MFSK8, &mfsk8_modem, "MFSK-8", "MFSK-8", "MFSK16" }, - { MODE_MFSK16, &mfsk16_modem, "MFSK16", "MFSK-16", "MFSK8" }, + { MODE_MFSK8, &mfsk8_modem, "MFSK-8", "MFSK-8", "MFSK8", "MFSK8" }, // !! These were swapped + { MODE_MFSK16, &mfsk16_modem, "MFSK16", "MFSK-16", "MFSK16", "MFSK16" }, - { MODE_MT63_500, &mt63_500_modem, "MT63-500", "MT63-500", "" }, - { MODE_MT63_1000, &mt63_1000_modem, "MT63-1XX", "MT63-1000", "" }, - { MODE_MT63_2000, &mt63_2000_modem, "MT63-2XX", "MT63-2000", "" }, + { MODE_MT63_500, &mt63_500_modem, "MT63-500", "MT63-500", "", "MT63" }, + { MODE_MT63_1000, &mt63_1000_modem, "MT63-1XX", "MT63-1000", "", "MT63" }, + { MODE_MT63_2000, &mt63_2000_modem, "MT63-2XX", "MT63-2000", "", "MT63" }, - { MODE_BPSK31, &psk31_modem, "BPSK31", "BPSK-31", "PSK31" }, - { MODE_QPSK31, &qpsk31_modem, "QPSK31", "QPSK-31", "QPSK31" }, - { MODE_PSK63, &psk63_modem, "PSK-63", "BPSK-63", "PSK63" }, - { MODE_QPSK63, &qpsk63_modem, "QPSK63", "QPSK-63", "QPSK63" }, - { MODE_PSK125, &psk125_modem, "PSK125", "BPSK-125", "PSK125" }, - { MODE_QPSK125, &qpsk125_modem, "QPSK-125", "QPSK-125", "QPSK125" }, - { MODE_PSK250, &psk250_modem, "PSK-250", "BPSK-250", "PSK250" }, - { MODE_QPSK250, &qpsk250_modem, "QPSK-250", "QPSK-250", "QPSK250" }, + { MODE_BPSK31, &psk31_modem, "BPSK31", "BPSK-31", "PSK31", "PSK31" }, + { MODE_QPSK31, &qpsk31_modem, "QPSK31", "QPSK-31", "QPSK31", "QPSK31" }, + { MODE_PSK63, &psk63_modem, "PSK-63", "BPSK-63", "PSK63", "PSK63" }, + { MODE_QPSK63, &qpsk63_modem, "QPSK63", "QPSK-63", "QPSK63", "QPSK63" }, + { MODE_PSK125, &psk125_modem, "PSK125", "BPSK-125", "PSK125", "PSK125" }, + { MODE_QPSK125, &qpsk125_modem, "QPSK-125", "QPSK-125", "QPSK125", "PSK125" }, + { MODE_PSK250, &psk250_modem, "PSK-250", "BPSK-250", "PSK250", "PSK250" }, // PSK250 not supported in 2.1.9 + { MODE_QPSK250, &qpsk250_modem, "QPSK-250", "QPSK-250", "QPSK250", "QPSK250" }, // PSK250 not supported in 2.1.9 - { MODE_OLIVIA, &olivia_modem, "OLIVIA", "Olivia", "" }, + { MODE_OLIVIA, &olivia_modem, "OLIVIA", "Olivia", "", "OLIVIA" }, - { MODE_RTTY, &rtty_modem, "RTTY", "RTTY", "RTTY" }, + { MODE_RTTY, &rtty_modem, "RTTY", "RTTY", "RTTY", "RTTY" }, - { MODE_THROB1, &throb1_modem, "THROB1", "Throb 1", "" }, - { MODE_THROB2, &throb2_modem, "THROB2", "Throb 2", "" }, - { MODE_THROB4, &throb4_modem, "THROB4", "Throb 4", "" }, - { MODE_THROBX1, &throbx1_modem, "THRBX1", "ThrobX 1", "" }, - { MODE_THROBX2, &throbx2_modem, "THRBX2", "ThrobX 2", "" }, - { MODE_THROBX4, &throbx4_modem, "THRBX4", "ThrobX 4", "" }, + { MODE_THROB1, &throb1_modem, "THROB1", "Throb 1", "", "THRB" }, + { MODE_THROB2, &throb2_modem, "THROB2", "Throb 2", "", "THRB" }, + { MODE_THROB4, &throb4_modem, "THROB4", "Throb 4", "", "THRB" }, + { MODE_THROBX1, &throbx1_modem, "THRBX1", "ThrobX 1", "", "THRBX" }, + { MODE_THROBX2, &throbx2_modem, "THRBX2", "ThrobX 2", "", "THRBX" }, + { MODE_THROBX4, &throbx4_modem, "THRBX4", "ThrobX 4", "", "THRBX" }, - { MODE_WWV, &wwv_modem, "WWV", "WWV", "" }, + { MODE_WWV, &wwv_modem, "WWV", "WWV", "", "" }, - { MODE_ANALYSIS, &anal_modem, "ANALYSIS", "Freq Analysis", "" } + { MODE_ANALYSIS, &anal_modem, "ANALYSIS", "Freq Analysis", "", "" } }; std::ostream& operator<<(std::ostream& s, const qrg_mode_t& m) diff --git a/src/include/FTextView.h b/src/include/FTextView.h index 85daffc6..f9353787 100644 --- a/src/include/FTextView.h +++ b/src/include/FTextView.h @@ -30,7 +30,6 @@ #include #include "threads.h" -//#include "TextView.h" /* fltk includes */ #include @@ -193,27 +192,29 @@ protected: /// The text widgets base class. /// This class implements a basic text editing widget based on Fl_Text_Editor_mod. /// -class FTextBase : virtual public ReceiveWidget +class FTextBase : public Fl_Text_Editor_mod { public: + enum TEXT_ATTR { RECV, XMIT, CTRL, SKIP, ALTR, NATTR }; + FTextBase(int x, int y, int w, int h, const char *l = 0); virtual ~FTextBase() { delete tbuf; delete sbuf; } + virtual void add(const char *text, int attr = RECV) = 0; + virtual void add(unsigned char c, int attr = RECV) = 0; + void addstr(const char *text, int attr = RECV) { add(text, attr); } + void addchr(unsigned char c, int attr = RECV) { add(c, attr); } + virtual int handle(int event); void clear(void) { tbuf->text(""); sbuf->text(""); } void setFont(Fl_Font f, int attr = NATTR); void setFontSize(int s, int attr = NATTR); void setFontColor(Fl_Color c, int attr = NATTR); - virtual void setFont(Fl_Font f) { setFont(f, NATTR); } - virtual void setFontSize(int s) { setFontSize(s, NATTR); } - virtual void setFontColor(Fl_Color c) { setFontColor(c, NATTR); } void cursorON(void) { show_cursor(); } virtual void resize(int X, int Y, int W, int H); - virtual void Show(void) { Fl_Text_Editor_mod::show(); } - virtual void Hide(void) { Fl_Text_Editor_mod::hide(); } static bool wheight_mult_tsize(void *arg, int xd, int yd); protected: @@ -236,7 +237,7 @@ protected: enum set_style_op_e { SET_FONT = 1 << 0, SET_SIZE = 1 << 1, SET_COLOR = 1 << 2 }; Fl_Text_Buffer *tbuf; ///< text buffer Fl_Text_Buffer *sbuf; ///< style buffer - Fl_Text_Display_mod::Style_Table_Entry styles[ReceiveWidget::NATTR]; + Fl_Text_Display_mod::Style_Table_Entry styles[NATTR]; Fl_Menu_Item *context_menu; int popx, popy; bool wrap; @@ -266,7 +267,7 @@ protected: enum { RX_MENU_QRZ_THIS, RX_MENU_CALL, RX_MENU_NAME, RX_MENU_QTH, RX_MENU_LOC, RX_MENU_RST_IN, RX_MENU_DIV, RX_MENU_CLEAR, RX_MENU_COPY, -#ifndef NDEBUG +#if 0 //#ifndef NDEBUG RX_MENU_READ, #endif RX_MENU_SAVE, RX_MENU_WRAP }; @@ -288,7 +289,7 @@ protected: /// /// A FTextBase subclass to display and edit text to be transmitted /// -class FTextEdit : public FTextBase, public TransmitWidget +class FTextEdit : public FTextBase { public: FTextEdit(int x, int y, int w, int h, const char *l = 0); diff --git a/src/include/confdialog.h b/src/include/confdialog.h index 6ec5ea4b..7944096b 100644 --- a/src/include/confdialog.h +++ b/src/include/confdialog.h @@ -115,7 +115,6 @@ extern Fl_Value_Input *valCWsweetspot; extern Fl_Value_Input *valRTTYsweetspot; extern Fl_Value_Input *valPSKsweetspot; extern Fl_Check_Button *btnStartAtSweetSpot; -extern Fl_Check_Button *btntextwidgets; extern Fl_Group *tabModems; extern Fl_Tabs *tabsModems; extern Fl_Group *tabCW; diff --git a/src/include/configuration.h b/src/include/configuration.h index 4d9f96cb..efe55064 100644 --- a/src/include/configuration.h +++ b/src/include/configuration.h @@ -182,8 +182,6 @@ struct configuration { RGBint RxColor; RGBint TxColor; - bool alt_text_widgets; - string strCommPorts; int rx_msgid; diff --git a/src/include/digiscope.h b/src/include/digiscope.h index 44550e30..b1c737c1 100644 --- a/src/include/digiscope.h +++ b/src/include/digiscope.h @@ -38,12 +38,14 @@ #include #include #include "threads.h" +#include "complex.h" class Digiscope : public Fl_Widget { public: #define DEFAULT_WIDTH 100 #define DEFAULT_HEIGHT 100 #define MAX_LEN 4096 +#define MAX_ZLEN 16184 enum scope_mode { SCOPE, PHASE, @@ -58,6 +60,9 @@ public: private: scope_mode _mode; double _buf[MAX_LEN]; + complex _zdata[MAX_ZLEN]; + int _zlen; + int _zptr; unsigned char *vidbuf; unsigned char *vidline; int _len; @@ -65,6 +70,7 @@ private: double _phase; double _flo, _fhi, _amp; bool _highlight; + public: Digiscope(int, int, int, int); ~Digiscope(); @@ -75,10 +81,12 @@ public: void draw_phase(); void draw_rtty(); void draw_crosshairs(); + void draw_xy(); void draw_video(); void data(double *data, int len, bool scale = true); void phase(double ph, bool hl); void video(double *data, int len ); + void zdata(complex *z, int len); void rtty(double flo, double fhi, double amp); void mode(scope_mode md); scope_mode mode() { return _mode;}; diff --git a/src/include/fileselect.h b/src/include/fileselect.h index 861464a0..f0f9d4fd 100644 --- a/src/include/fileselect.h +++ b/src/include/fileselect.h @@ -1,8 +1,8 @@ #ifndef FILESELECT_H #define FILESELECT_H -const char* file_select(const char* title, const char* filter, const char* def = 0); -const char* file_saveas(const char* title, const char* filter, const char* def = 0); +const char* file_select(const char* title, const char* filter, const char* def = 0, int* fsel = 0); +const char* file_saveas(const char* title, const char* filter, const char* def = 0, int* fsel = 0); const char* dir_select(const char* title, const char* filter, const char* def = 0); #endif // FILESELECT_H diff --git a/src/include/fl_digi.h b/src/include/fl_digi.h index a4edf275..5613002a 100644 --- a/src/include/fl_digi.h +++ b/src/include/fl_digi.h @@ -39,7 +39,6 @@ #include #include "combo.h" -//#include "TextView.h" #include "FTextView.h" #include "raster.h" #include "waterfall.h" @@ -51,12 +50,10 @@ extern Fl_Double_Window *fl_digi_main; extern Fl_Double_Window *scopeview; -extern ReceiveWidget *ReceiveText; -extern TransmitWidget *TransmitText; +extern FTextView *ReceiveText; +extern FTextEdit *TransmitText; extern Raster *FHdisp; extern Fl_Tile_check *TiledGroup; -extern Fl_Text_Buffer *rcvBuffer; -extern Fl_Text_Buffer *xmtBuffer; extern Fl_Box *StatusBar; extern Fl_Box *Status2; extern Fl_Box *Status1; @@ -115,6 +112,8 @@ extern void set_scope(double *data, int len, bool autoscale = true); extern void set_phase(double phase, bool highlight); extern void set_rtty(double, double, double); extern void set_video(double *, int); +extern void set_zdata(complex *, int); + extern void set_CWwpm(); extern void put_rx_char(unsigned int data); extern void put_sec_char( char chr ); diff --git a/src/include/globals.h b/src/include/globals.h index 750f8aef..c61ad66d 100644 --- a/src/include/globals.h +++ b/src/include/globals.h @@ -107,6 +107,7 @@ struct mode_info_t { const char *sname; const char *name; const char *pskmail_name; + const char *adif_name; }; extern const struct mode_info_t mode_info[NUM_MODES]; diff --git a/src/include/modem.h b/src/include/modem.h index 8dd41138..d337de0d 100644 --- a/src/include/modem.h +++ b/src/include/modem.h @@ -148,10 +148,10 @@ private: int findmask(int symbol); void wfid_sendchar(char c); - void wfid_sendchars(string s); + void wfid_sendchars(std::string s); public: - void wfid_text(string s); + void wfid_text(std::string s); // for CW ID transmission private: @@ -165,7 +165,7 @@ public: double cwid_nco(double freq); void cwid_send_symbol(int bits); void cwid_send_ch(int ch); - void cwid_sendtext (string s); + void cwid_sendtext (std::string s); void cwid(); }; diff --git a/src/include/picture.h b/src/include/picture.h index bf0112ec..c3630724 100644 --- a/src/include/picture.h +++ b/src/include/picture.h @@ -61,8 +61,12 @@ public: void clear(); void image(Fl_Image *img) {Fl_Widget::image(img);} void resize(int, int, int, int); +#if USE_LIBJPEG int save_jpeg(const char *); +#endif +#if USE_LIBPNG int save_png(const char *); +#endif }; #endif diff --git a/src/include/rtty.h b/src/include/rtty.h index 5b071ebd..a427584d 100644 --- a/src/include/rtty.h +++ b/src/include/rtty.h @@ -37,10 +37,12 @@ //#include "id.h" #include "mbuffer.h" -//#define RTTY_SampleRate 8000 -#define RTTY_SampleRate 11025 +#define RTTY_SampleRate 8000 +//#define RTTY_SampleRate 11025 +//#define RTTY_SampleRate 12000 -#define RTTYMaxSymLen 1024 +#define RTTYMaxSymLen (RTTY_SampleRate / 23) +#define MAXPIPE (2*RTTYMaxSymLen) #define LETTERS 0x100 #define FIGURES 0x200 @@ -96,10 +98,10 @@ private: Cmovavg *bitfilt; fftfilt *bpfilt; - mbuffer pipe; + mbuffer pipe; int pipeptr; - double bbfilter[RTTYMaxSymLen]; + double bbfilter[MAXPIPE]; unsigned int filterptr; RTTY_RX_STATE rxstate; @@ -113,6 +115,16 @@ private: double prevsymbol; complex prevsmpl; + + complex QI[1024]; + int QIptr; + double markphase; + double spacephase; + double marksig; + double spacesig; + double f1, f2; + fftfilt *markfilt; + fftfilt *spacefilt; double FSKbuf[OUTBUFSIZE]; // signal array for qrq drive double FSKphaseacc; @@ -125,10 +137,12 @@ private: void clear_syncscope(); void update_syncscope(); inline complex mixer(complex in); + void MarkSpace(complex in); unsigned char bitreverse(unsigned char in, int n); int decode_char(); int rttyparity(unsigned int); int rx(bool bit); +// transmit double nco(double freq); void send_symbol(int symbol); void send_stop(); diff --git a/src/include/util.h b/src/include/util.h index b8f8ca1b..0aa0dfee 100644 --- a/src/include/util.h +++ b/src/include/util.h @@ -115,6 +115,10 @@ deprecated__ typeof(strcat) strcat; */ #endif +#if !HAVE_STRCASESTR +char* strcasestr(const char* haystack, const char* needle); +#endif + #ifdef __CYGWIN__ # define NOMINMAX 1 #endif diff --git a/src/logger/logger.cxx b/src/logger/logger.cxx index 2656f628..d8a5a107 100644 --- a/src/logger/logger.cxx +++ b/src/logger/logger.cxx @@ -78,7 +78,7 @@ FIELD fields[] = { {"TX_PWR", 4} // 29 - power transmitted by this station }; -#define ADIF_VERS "2.0" +#define ADIF_VERS "2.1.9" static string adif; const char *ADIFHEADER = @@ -167,7 +167,7 @@ int submit_log(void) snprintf(adifdate, sizeof(adifdate), "%04d%02d%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); strftime(logtime, sizeof(logtime), "%H%M", tm); - const char *mode = mode_info[active_modem->get_mode()].sname; + const char *mode = mode_info[active_modem->get_mode()].adif_name; snprintf(strFreqMhz, sizeof(strFreqMhz), "%-12f", wf->dFreq()/1.0e6); diff --git a/src/mfsk/mfsk.cxx b/src/mfsk/mfsk.cxx index 19da41e7..0142cf21 100644 --- a/src/mfsk/mfsk.cxx +++ b/src/mfsk/mfsk.cxx @@ -572,10 +572,15 @@ int mfsk::rx_process(const double *buf, int len) rxstate = RX_STATE_DATA; // REQ_FLUSH(); put_status(""); -//#ifndef __CYGWIN__ +#if USE_LIBPNG string autosave_dir = HomeDir + "mfsk_pics/"; picRx->save_png(autosave_dir.c_str()); -//#endif +#else +# if USE_LIBJPEG + string autosave_dir = HomeDir + "mfsk_pics/"; + picRx->save_jpeg(autosave_dir.c_str()); +# endif +#endif } else recvpic(z); continue; @@ -882,10 +887,38 @@ void cb_picRxAbort( Fl_Widget *w, void *who) void cb_picRxSave( Fl_Widget *w, void *who) { // mfsk *me = (mfsk *)who; - const char *fn = - file_saveas( "Save image as:", "Portable Network Graphics\t*.png", "." ); + const char ffilter[] = "" +#if USE_LIBPNG + "Portable Network Graphics\t*.png\n" +#endif +#if USE_LIBJPEG + "Independent JPEG Group\t*.{jpg,jpeg}" +#endif + ; + const char dfname[] = "image." +#if USE_LIBPNG + "png" +#else + "jpg" +#endif + ; + + int fsel; + const char *fn = file_saveas("Save image as:", ffilter, dfname, &fsel); if (!fn) return; - picRx->save_png(fn); + // selected filter determines format + switch (fsel) { + case 0: +#if USE_LIBPNG + picRx->save_png(fn); + break; +#endif + // fall through if no libpng + case 1: +#if USE_LIBJPEG + picRx->save_jpeg(fn); +#endif + } } void createRxViewer(mfsk *who) @@ -894,9 +927,12 @@ void createRxViewer(mfsk *who) picRxWin = new Fl_Double_Window(200, 140); picRxWin->xclass(PACKAGE_NAME); picRx = new picture(2, 2, 136, 104); - btnpicRxSave = new Fl_Button(5, 140 - 30, 60, 24,"Save"); + btnpicRxSave = new Fl_Button(5, 140 - 30, 60, 24,"Save..."); btnpicRxSave->callback(cb_picRxSave, who); btnpicRxSave->hide(); +#if !(USE_LIBPNG || USE_LIBJPEG) + btnpicRxSave->deactivate(); +#endif btnpicRxAbort = new Fl_Button(70, 140 - 30, 60, 24, "Abort"); btnpicRxAbort->callback(cb_picRxAbort, who); btnpicRxClose = new Fl_Button(135, 140 - 30, 60, 24, "Hide"); diff --git a/src/misc/configuration.cxx b/src/misc/configuration.cxx index ef8a3b31..39e43a9c 100644 --- a/src/misc/configuration.cxx +++ b/src/misc/configuration.cxx @@ -193,8 +193,6 @@ configuration progdefaults = { { 255, 242, 190}, // RGBint RxColor; { 200, 235, 255}, // RGBint TxColor; - true, // bool alt_text_widgets; - "", // string strCommPorts 9876, // int rx_msgid 6789, // int tx_msgid diff --git a/src/misc/util.cxx b/src/misc/util.cxx index b72daf79..529ee4e5 100644 --- a/src/misc/util.cxx +++ b/src/misc/util.cxx @@ -1,5 +1,10 @@ #include +#include +#include + +#include + #include "util.h" /* Return the smallest power of 2 not less than n */ @@ -26,3 +31,22 @@ uint32_t floor2(uint32_t n) return n - (n >> 1); } + +#if !HAVE_STRCASESTR +// a simple inefficient implementation of strcasestr +char* strcasestr(const char* haystack, const char* needle) +{ + char *h = NULL, *n = NULL, *p = NULL; + if ((h = strdup(haystack)) == NULL || (n = strdup(needle)) == NULL) + goto ret; + for (p = h; *p; p++) + *p = tolower(*p); + for (p = n; *p; p++) + *p = tolower(*p); + p = strstr(h, n); +ret: + free(h); + free(n); + return p; +} +#endif // !HAVE_STRCASESTR diff --git a/src/waterfall/digiscope.cxx b/src/waterfall/digiscope.cxx index c5f6c54f..d06b43c7 100644 --- a/src/waterfall/digiscope.cxx +++ b/src/waterfall/digiscope.cxx @@ -43,6 +43,7 @@ Digiscope::Digiscope (int X, int Y, int W, int H) : vidline = new unsigned char[ 3 * (W-4)]; _highlight = false; _len = MAX_LEN; + _zptr = 0; } Digiscope::~Digiscope() @@ -82,6 +83,24 @@ void Digiscope::video(double *data, int len ) FL_AWAKE_D(); } +void Digiscope::zdata(complex *zarray, int len ) +{ + if (active_modem->HistoryON()) return; + + if (zarray == NULL || len == 0) + return; + + FL_LOCK_D(); + for (int i = 0; i < len; i++) { + _zdata[_zptr++] = zarray[i]; + if (_zptr == MAX_ZLEN) _zptr = 0; + } + + REQ_DROP(&Digiscope::redraw, this); + FL_UNLOCK_D(); + FL_AWAKE_D(); +} + void Digiscope::data(double *data, int len, bool scale) { if (active_modem->HistoryON()) return; @@ -163,6 +182,10 @@ void Digiscope::mode(scope_mode md) void Digiscope::draw_phase() { + fl_clip(x()+2,y()+2,w()-4,h()-4); + fl_color(FL_BLACK); + fl_rectf(x()+2,y()+2,w()-4,h()-4); + fl_push_matrix(); fl_translate(x() + w() / 2.0, y() + w() / 2.0); fl_scale( 0.9*w()/2, -0.9*w()/2); fl_color(FL_WHITE); @@ -193,11 +216,17 @@ void Digiscope::draw_phase() } else { fl_circle( 0.0, 0.0, 0.1); } + fl_pop_matrix(); + fl_pop_clip(); } void Digiscope::draw_crosshairs() { double phi, xp, yp; + fl_clip(x()+2,y()+2,w()-4,h()-4); + fl_color(FL_BLACK); + fl_rectf(x()+2,y()+2,w()-4,h()-4); + fl_push_matrix(); fl_translate(x() + w() / 2.0, y() + w() / 2.0); fl_scale( 0.9*w()/2, -0.9*w()/2); fl_color(FL_WHITE); @@ -234,11 +263,17 @@ void Digiscope::draw_crosshairs() fl_vertex(-xp, -yp); fl_vertex( xp, yp); fl_end_line(); + fl_pop_matrix(); + fl_pop_clip(); } void Digiscope::draw_scope() { int npts; + fl_clip(x()+2,y()+2,w()-4,h()-4); + fl_color(FL_BLACK); + fl_rectf(x()+2,y()+2,w()-4,h()-4); + fl_push_matrix(); npts = MIN(w(), _len); npts = MAX(1, npts); fl_translate(x()+2, y() + h() - 2); @@ -248,11 +283,47 @@ void Digiscope::draw_scope() for (int i = 0; i < npts; i++) fl_vertex( (double)i / npts, _buf[i * _len / npts] ); fl_end_line(); + fl_pop_matrix(); + fl_pop_clip(); +} + +void Digiscope::draw_xy() +{ + fl_clip(x()+2,y()+2,w()-4,h()-4); + fl_color(FL_BLACK); + fl_rectf(x()+2,y()+2,w()-4,h()-4); + fl_push_matrix(); + fl_translate(x() + w() / 2.0, y() + w() / 2.0); + fl_scale( w()/2.0, -w()/2.0); +// x & y axis + fl_color(FL_WHITE); + fl_begin_line(); + fl_vertex(-1.0, 0.0); + fl_vertex(+1.0, 0.0); + fl_end_line(); + fl_begin_line(); + fl_vertex(0.0, -1.0); + fl_vertex(0.0, +1.0); + fl_end_line(); +// data + fl_color(FL_GREEN); + int xp, yp; + for (int i = 0; i < MAX_ZLEN; i++ ) { + xp = (int)((_zdata[i].re + 1.0) * w() / 2.0); + yp = (int)((_zdata[i].im + 1.0) * h() / 2.0); + fl_point(xp,yp); + } + fl_pop_matrix(); + fl_pop_clip(); } void Digiscope::draw_rtty() { int npts; + fl_clip(x()+2,y()+2,w()-4,h()-4); + fl_color(FL_BLACK); + fl_rectf(x()+2,y()+2,w()-4,h()-4); + fl_push_matrix(); npts = MIN(w(), _len); npts = MAX(1, npts); fl_translate(x()+2, y() + h() - 2); @@ -271,6 +342,8 @@ void Digiscope::draw_rtty() for (int i = 0; i < npts; i++) fl_vertex( (double)i / npts, 0.5 + 0.75 * _buf[i * _len / npts] ); fl_end_line(); + fl_pop_matrix(); + fl_pop_clip(); } void Digiscope::draw_video() @@ -287,21 +360,16 @@ void Digiscope::draw() if (_mode == WWV || _mode == DOMWF) draw_video(); else { - fl_clip(x()+2,y()+2,w()-4,h()-4); - fl_color(FL_BLACK); - fl_rectf(x()+2,y()+2,w()-4,h()-4); - fl_push_matrix(); switch (_mode) { case SCOPE : draw_scope(); break; case PHASE : draw_phase(); break; case RTTY : draw_rtty(); break; - case XHAIRS : draw_crosshairs(); break; +// case XHAIRS : draw_crosshairs(); break; + case XHAIRS : draw_xy(); break; case DOMDATA : draw_scope(); break; case BLANK : default: break; } - fl_pop_matrix(); - fl_pop_clip(); } } diff --git a/src/widgets/FTextView.cxx b/src/widgets/FTextView.cxx index e0d9c639..a85af0a3 100644 --- a/src/widgets/FTextView.cxx +++ b/src/widgets/FTextView.cxx @@ -53,7 +53,7 @@ using namespace std; /// @param h /// @param l FTextBase::FTextBase(int x, int y, int w, int h, const char *l) - : ReceiveWidget(x, y, w, h, l), + : Fl_Text_Editor_mod(x, y, w, h, l), wrap(true), wrap_col(80), max_lines(0), scroll_hint(false) { tbuf = new Fl_Text_Buffer; @@ -81,7 +81,7 @@ int FTextBase::handle(int event) adjust_colours(); } - return ReceiveWidget::handle(event); + return Fl_Text_Editor_mod::handle(event); } void FTextBase::setFont(Fl_Font f, int attr) @@ -324,10 +324,9 @@ Fl_Menu_Item FTextView::view_menu[] = { /// @param h /// @param l FTextView::FTextView(int x, int y, int w, int h, const char *l) - : ReceiveWidget(x, y, w, h, l), FTextBase(x, y, w, h, l) + : FTextBase(x, y, w, h, l) { - tbuf->remove_modify_callback(buffer_modified_cb, - dynamic_cast(this)); + tbuf->remove_modify_callback(buffer_modified_cb, this); tbuf->add_modify_callback(changed_cb, this); cursor_style(Fl_Text_Display_mod::NORMAL_CURSOR); @@ -504,7 +503,7 @@ void FTextView::menu_cb(int val) kf_copy(Fl::event_key(), this); break; -#ifndef NDEBUG +#if 0 //#ifndef NDEBUG case RX_MENU_READ: { readFile(); @@ -547,7 +546,7 @@ void FTextView::changed_cb(int pos, int nins, int ndel, int nsty, const char *dt if (v->mTopLineNum + v->mNVisibleLines - 1 == v->mNBufferLines) v->scroll_hint = true; - v->buffer_modified_cb(pos, nins, ndel, nsty, dtext, dynamic_cast(v)); + v->buffer_modified_cb(pos, nins, ndel, nsty, dtext, v); } /// Removes Fl_Text_Edit keybindings that would modify text and put it out of @@ -599,14 +598,13 @@ Fl_Menu_Item FTextEdit::edit_menu[] = { int *FTextEdit::ptxpos; FTextEdit::FTextEdit(int x, int y, int w, int h, const char *l) - : ReceiveWidget(x, y, w, h, l), FTextBase(x, y, w, h, l), - TransmitWidget(x, y, w, h, l), + : FTextBase(x, y, w, h, l), PauseBreak(false), txpos(0), bkspaces(0) { ptxpos = &txpos; cursor_style(Fl_Text_Display_mod::NORMAL_CURSOR); - tbuf->remove_modify_callback(buffer_modified_cb, - dynamic_cast(this)); + tbuf->remove_modify_callback(buffer_modified_cb, this); + tbuf->add_modify_callback(changed_cb, this); context_menu = edit_menu; @@ -1018,8 +1016,8 @@ void FTextEdit::changed_cb(int pos, int nins, int ndel, int nsty, const char *dt e->redisplay_range(pos - 1, pos); } else if (nsty > 0) // restyled, e.g. selected, text - return e->buffer_modified_cb(pos, nins, ndel, nsty, dtext, - dynamic_cast(e)); + return e->buffer_modified_cb(pos, nins, ndel, nsty, dtext, e); + // No changes, e.g., a paste with an empty clipboard. return; } @@ -1044,7 +1042,7 @@ void FTextEdit::changed_cb(int pos, int nins, int ndel, int nsty, const char *dt e->sbuf->select(pos, pos + nins - ndel); - e->buffer_modified_cb(pos, nins, ndel, nsty, dtext, dynamic_cast(e)); + e->buffer_modified_cb(pos, nins, ndel, nsty, dtext, e); // We may need to scroll if the text was inserted by the // add() methods, e.g. by a macro if (e->mTopLineNum + e->mNVisibleLines - 1 <= e->mNBufferLines) diff --git a/src/widgets/picture.cxx b/src/widgets/picture.cxx index de52e9f5..9c477e8f 100644 --- a/src/widgets/picture.cxx +++ b/src/widgets/picture.cxx @@ -29,36 +29,13 @@ #include -extern "C" { -// This is needed to avoid a boolean conflict with jmorecfg.h -#ifdef __CYGWIN__ -# include -# define HAVE_BOOLEAN 1 +#if USE_LIBJPEG +# include #endif - -// This is needed to avoid a conflict between a -// system-defined INT32 typedef, and a macro defined in -// jmorecfg.h, included by jpeglib.h. If ADDRESS_TAG_BIT -// is defined, basestd.h has been included and we will have -// the typedef from cygwin, so we define XMD_H to avoid -// defining the macro in jmorecfg.h -#if defined(__CYGWIN__) && !defined(XMD_H) -# define XMD_H -# define FLDIGI_JPEG_XMD_H +#if USE_LIBPNG +# include #endif -#include - -#ifdef FLDIGI_JPEG_XMD_H -# undef FLDIGI_JPEG_XMD_H -# undef XMD_H -#endif - -//# include "transupp.h" -}; - -#include - #include "picture.h" using namespace std; @@ -275,6 +252,7 @@ static FILE* open_file(const char* name, const char* suffix) return fp; } +#if USE_LIBJPEG // // save_jpeg - Write a captured picture to a JPEG format file. // @@ -318,7 +296,9 @@ int picture::save_jpeg(const char *filename) return 0; } +#endif // USE_LIBJPEG +#if USE_LIBPNG int picture::save_png(const char* filename) { FILE* fp; @@ -377,3 +357,4 @@ int picture::save_png(const char* filename) return 0; } +#endif // USE_LIBPNG