From 9092259ce1c4e8bf3a62ac5748818cbf40b2f1d2 Mon Sep 17 00:00:00 2001 From: lwvmobile <59371473+lwvmobile@users.noreply.github.com> Date: Fri, 11 Feb 2022 19:25:05 -0500 Subject: [PATCH] Initial NCURSES Support Initial NCURSES Support Its in there, and can be called with -N, but it doesn't display much yet aside from program name, mbelib, and time. Just want to upload it so I can test it vs autobuild with cmake requiring ncurses libraries again --- CMakeLists.txt | 19 +++++--- include/dsd.h | 12 ++++- src/dsd_frame.c | 2 +- src/dsd_frame_sync.c | 69 ++++++++++++++++++++++++++++- src/dsd_main.c | 46 +++++++++---------- src/dsd_ncurses.c | 102 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 215 insertions(+), 35 deletions(-) create mode 100644 src/dsd_ncurses.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 96a0dc3..42d0a7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,18 +12,25 @@ find_package(ITPP REQUIRED) #find_package(LibPortAudio) #disabled for testing find_package(RTLSDR) #more messing around -#find_package(Curses REQUIRED) +#find_package(Curses) +find_package(Curses REQUIRED) #making this required until I can fix all instances of it being called to ifdef lines find_package(PULSEAUDIO) -#include_directories(SYSTEM ${LIBSNDFILE_INCLUDE_DIR} ${MBE_INCLUDE_DIR} ${ITPP_INCLUDE_DIR} ${CURSES_INCLUDE_DIR}) -#set(LIBS ${MBE_LIBRARY} ${LIBSNDFILE_LIBRARY} ${ITPP_LIBRARY} ${CURSES_LIBRARY}) +#include_directories(SYSTEM ${LIBSNDFILE_INCLUDE_DIR} ${MBE_INCLUDE_DIR} ${ITPP_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIRS} ${CURSES_INCLUDE_DIR}) +#set(LIBS ${MBE_LIBRARY} ${LIBSNDFILE_LIBRARY} ${ITPP_LIBRARY} ${PULSEAUDIO_SIMPLE_LIBRARY} ${CURSES_LIBRARY}) +#remove CURSES from 'required' set up top AFTER switching all commands to ifdef in dsd_main, dsd_framesync, and dsd_ncurses.c +#also, figure out how to make it build for wide character support in Linux Mint etc, like this -- $(ncursesw5-config --cflags --libs) +include_directories(SYSTEM ${LIBSNDFILE_INCLUDE_DIR} ${MBE_INCLUDE_DIR} ${ITPP_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIRS} ${CURSES_INCLUDE_DIR}) +set(LIBS ${MBE_LIBRARY} ${LIBSNDFILE_LIBRARY} ${ITPP_LIBRARY} ${PULSEAUDIO_SIMPLE_LIBRARY} ${CURSES_LIBRARY}) -include_directories(SYSTEM ${LIBSNDFILE_INCLUDE_DIR} ${MBE_INCLUDE_DIR} ${ITPP_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIRS} ) -set(LIBS ${MBE_LIBRARY} ${LIBSNDFILE_LIBRARY} ${ITPP_LIBRARY} ${PULSEAUDIO_SIMPLE_LIBRARY}) +if(Curses_FOUND) + include_directories(SYSTEM ${CURSES_INCLUDE_PATH}) + list(APPEND LIBS ${CURSES_LIBRARY}) + add_definitions(-DUSE_CURSES) +endif(Curses_FOUND) #going to disable PortAudio, works just fine with padsp in Linux, #hoping disabling this doesn't break OSX or cygwin, etc builds - #if(PORTAUDIO_FOUND) # include_directories(SYSTEM ${PORTAUDIO_INCLUDE_DIRS}) # list(APPEND LIBS ${PORTAUDIO_LIBRARIES}) diff --git a/include/dsd.h b/include/dsd.h index 5b627d2..af929d4 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -63,7 +63,9 @@ #ifdef USE_RTLSDR #include #endif - +//look into making this not required by doing ifdef, make new c file for methods, and CLI case option for ncurses terminal +#include //move this stuff to dsd.h +#include //move this stuff to dsd.h /* * global variables */ @@ -155,6 +157,7 @@ typedef struct pa_simple *pulse_raw_dev_out; pa_simple *pulse_digi_dev_in; pa_simple *pulse_digi_dev_out; + int use_ncurses_terminal; } dsd_opts; @@ -367,6 +370,13 @@ short nxdn_filter(short sample); //borrow from LEH for testing 'improved NXDN detection' int strncmperr(const char *s1, const char *s2, size_t size, int MaxErr); // +//ifdef ncurses +void ncursesOpen (); +void ncursesPrinter (dsd_opts * opts, dsd_state * state); +void ncursesClose (); +//endif ncurses + + #ifdef __cplusplus extern "C" { diff --git a/src/dsd_frame.c b/src/dsd_frame.c index 28d68d0..2390994 100644 --- a/src/dsd_frame.c +++ b/src/dsd_frame.c @@ -112,7 +112,7 @@ processFrame (dsd_opts * opts, dsd_state * state) if (opts->verbose > 0) { level = (int) state->max / 164; - printf ("inlvl: %2i%% ", level); + fprintf (stderr, "inlvl: %2i%% ", level); } } state->nac = 0; diff --git a/src/dsd_frame_sync.c b/src/dsd_frame_sync.c index 596fcca..97bb4e7 100644 --- a/src/dsd_frame_sync.c +++ b/src/dsd_frame_sync.c @@ -588,6 +588,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) printFrameSync (opts, state, " -ProVoice ", synctest_pos + 1, modulation); } state->lastsynctype = 14; + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } return (14); } else if ((strcmp (synctest32, INV_PROVOICE_SYNC) == 0) || (strcmp (synctest32, INV_PROVOICE_EA_SYNC) == 0)) @@ -603,6 +607,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) printFrameSync (opts, state, " -ProVoice ", synctest_pos + 1, modulation); } state->lastsynctype = 15; + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } return (15); } @@ -640,6 +648,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) } } state->lastsynctype = 8; + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } return (8); } else @@ -648,8 +660,8 @@ getFrameSync (dsd_opts * opts, dsd_state * state) } } //else if ((strcmp (synctest18, INV_NXDN_BS_VOICE_SYNC) == 0) || (strcmp (synctest18, INV_NXDN_MS_VOICE_SYNC) == 0)) - //else if ((strncmperr (synctest18, NXDN_BS_DATA_SYNC, 18, 1) == 0) || (strncmperr (synctest18, NXDN_MS_DATA_SYNC, 18, 1) == 0)) - else if ((strncmperr (synctest18, INV_NXDN_BS_VOICE_SYNC, 18, 1) == 0) || (strncmperr (synctest18, INV_NXDN_MS_VOICE_SYNC, 18, 1) == 0)) + //else if ((strncmperr (synctest18, NXDN_BS_DATA_SYNC, 18, 1) == 0) || (strncmperr (synctest18, NXDN_MS_DATA_SYNC, 18, 1) == 0)) //supposed to be voice, not data? IT WAS THIS ONE!! + else if ((strncmperr (synctest18, INV_NXDN_BS_VOICE_SYNC, 18, 1) == 0) || (strncmperr (synctest18, INV_NXDN_MS_VOICE_SYNC, 18, 1) == 0)) //supposed to be voice, not data? { now = time(NULL); //here, or down more if ((state->lastsynctype == 9) || (state->lastsynctype == 17)) @@ -676,6 +688,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) } } state->lastsynctype = 9; + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } return (9); } else @@ -711,6 +727,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) } } state->lastsynctype = 16; + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } return (16); } else @@ -747,6 +767,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) } } state->lastsynctype = 17; + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } return (17); } else @@ -772,6 +796,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) printFrameSync (opts, state, " +D-STAR ", synctest_pos + 1, modulation); } state->lastsynctype = 6; + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } return (6); } if (strcmp (synctest, INV_DSTAR_SYNC) == 0) @@ -787,6 +815,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) printFrameSync (opts, state, " -D-STAR ", synctest_pos + 1, modulation); } state->lastsynctype = 7; + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } return (7); } if (strcmp (synctest, DSTAR_HD) == 0) @@ -802,6 +834,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) printFrameSync (opts, state, " +D-STAR_HD ", synctest_pos + 1, modulation); } state->lastsynctype = 18; + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } return (18); } if (strcmp (synctest, INV_DSTAR_HD) == 0) @@ -817,6 +853,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) printFrameSync (opts, state, " -D-STAR_HD ", synctest_pos + 1, modulation); } state->lastsynctype = 19; + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } return (19); } @@ -836,6 +876,11 @@ getFrameSync (dsd_opts * opts, dsd_state * state) printFrameSync (opts, state, "(+P25p1) ", synctest_pos + 1, modulation); } state->lastsynctype = -1; + //do we want ncursesPrinter here?? + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } return (0); } else if ((state->lastsynctype == 1) && ((state->lastp25type == 1) || (state->lastp25type == 2))) @@ -850,6 +895,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) printFrameSync (opts, state, "(-P25p1) ", synctest_pos + 1, modulation); } state->lastsynctype = -1; + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } return (1); } else if ((state->lastsynctype == 3) && ((strcmp (synctest, X2TDMA_BS_VOICE_SYNC) != 0) || (strcmp (synctest, X2TDMA_MS_VOICE_SYNC) != 0))) @@ -864,6 +913,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) printFrameSync (opts, state, "(-X2-TDMA) ", synctest_pos + 1, modulation); } state->lastsynctype = -1; + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } return (3); } else if ((state->lastsynctype == 4) && ((strcmp (synctest, X2TDMA_BS_DATA_SYNC) != 0) || (strcmp (synctest, X2TDMA_MS_DATA_SYNC) != 0))) @@ -878,6 +931,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) printFrameSync (opts, state, "(+X2-TDMA) ", synctest_pos + 1, modulation); } state->lastsynctype = -1; + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } return (4); } else if ((state->lastsynctype == 11) && ((strcmp (synctest, DMR_BS_VOICE_SYNC) != 0) || (strcmp (synctest, DMR_MS_VOICE_SYNC) != 0))) @@ -892,6 +949,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) printFrameSync (opts, state, "(-DMR) ", synctest_pos + 1, modulation); } state->lastsynctype = -1; + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } return (11); } else if ((state->lastsynctype == 12) && ((strcmp (synctest, DMR_BS_DATA_SYNC) != 0) || (strcmp (synctest, DMR_MS_DATA_SYNC) != 0))) @@ -906,6 +967,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) printFrameSync (opts, state, "(+DMR) ", synctest_pos + 1, modulation); } state->lastsynctype = -1; + if (opts->use_ncurses_terminal == 1) + { + ncursesPrinter(opts, state); + } return (12); } } diff --git a/src/dsd_main.c b/src/dsd_main.c index 6c03f25..d94b6dd 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -52,11 +52,10 @@ int pretty_colors() } -#include "p25p1_heuristics.h" //accidentally had this disabled when getting good NXDN, so if it breaks again, try disabling this -#include "pa_devs.h" //accidentally had this disabled when getting good NXDN, so if it breaks again, try disabling this +#include "p25p1_heuristics.h" +#include "pa_devs.h" short int butt = 1; -#include -//#include + char * FM_banner[9] = { " CTRL + C twice to exit", " ██████╗ ██████╗██████╗    ███████╗███╗ ███╗███████╗", @@ -193,6 +192,7 @@ initOpts (dsd_opts * opts) opts->pulse_digi_rate_in = 48000; opts->pulse_digi_rate_out = 48000; //need to copy this to rtl type in and change rate out to 8000 opts->pulse_flush = 1; //set 0 to flush, 1 for flushed + opts->use_ncurses_terminal = 0; //ncurses terminal disabled by default, call with -N } void @@ -595,7 +595,7 @@ main (int argc, char **argv) exitflag = 0; signal (SIGINT, sigfun); - while ((c = getopt (argc, argv, "haep:P:qstv:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:V:U:Y:Wrl")) != -1) + while ((c = getopt (argc, argv, "haep:P:qstv:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:V:U:Y:NWrl")) != -1) { opterr = 0; switch (c) @@ -687,6 +687,11 @@ main (int argc, char **argv) fprintf (stderr,"Monitor Source Audio Currently Disabled in Pulse Audio Builds.\n"); break; + case 'N': + opts.use_ncurses_terminal = 1; + fprintf (stderr,"Enabling NCurses Terminal.\n"); + break; + case 'z': sscanf (optarg, "%d", &opts.scoperate); @@ -965,8 +970,13 @@ main (int argc, char **argv) } } + if (opts.use_ncurses_terminal == 1) + { + ncursesOpen(); + ncursesPrinter(&opts, &state); + } - if (opts.resume > 0) + if (opts.resume > 0) { openSerial (&opts, &state); } @@ -1026,24 +1036,7 @@ main (int argc, char **argv) } openAudioInDevice (&opts); - /* - setlocale(LC_ALL, ""); - sleep(3); - initscr(); //Initialize NCURSES screen window - start_color(); - init_pair(1, COLOR_YELLOW, COLOR_BLACK); //Yellow/Amber for frame sync/control channel, NV style - init_pair(2, COLOR_RED, COLOR_BLACK); //Red for Terminated Calls - init_pair(3, COLOR_GREEN, COLOR_BLACK); //Green for Active Calls - init_pair(4, COLOR_CYAN, COLOR_BLACK); //Cyan for Site Extra and Patches - init_pair(5, COLOR_MAGENTA, COLOR_BLACK); //Magenta for no frame sync/signal - noecho(); - cbreak(); - erase(); - for (short int i = 0; i < 7; i++) { - printw("%s \n", FM_banner[i]); } - attroff(COLOR_PAIR(4)); - refresh(); - */ + fprintf (stderr,"Press CTRL + C twice to close.\n"); //Kindly remind user to double tap CTRL + C } @@ -1067,7 +1060,10 @@ main (int argc, char **argv) { liveScanner (&opts, &state); } + if (opts.use_ncurses_terminal == 1){ + ncursesClose (); + } cleanupAndExit (&opts, &state); - //endwin(); + return (0); } diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c new file mode 100644 index 0000000..4f1117c --- /dev/null +++ b/src/dsd_ncurses.c @@ -0,0 +1,102 @@ +/*------------------------------------------------------------------------------- + * dsd_ncurses.c + * A dsd ncurses terminal printer + * + * ASCII art generated by: + * https://fsymbols.com/generators/carty/ + * + * LWVMOBILE + * 2022-02 DSD-FME Florida Man Edition + *-----------------------------------------------------------------------------*/ + /* + * Copyright (C) 2010 DSD Author + * GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0) + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "dsd.h" +#include "git_ver.h" +char versionstr[25]; +char * FM_bannerN[9] = { + " CTRL + C twice to exit", + " ██████╗ ██████╗██████╗    ███████╗███╗ ███╗███████╗", + " ██╔══██╗██╔════╝██╔══██╗   ██╔════╝████╗ ████║██╔════╝", + " ██║ ██║╚█████╗ ██║ ██║   █████╗ ██╔████╔██║█████╗ ", + " ██║ ██║ ╚═══██╗██║ ██║   ██╔══╝ ██║╚██╔╝██║██╔══╝ ", + " ██████╔╝██████╔╝██████╔╝   ██║ ██║ ╚═╝ ██║███████╗", + " ╚═════╝ ╚═════╝ ╚═════╝    ╚═╝ ╚═╝ ╚═╝╚══════╝", +}; + +time_t nowN; +char * getTimeN(void) //get pretty hh:mm:ss timestamp +{ + time_t t = time(NULL); + + char * curr; + char * stamp = asctime(localtime( & t)); + + curr = strtok(stamp, " "); + curr = strtok(NULL, " "); + curr = strtok(NULL, " "); + curr = strtok(NULL, " "); + + return curr; +} + +void ncursesOpen () +{ + mbe_printVersion (versionstr); + //setlocale(LC_ALL, ""); + initscr(); //Initialize NCURSES screen window + start_color(); + init_pair(1, COLOR_YELLOW, COLOR_BLACK); //Yellow/Amber for frame sync/control channel, NV style + init_pair(2, COLOR_RED, COLOR_BLACK); //Red for Terminated Calls + init_pair(3, COLOR_GREEN, COLOR_BLACK); //Green for Active Calls + init_pair(4, COLOR_CYAN, COLOR_BLACK); //Cyan for Site Extra and Patches + init_pair(5, COLOR_MAGENTA, COLOR_BLACK); //Magenta for no frame sync/signal + noecho(); + cbreak(); +} + +void +ncursesPrinter (dsd_opts * opts, dsd_state * state) +{ + erase(); + //disabling until wide support can be built for LM, etc. $(ncursesw5-config --cflags --libs) + //printw("%s \n", FM_bannerN[0]); //top line in white + //attron(COLOR_PAIR(4)); + //for (short int i = 1; i < 7; i++) { //following lines in cyan + //printw("%s \n", FM_bannerN[i]); } + //attroff(COLOR_PAIR(4)); + printw("Digital Speech Decoder: Florida Man Edition\n"); + printw("mbelib version %s\n", versionstr); + printw("Time: "); + printw("%s ", getTimeN()); + if (state->lastsynctype == 8 ||state->lastsynctype == 9 ||state->lastsynctype == 16 ||state->lastsynctype == 17) + { + printw("NXDN"); + } + printw("\n"); //line return + //add other interesting info to put here + + refresh(); + +} + +void ncursesClose () +{ + erase(); + refresh(); + endwin(); +}