diff --git a/include/dsd.h b/include/dsd.h index c9afab1..b2201dc 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -332,7 +332,8 @@ typedef struct char rigctlhostname[1024]; //UDP Socket Blaster Audio - int udp_sockfd; + int udp_sockfd; //digital + int udp_sockfdA; //analog 48k1 int udp_portno; char udp_hostname[1024]; @@ -1265,7 +1266,9 @@ int csvKeyImportHex(dsd_opts * opts, dsd_state * state); //UDP Socket Connect and UDP Socket Blaster (audio output) int udp_socket_connect(dsd_opts * opts, dsd_state * state); +int udp_socket_connectA(dsd_opts * opts, dsd_state * state); int udp_socket_blaster(dsd_opts * opts, dsd_state * state, size_t nsam, void * data); +int udp_socket_blasterA(dsd_opts * opts, dsd_state * state, size_t nsam, void * data); #ifdef __cplusplus extern "C" { diff --git a/src/dsd_main.c b/src/dsd_main.c index 5bf51eb..d116ac4 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -696,7 +696,8 @@ initOpts (dsd_opts * opts) sprintf (opts->rigctlhostname, "%s", "localhost"); //UDP Socket Blaster Audio - opts->udp_sockfd = 0; + opts->udp_sockfd = 0; + opts->udp_sockfdA = 0; opts->udp_portno = 23456; //default port, same os OP25's sockaudio.py sprintf (opts->udp_hostname, "%s", "127.0.0.1"); @@ -1510,6 +1511,9 @@ cleanupAndExit (dsd_opts * opts, dsd_state * state) if (opts->udp_sockfd) close (opts->udp_sockfd); + if (opts->udp_sockfdA) + close (opts->udp_sockfdA); + //close MBE out files if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state); if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state); @@ -2743,8 +2747,23 @@ main (int argc, char **argv) if (opts.monitor_input_audio == 1 || opts.frame_provoice == 1) { - fprintf (stderr, "NOTICE: Raw Audio Monitoring and Analog Calls Unavailable over UDP Audio Output\n"); - opts.monitor_input_audio = 0; + err = udp_socket_connectA(&opts, &state); + if (err < 0) + { + fprintf (stderr, "Error Configuring UDP Socket for UDP Blaster Audio Analog :( \n"); + opts.udp_sockfdA = 0; + opts.monitor_input_audio = 0; + } + else + { + fprintf (stderr, "UDP Blaster Output (Analog): "); + fprintf (stderr, "%s:", opts.udp_hostname); + fprintf (stderr, "%d \n", opts.udp_portno+2); + } + + //this functionality is disabled when trunking EDACS, but we still use the behavior for analog channel monitoring + if (opts.frame_provoice == 1 && opts.p25_trunk == 1) + opts.monitor_input_audio = 0; } } diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 9d52440..982a178 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -2429,6 +2429,11 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) if ( (opts->audio_out_type == 5 && opts->pulse_digi_rate_out == 48000 && opts->pulse_digi_out_channels == 1) && (opts->frame_provoice == 1 || opts->monitor_input_audio == 1) ) printw (" - Monitor RMS: %04ld ", opts->rtl_rms); printw (" \n"); + if (opts->udp_sockfdA != 0) //Analog Output on udp port +2 + { + printw ("| UDP Audio Output: %s:%d; 48 kHz 1 Ch; Analog Output; ", opts->udp_hostname, opts->udp_portno+2); + printw (" \n"); + } } // if (opts->monitor_input_audio == 1) diff --git a/src/dsd_rigctl.c b/src/dsd_rigctl.c index edc8909..ee40b98 100644 --- a/src/dsd_rigctl.c +++ b/src/dsd_rigctl.c @@ -31,6 +31,7 @@ void error(char *msg) { } struct sockaddr_in address; +struct sockaddr_in addressA; // // Connect @@ -316,6 +317,23 @@ int udp_socket_blaster(dsd_opts * opts, dsd_state * state, size_t nsam, void * d if (err < nsam) fprintf (stderr, "\n UDP Underflow %ld", err); //I'm not even sure if this is possible } +//Analog UDP port on +2 of normal open socket +int udp_socket_blasterA(dsd_opts * opts, dsd_state * state, size_t nsam, void * data) +{ + UNUSED(state); + size_t err = 0; + + //listen with: + + //short 48k/1 + //socat stdio udp-listen:23456 | play --buffer 960*2 -q -b 16 -r 48000 -c1 -t s16 - + + //send audio or data to socket + err = sendto(opts->udp_sockfdA, data, nsam, 0, (const struct sockaddr * ) & addressA, sizeof(struct sockaddr_in)); + if (err < 0) fprintf (stderr, "\n UDP SENDTO ERR %ld", err); //return value here is size_t number of characters sent, or -1 for failure + if (err < nsam) fprintf (stderr, "\n UDP Underflow %ld", err); //I'm not even sure if this is possible +} + int udp_socket_connect(dsd_opts * opts, dsd_state * state) { UNUSED(state); @@ -354,3 +372,42 @@ int udp_socket_connect(dsd_opts * opts, dsd_state * state) } } + +int udp_socket_connectA(dsd_opts * opts, dsd_state * state) +{ + UNUSED(state); + + long int err = 0; + err = opts->udp_sockfdA = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (err < 0) + { + fprintf (stderr, " UDP Socket Error %ld\n", err); + return (err); + } + + // Don't think this is needed, but doesn't seem to hurt to keep it here either + int broadcastEnable = 1; + err = setsockopt(opts->udp_sockfdA, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable)); + if (err < 0) + { + fprintf (stderr, " UDP Broadcast Set Error %ld\n", err); + return (err); + } + + memset((char * ) & addressA, 0, sizeof(addressA)); + addressA.sin_family = AF_INET; + err = addressA.sin_addr.s_addr = inet_addr(opts->udp_hostname); + if (err < 0) //error in this context reports back 32-bit inet_addr reversed order byte pairs + { + fprintf (stderr, " UDP inet_addr Error %ld\n", err); + return (err); + } + + addressA.sin_port = htons(opts->udp_portno+2); //plus 2 to current port assignment for the analog port value + if (err < 0) + { + fprintf (stderr, " UDP htons Error %ld\n", err); + return (err); + } + +} diff --git a/src/dsd_symbol.c b/src/dsd_symbol.c index 265c332..036343f 100644 --- a/src/dsd_symbol.c +++ b/src/dsd_symbol.c @@ -311,7 +311,7 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync) pa_simple_write(opts->pulse_raw_dev_out, state->analog_out, 960*2, NULL); if (opts->audio_out_type == 8) - udp_socket_blaster (opts, state, 960*2, state->analog_out); + udp_socket_blasterA (opts, state, 960*2, state->analog_out); //NOTE: Worked okay earlier in Cygwin, so should be fine -- can only operate at 48k1, else slow mode lag diff --git a/src/edacs-fme.c b/src/edacs-fme.c index d2367cd..0670f94 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -338,9 +338,9 @@ void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn if (opts->audio_out_type == 8) //UDP Audio { - udp_socket_blaster (opts, state, 960*2, analog1); - udp_socket_blaster (opts, state, 960*2, analog2); - udp_socket_blaster (opts, state, 960*2, analog3); + udp_socket_blasterA (opts, state, 960*2, analog1); + udp_socket_blasterA (opts, state, 960*2, analog2); + udp_socket_blasterA (opts, state, 960*2, analog3); } //added a condition check so that if OSS output and 8K, switches to 48K when opening OSS @@ -798,9 +798,9 @@ void edacs(dsd_opts * opts, dsd_state * state) // goto ENDPV; // #endif - //skip analog calls on UDP Audio Output - if (command == 0xEE && opts->audio_out_type == 8) - goto ENDPV; + + + //this is working now with the new import setup if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0) ) //DE is digital encrypted, B is block @@ -865,7 +865,7 @@ void edacs(dsd_opts * opts, dsd_state * state) } - ENDPV: + free (timestr); //free allocated memory to prevent memory leak fprintf (stderr, "\n");