From 43d63b20dccc06af2493f90f0ad40b43cf4cadbf Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Sat, 13 Jun 2026 16:08:29 -0400 Subject: [PATCH] WAV: Add custom tag option for per-call wav files; #352 --- .../cygwin_bat/complete_usage_options.txt | 5 ++- include/dsd.h | 3 +- src/dsd_events.c | 4 +- src/dsd_file.c | 41 +++++++++++++++++-- src/dsd_main.c | 16 ++++++-- src/dsd_ncurses_handler.c | 4 +- src/dsd_ncurses_menu.c | 4 +- src/edacs-fme.c | 16 ++++---- 8 files changed, 69 insertions(+), 24 deletions(-) diff --git a/examples/cygwin_bat/complete_usage_options.txt b/examples/cygwin_bat/complete_usage_options.txt index fd5f099..b77a705 100644 --- a/examples/cygwin_bat/complete_usage_options.txt +++ b/examples/cygwin_bat/complete_usage_options.txt @@ -1,4 +1,4 @@ -Build Version: AW 2026-1-g99f4228 +Build Version: AW 2026-29-ge6d2dd7 MBElib Version: 1.3.4 CODEC2 Support Enabled @@ -50,6 +50,8 @@ Input/Output options: -w Output synthesized speech to a single static .wav file. (Do not use with -P Per Call Switch) -P Enable Per Call WAV file saving. (Do not use with -w filename.wav single wav file switch) (Per Call works with everything now and doesn't require ncurses terminal!) + -j Custom Tag(s), colon delimted, to append to Per Call decoded .wav files. + -j TGT_LAPD:TAG_FIRE:FREQ_851987500 (Total 3 Tags, Maximum Letter Length = 100) -a Enable Call Alert Beep (Warning! Might be annoying.) -J Specify Filename for Event Log Output. @@ -222,4 +224,3 @@ Advanced Decoder options: Trunking Example TCP: dsd-fme -fs -i tcp -U 4532 -T -C dmr_t3_chan.csv -G group.csv -N 2> log.txt Trunking Example RTL: dsd-fme -fs -i rtl:0:450M:26:-2:8 -T -C connect_plus_chan.csv -G group.csv -N 2> log.txt - diff --git a/include/dsd.h b/include/dsd.h index 1b9144c..f883fcf 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -324,6 +324,7 @@ typedef struct char wav_out_file[1024]; char wav_out_fileR[1024]; char wav_out_file_raw[1024]; + char wav_custom_tag[100]; char symbol_out_file[1024]; char lrrp_out_file[1024]; char event_out_file[1024]; @@ -1185,7 +1186,7 @@ void openWavOutFileLR (dsd_opts * opts, dsd_state * state); //stereo wav file fo void openWavOutFileRaw (dsd_opts * opts, dsd_state * state); SNDFILE * open_wav_file (char * dir, char * temp_filename, uint16_t sample_rate, uint8_t ext); SNDFILE * close_wav_file(SNDFILE * wav_file); -SNDFILE * close_and_rename_wav_file(SNDFILE * wav_file, char * wav_out_filename, char * dir, Event_History_I * event_struct); +SNDFILE * close_and_rename_wav_file(SNDFILE * wav_file, char * wav_out_filename, char * dir, char * custom_tag, Event_History_I * event_struct); SNDFILE * close_and_delete_wav_file(SNDFILE * wav_file, char * wav_out_filename); void openSymbolOutFile (dsd_opts * opts, dsd_state * state); void closeSymbolOutFile (dsd_opts * opts, dsd_state * state); diff --git a/src/dsd_events.c b/src/dsd_events.c index 18f61cf..1bfd16f 100644 --- a/src/dsd_events.c +++ b/src/dsd_events.c @@ -218,13 +218,13 @@ void watchdog_event_history (dsd_opts * opts, dsd_state * state, uint8_t slot) if (slot == 0 && opts->wav_out_f != NULL) { - opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, event_struct); + opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, opts->wav_custom_tag, event_struct); opts->wav_out_f = open_wav_file(opts->wav_out_dir, opts->wav_out_file, 8000, 0); } else if (slot == 1 && opts->wav_out_fR != NULL) { - opts->wav_out_fR = close_and_rename_wav_file(opts->wav_out_fR, opts->wav_out_fileR, opts->wav_out_dir, event_struct); + opts->wav_out_fR = close_and_rename_wav_file(opts->wav_out_fR, opts->wav_out_fileR, opts->wav_out_dir, opts->wav_custom_tag, event_struct); opts->wav_out_fR = open_wav_file(opts->wav_out_dir, opts->wav_out_fileR, 8000, 0); } diff --git a/src/dsd_file.c b/src/dsd_file.c index f252888..9308a8a 100644 --- a/src/dsd_file.c +++ b/src/dsd_file.c @@ -502,7 +502,7 @@ SNDFILE * close_wav_file(SNDFILE * wav_file) return wav_file; } -SNDFILE * close_and_rename_wav_file(SNDFILE * wav_file, char * wav_out_filename, char * dir, Event_History_I * event_struct) +SNDFILE * close_and_rename_wav_file(SNDFILE * wav_file, char * wav_out_filename, char * dir, char * custom_tag, Event_History_I * event_struct) { sf_close(wav_file); @@ -538,11 +538,46 @@ SNDFILE * close_and_rename_wav_file(SNDFILE * wav_file, char * wav_out_filename, char new_filename[2000]; memset (new_filename, 0, sizeof(new_filename)); + //parse any possible custom tags or aliasing (up to 3) + char custom_string_temp[100]; + memset(custom_string_temp, 0, sizeof(custom_string_temp)); + memcpy(custom_string_temp, custom_tag, sizeof(custom_string_temp)); + char * token = strtok(custom_string_temp, ":"); + char tag[3][25]; + memset(tag, 0, sizeof(tag)); + sprintf(tag[0], "%s", ""); + sprintf(tag[1], "%s", ""); + sprintf(tag[2], "%s", ""); + + for (int i = 0; i < 3; i++) + { + + if (token != NULL) + { + tag[i][0] = '_'; + strncpy(tag[i]+1, token, 23); + tag[i][24] = '\0'; + token = strtok(NULL, ":"); + + //look for _TGT_, convert to strings + if (strncmp("_TGT_", tag[i], 5) == 0) + { + sprintf (tgt_str, "%s", tag[i]+5); + sprintf (src_str, "%d", source_id); + is_string = 1; + memset(tag[i], 0, sizeof(tag[i])); + sprintf(tag[i], "%s", ""); + } + + } + else break; + } + //check for String based TGT and SRC values (M17, YSF, DSTAR) if (is_string == 1) - sprintf (new_filename, "%s/%s_%s_%05d_%s_%s_TGT_%s_SRC_%s.wav", dir, datestr, timestr, random_number, sys_str, gi_str, tgt_str, src_str); + sprintf (new_filename, "%s/%s_%s_%05d_%s_%s%s%s%s_TGT_%s_SRC_%s.wav", dir, datestr, timestr, random_number, sys_str, gi_str, tag[0], tag[1], tag[2], tgt_str, src_str); else //is a numerical value - sprintf (new_filename, "%s/%s_%s_%05d_%s_%s_TGT_%d_SRC_%d.wav", dir, datestr, timestr, random_number, sys_str, gi_str, target_id, source_id); + sprintf (new_filename, "%s/%s_%s_%05d_%s_%s%s%s%s_TGT_%d_SRC_%d.wav", dir, datestr, timestr, random_number, sys_str, gi_str, tag[0], tag[1], tag[2], target_id, source_id); if (timestr != NULL) { diff --git a/src/dsd_main.c b/src/dsd_main.c index 288ee66..f073771 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -636,6 +636,7 @@ opts->wav_out_file[0] = 0; opts->wav_out_fileR[0] = 0; opts->wav_out_file_raw[0] = 0; + opts->wav_custom_tag[0] = 0; opts->symbol_out_file[0] = 0; opts->lrrp_out_file[0] = 0; opts->event_out_file[0] = 0; @@ -1436,6 +1437,8 @@ printf (" -w Output synthesized speech to a single static .wav file. (Do not use with -P Per Call Switch)\n"); printf (" -P Enable Per Call WAV file saving. (Do not use with -w filename.wav single wav file switch)\n"); printf (" (Per Call works with everything now and doesn't require ncurses terminal!)\n"); + printf (" -j Custom Tag(s), colon delimted, to append to Per Call decoded .wav files.\n"); + printf (" -j TGT_LAPD:TAG_FIRE:FREQ_851987500 (Total 3 Tags, Maximum Letter Length = 100)\n"); printf (" -a Enable Call Alert Beep\n"); printf (" (Warning! Might be annoying.)\n"); printf (" -J Specify Filename for Event Log Output.\n"); @@ -1776,10 +1779,10 @@ if (opts->static_wav_file == 0) { if (opts->wav_out_f != NULL) - opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, &state->event_history_s[0]); + opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, opts->wav_custom_tag, &state->event_history_s[0]); if (opts->wav_out_fR != NULL) - opts->wav_out_fR = close_and_rename_wav_file(opts->wav_out_fR, opts->wav_out_fileR, opts->wav_out_dir, &state->event_history_s[1]); + opts->wav_out_fR = close_and_rename_wav_file(opts->wav_out_fR, opts->wav_out_fileR, opts->wav_out_dir, opts->wav_custom_tag, &state->event_history_s[1]); } else if (opts->static_wav_file == 1) @@ -1895,7 +1898,7 @@ exitflag = 0; - while ((c = getopt (argc, argv, "~yhaepPqs:t:v:z:i:o:d:c:g:n:w:B:C:R:f:m:u:x:A:S:G:D:L:V:U:YK:b:H:X:M:NQ:WrlZTF@:!:01:2:345:6:^:7:8_:9:Ek:I:J:O+:")) != -1) + while ((c = getopt (argc, argv, "~yhaepPqs:t:v:z:i:o:d:c:g:n:w:B:C:R:f:m:u:x:A:S:G:D:L:V:U:YK:b:H:X:M:NQ:WrlZTF@:!:01:2:345:6:^:7:8_:9:Ek:I:J:O+:j:")) != -1) { switch (c) @@ -1909,7 +1912,7 @@ opts.call_alert = 1; break; - //Free'd up switches include: j, M, + //NOTE: Don't use -*, found it exhibits unusual behavior, was setting //itself to -3 for some reason, may be reading contents of directory @@ -1918,6 +1921,11 @@ //NOTE: The 'K' option for single BP key has been swapped to 'b' //'K' is now used for hexidecimal key.csv imports + + case 'j': //custom wav tags appended to per-call wav files + strncpy(opts.wav_custom_tag, optarg, 99); + opts.wav_custom_tag[99] = '\0'; + break; //this is a debug option hidden from users, but use it to replay .bin files on loop case '~': diff --git a/src/dsd_ncurses_handler.c b/src/dsd_ncurses_handler.c index fb88dff..33fb038 100644 --- a/src/dsd_ncurses_handler.c +++ b/src/dsd_ncurses_handler.c @@ -379,8 +379,8 @@ uint8_t ncurses_input_handler(dsd_opts * opts, dsd_state * state, int c) if (c == 112) //'p' key - stop all per call wav files //TODO: Fix { //TODO: Add Closing of RAW files as well? - opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, &state->event_history_s[0]); - opts->wav_out_fR = close_and_rename_wav_file(opts->wav_out_fR, opts->wav_out_fileR, opts->wav_out_dir, &state->event_history_s[1]); + opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, opts->wav_custom_tag, &state->event_history_s[0]); + opts->wav_out_fR = close_and_rename_wav_file(opts->wav_out_fR, opts->wav_out_fileR, opts->wav_out_dir, opts->wav_custom_tag, &state->event_history_s[1]); opts->wav_out_file[0] = 0; //Bugfix for decoded wav file display after disabling opts->wav_out_fileR[0] = 0; opts->dmr_stereo_wav = 0; diff --git a/src/dsd_ncurses_menu.c b/src/dsd_ncurses_menu.c index a3d64b1..a44ee8c 100644 --- a/src/dsd_ncurses_menu.c +++ b/src/dsd_ncurses_menu.c @@ -694,8 +694,8 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state) if (choicec == 12) { //TODO: Add Closing of RAW files as well? - opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, &state->event_history_s[0]); - opts->wav_out_fR = close_and_rename_wav_file(opts->wav_out_fR, opts->wav_out_fileR, opts->wav_out_dir, &state->event_history_s[1]); + opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, opts->wav_custom_tag, &state->event_history_s[0]); + opts->wav_out_fR = close_and_rename_wav_file(opts->wav_out_fR, opts->wav_out_fileR, opts->wav_out_dir, opts->wav_custom_tag, &state->event_history_s[1]); opts->wav_out_file[0] = 0; //Bugfix for decoded wav file display after disabling opts->wav_out_fileR[0] = 0; opts->dmr_stereo_wav = 0; diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 40377cc..9aae2d3 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -1098,7 +1098,7 @@ void edacs(dsd_opts * opts, dsd_state * state) if (is_digital == 1) {} //just write to already open temp file to be renamed later else //close the temp 8k wav file and open as 48k { - opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, &state->event_history_s[0]); + opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, opts->wav_custom_tag, &state->event_history_s[0]); opts->wav_out_f = open_wav_file(opts->wav_out_dir, opts->wav_out_file, 48000, 0); } } @@ -1214,7 +1214,7 @@ void edacs(dsd_opts * opts, dsd_state * state) if (is_digital == 1) {} //just write to already open temp file to be renamed later else //close the temp 8k wav file and open as 48k { - opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, &state->event_history_s[0]); + opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, opts->wav_custom_tag, &state->event_history_s[0]); opts->wav_out_f = open_wav_file(opts->wav_out_dir, opts->wav_out_file, 48000, 0); } } @@ -1321,7 +1321,7 @@ void edacs(dsd_opts * opts, dsd_state * state) if (is_digital == 1) {} //just write to already open temp file to be renamed later else //close the temp 8k wav file and open as 48k { - opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, &state->event_history_s[0]); + opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, opts->wav_custom_tag, &state->event_history_s[0]); opts->wav_out_f = open_wav_file(opts->wav_out_dir, opts->wav_out_file, 48000, 0); } } @@ -1501,7 +1501,7 @@ void edacs(dsd_opts * opts, dsd_state * state) if (is_digital == 1) {} //just write to already open temp file to be renamed later else //close the temp 8k wav file and open as 48k { - opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, &state->event_history_s[0]); + opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, opts->wav_custom_tag, &state->event_history_s[0]); opts->wav_out_f = open_wav_file(opts->wav_out_dir, opts->wav_out_file, 48000, 0); } } @@ -1757,7 +1757,7 @@ void edacs(dsd_opts * opts, dsd_state * state) if (is_digital == 1) {} //just write to already open temp file to be renamed later else //close the temp 8k wav file and open as 48k { - opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, &state->event_history_s[0]); + opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, opts->wav_custom_tag, &state->event_history_s[0]); opts->wav_out_f = open_wav_file(opts->wav_out_dir, opts->wav_out_file, 48000, 0); } } @@ -1870,7 +1870,7 @@ void edacs(dsd_opts * opts, dsd_state * state) if (is_digital == 1) {} //just write to already open temp file to be renamed later else //close the temp 8k wav file and open as 48k { - opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, &state->event_history_s[0]); + opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, opts->wav_custom_tag, &state->event_history_s[0]); opts->wav_out_f = open_wav_file(opts->wav_out_dir, opts->wav_out_file, 48000, 0); } } @@ -2166,7 +2166,7 @@ void edacs(dsd_opts * opts, dsd_state * state) if (is_digital == 1) {} //just write to already open temp file to be renamed later else //close the temp 8k wav file and open as 48k { - opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, &state->event_history_s[0]); + opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, opts->wav_custom_tag, &state->event_history_s[0]); opts->wav_out_f = open_wav_file(opts->wav_out_dir, opts->wav_out_file, 48000, 0); } } @@ -2312,7 +2312,7 @@ void eot_cc(dsd_opts * opts, dsd_state * state) if (opts->dmr_stereo_wav == 1) { if (opts->wav_out_f != NULL) - opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, &state->event_history_s[0]); + opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, opts->wav_custom_tag, &state->event_history_s[0]); opts->wav_out_f = open_wav_file(opts->wav_out_dir, opts->wav_out_file, 8000, 0); }