mirror of https://github.com/lwvmobile/dsd-fme.git
UDP Audio Output -- Initial Setup;
This commit is contained in:
parent
b2f6b158e3
commit
0c86ba29fc
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 <dir> Create mbe data files, use this directory (TDMA version is experimental)\n");
|
||||
printf (" -r <files> Read/Play saved mbe data from file(s)\n");
|
||||
printf (" -g <float> 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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
// }
|
||||
//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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue