#include <gtk/gtk.h>
-#include <pulse/pulseaudio.h>
#include <pulse/glib-mainloop.h>
+#include <pulse/pulseaudio.h>
#include <pulse/simple.h>
-#include "radio.h"
-#include "receiver.h"
-#include "transmitter.h"
#include "audio.h"
#include "mode.h"
#include "new_protocol.h"
#include "old_protocol.h"
+#include "radio.h"
+#include "receiver.h"
+#include "transmitter.h"
int n_input_devices;
AUDIO_DEVICE input_devices[MAX_AUDIO_DEVICES];
// samples in large chunks if fed from digimode programs.
//
#define MICRINGLEN 6000
-static float *mic_ring_buffer=NULL;
-static int mic_ring_read_pt=0;
-static int mic_ring_write_pt=0;
+static float *mic_ring_buffer = NULL;
+static int mic_ring_read_pt = 0;
+static int mic_ring_write_pt = 0;
static pa_glib_mainloop *main_loop;
static pa_mainloop_api *main_loop_api;
static pa_operation *op;
static pa_context *pa_ctx;
-static pa_simple* microphone_stream;
+static pa_simple *microphone_stream;
static gint local_microphone_buffer_offset;
static float *local_microphone_buffer;
static GThread *mic_read_thread_id;
static gboolean running;
-gint local_microphone_buffer_size=720;
+gint local_microphone_buffer_size = 720;
GMutex audio_mutex;
-static void source_list_cb(pa_context *context,const pa_source_info *s,int eol,void *data) {
- int i;
- if(eol>0) {
- for(i=0;i<n_input_devices;i++) {
- g_print("Input: %d: %s (%s)\n",input_devices[i].index,input_devices[i].name,input_devices[i].description);
+static void source_list_cb(pa_context *context, const pa_source_info *s,
+ int eol, void *data) {
+ int i;
+ if (eol > 0) {
+ for (i = 0; i < n_input_devices; i++) {
+ g_print("Input: %d: %s (%s)\n", input_devices[i].index,
+ input_devices[i].name, input_devices[i].description);
+ }
+ g_mutex_unlock(&audio_mutex);
+ } else if (n_input_devices < MAX_AUDIO_DEVICES) {
+ input_devices[n_input_devices].name = g_new0(char, strlen(s->name) + 1);
+ strncpy(input_devices[n_input_devices].name, s->name, strlen(s->name));
+ input_devices[n_input_devices].description =
+ g_new0(char, strlen(s->description) + 1);
+ strncpy(input_devices[n_input_devices].description, s->description,
+ strlen(s->description));
+ input_devices[n_input_devices].index = s->index;
+ n_input_devices++;
}
- g_mutex_unlock(&audio_mutex);
- } else if(n_input_devices<MAX_AUDIO_DEVICES) {
- input_devices[n_input_devices].name=g_new0(char,strlen(s->name)+1);
- strncpy(input_devices[n_input_devices].name,s->name,strlen(s->name));
- input_devices[n_input_devices].description=g_new0(char,strlen(s->description)+1);
- strncpy(input_devices[n_input_devices].description,s->description,strlen(s->description));
- input_devices[n_input_devices].index=s->index;
- n_input_devices++;
- }
}
-static void sink_list_cb(pa_context *context,const pa_sink_info *s,int eol,void *data) {
- int i;
- if(eol>0) {
- for(i=0;i<n_output_devices;i++) {
- g_print("Output: %d: %s (%s)\n",output_devices[i].index,output_devices[i].name,output_devices[i].description);
+static void sink_list_cb(pa_context *context, const pa_sink_info *s, int eol,
+ void *data) {
+ int i;
+ if (eol > 0) {
+ for (i = 0; i < n_output_devices; i++) {
+ g_print("Output: %d: %s (%s)\n", output_devices[i].index,
+ output_devices[i].name, output_devices[i].description);
+ }
+ op = pa_context_get_source_info_list(pa_ctx, source_list_cb, NULL);
+ } else if (n_output_devices < MAX_AUDIO_DEVICES) {
+ output_devices[n_output_devices].name =
+ g_new0(char, strlen(s->name) + 1);
+ strncpy(output_devices[n_output_devices].name, s->name,
+ strlen(s->name));
+ output_devices[n_output_devices].description =
+ g_new0(char, strlen(s->description) + 1);
+ strncpy(output_devices[n_output_devices].description, s->description,
+ strlen(s->description));
+ output_devices[n_output_devices].index = s->index;
+ n_output_devices++;
}
- op=pa_context_get_source_info_list(pa_ctx,source_list_cb,NULL);
- } else if(n_output_devices<MAX_AUDIO_DEVICES) {
- output_devices[n_output_devices].name=g_new0(char,strlen(s->name)+1);
- strncpy(output_devices[n_output_devices].name,s->name,strlen(s->name));
- output_devices[n_output_devices].description=g_new0(char,strlen(s->description)+1);
- strncpy(output_devices[n_output_devices].description,s->description,strlen(s->description));
- output_devices[n_output_devices].index=s->index;
- n_output_devices++;
- }
}
static void state_cb(pa_context *c, void *userdata) {
- pa_context_state_t state;
+ pa_context_state_t state;
- state = pa_context_get_state(c);
+ state = pa_context_get_state(c);
-g_print("%s: %d\n",__FUNCTION__,state);
- switch (state) {
+ g_print("%s: %d\n", __FUNCTION__, state);
+ switch (state) {
// There are just here for reference
case PA_CONTEXT_UNCONNECTED:
-g_print("audio: state_cb: PA_CONTEXT_UNCONNECTED\n");
- break;
+ g_print("audio: state_cb: PA_CONTEXT_UNCONNECTED\n");
+ break;
case PA_CONTEXT_CONNECTING:
-g_print("audio: state_cb: PA_CONTEXT_CONNECTING\n");
- break;
+ g_print("audio: state_cb: PA_CONTEXT_CONNECTING\n");
+ break;
case PA_CONTEXT_AUTHORIZING:
-g_print("audio: state_cb: PA_CONTEXT_AUTHORIZING\n");
- break;
+ g_print("audio: state_cb: PA_CONTEXT_AUTHORIZING\n");
+ break;
case PA_CONTEXT_SETTING_NAME:
-g_print("audio: state_cb: PA_CONTEXT_SETTING_NAME\n");
- break;
+ g_print("audio: state_cb: PA_CONTEXT_SETTING_NAME\n");
+ break;
case PA_CONTEXT_FAILED:
-g_print("audio: state_cb: PA_CONTEXT_FAILED\n");
- g_mutex_unlock(&audio_mutex);
- break;
+ g_print("audio: state_cb: PA_CONTEXT_FAILED\n");
+ g_mutex_unlock(&audio_mutex);
+ break;
case PA_CONTEXT_TERMINATED:
-g_print("audio: state_cb: PA_CONTEXT_TERMINATED\n");
- g_mutex_unlock(&audio_mutex);
- break;
+ g_print("audio: state_cb: PA_CONTEXT_TERMINATED\n");
+ g_mutex_unlock(&audio_mutex);
+ break;
case PA_CONTEXT_READY:
-g_print("audio: state_cb: PA_CONTEXT_READY\n");
-// get a list of the output devices
- n_input_devices=0;
- n_output_devices=0;
- op = pa_context_get_sink_info_list(pa_ctx,sink_list_cb,NULL);
- break;
+ g_print("audio: state_cb: PA_CONTEXT_READY\n");
+ // get a list of the output devices
+ n_input_devices = 0;
+ n_output_devices = 0;
+ op = pa_context_get_sink_info_list(pa_ctx, sink_list_cb, NULL);
+ break;
default:
- g_print("audio: state_cb: unknown state %d\n",state);
- break;
- }
+ g_print("audio: state_cb: unknown state %d\n", state);
+ break;
+ }
}
void audio_get_cards() {
- g_mutex_init(&audio_mutex);
- g_mutex_lock(&audio_mutex);
- main_loop=pa_glib_mainloop_new(NULL);
- main_loop_api=pa_glib_mainloop_get_api(main_loop);
- pa_ctx=pa_context_new(main_loop_api,"linhpsdr");
- pa_context_connect(pa_ctx,NULL,0,NULL);
- pa_context_set_state_callback(pa_ctx, state_cb, NULL);
+ g_mutex_init(&audio_mutex);
+ g_mutex_lock(&audio_mutex);
+ main_loop = pa_glib_mainloop_new(NULL);
+ main_loop_api = pa_glib_mainloop_get_api(main_loop);
+ pa_ctx = pa_context_new(main_loop_api, "linhpsdr");
+ pa_context_connect(pa_ctx, NULL, 0, NULL);
+ pa_context_set_state_callback(pa_ctx, state_cb, NULL);
}
int audio_open_output(RECEIVER *rx) {
- int result=0;
- pa_sample_spec sample_spec;
- int err;
+ int result = 0;
+ pa_sample_spec sample_spec;
+ int err;
- if(rx->audio_name==NULL) {
- result=-1;
- } else {
- g_mutex_lock(&rx->local_audio_mutex);
- sample_spec.rate=48000;
- sample_spec.channels=2;
- sample_spec.format=PA_SAMPLE_FLOAT32NE;
-
-
- char stream_id[16];
- sprintf(stream_id,"RX-%d",rx->id);
-
- rx->playstream=pa_simple_new(NULL, // Use the default server.
- "piHPSDR", // Our application's name.
- PA_STREAM_PLAYBACK,
- rx->audio_name,
- stream_id, // Description of our stream.
- &sample_spec, // Our sample format.
- NULL, // Use default channel map
- NULL, // Use default buffering attributes.
- &err // error code if returns NULL
- );
-
- if(rx->playstream!=NULL) {
- rx->local_audio_buffer_offset=0;
- rx->local_audio_buffer=g_new0(float,2*rx->local_audio_buffer_size);
- g_print("%s: allocated local_audio_buffer %p size %ld bytes\n",__FUNCTION__,rx->local_audio_buffer,2*rx->local_audio_buffer_size*sizeof(float));
+ if (rx->audio_name == NULL) {
+ result = -1;
} else {
- result=-1;
- g_print("%s: pa-simple_new failed: err=%d\n",__FUNCTION__,err);
+ g_mutex_lock(&rx->local_audio_mutex);
+ sample_spec.rate = 48000;
+ sample_spec.channels = 2;
+ sample_spec.format = PA_SAMPLE_FLOAT32NE;
+
+ char stream_id[16];
+ sprintf(stream_id, "RX-%d", rx->id);
+
+ rx->playstream =
+ pa_simple_new(NULL, // Use the default server.
+ "piHPSDR", // Our application's name.
+ PA_STREAM_PLAYBACK, rx->audio_name,
+ stream_id, // Description of our stream.
+ &sample_spec, // Our sample format.
+ NULL, // Use default channel map
+ NULL, // Use default buffering attributes.
+ &err // error code if returns NULL
+ );
+
+ if (rx->playstream != NULL) {
+ rx->local_audio_buffer_offset = 0;
+ rx->local_audio_buffer =
+ g_new0(float, 2 * rx->local_audio_buffer_size);
+ g_print("%s: allocated local_audio_buffer %p size %ld bytes\n",
+ __FUNCTION__, rx->local_audio_buffer,
+ 2 * rx->local_audio_buffer_size * sizeof(float));
+ } else {
+ result = -1;
+ g_print("%s: pa-simple_new failed: err=%d\n", __FUNCTION__, err);
+ }
+ g_mutex_unlock(&rx->local_audio_mutex);
}
- g_mutex_unlock(&rx->local_audio_mutex);
- }
- return result;
+ return result;
}
static void *mic_read_thread(gpointer arg) {
- int rc;
- int err;
-
- g_print("%s: running=%d\n",__FUNCTION__,running);
- while(running) {
- g_mutex_lock(&audio_mutex);
- if(local_microphone_buffer==NULL) {
- running=0;
- } else {
- rc=pa_simple_read(microphone_stream,
- local_microphone_buffer,
- local_microphone_buffer_size*sizeof(float),
- &err);
- if(rc<0) {
- running=0;
- g_print("%s: returned %d error=%d (%s)\n",__FUNCTION__,rc,err,pa_strerror(err));
- } else {
- gint newpt;
- for(gint i=0;i<local_microphone_buffer_size;i++) {
- gfloat sample=local_microphone_buffer[i];
- switch(protocol) {
- case ORIGINAL_PROTOCOL:
- case NEW_PROTOCOL:
- //
- // put sample into ring buffer
- //
- if (mic_ring_buffer != NULL) {
- // the "existence" of the ring buffer is now guaranteed for 1 msec,
- // see audio_close_input().
- newpt=mic_ring_write_pt +1;
- if (newpt == MICRINGLEN) newpt=0;
- if (newpt != mic_ring_read_pt) {
- // buffer space available, do the write
- mic_ring_buffer[mic_ring_write_pt]=sample;
- // atomic update of mic_ring_write_pt
- mic_ring_write_pt=newpt;
+ int rc;
+ int err;
+
+ g_print("%s: running=%d\n", __FUNCTION__, running);
+ while (running) {
+ g_mutex_lock(&audio_mutex);
+ if (local_microphone_buffer == NULL) {
+ running = 0;
+ } else {
+ rc = pa_simple_read(microphone_stream, local_microphone_buffer,
+ local_microphone_buffer_size * sizeof(float),
+ &err);
+ if (rc < 0) {
+ running = 0;
+ g_print("%s: returned %d error=%d (%s)\n", __FUNCTION__, rc,
+ err, pa_strerror(err));
+ } else {
+ gint newpt;
+ for (gint i = 0; i < local_microphone_buffer_size; i++) {
+ gfloat sample = local_microphone_buffer[i];
+ switch (protocol) {
+ case ORIGINAL_PROTOCOL:
+ case NEW_PROTOCOL:
+ //
+ // put sample into ring buffer
+ //
+ if (mic_ring_buffer != NULL) {
+ // the "existence" of the ring buffer is now
+ // guaranteed for 1 msec, see audio_close_input().
+ newpt = mic_ring_write_pt + 1;
+ if (newpt == MICRINGLEN)
+ newpt = 0;
+ if (newpt != mic_ring_read_pt) {
+ // buffer space available, do the write
+ mic_ring_buffer[mic_ring_write_pt] = sample;
+ // atomic update of mic_ring_write_pt
+ mic_ring_write_pt = newpt;
+ }
+ }
+ break;
+ default:
+ break;
+ }
}
- }
- break;
- default:
- break;
- }
+ }
}
- }
+ g_mutex_unlock(&audio_mutex);
}
- g_mutex_unlock(&audio_mutex);
- }
- g_print("%s: exit\n",__FUNCTION__);
- return NULL;
+ g_print("%s: exit\n", __FUNCTION__);
+ return NULL;
}
int audio_open_input() {
- pa_sample_spec sample_spec;
- int result=0;
-
- if(transmitter->microphone_name==NULL) {
- return -1;
- }
-
- g_mutex_lock(&audio_mutex);
-
-
- pa_buffer_attr attr;
- attr.maxlength = (uint32_t) -1;
- attr.tlength = (uint32_t) -1;
- attr.prebuf = (uint32_t) -1;
- attr.minreq = (uint32_t) -1;
- attr.fragsize = 512;
-
-
- sample_spec.rate=48000;
- sample_spec.channels=1;
- sample_spec.format=PA_SAMPLE_FLOAT32NE;
-
- microphone_stream=pa_simple_new(NULL, // Use the default server.
- "piHPSDR", // Our application's name.
- PA_STREAM_RECORD,
- transmitter->microphone_name,
- "TX", // Description of our stream.
- &sample_spec, // Our sample format.
- NULL, // Use default channel map
- //NULL,
- &attr, // Use default buffering attributes.
- NULL // Ignore error code.
- );
-
- if(microphone_stream!=NULL) {
- local_microphone_buffer_offset=0;
- local_microphone_buffer=g_new0(float,local_microphone_buffer_size);
-
- g_print("%s: allocating ring buffer\n",__FUNCTION__);
- mic_ring_buffer=(float *) g_new(float,MICRINGLEN);
- mic_ring_read_pt = mic_ring_write_pt=0;
- if (mic_ring_buffer == NULL) {
- audio_close_input();
- return -1;
+ pa_sample_spec sample_spec;
+ int result = 0;
+
+ if (transmitter->microphone_name == NULL) {
+ return -1;
}
- running=TRUE;
- g_print("%s: PULSEAUDIO mic_read_thread\n",__FUNCTION__);
- mic_read_thread_id=g_thread_new("mic_thread",mic_read_thread,NULL);
- if(!mic_read_thread_id ) {
- g_print("%s: g_thread_new failed on mic_read_thread\n",__FUNCTION__);
- g_free(local_microphone_buffer);
- local_microphone_buffer=NULL;
- running=FALSE;
- result=-1;
+ g_mutex_lock(&audio_mutex);
+
+ pa_buffer_attr attr;
+ attr.maxlength = (uint32_t)-1;
+ attr.tlength = (uint32_t)-1;
+ attr.prebuf = (uint32_t)-1;
+ attr.minreq = (uint32_t)-1;
+ attr.fragsize = 512;
+
+ sample_spec.rate = 48000;
+ sample_spec.channels = 1;
+ sample_spec.format = PA_SAMPLE_FLOAT32NE;
+
+ microphone_stream =
+ pa_simple_new(NULL, // Use the default server.
+ "piHPSDR", // Our application's name.
+ PA_STREAM_RECORD, transmitter->microphone_name,
+ "TX", // Description of our stream.
+ &sample_spec, // Our sample format.
+ NULL, // Use default channel map
+ // NULL,
+ &attr, // Use default buffering attributes.
+ NULL // Ignore error code.
+ );
+
+ if (microphone_stream != NULL) {
+ local_microphone_buffer_offset = 0;
+ local_microphone_buffer = g_new0(float, local_microphone_buffer_size);
+
+ g_print("%s: allocating ring buffer\n", __FUNCTION__);
+ mic_ring_buffer = (float *)g_new(float, MICRINGLEN);
+ mic_ring_read_pt = mic_ring_write_pt = 0;
+ if (mic_ring_buffer == NULL) {
+ audio_close_input();
+ return -1;
+ }
+
+ running = TRUE;
+ g_print("%s: PULSEAUDIO mic_read_thread\n", __FUNCTION__);
+ mic_read_thread_id = g_thread_new("mic_thread", mic_read_thread, NULL);
+ if (!mic_read_thread_id) {
+ g_print("%s: g_thread_new failed on mic_read_thread\n",
+ __FUNCTION__);
+ g_free(local_microphone_buffer);
+ local_microphone_buffer = NULL;
+ running = FALSE;
+ result = -1;
+ }
+ } else {
+ result = -1;
}
- } else {
- result=-1;
- }
- g_mutex_unlock(&audio_mutex);
+ g_mutex_unlock(&audio_mutex);
- return result;
+ return result;
}
void audio_close_output(RECEIVER *rx) {
- g_mutex_lock(&rx->local_audio_mutex);
- if(rx->playstream!=NULL) {
- pa_simple_free(rx->playstream);
- rx->playstream=NULL;
- }
- if(rx->local_audio_buffer!=NULL) {
- g_free(rx->local_audio_buffer);
- rx->local_audio_buffer=NULL;
- }
- g_mutex_unlock(&rx->local_audio_mutex);
+ g_mutex_lock(&rx->local_audio_mutex);
+ if (rx->playstream != NULL) {
+ pa_simple_free(rx->playstream);
+ rx->playstream = NULL;
+ }
+ if (rx->local_audio_buffer != NULL) {
+ g_free(rx->local_audio_buffer);
+ rx->local_audio_buffer = NULL;
+ }
+ g_mutex_unlock(&rx->local_audio_mutex);
}
void audio_close_input() {
- g_mutex_lock(&audio_mutex);
- if(microphone_stream!=NULL) {
- pa_simple_free(microphone_stream);
- microphone_stream=NULL;
- g_free(local_microphone_buffer);
- local_microphone_buffer=NULL;
- }
- g_mutex_unlock(&audio_mutex);
+ g_mutex_lock(&audio_mutex);
+ if (microphone_stream != NULL) {
+ pa_simple_free(microphone_stream);
+ microphone_stream = NULL;
+ g_free(local_microphone_buffer);
+ local_microphone_buffer = NULL;
+ }
+ g_mutex_unlock(&audio_mutex);
}
//
// from ring buffer
//
float audio_get_next_mic_sample() {
- int newpt;
- float sample;
-
- if ((mic_ring_buffer == NULL) || (mic_ring_read_pt == mic_ring_write_pt)) {
- // no buffer, or nothing in buffer: insert silence
- //g_print("%s: no samples\n",__FUNCTION__);
- sample=0.0;
- } else {
- // the "existence" of the ring buffer is now guaranteed for 1 msec,
- // see audio_close_input(),
- newpt = mic_ring_read_pt+1;
- if (newpt == MICRINGLEN) newpt=0;
- sample=mic_ring_buffer[mic_ring_read_pt];
- // atomic update of read pointer
- mic_ring_read_pt=newpt;
- }
- return sample;
+ int newpt;
+ float sample;
+
+ if ((mic_ring_buffer == NULL) || (mic_ring_read_pt == mic_ring_write_pt)) {
+ // no buffer, or nothing in buffer: insert silence
+ // g_print("%s: no samples\n",__FUNCTION__);
+ sample = 0.0;
+ } else {
+ // the "existence" of the ring buffer is now guaranteed for 1 msec,
+ // see audio_close_input(),
+ newpt = mic_ring_read_pt + 1;
+ if (newpt == MICRINGLEN)
+ newpt = 0;
+ sample = mic_ring_buffer[mic_ring_read_pt];
+ // atomic update of read pointer
+ mic_ring_read_pt = newpt;
+ }
+ return sample;
}
-int cw_audio_write(RECEIVER *rx,float sample) {
- int result=0;
- int rc;
- int err;
-
- g_mutex_lock(&rx->local_audio_mutex);
- if(rx->local_audio_buffer==NULL) {
- rx->local_audio_buffer_offset=0;
- rx->local_audio_buffer=g_new0(float,2*rx->local_audio_buffer_size);
- }
-
- rx->local_audio_buffer[rx->local_audio_buffer_offset*2]=sample;
- rx->local_audio_buffer[(rx->local_audio_buffer_offset*2)+1]=sample;
- rx->local_audio_buffer_offset++;
- if(rx->local_audio_buffer_offset>=rx->local_audio_buffer_size) {
- rc=pa_simple_write(rx->playstream,
- rx->local_audio_buffer,
- rx->local_audio_buffer_size*sizeof(float)*2,
- &err);
- if(rc!=0) {
- fprintf(stderr,"audio_write failed err=%d\n",err);
+int cw_audio_write(RECEIVER *rx, float sample) {
+ int result = 0;
+ int rc;
+ int err;
+
+ g_mutex_lock(&rx->local_audio_mutex);
+ if (rx->local_audio_buffer == NULL) {
+ rx->local_audio_buffer_offset = 0;
+ rx->local_audio_buffer = g_new0(float, 2 * rx->local_audio_buffer_size);
+ }
+
+ rx->local_audio_buffer[rx->local_audio_buffer_offset * 2] = sample;
+ rx->local_audio_buffer[(rx->local_audio_buffer_offset * 2) + 1] = sample;
+ rx->local_audio_buffer_offset++;
+ if (rx->local_audio_buffer_offset >= rx->local_audio_buffer_size) {
+ rc = pa_simple_write(rx->playstream, rx->local_audio_buffer,
+ rx->local_audio_buffer_size * sizeof(float) * 2,
+ &err);
+ if (rc != 0) {
+ fprintf(stderr, "audio_write failed err=%d\n", err);
+ }
+ rx->local_audio_buffer_offset = 0;
}
- rx->local_audio_buffer_offset=0;
- }
- g_mutex_unlock(&rx->local_audio_mutex);
+ g_mutex_unlock(&rx->local_audio_mutex);
- return result;
+ return result;
}
-int audio_write(RECEIVER *rx,float left_sample,float right_sample) {
- int result=0;
- int rc;
- int err;
-
- g_mutex_lock(&rx->local_audio_mutex);
- if(rx->local_audio_buffer==NULL) {
- rx->local_audio_buffer_offset=0;
- rx->local_audio_buffer=g_new0(float,2*rx->local_audio_buffer_size);
- }
-
- rx->local_audio_buffer[rx->local_audio_buffer_offset*2]=left_sample;
- rx->local_audio_buffer[(rx->local_audio_buffer_offset*2)+1]=right_sample;
- rx->local_audio_buffer_offset++;
- if(rx->local_audio_buffer_offset>=rx->local_audio_buffer_size) {
- rc=pa_simple_write(rx->playstream,
- rx->local_audio_buffer,
- rx->local_audio_buffer_size*sizeof(float)*2,
- &err);
- if(rc!=0) {
- fprintf(stderr,"audio_write failed err=%d\n",err);
+int audio_write(RECEIVER *rx, float left_sample, float right_sample) {
+ int result = 0;
+ int rc;
+ int err;
+
+ g_mutex_lock(&rx->local_audio_mutex);
+ if (rx->local_audio_buffer == NULL) {
+ rx->local_audio_buffer_offset = 0;
+ rx->local_audio_buffer = g_new0(float, 2 * rx->local_audio_buffer_size);
}
- rx->local_audio_buffer_offset=0;
- }
- g_mutex_unlock(&rx->local_audio_mutex);
- return result;
-}
+ rx->local_audio_buffer[rx->local_audio_buffer_offset * 2] = left_sample;
+ rx->local_audio_buffer[(rx->local_audio_buffer_offset * 2) + 1] =
+ right_sample;
+ rx->local_audio_buffer_offset++;
+ if (rx->local_audio_buffer_offset >= rx->local_audio_buffer_size) {
+ rc = pa_simple_write(rx->playstream, rx->local_audio_buffer,
+ rx->local_audio_buffer_size * sizeof(float) * 2,
+ &err);
+ if (rc != 0) {
+ fprintf(stderr, "audio_write failed err=%d\n", err);
+ }
+ rx->local_audio_buffer_offset = 0;
+ }
+ g_mutex_unlock(&rx->local_audio_mutex);
+ return result;
+}