diff --git a/include/dsd.h b/include/dsd.h
index dcd01b8..3e95053 100644
--- a/include/dsd.h
+++ b/include/dsd.h
@@ -331,11 +331,10 @@ typedef struct
int rigctlportno;
char rigctlhostname[1024];
- //udp socket for GQRX, SDR++, etc
+ //UDP Socket Blaster Audio
int udp_sockfd;
int udp_portno;
- char * udp_hostname;
- SNDFILE *udp_file_in;
+ char udp_hostname[1024];
//tcp socket for SDR++, etc
int tcp_sockfd;
@@ -1224,6 +1223,10 @@ int csvChanImport(dsd_opts * opts, dsd_state * state);
int csvKeyImportDec(dsd_opts * opts, dsd_state * state);
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_blaster(dsd_opts * opts, dsd_state * state, size_t nsam, void * data);
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/src/dsd_main.c b/src/dsd_main.c
index 6708662..b251337 100644
--- a/src/dsd_main.c
+++ b/src/dsd_main.c
@@ -675,10 +675,10 @@ initOpts (dsd_opts * opts)
opts->rigctlportno = 4532; //TCP Port Number; GQRX - 7356; SDR++ - 4532
sprintf (opts->rigctlhostname, "%s", "localhost");
- //udp input options
+ //UDP Socket Blaster Audio
opts->udp_sockfd = 0;
- opts->udp_portno = 7355; //default favored by GQRX and SDR++
- opts->udp_hostname = "localhost";
+ opts->udp_portno = 23456; //default port, same os OP25's sockaudio.py
+ sprintf (opts->udp_hostname, "%s", "0.0.0.0");
//tcp input options
opts->tcp_sockfd = 0;
@@ -1203,6 +1203,8 @@ usage ()
printf (" /dev/dsp for OSS audio (Depreciated: Will require padsp wrapper in Linux) \n");
#endif
printf (" null for no audio output\n");
+ printf (" udp for UDP socket blaster output (default host 0.0.0.0 (broadcast) default port 23456)\n");
+ printf (" udp:127.0.0.1:23470 for UDP socket blaster output (Custom Address and Port\n");
printf (" -d
Create mbe data files, use this directory (TDMA version is experimental)\n");
printf (" -r Read/Play saved mbe data from file(s)\n");
printf (" -g Audio Output Gain (Default: 0 = Auto; )\n");
@@ -1470,6 +1472,9 @@ cleanupAndExit (dsd_opts * opts, dsd_state * state)
ncursesClose(opts);
}
+ if (opts->udp_sockfd)
+ close (opts->udp_sockfd);
+
//close MBE out files
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
@@ -2611,6 +2616,50 @@ main (int argc, char **argv)
opts.audio_in_type = 0;
}
+ //UDP Socket Blaster Audio Output Setup
+ if((strncmp(opts.audio_out_dev, "udp", 3) == 0))
+ {
+
+ //read in values
+ fprintf (stderr, "UDP Blaster Output: ");
+ char * curr;
+
+ curr = strtok(opts.audio_out_dev, ":"); //should be 'udp'
+ if (curr != NULL) ; //continue
+ else goto UDPEND; //end early with preset values
+
+ curr = strtok(NULL, ":"); //udp blaster hostname
+ if (curr != NULL)
+ strncpy (opts.udp_hostname, curr, 1023); //set address to blast to
+
+ curr = strtok(NULL, ":"); //udp blaster port
+ if (curr != NULL)
+ opts.udp_portno = atoi (curr);
+
+ UDPEND:
+ fprintf (stderr, "%s:", opts.udp_hostname);
+ fprintf (stderr, "%d \n", opts.udp_portno);
+
+ int err = udp_socket_connect(&opts, &state);
+ if (err < 0)
+ {
+ fprintf (stderr, "Error Configuring UDP Socket for UDP Blaster Audio :( \n");
+ #ifdef AERO_BUILD
+ sprintf (opts.audio_in_dev, "%s", "/dev/dsp");
+ opts.audio_in_type = 5;
+ //since I can't determine what the configuration will be for 48k1 or 8k2 here(lazy), need to exit
+ exitflag = 1;
+ #else
+ sprintf (opts.audio_out_dev, "%s", "pulse");
+ opts.audio_out_type = 0;
+ #endif
+
+ }
+
+ opts.audio_out_type = 8;
+
+ }
+
if((strncmp(opts.audio_out_dev, "pulse", 5) == 0))
{
opts.audio_out_type = 0;
diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c
index 4f413b1..dd030b5 100644
--- a/src/dsd_ncurses.c
+++ b/src/dsd_ncurses.c
@@ -185,6 +185,22 @@ void beeper (dsd_opts * opts, dsd_state * state, int lr)
}
+ else if (opts->audio_out_type == 8) //UDP Audio
+ {
+ if (opts->pulse_digi_out_channels == 2 && opts->floating_point == 1)
+ udp_socket_blaster (opts, state, 320*4, samp_fs);
+
+ if (opts->pulse_digi_out_channels == 1 && opts->floating_point == 1)
+ udp_socket_blaster (opts, state, 160*4, samp_f);
+
+ if (opts->pulse_digi_out_channels == 2 && opts->floating_point == 0)
+ udp_socket_blaster (opts, state, 320*2, samp_ss);
+
+ if (opts->pulse_digi_out_channels == 1 && opts->floating_point == 0)
+ udp_socket_blaster (opts, state, 160*2, samp_s);
+
+ }
+
else if (opts->audio_out_type == 1) //STDOUT
{
if (opts->pulse_digi_out_channels == 2 && opts->floating_point == 1)
@@ -454,10 +470,6 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
sf_close(opts->tcp_file_in);
}
- if (opts->audio_in_type == 5) //close UDP input SF file so we don't buffer audio while not decoding
- {
- // sf_close(opts->udp_file_in); //disable for testing
- }
state->payload_keyid = 0;
state->payload_keyidR = 0;
@@ -1810,10 +1822,6 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
opts->tcp_file_in = sf_open_fd(opts->tcp_sockfd, SFM_READ, opts->audio_in_file_info, 0);
}
- if (opts->audio_in_type == 5) //re-open UDP input 'file'
- {
- // opts->udp_file_in = sf_open_fd(opts->udp_sockfd, SFM_READ, opts->audio_in_file_info, 0);
- }
//update sync time on cc sync so we don't immediately go CC hunting when exiting the menu
state->last_cc_sync_time = time(NULL);
@@ -2346,6 +2354,18 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw (" \n");
}
+ if (opts->audio_out_type == 8)
+ {
+ printw ("| UDP Audio Output: %s:%d; %d kHz %d Ch; %02.0f%%", opts->udp_hostname, opts->udp_portno, opts->pulse_digi_rate_out/1000, opts->pulse_digi_out_channels, state->aout_gain*2);
+ if (opts->pulse_digi_out_channels == 2) printw (" G: %02.0f%%", state->aout_gainR*2);
+ if (opts->audio_gain == 0) printw (" (+/-) Auto");
+ if (opts->audio_gain > 0) printw (" (+/-) Manual");
+ if (opts->call_alert == 1) printw (" *CA!"); //Call Alert
+ 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->monitor_input_audio == 1)
// {
// printw ("| Monitoring Source Audio when Carrier Present and No Sync Detected (WIP)\n");
diff --git a/src/dsd_rigctl.c b/src/dsd_rigctl.c
index 8f21c06..24ba02a 100644
--- a/src/dsd_rigctl.c
+++ b/src/dsd_rigctl.c
@@ -30,6 +30,8 @@ void error(char *msg) {
exit(0);
}
+struct sockaddr_in address;
+
//
// Connect
//
@@ -281,42 +283,58 @@ void rtl_udp_tune(dsd_opts * opts, dsd_state * state, long int frequency)
close (handle); //close socket after sending.
}
-// int udp_sock_con(dsd_opts * opts, dsd_state * state)
-// {
-// UNUSED(state);
-// UNUSED(opts);
+int udp_socket_blaster(dsd_opts * opts, dsd_state * state, size_t nsam, void * data)
+{
+ UNUSED(state);
+ size_t err = 0;
-// int handle, err; //convert handle and address to state variables
-// handle = err = 0;
-// unsigned short udp_port = 9999;
-// struct sockaddr_in address;
-// handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-// if (handle != 0)
-// {
-// fprintf (stderr, " UDP Socket Error \n");
-// return (handle);
-// }
-// memset((char * ) & address, 0, sizeof(address));
-// address.sin_family = AF_INET;
-// err = address.sin_addr.s_addr = inet_addr("127.0.0.1"); //make user configurable later
-// if (err != 0)
-// {
-// fprintf (stderr, " UDP inet_addr Error \n");
-// return (err);
-// }
-// address.sin_port = htons(udp_port);
-// if (err != 0)
-// {
-// fprintf (stderr, " UDP htons Error \n");
-// return (err);
-// }
-// // close (handle); //close socket after sending. //leave open for the blaster
-// }
+ //listen with:
-// int udp_sock_send(dsd_opts * opts, dsd_state * state, short samp[320])
-// {
-// UNUSED(state);
-// UNUSED(opts);
+ //short 8k/2
+ //socat stdio udp-listen:23456 | play -q -b 16 -r 8000 -c2 -t s16 -
-// sendto(handle, samp, 320, 0, (const struct sockaddr * ) & address, sizeof(struct sockaddr_in));
-// }
\ No newline at end of file
+ //short 48k/2
+ //socat stdio udp-listen:23456 | play -q -b 16 -r 48000 -c2 -t s16 -
+
+ //float 8k/2
+ //socat stdio udp-listen:23456 | play -q -e float -b 32 -r 8000 -c2 -t f32 -
+
+ //float 8k/1
+ //socat stdio udp-listen:23456 | play -q -e float -b 32 -r 8000 -c1 -t f32 -
+
+ //send audio or data to socket
+ err = sendto(opts->udp_sockfd, data, nsam, 0, (const struct sockaddr * ) & address, sizeof(struct sockaddr_in));
+ if (err < 0) fprintf (stderr, "\n UDP SENDTO ERR %d", err); //return value here is size_t number of characters sent, or -1 for failure
+ if (err < nsam) fprintf (stderr, "\n UDP Underflow %d", err); //I'm not even sure if this is possible
+}
+
+int udp_socket_connect(dsd_opts * opts, dsd_state * state)
+{
+ UNUSED(state);
+ UNUSED(opts);
+
+ int handle, err; //convert handle and address to state variables
+ handle = err = 0;
+ unsigned short udp_port = opts->udp_portno;
+ opts->udp_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (opts->udp_sockfd < 0) //is this correct?
+ {
+ fprintf (stderr, " UDP Socket Error \n");
+ return (handle);
+ }
+ memset((char * ) & address, 0, sizeof(address));
+ address.sin_family = AF_INET;
+ err = address.sin_addr.s_addr = inet_addr(opts->udp_hostname);
+ if (err < 0)
+ {
+ fprintf (stderr, " UDP inet_addr Error \n");
+ return (err);
+ }
+ address.sin_port = htons(udp_port);
+ if (err < 0)
+ {
+ fprintf (stderr, " UDP htons Error \n");
+ return (err);
+ }
+
+}