From 259dfa46d882c011a8194c48d3ca1b5c092e2333 Mon Sep 17 00:00:00 2001
From: John Melton G0ORX <john.d.melton@googlemail.com>
Date: Thu, 17 Jun 2021 15:41:46 +0100
Subject: [PATCH] Bulk changes to gpiod branch

---
 actions.c         | 1743 +++++++++++++++++++++++++++------------------
 actions.h         |  190 +++--
 alsa_midi.c       |    2 +
 encoder_menu.c    |   68 +-
 gpio.c            |   56 +-
 i2c.c             |    6 +-
 iambic.c          |    1 +
 midi.h            |   20 +-
 midi2.c           |  185 +++--
 midi3.c           |  276 ++++---
 midi_menu.c       |   71 +-
 radio.c           |    2 -
 receiver.c        |   32 +-
 rx_menu.c         |    6 +-
 sliders.c         |   22 +-
 sliders.h         |   30 +-
 soapy_discovery.c |   34 +-
 switch_menu.c     |   73 +-
 toolbar.c         |   44 +-
 zoompan.c         |    1 +
 20 files changed, 1646 insertions(+), 1216 deletions(-)

diff --git a/actions.c b/actions.c
index 4614b72..9d17398 100644
--- a/actions.c
+++ b/actions.c
@@ -29,175 +29,162 @@
 #include "actions.h"
 #include "gpio.h"
 #include "toolbar.h"
+#ifdef LOCALCW
+#include "iambic.h"
+#endif
 
-char *encoder_string[ENCODER_ACTIONS] = {
-  "NO ACTION",
-  "AF GAIN",
-  "AF GAIN RX1",
-  "AF GAIN RX2",
-  "AGC GAIN",
-  "AGC GAIN RX1",
-  "AGC GAIN RX2",
-  "ATTENUATION",
-  "COMP",
-  "CW FREQUENCY",
-  "CW SPEED",
-  "DIVERSITY GAIN",
-  "DIVERSITY GAIN (coarse)",
-  "DIVERSITY GAIN (fine)",
-  "DIVERSITY PHASE",
-  "DIVERSITY PHASE (coarse)",
-  "DIVERSITY PHASE (fine)",
-  "DRIVE",
-  "IF SHIFT",
-  "IF SHIFT RX1",
-  "IF SHIFT RX2",
-  "IF WIDTH",
-  "IF WIDTH RX1",
-  "IF WIDTH RX2",
-  "MIC GAIN",
-  "PAN",
-  "PANADAPTER HIGH",
-  "PANADAPTER LOW",
-  "PANADAPTER STEP",
-  "RF GAIN",
-  "RF GAIN RX1",
-  "RF GAIN RX2",
-  "RIT",
-  "RIT RX1",
-  "RIT RX2",
-  "SQUELCH",
-  "SQUELCH RX1",
-  "SQUELCH RX2",
-  "TUNE DRIVE",
-  "VFO",
-  "WATERFALL HIGH",
-  "WATERFALL LOW",
-  "XIT",
-  "ZOOM"
-};
-
-char *sw_string[SWITCH_ACTIONS] = {
-  "",
-  "A TO B",
-  "A SWAP B",
-  "AGC +",
-  "ANF",
-  "B TO A",
-  "BAND -",
-  "BAND +",
-  "BSTACK -",
-  "BSTACK +",
-  "CTUN",
-  "DIV",
-  "DUPLEX",
-  "FILTER -",
-  "FILTER +",
-  "FUNCT",
-  "LOCK",
-  "AGC",
-  "BAND",
-  "BSTACK",
-  "DIV",
-  "FILTER",
-  "FREQUENCY",
-  "MEMORY",
-  "MODE",
-  "NOISE",
-  "PS",
-  "MODE -",
-  "MODE +",
-  "MOX",
-  "MUTE",
-  "NB",
-  "NR",
-  "PAN -",
-  "PAN +",
-  "PS",
-  "RIT",
-  "RIT CL",
-  "RIT -",
-  "RIT +",
-  "RSAT",
-  "SAT",
-  "SNB",
-  "SPLIT",
-  "TUN",
-  "TUNE FULL",
-  "TUNE MEM",
-  "TWO TONE",
-  "VFOSTEP +",
-  "VFOSTEP -",
-  "XIT",
-  "XIT CL",
-  "XIT -",
-  "XIT +",
-  "ZOOM -",
-  "ZOOM +"
-};
-
-char *sw_cap_string[SWITCH_ACTIONS] = {
-  "",
-  "A>B",
-  "A<>B",
-  "AGC",
-  "ANF",
-  "B>A",
-  "BAND -",
-  "BAND +",
-  "BST-",
-  "BST+",
-  "CTUN",
-  "DIV",
-  "DUP",
-  "FILT -",
-  "FILT +",
-  "FUNC",
-  "LOCK",
-  "AGC",
-  "BAND",
-  "BSTACK",
-  "DIV",
-  "FILTER",
-  "FREQ",
-  "MEM",
-  "MODE",
-  "NOISE",
-  "PS",
-  "MODE -",
-  "MODE +",
-  "MOX",
-  "MUTE",
-  "NB",
-  "NR",
-  "PAN-",
-  "PAN+",
-  "PS",
-  "RIT",
-  "RIT CL",
-  "RIT -",
-  "RIT +",
-  "RSAT",
-  "SAT",
-  "SNB",
-  "SPLIT",
-  "TUNE",
-  "TUN-F",
-  "TUN-M",
-  "2TONE",
-  "STEP+",
-  "STEP-",
-  "XIT",
-  "XIT CL",
-  "XIT -",
-  "XIT +",
-  "ZOOM-",
-  "ZOOM+",
+ACTION_TABLE ActionTable[] = {
+  {NO_ACTION,		"NONE",			NULL,		TYPE_NONE},
+  {A_SWAP_B,		"A<>B",			"A<>B",		MIDI_KEY | CONTROLLER_SWITCH},
+  {A_TO_B,		"A>B",			"A>B",		MIDI_KEY | CONTROLLER_SWITCH},
+  {AF_GAIN,		"AF GAIN",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {AF_GAIN_RX1,		"AF GAIN\nRX1",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {AF_GAIN_RX2,		"AF GAIN\nRX2",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {AGC,			"AGC",			"AGC",		MIDI_KEY | CONTROLLER_SWITCH},
+  {AGC_GAIN,		"AGC GAIN",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {AGC_GAIN_RX1,	"AGC GAIN\nRX1",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {AGC_GAIN_RX2,	"AGC GAIN\nRX2",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {ANF,			"ANF",			"ANF",		MIDI_KEY | CONTROLLER_SWITCH},
+  {ATTENUATION,		"ATTEN",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {B_TO_A,		"A<B",			"A<B",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_10,		"BAND 10",		"10",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_12,		"BAND 12",		"12",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_1240,		"BAND 1240",		"1240",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_144,		"BAND 144",		"144",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_15,		"BAND 15",		"15",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_160,		"BAND 160",		"160",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_17,		"BAND 17",		"17",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_20,		"BAND 20",		"20",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_220,		"BAND 220",		"220",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_2300,		"BAND 2300",		"2300",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_30,		"BAND 30",		"30",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_3400,		"BAND 3400",		"3400",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_40,		"BAND 40",		"40",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_430,		"BAND 430",		"430",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_6,		"BAND 6",		"6",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_60,		"BAND 60",		"60",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_70,		"BAND 70",		"70",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_80,		"BAND 80",		"80",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_902,		"BAND 902",		"902",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_AIR,		"BAND AIR",		"AIR",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_GEN,		"BAND GEN",		"GEN",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_MINUS,		"BAND -",		"BND+",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_PLUS,		"BAND +",		"BND-",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BAND_WWV,		"BAND WWV",		"WWV",		MIDI_KEY | CONTROLLER_SWITCH},
+  {BANDSTACK_MINUS,	"BANDSTACK -",		"BSTK-",	MIDI_KEY | CONTROLLER_SWITCH},
+  {BANDSTACK_PLUS,	"BANDSTACK +",		"BSTK+",	MIDI_KEY | CONTROLLER_SWITCH},
+  {COMP_ENABLE,		"COMP ON/OFF",		"COMP",		MIDI_KEY | CONTROLLER_SWITCH},
+  {COMPRESSION,		"COMPRESSION",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {CTUN,		"CTUN",			"CTUN",		MIDI_KEY | CONTROLLER_SWITCH},
+  {CW_FREQUENCY,	"CW FREQUENCY",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {CW_LEFT,		"CW LEFT",		"CWL",		MIDI_KEY | CONTROLLER_SWITCH},
+  {CW_RIGHT,		"CW RIGHT",		"CWR",		MIDI_KEY | CONTROLLER_SWITCH},
+  {CW_SPEED,		"CW SPEED",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {DIV,			"DIV ON/OFF",		"DIV",		MIDI_KEY | CONTROLLER_SWITCH},
+  {DIV_GAIN,		"DIV GAIN",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {DIV_GAIN_COARSE,	"DIV GAIN\nCOARSE",	NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {DIV_GAIN_FINE,	"DIV GAIN\nFINE",	NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {DIV_PHASE,		"DIV PHASE",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {DIV_PHASE_COARSE,	"DIV PHASE\nCOARSE",	NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {DIV_PHASE_FINE,	"DIV PHASE\nFINE",	NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {DRIVE,		"TX DRIVE",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {DUPLEX,		"DUPLEX",		"DUP",		MIDI_KEY | CONTROLLER_SWITCH},
+  {FILTER_MINUS,	"FILTER +",		"FL+",		MIDI_KEY | CONTROLLER_SWITCH},
+  {FILTER_PLUS,		"FILTER -",		"FL-",		MIDI_KEY | CONTROLLER_SWITCH},
+  {FUNCTION,		"FUNC",		"FUNC",		CONTROLLER_SWITCH},
+  {IF_SHIFT,		"IF SHIFT",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {IF_SHIFT_RX1,	"IF SHIFT\nRX1",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {IF_SHIFT_RX2,	"IF SHIFT\nRX2",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {IF_WIDTH,		"IF WIDTH",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {IF_WIDTH_RX1,	"IF WIDTH\nRX1",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {IF_WIDTH_RX2,	"IF WIDTH\nRX2",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {LINEIN_GAIN,		"LINEIN\nGAIN",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {LOCK,		"LOCK",			"LOCK",		MIDI_KEY | CONTROLLER_SWITCH},
+  {MENU_AGC,		"AGC\nMENU",		"AGC",		MIDI_KEY | CONTROLLER_SWITCH},
+  {MENU_BAND,		"BAND\nMENU",		"BAND",		MIDI_KEY | CONTROLLER_SWITCH},
+  {MENU_BANDSTACK,	"BSTCK\nMENU",	"BSTK",		MIDI_KEY | CONTROLLER_SWITCH},
+  {MENU_DIVERSITY,	"DIV\nMENU",	"DIV",		MIDI_KEY | CONTROLLER_SWITCH},
+  {MENU_FILTER,		"FILT\nMENU",		"FILT",		MIDI_KEY | CONTROLLER_SWITCH},
+  {MENU_FREQUENCY,	"FREQ\nMENU",	"FREQ",		MIDI_KEY | CONTROLLER_SWITCH},
+  {MENU_MEMORY,		"MEMORY\nMENU",		"MEM",		MIDI_KEY | CONTROLLER_SWITCH},
+  {MENU_MODE,		"MODE\nMENU",		"MODE",		MIDI_KEY | CONTROLLER_SWITCH},
+  {MENU_NOISE,		"NOISE\nMENU",		"NOISE",	MIDI_KEY | CONTROLLER_SWITCH},
+  {MENU_PS,		"PS MENU",		"PS",		MIDI_KEY | CONTROLLER_SWITCH},
+  {MIC_GAIN,		"MIC GAIN",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {MODE_MINUS,		"MODE +",		"MOD+",		MIDI_KEY | CONTROLLER_SWITCH},
+  {MODE_PLUS,		"MODE -",		"MOD-",		MIDI_KEY | CONTROLLER_SWITCH},
+  {MOX,			"MOX",			"MOX",		MIDI_KEY | CONTROLLER_SWITCH},
+  {MUTE,		"MUTE",			"MUTE",		MIDI_KEY | CONTROLLER_SWITCH},
+  {NB,			"NB",			"NB",		MIDI_KEY | CONTROLLER_SWITCH},
+  {NR,			"NR",			"NR",		MIDI_KEY | CONTROLLER_SWITCH},
+  {NUMPAD_0,		"NUMPAD\n0",		"0",		MIDI_KEY | CONTROLLER_SWITCH},
+  {NUMPAD_1,		"NUMPAD\n1",		"1",		MIDI_KEY | CONTROLLER_SWITCH},
+  {NUMPAD_2,		"NUMPAD\n2",		"2",		MIDI_KEY | CONTROLLER_SWITCH},
+  {NUMPAD_3,		"NUMPAD\n3",		"3",		MIDI_KEY | CONTROLLER_SWITCH},
+  {NUMPAD_4,		"NUMPAD\n4",		"4",		MIDI_KEY | CONTROLLER_SWITCH},
+  {NUMPAD_5,		"NUMPAD\n5",		"5",		MIDI_KEY | CONTROLLER_SWITCH},
+  {NUMPAD_6,		"NUMPAD\n6",		"6",		MIDI_KEY | CONTROLLER_SWITCH},
+  {NUMPAD_7,		"NUMPAD\n7",		"7",		MIDI_KEY | CONTROLLER_SWITCH},
+  {NUMPAD_8,		"NUMPAD\n8",		"8",		MIDI_KEY | CONTROLLER_SWITCH},
+  {NUMPAD_9,		"NUMPAD\n9",		"9",		MIDI_KEY | CONTROLLER_SWITCH},
+  {NUMPAD_CL,		"NUMPAD\nCL",		"CL",		MIDI_KEY | CONTROLLER_SWITCH},
+  {NUMPAD_ENTER,	"NUMPAD\nENTER",		"EN",		MIDI_KEY | CONTROLLER_SWITCH},
+  {PAN,			"PAN",			NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {PAN_MINUS,		"PAN -",		"PAN-",		MIDI_KEY | CONTROLLER_SWITCH},
+  {PAN_PLUS,		"PAN +",		"PAN+",		MIDI_KEY | CONTROLLER_SWITCH},
+  {PANADAPTER_HIGH,	"PAN HIGH",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {PANADAPTER_LOW,	"PAN LOW",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {PANADAPTER_STEP,	"PAN STEP",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {PREAMP,		"PREAMP\nON/OFF",	"PRE",		MIDI_KEY | CONTROLLER_SWITCH},
+  {PS,			"PS ON/OFF",		"PS",		MIDI_KEY | CONTROLLER_SWITCH},
+  {PTT,			"PTT",			"PTT",		MIDI_KEY | CONTROLLER_SWITCH},
+  {RF_GAIN,		"RF GAIN",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {RF_GAIN_RX1,		"RF GAIN\nRX1",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {RF_GAIN_RX2,		"RF GAIN\nRX2",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {RIT,			"RIT",			NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {RIT_CLEAR,		"RIT\nCLEAR",		"RITCL",	MIDI_KEY | CONTROLLER_SWITCH},
+  {RIT_ENABLE,		"RIT\nON/OFF",		"RIT",		MIDI_KEY | CONTROLLER_SWITCH},
+  {RIT_MINUS,		"RIT +",		"RIT-",		MIDI_KEY | CONTROLLER_SWITCH},
+  {RIT_PLUS,		"RIT -",		"RIT+",		MIDI_KEY | CONTROLLER_SWITCH},
+  {RIT_RX1,		"RIT\nRX1",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {RIT_RX2,		"RIT\nRX2",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {RIT_STEP,		"RIT\nSTEP",		"RITST",	MIDI_KEY | CONTROLLER_SWITCH},
+  {RSAT,		"RSAT",			"RSAT",		MIDI_KEY | CONTROLLER_SWITCH},
+  {SAT,			"SAT",			"SAT",		MIDI_KEY | CONTROLLER_SWITCH},
+  {SNB,			"SNB",			"SNB",		MIDI_KEY | CONTROLLER_SWITCH},
+  {SPLIT,		"SPLIT",		"SPLIT",	MIDI_KEY | CONTROLLER_SWITCH},
+  {SQUELCH,		"SQUELCH",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {SQUELCH_RX1,		"SQUELCH\nRX1",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {SQUELCH_RX2,		"SQUELCH\nRX1",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {SWAP_RX,		"SWAP RX",		"SWAPRX",	MIDI_KEY | CONTROLLER_SWITCH},
+  {TUNE,		"TUNE",			"TUNE",		MIDI_KEY | CONTROLLER_SWITCH},
+  {TUNE_DRIVE,		"TUNE\nDRIVE",		NULL,		MIDI_KNOB | MIDI_WHEEL | CONTROLLER_ENCODER},
+  {TUNE_FULL,		"TUNE\nFULL",		"TUNF",		MIDI_KEY | CONTROLLER_SWITCH},
+  {TUNE_MEMORY,		"TUNE\nMEMORY",		"TUNM",		MIDI_KEY | CONTROLLER_SWITCH},
+  {TWO_TONE,		"TWO TONE",		"2TONE",	MIDI_KEY | CONTROLLER_SWITCH},
+  {VFO,			"VFO",			NULL,		MIDI_WHEEL | CONTROLLER_ENCODER},
+  {VFO_STEP_MINUS,	"VFO STEP -",		"STEP-",	MIDI_KEY | CONTROLLER_SWITCH},
+  {VFO_STEP_PLUS,	"VFO STEP +",		"STEP+",	MIDI_KEY | CONTROLLER_SWITCH},
+  {VFOA,		"VFO A",		NULL,		MIDI_WHEEL | CONTROLLER_ENCODER},
+  {VFOB,		"VFO B",		NULL,		MIDI_WHEEL | CONTROLLER_ENCODER},
+  {VOX,			"VOX\nON/OFF",		"VOX",		MIDI_KEY | CONTROLLER_SWITCH},
+  {VOXLEVEL,		"VOX\nLEVEL",		NULL,		MIDI_WHEEL | CONTROLLER_ENCODER},
+  {WATERFALL_HIGH,	"WATERFALL\nHIGH",	NULL,		MIDI_WHEEL | CONTROLLER_ENCODER},
+  {WATERFALL_LOW,	"WATERFALL\nLOW",	NULL,		MIDI_WHEEL | CONTROLLER_ENCODER},
+  {XIT	,		"XIT",			NULL,		MIDI_WHEEL | CONTROLLER_ENCODER},
+  {XIT_CLEAR,		"XIT\nCLEAR",		"XITCL",	MIDI_KEY | CONTROLLER_SWITCH},
+  {XIT_ENABLE,		"XIT\nON/OFF",		"XIT",		MIDI_KEY | CONTROLLER_SWITCH},
+  {XIT_MINUS,		"XIT -",		"XIT-",		MIDI_KEY | CONTROLLER_SWITCH},
+  {XIT_PLUS,		"XIT +",		"XIT+",		MIDI_KEY | CONTROLLER_SWITCH},
+  {ZOOM,		"ZOOM",			NULL,		MIDI_WHEEL | CONTROLLER_ENCODER},
+  {ZOOM_MINUS,		"ZOOM -",		"ZOOM-",	MIDI_KEY | CONTROLLER_SWITCH},
+  {ZOOM_PLUS,		"ZOOM +",		"ZOOM+",	MIDI_KEY | CONTROLLER_SWITCH},
+  {ACTIONS,		"",			NULL,		TYPE_NONE}
 };
 
 
-int encoder_action(void *data) {
-  ENCODER_ACTION *a=(ENCODER_ACTION *)data;
+int process_action(void *data) {
+  PROCESS_ACTION *a=(PROCESS_ACTION *)data;
   double value;
   int mode;
   int id;
@@ -205,14 +192,31 @@ int encoder_action(void *data) {
   FILTER *band_filter;
   FILTER *filter;
   int new_val;
+  int i;
 
+  //g_print("%s: action=%d mode=%d value=%d\n",__FUNCTION__,a->action,a->mode,a->val);
   switch(a->action) {
-    case ENCODER_VFO:
-      vfo_step(a->val);
+
+    case A_SWAP_B:
+      if(a->mode==PRESSED) {
+        vfo_a_swap_b();
+      }
+      break;
+    case A_TO_B:
+      if(a->mode==PRESSED) {
+        vfo_a_to_b();
+      }
       break;
-    case ENCODER_AF_GAIN:
+    case AF_GAIN:
       value=active_receiver->volume;
-      value+=a->val/100.0;
+      switch(a->mode) {
+	case RELATIVE:
+          value+=a->val/100.0;
+	  break;
+	case ABSOLUTE:
+	  value=a->val/100.0;
+	  break;
+      }
       if(value<0.0) {
         value=0.0;
       } else if(value>1.0) {
@@ -220,7 +224,7 @@ int encoder_action(void *data) {
       }
       set_af_gain(active_receiver->id,value);
       break;
-    case ENCODER_AF_GAIN_RX1:
+    case AF_GAIN_RX1:
       value=receiver[0]->volume;
       value+=a->val/100.0;
       if(value<0.0) {
@@ -230,7 +234,7 @@ int encoder_action(void *data) {
       }
       set_af_gain(0,value);
       break;
-    case ENCODER_AF_GAIN_RX2:
+    case AF_GAIN_RX2:
       value=receiver[1]->volume;
       value+=a->val/100.0;
       if(value<0.0) {
@@ -240,40 +244,17 @@ int encoder_action(void *data) {
       }
       set_af_gain(1,value);
       break;
-    case ENCODER_RF_GAIN:
-      //value=active_receiver->gain;
-      value=adc[active_receiver->id].gain;
-      value+=a->val;
-      if(value<0.0) {
-        value=0.0;
-      } else if(value>100.0) {
-        value=100.0;
-      }
-      set_rf_gain(active_receiver->id,value);
-      break;
-    case ENCODER_RF_GAIN_RX1:
-      //value=receiver[0]->rf_gain;
-      value=adc[receiver[0]->id].gain;
-      value+=a->val;
-      if(value<0.0) {
-        value=0.0;
-      } else if(value>100.0) {
-        value=100.0;
-      }
-      set_rf_gain(0,value);
-      break;
-    case ENCODER_RF_GAIN_RX2:
-      //value=receiver[1]->rf_gain;
-      value=adc[receiver[1]->id].gain;
-      value+=a->val;
-      if(value<0.0) {
-        value=0.0;
-      } else if(value>71.0) {
-        value=71.0;
+    case AGC:
+      if(a->mode==PRESSED) {
+        active_receiver->agc++;
+        if(active_receiver->agc>+AGC_LAST) {
+          active_receiver->agc=0;
+        }
+        set_agc(active_receiver, active_receiver->agc);
+        g_idle_add(ext_vfo_update, NULL);
       }
-      set_rf_gain(1,value);
       break;
-    case ENCODER_AGC_GAIN:
+    case AGC_GAIN:
       value=active_receiver->agc_gain;
       value+=a->val;
       if(value<-20.0) {
@@ -283,7 +264,7 @@ int encoder_action(void *data) {
       }
       set_agc_gain(active_receiver->id,value);
       break;
-    case ENCODER_AGC_GAIN_RX1:
+    case AGC_GAIN_RX1:
       value=receiver[0]->agc_gain;
       value+=a->val;
       if(value<-20.0) {
@@ -293,7 +274,7 @@ int encoder_action(void *data) {
       }
       set_agc_gain(0,value);
       break;
-    case ENCODER_AGC_GAIN_RX2:
+    case AGC_GAIN_RX2:
       value=receiver[1]->agc_gain;
       value+=a->val;
       if(value<-20.0) {
@@ -303,25 +284,20 @@ int encoder_action(void *data) {
       }
       set_agc_gain(1,value);
       break;
-    case ENCODER_IF_WIDTH:
-      filter_width_changed(active_receiver->id,a->val);
-      break;
-    case ENCODER_IF_WIDTH_RX1:
-      filter_width_changed(0,a->val);
-      break;
-    case ENCODER_IF_WIDTH_RX2:
-      filter_width_changed(1,a->val);
-      break;
-    case ENCODER_IF_SHIFT:
-      filter_shift_changed(active_receiver->id,a->val);
-      break;
-    case ENCODER_IF_SHIFT_RX1:
-      filter_shift_changed(0,a->val);
-      break;
-    case ENCODER_IF_SHIFT_RX2:
-      filter_shift_changed(1,a->val);
+    case ANF:
+      if(a->mode==PRESSED) {
+        if(active_receiver->anf==0) {
+          active_receiver->anf=1;
+          mode_settings[vfo[active_receiver->id].mode].anf=1;
+        } else {
+          active_receiver->anf=0;
+          mode_settings[vfo[active_receiver->id].mode].anf=0;
+        }
+        SetRXAANFRun(active_receiver->id, active_receiver->anf);
+        g_idle_add(ext_vfo_update, NULL);
+      }
       break;
-    case ENCODER_ATTENUATION:
+    case ATTENUATION:
       value=(double)adc[active_receiver->adc].attenuation;
       value+=(double)a->val;
       if(have_rx_gain) {
@@ -339,213 +315,455 @@ int encoder_action(void *data) {
       }
       set_attenuation_value(value);
       break;
-    case ENCODER_MIC_GAIN:
-      value=mic_gain;
-      value+=(double)a->val;
-      if(value<-12.0) {
-        value=-12.0;
-      } else if(value>50.0) {
-        value=50.0;
+    case B_TO_A:
+      if(a->mode==PRESSED) {
+        vfo_b_to_a();
       }
-      set_mic_gain(value);
       break;
-    case ENCODER_DRIVE:
-      value=getDrive();
-      value+=(double)a->val;
-      if(value<0.0) {
-        value=0.0;
-      } else if(value>drive_max) {
-        value=drive_max;
+    case BAND_10:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band160);
       }
-      set_drive(value);
       break;
-    case ENCODER_RIT:
-      vfo_rit(active_receiver->id,a->val);
+    case BAND_12:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band12);
+      }
       break;
-    case ENCODER_RIT_RX1:
-      vfo_rit(receiver[0]->id,a->val);
+#ifdef SOAPYSDR
+    case BAND_1240:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band1240);
+      }
       break;
-    case ENCODER_RIT_RX2:
-      vfo_rit(receiver[1]->id,a->val);
+    case BAND_144:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band144);
+      }
       break;
-    case ENCODER_XIT:
-      value=(double)transmitter->xit;
-      value+=(double)(a->val*rit_increment);
-      if(value<-10000.0) {
-        value=-10000.0;
-      } else if(value>10000.0) {
-        value=10000.0;
+#endif
+    case BAND_15:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band15);
       }
-      transmitter->xit=(int)value;
-      if(protocol==NEW_PROTOCOL) {
-        schedule_high_priority();
+      break;
+    case BAND_160:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band160);
       }
-      g_idle_add(ext_vfo_update,NULL);
       break;
-    case ENCODER_CW_SPEED:
-      value=(double)cw_keyer_speed;
-      value+=(double)a->val;
-      if(value<1.0) {
-        value=1.0;
-      } else if(value>60.0) {
-        value=60.0;
+    case BAND_17:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band17);
       }
-      cw_keyer_speed=(int)value;
-      g_idle_add(ext_vfo_update,NULL);
       break;
-    case ENCODER_CW_FREQUENCY:
-      value=(double)cw_keyer_sidetone_frequency;
-      value+=(double)a->val;
-      if(value<0.0) {
-        value=0.0;
-      } else if(value>1000.0) {
-        value=1000.0;
+    case BAND_20:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band20);
       }
-      cw_keyer_sidetone_frequency=(int)value;
-      g_idle_add(ext_vfo_update,NULL);
       break;
-    case ENCODER_PANADAPTER_HIGH:
-      value=(double)active_receiver->panadapter_high;
-      value+=(double)a->val;
-      active_receiver->panadapter_high=(int)value;
+#ifdef SOAPYSDR
+    case BAND_220:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band220);
+      }
       break;
-    case ENCODER_PANADAPTER_LOW:
-      value=(double)active_receiver->panadapter_low;
-      value+=(double)a->val;
-      active_receiver->panadapter_low=(int)value;
+    case BAND_2300:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band2300);
+      }
       break;
-    case ENCODER_PANADAPTER_STEP:
-      value=(double)active_receiver->panadapter_step;
-      value+=(double)a->val;
-      active_receiver->panadapter_step=(int)value;
+#endif
+    case BAND_30:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band30);
+      }
       break;
-    case ENCODER_WATERFALL_HIGH:
-      value=(double)active_receiver->waterfall_high;
-      value+=(double)a->val;
-      active_receiver->waterfall_high=(int)value;
+#ifdef SOAPYSDR
+    case BAND_3400:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band3400);
+      }
       break;
-    case ENCODER_WATERFALL_LOW:
-      value=(double)active_receiver->waterfall_low;
-      value+=(double)a->val;
-      active_receiver->waterfall_low=(int)value;
+#endif
+    case BAND_40:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band40);
+      }
       break;
-    case ENCODER_SQUELCH:
-      value=active_receiver->squelch;
-      value+=(double)a->val;
-      if(value<0.0) {
-        value=0.0;
-      } else if(value>100.0) {
-        value=100.0;
+#ifdef SOAPYSDR
+    case BAND_430:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band430);
       }
-      active_receiver->squelch=value;
-      set_squelch(active_receiver);
       break;
-    case ENCODER_SQUELCH_RX1:
-      value=receiver[0]->squelch;
-      value+=(double)a->val;
-      if(value<0.0) {
-        value=0.0;
-      } else if(value>100.0) {
-        value=100.0;
+#endif
+    case BAND_6:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band6);
       }
-      receiver[0]->squelch=value;
-      set_squelch(receiver[0]);
       break;
-    case ENCODER_SQUELCH_RX2:
-      value=receiver[1]->squelch;
-      value+=(double)a->val;
-      if(value<0.0) {
-        value=0.0;
-      } else if(value>100.0) {
-        value=100.0;
+    case BAND_60:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band60);
       }
-      receiver[1]->squelch=value;
-      set_squelch(receiver[1]);
       break;
-    case ENCODER_COMP:
-      value=(double)transmitter->compressor_level;
-      value+=(double)a->val;
-      if(value<0.0) {
-        value=0.0;
-      } else if(value>20.0) {
-        value=20.0;
+#ifdef SOAPYSDR
+    case BAND_70:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band70);
       }
-      transmitter->compressor_level=(int)value;
-      set_compression(transmitter);
       break;
-    case ENCODER_DIVERSITY_GAIN:
-      update_diversity_gain((double)a->val * 0.5);
+#endif
+    case BAND_80:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band80);
+      }
       break;
-    case ENCODER_DIVERSITY_GAIN_COARSE:
-      update_diversity_gain((double)a->val * 2.5);
+#ifdef SOAPYSDR
+    case BAND_902:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,band902);
+      }
       break;
-    case ENCODER_DIVERSITY_GAIN_FINE:
-      update_diversity_gain((double)a->val * 0.1);
+    case BAND_AIR:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,bandAIR);
+      }
       break;
-    case ENCODER_DIVERSITY_PHASE:
-      update_diversity_phase((double)a->val* 0.5);
+#endif
+    case BAND_GEN:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,bandGen);
+      }
       break;
-    case ENCODER_DIVERSITY_PHASE_COARSE:
-      update_diversity_phase((double)a->val*2.5);
+    case BAND_MINUS:
+      if(a->mode==PRESSED) {
+        long long frequency_min=radio->frequency_min;
+        long long frequency_max=radio->frequency_max;
+        int b=vfo[active_receiver->id].band;
+        BAND *band;
+        int found=0;
+        while(!found) {
+          b--;
+          if(b<0) b=BANDS+XVTRS-1;
+          band=(BAND*)band_get_band(b);
+          if(strlen(band->title)>0) {
+            if(b<BANDS) {
+              if(band->frequencyMin<frequency_min || band->frequencyMax>frequency_max) {
+                continue;
+              }
+            }
+            vfo_band_changed(active_receiver->id,b);
+            found=1;
+          }
+        }
+      }
       break;
-    case ENCODER_DIVERSITY_PHASE_FINE:
-      update_diversity_phase((double)a->val*0.1);
+    case BAND_PLUS:
+      if(a->mode==PRESSED) {
+        long long frequency_min=radio->frequency_min;
+        long long frequency_max=radio->frequency_max;
+        int b=vfo[active_receiver->id].band;
+        BAND *band;
+        int found=0;
+        while(!found) {
+          b++;
+          if(b>=BANDS+XVTRS) b=0;
+          band=(BAND*)band_get_band(b);
+          if(strlen(band->title)>0) {
+            if(b<BANDS) {
+              if(!(band->frequencyMin==0.0 && band->frequencyMax==0.0)) {
+                if(band->frequencyMin<frequency_min || band->frequencyMax>frequency_max) {
+                  continue;
+                }
+              }
+            }
+            vfo_band_changed(active_receiver->id,b);
+            found=1;
+          }
+        }
+      }
       break;
-    case ENCODER_ZOOM:
-      update_zoom((double)a->val);
+    case BAND_WWV:
+      if(a->mode==PRESSED) {
+        vfo_band_changed(active_receiver->id,bandWWV);
+      }
       break;
-    case ENCODER_PAN:
-      update_pan((double)a->val*100);
+    case BANDSTACK_MINUS:
+      if(a->mode==PRESSED) {
+        BAND *band=band_get_band(vfo[active_receiver->id].band);
+        BANDSTACK *bandstack=band->bandstack;
+        int b=vfo[active_receiver->id].bandstack-1;
+        if(b<0) b=bandstack->entries-1;;
+        vfo_bandstack_changed(b);
+      }
       break;
-  }
-  g_free(data);
-  return 0;
-}
-
-int switch_action(void *data) {
-  int i;
-  SWITCH_ACTION *a=(SWITCH_ACTION *)data;
-  if(a->state==PRESSED) {
-    switch(a->action) {
-      case FUNCTION:
-	switch(controller) {
-          case NO_CONTROLLER:
-          case CONTROLLER1:
-            function++;
-            if(function>=MAX_FUNCTIONS) {
-              function=0;
-            }
-            toolbar_switches=switches_controller1[function];
-            switches=switches_controller1[function];
-            update_toolbar_labels();
-	    break;
-	  case CONTROLLER2_V1:
-	  case CONTROLLER2_V2:
-            function++;
-            if(function>=MAX_FUNCTIONS) {
-              function=0;
-            }
-            toolbar_switches=switches_controller1[function];
-            update_toolbar_labels();
-	    break;
+    case BANDSTACK_PLUS:
+      if(a->mode==PRESSED) {
+        BAND *band=band_get_band(vfo[active_receiver->id].band);
+        BANDSTACK *bandstack=band->bandstack;
+        int b=vfo[active_receiver->id].bandstack+1;
+        if(b>=bandstack->entries) b=0;
+        vfo_bandstack_changed(b);
+      }
+      break;
+    case COMP_ENABLE:
+      if(can_transmit) {
+        transmitter_set_compressor(transmitter,transmitter->compressor?FALSE:TRUE);
+      }
+      break;
+    case COMPRESSION:
+      if(can_transmit) {
+        value=transmitter->compressor_level;
+        value+=a->val;
+        if(value<0.0) {
+          value=0.0;
+        } else if(value>20.0) {
+          value=20.0;
         }
-        break;
-      case TUNE:
-	if(getMox()==1) {
-          setMox(0);
+	transmitter_set_compressor_level(transmitter,value);
+      }
+      break;
+    case CTUN:
+      if(a->mode==PRESSED) {
+        vfo[active_receiver->id].ctun=!vfo[active_receiver->id].ctun;
+        if(!vfo[active_receiver->id].ctun) {
+          vfo[active_receiver->id].offset=0;
         }
-        if(getTune()==0) {
-          if(canTransmit() || tx_out_of_band) {
-            setTune(1);
-          } else {
-            transmitter_set_out_of_band(transmitter);
-          }
-        } else {
-          setTune(0);
+        vfo[active_receiver->id].ctun_frequency=vfo[active_receiver->id].frequency;
+        set_offset(receiver[active_receiver->id],vfo[active_receiver->id].offset);
+        g_idle_add(ext_vfo_update, NULL);
+      }
+      break;
+    case CW_FREQUENCY:
+#ifdef LOCALCW
+      value=(double)cw_keyer_sidetone_frequency;
+      value+=(double)a->val;
+      if(value<0.0) {
+        value=0.0;
+      } else if(value>1000.0) {
+        value=1000.0;
+      }
+      cw_keyer_sidetone_frequency=(int)value;
+      g_idle_add(ext_vfo_update,NULL);
+#endif
+      break;
+    case CW_LEFT:
+    case CW_RIGHT:
+      if(a->mode==PRESSED || a->mode==RELEASED) {
+#ifdef LOCALCW
+        keyer_event(a->action==CW_LEFT,a->mode==PRESSED);
+#endif
+      }
+      break;
+    case CW_SPEED:
+#ifdef LOCALCW
+      value=(double)cw_keyer_speed;
+      value+=(double)a->val;
+      if(value<1.0) {
+        value=1.0;
+      } else if(value>60.0) {
+        value=60.0;
+      }
+      cw_keyer_speed=(int)value;
+      g_idle_add(ext_vfo_update,NULL);
+#endif
+      break;
+    case DIV:
+      if(a->mode==PRESSED) {
+        diversity_enabled=diversity_enabled==1?0:1;
+        if (protocol == NEW_PROTOCOL) {
+          schedule_high_priority();
+          schedule_receive_specific();
         }
-        g_idle_add(ext_vfo_update,NULL);
-        break;
-      case MOX:
+        g_idle_add(ext_vfo_update, NULL);
+      }
+      break;
+    case DIV_GAIN:
+      update_diversity_gain((double)a->val * 0.5);
+      break;
+    case DIV_GAIN_COARSE:
+      update_diversity_gain((double)a->val * 2.5);
+      break;
+    case DIV_GAIN_FINE:
+      update_diversity_gain((double)a->val * 0.1);
+      break;
+    case DIV_PHASE:
+      update_diversity_phase((double)a->val* 0.5);
+      break;
+    case DIV_PHASE_COARSE:
+      update_diversity_phase((double)a->val*2.5);
+      break;
+    case DIV_PHASE_FINE:
+      update_diversity_phase((double)a->val*0.1);
+      break;
+    case DRIVE:
+      value=getDrive();
+      value+=(double)a->val;
+      if(value<0.0) {
+        value=0.0;
+      } else if(value>drive_max) {
+        value=drive_max;
+      }
+      set_drive(value);
+      break;
+    case DUPLEX:
+      if(can_transmit && !isTransmitting()) {
+        duplex=duplex==1?0:1;
+        g_idle_add(ext_set_duplex, NULL);
+      }
+      break;
+    case FILTER_MINUS:
+      if(a->mode==PRESSED) {
+        int f=vfo[active_receiver->id].filter+1;
+        if(f>=FILTERS) f=0;
+        vfo_filter_changed(f);
+      }
+      break;
+    case FILTER_PLUS:
+      if(a->mode==PRESSED) {
+        int f=vfo[active_receiver->id].filter-1;
+        if(f<0) f=FILTERS-1;
+        vfo_filter_changed(f);
+      }
+      break;
+    case FUNCTION:
+      switch(controller) {
+        case NO_CONTROLLER:
+        case CONTROLLER1:
+          function++;
+          if(function>=MAX_FUNCTIONS) {
+            function=0;
+          }
+          toolbar_switches=switches_controller1[function];
+          switches=switches_controller1[function];
+          update_toolbar_labels();
+	  break;
+	case CONTROLLER2_V1:
+	case CONTROLLER2_V2:
+          function++;
+          if(function>=MAX_FUNCTIONS) {
+            function=0;
+          }
+          toolbar_switches=switches_controller1[function];
+          update_toolbar_labels();
+	  break;
+      }
+      break;
+    case IF_SHIFT:
+      filter_shift_changed(active_receiver->id,a->val);
+      break;
+    case IF_SHIFT_RX1:
+      filter_shift_changed(0,a->val);
+      break;
+    case IF_SHIFT_RX2:
+      filter_shift_changed(1,a->val);
+      break;
+    case IF_WIDTH:
+      filter_width_changed(active_receiver->id,a->val);
+      break;
+    case IF_WIDTH_RX1:
+      filter_width_changed(0,a->val);
+      break;
+    case IF_WIDTH_RX2:
+      filter_width_changed(1,a->val);
+      break;
+    //case LINEIN_GAIN:
+    case LOCK:
+      if(a->mode==PRESSED) {
+#ifdef CLIENT_SERVER
+        if(radio_is_remote) {
+          send_lock(client_socket,locked==1?0:1);
+        } else {
+#endif
+          locked=locked==1?0:1;
+          g_idle_add(ext_vfo_update, NULL);
+#ifdef CLIENT_SERVER
+        }
+#endif
+      }
+      break;
+    case MENU_AGC:
+      if(a->mode==PRESSED) {
+        start_agc();
+      }
+      break;
+    case MENU_BAND:
+      if(a->mode==PRESSED) {
+        start_band();
+      }
+      break;
+    case MENU_BANDSTACK:
+      if(a->mode==PRESSED) {
+        start_bandstack();
+      }
+      break;
+    case MENU_DIVERSITY:
+      if(a->mode==PRESSED) {
+        start_diversity();
+      }
+      break;
+    case MENU_FILTER:
+      if(a->mode==PRESSED) {
+        start_filter();
+      }
+      break;
+    case MENU_FREQUENCY:
+      if(a->mode==PRESSED) {
+        start_vfo(active_receiver->id);
+      }
+      break;
+    case MENU_MEMORY:
+      if(a->mode==PRESSED) {
+        start_store();
+      }
+      break;
+    case MENU_MODE:
+      if(a->mode==PRESSED) {
+        start_mode();
+      }
+      break;
+    case MENU_NOISE:
+      if(a->mode==PRESSED) {
+        start_noise();
+      }
+      break;
+#ifdef PURESIGNAL
+    case MENU_PS:
+      if(a->mode==PRESSED) {
+        start_ps();
+      }
+      break;
+#endif
+    case MIC_GAIN:
+      value=mic_gain;
+      value+=(double)a->val;
+      if(value<-12.0) {
+        value=-12.0;
+      } else if(value>50.0) {
+        value=50.0;
+      }
+      set_mic_gain(value);
+      break;
+    case MODE_MINUS:
+      if(a->mode==PRESSED) {
+        int mode=vfo[active_receiver->id].mode;
+        mode--;
+        if(mode<0) mode=MODES-1;
+        vfo_mode_changed(mode);
+      }
+      break;
+    case MODE_PLUS:
+      if(a->mode==PRESSED) {
+        int mode=vfo[active_receiver->id].mode;
+        mode++;
+        if(mode>=MODES) mode=0;
+        vfo_mode_changed(mode);
+      }
+      break;
+    case MOX:
+      if(a->mode==PRESSED) {
         if(getTune()==1) {
           setTune(0);
         }
@@ -559,105 +777,436 @@ int switch_action(void *data) {
           setMox(0);
         }
         g_idle_add(ext_vfo_update,NULL);
-        break;
-      case PS:
+      }
+      break;
+    case MUTE:
+      if(a->mode==PRESSED) {
+        active_receiver->mute_radio=!active_receiver->mute_radio;
+      }
+      break;
+    case NB:
+      if(a->mode==PRESSED) {
+        if(active_receiver->nb==0 && active_receiver->nb2==0) {
+          active_receiver->nb=1;
+          active_receiver->nb2=0;
+          mode_settings[vfo[active_receiver->id].mode].nb=1;
+          mode_settings[vfo[active_receiver->id].mode].nb2=0;
+        } else if(active_receiver->nb==1 && active_receiver->nb2==0) {
+          active_receiver->nb=0;
+          active_receiver->nb2=1;
+          mode_settings[vfo[active_receiver->id].mode].nb=0;
+          mode_settings[vfo[active_receiver->id].mode].nb2=1;
+        } else if(active_receiver->nb==0 && active_receiver->nb2==1) {
+          active_receiver->nb=0;
+          active_receiver->nb2=0;
+          mode_settings[vfo[active_receiver->id].mode].nb=0;
+          mode_settings[vfo[active_receiver->id].mode].nb2=0;
+        }
+        update_noise();
+      }
+      break;
+    case NR:
+      if(a->mode==PRESSED) {
+        if(active_receiver->nr==0 && active_receiver->nr2==0) {
+          active_receiver->nr=1;
+          active_receiver->nr2=0;
+          mode_settings[vfo[active_receiver->id].mode].nr=1;
+          mode_settings[vfo[active_receiver->id].mode].nr2=0;
+        } else if(active_receiver->nr==1 && active_receiver->nr2==0) {
+          active_receiver->nr=0;
+          active_receiver->nr2=1;
+          mode_settings[vfo[active_receiver->id].mode].nr=0;
+          mode_settings[vfo[active_receiver->id].mode].nr2=1;
+        } else if(active_receiver->nr==0 && active_receiver->nr2==1) {
+          active_receiver->nr=0;
+          active_receiver->nr2=0;
+          mode_settings[vfo[active_receiver->id].mode].nr=0;
+          mode_settings[vfo[active_receiver->id].mode].nr2=0;
+        }
+        update_noise();
+      }
+      break;
+    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;
+    case PAN:
+      update_pan((double)a->val*100);
+      break;
+    case PAN_MINUS:
+      if(a->mode==PRESSED) {
+        update_pan(-100.0);
+      }
+      break;
+    case PAN_PLUS:
+       if(a->mode==PRESSED) {
+         update_pan(+100.0);
+       }
+       break;
+    case PANADAPTER_HIGH:
+      value=(double)active_receiver->panadapter_high;
+      value+=(double)a->val;
+      active_receiver->panadapter_high=(int)value;
+      break;
+    case PANADAPTER_LOW:
+      value=(double)active_receiver->panadapter_low;
+      value+=(double)a->val;
+      active_receiver->panadapter_low=(int)value;
+      break;
+    case PANADAPTER_STEP:
+      value=(double)active_receiver->panadapter_step;
+      value+=(double)a->val;
+      active_receiver->panadapter_step=(int)value;
+      break;
+    case PREAMP:
+    case PS:
 #ifdef PURESIGNAL
+      if(a->mode==PRESSED) {
         if(can_transmit) {
           if(transmitter->puresignal==0) {
             tx_set_ps(transmitter,1);
           } else {
-            tx_set_ps(transmitter,0);
+            tx_set_ps(transmitter,0);
+          }
+        }
+      }
+#endif
+      break;
+    case PTT:
+      if(a->mode==PRESSED || a->mode==RELEASED) {
+	mox_update(a->mode==PRESSED);
+      }
+      break;
+    case RF_GAIN:
+      value=adc[active_receiver->id].gain;
+      value+=a->val;
+      if(value<0.0) {
+        value=0.0;
+      } else if(value>100.0) {
+        value=100.0;
+      }
+      set_rf_gain(active_receiver->id,value);
+      break;
+    case RF_GAIN_RX1:
+      value=adc[receiver[0]->id].gain;
+      value+=a->val;
+      if(value<0.0) {
+        value=0.0;
+      } else if(value>100.0) {
+        value=100.0;
+      }
+      set_rf_gain(0,value);
+      break;
+    case RF_GAIN_RX2:
+      value=adc[receiver[1]->id].gain;
+      value+=a->val;
+      if(value<0.0) {
+        value=0.0;
+      } else if(value>71.0) {
+        value=71.0;
+      }
+      set_rf_gain(1,value);
+      break;
+    case RIT:
+      vfo_rit(active_receiver->id,a->val);
+      break;
+    case RIT_CLEAR:
+      if(a->mode==PRESSED) {
+        vfo_rit_clear(active_receiver->id);
+      }
+      break;
+    case RIT_ENABLE:
+      if(a->mode==PRESSED) {
+        vfo_rit_update(active_receiver->id);
+      }
+      break;
+    case RIT_MINUS:
+      if(a->mode==PRESSED) {
+        vfo_rit(active_receiver->id,-1);
+      }
+      break;
+    case RIT_PLUS:
+      if(a->mode==PRESSED) {
+        vfo_rit(active_receiver->id,1);
+      }
+      break;
+    case RIT_RX1:
+      vfo_rit(receiver[0]->id,a->val);
+      break;
+    case RIT_RX2:
+      vfo_rit(receiver[1]->id,a->val);
+      break;
+    case RIT_STEP:
+      switch(a->mode) {
+        case PRESSED:
+	  a->val=1;
+	  // fall through
+	case RELATIVE:
+	  if(a->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;
+      }
+      g_idle_add(ext_vfo_update,NULL);
+      break;
+    case RSAT:
+      if(a->mode==PRESSED) {
+        sat_mode=RSAT_MODE;
+        g_idle_add(ext_vfo_update, NULL);
+      }
+      break;
+    case SAT:
+      if(a->mode==PRESSED) {
+        sat_mode=SAT_MODE;
+        g_idle_add(ext_vfo_update, NULL);
+      }
+      break;
+    case SNB:
+      if(a->mode==PRESSED) {
+        if(active_receiver->snb==0) {
+          active_receiver->snb=1;
+          mode_settings[vfo[active_receiver->id].mode].snb=1;
+        } else {
+          active_receiver->snb=0;
+        mode_settings[vfo[active_receiver->id].mode].snb=0;
+        }
+        update_noise();
+      }
+      break;
+    case SPLIT:
+      if(a->mode==PRESSED) {
+        if(can_transmit) {
+          split=split==1?0:1;
+          tx_set_mode(transmitter,get_tx_mode());
+          g_idle_add(ext_vfo_update, NULL);
+        }
+      }
+      break;
+    case SQUELCH:
+      value=active_receiver->squelch;
+      value+=(double)a->val;
+      if(value<0.0) {
+        value=0.0;
+      } else if(value>100.0) {
+        value=100.0;
+      }
+      active_receiver->squelch=value;
+      set_squelch(active_receiver);
+      break;
+    case SQUELCH_RX1:
+      value=receiver[0]->squelch;
+      value+=(double)a->val;
+      if(value<0.0) {
+        value=0.0;
+      } else if(value>100.0) {
+        value=100.0;
+      }
+      receiver[0]->squelch=value;
+      set_squelch(receiver[0]);
+      break;
+    case SQUELCH_RX2:
+      value=receiver[1]->squelch;
+      value+=(double)a->val;
+      if(value<0.0) {
+        value=0.0;
+      } else if(value>100.0) {
+        value=100.0;
+      }
+      receiver[1]->squelch=value;
+      set_squelch(receiver[1]);
+      break;
+    case SWAP_RX:
+      if(a->mode==PRESSED) {
+        if(receivers==2) {
+          active_receiver=receiver[active_receiver->id==1?0:1];
+          g_idle_add(menu_active_receiver_changed,NULL);
+          g_idle_add(ext_vfo_update,NULL);
+          g_idle_add(sliders_active_receiver_changed,NULL);
+        }
+      }
+      break;
+    case TUNE:
+      if(a->mode==PRESSED) {
+        if(getMox()==1) {
+          setMox(0);
+        }
+        if(getTune()==0) {
+          if(canTransmit() || tx_out_of_band) {
+            setTune(1);
+          } else {
+            transmitter_set_out_of_band(transmitter);
           }
+        } else {
+          setTune(0);
         }
-#endif
-        break;
-      case TWO_TONE:
+        g_idle_add(ext_vfo_update,NULL);
+      }
+      break;
+    case TUNE_DRIVE:
+      if(can_transmit) {
+        switch(a->mode) {
+          case RELATIVE:
+            if(a->val>0) {
+              transmitter->tune_percent=transmitter->tune_percent+1;
+	    }
+            if(a->val<0) {
+              transmitter->tune_percent=transmitter->tune_percent-1;
+	    }
+	    if(transmitter->tune_percent<0) transmitter->tune_percent=0;
+	    if(transmitter->tune_percent>100) transmitter->tune_percent=100;
+            break;
+          case ABSOLUTE:
+	    transmitter->tune_percent=(int)a->val;
+	    if(transmitter->tune_percent<0) transmitter->tune_percent=0;
+	    if(transmitter->tune_percent>100) transmitter->tune_percent=100;
+            break;
+        }
+      }
+      break;
+    case TUNE_FULL:
+      if(a->mode==PRESSED) {
+        if(can_transmit) {
+	  full_tune=full_tune?FALSE:TRUE;
+	  memory_tune=FALSE;
+	}
+      }
+      break;
+    case TUNE_MEMORY:
+      if(a->mode==PRESSED) {
+        if(can_transmit) {
+	  memory_tune=memory_tune?FALSE:TRUE;
+	  full_tune=FALSE;
+	}
+      }
+      break;
+    case TWO_TONE:
+      if(a->mode==PRESSED) {
         if(can_transmit) {
           int state=transmitter->twotone?0:1;
           tx_set_twotone(transmitter,state);
         }
-        break;
-      case VFOSTEP_PLUS:
+      }
+      break;
+    case VFO:
+      vfo_step(a->val);
+      break;
+    case VFO_STEP_MINUS:
+      if(a->mode==PRESSED) {
         for(i=0;i<STEPS;i++) {
           if(steps[i]==step) break;
         }
         if(i>=STEPS) i=0;
-	i++;
-	if(i>=STEPS) i=0;
+        i--;
+        if(i<0) i=STEPS-1;
         step=steps[i];
         g_idle_add(ext_vfo_update, NULL);
-	break;
-      case VFOSTEP_MINUS:
+      }
+      break;
+    case VFO_STEP_PLUS:
+      if(a->mode==PRESSED) {
         for(i=0;i<STEPS;i++) {
           if(steps[i]==step) break;
         }
         if(i>=STEPS) i=0;
-	i--;
-	if(i<0) i=STEPS-1;
+        i++;
+        if(i>=STEPS) i=0;
         step=steps[i];
         g_idle_add(ext_vfo_update, NULL);
-	break;
-      case NR:
-        if(active_receiver->nr==0 && active_receiver->nr2==0) {
-          active_receiver->nr=1;
-          active_receiver->nr2=0;
-          mode_settings[vfo[active_receiver->id].mode].nr=1;
-          mode_settings[vfo[active_receiver->id].mode].nr2=0;
-        } else if(active_receiver->nr==1 && active_receiver->nr2==0) {
-          active_receiver->nr=0;
-          active_receiver->nr2=1;
-          mode_settings[vfo[active_receiver->id].mode].nr=0;
-          mode_settings[vfo[active_receiver->id].mode].nr2=1;
-        } else if(active_receiver->nr==0 && active_receiver->nr2==1) {
-          active_receiver->nr=0;
-          active_receiver->nr2=0;
-          mode_settings[vfo[active_receiver->id].mode].nr=0;
-          mode_settings[vfo[active_receiver->id].mode].nr2=0;
-        }
-        update_noise();
-        break;
-      case NB:
-        if(active_receiver->nb==0 && active_receiver->nb2==0) {
-          active_receiver->nb=1;
-          active_receiver->nb2=0;
-          mode_settings[vfo[active_receiver->id].mode].nb=1;
-          mode_settings[vfo[active_receiver->id].mode].nb2=0;
-        } else if(active_receiver->nb==1 && active_receiver->nb2==0) {
-          active_receiver->nb=0;
-          active_receiver->nb2=1;
-          mode_settings[vfo[active_receiver->id].mode].nb=0;
-          mode_settings[vfo[active_receiver->id].mode].nb2=1;
-        } else if(active_receiver->nb==0 && active_receiver->nb2==1) {
-          active_receiver->nb=0;
-          active_receiver->nb2=0;
-          mode_settings[vfo[active_receiver->id].mode].nb=0;
-          mode_settings[vfo[active_receiver->id].mode].nb2=0;
-        }
-        update_noise();
-        break;
-      case SNB:
-        if(active_receiver->snb==0) {
-          active_receiver->snb=1;
-          mode_settings[vfo[active_receiver->id].mode].snb=1;
-        } else {
-          active_receiver->snb=0;
-          mode_settings[vfo[active_receiver->id].mode].snb=0;
+      }
+      break;
+    case VFOA:
+      if(a->mode==RELATIVE && !locked) {
+	vfo_id_step(0,(int)a->val);
+      }
+      break;
+    case VFOB:
+      if(a->mode==RELATIVE && !locked) {
+	vfo_id_step(1,(int)a->val);
+      }
+      break;
+    case VOX:
+      vox_enabled = !vox_enabled;
+      g_idle_add(ext_vfo_update, NULL);
+      break;
+    case VOXLEVEL:
+      if(a->mode==ABSOLUTE) {
+	vox_threshold = 0.01 * a->val;
+      } else if(a->mode==RELATIVE) {
+        vox_threshold += a->val * 0.01;
+        if (vox_threshold > 1.0) vox_threshold=1.0;
+        if (vox_threshold < 0.0) vox_threshold=0.0;
+      }
+      break;
+    case WATERFALL_HIGH:
+      value=(double)active_receiver->waterfall_high;
+      value+=(double)a->val;
+      active_receiver->waterfall_high=(int)value;
+      break;
+    case WATERFALL_LOW:
+      value=(double)active_receiver->waterfall_low;
+      value+=(double)a->val;
+      active_receiver->waterfall_low=(int)value;
+      break;
+    case XIT:
+      value=(double)transmitter->xit;
+      value+=(double)(a->val*rit_increment);
+      if(value<-10000.0) {
+        value=-10000.0;
+      } else if(value>10000.0) {
+        value=10000.0;
+      }
+      transmitter->xit=(int)value;
+      if(protocol==NEW_PROTOCOL) {
+        schedule_high_priority();
+      }
+      g_idle_add(ext_vfo_update,NULL);
+      break;
+    case XIT_CLEAR:
+      if(a->mode==PRESSED) {
+        if(can_transmit) {
+          transmitter->xit=0;
+          g_idle_add(ext_vfo_update, NULL);
         }
-        update_noise();
-        break;
-      case RIT:
-        vfo_rit_update(active_receiver->id);
-        break;
-      case RIT_CLEAR:
-        vfo_rit_clear(active_receiver->id);
-        break;
-      case RIT_MINUS:
-	vfo_rit(active_receiver->id,-1);
-        break;
-      case RIT_PLUS:
-	vfo_rit(active_receiver->id,1);
-        break;
-      case XIT:
+      }
+      break;
+    case XIT_ENABLE:
+      if(a->mode==PRESSED) {
         if(can_transmit) {
           transmitter->xit_enabled=transmitter->xit_enabled==1?0:1;
           if(protocol==NEW_PROTOCOL) {
@@ -665,14 +1214,10 @@ int switch_action(void *data) {
           }
         }
         g_idle_add(ext_vfo_update, NULL);
-        break;
-      case XIT_CLEAR:
-        if(can_transmit) {
-          transmitter->xit=0;
-          g_idle_add(ext_vfo_update, NULL);
-        }
-        break;
-      case XIT_MINUS:
+      }
+      break;
+    case XIT_MINUS:
+      if(a->mode==PRESSED) {
         if(can_transmit) {
           double value=(double)transmitter->xit;
           value-=(double)rit_increment;
@@ -686,9 +1231,11 @@ int switch_action(void *data) {
             schedule_high_priority();
           }
           g_idle_add(ext_vfo_update,NULL);
-	}
-	break;
-      case XIT_PLUS:
+        }
+      }
+      break;
+    case XIT_PLUS:
+      if(a->mode==PRESSED) {
         if(can_transmit) {
           double value=(double)transmitter->xit;
           value+=(double)rit_increment;
@@ -703,227 +1250,29 @@ int switch_action(void *data) {
           }
           g_idle_add(ext_vfo_update,NULL);
         }
-        break;
-      case BAND_PLUS:
-        {
-        long long frequency_min=radio->frequency_min;
-        long long frequency_max=radio->frequency_max;
-        int b=vfo[active_receiver->id].band;
-        BAND *band;
-        int found=0;
-        while(!found) {
-          b++;
-          if(b>=BANDS+XVTRS) b=0;
-          band=(BAND*)band_get_band(b);
-          if(strlen(band->title)>0) {
-            if(b<BANDS) {
-              if(!(band->frequencyMin==0.0 && band->frequencyMax==0.0)) {
-                if(band->frequencyMin<frequency_min || band->frequencyMax>frequency_max) {
-                  continue;
-                }
-              }
-            }
-            vfo_band_changed(active_receiver->id,b);
-            found=1;
-          }
-        }
-        }
-        break;
-      case BAND_MINUS:
-        {
-        long long frequency_min=radio->frequency_min;
-        long long frequency_max=radio->frequency_max;
-        int b=vfo[active_receiver->id].band;
-        BAND *band;
-        int found=0;
-        while(!found) {
-          b--;
-          if(b<0) b=BANDS+XVTRS-1;
-          band=(BAND*)band_get_band(b);
-          if(strlen(band->title)>0) {
-            if(b<BANDS) {
-              if(band->frequencyMin<frequency_min || band->frequencyMax>frequency_max) {
-                continue;
-              }
-            }
-            vfo_band_changed(active_receiver->id,b);
-            found=1;
-          }
-        }
-        }
-        break;
-      case BANDSTACK_PLUS:
-        {
-        BAND *band=band_get_band(vfo[active_receiver->id].band);
-        BANDSTACK *bandstack=band->bandstack;
-        int b=vfo[active_receiver->id].bandstack+1;
-        if(b>=bandstack->entries) b=0;
-        vfo_bandstack_changed(b);
-        }
-        break;
-      case BANDSTACK_MINUS:
-        {
-        BAND *band=band_get_band(vfo[active_receiver->id].band);
-        BANDSTACK *bandstack=band->bandstack;
-        int b=vfo[active_receiver->id].bandstack-1;
-        if(b<0) b=bandstack->entries-1;;
-        vfo_bandstack_changed(b);
-        }
-        break;
-      case MODE_PLUS:
-        {
-        int mode=vfo[active_receiver->id].mode;
-        mode++;
-        if(mode>=MODES) mode=0;
-        vfo_mode_changed(mode);
-        }
-        break;
-      case MODE_MINUS:
-        {
-        int mode=vfo[active_receiver->id].mode;
-        mode--;
-        if(mode<0) mode=MODES-1;
-        vfo_mode_changed(mode);
-        }
-        break;
-      case FILTER_PLUS:
-        {
-        int f=vfo[active_receiver->id].filter-1;
-        if(f<0) f=FILTERS-1;
-        vfo_filter_changed(f);
-        }
-        break;
-      case FILTER_MINUS:
-        {
-        int f=vfo[active_receiver->id].filter+1;
-        if(f>=FILTERS) f=0;
-        vfo_filter_changed(f);
-        }
-        break;
-      case A_TO_B:
-        vfo_a_to_b();
-        break;
-      case B_TO_A:
-        vfo_b_to_a();
-        break;
-      case A_SWAP_B:
-        vfo_a_swap_b();
-        break;
-      case LOCK:
-#ifdef CLIENT_SERVER
-        if(radio_is_remote) {
-          send_lock(client_socket,locked==1?0:1);
-        } else {
-#endif
-          locked=locked==1?0:1;
-          g_idle_add(ext_vfo_update, NULL);
-#ifdef CLIENT_SERVER
-        }
-#endif
-        break;
-      case CTUN:
-        vfo[active_receiver->id].ctun=!vfo[active_receiver->id].ctun;
-        if(!vfo[active_receiver->id].ctun) {
-          vfo[active_receiver->id].offset=0;
-        }
-        vfo[active_receiver->id].ctun_frequency=vfo[active_receiver->id].frequency;
-        set_offset(receiver[active_receiver->id],vfo[active_receiver->id].offset);
-        g_idle_add(ext_vfo_update, NULL);
-        break;
-      case AGC:
-        active_receiver->agc++;
-        if(active_receiver->agc>+AGC_LAST) {
-          active_receiver->agc=0;
-        }
-        set_agc(active_receiver, active_receiver->agc);
-        g_idle_add(ext_vfo_update, NULL);
-        break;
-      case SPLIT:
-        if(can_transmit) {
-          split=split==1?0:1;
-          tx_set_mode(transmitter,get_tx_mode());
-          g_idle_add(ext_vfo_update, NULL);
-        }
-        break;
-      case DIVERSITY:
-        diversity_enabled=diversity_enabled==1?0:1;
-        if (protocol == NEW_PROTOCOL) {
-          schedule_high_priority();
-          schedule_receive_specific();
-        }
-        g_idle_add(ext_vfo_update, NULL);
-        break;
-      case SAT:
-        switch(sat_mode) {
-          case SAT_NONE:
-            sat_mode=SAT_MODE;
-            break;
-          case SAT_MODE:
-            sat_mode=RSAT_MODE;
-            break;
-          case RSAT_MODE:
-            sat_mode=SAT_NONE;
-            break;
-        }
-        g_idle_add(ext_vfo_update, NULL);
-        break;
-      case MENU_AGC:
-        start_agc();
-        break;
-      case MENU_BAND:
-        start_band();
-        break;
-      case MENU_BANDSTACK:
-        start_bandstack();
-        break;
-      case MENU_MODE:
-        start_mode();
-        break;
-      case MENU_NOISE:
-        start_noise();
-        break;
-      case MENU_FILTER:
-        start_filter();
-        break;
-      case MENU_FREQUENCY:
-        start_vfo(active_receiver->id);
-        break;
-      case MENU_MEMORY:
-        start_store();
-        break;
-      case MENU_DIVERSITY:
-        start_diversity();
-        break;
-#ifdef PURESIGNAL
-      case MENU_PS:
-        start_ps();
-        break;
-#endif
-      case MUTE:
-        active_receiver->mute_radio=!active_receiver->mute_radio;
-        break;
-      case PAN_MINUS:
-        update_pan(-100.0);
-        break;
-      case PAN_PLUS:
-        update_pan(+100.0);
-        break;
-      case ZOOM_MINUS:
+      }
+      break;
+    case ZOOM:
+      update_zoom((double)a->val);
+      break;
+    case ZOOM_MINUS:
+      if(a->mode==PRESSED) {
         update_zoom(-1);
-        break;
-      case ZOOM_PLUS:
+      }
+      break;
+    case ZOOM_PLUS:
+      if(a->mode==PRESSED) {
         update_zoom(+1);
-        break;
-      default:
-        g_print("%s: UNKNOWN PRESSED SWITCH ACTION %d\n",__FUNCTION__,a->action);
-        break;
-    }
-  } else if(a->state==RELEASED) {
-    // only switch functions that increment/decrement while pressed
-    switch(a->action) {
-      default:
-        break;
-    }
+      }
+      break;
+
+    default:
+      if(a->action>=0 && a->action<ACTIONS) {
+        g_print("%s: UNKNOWN PRESSED SWITCH ACTION %d (%s)\n",__FUNCTION__,a->action,ActionTable[a->action].str);
+      } else {
+        g_print("%s: INVALID PRESSED SWITCH ACTION %d\n",__FUNCTION__,a->action);
+      }
+      break;
   }
   g_free(data);
   return 0;
diff --git a/actions.h b/actions.h
index b48c5b3..13d18a4 100644
--- a/actions.h
+++ b/actions.h
@@ -1,69 +1,70 @@
 
-enum {
-  ENCODER_NO_ACTION=0,
-  ENCODER_AF_GAIN,
-  ENCODER_AF_GAIN_RX1,
-  ENCODER_AF_GAIN_RX2,
-  ENCODER_AGC_GAIN,
-  ENCODER_AGC_GAIN_RX1,
-  ENCODER_AGC_GAIN_RX2,
-  ENCODER_ATTENUATION,
-  ENCODER_COMP,
-  ENCODER_CW_FREQUENCY,
-  ENCODER_CW_SPEED,
-  ENCODER_DIVERSITY_GAIN,
-  ENCODER_DIVERSITY_GAIN_COARSE,
-  ENCODER_DIVERSITY_GAIN_FINE,
-  ENCODER_DIVERSITY_PHASE,
-  ENCODER_DIVERSITY_PHASE_COARSE,
-  ENCODER_DIVERSITY_PHASE_FINE,
-  ENCODER_DRIVE,
-  ENCODER_IF_SHIFT,
-  ENCODER_IF_SHIFT_RX1,
-  ENCODER_IF_SHIFT_RX2,
-  ENCODER_IF_WIDTH,
-  ENCODER_IF_WIDTH_RX1,
-  ENCODER_IF_WIDTH_RX2,
-  ENCODER_MIC_GAIN,
-  ENCODER_PAN,
-  ENCODER_PANADAPTER_HIGH,
-  ENCODER_PANADAPTER_LOW,
-  ENCODER_PANADAPTER_STEP,
-  ENCODER_RF_GAIN,
-  ENCODER_RF_GAIN_RX1,
-  ENCODER_RF_GAIN_RX2,
-  ENCODER_RIT,
-  ENCODER_RIT_RX1,
-  ENCODER_RIT_RX2,
-  ENCODER_SQUELCH,
-  ENCODER_SQUELCH_RX1,
-  ENCODER_SQUELCH_RX2,
-  ENCODER_TUNE_DRIVE,
-  ENCODER_VFO,
-  ENCODER_WATERFALL_HIGH,
-  ENCODER_WATERFALL_LOW,
-  ENCODER_XIT,
-  ENCODER_ZOOM,
-  ENCODER_ACTIONS
-};
-
-enum {
+enum ACTION {
   NO_ACTION=0,
-  A_TO_B,
   A_SWAP_B,
+  A_TO_B,
+  AF_GAIN,
+  AF_GAIN_RX1,
+  AF_GAIN_RX2,
   AGC,
+  AGC_GAIN,
+  AGC_GAIN_RX1,
+  AGC_GAIN_RX2,
   ANF,
+  ATTENUATION,
   B_TO_A,
+  BAND_10,
+  BAND_12,
+  BAND_1240,
+  BAND_144,
+  BAND_15,
+  BAND_160,
+  BAND_17,
+  BAND_20,
+  BAND_220,
+  BAND_2300,
+  BAND_30,
+  BAND_3400,
+  BAND_40,
+  BAND_430,
+  BAND_6,
+  BAND_60,
+  BAND_70,
+  BAND_80,
+  BAND_902,
+  BAND_AIR,
+  BAND_GEN,
   BAND_MINUS,
   BAND_PLUS,
+  BAND_WWV,
   BANDSTACK_MINUS,
   BANDSTACK_PLUS,
+  COMP_ENABLE,
+  COMPRESSION,
   CTUN,
-  DIVERSITY,
+  CW_FREQUENCY,
+  CW_LEFT,
+  CW_RIGHT,
+  CW_SPEED,
+  DIV,
+  DIV_GAIN,
+  DIV_GAIN_COARSE,
+  DIV_GAIN_FINE,
+  DIV_PHASE,
+  DIV_PHASE_COARSE,
+  DIV_PHASE_FINE,
+  DRIVE,
   DUPLEX,
   FILTER_MINUS,
   FILTER_PLUS,
   FUNCTION,
+  IF_SHIFT,
+  IF_SHIFT_RX1,
+  IF_SHIFT_RX2,
+  IF_WIDTH,
+  IF_WIDTH_RX1,
+  IF_WIDTH_RX2,
+  LINEIN_GAIN,
   LOCK,
   MENU_AGC,
   MENU_BAND,
@@ -75,63 +76,108 @@ enum {
   MENU_MODE,
   MENU_NOISE,
   MENU_PS,
+  MIC_GAIN,
   MODE_MINUS,
   MODE_PLUS,
   MOX,
   MUTE,
   NB,
   NR,
+  NUMPAD_0,
+  NUMPAD_1,
+  NUMPAD_2,
+  NUMPAD_3,
+  NUMPAD_4,
+  NUMPAD_5,
+  NUMPAD_6,
+  NUMPAD_7,
+  NUMPAD_8,
+  NUMPAD_9,
+  NUMPAD_CL,
+  NUMPAD_ENTER,
+  PAN,
   PAN_MINUS,
   PAN_PLUS,
+  PANADAPTER_HIGH,
+  PANADAPTER_LOW,
+  PANADAPTER_STEP,
+  PREAMP,
   PS,
+  PTT,
+  RF_GAIN,
+  RF_GAIN_RX1,
+  RF_GAIN_RX2,
   RIT,
   RIT_CLEAR,
+  RIT_ENABLE,
   RIT_MINUS,
   RIT_PLUS,
+  RIT_RX1,
+  RIT_RX2,
+  RIT_STEP,
   RSAT,
   SAT,
   SNB,
   SPLIT,
+  SQUELCH,
+  SQUELCH_RX1,
+  SQUELCH_RX2,
+  SWAP_RX,
   TUNE,
+  TUNE_DRIVE,
   TUNE_FULL,
   TUNE_MEMORY,
   TWO_TONE,
-  VFOSTEP_PLUS,
-  VFOSTEP_MINUS,
+  VFO,
+  VFO_STEP_MINUS,
+  VFO_STEP_PLUS,
+  VFOA,
+  VFOB,
+  VOX,
+  VOXLEVEL,
+  WATERFALL_HIGH,
+  WATERFALL_LOW,
   XIT,
   XIT_CLEAR,
+  XIT_ENABLE,
   XIT_MINUS,
   XIT_PLUS,
+  ZOOM,
   ZOOM_MINUS,
   ZOOM_PLUS,
-  SWITCH_ACTIONS,
+  ACTIONS
 };
 
-enum {
-  PRESSED,
-  RELEASED
+enum ACTIONtype {
+  TYPE_NONE=0,
+  MIDI_KEY=1,           // MIDI Button (press event)
+  MIDI_KNOB=2,          // MIDI Knob   (value between 0 and 100)
+  MIDI_WHEEL=4,         // MIDI Wheel  (direction and speed)
+  CONTROLLER_SWITCH=8,  // Controller Button
+  CONTROLLER_ENCODER=16 // Controller Encoder
 };
 
-typedef struct _switch_action {
-  gint action;
-  gboolean state;
-} SWITCH_ACTION;
+typedef struct _action_table {
+  enum ACTION action;
+  const char *str;		// desciptive text
+  const char *button_str;	// short button text
+  enum ACTIONtype type;
+} ACTION_TABLE;
 
-enum {
+enum ACTION_MODE {
   RELATIVE,
-  ABSOLUTE
+  ABSOLUTE,
+  PRESSED,
+  RELEASED
 };
 
-typedef struct _encoder_action {
-  gint action;
-  gboolean mode;
+typedef struct process_action {
+  enum ACTION action;
+  enum ACTION_MODE mode;
   gint val;
-} ENCODER_ACTION;
+} PROCESS_ACTION;
 
-extern char *encoder_string[ENCODER_ACTIONS];
-extern char *sw_string[SWITCH_ACTIONS];
-extern char *sw_cap_string[SWITCH_ACTIONS];
+extern ACTION_TABLE ActionTable[ACTIONS+1];
 
-extern int encoder_action(void *data);
-extern int switch_action(void *data);
+extern int process_action(void *data);
 
diff --git a/alsa_midi.c b/alsa_midi.c
index eb4d0af..9cae879 100644
--- a/alsa_midi.c
+++ b/alsa_midi.c
@@ -20,6 +20,7 @@
 
 #include <gtk/gtk.h>
 
+#include "actions.h"
 #include "midi.h"
 #include "midi_menu.h"
 #include "alsa_midi.h"
@@ -220,6 +221,7 @@ int register_midi_device(char *myname) {
         g_print("%s: Cannot find MIDI device: %s\n",__FUNCTION__,myname);
 	ret=-1;
     }
+    return ret;
 }
 
 void close_midi_device() {
diff --git a/encoder_menu.c b/encoder_menu.c
index 44876eb..aa8aa59 100644
--- a/encoder_menu.c
+++ b/encoder_menu.c
@@ -68,19 +68,19 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_d
 static void encoder_bottom_select_cb(GtkWidget *widget,gpointer data) {
   CHOICE *choice=(CHOICE *)data;
   encoders[choice->id].bottom_encoder_function=choice->action;
-  gtk_button_set_label(GTK_BUTTON(choice->button),encoder_string[choice->action]);
+  gtk_button_set_label(GTK_BUTTON(choice->button),ActionTable[choice->action].button_str);
 }
 
 static void encoder_top_select_cb(GtkWidget *widget,gpointer data) {
   CHOICE *choice=(CHOICE *)data;
   encoders[choice->id].top_encoder_function=choice->action;
-  gtk_button_set_label(GTK_BUTTON(choice->button),encoder_string[choice->action]);
+  gtk_button_set_label(GTK_BUTTON(choice->button),ActionTable[choice->action].button_str);
 }
 
 static void encoder_switch_select_cb(GtkWidget *widget,gpointer data) {
   CHOICE *choice=(CHOICE *)data;
   encoders[choice->id].switch_function=choice->action;
-  gtk_button_set_label(GTK_BUTTON(choice->button),sw_string[choice->action]);
+  gtk_button_set_label(GTK_BUTTON(choice->button),ActionTable[choice->action].button_str);
 }
 
 static gboolean encoder_bottom_cb(GtkWidget *widget, GdkEvent *event, gpointer data) {
@@ -88,14 +88,16 @@ static gboolean encoder_bottom_cb(GtkWidget *widget, GdkEvent *event, gpointer d
   int i;
 
   GtkWidget *menu=gtk_menu_new();
-  for(i=0;i<ENCODER_ACTIONS;i++) {
-    GtkWidget *menu_item=gtk_menu_item_new_with_label(encoder_string[i]);
-    CHOICE *choice=g_new0(CHOICE,1);
-    choice->id=encoder;
-    choice->action=i;
-    choice->button=widget;
-    g_signal_connect(menu_item,"activate",G_CALLBACK(encoder_bottom_select_cb),choice);
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
+  for(i=0;i<ACTIONS;i++) {
+    if(ActionTable[i].type|CONTROLLER_ENCODER) {
+      GtkWidget *menu_item=gtk_menu_item_new_with_label(ActionTable[i].str);
+      CHOICE *choice=g_new0(CHOICE,1);
+      choice->id=encoder;
+      choice->action=i;
+      choice->button=widget;
+      g_signal_connect(menu_item,"activate",G_CALLBACK(encoder_bottom_select_cb),choice);
+      gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
+    }
   }
   gtk_widget_show_all(menu);
 #if GTK_CHECK_VERSION(3,22,0)
@@ -113,14 +115,16 @@ static gboolean encoder_top_cb(GtkWidget *widget, GdkEvent *event, gpointer data
   int i;
 
   GtkWidget *menu=gtk_menu_new();
-  for(i=0;i<ENCODER_ACTIONS;i++) {
-    GtkWidget *menu_item=gtk_menu_item_new_with_label(encoder_string[i]);
-    CHOICE *choice=g_new0(CHOICE,1);
-    choice->id=encoder;
-    choice->action=i;
-    choice->button=widget;
-    g_signal_connect(menu_item,"activate",G_CALLBACK(encoder_top_select_cb),choice);
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
+  for(i=0;i<ACTIONS;i++) {
+    if(ActionTable[i].type|CONTROLLER_ENCODER) {
+      GtkWidget *menu_item=gtk_menu_item_new_with_label(ActionTable[i].str);
+      CHOICE *choice=g_new0(CHOICE,1);
+      choice->id=encoder;
+      choice->action=i;
+      choice->button=widget;
+      g_signal_connect(menu_item,"activate",G_CALLBACK(encoder_top_select_cb),choice);
+      gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
+    }
   }
   gtk_widget_show_all(menu);
 #if GTK_CHECK_VERSION(3,22,0)
@@ -138,14 +142,16 @@ static gboolean encoder_switch_cb(GtkWidget *widget, GdkEvent *event, gpointer d
   int i;
 
   GtkWidget *menu=gtk_menu_new();
-  for(i=0;i<SWITCH_ACTIONS;i++) {
-    GtkWidget *menu_item=gtk_menu_item_new_with_label(sw_string[i]);
-    CHOICE *choice=g_new0(CHOICE,1);
-    choice->id=encoder;
-    choice->action=i;
-    choice->button=widget;
-    g_signal_connect(menu_item,"activate",G_CALLBACK(encoder_switch_select_cb),choice);
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
+  for(i=0;i<ACTIONS;i++) {
+    if(ActionTable[i].type|CONTROLLER_SWITCH) {
+      GtkWidget *menu_item=gtk_menu_item_new_with_label(ActionTable[i].str);
+      CHOICE *choice=g_new0(CHOICE,1);
+      choice->id=encoder;
+      choice->action=i;
+      choice->button=widget;
+      g_signal_connect(menu_item,"activate",G_CALLBACK(encoder_switch_select_cb),choice);
+      gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
+    }
   }
   gtk_widget_show_all(menu);
 #if GTK_CHECK_VERSION(3,22,0)
@@ -233,24 +239,24 @@ void encoder_menu(GtkWidget *parent) {
 
     if(i==(max_encoders-1)) {
       widget=gtk_label_new(NULL);
-      g_sprintf(label,"<b>%s</b>",encoder_string[encoders[i].bottom_encoder_function]);
+      g_sprintf(label,"<b>%s</b>",ActionTable[encoders[i].bottom_encoder_function].str);
       gtk_label_set_markup (GTK_LABEL(widget), label);
     } else {
-      widget=gtk_button_new_with_label(encoder_string[encoders[i].bottom_encoder_function]);
+      widget=gtk_button_new_with_label(ActionTable[encoders[i].bottom_encoder_function].str);
       g_signal_connect(widget,"button_press_event",G_CALLBACK(encoder_bottom_cb),GINT_TO_POINTER(i));
     }
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
     col++;
 
     if(controller==CONTROLLER2_V2) {
-      widget=gtk_button_new_with_label(encoder_string[encoders[i].top_encoder_function]);
+      widget=gtk_button_new_with_label(ActionTable[encoders[i].top_encoder_function].str);
       g_signal_connect(widget,"button_press_event",G_CALLBACK(encoder_top_cb),GINT_TO_POINTER(i));
       gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
       col++;
     }
 
     if(i!=(max_encoders-1)) {
-      widget=gtk_button_new_with_label(sw_string[encoders[i].switch_function]);
+      widget=gtk_button_new_with_label(ActionTable[encoders[i].switch_function].str);
       g_signal_connect(widget,"button_press_event",G_CALLBACK(encoder_switch_cb),GINT_TO_POINTER(i));
       gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
       col++;
diff --git a/gpio.c b/gpio.c
index 139c647..9eab905 100644
--- a/gpio.c
+++ b/gpio.c
@@ -157,27 +157,27 @@ ENCODER encoders_no_controller[MAX_ENCODERS]={
   };
 
 ENCODER encoders_controller1[MAX_ENCODERS]={
-  {TRUE,TRUE,20,1,26,1,0,ENCODER_AF_GAIN,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,TRUE,TRUE,25,MENU_BAND,0L},
-  {TRUE,TRUE,16,1,19,1,0,ENCODER_AGC_GAIN,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,TRUE,TRUE,8,MENU_BANDSTACK,0L},
-  {TRUE,TRUE,4,1,21,1,0,ENCODER_DRIVE,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,TRUE,TRUE,7,MENU_MODE,0L},
-  {TRUE,TRUE,18,1,17,1,0,ENCODER_VFO,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,FALSE,TRUE,0,0,0L},
+  {TRUE,TRUE,20,1,26,1,0,AF_GAIN,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,TRUE,TRUE,25,MENU_BAND,0L},
+  {TRUE,TRUE,16,1,19,1,0,AGC_GAIN,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,TRUE,TRUE,8,MENU_BANDSTACK,0L},
+  {TRUE,TRUE,4,1,21,1,0,DRIVE,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,TRUE,TRUE,7,MENU_MODE,0L},
+  {TRUE,TRUE,18,1,17,1,0,VFO,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,FALSE,TRUE,0,0,0L},
   {FALSE,TRUE,0,1,0,0,1,0,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,FALSE,TRUE,0,0,0L},
   };
 
 ENCODER encoders_controller2_v1[MAX_ENCODERS]={
-  {TRUE,TRUE,20,1,26,1,0,ENCODER_AF_GAIN,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,TRUE,TRUE,22,MENU_BAND,0L},
-  {TRUE,TRUE,4,1,21,1,0,ENCODER_AGC_GAIN,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,TRUE,TRUE,27,MENU_BANDSTACK,0L},
-  {TRUE,TRUE,16,1,19,1,0,ENCODER_IF_WIDTH,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,TRUE,TRUE,23,MENU_MODE,0L},
-  {TRUE,TRUE,25,1,8,1,0,ENCODER_RIT,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,TRUE,TRUE,24,MENU_FREQUENCY,0L},
-  {TRUE,TRUE,18,1,17,1,0,ENCODER_VFO,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,FALSE,TRUE,0,0,0L},
+  {TRUE,TRUE,20,1,26,1,0,AF_GAIN,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,TRUE,TRUE,22,MENU_BAND,0L},
+  {TRUE,TRUE,4,1,21,1,0,AGC_GAIN,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,TRUE,TRUE,27,MENU_BANDSTACK,0L},
+  {TRUE,TRUE,16,1,19,1,0,IF_WIDTH,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,TRUE,TRUE,23,MENU_MODE,0L},
+  {TRUE,TRUE,25,1,8,1,0,RIT,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,TRUE,TRUE,24,MENU_FREQUENCY,0L},
+  {TRUE,TRUE,18,1,17,1,0,VFO,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,FALSE,TRUE,0,0,0L},
   };
 
 ENCODER encoders_controller2_v2[MAX_ENCODERS]={
-  {TRUE,TRUE,5,1,6,1,0,ENCODER_RF_GAIN,R_START,TRUE,TRUE,26,1,20,1,0,ENCODER_AF_GAIN,R_START,TRUE,TRUE,22,MENU_BAND,0L},
-  {TRUE,TRUE,9,1,7,1,0,ENCODER_ATTENUATION,R_START,TRUE,TRUE,21,1,4,1,0,ENCODER_AGC_GAIN,R_START,TRUE,TRUE,27,MENU_MODE,0L},
-  {TRUE,TRUE,11,1,10,1,0,ENCODER_IF_WIDTH,R_START,TRUE,TRUE,19,1,16,1,0,ENCODER_IF_SHIFT,R_START,TRUE,TRUE,23,MENU_FILTER,0L},
-  {TRUE,TRUE,13,1,12,1,0,ENCODER_XIT,R_START,TRUE,TRUE,8,1,25,1,0,ENCODER_RIT,R_START,TRUE,TRUE,24,MENU_FREQUENCY,0L},
-  {TRUE,TRUE,18,1,17,1,0,ENCODER_VFO,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,FALSE,TRUE,0,0,0L},
+  {TRUE,TRUE,5,1,6,1,0,RF_GAIN,R_START,TRUE,TRUE,26,1,20,1,0,AF_GAIN,R_START,TRUE,TRUE,22,MENU_BAND,0L},
+  {TRUE,TRUE,9,1,7,1,0,ATTENUATION,R_START,TRUE,TRUE,21,1,4,1,0,AGC_GAIN,R_START,TRUE,TRUE,27,MENU_MODE,0L},
+  {TRUE,TRUE,11,1,10,1,0,IF_WIDTH,R_START,TRUE,TRUE,19,1,16,1,0,IF_SHIFT,R_START,TRUE,TRUE,23,MENU_FILTER,0L},
+  {TRUE,TRUE,13,1,12,1,0,XIT,R_START,TRUE,TRUE,8,1,25,1,0,RIT,R_START,TRUE,TRUE,24,MENU_FREQUENCY,0L},
+  {TRUE,TRUE,18,1,17,1,0,VFO,R_START,FALSE,TRUE,0,0,0,0,0,0,R_START,FALSE,TRUE,0,0,0L},
   };
 
 ENCODER *encoders=encoders_no_controller;
@@ -207,8 +207,8 @@ SWITCH switches_controller1[MAX_FUNCTIONS][MAX_SWITCHES]={
    {TRUE,TRUE,12,MENU_BANDSTACK,0L},
    {TRUE,TRUE,6,MENU_MODE,0L},
    {TRUE,TRUE,5,MENU_FILTER,0L},
-   {TRUE,TRUE,24,NR,0L},
-   {TRUE,TRUE,23,AGC,0L},
+   {TRUE,TRUE,24,MENU_NOISE,0L},
+   {TRUE,TRUE,23,MENU_AGC,0L},
    {TRUE,TRUE,22,FUNCTION,0L},
    {FALSE,FALSE,0,NO_ACTION,0L},
    {FALSE,FALSE,0,NO_ACTION,0L},
@@ -363,7 +363,7 @@ static unsigned int millis () {
 }
 
 static gpointer rotary_encoder_thread(gpointer data) {
-  ENCODER_ACTION *a;
+  PROCESS_ACTION *a;
   int i;
 
   usleep(250000);
@@ -373,20 +373,20 @@ static gpointer rotary_encoder_thread(gpointer data) {
     for(i=0;i<MAX_ENCODERS;i++) {
       if(encoders[i].bottom_encoder_enabled && encoders[i].bottom_encoder_pos!=0) {
         //g_print("%s: BOTTOM encoder %d pos=%d\n",__FUNCTION__,i,encoders[i].bottom_encoder_pos);
-        a=g_new(ENCODER_ACTION,1);
+        a=g_new(PROCESS_ACTION,1);
         a->action=encoders[i].bottom_encoder_function;
         a->mode=RELATIVE;
         a->val=encoders[i].bottom_encoder_pos;
-        g_idle_add(encoder_action,a);
+        g_idle_add(process_action,a);
         encoders[i].bottom_encoder_pos=0;
       }
       if(encoders[i].top_encoder_enabled && encoders[i].top_encoder_pos!=0) {
         //g_print("%s: TOP encoder %d pos=%d\n",__FUNCTION__,i,encoders[i].top_encoder_pos);
-        a=g_new(ENCODER_ACTION,1);
+        a=g_new(PROCESS_ACTION,1);
         a->action=encoders[i].top_encoder_function;
         a->mode=RELATIVE;
         a->val=encoders[i].top_encoder_pos;
-        g_idle_add(encoder_action,a);
+        g_idle_add(process_action,a);
         encoders[i].top_encoder_pos=0;
       }
     }
@@ -548,10 +548,10 @@ static void process_edge(int offset,int value) {
       break;
     } else if(encoders[i].switch_enabled && encoders[i].switch_address==offset) {
       //g_print("%s: found %d encoder %d switch\n",__FUNCTION__,offset,i);
-      SWITCH_ACTION *a=g_new(SWITCH_ACTION,1);
+      PROCESS_ACTION *a=g_new(PROCESS_ACTION,1);
       a->action=encoders[i].switch_function;
-      a->state=value;
-      g_idle_add(switch_action,a);
+      a->mode=value?PRESSED:RELEASED;
+      g_idle_add(process_action,a);
       found=TRUE;
       break;
     }
@@ -575,12 +575,12 @@ static void process_edge(int offset,int value) {
         if(t<switches[i].switch_debounce) {
           return;
         }
-g_print("%s: switches=%p function=%d (%s)\n",__FUNCTION__,switches,switches[i].switch_function,sw_string[switches[i].switch_function]);
+//g_print("%s: switches=%p function=%d (%s)\n",__FUNCTION__,switches,switches[i].switch_function,sw_string[switches[i].switch_function]);
         switches[i].switch_debounce=t+settle_time;
-        SWITCH_ACTION *a=g_new(SWITCH_ACTION,1);
+        PROCESS_ACTION *a=g_new(PROCESS_ACTION,1);
         a->action=switches[i].switch_function;
-        a->state=value;
-        g_idle_add(switch_action,a);
+        a->mode=value?PRESSED:RELEASED;
+        g_idle_add(process_action,a);
         break;
       }
     }
diff --git a/i2c.c b/i2c.c
index 78fc43b..711cd87 100644
--- a/i2c.c
+++ b/i2c.c
@@ -93,10 +93,10 @@ g_print("%s: flags=%04X ints=%04X\n",__FUNCTION__,flags,ints);
         }
         if(i<16) {
 g_print("%s: switches=%p sw=%d action=%d\n",__FUNCTION__,switches,i,switches[i].switch_function);
-          SWITCH_ACTION *a=g_new(SWITCH_ACTION,1);
+          PROCESS_ACTION *a=g_new(PROCESS_ACTION,1);
           a->action=switches[i].switch_function;
-          a->state=PRESSED;
-          g_idle_add(switch_action,a);
+          a->mode=PRESSED;
+          g_idle_add(process_action,a);
         }
       }
     }
diff --git a/iambic.c b/iambic.c
index 6f32453..a7ff8a2 100644
--- a/iambic.c
+++ b/iambic.c
@@ -296,6 +296,7 @@ void keyer_update() {
 static int enforce_cw_vox;
 
 void keyer_event(int left, int state) {
+  g_print("%s: running=%d left=%d state=%d\n",__FUNCTION__,running,left,state);
     if (!running) return;
     if (state) {
         // This is to remember whether the key stroke interrupts a running CAT CW 
diff --git a/midi.h b/midi.h
index 5c66621..841980a 100644
--- a/midi.h
+++ b/midi.h
@@ -48,6 +48,7 @@
 // MIDIaction encodes the "action" to be taken in Layer3
 // (sorted alphabetically by the keyword)
 //
+/*
 enum MIDIaction {
   ACTION_NONE=0,	// NONE:		No-Op (unassigned key)
   VFO_A2B,		// A2B:			VFO A -> B
@@ -148,6 +149,7 @@ enum MIDIaction {
   ZOOM_UP,		// ZOOMUP:		change zoom factor
   ZOOM_DOWN,		// ZOOMDOWN:		change zoom factor
 };
+*/
 
 //
 // MIDItype encodes the type of MIDI control. This info
@@ -172,13 +174,14 @@ enum MIDIaction {
 //  100 very fast going up
 //
 
+/*
 enum MIDItype {
  TYPE_NONE=0,
  MIDI_KEY=1,          // Button (press event)
  MIDI_KNOB=2,         // Knob   (value between 0 and 100)
  MIDI_WHEEL=4         // Wheel  (direction and speed)
 };
-
+*/
 extern gchar *midi_types[];
 extern gchar *midi_events[];
 
@@ -198,12 +201,11 @@ enum MIDIevent {
 //
 // Data structure for Layer-2
 //
-
-typedef struct _action_table {
-  enum MIDIaction action;
+typedef struct _old_action_table {
+  enum ACTION action;
   const char *str;
-  enum MIDItype type;
-} ACTION_TABLE;
+  enum ACTIONtype type;
+} OLD_ACTION_TABLE;
 
 extern ACTION_TABLE ActionTable[];
 
@@ -236,7 +238,7 @@ struct desc {
    int               channel;     // -1 for ANY channel
    enum MIDIevent    event;	  // type of event (NOTE on/off, Controller change, Pitch value)
    int               onoff;       // 1: generate upstream event both for Note-on and Note-off
-   enum MIDItype     type;        // Key, Knob, or Wheel
+   enum ACTIONtype   type;        // Key, Knob, or Wheel
    int               vfl1,vfl2;   // Wheel only: range of controller values for "very fast left"
    int               fl1,fl2;     // Wheel only: range of controller values for "fast left"
    int               lft1,lft2;   // Wheel only: range of controller values for "slow left"
@@ -244,7 +246,7 @@ struct desc {
    int               fr1,fr2;     // Wheel only: range of controller values for "fast right"
    int               rgt1,rgt2;   // Wheel only: range of controller values for "slow right"
    int		     delay;       // Wheel only: delay (msec) before next message is given upstream
-   enum MIDIaction   action;	  // SDR "action" to generate
+   int   action;	  // SDR "action" to generate
    struct desc       *next;       // Next defined action for a controller/key with that note value (NULL for end of list)
 };
 
@@ -287,5 +289,5 @@ int MIDIstop();
 // tons of invocations of g_idle_add with routines from ext.c
 //
 
-void DoTheMidi(enum MIDIaction code, enum MIDItype type, int val);
+void DoTheMidi(int code, enum ACTIONtype type, int val);
 #endif
diff --git a/midi2.c b/midi2.c
index f0c5175..054c0f5 100644
--- a/midi2.c
+++ b/midi2.c
@@ -20,6 +20,7 @@
 #include "transmitter.h"
 #include "radio.h"
 #include "main.h"
+#include "actions.h"
 #include "midi.h"
 
 
@@ -29,7 +30,7 @@ void NewMidiEvent(enum MIDIevent event, int channel, int note, int val) {
 
     struct desc *desc;
     int new;
-    static enum MIDIaction last_wheel_action=ACTION_NONE ;
+    static int last_wheel_action=NO_ACTION ;
     static struct timespec tp, last_wheel_tp={0,0};
     long delta;
 
@@ -107,80 +108,68 @@ void NewMidiEvent(enum MIDIevent event, int channel, int note, int val) {
 gchar *midi_types[] = {"NONE","KEY","KNOB/SLIDER","*INVALID*","WHEEL"};
 gchar *midi_events[] = {"NONE","NOTE","CTRL","PITCH"};
 
-/*
- * This data structre connects names as used in the midi.props file with
- * our MIDIaction enum values.
- * Take care that no key word is contained in another one!
- * Example: use "CURRVFO" not "VFO" otherwise there is possibly
- * a match for "VFO" when the key word is "VFOA".
- */
-
-/*
-static struct {
-  enum MIDIaction action;
-  const char *str;
-  enum MIDItype type;
-} ActionTable[] = {
-*/
-ACTION_TABLE ActionTable[] = {
-	{ ACTION_NONE,		"NONE",		TYPE_NONE},
-	{ VFO_A2B,		"A2B",		MIDI_KEY},
-        { MIDI_AF_GAIN,      	"AFGAIN",	MIDI_KNOB|MIDI_WHEEL},
-	{ AGCATTACK,   		"AGCATTACK",	MIDI_KEY},
-        { MIDI_AGC,     	"AGCVAL",	MIDI_KNOB|MIDI_WHEEL},
+//
+// maintained so old midi configurations can be loaded
+//
+OLD_ACTION_TABLE OLD_ActionTable[] = {
+	{ NO_ACTION,		"NONE",		TYPE_NONE},
+	{ A_TO_B,		"A2B",		MIDI_KEY},
+        { AF_GAIN,      	"AFGAIN",	MIDI_KNOB|MIDI_WHEEL},
+	{ AGC,   		"AGCATTACK",	MIDI_KEY},
+        { AGC_GAIN, 	    	"AGCVAL",	MIDI_KNOB|MIDI_WHEEL},
         { ANF,     		"ANF",		MIDI_KEY},
-        { ATT,          	"ATT",		MIDI_KNOB|MIDI_WHEEL},
-	{ VFO_B2A,		"B2A",		MIDI_KEY},
-	{ MIDI_BAND_10,         "BAND10",	MIDI_KEY},
-        { MIDI_BAND_12,         "BAND12",	MIDI_KEY},
-        { MIDI_BAND_1240,       "BAND1240",	MIDI_KEY},
-        { MIDI_BAND_144,        "BAND144",	MIDI_KEY},
-        { MIDI_BAND_15,         "BAND15",	MIDI_KEY},
-        { MIDI_BAND_160,        "BAND160",	MIDI_KEY},
-        { MIDI_BAND_17,         "BAND17",	MIDI_KEY},
-        { MIDI_BAND_20,         "BAND20",	MIDI_KEY},
-        { MIDI_BAND_220,        "BAND220",	MIDI_KEY},
-        { MIDI_BAND_2300,       "BAND2300",	MIDI_KEY},
-        { MIDI_BAND_30,         "BAND30",	MIDI_KEY},
-        { MIDI_BAND_3400,       "BAND3400",	MIDI_KEY},
-        { MIDI_BAND_40,         "BAND40",	MIDI_KEY},
-        { MIDI_BAND_430,        "BAND430",	MIDI_KEY},
-        { MIDI_BAND_6,          "BAND6",	MIDI_KEY},
-        { MIDI_BAND_60,         "BAND60",	MIDI_KEY},
-        { MIDI_BAND_70,         "BAND70",	MIDI_KEY},
-        { MIDI_BAND_80,         "BAND80",	MIDI_KEY},
-        { MIDI_BAND_902,        "BAND902",	MIDI_KEY},
-        { MIDI_BAND_AIR,        "BANDAIR",	MIDI_KEY},
-        { BAND_DOWN,            "BANDDOWN",	MIDI_KEY},
-        { MIDI_BAND_GEN,        "BANDGEN",	MIDI_KEY},
-        { BAND_UP,              "BANDUP",	MIDI_KEY},
-        { MIDI_BAND_WWV,        "BANDWWV",	MIDI_KEY},
-        { COMPRESS,     	"COMPRESS",	MIDI_KEY},
-	{ MIDI_CTUN,  		"CTUN",		MIDI_KEY},
+        { ATTENUATION, 		"ATT",		MIDI_KNOB|MIDI_WHEEL},
+	{ B_TO_A,			"B2A",		MIDI_KEY},
+	{ BAND_10,         "BAND10",	MIDI_KEY},
+        { BAND_12,         "BAND12",	MIDI_KEY},
+        { BAND_1240,       "BAND1240",	MIDI_KEY},
+        { BAND_144,        "BAND144",	MIDI_KEY},
+        { BAND_15,         "BAND15",	MIDI_KEY},
+        { BAND_160,        "BAND160",	MIDI_KEY},
+        { BAND_17,         "BAND17",	MIDI_KEY},
+        { BAND_20,         "BAND20",	MIDI_KEY},
+        { BAND_220,        "BAND220",	MIDI_KEY},
+        { BAND_2300,       "BAND2300",	MIDI_KEY},
+        { BAND_30,         "BAND30",	MIDI_KEY},
+        { BAND_3400,       "BAND3400",	MIDI_KEY},
+        { BAND_40,         "BAND40",	MIDI_KEY},
+        { BAND_430,        "BAND430",	MIDI_KEY},
+        { BAND_6,          "BAND6",	MIDI_KEY},
+        { BAND_60,         "BAND60",	MIDI_KEY},
+        { BAND_70,         "BAND70",	MIDI_KEY},
+        { BAND_80,         "BAND80",	MIDI_KEY},
+        { BAND_902,        "BAND902",	MIDI_KEY},
+        { BAND_AIR,        "BANDAIR",	MIDI_KEY},
+        { BAND_MINUS,      "BANDDOWN",	MIDI_KEY},
+        { BAND_GEN,        "BANDGEN",	MIDI_KEY},
+        { BAND_PLUS,       "BANDUP",	MIDI_KEY},
+        { BAND_WWV,        "BANDWWV",	MIDI_KEY},
+        { COMPRESSION,     	"COMPRESS",	MIDI_KEY},
+	{ CTUN,  		"CTUN",		MIDI_KEY},
 	{ VFO,			"CURRVFO",	MIDI_WHEEL},
-	{ CWLEFT,		"CWL",		MIDI_KEY},
-	{ CWRIGHT,		"CWR",		MIDI_KEY},
-	{ CWSPEED,		"CWSPEED",	MIDI_KNOB|MIDI_WHEEL},
-	{ DIV_COARSEGAIN,	"DIVCOARSEGAIN",	MIDI_KNOB|MIDI_WHEEL},
-	{ DIV_COARSEPHASE,	"DIVCOARSEPHASE",	MIDI_KNOB|MIDI_WHEEL},
-	{ DIV_FINEGAIN,		"DIVFINEGAIN",	MIDI_KNOB|MIDI_WHEEL},
-	{ DIV_FINEPHASE,	"DIVFINEPHASE",	MIDI_KNOB|MIDI_WHEEL},
+	{ CW_LEFT,		"CWL",		MIDI_KEY},
+	{ CW_RIGHT,		"CWR",		MIDI_KEY},
+	{ CW_SPEED,		"CWSPEED",	MIDI_KNOB|MIDI_WHEEL},
+	{ DIV_GAIN_COARSE,	"DIVCOARSEGAIN",	MIDI_KNOB|MIDI_WHEEL},
+	{ DIV_PHASE_COARSE,	"DIVCOARSEPHASE",	MIDI_KNOB|MIDI_WHEEL},
+	{ DIV_GAIN_FINE,	"DIVFINEGAIN",	MIDI_KNOB|MIDI_WHEEL},
+	{ DIV_PHASE_FINE,	"DIVFINEPHASE",	MIDI_KNOB|MIDI_WHEEL},
 	{ DIV_GAIN,		"DIVGAIN",	MIDI_KNOB|MIDI_WHEEL},
 	{ DIV_PHASE,		"DIVPHASE",	MIDI_KNOB|MIDI_WHEEL},
-	{ DIV_TOGGLE,		"DIVTOGGLE",	MIDI_KEY},
-	{ MIDI_DUP,  		"DUP",		MIDI_KEY},
-        { FILTER_DOWN,  	"FILTERDOWN",	MIDI_KEY},
-        { FILTER_UP,    	"FILTERUP",	MIDI_KEY},
+	{ DIV,			"DIVTOGGLE",	MIDI_KEY},
+	{ DUPLEX,  		"DUP",		MIDI_KEY},
+        { FILTER_MINUS,  	"FILTERDOWN",	MIDI_KEY},
+        { FILTER_PLUS,    	"FILTERUP",	MIDI_KEY},
 	{ MENU_FILTER,		"MENU_FILTER",	MIDI_KEY},
 	{ MENU_MODE,		"MENU_MODE",	MIDI_KEY},
-	{ MIDI_LOCK,    	"LOCK",		MIDI_KEY},
-        { MIC_VOLUME,   	"MICGAIN",	MIDI_KNOB|MIDI_WHEEL},
-	{ MODE_DOWN,		"MODEDOWN",	MIDI_KEY|MIDI_KNOB|MIDI_WHEEL},
-	{ MODE_UP,		"MODEUP",	MIDI_KEY|MIDI_KNOB|MIDI_WHEEL},
-        { MIDI_MOX,     	"MOX",	MIDI_KEY},
-	{ MIDI_MUTE,		"MUTE",	MIDI_KEY},
-	{ MIDI_NB,    		"NOISEBLANKER",	MIDI_KEY},
-	{ MIDI_NR,    		"NOISEREDUCTION",	MIDI_KEY},
+	{ LOCK,	    		"LOCK",		MIDI_KEY},
+        { MIC_GAIN,   		"MICGAIN",	MIDI_KNOB|MIDI_WHEEL},
+	{ MODE_MINUS,		"MODEDOWN",	MIDI_KEY|MIDI_KNOB|MIDI_WHEEL},
+	{ MODE_PLUS,		"MODEUP",	MIDI_KEY|MIDI_KNOB|MIDI_WHEEL},
+        { MOX, 		    	"MOX",	MIDI_KEY},
+	{ MUTE,			"MUTE",	MIDI_KEY},
+	{ NB,    		"NOISEBLANKER",	MIDI_KEY},
+	{ NR,    		"NOISEREDUCTION",	MIDI_KEY},
 	{ NUMPAD_0,		"NUMPAD0",	MIDI_KEY},
 	{ NUMPAD_1,		"NUMPAD1",	MIDI_KEY},
 	{ NUMPAD_2,		"NUMPAD2",	MIDI_KEY},
@@ -193,49 +182,49 @@ ACTION_TABLE ActionTable[] = {
 	{ NUMPAD_9,		"NUMPAD9",	MIDI_KEY},
 	{ NUMPAD_CL,		"NUMPADCL",	MIDI_KEY},
 	{ NUMPAD_ENTER,		"NUMPADENTER",	MIDI_KEY},
-        { MIDI_PAN,		"PAN",	MIDI_KNOB|MIDI_WHEEL},
-        { PAN_HIGH,     	"PANHIGH",	MIDI_KNOB|MIDI_WHEEL},
-        { PAN_LOW,      	"PANLOW",	MIDI_KNOB|MIDI_WHEEL},
-        { PRE,          	"PREAMP",	MIDI_KEY},
-	{ MIDI_PS,    		"PURESIGNAL",	MIDI_KEY},
-	{ MIDI_RF_GAIN, 	"RFGAIN",	MIDI_KNOB|MIDI_WHEEL},
-        { TX_DRIVE,     	"RFPOWER",	MIDI_KNOB|MIDI_WHEEL},
-	{ MIDI_RIT_CLEAR,	"RITCLEAR",	MIDI_KEY},
+        { PAN,			"PAN",	MIDI_KNOB|MIDI_WHEEL},
+        { PANADAPTER_HIGH,     	"PANHIGH",	MIDI_KNOB|MIDI_WHEEL},
+        { PANADAPTER_LOW,      	"PANLOW",	MIDI_KNOB|MIDI_WHEEL},
+        { PREAMP,          	"PREAMP",	MIDI_KEY},
+	{ PS,    		"PURESIGNAL",	MIDI_KEY},
+	{ RF_GAIN,	 	"RFGAIN",	MIDI_KNOB|MIDI_WHEEL},
+        { DRIVE, 	    	"RFPOWER",	MIDI_KNOB|MIDI_WHEEL},
+	{ RIT_CLEAR,		"RITCLEAR",	MIDI_KEY},
 	{ RIT_STEP, 		"RITSTEP",	MIDI_KNOB|MIDI_WHEEL},
-        { RIT_TOGGLE,   	"RITTOGGLE",	MIDI_KEY},
-        { RIT_VAL,      	"RITVAL",	MIDI_KNOB|MIDI_WHEEL},
-        { MIDI_SAT,     	"SAT",	MIDI_KEY},
+        { RIT_ENABLE,   	"RITTOGGLE",	MIDI_KEY},
+        { RIT, 	     	"RITVAL",	MIDI_KNOB|MIDI_WHEEL},
+        { SAT,     		"SAT",	MIDI_KEY},
         { SNB, 		    	"SNB",	MIDI_KEY},
-	{ MIDI_SPLIT,  		"SPLIT",	MIDI_KEY},
+	{ SPLIT,  		"SPLIT",	MIDI_KEY},
 	{ SWAP_RX,		"SWAPRX",	MIDI_KEY},
-	{ SWAP_VFO,		"SWAPVFO",	MIDI_KEY},
-        { MIDI_TUNE,    	"TUNE",	MIDI_KEY},
+	{ A_SWAP_B,		"SWAPVFO",	MIDI_KEY},
+        { TUNE, 	   	"TUNE",	MIDI_KEY},
         { VFOA,         	"VFOA",	MIDI_WHEEL},
         { VFOB,         	"VFOB",	MIDI_WHEEL},
-	{ VFO_STEP_UP,  	"VFOSTEPUP",	MIDI_KEY},
-	{ VFO_STEP_DOWN,	"VFOSTEPDOWN",	MIDI_KEY},
+	{ VFO_STEP_MINUS,	"VFOSTEPDOWN",	MIDI_KEY},
+	{ VFO_STEP_PLUS,  	"VFOSTEPUP",	MIDI_KEY},
 	{ VOX,   		"VOX",	MIDI_KEY},
 	{ VOXLEVEL,   		"VOXLEVEL",	MIDI_KNOB|MIDI_WHEEL},
-	{ MIDI_XIT_CLEAR,  	"XITCLEAR",	MIDI_KEY},
-	{ XIT_VAL,  		"XITVAL",	MIDI_KNOB|MIDI_WHEEL},
-	{ MIDI_ZOOM,		"ZOOM",	MIDI_KNOB|MIDI_WHEEL},
-	{ ZOOM_UP,		"ZOOMUP",	MIDI_KEY},
-	{ ZOOM_DOWN,		"ZOOMDOWN",	MIDI_KEY},
-        { ACTION_NONE,  	"NONE",	TYPE_NONE}
+	{ XIT_CLEAR, 	 	"XITCLEAR",	MIDI_KEY},
+	{ XIT,  		"XITVAL",	MIDI_KNOB|MIDI_WHEEL},
+	{ ZOOM,			"ZOOM",	MIDI_KNOB|MIDI_WHEEL},
+	{ ZOOM_MINUS,		"ZOOMDOWN",	MIDI_KEY},
+	{ ZOOM_PLUS,		"ZOOMUP",	MIDI_KEY},
+        { NO_ACTION,  	"NONE",	TYPE_NONE}
 };
 
 /*
  * Translation from keyword in midi.props file to MIDIaction
  */
 
-static enum MIDIaction keyword2action(char *s) {
+static int keyword2action(char *s) {
     int i=0;
 
-    for (i=0; i< (sizeof(ActionTable) / sizeof(ActionTable[0])); i++) {
-	if (!strcmp(s, ActionTable[i].str)) return ActionTable[i].action;
+    for (i=0; i< (sizeof(OLD_ActionTable) / sizeof(OLD_ActionTable[0])); i++) {
+	if (!strcmp(s, OLD_ActionTable[i].str)) return OLD_ActionTable[i].action;
     }
     fprintf(stderr,"MIDI: action keyword %s NOT FOUND.\n", s);
-    return ACTION_NONE;
+    return NO_ACTION;
 }
 
 
@@ -255,12 +244,12 @@ int MIDIstartup(char *filename) {
     char zeile[255];
     char *cp,*cq;
     int key;
-    enum MIDIaction action;
+    int action;
     int chan;
     int t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12;
     int onoff, delay;
     struct desc *desc,*dp;
-    enum MIDItype type;
+    enum ACTIONtype type;
     enum MIDIevent event;
     int i;
     char c;
@@ -383,7 +372,7 @@ g_print("%s:DELAY:%d\n",__FUNCTION__,delay);
 //fprintf(stderr,"MIDI:THR:%d/%d, %d/%d, %d/%d, %d/%d, %d/%d, %d/%d\n",t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12);
       }
       if ((cp = strstr(zeile, "ACTION="))) {
-        // cut zeile at the first blank character following
+	  // cut zeile at the first blank character following
         cq=cp+7;
         while (*cq != 0 && *cq != '\n' && *cq != ' ' && *cq != '\t') cq++;
 	*cq=0;
diff --git a/midi3.c b/midi3.c
index d7b2dd8..2294a62 100644
--- a/midi3.c
+++ b/midi3.c
@@ -21,38 +21,75 @@
 #include "sliders.h"
 #include "ext.h"
 #include "agc.h"
+#include "actions.h"
 #include "midi.h"
 #ifdef LOCALCW
 #include "iambic.h"
 #endif
 
-void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
+void DoTheMidi(int action, enum ACTIONtype type, int val) {
 
     int new;
     double dnew;
     double *dp;
     int    *ip;
+    PROCESS_ACTION *a;
 
     //
     // Handle cases in alphabetical order of the key words in midi.props
     //
+
+    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);
+	break;
+      case MIDI_KNOB:
+        a=g_new(PROCESS_ACTION,1);
+        a->action=action;
+        a->mode=ABSOLUTE;
+        a->val=val;
+        g_idle_add(process_action,a);
+        break;
+      case MIDI_WHEEL:
+        a=g_new(PROCESS_ACTION,1);
+        a->action=action;
+        a->mode=RELATIVE;
+        a->val=val;
+        g_idle_add(process_action,a);
+        break;
+    }
+
+/*
     switch (action) {
 	/////////////////////////////////////////////////////////// "A2B"
-	case VFO_A2B: // only key supported
+	case A_TO_B: // only key supported
 	    if (type == MIDI_KEY) {
-	      g_idle_add(ext_vfo_a_to_b, NULL);
+	      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 MIDI_AF_GAIN: // knob or wheel supported
+	case AF_GAIN: // knob or wheel supported
             switch (type) {
 	      case MIDI_KNOB:
-		active_receiver->volume = 0.01*val;
+		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:	
-		dnew=active_receiver->volume += 0.01*val;
-		if (dnew < 0.0) dnew=0.0; if (dnew > 1.0) dnew=1.0;
-		active_receiver->volume = dnew;
+		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
@@ -62,43 +99,57 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    g_idle_add(ext_update_af_gain, NULL);
 	    break;
 	/////////////////////////////////////////////////////////// "AGCATTACK"
-	case AGCATTACK: // only key supported
+	case AGC: // only key supported
 	    // cycle through fast/med/slow AGC attack
 	    if (type == MIDI_KEY) {
-	      new=active_receiver->agc + 1;
-	      if (new > AGC_FAST) new=0;
-	      active_receiver->agc=new;
-	      g_idle_add(ext_vfo_update, NULL);
+	      a=g_new(PROCESS_ACTION,1);
+              a->action=AGC;
+              a->mode=PRESSED;
+              g_idle_add(process_action,a);
 	    }
 	    break;
 	/////////////////////////////////////////////////////////// "AGCVAL"
-	case MIDI_AGC: // knob or wheel supported
+	case AGC_GAIN: // knob or wheel supported
 	    switch (type) {
 	      case MIDI_KNOB:
-		dnew = -20.0 + 1.4*val;
+		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:
-		dnew=active_receiver->agc_gain + val;
-		if (dnew < -20.0) dnew=-20.0; if (dnew > 120.0) dnew=120.0;
+		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;
+		//dnew=active_receiver->agc_gain;
 		break;
 	    }
-	    dp=malloc(sizeof(double));
-	    *dp=dnew;
-	    g_idle_add(ext_set_agc_gain, (gpointer) dp);
+	    //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) {
-	      g_idle_add(ext_anf_update, NULL);
+	      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 ATT:	// Key for ALEX attenuator, wheel or knob for slider
+	case ATTENUATION:	// Key for ALEX attenuator, wheel or knob for slider
 	    switch(type) {
 	      case MIDI_KEY:
 		if (filter_board == ALEX && active_receiver->adc == 0) {
@@ -143,9 +194,13 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    }
 	    break;
 	/////////////////////////////////////////////////////////// "B2A"
-	case VFO_B2A: // only key supported
+	case B_TO_A: // only key supported
 	    if (type == MIDI_KEY) {
-	      g_idle_add(ext_vfo_b_to_a, NULL);
+	      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"
@@ -188,133 +243,133 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    break;
 
 	/////////////////////////////////////////////////////////// "BANDxxx"
-        case MIDI_BAND_10:
+        case BAND_10:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band10));
             }
             break;
-        case MIDI_BAND_12:
+        case BAND_12:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band12));
             }
             break;
 #ifdef SOAPYSDR
-        case MIDI_BAND_1240:
+        case BAND_1240:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band1240));
             }
             break;
-        case MIDI_BAND_144:
+        case BAND_144:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band144));
             }
             break;
 #endif
-        case MIDI_BAND_15:
+        case BAND_15:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band15));
             }
             break;
-        case MIDI_BAND_160:
+        case BAND_160:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band160));
             }
             break;
-        case MIDI_BAND_17:
+        case BAND_17:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band17));
             }
             break;
-        case MIDI_BAND_20:
+        case BAND_20:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band20));
             }
             break;
 #ifdef SOAPYSDR
-        case MIDI_BAND_220:
+        case BAND_220:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band220));
             }
             break;
-        case MIDI_BAND_2300:
+        case BAND_2300:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band2300));
             }
             break;
 #endif
-        case MIDI_BAND_30:
+        case BAND_30:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band30));
             }
             break;
 #ifdef SOAPYSDR
-        case MIDI_BAND_3400:
+        case BAND_3400:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band3400));
             }
             break;
-        case MIDI_BAND_70:
+        case BAND_70:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band70));
             }
             break;
 #endif
-        case MIDI_BAND_40:
+        case BAND_40:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band40));
             }
             break;
 #ifdef SOAPYSDR
-        case MIDI_BAND_430:
+        case BAND_430:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band430));
             }
             break;
 #endif
-        case MIDI_BAND_6:
+        case BAND_6:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band6));
             }
             break;
-        case MIDI_BAND_60:
+        case BAND_60:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band60));
             }
             break;
-        case MIDI_BAND_80:
+        case BAND_80:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band80));
             }
             break;
 #ifdef SOAPYSDR
-        case MIDI_BAND_902:
+        case BAND_902:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(band902));
             }
             break;
-        case MIDI_BAND_AIR:
+        case BAND_AIR:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(bandAIR));
             }
             break;
 #endif
-        case MIDI_BAND_GEN:
+        case BAND_GEN:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(bandGen));
             }
             break;
-        case MIDI_BAND_WWV:
+        case BAND_WWV:
             if (type == MIDI_KEY) {
               g_idle_add(ext_band_select, GINT_TO_POINTER(bandWWV));
             }
             break;
 	/////////////////////////////////////////////////////////// "BANDDOWN"
 	/////////////////////////////////////////////////////////// "BANDUP"
-	case BAND_DOWN:
-	case BAND_UP:
+	case BAND_MINUS:
+	case BAND_PLUS:
 	    switch (type) {
 	      case MIDI_KEY:
-		new=(action == BAND_UP) ? 1 : -1;
+		new=(action == BAND_PLUS) ? 1 : -1;
 		break;
 	      case MIDI_WHEEL:
 		new=val > 0 ? 1 : -1;
@@ -340,8 +395,8 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	      g_idle_add(ext_vfo_band_changed, GINT_TO_POINTER(new));
 	    }
 	    break;
-	/////////////////////////////////////////////////////////// "COMPRESS"
-	case COMPRESS: // wheel or knob
+	/////////////////////////////////////////////////////////// "COMPRESSION"
+	case COMPRESSION: // wheel or knob
 	    switch (type) {
 	      case MIDI_WHEEL:
 		dnew=transmitter->compressor_level + val;
@@ -364,7 +419,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    g_idle_add(ext_set_compression, NULL);
 	    break;
 	/////////////////////////////////////////////////////////// "CTUN"
-	case MIDI_CTUN: // only key supported
+	case CTUN: // only key supported
 	    // toggle CTUN
 	    if (type == MIDI_KEY) {
 	      g_idle_add(ext_ctun_update, NULL);
@@ -378,20 +433,20 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    break;
 	/////////////////////////////////////////////////////////// "CWL"
 	/////////////////////////////////////////////////////////// "CWR"
-	case CWLEFT: // only key
-	case CWRIGHT: // only key
+	case CW_LEFT: // only key
+	case CW_RIGHT: // only key
 #ifdef LOCALCW
 	    if (type == MIDI_KEY) {
-		new=(action == CWLEFT);
+		new=(action == CW_LEFT);
 		keyer_event(new,val);
 	    }
 #else
-	    g_print("%s: %s:%d\n",__FUNCTION__,action==CWLEFT?"CWL":"CWR",val);
+	    g_print("%s: %s:%d\n",__FUNCTION__,action==CW_LEFT?"CWL":"CWR",val);
 
 #endif
 	    break;
 	/////////////////////////////////////////////////////////// "CWSPEED"
-	case CWSPEED: // knob or wheel
+	case CW_SPEED: // knob or wheel
             switch (type) {
               case MIDI_KNOB:
 		// speed between 5 and 35 wpm
@@ -416,12 +471,12 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
             g_idle_add(ext_vfo_update, NULL);
 	    break;
 	/////////////////////////////////////////////////////////// "DIVCOARSEGAIN"
-	case DIV_COARSEGAIN:  // knob or wheel supported
-	case DIV_FINEGAIN:    // knob or wheel supported
+	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_COARSEGAIN || action == DIV_GAIN) {
+                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 {
@@ -434,7 +489,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
                 // 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_COARSEGAIN) {
+		} else if (action == DIV_GAIN_COARSE) {
 		  dnew = val*2.5;
 		} else {
 		  dnew = val * 0.1;
@@ -452,14 +507,14 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
             g_idle_add(ext_diversity_change_gain, dp);
             break;
         /////////////////////////////////////////////////////////// "DIVPHASE"
-        case DIV_COARSEPHASE:   // knob or wheel supported
-        case DIV_FINEPHASE:     // knob or wheel supported
+        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_COARSEPHASE || action == DIV_PHASE) {
+                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 {
@@ -471,9 +526,9 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
               case MIDI_WHEEL:
 		if (action == DIV_PHASE) {
 		  dnew = val*0.5; 
-		} else if (action == DIV_COARSEPHASE) {
+		} else if (action == DIV_PHASE_COARSE) {
 		  dnew = val*2.5;
-		} else if (action == DIV_FINEPHASE) {
+		} else if (action == DIV_PHASE_FINE) {
 		  dnew = 0.1*val;
 		}
                 break;
@@ -489,7 +544,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
             g_idle_add(ext_diversity_change_phase, dp);
             break;
         /////////////////////////////////////////////////////////// "DIVTOGGLE"
-        case DIV_TOGGLE:   // only key supported
+        case DIV:   // only key supported
             if (type == MIDI_KEY) {
                 // enable/disable DIVERSITY
                 diversity_enabled = diversity_enabled ? 0 : 1;
@@ -497,7 +552,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
             }
             break;
 	/////////////////////////////////////////////////////////// "DUP"
-        case MIDI_DUP:
+        case DUPLEX:
 	    if (can_transmit && !isTransmitting()) {
 	      duplex=duplex==1?0:1;
               g_idle_add(ext_set_duplex, NULL);
@@ -505,15 +560,15 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
             break;
 	/////////////////////////////////////////////////////////// "FILTERDOWN"
 	/////////////////////////////////////////////////////////// "FILTERUP"
-	case FILTER_DOWN:
-	case FILTER_UP:
+	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_UP) ? -1 : 1;
+		new=(action == FILTER_PLUS) ? -1 : 1;
 		break;
 	      case MIDI_WHEEL:
 		new=val > 0 ? -1 : 1;
@@ -544,14 +599,14 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    g_idle_add(ext_menu_mode, NULL);
 	    break;
 	/////////////////////////////////////////////////////////// "LOCK"
-	case MIDI_LOCK: // only key supported
+	case LOCK: // only key supported
 	    if (type == MIDI_KEY) {
 	      locked=!locked;
 	      g_idle_add(ext_vfo_update, NULL);
 	    }
 	    break;
 	/////////////////////////////////////////////////////////// "MICGAIN"
-	case MIC_VOLUME: // knob or wheel supported
+	case MIC_GAIN: // knob or wheel supported
 	    // TODO: possibly adjust linein value if that is effective
 	    switch (type) {
 	      case MIDI_KNOB:
@@ -573,11 +628,11 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    break;
 	/////////////////////////////////////////////////////////// "MODEDOWN"
 	/////////////////////////////////////////////////////////// "MODEUP"
-	case MODE_DOWN:
-	case MODE_UP:
+	case MODE_MINUS:
+	case MODE_PLUS:
 	    switch (type) {
 	      case MIDI_KEY:
-		new=(action == MODE_UP) ? 1 : -1;
+		new=(action == MODE_PLUS) ? 1 : -1;
 		break;
 	      case MIDI_WHEEL:
 		new=val > 0 ? 1 : -1;
@@ -600,20 +655,20 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    }
 	    break;
 	/////////////////////////////////////////////////////////// "MOX"
-	case MIDI_MOX: // only key supported
+	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 MIDI_MUTE:
+        case MUTE:
             if (type == MIDI_KEY) {
               g_idle_add(ext_mute_update,NULL);
 	    }
             break;
 	/////////////////////////////////////////////////////////// "NOISEBLANKER"
-	case MIDI_NB: // only key supported
+	case NB: // only key supported
 	    // cycle through NoiseBlanker settings: OFF, NB, NB2
             if (type == MIDI_KEY) {
 	      if (active_receiver->nb) {
@@ -630,7 +685,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    }
 	    break;
 	/////////////////////////////////////////////////////////// "NOISEREDUCTION"
-	case MIDI_NR: // only key supported
+	case NR: // only key supported
 	    // cycle through NoiseReduction settings: OFF, NR1, NR2
 	    if (type == MIDI_KEY) {
 	      if (active_receiver->nr) {
@@ -648,7 +703,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    }
 	    break;
 	/////////////////////////////////////////////////////////// "PAN"
-        case MIDI_PAN:  // wheel and knob
+        case PAN:  // wheel and knob
 	    switch (type) {
               case MIDI_WHEEL:
                 g_idle_add(ext_pan_update,GINT_TO_POINTER(val));
@@ -662,7 +717,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
             }
             break;
 	/////////////////////////////////////////////////////////// "PANHIGH"
-	case PAN_HIGH:  // wheel or knob
+	case PANADAPTER_HIGH:  // wheel or knob
 	    switch (type) {
 	      case MIDI_WHEEL:
 		if (mox) {
@@ -689,7 +744,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    g_idle_add(ext_vfo_update, NULL);
 	    break;
 	/////////////////////////////////////////////////////////// "PANLOW"
-	case PAN_LOW:  // wheel and knob
+	case PANADAPTER_LOW:  // wheel and knob
 	    switch (type) {
 	      case MIDI_WHEEL:
 		if (isTransmitting()) {
@@ -718,7 +773,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    g_idle_add(ext_vfo_update, NULL);
 	    break;
 	/////////////////////////////////////////////////////////// "PREAMP"
-	case PRE:	// only key supported
+	case PREAMP:	// only key supported
 	    if (type == MIDI_KEY) {
 		//
 		// Normally on/off, but for CHARLY25, cycle through three
@@ -751,7 +806,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    }
 	    break;
 	/////////////////////////////////////////////////////////// "PURESIGNAL"
-	case MIDI_PS: // only key supported
+	case PS: // only key supported
 #ifdef PURESIGNAL
 	    // toggle PURESIGNAL
 	    if (type == MIDI_KEY) {
@@ -761,7 +816,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 #endif
 	    break;
 	/////////////////////////////////////////////////////////// "RFGAIN"
-        case MIDI_RF_GAIN: // knob or wheel supported
+        case RF_GAIN: // knob or wheel supported
             if (type == MIDI_KNOB) {
                 new=val;
             } else  if (type == MIDI_WHEEL) {
@@ -771,7 +826,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
             g_idle_add(ext_set_rf_gain, GINT_TO_POINTER((int)new));
 	    break;
 	/////////////////////////////////////////////////////////// "RFPOWER"
-	case TX_DRIVE: // knob or wheel supported
+	case DRIVE: // knob or wheel supported
 	    switch (type) {
 	      case MIDI_KNOB:
 		dnew = val;
@@ -791,7 +846,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    g_idle_add(ext_set_drive, (gpointer) dp);
 	    break;
 	/////////////////////////////////////////////////////////// "RITCLEAR"
-	case MIDI_RIT_CLEAR:	  // only key supported
+	case RIT_CLEAR:	  // only key supported
 	    if (type == MIDI_KEY) {
 	      // clear RIT value
 	      vfo[active_receiver->id].rit = new;
@@ -804,7 +859,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
               case MIDI_KEY:
                 // key cycles through in upward direction
                 val=1;
-                /* FALLTHROUGH */
+                // FALLTHROUGH
               case MIDI_WHEEL:
                 // wheel cycles upward or downward
                 if (val > 0) {
@@ -822,7 +877,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
             g_idle_add(ext_vfo_update, NULL);
             break;
 	/////////////////////////////////////////////////////////// "RITTOGGLE"
-	case RIT_TOGGLE:  // only key supported
+	case RIT_ENABLE:  // only key supported
 	    if (type == MIDI_KEY) {
 		// enable/disable RIT
 		new=vfo[active_receiver->id].rit_enabled;
@@ -831,7 +886,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    }
 	    break;
 	/////////////////////////////////////////////////////////// "RITVAL"
-	case RIT_VAL:	// wheel or knob
+	case RIT:	// wheel or knob
 	    switch (type) {
 	      case MIDI_WHEEL:
 		// This changes the RIT value incrementally,
@@ -856,7 +911,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    g_idle_add(ext_vfo_update, NULL);
 	    break;
 	/////////////////////////////////////////////////////////// "SAT"
-        case MIDI_SAT:
+        case SAT:
 	    switch (sat_mode) {
 		case SAT_NONE:
 		  sat_mode=SAT_MODE;
@@ -878,7 +933,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    }
 	    break;
 	/////////////////////////////////////////////////////////// "SPLIT"
-	case MIDI_SPLIT: // only key supported
+	case SPLIT: // only key supported
 	    // toggle split mode
 	    if (type == MIDI_KEY) {
               g_idle_add(ext_split_toggle, NULL);
@@ -896,13 +951,13 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    }
 	    break;    
 	/////////////////////////////////////////////////////////// "SWAPVFO"
-	case SWAP_VFO:	// only key supported
-	    if (type == MIDI_KEY) {
-		g_idle_add(ext_vfo_a_swap_b,NULL);
-	    }
-	    break;    
+	//case SWAP_VFO:	// only key supported
+	//    if (type == MIDI_KEY) {
+//		g_idle_add(ext_vfo_a_swap_b,NULL);
+//	    }
+//	    break;    
 	/////////////////////////////////////////////////////////// "TUNE"
-	case MIDI_TUNE: // only key supported
+	case TUNE: // only key supported
 	    if (type == MIDI_KEY && can_transmit) {
 	        new = !tune;
 		g_idle_add(ext_tune_update, GINT_TO_POINTER(new));
@@ -921,11 +976,11 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    break;
 	/////////////////////////////////////////////////////////// "VFOSTEPDOWN"
 	/////////////////////////////////////////////////////////// "VFOSTEPUP"
-        case VFO_STEP_DOWN: // key or wheel supported
-        case VFO_STEP_UP:
+        case VFO_STEP_MINUS: // key or wheel supported
+        case VFO_STEP_PLUS:
 	    switch (type) {
 	      case MIDI_KEY:
-		new =  (action == VFO_STEP_UP) ? 1 : -1;
+		new =  (action == VFO_STEP_PLUS) ? 1 : -1;
 		g_idle_add(ext_update_vfo_step, GINT_TO_POINTER(new));
 		break;
 	      case MIDI_WHEEL:
@@ -967,7 +1022,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    // VOX level not shown on screen, hence no VFO update
 	    break;
 	/////////////////////////////////////////////////////////// "XITCLEAR"
-        case MIDI_XIT_CLEAR:  // only key supported
+        case XIT_CLEAR:  // only key supported
             if (type == MIDI_KEY) {
                 // this clears the XIT value and disables XIT
                 if(can_transmit) {
@@ -978,7 +1033,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
             }
             break;
 	/////////////////////////////////////////////////////////// "XITVAL"
-        case XIT_VAL:   // wheel and knob supported.
+        case XIT:   // wheel and knob supported.
 	    if (can_transmit) {
               switch (type) {
                 case MIDI_WHEEL:
@@ -1005,7 +1060,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    }
             break;
 	/////////////////////////////////////////////////////////// "ZOOM"
-        case MIDI_ZOOM:  // wheel and knob
+        case ZOOM:  // wheel and knob
             switch (type) {
               case MIDI_WHEEL:
 g_print("MIDI_ZOOM: MIDI_WHEEL: val=%d\n",val);
@@ -1022,11 +1077,11 @@ g_print("MIDI_ZOOM: MIDI_KNOB: val=%d\n",val);
             break;
 	/////////////////////////////////////////////////////////// "ZOOMDOWN"
 	/////////////////////////////////////////////////////////// "ZOOMUP"
-        case ZOOM_UP:  // key
-        case ZOOM_DOWN:  // key
+        case ZOOM_MINUS:  // key
+        case ZOOM_PLUS:  // key
 	    switch (type) {
 	      case MIDI_KEY:
-		new =  (action == ZOOM_UP) ? 1 : -1;
+		new =  (action == ZOOM_PLUS) ? 1 : -1;
                 g_idle_add(ext_zoom_update,GINT_TO_POINTER(new));
 		break;
 	      case MIDI_WHEEL:
@@ -1040,11 +1095,12 @@ g_print("MIDI_ZOOM: MIDI_KNOB: val=%d\n",val);
 	    }
             break;
 
-	case ACTION_NONE:
+	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 4fd8304..4d69ec6 100644
--- a/midi_menu.c
+++ b/midi_menu.c
@@ -34,6 +34,7 @@
 #include "adc.h"
 #include "dac.h"
 #include "radio.h"
+#include "actions.h"
 #include "midi.h"
 #include "alsa_midi.h"
 #include "new_menu.h"
@@ -84,8 +85,8 @@ static int thisNote;
 static int thisVal;
 static int thisMin;
 static int thisMax;
-static enum MIDItype thisType;
-static enum MIDIaction thisAction;
+static enum ACTIONtype thisType;
+static int thisAction;
 
 gchar *midi_device_name=NULL;
 static gint device_index=-1;
@@ -167,7 +168,7 @@ static void type_changed_cb(GtkWidget *widget, gpointer data) {
     gtk_combo_box_set_active (GTK_COMBO_BOX(newAction),0);
   } else if(strcmp(type,"KEY")==0) {
     // add all the Key actions
-    while(ActionTable[i].action!=ACTION_NONE) {
+    for(i=1;i<ACTIONS;i++) {
       if(ActionTable[i].type&MIDI_KEY) {
         gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(newAction),NULL,ActionTable[i].str);
 	if(ActionTable[i].action==thisAction) {
@@ -175,11 +176,10 @@ static void type_changed_cb(GtkWidget *widget, gpointer data) {
 	}
 	j++;
       }
-      i++;
     }
   } else if(strcmp(type,"KNOB/SLIDER")==0) {
     // add all the Knob actions
-    while(ActionTable[i].action!=ACTION_NONE) {
+    for(i=1;i<ACTIONS;i++) {
       if(ActionTable[i].type&MIDI_KNOB) {
         gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(newAction),NULL,ActionTable[i].str);
 	if(ActionTable[i].action==thisAction) {
@@ -187,11 +187,10 @@ static void type_changed_cb(GtkWidget *widget, gpointer data) {
 	}
 	j++;
       }
-      i++;
     }
   } else if(strcmp(type,"WHEEL")==0) {
     // add all the Wheel actions
-    while(ActionTable[i].action!=ACTION_NONE) {
+    for(i=1;i<ACTIONS;i++) {
       if(ActionTable[i].type&MIDI_WHEEL || ActionTable[i].type&MIDI_KNOB) {
         gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(newAction),NULL,ActionTable[i].str);
 	if(ActionTable[i].action==thisAction) {
@@ -199,7 +198,6 @@ static void type_changed_cb(GtkWidget *widget, gpointer data) {
 	}
 	j++;
       }
-      i++;
     }
   }
 }
@@ -253,9 +251,9 @@ static void tree_selection_changed_cb (GtkTreeSelection *selection, gpointer dat
         } else {
           thisType=TYPE_NONE;
         }
-        thisAction=ACTION_NONE;
+        thisAction=NO_ACTION;
         int i=1;
-        while(ActionTable[i].action!=ACTION_NONE) {
+        while(ActionTable[i].action!=NO_ACTION) {
           if(strcmp(ActionTable[i].str,str_action)==0) {
             thisAction=ActionTable[i].action;
             break;
@@ -499,9 +497,9 @@ static void add_cb(GtkButton *widget,gpointer user_data) {
     type=TYPE_NONE;
   }
 
-  action=ACTION_NONE;
+  action=NO_ACTION;
   i=1;
-  while(ActionTable[i].action!=ACTION_NONE) {
+  while(ActionTable[i].action!=NO_ACTION) {
     if(strcmp(ActionTable[i].str,str_action)==0) {
       action=ActionTable[i].action;
       break;
@@ -517,7 +515,7 @@ static void add_cb(GtkButton *widget,gpointer user_data) {
   desc->action = action; // MIDIaction
   desc->type = type; // MIDItype
   desc->event = thisEvent; // MIDevent
-  desc->onoff = action==CWLEFT || action==CWRIGHT;
+  desc->onoff = action==CW_LEFT || action==CW_RIGHT || PTT;
   desc->delay = 0;
   desc->vfl1  = -1;
   desc->vfl2  = -1;
@@ -573,9 +571,9 @@ static void update_cb(GtkButton *widget,gpointer user_data) {
     thisType=TYPE_NONE;
   }
 
-  thisAction=ACTION_NONE;
+  thisAction=NO_ACTION;
   i=1;
-  while(ActionTable[i].action!=ACTION_NONE) {
+  while(ActionTable[i].action!=NO_ACTION) {
     if(strcmp(ActionTable[i].str,str_action)==0) {
       thisAction=ActionTable[i].action;
       break;
@@ -750,7 +748,7 @@ void midi_menu(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),label,col++,row,1,1);
   label=gtk_label_new("Note");
   gtk_grid_attach(GTK_GRID(grid),label,col++,row,1,1);
-  label=gtk_label_new("Type");
+  label=gtk_label_new("Type/Action");
   gtk_grid_attach(GTK_GRID(grid),label,col++,row,1,1);
   label=gtk_label_new("Value");
   gtk_grid_attach(GTK_GRID(grid),label,col++,row,1,1);
@@ -758,27 +756,38 @@ void midi_menu(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),label,col++,row,1,1);
   label=gtk_label_new("Max");
   gtk_grid_attach(GTK_GRID(grid),label,col++,row,1,1);
-  label=gtk_label_new("Action");
-  gtk_grid_attach(GTK_GRID(grid),label,col++,row,1,1);
+  //label=gtk_label_new("Action");
+  //gtk_grid_attach(GTK_GRID(grid),label,col++,row,1,1);
 
 
   row++;
   col=0;
   newEvent=gtk_label_new("");
-  gtk_grid_attach(GTK_GRID(grid),newEvent,col++,row,1,1);
+  gtk_grid_attach(GTK_GRID(grid),newEvent,col,row,1,1);
+  col++;
   newChannel=gtk_label_new("");
-  gtk_grid_attach(GTK_GRID(grid),newChannel,col++,row,1,1);
+  gtk_grid_attach(GTK_GRID(grid),newChannel,col,row,1,1);
+  col++;
   newNote=gtk_label_new("");
-  gtk_grid_attach(GTK_GRID(grid),newNote,col++,row,1,1);
+  gtk_grid_attach(GTK_GRID(grid),newNote,col,row,1,1);
+  col++;
   newType=gtk_combo_box_text_new();
-  gtk_grid_attach(GTK_GRID(grid),newType,col++,row,1,1);
+  gtk_grid_attach(GTK_GRID(grid),newType,col,row,1,1);
+  col++;
   g_signal_connect(newType,"changed",G_CALLBACK(type_changed_cb),NULL);
   newVal=gtk_label_new("");
-  gtk_grid_attach(GTK_GRID(grid),newVal,col++,row,1,1);
+  col++;
+  gtk_grid_attach(GTK_GRID(grid),newVal,col,row,1,1);
   newMin=gtk_label_new("");
-  gtk_grid_attach(GTK_GRID(grid),newMin,col++,row,1,1);
+  col++;
+  gtk_grid_attach(GTK_GRID(grid),newMin,col,row,1,1);
   newMax=gtk_label_new("");
-  gtk_grid_attach(GTK_GRID(grid),newMax,col++,row,1,1);
+  col++;
+  gtk_grid_attach(GTK_GRID(grid),newMax,col,row,1,1);
+
+  row++;
+  col=col-4;
+
   newAction=gtk_combo_box_text_new();
   gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(newAction),5);
   gtk_grid_attach(GTK_GRID(grid),newAction,col++,row,1,1);
@@ -895,7 +904,7 @@ static int update(void *data) {
       if(thisEvent==MIDI_PITCH || thisEvent==MIDI_NOTE) {
 	i=1;
 	j=0;
-	while(ActionTable[i].action!=ACTION_NONE) {
+	while(ActionTable[i].action!=NO_ACTION) {
           if(ActionTable[i].type&MIDI_KEY) {
             gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(newAction),NULL,ActionTable[i].str);
             if(ActionTable[i].action==thisAction) {
@@ -1026,7 +1035,7 @@ void NewMidiConfigureEvent(enum MIDIevent event, int channel, int note, int val)
     thisMin=val;
     thisMax=val;
     thisType=TYPE_NONE;
-    thisAction=ACTION_NONE;
+    thisAction=NO_ACTION;
 
     // search tree to see if it is existing event
     valid=gtk_tree_model_get_iter_first(model,&iter);
@@ -1065,9 +1074,9 @@ void NewMidiConfigureEvent(enum MIDIevent event, int channel, int note, int val)
           } else {
             thisType=TYPE_NONE;
           }
-          thisAction=ACTION_NONE;
+          thisAction=NO_ACTION;
           int i=1;
-          while(ActionTable[i].action!=ACTION_NONE) {
+          while(ActionTable[i].action!=NO_ACTION) {
             if(strcmp(ActionTable[i].str,str_action)==0) {
               thisAction=ActionTable[i].action;
               break;
@@ -1196,10 +1205,10 @@ void midi_restore_state() {
 	  }
           sprintf(name,"midi[%d].channel[%d].action",i,channel);
           value=getProperty(name);
-	  action=ACTION_NONE;
+	  action=NO_ACTION;
           if(value) {
 	    int j=1;
-	    while(ActionTable[j].type!=ACTION_NONE) {
+	    while(ActionTable[j].type!=NO_ACTION) {
               if(strcmp(value,ActionTable[j].str)==0) {
                 action=ActionTable[j].action;
 		break;
diff --git a/radio.c b/radio.c
index 194a038..2b9e1c4 100644
--- a/radio.c
+++ b/radio.c
@@ -2153,7 +2153,6 @@ g_print("radioRestoreState: %s\n",property_path);
 #ifdef  SOAPYSDR
     if(device==SOAPYSDR_USB_DEVICE) {
       value=getProperty("radio.adc[0].agc");
-      if(value) soapy_protocol_set_automatic_gain(atoi(value));
     }
 #endif
 
@@ -2192,7 +2191,6 @@ g_print("radioRestoreState: %s\n",property_path);
 #ifdef  SOAPYSDR
       if(device==SOAPYSDR_USB_DEVICE) {
         value=getProperty("radio.adc[1].agc");
-        if(value) soapy_protocol_set_automatic_gain(atoi(value));
       }
 #endif
 
diff --git a/receiver.c b/receiver.c
index c27749b..a5d2ab4 100644
--- a/receiver.c
+++ b/receiver.c
@@ -1187,23 +1187,23 @@ void receiver_change_sample_rate(RECEIVER *rx,int sample_rate) {
 
 g_print("%s: id=%d rate=%d scale=%d buffer_size=%d output_samples=%d\n",__FUNCTION__,rx->id,sample_rate,scale,rx->buffer_size,rx->output_samples);
 #ifdef PURESIGNAL
-  if(can_transmit && transmitter->puresignal) {
-  if (rx->id == PS_RX_FEEDBACK) {
-    if (protocol == ORIGINAL_PROTOCOL) {
-      rx->pixels = 2* scale * rx->width;
-    } else {
-      // We should never arrive here, since the sample rate of the
-      // PS feedback receiver is fixed.
-      rx->pixels = 8 * rx->width;
+  if(can_transmit/* && transmitter->puresignal*/) {
+    if (rx->id == PS_RX_FEEDBACK) {
+      if (protocol == ORIGINAL_PROTOCOL) {
+        rx->pixels = 2* scale * rx->width;
+      } else {
+        // We should never arrive here, since the sample rate of the
+        // PS feedback receiver is fixed.
+        rx->pixels = 8 * rx->width;
+      }
+      g_free(rx->pixel_samples);
+      rx->pixel_samples=g_new(float,rx->pixels);
+      init_analyzer(rx);
+      g_print("%s: PS FEEDBACK: id=%d rate=%d buffer_size=%d output_samples=%d\n",
+                     __FUNCTION__,rx->id, rx->sample_rate, rx->buffer_size, rx->output_samples);
+      g_mutex_unlock(&rx->mutex);
+      return;
     }
-    g_free(rx->pixel_samples);
-    rx->pixel_samples=g_new(float,rx->pixels);
-    init_analyzer(rx);
-    g_print("%s: PS FEEDBACK: id=%d rate=%d buffer_size=%d output_samples=%d\n",
-                   __FUNCTION__,rx->id, rx->sample_rate, rx->buffer_size, rx->output_samples);
-    g_mutex_unlock(&rx->mutex);
-    return;
-  }
   }
 #endif
   if (rx->audio_output_buffer != NULL) {
diff --git a/rx_menu.c b/rx_menu.c
index 394afc6..8fade9d 100644
--- a/rx_menu.c
+++ b/rx_menu.c
@@ -197,9 +197,6 @@ void rx_menu(GtkWidget *parent) {
 
   GtkWidget *grid=gtk_grid_new();
   gtk_grid_set_column_spacing (GTK_GRID(grid),10);
-  //gtk_grid_set_row_spacing (GTK_GRID(grid),10);
-  //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-  //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
 
   GtkWidget *close_b=gtk_button_new_with_label("Close");
   g_signal_connect (close_b, "button_press_event", G_CALLBACK(close_cb), NULL);
@@ -382,8 +379,11 @@ void rx_menu(GtkWidget *parent) {
     gtk_grid_attach(GTK_GRID(grid),output,x,++row,1,1);
     g_signal_connect(output,"changed",G_CALLBACK(local_output_changed_cb),NULL);
 
+    /*
     row=0;
     x++;
+    */
+    row++;
 
     GtkWidget *stereo_b=gtk_radio_button_new_with_label(NULL,"Stereo");
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (stereo_b), active_receiver->audio_channel==STEREO);
diff --git a/sliders.c b/sliders.c
index b8ab243..60bcdcb 100644
--- a/sliders.c
+++ b/sliders.c
@@ -59,6 +59,7 @@
 #ifdef CLIENT_SERVER
 #include "client_server.h"
 #endif
+#include "actions.h"
 
 static int width;
 static int height;
@@ -349,7 +350,6 @@ void update_af_gain() {
 }
 
 void set_af_gain(int rx,double value) {
-  g_print("%s\n",__FUNCTION__);
   receiver[rx]->volume=value;
   SetRXAPanelGain1 (receiver[rx]->id, receiver[rx]->volume);
   if(display_sliders) {
@@ -449,7 +449,7 @@ void set_rf_gain(int rx,double value) {
 
 void set_filter_width(int rx,int width) {
   g_print("%s\n",__FUNCTION__);
-    if(scale_status!=FILTER_WIDTH || scale_rx!=rx) {
+    if(scale_status!=IF_WIDTH || scale_rx!=rx) {
       if(scale_status!=NO_FUNCTION) {
         g_source_remove(scale_timer);
         gtk_widget_destroy(scale_dialog);
@@ -457,7 +457,7 @@ void set_filter_width(int rx,int width) {
       }
     }
     if(scale_status==NO_FUNCTION) {
-      scale_status=FILTER_WIDTH;
+      scale_status=IF_WIDTH;
       scale_rx=rx;
       char title[64];
       sprintf(title,"Filter Width RX %d (Hz)",rx);
@@ -480,7 +480,7 @@ void set_filter_width(int rx,int width) {
 
 void set_filter_shift(int rx,int shift) {
   g_print("%s\n",__FUNCTION__);
-    if(scale_status!=FILTER_SHIFT || scale_rx!=rx) {
+    if(scale_status!=IF_SHIFT || scale_rx!=rx) {
       if(scale_status!=NO_FUNCTION) {
         g_source_remove(scale_timer);
         gtk_widget_destroy(scale_dialog);
@@ -488,7 +488,7 @@ void set_filter_shift(int rx,int shift) {
       }
     }
     if(scale_status==NO_FUNCTION) {
-      scale_status=FILTER_SHIFT;
+      scale_status=IF_SHIFT;
       scale_rx=rx;
       char title[64];
       sprintf(title,"Filter SHIFT RX %d (Hz)",rx);
@@ -724,7 +724,7 @@ void set_compression(TRANSMITTER* tx) {
     gtk_range_set_value (GTK_RANGE(comp_scale),tx->compressor_level);
   } else {
 #endif
-    if(scale_status!=COMP) {
+    if(scale_status!=COMPRESSION) {
       if(scale_status!=NO_FUNCTION) {
         g_source_remove(scale_timer);
         gtk_widget_destroy(scale_dialog);
@@ -732,7 +732,7 @@ void set_compression(TRANSMITTER* tx) {
       }
     }
     if(scale_status==NO_FUNCTION) {
-      scale_status=COMP;
+      scale_status=COMPRESSION;
       scale_dialog=gtk_dialog_new_with_buttons("COMP",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
       GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
       comp_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 20.0, 1.00);
@@ -755,7 +755,7 @@ void set_compression(TRANSMITTER* tx) {
 
 void show_diversity_gain() {
   g_print("%s\n",__FUNCTION__);
-    if(scale_status!=DIVERSITY_GAIN) {
+    if(scale_status!=DIV_GAIN) {
       if(scale_status!=NO_FUNCTION) {
         g_source_remove(scale_timer);
         gtk_widget_destroy(scale_dialog);
@@ -763,7 +763,7 @@ void show_diversity_gain() {
       }
     }
     if(scale_status==NO_FUNCTION) {
-      scale_status=DIVERSITY_GAIN;
+      scale_status=DIV_GAIN;
       scale_dialog=gtk_dialog_new_with_buttons("Diversity Gain",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
       GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
       diversity_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-27.0, 27.0, 0.01);
@@ -783,7 +783,7 @@ void show_diversity_gain() {
 
 void show_diversity_phase() {
   g_print("%s\n",__FUNCTION__);
-    if(scale_status!=DIVERSITY_PHASE) {
+    if(scale_status!=DIV_PHASE) {
       if(scale_status!=NO_FUNCTION) {
         g_source_remove(scale_timer);
         gtk_widget_destroy(scale_dialog);
@@ -791,7 +791,7 @@ void show_diversity_phase() {
       }
     }
     if(scale_status==NO_FUNCTION) {
-      scale_status=DIVERSITY_PHASE;
+      scale_status=DIV_PHASE;
       scale_dialog=gtk_dialog_new_with_buttons("Diversity Phase",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
       GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
       diversity_phase_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, -180.0, 180.0, 0.1);
diff --git a/sliders.h b/sliders.h
index 7c981c7..c532bdb 100644
--- a/sliders.h
+++ b/sliders.h
@@ -24,21 +24,21 @@
 
 enum {
   NO_FUNCTION=0,
-  AF_GAIN,
-  RF_GAIN,
-  MIC_GAIN,
-  LINEIN_GAIN,
-  AGC_GAIN,
-  DRIVE,
-  ATTENUATION,
-  SQUELCH,
-  COMP,
-  FILTER_WIDTH,
-  FILTER_SHIFT,
-  DIVERSITY_GAIN,
-  DIVERSITY_PHASE,
-  ZOOM,
-  PAN
+  SLIDER_AF_GAIN,
+  SLIDER_RF_GAIN,
+  SLIDER_MIC_GAIN,
+  SLIDER_LINEIN_GAIN,
+  SLIDER_AGC_GAIN,
+  SLIDER_DRIVE,
+  SLIDER_ATTENUATION,
+  SLIDER_SQUELCH,
+  SLIDER_COMP,
+  SLIDER_FILTER_WIDTH,
+  SLIDER_FILTER_SHIFT,
+  SLIDER_DIVERSITY_GAIN,
+  SLIDER_DIVERSITY_PHASE,
+  SLIDER_ZOOM,
+  SLIDER_PAN
 };
 
 extern gint scale_timer;
diff --git a/soapy_discovery.c b/soapy_discovery.c
index a8a026e..c459ac0 100644
--- a/soapy_discovery.c
+++ b/soapy_discovery.c
@@ -118,42 +118,18 @@ static void get_info(char *driver) {
   }
 
 
-  int sample_rate=0;
+  int sample_rate=768000;
   SoapySDRRange *rx_rates=SoapySDRDevice_getSampleRateRange(sdr, SOAPY_SDR_RX, 0, &rx_rates_length);
   fprintf(stderr,"Rx sample rates: ");
   for (size_t i = 0; i < rx_rates_length; i++) {
     fprintf(stderr,"%f -> %f (%f),", rx_rates[i].minimum, rx_rates[i].maximum, rx_rates[i].minimum/48000.0);
-    if(sample_rate==0) {
-      if(rx_rates[i].minimum==rx_rates[i].maximum) {
-        if(((int)rx_rates[i].minimum%48000)==0) {
-          sample_rate=(int)rx_rates[i].minimum;
-        }
-      } else {
-        if((384000.0>=rx_rates[i].minimum) && (384000<=(int)rx_rates[i].maximum)) {
-          sample_rate=384000;
-        }
-        if((768000.0>=rx_rates[i].minimum) && (768000<=(int)rx_rates[i].maximum)) {
-          sample_rate=768000;
-        }
-      }
-    }
   }
-  fprintf(stderr,"\n");
-  free(rx_rates);
-
-  if(strcmp(driver,"lime")==0) {
-    sample_rate=768000;
-  } else if(strcmp(driver,"plutosdr")==0) {
-    sample_rate=768000;
-  } else if(strcmp(driver,"rtlsdr")==0) {
+  if(strcmp(driver,"rtlsdr")==0) {
     sample_rate=1536000;
-  } else if(strcmp(driver,"sdrplay")==0) {
-    //sample_rate=96000;
-    sample_rate=768000;
-  } else {
-    sample_rate=1048576;
   }
-
+  
+  fprintf(stderr,"\n");
+  free(rx_rates);
   fprintf(stderr,"sample_rate selected %d\n",sample_rate);
 
   if(tx_channels>0) {
diff --git a/switch_menu.c b/switch_menu.c
index 43ea0ee..34fbf00 100644
--- a/switch_menu.c
+++ b/switch_menu.c
@@ -70,17 +70,15 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_d
 }
 
 void switch_page_cb(GtkNotebook *notebook,GtkWidget *page,guint page_num,gpointer user_data) {
-  g_print("%s: page %d\n",__FUNCTION__,page_num);
   temp_switches=switches_controller1[page_num];
 }
 
 static void switch_select_cb(GtkWidget *widget, gpointer data) {
   char text[128];
   CHOICE *choice=(CHOICE *)data;
-g_print("%s: temp_switches=%p\n",__FUNCTION__,temp_switches);
   temp_switches[choice->sw].switch_function=choice->action;
   GtkWidget *label=gtk_bin_get_child(GTK_BIN(choice->button));
-  sprintf(text,"<span size=\"smaller\">%s</span>",sw_string[choice->action]);
+  sprintf(text,"<span size=\"smaller\">%s</span>",ActionTable[choice->action].str);
   gtk_label_set_markup (GTK_LABEL(label), text);
   update_toolbar_labels();
 }
@@ -90,14 +88,16 @@ static gboolean switch_cb(GtkWidget *widget, GdkEvent *event, gpointer data) {
   int i;
 
   GtkWidget *menu=gtk_menu_new();
-  for(i=0;i<SWITCH_ACTIONS;i++) {
-    GtkWidget *menu_item=gtk_menu_item_new_with_label(sw_string[i]);
-    CHOICE *choice=g_new0(CHOICE,1);
-    choice->sw=sw;
-    choice->action=i;
-    choice->button=widget;
-    g_signal_connect(menu_item,"activate",G_CALLBACK(switch_select_cb),choice);
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
+  for(i=0;i<ACTIONS;i++) {
+    if(ActionTable[i].type | CONTROLLER_SWITCH) {
+      GtkWidget *menu_item=gtk_menu_item_new_with_label(ActionTable[i].str);
+      CHOICE *choice=g_new0(CHOICE,1);
+      choice->sw=sw;
+      choice->action=i;
+      choice->button=widget;
+      g_signal_connect(menu_item,"activate",G_CALLBACK(switch_select_cb),choice);
+      gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
+    }
   }
   gtk_widget_show_all(menu);
 #if GTK_CHECK_VERSION(3,22,0)
@@ -111,10 +111,6 @@ static gboolean switch_cb(GtkWidget *widget, GdkEvent *event, gpointer data) {
 }
 
 static void response_event(GtkWidget *dialog,gint id,gpointer user_data) {
-  g_print("%s: id=%d\n",__FUNCTION__,id);
-  if(id==GTK_RESPONSE_ACCEPT) {
-    g_print("%s: ACCEPT\n",__FUNCTION__);
-  }
   gtk_widget_destroy(dialog);
   dialog=NULL;
   active_menu=NO_MENU;
@@ -130,7 +126,6 @@ void switch_menu(GtkWidget *parent) {
   GtkWidget *widget;
   gint function=0;
 
-g_print("%s: switches_no_controller=%p switches_controller1=%p switches_controller2_v1=%p switches_controller2_v2=%p\n",__FUNCTION__,&switches_no_controller,&switches_controller1,&switches_controller2_v1,&switches_controller2_v2);
 
   dialog=gtk_dialog_new_with_buttons("piHPSDR - Switch Actions",GTK_WINDOW(parent),GTK_DIALOG_DESTROY_WITH_PARENT,("OK"),GTK_RESPONSE_ACCEPT,NULL);
   g_signal_connect (dialog, "response", G_CALLBACK (response_event), NULL);
@@ -146,8 +141,8 @@ g_print("%s: switches_no_controller=%p switches_controller1=%p switches_controll
 next_function_set:
 
   grid=gtk_grid_new();
-  gtk_grid_set_column_homogeneous(GTK_GRID(grid),FALSE);
-  gtk_grid_set_row_homogeneous(GTK_GRID(grid),FALSE);
+  gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+  gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
   gtk_grid_set_column_spacing (GTK_GRID(grid),2);
   gtk_grid_set_row_spacing (GTK_GRID(grid),2);
 
@@ -175,81 +170,80 @@ next_function_set:
       break;
   }
 
-  g_print("%s: temp_switches=%p\n",temp_switches);
 
   int original_row=row;
 
   if(controller==CONTROLLER2_V1 || controller==CONTROLLER2_V2) {
     row=row+5;
     col=0;
-    widget=gtk_button_new_with_label(sw_string[temp_switches[0].switch_function]);
+    widget=gtk_button_new_with_label(ActionTable[temp_switches[0].switch_function].str);
     g_signal_connect(widget,"button_press_event",G_CALLBACK(switch_cb),GINT_TO_POINTER(0));
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
     col++;
-    widget=gtk_button_new_with_label(sw_string[temp_switches[1].switch_function]);
+    widget=gtk_button_new_with_label(ActionTable[temp_switches[1].switch_function].str);
     g_signal_connect(widget,"button_press_event",G_CALLBACK(switch_cb),GINT_TO_POINTER(1));
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
     col++;
-    widget=gtk_button_new_with_label(sw_string[temp_switches[2].switch_function]);
+    widget=gtk_button_new_with_label(ActionTable[temp_switches[2].switch_function].str);
     g_signal_connect(widget,"button_press_event",G_CALLBACK(switch_cb),GINT_TO_POINTER(2));
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
     col++;
-    widget=gtk_button_new_with_label(sw_string[temp_switches[3].switch_function]);
+    widget=gtk_button_new_with_label(ActionTable[temp_switches[3].switch_function].str);
     g_signal_connect(widget,"button_press_event",G_CALLBACK(switch_cb),GINT_TO_POINTER(3));
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
     col++;
-    widget=gtk_button_new_with_label(sw_string[temp_switches[4].switch_function]);
+    widget=gtk_button_new_with_label(ActionTable[temp_switches[4].switch_function].str);
     g_signal_connect(widget,"button_press_event",G_CALLBACK(switch_cb),GINT_TO_POINTER(4));
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
     col++;
-    widget=gtk_button_new_with_label(sw_string[temp_switches[5].switch_function]);
+    widget=gtk_button_new_with_label(ActionTable[temp_switches[5].switch_function].str);
     g_signal_connect(widget,"button_press_event",G_CALLBACK(switch_cb),GINT_TO_POINTER(5));
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
     col++;
-    widget=gtk_button_new_with_label(sw_string[temp_switches[6].switch_function]);
+    widget=gtk_button_new_with_label(ActionTable[temp_switches[6].switch_function].str);
     g_signal_connect(widget,"button_press_event",G_CALLBACK(switch_cb),GINT_TO_POINTER(6));
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
     col++;
 
     row=original_row;
     col=8;
-    widget=gtk_button_new_with_label(sw_string[temp_switches[7].switch_function]);
+    widget=gtk_button_new_with_label(ActionTable[temp_switches[7].switch_function].str);
     g_signal_connect(widget,"button_press_event",G_CALLBACK(switch_cb),GINT_TO_POINTER(7));
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
     row++;
     col=7;
-    widget=gtk_button_new_with_label(sw_string[temp_switches[8].switch_function]);
+    widget=gtk_button_new_with_label(ActionTable[temp_switches[8].switch_function].str);
     g_signal_connect(widget,"button_press_event",G_CALLBACK(switch_cb),GINT_TO_POINTER(8));
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
     col++;
-    widget=gtk_button_new_with_label(sw_string[temp_switches[9].switch_function]);
+    widget=gtk_button_new_with_label(ActionTable[temp_switches[9].switch_function].str);
     g_signal_connect(widget,"button_press_event",G_CALLBACK(switch_cb),GINT_TO_POINTER(9));
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
     row++;
     col=7;
-    widget=gtk_button_new_with_label(sw_string[temp_switches[10].switch_function]);
+    widget=gtk_button_new_with_label(ActionTable[temp_switches[10].switch_function].str);
     g_signal_connect(widget,"button_press_event",G_CALLBACK(switch_cb),GINT_TO_POINTER(10));
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
     col++;
-    widget=gtk_button_new_with_label(sw_string[temp_switches[11].switch_function]);
+    widget=gtk_button_new_with_label(ActionTable[temp_switches[11].switch_function].str);
     g_signal_connect(widget,"button_press_event",G_CALLBACK(switch_cb),GINT_TO_POINTER(11));
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
     row++;
     col=7;
-    widget=gtk_button_new_with_label(sw_string[temp_switches[12].switch_function]);
+    widget=gtk_button_new_with_label(ActionTable[temp_switches[12].switch_function].str);
     g_signal_connect(widget,"button_press_event",G_CALLBACK(switch_cb),GINT_TO_POINTER(12));
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
     col++;
-    widget=gtk_button_new_with_label(sw_string[temp_switches[13].switch_function]);
+    widget=gtk_button_new_with_label(ActionTable[temp_switches[13].switch_function].str);
     g_signal_connect(widget,"button_press_event",G_CALLBACK(switch_cb),GINT_TO_POINTER(13));
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
     row++;
     col=7;
-    widget=gtk_button_new_with_label(sw_string[temp_switches[14].switch_function]);
+    widget=gtk_button_new_with_label(ActionTable[temp_switches[14].switch_function].str);
     g_signal_connect(widget,"button_press_event",G_CALLBACK(switch_cb),GINT_TO_POINTER(14));
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
     col++;
-    widget=gtk_button_new_with_label(sw_string[temp_switches[15].switch_function]);
+    widget=gtk_button_new_with_label(ActionTable[temp_switches[15].switch_function].str);
     g_signal_connect(widget,"button_press_event",G_CALLBACK(switch_cb),GINT_TO_POINTER(15));
     gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
 
@@ -258,11 +252,12 @@ next_function_set:
     int start_row=row;
     for(int i=0;i<max_switches;i++) {
       if((controller==NO_CONTROLLER || controller==CONTROLLER1) && (temp_switches[i].switch_function==FUNCTION)) {
-        widget=gtk_label_new(NULL);
-        g_sprintf(label,"<b>%s</b>",sw_string[temp_switches[i].switch_function]);
-        gtk_label_set_markup (GTK_LABEL(widget), label);
+        widget=gtk_button_new_with_label(ActionTable[temp_switches[i].switch_function].str);
+        //widget=gtk_label_new(NULL);
+        //g_sprintf(label,"<b>%s</b>",ActionTable[temp_switches[i].switch_function].str);
+        //gtk_label_set_markup (GTK_LABEL(widget), label);
       } else {
-        widget=gtk_button_new_with_label(sw_string[temp_switches[i].switch_function]);
+        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));
       }
       gtk_grid_attach(GTK_GRID(grid),widget,col,row,1,1);
diff --git a/toolbar.c b/toolbar.c
index 7cdd157..1c7c787 100644
--- a/toolbar.c
+++ b/toolbar.c
@@ -103,14 +103,14 @@ static gboolean xit_timer_cb(gpointer data) {
 }
 
 void update_toolbar_labels() {
-  gtk_button_set_label(GTK_BUTTON(sim_mox),sw_cap_string[toolbar_switches[0].switch_function]);
-  gtk_button_set_label(GTK_BUTTON(sim_s1),sw_cap_string[toolbar_switches[1].switch_function]);
-  gtk_button_set_label(GTK_BUTTON(sim_s2),sw_cap_string[toolbar_switches[2].switch_function]);
-  gtk_button_set_label(GTK_BUTTON(sim_s3),sw_cap_string[toolbar_switches[3].switch_function]);
-  gtk_button_set_label(GTK_BUTTON(sim_s4),sw_cap_string[toolbar_switches[4].switch_function]);
-  gtk_button_set_label(GTK_BUTTON(sim_s5),sw_cap_string[toolbar_switches[5].switch_function]);
-  gtk_button_set_label(GTK_BUTTON(sim_s6),sw_cap_string[toolbar_switches[6].switch_function]);
-  gtk_button_set_label(GTK_BUTTON(sim_function),sw_cap_string[toolbar_switches[7].switch_function]);
+  gtk_button_set_label(GTK_BUTTON(sim_mox),ActionTable[toolbar_switches[0].switch_function].button_str);
+  gtk_button_set_label(GTK_BUTTON(sim_s1),ActionTable[toolbar_switches[1].switch_function].button_str);
+  gtk_button_set_label(GTK_BUTTON(sim_s2),ActionTable[toolbar_switches[2].switch_function].button_str);
+  gtk_button_set_label(GTK_BUTTON(sim_s3),ActionTable[toolbar_switches[3].switch_function].button_str);
+  gtk_button_set_label(GTK_BUTTON(sim_s4),ActionTable[toolbar_switches[4].switch_function].button_str);
+  gtk_button_set_label(GTK_BUTTON(sim_s5),ActionTable[toolbar_switches[5].switch_function].button_str);
+  gtk_button_set_label(GTK_BUTTON(sim_s6),ActionTable[toolbar_switches[6].switch_function].button_str);
+  gtk_button_set_label(GTK_BUTTON(sim_function),ActionTable[toolbar_switches[7].switch_function].button_str);
 }
 
 static void close_cb(GtkWidget *widget, gpointer data) {
@@ -502,18 +502,18 @@ void tune_update(int state) {
 
 void switch_pressed_cb(GtkWidget *widget, gpointer data) {
   gint i=GPOINTER_TO_INT(data);
-  SWITCH_ACTION *a=g_new(SWITCH_ACTION,1);
+  PROCESS_ACTION *a=g_new(PROCESS_ACTION,1);
   a->action=toolbar_switches[i].switch_function;
-  a->state=PRESSED;
-  g_idle_add(switch_action,a);
+  a->mode=PRESSED;
+  g_idle_add(process_action,a);
 }
 
 void switch_released_cb(GtkWidget *widget, gpointer data) {
   gint i=GPOINTER_TO_INT(data);
-  SWITCH_ACTION *a=g_new(SWITCH_ACTION,1);
+  PROCESS_ACTION *a=g_new(PROCESS_ACTION,1);
   a->action=toolbar_switches[i].switch_function;
-  a->state=RELEASED;
-  g_idle_add(switch_action,a);
+  a->mode=RELEASED;
+  g_idle_add(process_action,a);
 }
 
 GtkWidget *toolbar_init(int my_width, int my_height, GtkWidget* parent) {
@@ -539,43 +539,43 @@ GtkWidget *toolbar_init(int my_width, int my_height, GtkWidget* parent) {
     gtk_widget_set_size_request (toolbar, width, height);
     gtk_grid_set_column_homogeneous(GTK_GRID(toolbar),TRUE);
 
-    sim_mox=gtk_button_new_with_label(sw_cap_string[toolbar_switches[0].switch_function]);
+    sim_mox=gtk_button_new_with_label(ActionTable[toolbar_switches[0].switch_function].button_str);
     g_signal_connect(G_OBJECT(sim_mox),"pressed",G_CALLBACK(switch_pressed_cb),GINT_TO_POINTER(0));
     gtk_grid_attach(GTK_GRID(toolbar),sim_mox,0,0,4,1);
 
-    sim_s1=gtk_button_new_with_label(sw_cap_string[toolbar_switches[1].switch_function]);
+    sim_s1=gtk_button_new_with_label(ActionTable[toolbar_switches[1].switch_function].button_str);
     gtk_widget_set_size_request (sim_s1, button_width, 0);
     g_signal_connect(G_OBJECT(sim_s1),"pressed",G_CALLBACK(switch_pressed_cb),GINT_TO_POINTER(1));
     g_signal_connect(G_OBJECT(sim_s1),"released",G_CALLBACK(switch_released_cb),GINT_TO_POINTER(1));
     gtk_grid_attach(GTK_GRID(toolbar),sim_s1,4,0,4,1);
 
-    sim_s2=gtk_button_new_with_label(sw_cap_string[toolbar_switches[2].switch_function]);
+    sim_s2=gtk_button_new_with_label(ActionTable[toolbar_switches[2].switch_function].button_str);
     gtk_widget_set_size_request (sim_s2, button_width, 0);
     g_signal_connect(G_OBJECT(sim_s2),"pressed",G_CALLBACK(switch_pressed_cb),GINT_TO_POINTER(2));
     g_signal_connect(G_OBJECT(sim_s2),"released",G_CALLBACK(switch_released_cb),GINT_TO_POINTER(2));
     gtk_grid_attach(GTK_GRID(toolbar),sim_s2,8,0,4,1);
 
-    sim_s3=gtk_button_new_with_label(sw_cap_string[toolbar_switches[3].switch_function]);
+    sim_s3=gtk_button_new_with_label(ActionTable[toolbar_switches[3].switch_function].button_str);
     g_signal_connect(G_OBJECT(sim_s3),"pressed",G_CALLBACK(switch_pressed_cb),GINT_TO_POINTER(3));
     g_signal_connect(G_OBJECT(sim_s3),"released",G_CALLBACK(switch_released_cb),GINT_TO_POINTER(3));
     gtk_grid_attach(GTK_GRID(toolbar),sim_s3,12,0,4,1);
 
-    sim_s4=gtk_button_new_with_label(sw_cap_string[toolbar_switches[4].switch_function]);
+    sim_s4=gtk_button_new_with_label(ActionTable[toolbar_switches[4].switch_function].button_str);
     g_signal_connect(G_OBJECT(sim_s4),"pressed",G_CALLBACK(switch_pressed_cb),GINT_TO_POINTER(4));
     g_signal_connect(G_OBJECT(sim_s4),"released",G_CALLBACK(switch_released_cb),GINT_TO_POINTER(4));
     gtk_grid_attach(GTK_GRID(toolbar),sim_s4,16,0,4,1);
 
-    sim_s5=gtk_button_new_with_label(sw_cap_string[toolbar_switches[5].switch_function]);
+    sim_s5=gtk_button_new_with_label(ActionTable[toolbar_switches[5].switch_function].button_str);
     g_signal_connect(G_OBJECT(sim_s5),"pressed",G_CALLBACK(switch_pressed_cb),GINT_TO_POINTER(5));
     g_signal_connect(G_OBJECT(sim_s5),"released",G_CALLBACK(switch_released_cb),GINT_TO_POINTER(5));
     gtk_grid_attach(GTK_GRID(toolbar),sim_s5,20,0,4,1);
 
-    sim_s6=gtk_button_new_with_label(sw_cap_string[toolbar_switches[6].switch_function]);
+    sim_s6=gtk_button_new_with_label(ActionTable[toolbar_switches[6].switch_function].button_str);
     g_signal_connect(G_OBJECT(sim_s6),"pressed",G_CALLBACK(switch_pressed_cb),GINT_TO_POINTER(6));
     g_signal_connect(G_OBJECT(sim_s6),"released",G_CALLBACK(switch_released_cb),GINT_TO_POINTER(6));
     gtk_grid_attach(GTK_GRID(toolbar),sim_s6,24,0,4,1);
 
-    sim_function=gtk_button_new_with_label(sw_cap_string[toolbar_switches[7].switch_function]);
+    sim_function=gtk_button_new_with_label(ActionTable[toolbar_switches[7].switch_function].button_str);
     g_signal_connect(G_OBJECT(sim_function),"pressed",G_CALLBACK(switch_pressed_cb),GINT_TO_POINTER(7));
     gtk_grid_attach(GTK_GRID(toolbar),sim_function,28,0,4,1);
 
diff --git a/zoompan.c b/zoompan.c
index 91bda57..29eb754 100644
--- a/zoompan.c
+++ b/zoompan.c
@@ -32,6 +32,7 @@
 #ifdef CLIENT_SERVER
 #include "client_server.h"
 #endif
+#include "actions.h"
 
 static int width;
 static int height;
-- 
2.45.2