From 9324852bea1f07551bfbf5ef98cf4923fed69989 Mon Sep 17 00:00:00 2001
From: John Melton G0ORX <john.d.melton@googlemail.com>
Date: Thu, 5 Aug 2021 17:09:24 +0100
Subject: [PATCH] Updated actions. Handle CW MIDI input early (no actions).

---
 Makefile        |    2 +-
 action_dialog.c |   16 +-
 actions.c       |   43 +-
 css.c           |   17 +
 encoder_menu.c  |   10 +-
 main.c          |    3 +-
 meter.c         |    4 +-
 midi3.c         | 1064 +----------------------------------------------
 midi_menu.c     |    7 -
 new_protocol.c  |    6 +
 old_protocol.c  |    1 +
 pulseaudio.c    |    2 +-
 radio.c         |   11 +-
 radio.h         |    2 +
 radio_menu.c    |   23 +-
 switch_menu.c   |    8 -
 toolbar_menu.c  |    9 -
 vfo.c           |    4 +-
 18 files changed, 135 insertions(+), 1097 deletions(-)

diff --git a/Makefile b/Makefile
index 177adaf..8f12050 100644
--- a/Makefile
+++ b/Makefile
@@ -26,7 +26,7 @@ PURESIGNAL_INCLUDE=PURESIGNAL
 # USBOZY_INCLUDE=USBOZY
 
 # uncomment the line to below include support local CW keyer
-#LOCALCW_INCLUDE=LOCALCW
+LOCALCW_INCLUDE=LOCALCW
 
 # uncomment the line below for SoapySDR
 #SOAPYSDR_INCLUDE=SOAPYSDR
diff --git a/action_dialog.c b/action_dialog.c
index a60fd71..f60063d 100644
--- a/action_dialog.c
+++ b/action_dialog.c
@@ -7,6 +7,7 @@ typedef struct _choice {
   int action;
   GtkWidget *button;
   gulong signal_id;
+  struct _choice *previous;
 } CHOICE;
 
 static GtkWidget *dialog;
@@ -26,6 +27,8 @@ static void action_select_cb(GtkWidget *widget,gpointer data) {
 
 int action_dialog(GtkWidget *parent,int filter,int currentAction) {
   int i,j;
+  CHOICE *previous=NULL;
+  CHOICE *choice=NULL;
 
   action=currentAction;
   previous_button=NULL;
@@ -44,15 +47,18 @@ int action_dialog(GtkWidget *parent,int filter,int currentAction) {
   for(i=0;i<ACTIONS;i++) {
     if((ActionTable[i].type&filter) || (ActionTable[i].type==TYPE_NONE)) {
       GtkWidget *button=gtk_toggle_button_new_with_label(ActionTable[i].str);
-      gtk_widget_set_name(button,"small_button");
+      gtk_widget_set_name(button,"small_toggle_button");
       gtk_grid_attach(GTK_GRID(grid),button,j%GRID_WIDTH,j/GRID_WIDTH,1,1);
       if(ActionTable[i].action==currentAction) {
         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
       }
-      CHOICE *choice=g_new0(CHOICE,1);
+      choice=g_new0(CHOICE,1);
       choice->action=i;
       choice->button=button;
       choice->signal_id=g_signal_connect(button,"toggled",G_CALLBACK(action_select_cb),choice);
+      choice->previous=previous;
+      previous=choice;
+
       if(ActionTable[i].action==currentAction) {
         previous_button=button;
         previous_signal_id=choice->signal_id;
@@ -68,6 +74,12 @@ int action_dialog(GtkWidget *parent,int filter,int currentAction) {
   if(result!=GTK_RESPONSE_ACCEPT) {
     action=currentAction;
   }
+  // free up choice structures
+  while(previous!=NULL) {
+    choice=previous;
+    previous=choice->previous;
+    g_free(choice);
+  }
   return action;
 }
 
diff --git a/actions.c b/actions.c
index b2a2e7e..1e73ac2 100644
--- a/actions.c
+++ b/actions.c
@@ -182,6 +182,21 @@ ACTION_TABLE ActionTable[] = {
   {ACTIONS,		"",			NULL,		TYPE_NONE}
 };
 
+static gint timer=0;
+static gboolean timer_released;
+
+static int timeout_cb(gpointer data) {
+  if(timer_released) {
+    g_free(data);
+    timer=0;
+    return FALSE;
+  }
+  // process the action;
+  process_action(data);
+  return TRUE;
+}
+
+
 
 int process_action(void *data) {
   PROCESS_ACTION *a=(PROCESS_ACTION *)data;
@@ -193,8 +208,9 @@ int process_action(void *data) {
   FILTER *filter;
   int new_val;
   int i;
+  gboolean free_action=TRUE;
 
-  g_print("%s: action=%d mode=%d value=%d\n",__FUNCTION__,a->action,a->mode,a->val);
+  //g_print("%s: action=%d mode=%d value=%d\n",__FUNCTION__,a->action,a->mode,a->val);
   switch(a->action) {
 
     case A_SWAP_B:
@@ -955,11 +971,25 @@ int process_action(void *data) {
     case RIT_MINUS:
       if(a->mode==PRESSED) {
         vfo_rit(active_receiver->id,-1);
+	if(timer==0) {
+  	  timer=g_timeout_add(250,timeout_cb,a);
+	  timer_released=FALSE;
+	}
+	free_action=FALSE;
+      } else {
+	timer_released=TRUE;
       }
       break;
     case RIT_PLUS:
       if(a->mode==PRESSED) {
         vfo_rit(active_receiver->id,1);
+	if(timer==0) {
+	  timer=g_timeout_add(250,timeout_cb,a);
+	  timer_released=FALSE;
+	}
+	free_action=FALSE;
+      } else {
+	timer_released=TRUE;
       }
       break;
     case RIT_RX1:
@@ -1192,6 +1222,7 @@ int process_action(void *data) {
         value=10000.0;
       }
       transmitter->xit=(int)value;
+      transmitter->xit_enabled=(value!=0);
       if(protocol==NEW_PROTOCOL) {
         schedule_high_priority();
       }
@@ -1201,6 +1232,10 @@ int process_action(void *data) {
       if(a->mode==PRESSED) {
         if(can_transmit) {
           transmitter->xit=0;
+          transmitter->xit_enabled=0;
+          if(protocol==NEW_PROTOCOL) {
+            schedule_high_priority();
+          }
           g_idle_add(ext_vfo_update, NULL);
         }
       }
@@ -1227,6 +1262,7 @@ int process_action(void *data) {
             value=10000.0;
           }
           transmitter->xit=(int)value;
+	  transmitter->xit_enabled=(value!=0);
           if(protocol==NEW_PROTOCOL) {
             schedule_high_priority();
           }
@@ -1245,6 +1281,7 @@ int process_action(void *data) {
             value=10000.0;
           }
           transmitter->xit=(int)value;
+	  transmitter->xit_enabled=(value!=0);
           if(protocol==NEW_PROTOCOL) {
             schedule_high_priority();
           }
@@ -1274,7 +1311,9 @@ int process_action(void *data) {
       }
       break;
   }
-  g_free(data);
+  if(free_action) {
+    g_free(data);
+  }
   return 0;
 }
 
diff --git a/css.c b/css.c
index 810492c..16bfd7b 100644
--- a/css.c
+++ b/css.c
@@ -2,11 +2,28 @@
 #include "css.h"
 
 char *css=
+"  @define-color TOGGLE_ON rgb(100%,0%,0%);\n"
+"  @define-color TOGGLE_OFF rgb(70%,70%,70%);\n"
 "  #small_button {\n"
 "    padding: 0;\n"
 "    font-family: Sans;\n"
 "    font-size: 15px;\n"
 "    }\n"
+"  #small_toggle_button {\n"
+"    padding: 0;\n"
+"    font-family: Sans;\n"
+"    font-size: 15px;\n"
+"    background-image: none;\n"
+"    background-color: @TOGGLE_OFF;\n"
+"    }\n"
+"  #small_toggle_button:checked {\n"
+"    padding: 0;\n"
+"    font-family: Sans;\n"
+"    font-size: 15px;\n"
+"    background-image: none;\n"
+"    background-color: @TOGGLE_ON;\n"
+"    }\n"
+
 ;
 
 void load_css() {
diff --git a/encoder_menu.c b/encoder_menu.c
index 933be4b..66b6b2f 100644
--- a/encoder_menu.c
+++ b/encoder_menu.c
@@ -37,14 +37,6 @@
 #include "gpio.h"
 #include "i2c.h"
 
-typedef struct _choice {
-  int id;
-  int action;
-  GtkWidget *initial_button;
-  GtkWidget *button;
-  gulong signal_id;
-} CHOICE;
-
 static GtkWidget *parent_window=NULL;
 
 static GtkWidget *dialog=NULL;
@@ -101,7 +93,7 @@ void encoder_menu(GtkWidget *parent) {
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent));
   //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
-  char title[32];
+  char title[64];
   switch(controller) {
     case NO_CONTROLLER:
       sprintf(title,"piHPSDR - No Encoders");
diff --git a/main.c b/main.c
index 903f450..def2e87 100644
--- a/main.c
+++ b/main.c
@@ -199,7 +199,7 @@ static int init(void *data) {
   char *c=getcwd(wisdom_directory, sizeof(wisdom_directory));
   strcpy(&wisdom_directory[strlen(wisdom_directory)],"/");
   fprintf(stderr,"Securing wisdom file in directory: %s\n", wisdom_directory);
-  status_text("Creating FFTW Wisdom file ...");
+  status_text("Checking FFTW Wisdom file ...");
   wisdom_running=1;
   pthread_create(&wisdom_thread_id, NULL, wisdom_thread, wisdom_directory);
   while (wisdom_running) {
@@ -209,6 +209,7 @@ static int init(void *data) {
       while (gtk_events_pending ()) {
         gtk_main_iteration ();
       }
+      status_text("Creating FFTW Wisdom file ...");
   }
 
   g_idle_add(ext_discovery,NULL);
diff --git a/meter.c b/meter.c
index fd48176..f36d6c0 100644
--- a/meter.c
+++ b/meter.c
@@ -446,7 +446,9 @@ if(analog_meter) {
 
       double swr;
       if (max_level > reverse) {
-        swr=(max_level+reverse)/(max_level-reverse);
+        //swr=(max_level+reverse)/(max_level-reverse);
+	// fix fhanks to JW1TWP
+	swr=(1+sqrt(max_level/reverse))/(1-sqrt(max_level/reverse));
       } else {
         swr=999.9;
       }
diff --git a/midi3.c b/midi3.c
index f2f0e7b..06aad2a 100644
--- a/midi3.c
+++ b/midi3.c
@@ -35,18 +35,22 @@ void DoTheMidi(int action, enum ACTIONtype type, int val) {
     int    *ip;
     PROCESS_ACTION *a;
 
-    //
-    // Handle cases in alphabetical order of the key words in midi.props
-    //
-
-    g_print("%s: action=%d type=%d val=%d\n",__FUNCTION__,action,type,val);
+    //g_print("%s: action=%d type=%d val=%d\n",__FUNCTION__,action,type,val);
 
     switch(type) {
       case MIDI_KEY:
-        a=g_new(PROCESS_ACTION,1);
-        a->action=action;
-        a->mode=val?PRESSED:RELEASED;
-        g_idle_add(process_action,a);
+	if(action==CW_LEFT || action==CW_RIGHT) {
+#ifdef LOCALCW
+          keyer_event(action==CW_LEFT,val);
+#else
+          g_print("MIDI CW key but compiled without LOCALCW\n");
+#endif
+        } else {
+          a=g_new(PROCESS_ACTION,1);
+          a->action=action;
+          a->mode=val?PRESSED:RELEASED;
+          g_idle_add(process_action,a);
+	}
 	break;
       case MIDI_KNOB:
         a=g_new(PROCESS_ACTION,1);
@@ -63,1046 +67,4 @@ void DoTheMidi(int action, enum ACTIONtype type, int val) {
         g_idle_add(process_action,a);
         break;
     }
-
-/*
-    switch (action) {
-	/////////////////////////////////////////////////////////// "A2B"
-	case A_TO_B: // only key supported
-	    if (type == MIDI_KEY) {
-	      a=g_new(PROCESS_ACTION,1);
-              a->action=A_TO_B;
-              a->mode=PRESSED;
-              g_idle_add(process_action,a);
-	      //g_idle_add(ext_vfo_a_to_b, NULL);
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "AFGAIN"
-	case AF_GAIN: // knob or wheel supported
-            switch (type) {
-	      case MIDI_KNOB:
-		a=g_new(PROCESS_ACTION,1);
-                a->action=AF_GAIN;
-                a->mode=ABSOLUTE;
-                a->val=val;
-                g_idle_add(process_action,a);
-		break;
-	      case MIDI_WHEEL:	
-		a=g_new(PROCESS_ACTION,1);
-                a->action=AF_GAIN;
-                a->mode=RELATIVE;
-                a->val=val;
-                g_idle_add(process_action,a);
-		break;
-	      default:
-		// do not change volume
-		// we should not come here anyway
-		break;
-	    }
-	    g_idle_add(ext_update_af_gain, NULL);
-	    break;
-	/////////////////////////////////////////////////////////// "AGCATTACK"
-	case AGC: // only key supported
-	    // cycle through fast/med/slow AGC attack
-	    if (type == MIDI_KEY) {
-	      a=g_new(PROCESS_ACTION,1);
-              a->action=AGC;
-              a->mode=PRESSED;
-              g_idle_add(process_action,a);
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "AGCVAL"
-	case AGC_GAIN: // knob or wheel supported
-	    switch (type) {
-	      case MIDI_KNOB:
-		a=g_new(PROCESS_ACTION,1);
-                a->action=AGC_GAIN;
-                a->mode=ABSOLUTE;
-                a->val=val;
-                g_idle_add(process_action,a);
-		//dnew = -20.0 + 1.4*val;
-		break;
-	      case MIDI_WHEEL:
-		a=g_new(PROCESS_ACTION,1);
-                a->action=AGC_GAIN;
-                a->mode=RELATIVE;
-                a->val=val;
-                g_idle_add(process_action,a);
-		//dnew=active_receiver->agc_gain + val;
-		//if (dnew < -20.0) dnew=-20.0; if (dnew > 120.0) dnew=120.0;
-		break;
-	      default:
-		// do not change value
-		// we should not come here anyway
-		//dnew=active_receiver->agc_gain;
-		break;
-	    }
-	    //dp=malloc(sizeof(double));
-	    //*dp=dnew;
-	    //g_idle_add(ext_set_agc_gain, (gpointer) dp);
-	    break;
-	/////////////////////////////////////////////////////////// "ANF"
-	case ANF:	// only key supported
-	    if (type == MIDI_KEY) {
-	      a=g_new(PROCESS_ACTION,1);
-              a->action=ANF;
-              a->mode=PRESSED;
-              g_idle_add(process_action,a);
-	      //g_idle_add(ext_anf_update, NULL);
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "ATT"
-	case ATTENUATION:	// Key for ALEX attenuator, wheel or knob for slider
-	    switch(type) {
-	      case MIDI_KEY:
-		if (filter_board == ALEX && active_receiver->adc == 0) {
-		  new=active_receiver->alex_attenuation + 1;
-		  if (new > 3) new=0;
-		  g_idle_add(ext_set_alex_attenuation, GINT_TO_POINTER(new));
-		  g_idle_add(ext_update_att_preamp, NULL);
-		}
-		break;
-	      case MIDI_WHEEL:
-		new=adc[active_receiver->adc].attenuation + val;
-		dp=malloc(sizeof(double));
-		*dp=(double) new;
-                if(have_rx_gain) {
-                  if(*dp<-12.0) {
-                    *dp=-12.0;
-                  } else if(*dp>48.0) {
-                    *dp=48.0;
-                  }
-                } else {
-                  if(*dp<0.0) {
-                    *dp=0.0;
-                  } else if (*dp>31.0) {
-                    *dp=31.0;
-                  }
-                }
-		g_idle_add(ext_set_attenuation_value,(gpointer) dp);
-		break;
-	      case MIDI_KNOB:
-		dp=malloc(sizeof(double));
-                if (have_rx_gain) {
-		  *dp=-12.0 + 0.6*(double) val;
-                } else {
-                  *dp = 0.31 * (double) val;
-                }
-		g_idle_add(ext_set_attenuation_value,(gpointer) dp);
-		break;
-	      default:
-		// do nothing
-		// we should not come here anyway
-		break;
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "B2A"
-	case B_TO_A: // only key supported
-	    if (type == MIDI_KEY) {
-	      a=g_new(PROCESS_ACTION,1);
-              a->action=B_TO_A;
-              a->mode=PRESSED;
-              g_idle_add(process_action,a);
-	      //g_idle_add(ext_vfo_b_to_a, NULL);
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "NUMPADxx"
-	case NUMPAD_0:
-	    g_idle_add(ext_num_pad,GINT_TO_POINTER(0));
-            break;
-	case NUMPAD_1:
-	    g_idle_add(ext_num_pad,GINT_TO_POINTER(1));
-            break;
-	case NUMPAD_2:
-	    g_idle_add(ext_num_pad,GINT_TO_POINTER(2));
-            break;
-	case NUMPAD_3:
-	    g_idle_add(ext_num_pad,GINT_TO_POINTER(3));
-            break;
-	case NUMPAD_4:
-	    g_idle_add(ext_num_pad,GINT_TO_POINTER(4));
-            break;
-	case NUMPAD_5:
-	    g_idle_add(ext_num_pad,GINT_TO_POINTER(5));
-            break;
-	case NUMPAD_6:
-	    g_idle_add(ext_num_pad,GINT_TO_POINTER(6));
-            break;
-	case NUMPAD_7:
-	    g_idle_add(ext_num_pad,GINT_TO_POINTER(7));
-            break;
-	case NUMPAD_8:
-	    g_idle_add(ext_num_pad,GINT_TO_POINTER(8));
-            break;
-	case NUMPAD_9:
-	    g_idle_add(ext_num_pad,GINT_TO_POINTER(9));
-            break;
-	case NUMPAD_CL:
-	    g_idle_add(ext_num_pad,GINT_TO_POINTER(-1));
-            break;
-	case NUMPAD_ENTER:
-	    g_idle_add(ext_num_pad,GINT_TO_POINTER(-2));
-            break;
-	    break;
-
-	/////////////////////////////////////////////////////////// "BANDxxx"
-        case BAND_10:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band10));
-            }
-            break;
-        case BAND_12:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band12));
-            }
-            break;
-#ifdef SOAPYSDR
-        case BAND_1240:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band1240));
-            }
-            break;
-        case BAND_144:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band144));
-            }
-            break;
-#endif
-        case BAND_15:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band15));
-            }
-            break;
-        case BAND_160:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band160));
-            }
-            break;
-        case BAND_17:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band17));
-            }
-            break;
-        case BAND_20:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band20));
-            }
-            break;
-#ifdef SOAPYSDR
-        case BAND_220:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band220));
-            }
-            break;
-        case BAND_2300:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band2300));
-            }
-            break;
-#endif
-        case BAND_30:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band30));
-            }
-            break;
-#ifdef SOAPYSDR
-        case BAND_3400:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band3400));
-            }
-            break;
-        case BAND_70:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band70));
-            }
-            break;
-#endif
-        case BAND_40:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band40));
-            }
-            break;
-#ifdef SOAPYSDR
-        case BAND_430:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band430));
-            }
-            break;
-#endif
-        case BAND_6:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band6));
-            }
-            break;
-        case BAND_60:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band60));
-            }
-            break;
-        case BAND_80:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band80));
-            }
-            break;
-#ifdef SOAPYSDR
-        case BAND_902:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(band902));
-            }
-            break;
-        case BAND_AIR:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(bandAIR));
-            }
-            break;
-#endif
-        case BAND_GEN:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(bandGen));
-            }
-            break;
-        case BAND_WWV:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_band_select, GINT_TO_POINTER(bandWWV));
-            }
-            break;
-	/////////////////////////////////////////////////////////// "BANDDOWN"
-	/////////////////////////////////////////////////////////// "BANDUP"
-	case BAND_MINUS:
-	case BAND_PLUS:
-	    switch (type) {
-	      case MIDI_KEY:
-		new=(action == BAND_PLUS) ? 1 : -1;
-		break;
-	      case MIDI_WHEEL:
-		new=val > 0 ? 1 : -1;
-		break;
-	      case MIDI_KNOB:
-		// cycle through the bands
-		new = ((BANDS-1) * val) / 100 - vfo[active_receiver->id].band;
-		break;
-	      default:
-		// do not change
-		// we should not come here anyway
-		new=0;
-		break;
-	    }
-	    //
-	    // If the band has not changed, do nothing. Otherwise
-	    // vfo.c will loop through the band stacks
-	    //
-	    if (new != 0) {
-	      new+=vfo[active_receiver->id].band;
-	      if (new >= BANDS) new=0;
-	      if (new < 0) new=BANDS-1;
-	      g_idle_add(ext_vfo_band_changed, GINT_TO_POINTER(new));
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "COMPRESSION"
-	case COMPRESSION: // wheel or knob
-	    switch (type) {
-	      case MIDI_WHEEL:
-		dnew=transmitter->compressor_level + val;
-		if (dnew > 20.0) dnew=20.0;
-		if (dnew < 0 ) dnew=0;
-		break;
-	      case MIDI_KNOB:
-		dnew=(20.0*val)/100.0;
-		break;
-	      default:
-		// do not change
-		// we should not come here anyway
-		dnew=transmitter->compressor_level;
-		break;
-	    }
-	    transmitter->compressor_level=dnew;
-	    // automatically engange compressor if level > 0.5
-	    if (dnew < 0.5) transmitter->compressor=0;
-	    if (dnew > 0.5) transmitter->compressor=1;
-	    g_idle_add(ext_set_compression, NULL);
-	    break;
-	/////////////////////////////////////////////////////////// "CTUN"
-	case CTUN: // only key supported
-	    // toggle CTUN
-	    if (type == MIDI_KEY) {
-	      g_idle_add(ext_ctun_update, NULL);
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "CURRVFO"
-	case VFO: // only wheel supported
-	    if (type == MIDI_WHEEL && !locked) {
-		g_idle_add(ext_vfo_step, GINT_TO_POINTER(val));
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "CWL"
-	/////////////////////////////////////////////////////////// "CWR"
-	case CW_LEFT: // only key
-	case CW_RIGHT: // only key
-#ifdef LOCALCW
-	    if (type == MIDI_KEY) {
-		new=(action == CW_LEFT);
-		keyer_event(new,val);
-	    }
-#else
-	    g_print("%s: %s:%d\n",__FUNCTION__,action==CW_LEFT?"CWL":"CWR",val);
-
-#endif
-	    break;
-	/////////////////////////////////////////////////////////// "CWSPEED"
-	case CW_SPEED: // knob or wheel
-            switch (type) {
-              case MIDI_KNOB:
-		// speed between 5 and 35 wpm
-                new= (int) (5.0 + (double) val * 0.3);
-                break;
-              case MIDI_WHEEL:
-		// here we allow from 1 to 60 wpm
-                new = cw_keyer_speed + val;
-		if (new <  1) new=1;
-		if (new > 60) new=60;
-                break;
-              default:
-                // do not change
-                // we should not come here anyway
-                new = cw_keyer_speed;
-                break;
-            }
-	    cw_keyer_speed=new;
-#ifdef LOCALCW
-	    keyer_update();
-#endif
-            g_idle_add(ext_vfo_update, NULL);
-	    break;
-	/////////////////////////////////////////////////////////// "DIVCOARSEGAIN"
-	case DIV_GAIN_COARSE:  // knob or wheel supported
-	case DIV_GAIN_FINE:    // knob or wheel supported
-	case DIV_GAIN:        // knob or wheel supported
-            switch (type) {
-              case MIDI_KNOB:
-                if (action == DIV_GAIN_COARSE || action == DIV_GAIN) {
-		  // -25 to +25 dB in steps of 0.5 dB
-		  dnew = 10.0*(-25.0 + 0.5*val - div_gain);
-		} else {
-		  // round gain to a multiple of 0.5 dB and apply a +/- 0.5 dB update
-                  new = (int) (2*div_gain + 1.0) / 2;
-		  dnew = 10.0*((double) new + 0.01*val - 0.5 - div_gain);
-		}
-                break;
-              case MIDI_WHEEL:
-                // coarse: increaments in steps of 0.25 dB, medium: steps of 0.1 dB fine: in steps of 0.01 dB
-                if (action == DIV_GAIN) {
-		  dnew = val*0.5;
-		} else if (action == DIV_GAIN_COARSE) {
-		  dnew = val*2.5;
-		} else {
-		  dnew = val * 0.1;
-	 	}
-                break;
-              default:
-                // do not change
-                // we should not come here anyway
-		dnew = 0.0;
-                break;
-            }
-	    // dnew is the delta times 10
-	    dp=malloc(sizeof(double));
-	    *dp=dnew;
-            g_idle_add(ext_diversity_change_gain, dp);
-            break;
-        /////////////////////////////////////////////////////////// "DIVPHASE"
-        case DIV_PHASE_COARSE:   // knob or wheel supported
-        case DIV_PHASE_FINE:     // knob or wheel supported
-	case DIV_PHASE:		// knob or wheel supported
-            switch (type) {
-              case MIDI_KNOB:
-		// coarse: change phase from -180 to 180
-                // fine: change from -5 to 5
-                if (action == DIV_PHASE_COARSE || action == DIV_PHASE) {
-		  // coarse: change phase from -180 to 180 in steps of 3.6 deg
-                  dnew = (-180.0 + 3.6*val - div_phase);
-                } else {
-		  // fine: round to multiple of 5 deg and apply a +/- 5 deg update
-                  new = 5 * ((int) (div_phase+0.5) / 5);
-                  dnew =  (double) new + 0.1*val -5.0 -div_phase;
-                }
-                break;
-              case MIDI_WHEEL:
-		if (action == DIV_PHASE) {
-		  dnew = val*0.5; 
-		} else if (action == DIV_PHASE_COARSE) {
-		  dnew = val*2.5;
-		} else if (action == DIV_PHASE_FINE) {
-		  dnew = 0.1*val;
-		}
-                break;
-              default:
-                // do not change
-                // we should not come here anyway
-                dnew = 0.0;
-                break;
-            }
-            // dnew is the delta
-            dp=malloc(sizeof(double));
-            *dp=dnew;
-            g_idle_add(ext_diversity_change_phase, dp);
-            break;
-        /////////////////////////////////////////////////////////// "DIVTOGGLE"
-        case DIV:   // only key supported
-            if (type == MIDI_KEY) {
-                // enable/disable DIVERSITY
-                diversity_enabled = diversity_enabled ? 0 : 1;
-                g_idle_add(ext_vfo_update, NULL);
-            }
-            break;
-	/////////////////////////////////////////////////////////// "DUP"
-        case DUPLEX:
-	    if (can_transmit && !isTransmitting()) {
-	      duplex=duplex==1?0:1;
-              g_idle_add(ext_set_duplex, NULL);
-	    }
-            break;
-	/////////////////////////////////////////////////////////// "FILTERDOWN"
-	/////////////////////////////////////////////////////////// "FILTERUP"
-	case FILTER_MINUS:
-	case FILTER_PLUS:
-	    //
-	    // In filter.c, the filters are sorted such that the widest one comes first
-	    // Therefore let FILTER_UP move down.
-	    //
-	    switch (type) {
-	      case MIDI_KEY:
-		new=(action == FILTER_PLUS) ? -1 : 1;
-		break;
-	      case MIDI_WHEEL:
-		new=val > 0 ? -1 : 1;
-		break;
-	      case MIDI_KNOB:
-		// cycle through all the filters: val=100 maps to filter #0
-		new = ((FILTERS-1) * (val-100)) / 100 - vfo[active_receiver->id].filter;
-		break;
-	      default:
-		// do not change filter setting
-		// we should not come here anyway
-		new=0;
-		break;
-	    }
-	    if (new != 0) {
-	      new+=vfo[active_receiver->id].filter;
-	      if (new >= FILTERS) new=0;
-	      if (new <0) new=FILTERS-1;
-	      g_idle_add(ext_vfo_filter_changed, GINT_TO_POINTER(new));
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "MENU_FILTFILTERER"
-	case MENU_FILTER:
-	    g_idle_add(ext_menu_filter, NULL);
-	    break;
-	/////////////////////////////////////////////////////////// "MENU_MODE"
-	case MENU_MODE:
-	    g_idle_add(ext_menu_mode, NULL);
-	    break;
-	/////////////////////////////////////////////////////////// "LOCK"
-	case LOCK: // only key supported
-	    if (type == MIDI_KEY) {
-	      locked=!locked;
-	      g_idle_add(ext_vfo_update, NULL);
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "MICGAIN"
-	case MIC_GAIN: // knob or wheel supported
-	    // TODO: possibly adjust linein value if that is effective
-	    switch (type) {
-	      case MIDI_KNOB:
-		dnew=-10.0 + 0.6*val;
-		break;
-	      case MIDI_WHEEL:
-		dnew = mic_gain + val;
-		if (dnew < -10.0) dnew=-10.0; if (dnew > 50.0) dnew=50.0;
-		break;
-	      default:
-		// do not change mic gain
-		// we should not come here anyway
-		dnew = mic_gain;
-		break;
-	    }
-	    dp=malloc(sizeof(double));
-	    *dp=dnew;
-	    g_idle_add(ext_set_mic_gain, (gpointer) dp);
-	    break;
-	/////////////////////////////////////////////////////////// "MODEDOWN"
-	/////////////////////////////////////////////////////////// "MODEUP"
-	case MODE_MINUS:
-	case MODE_PLUS:
-	    switch (type) {
-	      case MIDI_KEY:
-		new=(action == MODE_PLUS) ? 1 : -1;
-		break;
-	      case MIDI_WHEEL:
-		new=val > 0 ? 1 : -1;
-		break;
-	      case MIDI_KNOB:
-		// cycle through all the modes
-		new = ((MODES-1) * val) / 100 - vfo[active_receiver->id].mode;
-		break;
-	      default:
-		// do not change
-		// we should not come here anyway
-		new=0;
-		break;
-	    }
-	    if (new != 0) {
-	      new+=vfo[active_receiver->id].mode;
-	      if (new >= MODES) new=0;
-	      if (new <0) new=MODES-1;
-	      g_idle_add(ext_vfo_mode_changed, GINT_TO_POINTER(new));
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "MOX"
-	case MOX: // only key supported
-	    if (type == MIDI_KEY && can_transmit) {
-	        new = !mox;
-		g_idle_add(ext_mox_update, GINT_TO_POINTER(new));
-	    }
-	    break;    
-        /////////////////////////////////////////////////////////// "MUTE"
-        case MUTE:
-            if (type == MIDI_KEY) {
-              g_idle_add(ext_mute_update,NULL);
-	    }
-            break;
-	/////////////////////////////////////////////////////////// "NOISEBLANKER"
-	case NB: // only key supported
-	    // cycle through NoiseBlanker settings: OFF, NB, NB2
-            if (type == MIDI_KEY) {
-	      if (active_receiver->nb) {
-		active_receiver->nb = 0;
-		active_receiver->nb2= 1;
-	      } else if (active_receiver->nb2) {
-		active_receiver->nb = 0;
-		active_receiver->nb2= 0;
-	      } else {
-		active_receiver->nb = 1;
-		active_receiver->nb2= 0;
-	      }
-	      g_idle_add(ext_vfo_update, NULL);
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "NOISEREDUCTION"
-	case NR: // only key supported
-	    // cycle through NoiseReduction settings: OFF, NR1, NR2
-	    if (type == MIDI_KEY) {
-	      if (active_receiver->nr) {
-		active_receiver->nr = 0;
-		active_receiver->nr2= 1;
-	      } else if (active_receiver->nr2) {
-		active_receiver->nr = 0;
-		active_receiver->nr2= 0;
-	      } else {
-		active_receiver->nr = 1;
-		active_receiver->nr2= 0;
-	      }
-	      g_idle_add(ext_update_noise, NULL);
-	      g_idle_add(ext_vfo_update, NULL);
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "PAN"
-        case PAN:  // wheel and knob
-	    switch (type) {
-              case MIDI_WHEEL:
-                g_idle_add(ext_pan_update,GINT_TO_POINTER(val));
-                break;
-	      case MIDI_KNOB:
-                g_idle_add(ext_pan_set,GINT_TO_POINTER(val));
-                break;
-	      default:
-		// no action for keys (we should not come here anyway)
-		break;
-            }
-            break;
-	/////////////////////////////////////////////////////////// "PANHIGH"
-	case PANADAPTER_HIGH:  // wheel or knob
-	    switch (type) {
-	      case MIDI_WHEEL:
-		if (mox) {
-		    // TX panadapter affected
-		    transmitter->panadapter_high += val;
-		} else {
-		    active_receiver->panadapter_high += val;
-		}
-		break;
-	    case MIDI_KNOB:
-		// Adjust "high water" in the range -50 ... 0 dBm
-		new = -50 + val/2;
-		if (mox) {
-		    transmitter->panadapter_high = new;
-		} else {
-		    active_receiver->panadapter_high = new;
-		}
-		break;
-	      default:
-		// do nothing
-		// we should not come here anyway
-		break;
-	    }
-	    g_idle_add(ext_vfo_update, NULL);
-	    break;
-	/////////////////////////////////////////////////////////// "PANLOW"
-	case PANADAPTER_LOW:  // wheel and knob
-	    switch (type) {
-	      case MIDI_WHEEL:
-		if (isTransmitting()) {
-		    // TX panadapter affected
-		    transmitter->panadapter_low += val;
-		} else {
-		    active_receiver->panadapter_low += val;
-		}
-		break;
-	      case MIDI_KNOB:
-		if (isTransmitting()) {
-		    // TX panadapter: use values -100 through -50
-		    new = -100 + val/2;
-		    transmitter->panadapter_low =new;
-		} else {
-		    // RX panadapter: use values -140 through -90
-		    new = -140 + val/2;
-		    active_receiver->panadapter_low = new;
-		}
-		break;
-	      default:
-		// do nothing
-		// we should not come here anyway
-		break;
-	    }
-	    g_idle_add(ext_vfo_update, NULL);
-	    break;
-	/////////////////////////////////////////////////////////// "PREAMP"
-	case PREAMP:	// only key supported
-	    if (type == MIDI_KEY) {
-		//
-		// Normally on/off, but for CHARLY25, cycle through three
-		// possible states. Current HPSDR hardware does no have
-		// switch'able preamps.
-		//
-		int c25= (filter_board == CHARLY25);
-		new = active_receiver->preamp + active_receiver->dither;
-		new++;
-		if (c25) {
-		  if (new >2) new=0;
-		} else {
-		  if (new >1) new=0;
-		}
-		switch (new) {
-		    case 0:
-			active_receiver->preamp=0;
-			if (c25) active_receiver->dither=0;
-			break;
-		    case 1:
-			active_receiver->preamp=1;
-			if (c25) active_receiver->dither=0;
-			break;
-		    case 2:
-			active_receiver->preamp=1;
-			if (c25) active_receiver->dither=1;
-			break;
-		}
-		g_idle_add(ext_update_att_preamp, NULL);
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "PURESIGNAL"
-	case PS: // only key supported
-#ifdef PURESIGNAL
-	    // toggle PURESIGNAL
-	    if (type == MIDI_KEY) {
-	      new=!(transmitter->puresignal);
-	      g_idle_add(ext_tx_set_ps,GINT_TO_POINTER(new));
-	    }
-#endif
-	    break;
-	/////////////////////////////////////////////////////////// "RFGAIN"
-        case RF_GAIN: // knob or wheel supported
-            if (type == MIDI_KNOB) {
-                new=val;
-            } else  if (type == MIDI_WHEEL) {
-                //new=(int)active_receiver->rf_gain+val;
-                new=(int)adc[active_receiver->id].gain+val;
-            }
-            g_idle_add(ext_set_rf_gain, GINT_TO_POINTER((int)new));
-	    break;
-	/////////////////////////////////////////////////////////// "RFPOWER"
-	case DRIVE: // knob or wheel supported
-	    switch (type) {
-	      case MIDI_KNOB:
-		dnew = val;
-		break;
-	      case MIDI_WHEEL:
-		dnew=transmitter->drive + val;
-		if (dnew < 0.0) dnew=0.0; if (dnew > 100.0) dnew=100.0;
-		break;
-	      default:
-		// do not change value
-		// we should not come here anyway
-		dnew=transmitter->drive;
-		break;
-	    }
-	    dp=malloc(sizeof(double));
-	    *dp=dnew;
-	    g_idle_add(ext_set_drive, (gpointer) dp);
-	    break;
-	/////////////////////////////////////////////////////////// "RITCLEAR"
-	case RIT_CLEAR:	  // only key supported
-	    if (type == MIDI_KEY) {
-	      // clear RIT value
-	      vfo[active_receiver->id].rit = new;
-	      g_idle_add(ext_vfo_update, NULL);
-	    }
-	/////////////////////////////////////////////////////////// "RITSTEP"
-        case RIT_STEP: // key or wheel supported
-            // This cycles between RIT increments 1, 10, 100, 1, 10, 100, ...
-            switch (type) {
-              case MIDI_KEY:
-                // key cycles through in upward direction
-                val=1;
-                // FALLTHROUGH
-              case MIDI_WHEEL:
-                // wheel cycles upward or downward
-                if (val > 0) {
-                  rit_increment=10*rit_increment;
-                } else {
-                  rit_increment=rit_increment/10;
-                }
-                if (rit_increment < 1) rit_increment=100;
-                if (rit_increment > 100) rit_increment=1;
-                break;
-              default:
-                // do nothing
-                break;
-            }
-            g_idle_add(ext_vfo_update, NULL);
-            break;
-	/////////////////////////////////////////////////////////// "RITTOGGLE"
-	case RIT_ENABLE:  // only key supported
-	    if (type == MIDI_KEY) {
-		// enable/disable RIT
-		new=vfo[active_receiver->id].rit_enabled;
-		vfo[active_receiver->id].rit_enabled = new ? 0 : 1;
-	        g_idle_add(ext_vfo_update, NULL);
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "RITVAL"
-	case RIT:	// wheel or knob
-	    switch (type) {
-	      case MIDI_WHEEL:
-		// This changes the RIT value incrementally,
-	  	// but we restrict the change to +/ 9.999 kHz
-		new = vfo[active_receiver->id].rit + val*rit_increment;
-		if (new >  9999) new= 9999;
-		if (new < -9999) new=-9999;
-		vfo[active_receiver->id].rit = new;
-		break;
-	      case MIDI_KNOB:
-	 	// knob: adjust in the range +/ 50*rit_increment
-		new = (val-50) * rit_increment;
-		vfo[active_receiver->id].rit = new;
-		break;
-	      default:
-		// do nothing
-		// we should not come here anyway
-		break;
-	    }
-	    // enable/disable RIT according to RIT value
-	    vfo[active_receiver->id].rit_enabled = (vfo[active_receiver->id].rit == 0) ? 0 : 1;
-	    g_idle_add(ext_vfo_update, NULL);
-	    break;
-	/////////////////////////////////////////////////////////// "SAT"
-        case SAT:
-	    switch (sat_mode) {
-		case SAT_NONE:
-		  sat_mode=SAT_MODE;
-		  break;
-		case SAT_MODE:
-		  sat_mode=RSAT_MODE;
-		  break;
-		case RSAT_MODE:
-		default:
-		  sat_mode=SAT_NONE;
-		  break;
-	    }
-	    g_idle_add(ext_vfo_update, NULL);
-            break;
-	/////////////////////////////////////////////////////////// "SNB"
-	case SNB:	// only key supported
-	    if (type == MIDI_KEY) {
-	      g_idle_add(ext_snb_update, NULL);
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "SPLIT"
-	case SPLIT: // only key supported
-	    // toggle split mode
-	    if (type == MIDI_KEY) {
-              g_idle_add(ext_split_toggle, NULL);
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "SWAPRX"
-	case SWAP_RX:	// only key supported
-	    if (type == MIDI_KEY && receivers == 2) {
-		new=active_receiver->id;	// 0 or 1
-		new= (new == 1) ? 0 : 1;	// id of currently inactive receiver
-		active_receiver=receiver[new];
-		g_idle_add(menu_active_receiver_changed,NULL);
-		g_idle_add(ext_vfo_update,NULL);
-		g_idle_add(sliders_active_receiver_changed,NULL);
-	    }
-	    break;    
-	/////////////////////////////////////////////////////////// "SWAPVFO"
-	//case SWAP_VFO:	// only key supported
-	//    if (type == MIDI_KEY) {
-//		g_idle_add(ext_vfo_a_swap_b,NULL);
-//	    }
-//	    break;    
-	/////////////////////////////////////////////////////////// "TUNE"
-	case TUNE: // only key supported
-	    if (type == MIDI_KEY && can_transmit) {
-	        new = !tune;
-		g_idle_add(ext_tune_update, GINT_TO_POINTER(new));
-	    }
-	    break;    
-	/////////////////////////////////////////////////////////// "VFOA"
-	/////////////////////////////////////////////////////////// "VFOB"
-	case VFOA: // only wheel supported
-	case VFOB: // only wheel supported
-	    if (type == MIDI_WHEEL && !locked) {
-	        ip=malloc(2*sizeof(int));
-		*ip = (action == VFOA) ? 0 : 1;   // could use (action - VFOA) to support even more VFOs
-		*(ip+1)=val;
-		g_idle_add(ext_vfo_id_step, ip);
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "VFOSTEPDOWN"
-	/////////////////////////////////////////////////////////// "VFOSTEPUP"
-        case VFO_STEP_MINUS: // key or wheel supported
-        case VFO_STEP_PLUS:
-	    switch (type) {
-	      case MIDI_KEY:
-		new =  (action == VFO_STEP_PLUS) ? 1 : -1;
-		g_idle_add(ext_update_vfo_step, GINT_TO_POINTER(new));
-		break;
-	      case MIDI_WHEEL:
-		new = (val > 0) ? 1 : -1;
-		g_idle_add(ext_update_vfo_step, GINT_TO_POINTER(new));
-		break;
-	      default:
-		// do nothing
-		// we should not come here anyway
-		break;
-	    }
-            break;
-	/////////////////////////////////////////////////////////// "VOX"
-	case VOX: // only key supported
-	    // toggle VOX
-	    if (type == MIDI_KEY) {
-	      vox_enabled = !vox_enabled;
-	      g_idle_add(ext_vfo_update, NULL);
-	    }
-	    break;
-	/////////////////////////////////////////////////////////// "VOXLEVEL"
-	case VOXLEVEL: // knob or wheel supported
-            switch (type) {
-              case MIDI_WHEEL:
-                // This changes the value incrementally,
-                // but stay within limits (0.0 through 1.0)
-                vox_threshold += (double) val * 0.01;
-		if (vox_threshold > 1.0) vox_threshold=1.0;
-		if (vox_threshold < 0.0) vox_threshold=0.0;
-                break;
-              case MIDI_KNOB:
-                vox_threshold = 0.01 * (double) val;
-                break;
-              default:
-                // do nothing
-                // we should not come here anyway
-                break;
-            }
-	    // VOX level not shown on screen, hence no VFO update
-	    break;
-	/////////////////////////////////////////////////////////// "XITCLEAR"
-        case XIT_CLEAR:  // only key supported
-            if (type == MIDI_KEY) {
-                // this clears the XIT value and disables XIT
-                if(can_transmit) {
-                  transmitter->xit = 0;
-                  transmitter->xit_enabled = 0;
-                  g_idle_add(ext_vfo_update, NULL);
-                }
-            }
-            break;
-	/////////////////////////////////////////////////////////// "XITVAL"
-        case XIT:   // wheel and knob supported.
-	    if (can_transmit) {
-              switch (type) {
-                case MIDI_WHEEL:
-                  // This changes the XIT value incrementally,
-                  // but we restrict the change to +/ 9.999 kHz
-                  new = transmitter->xit + val*rit_increment;
-                  if (new >  9999) new= 9999;
-                  if (new < -9999) new=-9999;
-                  transmitter->xit = new;
-                  break;
-                case MIDI_KNOB:
-                  // knob: adjust in the range +/ 50*rit_increment
-                  new = (val-50) * rit_increment;
-                  transmitter->xit = new;
-                  break;
-                default:
-                  // do nothing
-                  // we should not come here anyway
-                  break;
-              }
-              // enable/disable XIT according to XIT value
-              transmitter->xit_enabled = (transmitter->xit == 0) ? 0 : 1;
-              g_idle_add(ext_vfo_update, NULL);
-	    }
-            break;
-	/////////////////////////////////////////////////////////// "ZOOM"
-        case ZOOM:  // wheel and knob
-            switch (type) {
-              case MIDI_WHEEL:
-g_print("MIDI_ZOOM: MIDI_WHEEL: val=%d\n",val);
-                g_idle_add(ext_zoom_update,GINT_TO_POINTER(val));
-                break;
-              case MIDI_KNOB:
-g_print("MIDI_ZOOM: MIDI_KNOB: val=%d\n",val);
-                g_idle_add(ext_zoom_set,GINT_TO_POINTER(val));
-                break;
-	      default:
-		// no action for keys (should not come here anyway)
-		break;
-            }
-            break;
-	/////////////////////////////////////////////////////////// "ZOOMDOWN"
-	/////////////////////////////////////////////////////////// "ZOOMUP"
-        case ZOOM_MINUS:  // key
-        case ZOOM_PLUS:  // key
-	    switch (type) {
-	      case MIDI_KEY:
-		new =  (action == ZOOM_PLUS) ? 1 : -1;
-                g_idle_add(ext_zoom_update,GINT_TO_POINTER(new));
-		break;
-	      case MIDI_WHEEL:
-		new = (val > 0) ? 1 : -1;
-                g_idle_add(ext_zoom_update,GINT_TO_POINTER(new));
-		break;
-	      default:
-		// do nothing
-		// we should not come here anyway
-		break;
-	    }
-            break;
-
-	case NO_ACTION:
-	    // No error message, this is the "official" action for un-used controller buttons.
-	    break;
-	default:
-	    // This means we have forgotten to implement an action, so we inform on stderr.
-	    fprintf(stderr,"Unimplemented MIDI action: A=%d\n", (int) action);
-    }
-    */
 }
diff --git a/midi_menu.c b/midi_menu.c
index 20acaaf..0d29db8 100644
--- a/midi_menu.c
+++ b/midi_menu.c
@@ -99,13 +99,6 @@ enum {
   UPDATE_EXISTING
 };
 
-typedef struct _choice {
-  int action;
-  GtkWidget *initial_button;
-  GtkWidget *button;
-  gulong signal_id;
-} CHOICE;
-
 static int update(void *data);
 static void load_store();
 
diff --git a/new_protocol.c b/new_protocol.c
index 0f8bd7d..c7eed19 100644
--- a/new_protocol.c
+++ b/new_protocol.c
@@ -693,6 +693,8 @@ static void new_protocol_high_priority() {
           }
         }
 
+	rxFrequency+=calibration;
+
         phase=(long)((4294967296.0*(double)rxFrequency)/122880000.0);
         high_priority_buffer_to_radio[ 9]=phase>>24;
         high_priority_buffer_to_radio[10]=phase>>16;
@@ -724,6 +726,8 @@ static void new_protocol_high_priority() {
             }
           }
 
+	  rxFrequency+=calibration;
+
 	  phase=(long)((4294967296.0*(double)rxFrequency)/122880000.0);
 	  high_priority_buffer_to_radio[9+(ddc*4)]=phase>>24;
 	  high_priority_buffer_to_radio[10+(ddc*4)]=phase>>16;
@@ -750,6 +754,8 @@ static void new_protocol_high_priority() {
       }
     }
 
+    txFrequency+=calibration;
+
     phase=(long)((4294967296.0*(double)txFrequency)/122880000.0);
 
     if(isTransmitting() && transmitter->puresignal) {
diff --git a/old_protocol.c b/old_protocol.c
index 0dfa768..d8fb656 100644
--- a/old_protocol.c
+++ b/old_protocol.c
@@ -773,6 +773,7 @@ static long long channel_freq(int chan) {
       }
     }
   }
+  freq+=calibration;
   return freq;
 }
 
diff --git a/pulseaudio.c b/pulseaudio.c
index 2435907..d4197c9 100644
--- a/pulseaudio.c
+++ b/pulseaudio.c
@@ -323,7 +323,7 @@ float audio_get_next_mic_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__);
+    //g_print("%s: no samples\n",__FUNCTION__);
     sample=0.0;
   } else {
     // the "existence" of the ring buffer is now guaranteed for 1 msec,
diff --git a/radio.c b/radio.c
index d39d510..d8d5f49 100644
--- a/radio.c
+++ b/radio.c
@@ -114,6 +114,9 @@ static GtkWidget *panadapter;
 static GtkWidget *waterfall;
 static GtkWidget *audio_waterfall;
 
+// RX and TX calibration
+long long calibration=0LL;
+
 /*
 #ifdef GPIO
 static GtkWidget *encoders;
@@ -2072,8 +2075,11 @@ g_print("radioRestoreState: %s\n",property_path);
     value=getProperty("binaural");
     if(value) binaural=atoi(value);
 
+    value=getProperty("calibration");
+    if(value) calibration=atoll(value);
+
     value=getProperty("frequencyB");
-    if(value) frequencyB=atol(value);
+    if(value) frequencyB=atoll(value);
 
     value=getProperty("modeB");
     if(value) modeB=atoi(value);
@@ -2417,6 +2423,9 @@ g_print("radioSaveState: %s\n",property_path);
     sprintf(value,"%d",binaural);
     setProperty("binaural",value);
 
+    sprintf(value,"%lld",calibration);
+    setProperty("calibration",value);
+
     sprintf(value,"%lld",frequencyB);
     setProperty("frequencyB",value);
     sprintf(value,"%d",modeB);
diff --git a/radio.h b/radio.h
index de56307..6a7513f 100644
--- a/radio.h
+++ b/radio.h
@@ -63,6 +63,8 @@ extern gboolean radio_is_remote;
 
 extern GtkWidget *fixed;
 
+extern long long calibration;
+
 extern char property_path[];
 
 #define NONE 0
diff --git a/radio_menu.c b/radio_menu.c
index fbc3080..1a81b99 100644
--- a/radio_menu.c
+++ b/radio_menu.c
@@ -167,6 +167,10 @@ static void dac0_gain_value_changed_cb(GtkWidget *widget, gpointer data) {
 */
 #endif
 
+static void calibration_value_changed_cb(GtkWidget *widget, gpointer data) {
+  calibration=(long long)gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+}
+
 static void rx_gain_calibration_value_changed_cb(GtkWidget *widget, gpointer data) {
   rx_gain_calibration=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
 }
@@ -425,8 +429,10 @@ void radio_menu(GtkWidget *parent) {
   GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
 
   GtkWidget *grid=gtk_grid_new();
-  gtk_grid_set_column_spacing (GTK_GRID(grid),10);
+  gtk_grid_set_column_spacing (GTK_GRID(grid),5);
   gtk_grid_set_row_spacing (GTK_GRID(grid),5);
+  gtk_grid_set_column_homogeneous (GTK_GRID(grid), FALSE);
+  gtk_grid_set_row_homogeneous (GTK_GRID(grid), FALSE);
 
   int col=0;
   int row=0;
@@ -810,9 +816,20 @@ void radio_menu(GtkWidget *parent) {
   g_signal_connect(mute_rx_b,"toggled",G_CALLBACK(mute_rx_cb),NULL);
 
   row++;
+  col=0;
+ 
+  GtkWidget *calibration_label=gtk_label_new(NULL);
+  gtk_label_set_markup(GTK_LABEL(calibration_label), "<b>Frequency\nCalibration(Hz):</b>");
+  gtk_grid_attach(GTK_GRID(grid),calibration_label,col,row,1,1);
+  col++;
+
+  GtkWidget *calibration_b=gtk_spin_button_new_with_range(-10000.0,10000.0,1.0);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(calibration_b),(double)calibration);
+  gtk_grid_attach(GTK_GRID(grid),calibration_b,col,row,1,1);
+  g_signal_connect(calibration_b,"value_changed",G_CALLBACK(calibration_value_changed_cb),NULL);
 
   if(have_rx_gain) {
-    col=0;
+    col++;
     GtkWidget *rx_gain_label=gtk_label_new(NULL);
     gtk_label_set_markup(GTK_LABEL(rx_gain_label), "<b>RX Gain Calibration:</b>");
     gtk_grid_attach(GTK_GRID(grid),rx_gain_label,col,row,1,1);
@@ -823,8 +840,8 @@ void radio_menu(GtkWidget *parent) {
     gtk_grid_attach(GTK_GRID(grid),rx_gain_calibration_b,col,row,1,1);
     g_signal_connect(rx_gain_calibration_b,"value_changed",G_CALLBACK(rx_gain_calibration_value_changed_cb),NULL);
 
-    row++;
   }
+  row++;
 
   if(row>temp_row) temp_row=row;
 
diff --git a/switch_menu.c b/switch_menu.c
index 16d479e..94bee0d 100644
--- a/switch_menu.c
+++ b/switch_menu.c
@@ -38,14 +38,6 @@
 #include "gpio.h"
 #include "i2c.h"
 
-typedef struct _choice {
-  int sw;
-  int action;
-  GtkWidget *initial_button;
-  GtkWidget *button;
-  gulong signal_id;
-} CHOICE;
-
 static GtkWidget *parent_window=NULL;
 
 static GtkWidget *dialog=NULL;
diff --git a/toolbar_menu.c b/toolbar_menu.c
index 0297e36..4dd2cc5 100644
--- a/toolbar_menu.c
+++ b/toolbar_menu.c
@@ -39,14 +39,6 @@
 #include "gpio.h"
 #include "i2c.h"
 
-typedef struct _choice {
-  int sw;
-  int action;
-  GtkWidget *initial_button;
-  GtkWidget *button;
-  gulong signal_id;
-} CHOICE;
-
 static GtkWidget *parent_window=NULL;
 
 static GtkWidget *dialog=NULL;
@@ -135,7 +127,6 @@ next_function_set:
     } else {
       widget=gtk_button_new_with_label(ActionTable[temp_switches[i].switch_function].str);
       g_signal_connect(widget,"button-press-event",G_CALLBACK(switch_cb),GINT_TO_POINTER(i));
-g_print("%s: %d\n",__FUNCTION__,i);
     }
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
     col++;
diff --git a/vfo.c b/vfo.c
index 5fe726c..07ddf0b 100644
--- a/vfo.c
+++ b/vfo.c
@@ -1301,6 +1301,7 @@ void vfo_rit_update(int rx) {
 
 void vfo_rit_clear(int rx) {
   vfo[receiver[rx]->id].rit=0;
+  vfo[receiver[rx]->id].rit_enabled=0;
   receiver_frequency_changed(receiver[rx]);
   g_idle_add(ext_vfo_update, NULL);
 }
@@ -1313,7 +1314,8 @@ void vfo_rit(int rx,int i) {
   } else if(value>10000.0) {
     value=10000.0;
   }
-  vfo[receiver[rx]->id].rit=(int)value;
+  vfo[receiver[rx]->id].rit=value;
+  vfo[receiver[rx]->id].rit_enabled=(value!=0);
   receiver_frequency_changed(receiver[rx]);
   g_idle_add(ext_vfo_update,NULL);
 }
-- 
2.45.2