]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
Makefile
authorJohn Melton - G0ORX/N6LYT <john.d.melton@googlemail.com>
Fri, 9 Sep 2016 16:11:38 +0000 (16:11 +0000)
committerJohn Melton - G0ORX/N6LYT <john.d.melton@googlemail.com>
Fri, 9 Sep 2016 16:11:38 +0000 (16:11 +0000)
16 files changed:
audio.c
audio.h
lime_protocol.c
main.c
menu.c
new_protocol.c
new_protocol.h
old_protocol.c
pihpsdr
radio.c
radio.h
release/documentation/pihpsdr-install.odt
release/documentation/pihpsdr-install.pdf
release/pihpsdr.tar
release/pihpsdr/install.sh
release/pihpsdr/pihpsdr

diff --git a/audio.c b/audio.c
index fef9049fb7a8adadcb759ca64b548ab51086d119..d45f5e170045ac6aa46df7495922e2de05b3cf99 100644 (file)
--- a/audio.c
+++ b/audio.c
@@ -18,6 +18,8 @@
 */
 
 
+#include <gtk/gtk.h>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sched.h>
 #include <semaphore.h>
 
-#include <pulse/simple.h>
-#include <pulse/error.h>
+#include <alsa/asoundlib.h>
 
 #include "audio.h"
+#include "new_protocol.h"
 #include "radio.h"
 
 int audio = 0;
-//int audio_buffer_size = 2016; // samples (both left and right)
 int audio_buffer_size = 256; // samples (both left and right)
+int mic_buffer_size = 720; // samples (both left and right)
 
-static pa_simple *stream;
+static snd_pcm_t *playback_handle=NULL;
+static snd_pcm_t *record_handle=NULL;
 
 // each buffer contains 63 samples of left and right audio at 16 bits
 #define AUDIO_SAMPLES 63
@@ -47,53 +50,340 @@ static pa_simple *stream;
 #define AUDIO_BUFFERS 10
 #define AUDIO_BUFFER_SIZE (AUDIO_SAMPLE_SIZE*AUDIO_CHANNELS*audio_buffer_size)
 
-static unsigned char *audio_buffer;
+#define MIC_BUFFER_SIZE (AUDIO_SAMPLE_SIZE*AUDIO_CHANNELS*mic_buffer_size)
+
+static unsigned char *audio_buffer=NULL;
 static int audio_offset=0;
 
-int audio_init() {
+static unsigned char *mic_buffer=NULL;
 
-    static const pa_sample_spec spec= {
-        .format = PA_SAMPLE_S16RE,
-        .rate =  48000,
-        .channels = 2
-    };
+static pthread_t mic_read_thread_id;
 
-    int error;
+static int running=FALSE;
 
-fprintf(stderr,"audio_init audio_buffer_size=%d\n",audio_buffer_size);
+static void *mic_read_thread(void *arg);
 
-    audio_buffer=(unsigned char *)malloc(AUDIO_BUFFER_SIZE);
+char *input_devices[16];
+int n_input_devices=0;
+int n_selected_input_device=-1;
 
-    if (!(stream = pa_simple_new(NULL, "pihpsdr", PA_STREAM_PLAYBACK, NULL, "playback", &spec, NULL, NULL, &error))) {
-        fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
-        return -1;
-    }
+char *output_devices[16];
+int n_output_devices=0;
+int n_selected_output_device=-1;
+
+int audio_open_output() {
+  int err;
+  snd_pcm_hw_params_t *hw_params;
+  int rate=48000;
+  int dir=0;
+
+
+  if(n_selected_output_device<0 || n_selected_output_device>=n_output_devices) {
+    n_selected_output_device=-1;
+    return -1;
+  }
+
+  int i;
+  char hw[16];
+  char *selected=output_devices[n_selected_output_device];
+fprintf(stderr,"audio_open_output: selected=%d:%s\n",n_selected_output_device,selected);
+
+  i=0;
+  while(selected[i]!=' ') {
+    hw[i]=selected[i];
+    i++;
+  }
+  hw[i]='\0';
+  
+  if ((err = snd_pcm_open (&playback_handle, hw, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
+    fprintf (stderr, "audio_open_output: cannot open audio device %s (%s)\n", 
+            hw,
+            snd_strerror (err));
+    return -1;
+  }
 
-    return 0;
+
+  if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
+    fprintf (stderr, "audio_open_output: cannot allocate hardware parameter structure (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+
+  if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0) {
+    fprintf (stderr, "audio_open_output: cannot initialize hardware parameter structure (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+
+  if ((err = snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+    fprintf (stderr, "audio_open_output: cannot set access type (%s)\n",
+            snd_strerror (err));
+    return -1;
 }
+       
+  if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
+    fprintf (stderr, "audio_open_output: cannot set sample format (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+       
+
+  if ((err = snd_pcm_hw_params_set_rate_near (playback_handle, hw_params, &rate, &dir)) < 0) {
+    fprintf (stderr, "audio_open_output: cannot set sample rate (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+       
+  if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, 2)) < 0) {
+    fprintf (stderr, "audio_open_output: cannot set channel count (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+       
+  if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) {
+    fprintf (stderr, "audio_open_output: cannot set parameters (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+       
+  snd_pcm_hw_params_free (hw_params);
 
-void audio_close() {
-  pa_simple_free(stream);
+  audio_offset=0;
+  audio_buffer=(unsigned char *)malloc(AUDIO_BUFFER_SIZE);
+
+  return 0;
+}
+       
+int audio_open_input() {
+  int err;
+  snd_pcm_hw_params_t *hw_params;
+  int rate=48000;
+  int dir=0;
+
+  if(n_selected_output_device<0 || n_selected_output_device>=n_output_devices) {
+    n_selected_output_device=-1;
+    return -1;
+  }
+
+  int i;
+  char hw[16];
+  char *selected=input_devices[n_selected_input_device];
+  fprintf(stderr,"audio_open_input: selected=%d:%s\n",n_selected_input_device,selected);
+  
+  i=0;
+  while(selected[i]!=' ') {
+    hw[i]=selected[i];
+    i++;
+  }
+  hw[i]='\0';
+
+
+  if ((err = snd_pcm_open (&record_handle, hw, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
+    fprintf (stderr, "audio_open_input: cannot open audio device %s (%s)\n",
+            hw,
+            snd_strerror (err));
+    return -1;
+  }
+
+  if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
+    fprintf (stderr, "audio_open_input: cannot allocate hardware parameter structure (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+
+  if ((err = snd_pcm_hw_params_any (record_handle, hw_params)) < 0) {
+    fprintf (stderr, "audio_open_input: cannot initialize hardware parameter structure (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+
+  if ((err = snd_pcm_hw_params_set_access (record_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+    fprintf (stderr, "audio_open_input: cannot set access type (%s)\n",
+            snd_strerror (err));
+    return -1;
 }
 
-void audio_write(short left_sample,short right_sample) {
-  int result;
+  if ((err = snd_pcm_hw_params_set_format (record_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
+    fprintf (stderr, "audio_open_input: cannot set sample format (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+
+  if ((err = snd_pcm_hw_params_set_rate_near (record_handle, hw_params, &rate, &dir)) < 0) {
+    fprintf (stderr, "audio_open_input: cannot set sample rate (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+
+  if ((err = snd_pcm_hw_params_set_channels (record_handle, hw_params, 1)) < 0) {
+    fprintf (stderr, "audio_open_input: cannot set channel count (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+
+  if ((err = snd_pcm_hw_params (record_handle, hw_params)) < 0) {
+    fprintf (stderr, "audio_open_input: cannot set parameters (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+
+  snd_pcm_hw_params_free (hw_params);
+
+  mic_buffer=(unsigned char *)malloc(MIC_BUFFER_SIZE);
+
+  running=TRUE;
+  err=pthread_create(&mic_read_thread_id,NULL,mic_read_thread,NULL);
+  if(err != 0) {
+    fprintf(stderr,"pthread_create failed on mic_read_thread: rc=%d\n", err);
+    return -1;
+  }
+
+  return 0;
+}
+
+void audio_close_output() {
+  if(playback_handle!=NULL) {
+    snd_pcm_close (playback_handle);
+    playback_handle=NULL;
+  }
+  if(audio_buffer!=NULL) {
+    free(audio_buffer);
+    audio_buffer=NULL;
+  }
+}
+
+void audio_close_input() {
+  running=FALSE;
+  if(record_handle!=NULL) {
+    snd_pcm_close (record_handle);
+    record_handle=NULL;
+  }
+  if(mic_buffer!=NULL) {
+    free(mic_buffer);
+    mic_buffer=NULL;
+  }
+}
+
+int audio_write(short left_sample,short right_sample) {
   int error;
 
-  audio_buffer[audio_offset++]=left_sample>>8;
-  audio_buffer[audio_offset++]=left_sample;
-  audio_buffer[audio_offset++]=right_sample>>8;
-  audio_buffer[audio_offset++]=right_sample;
-
-  if(audio_offset==AUDIO_BUFFER_SIZE) {
-//fprintf(stderr,"pa_simple_write...");
-    result=pa_simple_write(stream, audio_buffer, (size_t)AUDIO_BUFFER_SIZE, &error);
-//fprintf(stderr,"%d\n",result);
-    if(result< 0) {
-      fprintf(stderr, __FILE__": pa_simple_write() failed: %s\n", pa_strerror(error));
-      //_exit(1);
+  if(playback_handle!=NULL && audio_buffer!=NULL) {
+    audio_buffer[audio_offset++]=left_sample;
+    audio_buffer[audio_offset++]=left_sample>>8;
+    audio_buffer[audio_offset++]=right_sample;
+    audio_buffer[audio_offset++]=right_sample>>8;
+
+    if(audio_offset==AUDIO_BUFFER_SIZE) {
+
+      if ((error = snd_pcm_writei (playback_handle, audio_buffer, audio_buffer_size)) != audio_buffer_size) {
+        if(error==-EPIPE) {
+          if ((error = snd_pcm_prepare (playback_handle)) < 0) {
+            fprintf (stderr, "audio_write: cannot prepare audio interface for use (%s)\n",
+                    snd_strerror (error));
+            return -1;
+          }
+          if ((error = snd_pcm_writei (playback_handle, audio_buffer, audio_buffer_size)) != audio_buffer_size) {
+            fprintf (stderr, "audio_write: write to audio interface failed (%s)\n",
+                    snd_strerror (error));
+            return -1;
+          }
+        }
+      }
+      audio_offset=0;
+    }
+  }
+  return 0;
+}
+
+static void *mic_read_thread(void *arg) {
+  int error;
+  if ((error = snd_pcm_prepare (record_handle)) < 0) {
+    fprintf (stderr, "mic_read_thread: cannot prepare audio interface for use (%s)\n",
+            snd_strerror (error));
+    return;
+  }
+  while(running) {
+    if ((error = snd_pcm_readi (record_handle, mic_buffer, mic_buffer_size)) != mic_buffer_size) {
+      if(running) {
+        fprintf (stderr, "mic_read_thread: read from audio interface failed (%s)\n",
+                snd_strerror (error));
+        running=FALSE;
+      }
+      break;
+    } else {
+      // process the mic input
+      switch(protocol) {
+        case ORIGINAL_PROTOCOL:
+          break;
+        case NEW_PROTOCOL:
+          new_protocol_process_local_mic(mic_buffer,1);
+          break;
+        default:
+          break;
+      }
     }
-    audio_offset=0;
   }
+
 }
 
+void audio_get_cards(int input) {
+  snd_ctl_card_info_t *info;
+  snd_pcm_info_t *pcminfo;
+  snd_ctl_card_info_alloca(&info);
+  snd_pcm_info_alloca(&pcminfo);
+  int i;
+
+  if(input) {
+    for(i=0;i<n_input_devices;i++) {
+      free(input_devices[i]);
+    }
+    n_input_devices=0;
+  } else {
+    for(i=0;i<n_output_devices;i++) {
+      free(output_devices[i]);
+    }
+    n_output_devices=0;
+  }
+  int card = -1;
+  while (snd_card_next(&card) >= 0 && card >= 0) {
+    int err = 0;
+    snd_ctl_t *handle;
+    char name[20];
+    snprintf(name, sizeof(name), "hw:%d", card);
+    if ((err = snd_ctl_open(&handle, name, 0)) < 0) {
+      continue;
+    }
+
+    if ((err = snd_ctl_card_info(handle, info)) < 0) {
+      snd_ctl_close(handle);
+      continue;
+    }
+
+    int dev = -1;
+    while (snd_ctl_pcm_next_device(handle, &dev) >= 0 && dev >= 0) {
+      snd_pcm_info_set_device(pcminfo, dev);
+      snd_pcm_info_set_subdevice(pcminfo, 0);
+      snd_pcm_info_set_stream(pcminfo, input ? SND_PCM_STREAM_CAPTURE
+          : SND_PCM_STREAM_PLAYBACK);
+      if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
+        continue;
+      }
+
+      char *device_id=malloc(64);
+      
+      snprintf(device_id, 64, "plughw:%d,%d %s", card, dev, snd_ctl_card_info_get_name(info));
+      if(input) {
+fprintf(stderr,"input_device: %s\n",device_id);
+        input_devices[n_input_devices++]=device_id;
+      } else {
+        output_devices[n_output_devices++]=device_id;
+fprintf(stderr,"output_device: %s\n",device_id);
+      }
+
+    }
+
+    snd_ctl_close(handle);
+
+  }
+}
diff --git a/audio.h b/audio.h
index 89e90d89f84b52665361a4a31b553fe1e7c74479..ceec2a0d763bff663c4e1733d9396d6f9372bde6 100644 (file)
--- a/audio.h
+++ b/audio.h
 #ifndef _AUDIO_H
 #define _AUDIO_H
 
-extern int audio;
-extern int audio_buffer_size;
+extern char *input_devices[];
+extern int n_input_devices;
+extern int n_selected_input_device;
 
-int audio_init();
-void audio_close();
-void audio_write(short left_sample,short right_sample);
-/*
-void audio_write(double *buffer,int samples);
-*/
+extern char *output_devices[];
+extern int n_output_devices;
+extern int n_selected_output_device;
+
+extern int audio_open_output();
+extern int audio_open_input();
+extern void audio_close_output();
+extern void audio_close_input();
+extern int audio_write(short left_sample,short right_sample);
+extern void audio_get_cards();
 
 #endif
index 56e2cf4eebbf5928eaf2823d1487ed24b945dde9..c0c34e1532974cbdcd5fff1bbe8a8c439faa1502 100644 (file)
@@ -187,10 +187,10 @@ fprintf(stderr,"lime_protocol: setting save_frequency: %lld\n",saved_frequency);
       lime_protocol_set_frequency(saved_frequency);
   }
 
-fprintf(stderr,"lime_protocol_init: audio_init\n");
-  if(audio_init()!=0) {
+fprintf(stderr,"lime_protocol_init: audio_open_output\n");
+  if(audio_open_output()!=0) {
     local_audio=false;
-    fprintf(stderr,"audio_init failed\n");
+    fprintf(stderr,"audio_open_output failed\n");
   }
 
 fprintf(stderr,"lime_protocol_init: create receive_thread\n");
diff --git a/main.c b/main.c
index 30b0a9343075fb5152830fd37c0177ca697aea21..78b366aa7c38fabc8beba4bf05c4c8aade527d6a 100644 (file)
--- a/main.c
+++ b/main.c
@@ -27,6 +27,8 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+
+#include "audio.h"
 #include "main.h"
 #include "channel.h"
 #include "discovered.h"
@@ -332,6 +334,9 @@ gint init(void* arg) {
 
   fprintf(stderr,"init\n");
 
+  audio_get_cards(0);
+  audio_get_cards(1);
+
   cursor_arrow=gdk_cursor_new(GDK_ARROW);
   cursor_watch=gdk_cursor_new(GDK_WATCH);
 
diff --git a/menu.c b/menu.c
index 46dd57fcde1f8812414ec40ebdf43f71c5bd1db5..a8d2197facc90b5841697c0f39f6ed5b13829082 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -187,14 +187,48 @@ static void micboost_cb(GtkWidget *widget, gpointer data) {
 static void local_audio_cb(GtkWidget *widget, gpointer data) {
   if(local_audio) {
     local_audio=0;
-    audio_close();
+    audio_close_output();
   } else {
-    if(audio_init()==0) {
+    if(audio_open_output()==0) {
       local_audio=1;
     }
   }
 }
 
+static void local_output_changed_cb(GtkWidget *widget, gpointer data) {
+  n_selected_output_device=(int)(long)data;
+fprintf(stderr,"local_output_changed: %d\n",n_selected_output_device);
+
+  if(local_audio) {
+    audio_close_output();
+    if(audio_open_output()==0) {
+      local_audio=1;
+    }
+  }
+}
+
+static void local_microphone_cb(GtkWidget *widget, gpointer data) {
+  if(local_microphone) {
+    local_microphone=0;
+    audio_close_input();
+  } else {
+    if(audio_open_input()==0) {
+      local_microphone=1;
+    }
+  }
+}
+
+static void local_input_changed_cb(GtkWidget *widget, gpointer data) {
+  n_selected_input_device=(int)(long)data;
+fprintf(stderr,"local_input_changed: %d\n",n_selected_input_device);
+  if(local_microphone) {
+    audio_close_input();
+    if(audio_open_input()==0) {
+      local_microphone=1;
+    }
+  }
+}
+
 static void toolbar_dialog_buttons_cb(GtkWidget *widget, gpointer data) {
   toolbar_dialog_buttons=toolbar_dialog_buttons==1?0:1;
   update_toolbar_labels();
@@ -535,8 +569,9 @@ static gboolean menu_pressed_event_cb (GtkWidget *widget,
 
   GtkWidget *general_label=gtk_label_new("General");
   GtkWidget *general_grid=gtk_grid_new();
+  gtk_grid_set_column_spacing (GTK_GRID(general_grid),10);
   //gtk_grid_set_row_homogeneous(GTK_GRID(general_grid),TRUE);
-  gtk_grid_set_column_homogeneous(GTK_GRID(general_grid),TRUE);
+  //gtk_grid_set_column_homogeneous(GTK_GRID(general_grid),TRUE);
 
 
   GtkWidget *vfo_divisor_label=gtk_label_new("VFO Encoder Divisor: ");
@@ -586,34 +621,6 @@ static gboolean menu_pressed_event_cb (GtkWidget *widget,
     g_signal_connect(rx_preamp_b,"toggled",G_CALLBACK(rx_preamp_cb),NULL);
 */
 
-    GtkWidget *linein_b=gtk_check_button_new_with_label("Mic Line In");
-    //gtk_widget_override_font(linein_b, pango_font_description_from_string("Arial 18"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (linein_b), mic_linein);
-    gtk_widget_show(linein_b);
-    gtk_grid_attach(GTK_GRID(general_grid),linein_b,1,2,1,1);
-    g_signal_connect(linein_b,"toggled",G_CALLBACK(linein_cb),NULL);
-
-    GtkWidget *micboost_b=gtk_check_button_new_with_label("Mic Boost");
-    //gtk_widget_override_font(micboost_b, pango_font_description_from_string("Arial 18"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (micboost_b), mic_boost);
-    gtk_widget_show(micboost_b);
-    gtk_grid_attach(GTK_GRID(general_grid),micboost_b,1,3,1,1);
-    g_signal_connect(micboost_b,"toggled",G_CALLBACK(micboost_cb),NULL);
-
-    GtkWidget *local_audio_b=gtk_check_button_new_with_label("Local Audio");
-    //gtk_widget_override_font(local_audio_b, pango_font_description_from_string("Arial 18"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (local_audio_b), local_audio);
-    gtk_widget_show(local_audio_b);
-    gtk_grid_attach(GTK_GRID(general_grid),local_audio_b,1,4,1,1);
-    g_signal_connect(local_audio_b,"toggled",G_CALLBACK(local_audio_cb),NULL);
-
-    GtkWidget *b_toolbar_dialog_buttons=gtk_check_button_new_with_label("Buttons Display Dialog");
-    //gtk_widget_override_font(b_toolbar_dialog_buttons, pango_font_description_from_string("Arial 18"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_toolbar_dialog_buttons), toolbar_dialog_buttons);
-    gtk_widget_show(b_toolbar_dialog_buttons);
-    gtk_grid_attach(GTK_GRID(general_grid),b_toolbar_dialog_buttons,1,5,1,1);
-    g_signal_connect(b_toolbar_dialog_buttons,"toggled",G_CALLBACK(toolbar_dialog_buttons_cb),(gpointer *)NULL);
-
     if((protocol==NEW_PROTOCOL && device==NEW_DEVICE_ORION) ||
        (protocol==NEW_PROTOCOL && device==NEW_DEVICE_ORION2) ||
        (protocol==ORIGINAL_PROTOCOL && device==DEVICE_ORION)) {
@@ -622,28 +629,28 @@ static gboolean menu_pressed_event_cb (GtkWidget *widget,
       //gtk_widget_override_font(ptt_ring_b, pango_font_description_from_string("Arial 18"));
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_ring_b), mic_ptt_tip_bias_ring==0);
       gtk_widget_show(ptt_ring_b);
-      gtk_grid_attach(GTK_GRID(general_grid),ptt_ring_b,1,6,1,1);
+      gtk_grid_attach(GTK_GRID(general_grid),ptt_ring_b,1,5,1,1);
       g_signal_connect(ptt_ring_b,"pressed",G_CALLBACK(ptt_ring_cb),NULL);
 
       GtkWidget *ptt_tip_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ptt_ring_b),"PTT On Tip, Mic and Bias on Ring");
       //gtk_widget_override_font(ptt_tip_b, pango_font_description_from_string("Arial 18"));
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_tip_b), mic_ptt_tip_bias_ring==1);
       gtk_widget_show(ptt_tip_b);
-      gtk_grid_attach(GTK_GRID(general_grid),ptt_tip_b,1,7,1,1);
+      gtk_grid_attach(GTK_GRID(general_grid),ptt_tip_b,1,6,1,1);
       g_signal_connect(ptt_tip_b,"pressed",G_CALLBACK(ptt_tip_cb),NULL);
 
       GtkWidget *ptt_b=gtk_check_button_new_with_label("PTT Enabled");
       //gtk_widget_override_font(ptt_b, pango_font_description_from_string("Arial 18"));
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_b), mic_ptt_enabled);
       gtk_widget_show(ptt_b);
-      gtk_grid_attach(GTK_GRID(general_grid),ptt_b,1,8,1,1);
+      gtk_grid_attach(GTK_GRID(general_grid),ptt_b,1,7,1,1);
       g_signal_connect(ptt_b,"toggled",G_CALLBACK(ptt_cb),NULL);
 
       GtkWidget *bias_b=gtk_check_button_new_with_label("BIAS Enabled");
       //gtk_widget_override_font(bias_b, pango_font_description_from_string("Arial 18"));
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bias_b), mic_bias_enabled);
       gtk_widget_show(bias_b);
-      gtk_grid_attach(GTK_GRID(general_grid),bias_b,1,9,1,1);
+      gtk_grid_attach(GTK_GRID(general_grid),bias_b,1,8,1,1);
       g_signal_connect(bias_b,"toggled",G_CALLBACK(bias_cb),NULL);
     }
 
@@ -652,13 +659,13 @@ static gboolean menu_pressed_event_cb (GtkWidget *widget,
     //gtk_widget_override_font(alex_b, pango_font_description_from_string("Arial 18"));
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (alex_b), filter_board==ALEX);
     gtk_widget_show(alex_b);
-    gtk_grid_attach(GTK_GRID(general_grid),alex_b,2,2,1,1);
+    gtk_grid_attach(GTK_GRID(general_grid),alex_b,1,2,1,1);
 
     GtkWidget *apollo_b=gtk_check_button_new_with_label("APOLLO");
     //gtk_widget_override_font(apollo_b, pango_font_description_from_string("Arial 18"));
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (apollo_b), filter_board==APOLLO);
     gtk_widget_show(apollo_b);
-    gtk_grid_attach(GTK_GRID(general_grid),apollo_b,2,3,1,1);
+    gtk_grid_attach(GTK_GRID(general_grid),apollo_b,1,3,1,1);
   
     g_signal_connect(alex_b,"toggled",G_CALLBACK(alex_cb),apollo_b);
     g_signal_connect(apollo_b,"toggled",G_CALLBACK(apollo_cb),alex_b);
@@ -758,6 +765,77 @@ static gboolean menu_pressed_event_cb (GtkWidget *widget,
 
   id=gtk_notebook_append_page(GTK_NOTEBOOK(notebook),general_grid,general_label);
 
+
+
+  GtkWidget *audio_label=gtk_label_new("Audio");
+  GtkWidget *audio_grid=gtk_grid_new();
+  //gtk_grid_set_row_homogeneous(GTK_GRID(audio_grid),TRUE);
+  gtk_grid_set_column_spacing (GTK_GRID(audio_grid),10);
+
+  if(protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL) {
+    GtkWidget *linein_b=gtk_check_button_new_with_label("Mic Line In");
+    //gtk_widget_override_font(linein_b, pango_font_description_from_string("Arial 18"));
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (linein_b), mic_linein);
+    gtk_widget_show(linein_b);
+    gtk_grid_attach(GTK_GRID(audio_grid),linein_b,0,0,1,1);
+    g_signal_connect(linein_b,"toggled",G_CALLBACK(linein_cb),NULL);
+
+    GtkWidget *micboost_b=gtk_check_button_new_with_label("Mic Boost");
+    //gtk_widget_override_font(micboost_b, pango_font_description_from_string("Arial 18"));
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (micboost_b), mic_boost);
+    gtk_widget_show(micboost_b);
+    gtk_grid_attach(GTK_GRID(audio_grid),micboost_b,0,1,1,1);
+    g_signal_connect(micboost_b,"toggled",G_CALLBACK(micboost_cb),NULL);
+  }
+
+
+  if(n_output_devices>0) {
+    GtkWidget *local_audio_b=gtk_check_button_new_with_label("Local Audio");
+    //gtk_widget_override_font(local_audio_b, pango_font_description_from_string("Arial 18"));
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (local_audio_b), local_audio);
+    gtk_widget_show(local_audio_b);
+    gtk_grid_attach(GTK_GRID(audio_grid),local_audio_b,1,0,1,1);
+    g_signal_connect(local_audio_b,"toggled",G_CALLBACK(local_audio_cb),NULL);
+    for(i=0;i<n_output_devices;i++) {
+      GtkWidget *output;
+      if(i==0) {
+        output=gtk_radio_button_new_with_label(NULL,output_devices[i]);
+      } else {
+        output=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(output),output_devices[i]);
+      }
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (output), n_selected_output_device==i);
+      gtk_widget_show(output);
+      gtk_grid_attach(GTK_GRID(audio_grid),output,1,i+1,1,1);
+      g_signal_connect(output,"pressed",G_CALLBACK(local_output_changed_cb),(gpointer *)i);
+    }
+  }
+
+  if(n_input_devices>0) {
+    GtkWidget *local_audio_b=gtk_check_button_new_with_label("Microphone Audio");
+    //gtk_widget_override_font(local_audio_b, pango_font_description_from_string("Arial 18"));
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (local_audio_b), local_audio);
+    gtk_widget_show(local_audio_b);
+    gtk_grid_attach(GTK_GRID(audio_grid),local_audio_b,2,0,1,1);
+    g_signal_connect(local_audio_b,"toggled",G_CALLBACK(local_input_changed_cb),NULL);
+    for(i=0;i<n_input_devices;i++) {
+      GtkWidget *input;
+      if(i==0) {
+        input=gtk_radio_button_new_with_label(NULL,input_devices[i]);
+      } else {
+        input=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(input),input_devices[i]);
+      }
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (input), n_selected_input_device==i);
+      gtk_widget_show(input);
+      gtk_grid_attach(GTK_GRID(audio_grid),input,2,i+1,1,1);
+      g_signal_connect(input,"pressed",G_CALLBACK(local_microphone_cb),(gpointer *)i);
+    }
+  }
+
+  id=gtk_notebook_append_page(GTK_NOTEBOOK(notebook),audio_grid,audio_label);
+
+
   GtkWidget *ant_label=gtk_label_new("Ant");
   ant_grid=gtk_grid_new();
   gtk_grid_set_row_homogeneous(GTK_GRID(ant_grid),TRUE);
@@ -1109,6 +1187,12 @@ static gboolean menu_pressed_event_cb (GtkWidget *widget,
   gtk_grid_attach(GTK_GRID(display_grid),b_display_toolbar,3,7,1,1);
   g_signal_connect(b_display_toolbar,"toggled",G_CALLBACK(display_toolbar_cb),(gpointer *)NULL);
 
+  GtkWidget *b_toolbar_dialog_buttons=gtk_check_button_new_with_label("Buttons Display Dialog");
+  //gtk_widget_override_font(b_toolbar_dialog_buttons, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_toolbar_dialog_buttons), toolbar_dialog_buttons);
+  gtk_widget_show(b_toolbar_dialog_buttons);
+  gtk_grid_attach(GTK_GRID(display_grid),b_toolbar_dialog_buttons,0,8,1,1);
+  g_signal_connect(b_toolbar_dialog_buttons,"toggled",G_CALLBACK(toolbar_dialog_buttons_cb),(gpointer *)NULL);
 
   id=gtk_notebook_append_page(GTK_NOTEBOOK(notebook),display_grid,display_label);
 
@@ -1552,6 +1636,9 @@ GtkWidget* menu_init(int width,int height,GtkWidget *parent) {
 
   fprintf(stderr,"menu_init: width=%d height=%d\n",width,height);
 
+  audio_get_cards(1); // input
+  audio_get_cards(0); // output
+
   parent_window=parent;
 
   box=gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
index 0f61f51cf2aac57daa5851905943fa68d3683e86..7fe67e1684c5ead376a7d137b65cd1e2125392d7 100644 (file)
@@ -221,12 +221,19 @@ void new_protocol_init(int rx,int pixels) {
     fprintf(stderr,"new_protocol_init: %d\n",rx);
 
     if(local_audio) {
-      if(audio_init()!=0) {
-        fprintf(stderr,"audio_init failed\n");
+      if(audio_open_output()!=0) {
+        fprintf(stderr,"audio_open_output failed\n");
         local_audio=0;
       }
     }
 
+    if(local_microphone) {
+      if(audio_open_input()!=0) {
+        fprintf(stderr,"audio_open_input failed\n");
+        local_microphone=0;
+      }
+    }
+
     new_protocol_calc_buffers();
 
     rc=sem_init(&response_sem, 0, 0);
@@ -329,12 +336,16 @@ fprintf(stderr,"new_protocol_high_priority: run=%d\n", run);
     buffer[331]=phase>>8;
     buffer[332]=phase;
 
-    double d=drive;
-    if(tune) {
-      d=tune_drive;
+    int power=0;
+    if(isTransmitting()) {
+      double d=drive;
+      if(tune) {
+        d=tune_drive;
+      }
+      d=d*((double)band->pa_calibration/100.0);
+      power=(int)(d*255.0);
     }
-    d=d*((double)band->pa_calibration/100.0);
-    int power=(int)(d*255.0);
+    
     buffer[345]=power&0xFF;
 
 fprintf(stderr,"power=%d\n",power);
@@ -733,7 +744,9 @@ fprintf(stderr,"outputsamples=%d\n", outputsamples);
               process_high_priority(buffer);
               break;
             case MIC_LINE_TO_HOST_PORT:
-              process_mic_data(buffer);
+              if(!local_microphone) {
+                process_mic_data(buffer);
+              }
               break;
             default:
               break;
@@ -859,14 +872,14 @@ static void process_mic_data(unsigned char *buffer) {
     double micsampledouble;
 
     sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF);
-    if(isTransmitting()) {
+//    if(isTransmitting()) {
         b=4;
         int i,j,s;
         for(i=0;i<720;i++) {
             micsample  = (int)((signed char) buffer[b++]) << 8;
             micsample  |= (int)((unsigned char)buffer[b++] & 0xFF);
 #ifdef FREEDV
-            if(mode==modeFREEDV) {
+            if(mode==modeFREEDV && isTransmitting()) {
                 if(freedv_samples==0) { // 48K to 8K
                     int modem_samples=mod_sample_freedv(micsample);
                     if(modem_samples!=0) {
@@ -892,7 +905,7 @@ static void process_mic_data(unsigned char *buffer) {
             } else {
 #endif
                micsampledouble = (double)micsample/32767.0; // 16 bit sample
-               if(mode==modeCWL || mode==modeCWU || tune) {
+               if(mode==modeCWL || mode==modeCWU || tune || !isTransmitting()) {
                    micinputbuffer[micsamples*2]=0.0;
                    micinputbuffer[(micsamples*2)+1]=0.0;
                } else {
@@ -911,7 +924,7 @@ static void process_mic_data(unsigned char *buffer) {
 #endif
 
         }
-    }
+//    }
 
 }
 
@@ -936,11 +949,15 @@ static void process_freedv_rx_buffer() {
           for(t=0;t<6;t++) { // 8k to 48k
             if(local_audio) {
                 audio_write(leftaudiosample,rightaudiosample);
+                leftaudiosample=0;
+                rightaudiosample=0;
             }
+
             audiobuffer[audioindex++]=leftaudiosample>>8;
             audiobuffer[audioindex++]=leftaudiosample;
             audiobuffer[audioindex++]=rightaudiosample>>8;
             audiobuffer[audioindex++]=rightaudiosample;
+            
             if(audioindex>=sizeof(audiobuffer)) {
                 // insert the sequence
               audiobuffer[0]=audiosequence>>24;
@@ -1091,6 +1108,80 @@ static void full_tx_buffer() {
   }
 }
 
+void *new_protocol_process_local_mic(unsigned char *buffer,int le) {
+    int b;
+    int leftmicsample;
+    int rightmicsample;
+    double leftmicsampledouble;
+    double rightmicsampledouble;
+
+//    if(isTransmitting()) {
+        b=0;
+        int i,j,s;
+        for(i=0;i<720;i++) {
+            if(le) {
+              leftmicsample  = (int)((unsigned char)buffer[b++] & 0xFF);
+              leftmicsample  |= (int)((signed char) buffer[b++]) << 8;
+              //rightmicsample  = (int)((unsigned char)buffer[b++] & 0xFF);
+              //rightmicsample  |= (int)((signed char) buffer[b++]) << 8;
+              rightmicsample=leftmicsample;
+            } else {
+              leftmicsample  = (int)((signed char) buffer[b++]) << 8;
+              leftmicsample  |= (int)((unsigned char)buffer[b++] & 0xFF);
+              rightmicsample  = (int)((signed char) buffer[b++]) << 8;
+              rightmicsample  |= (int)((unsigned char)buffer[b++] & 0xFF);
+            }
+#ifdef FREEDV
+            if(mode==modeFREEDV && isTransmitting()) {
+                if(freedv_samples==0) { // 48K to 8K
+                    int modem_samples=mod_sample_freedv(leftmicsample);
+                    if(modem_samples!=0) {
+                      for(s=0;s<modem_samples;s++) {
+                        for(j=0;j<freedv_resample;j++) {  // 8K to 48K
+                          leftmicsample=mod_out[s];
+                          leftmicsampledouble=(double)leftmicsample/32767.0; // 16 bit sample 2^16-1
+                          micinputbuffer[micsamples*2]=leftmicsampledouble*mic_gain;
+                          micinputbuffer[(micsamples*2)+1]=leftmicsampledouble*mic_gain;
+                          micsamples++;
+                          if(micsamples==BUFFER_SIZE) {
+                            full_tx_buffer();
+                            micsamples=0;
+                          }
+                        }
+                      }
+                    }
+               }
+               freedv_samples++;
+               if(freedv_samples==freedv_resample) {
+                   freedv_samples=0;
+               }
+            } else {
+#endif
+               leftmicsampledouble = (double)leftmicsample/32767.0; // 16 bit sample
+               rightmicsampledouble = (double)rightmicsample/32767.0; // 16 bit sample
+               if(mode==modeCWL || mode==modeCWU || tune || !isTransmitting()) {
+                   micinputbuffer[micsamples*2]=0.0;
+                   micinputbuffer[(micsamples*2)+1]=0.0;
+               } else {
+                   micinputbuffer[micsamples*2]=leftmicsampledouble*mic_gain;
+                   micinputbuffer[(micsamples*2)+1]=rightmicsampledouble*mic_gain;
+               }
+
+               micsamples++;
+
+               if(micsamples==BUFFER_SIZE) {
+                   full_tx_buffer();
+                   micsamples=0;
+               }
+#ifdef FREEDV
+           }
+#endif
+
+        }
+//    }
+
+}
+
 void* new_protocol_timer_thread(void* arg) {
     int count=0;
 fprintf(stderr,"new_protocol_timer_thread\n");
index a5c5f1055ac36dc51ccdb1b933f43fec7bd2b03b..b1e714d74db0ab2ff23f0d60620b3952b6c77a7c 100644 (file)
@@ -72,4 +72,5 @@ void setTune(int state);
 int getTune();
 int isTransmitting();
 
+void *new_protocol_process_local_mic(unsigned char *buffer,int le);
 #endif
index 9ca7ce544d97c0fbb5fccde9350f1638cc27f1e1..c974822de60439642602fd58d346b468c0fecfcc 100644 (file)
@@ -233,8 +233,8 @@ void old_protocol_init(int rx,int pixels) {
   //int result=sem_init(&frequency_changed_sem, 0, 1);
 
   if(local_audio) {
-    if(audio_init()!=0) {
-      fprintf(stderr,"audio_init failed\n");
+    if(audio_open_output()!=0) {
+      fprintf(stderr,"audio_open_output failed\n");
       local_audio=0;
     }
   }
diff --git a/pihpsdr b/pihpsdr
index a49694c48984652cb9bb8a4c90fb578846f33433..4138a68378e6ddd8e2997011af8d60f89be5c6ce 100755 (executable)
Binary files a/pihpsdr and b/pihpsdr differ
diff --git a/radio.c b/radio.c
index 48d783c564ef1c5ab12359c0bf9490adf781e3b8..f655b87b117c1f818f1b214f0d6cae12960d1588 100644 (file)
--- a/radio.c
+++ b/radio.c
@@ -23,6 +23,7 @@
 #include <semaphore.h>
 #include <math.h>
 
+#include "audio.h"
 #include "discovered.h"
 //#include "discovery.h"
 #include "mode.h"
@@ -191,6 +192,7 @@ int smeter=RXA_S_AV;
 int alc=TXA_ALC_PK;
 
 int local_audio=0;
+int local_microphone=0;
 
 int eer_pwm_min=100;
 int eer_pwm_max=800;
@@ -559,6 +561,12 @@ void radioRestoreState() {
     if(value) alc=atoi(value);
     value=getProperty("local_audio");
     if(value) local_audio=atoi(value);
+    value=getProperty("n_selected_output_device");
+    if(value) n_selected_output_device=atoi(value);
+    value=getProperty("local_microphone");
+    if(value) local_microphone=atoi(value);
+    value=getProperty("n_selected_input_device");
+    if(value) n_selected_input_device=atoi(value);
     bandRestoreState();
     sem_post(&property_sem);
 }
@@ -704,6 +712,12 @@ void radioSaveState() {
     setProperty("alc",value);
     sprintf(value,"%d",local_audio);
     setProperty("local_audio",value);
+    sprintf(value,"%d",n_selected_output_device);
+    setProperty("n_selected_output_device",value);
+    sprintf(value,"%d",local_microphone);
+    setProperty("local_microphone",value);
+    sprintf(value,"%d",n_selected_input_device);
+    setProperty("n_selected_input_device",value);
     bandSaveState();
 
     saveProperties(property_path);
diff --git a/radio.h b/radio.h
index bfc7d6a980a7570efe76ea595b28b1d569d2badc..b158ab1b43f9e9a0ec034efc4beca92718753ab0 100644 (file)
--- a/radio.h
+++ b/radio.h
@@ -206,6 +206,7 @@ extern int smeter;
 extern int alc;
 
 extern int local_audio;
+extern int local_microphone;
 
 extern int eer_pwm_min;
 extern int eer_pwm_max;
index 14e5f94c0d9630d0fd6800f3e264b6cf49a893ea..ba1e9e80e73f46bcaf54b59b974f6eda5780c9ce 100644 (file)
Binary files a/release/documentation/pihpsdr-install.odt and b/release/documentation/pihpsdr-install.odt differ
index 18d7bdeea9406983977e42d4886f0a118b3897ce..8272a1765dc0bfe02292682a097f9f3190d3fb51 100644 (file)
Binary files a/release/documentation/pihpsdr-install.pdf and b/release/documentation/pihpsdr-install.pdf differ
index 5b26589141c72dd1d999243accd96e939ce10971..7ef2e18225d309b4804195da430db60131a50002 100644 (file)
Binary files a/release/pihpsdr.tar and b/release/pihpsdr.tar differ
index 7692b8f80f2efff7fa0175113e94686e03d5a6b5..d6f769b5383d9b759cecc50bc78c64588f70b538 100755 (executable)
@@ -1,12 +1,17 @@
-rm -rf /usr/local/lib/libwdsp.so
-rm -rf /usr/local/lib/libpsk.so
-rm -rf /usr/local/lib/libcodec2.so
-rm -rf /usr/local/lib/libSoapySDR.so
-cp libwdsp.so /usr/local/lib
-cp libpsk.so /usr/local/lib
-cp libcodec2.so.0.5 /usr/local/lib
-cp libSoapySDR.so.0.5-1 /usr/local/lib
-cd /usr/local/lib; ln -s libcodec2.so.0.5 libcodec2.so
-cd /usr/local/lib; ln -s libSoapySDR.so.0.5-1 libSoapySDR.so.0.5.0
-cd /usr/local/lib; ln -s libSoapySDR.so.0.5-1 libSoapySDR.so
-ldconfig
+sudo apt-get -y install libfftw3-3
+sudo apt-get -y install xscreensaver
+wget abyz.co.uk/rpi/pigpio/pigpio.zip
+unzip pigpio.zip
+cd PIGPIO; make; sudo make install
+sudo rm -rf /usr/local/lib/libwdsp.so
+sudo rm -rf /usr/local/lib/libpsk.so
+sudo rm -rf /usr/local/lib/libcodec2.so
+sudo rm -rf /usr/local/lib/libSoapySDR.so
+sudo cp libwdsp.so /usr/local/lib
+sudo cp libpsk.so /usr/local/lib
+sudo cp libcodec2.so.0.5 /usr/local/lib
+sudo cp libSoapySDR.so.0.5-1 /usr/local/lib
+sudo cd /usr/local/lib; ln -s libcodec2.so.0.5 libcodec2.so
+sudo cd /usr/local/lib; ln -s libSoapySDR.so.0.5-1 libSoapySDR.so.0.5.0
+sudo cd /usr/local/lib; ln -s libSoapySDR.so.0.5-1 libSoapySDR.so
+sudo ldconfig
index a49694c48984652cb9bb8a4c90fb578846f33433..4138a68378e6ddd8e2997011af8d60f89be5c6ce 100755 (executable)
Binary files a/release/pihpsdr/pihpsdr and b/release/pihpsdr/pihpsdr differ