]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
Rewrite of rigctl (CAT commands)
authorJohn Melton G0ORX <john.d.melton@googlemail.com>
Wed, 20 May 2020 07:42:14 +0000 (08:42 +0100)
committerJohn Melton G0ORX <john.d.melton@googlemail.com>
Wed, 20 May 2020 07:42:14 +0000 (08:42 +0100)
41 files changed:
agc_menu.c
band_menu.c
client_server.c [new file with mode: 0644]
client_server.h [new file with mode: 0644]
discovered.h
discovery.c
exit_menu.c
ext.c
ext.h
freqent_menu.c
gpio.c
main.c
new_menu.c
new_menu.h
new_protocol.c
noise_menu.c
noise_menu.h
pa_menu.h
radio.c
radio.h
radio_menu.c
radio_menu.h
receiver.c
receiver.h
rigctl.c
rigctl_menu.c
rigctl_menu.h
rx_panadapter.c
server_menu.c [new file with mode: 0644]
server_menu.h [new file with mode: 0644]
sliders.c
soapy_discovery.c
soapy_protocol.c
toolbar.c
update.c
vfo.c
vfo.h
vfo_menu.c
waterfall.c
zoompan.c
zoompan.h

index bf8ec11aa4e25e15d9b1b77e8d07f4816420cf0c..56702189b2298c1e9a53b7ec22c3e5ab8e249a88 100644 (file)
@@ -59,8 +59,16 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_d
 static void agc_select_cb (GtkToggleButton *widget, gpointer        data) {
   if(gtk_toggle_button_get_active(widget)) {
     active_receiver->agc=GPOINTER_TO_INT(data);
-    set_agc(active_receiver, active_receiver->agc);
-    g_idle_add(ext_vfo_update, NULL);
+#ifdef CLIENT_SERVER
+    if(radio_is_remote) {
+      send_agc(client_socket,active_receiver->id,active_receiver->agc);
+    } else {
+#endif
+      set_agc(active_receiver, active_receiver->agc);
+      g_idle_add(ext_vfo_update, NULL);
+#ifdef CLIENT_SERVER
+    }
+#endif
   }
 }
 
index bc79bed3018aa6982df92982a0a2e4be9c6f5776..30c70b74a87139616ef49620c20e2554a1219289 100644 (file)
@@ -32,6 +32,7 @@
 #include "receiver.h"
 #include "vfo.h"
 #include "button_text.h"
+#include "client_server.h"
 
 static GtkWidget *parent_window=NULL;
 
@@ -62,7 +63,15 @@ gboolean band_select_cb (GtkWidget *widget, gpointer        data) {
   set_button_text_color(last_band,"black");
   last_band=widget;
   set_button_text_color(last_band,"orange");
-  vfo_band_changed(b);
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_band(client_socket,active_receiver->id,b);
+  } else {
+#endif
+    vfo_band_changed(active_receiver->id,b);
+#ifdef CLIENT_SERVER
+  }
+#endif
   return FALSE;
 }
 
@@ -103,6 +112,7 @@ void band_menu(GtkWidget *parent) {
   long long frequency_min=radio->frequency_min;
   long long frequency_max=radio->frequency_max;
 
+g_print("band_menu: min=%lld max=%lld\n",frequency_min,frequency_max);
   j=0;
   for(i=0;i<BANDS+XVTRS;i++) {
     band=(BAND*)band_get_band(i);
diff --git a/client_server.c b/client_server.c
new file mode 100644 (file)
index 0000000..5692538
--- /dev/null
@@ -0,0 +1,2502 @@
+/* Copyright (C)
+* 2020 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <string.h>
+#include <strings.h>
+#ifndef __APPLE__
+#include <endian.h>
+#endif
+#include <semaphore.h>
+
+#include "discovered.h"
+#include "adc.h"
+#include "dac.h"
+#include "receiver.h"
+#include "transmitter.h"
+#include "radio.h"
+#include "main.h"
+#include "vfo.h"
+#ifdef CLIENT_SERVER
+#include "client_server.h"
+#endif
+#include "ext.h"
+#include "audio.h"
+
+#define DISCOVERY_PORT 4992
+#define LISTEN_PORT 50000
+
+gint listen_port=LISTEN_PORT;
+
+REMOTE_CLIENT *clients=NULL;
+
+GMutex client_mutex;
+
+#define MAX_COMMAND 256
+
+enum {
+  NO_ACTION,
+  SET,
+  MOVE,
+  MOVETO,
+  GET,
+  START,
+  STOP,
+};
+
+static char title[128];
+
+gboolean hpsdr_server=FALSE;
+
+gint client_socket=-1;
+GThread *client_thread_id;
+gint start_spectrum(void *data);
+gboolean remote_started=FALSE;
+
+static GThread *listen_thread_id;
+static char status[1024];
+static int n_status=0;
+static char reply[64];
+static gboolean running;
+static gint listen_socket;
+
+static int audio_buffer_index=0;
+AUDIO_DATA audio_data;
+
+
+GMutex accumulated_mutex;
+static int accumulated_steps=0;
+static long long accumulated_hz=0LL;
+static gboolean accumulated_round=FALSE;
+gint check_vfo_timer_id=-1;
+
+REMOTE_CLIENT *add_client(REMOTE_CLIENT *client) {
+g_print("add_client: %p\n",client);
+// add to front of queue
+  g_mutex_lock(&client_mutex);
+  client->next=clients;
+  clients=client;
+  g_mutex_unlock(&client_mutex);
+g_print("add_client: clients=%p\n",clients);
+  return client;
+}
+
+void delete_client(REMOTE_CLIENT *client) {
+g_print("delete_client: %p\n",client);
+  g_mutex_lock(&client_mutex);
+  if(clients==client) {
+    clients=client->next;
+    g_free(client);
+  } else {
+    REMOTE_CLIENT* c=clients;
+    REMOTE_CLIENT* last_c=NULL;
+    while(c!=NULL && c!=client) {
+      last_c=c;
+      c=c->next;
+    }
+    if(c!=NULL) {
+      last_c->next=c->next;
+      g_free(c);
+    }
+  }
+g_print("delete_client: clients=%p\n",clients);
+  g_mutex_unlock(&client_mutex);
+}
+
+static int recv_bytes(int s,char *buffer,int bytes) {
+  int bytes_read=0;
+  int rc;
+  while(bytes_read!=bytes) {
+    rc=recv(s,&buffer[bytes_read],bytes-bytes_read,0);
+    if(rc<0) {
+      bytes_read=rc;
+      perror("recv_bytes");
+      break;
+    } else {
+      bytes_read+=rc;
+    }
+  }
+  return bytes_read;
+}
+
+static int send_bytes(int s,char *buffer,int bytes) {
+  int bytes_sent=0;
+  int rc;
+  if(s<0) return -1;
+  while(bytes_sent!=bytes) {
+    rc=send(s,&buffer[bytes_sent],bytes-bytes_sent,0);
+    if(rc<0) {
+      bytes_sent=rc;
+      perror("send_bytes");
+      break;
+    } else {
+      bytes_sent+=rc;
+    }
+  }
+  return bytes_sent;
+}
+
+void remote_audio(RECEIVER *rx,short left_sample,short right_sample) {
+  int i=audio_buffer_index*2;
+  audio_data.sample[i]=htons(left_sample);
+  audio_data.sample[i+1]=htons(right_sample);
+  audio_buffer_index++;
+  if(audio_buffer_index>=AUDIO_DATA_SIZE) {
+    g_mutex_lock(&client_mutex);
+    REMOTE_CLIENT *c=clients;
+    while(c!=NULL && c->socket!=-1) {
+      audio_data.header.sync=REMOTE_SYNC;
+      audio_data.header.data_type=htons(INFO_AUDIO);
+      audio_data.header.version=htonll(CLIENT_SERVER_VERSION);
+      audio_data.rx=rx->id;
+      audio_data.samples=ntohs(audio_buffer_index);
+      int bytes_sent=send_bytes(c->socket,(char *)&audio_data,sizeof(audio_data));
+      if(bytes_sent<0) {
+        perror("remote_audio");
+        if(c->socket!=-1) {
+          close(c->socket);
+        }
+      }
+      c=c->next;
+    }
+    g_mutex_unlock(&client_mutex);
+    audio_buffer_index=0;
+  }
+}
+
+static gint send_spectrum(void *arg) {
+  REMOTE_CLIENT *client=(REMOTE_CLIENT *)arg;
+  float *samples;
+  double sample;
+  short s;
+  SPECTRUM_DATA spectrum_data;
+  gint result;
+
+  result=TRUE;
+
+  if(!(client->receiver[0].send_spectrum || client->receiver[1].send_spectrum) || !client->running) {
+    client->spectrum_update_timer_id=-1;
+g_print("send_spectrum: no more receivers\n");
+    return FALSE;
+  }
+
+  for(int r=0;r<receivers;r++) {
+    RECEIVER *rx=receiver[r];
+    if(client->receiver[r].send_spectrum) {
+      if(rx->displaying && (rx->pixels>0) && (rx->pixel_samples!=NULL)) {
+        g_mutex_lock(&rx->display_mutex);
+        spectrum_data.header.sync=REMOTE_SYNC;
+        spectrum_data.header.data_type=htons(INFO_SPECTRUM);
+        spectrum_data.header.version=htonll(CLIENT_SERVER_VERSION);
+        spectrum_data.rx=r;
+        spectrum_data.vfo_a_freq=htonll(vfo[VFO_A].frequency);
+        spectrum_data.vfo_b_freq=htonll(vfo[VFO_B].frequency);
+        spectrum_data.vfo_a_ctun_freq=htonll(vfo[VFO_A].ctun_frequency);
+        spectrum_data.vfo_b_ctun_freq=htonll(vfo[VFO_B].ctun_frequency);
+        spectrum_data.vfo_a_offset=htonll(vfo[VFO_A].offset);
+        spectrum_data.vfo_b_offset=htonll(vfo[VFO_B].offset);
+        s=(short)receiver[r]->meter;
+        spectrum_data.meter=htons(s);
+        spectrum_data.samples=htons(rx->width);
+        samples=rx->pixel_samples;
+        for(int i=0;i<rx->width;i++) {
+          s=(short)samples[i+rx->pan];
+          spectrum_data.sample[i]=htons(s);
+        }
+        // send the buffer
+        int bytes_sent=send_bytes(client->socket,(char *)&spectrum_data,sizeof(spectrum_data));
+        if(bytes_sent<0) {
+          result=FALSE;
+        }
+        g_mutex_unlock(&rx->display_mutex);
+      }
+    }
+  }
+  return result;
+}
+
+void send_radio_data(REMOTE_CLIENT *client) {
+  RADIO_DATA radio_data;
+  radio_data.header.sync=REMOTE_SYNC;
+  radio_data.header.data_type=htons(INFO_RADIO);
+  radio_data.header.version=htonl(CLIENT_SERVER_VERSION);
+  strcpy(radio_data.name,radio->name);
+  radio_data.protocol=htons(radio->protocol);
+  radio_data.device=htons(radio->device);
+  uint64_t temp=(uint64_t)radio->frequency_min;
+  radio_data.frequency_min=htonll(temp);
+  temp=(uint64_t)radio->frequency_max;
+  radio_data.frequency_max=htonll(temp);
+  long long rate=(long long)radio_sample_rate;
+  radio_data.sample_rate=htonll(rate);
+  radio_data.display_filled=display_filled;
+  radio_data.locked=locked;
+  radio_data.supported_receivers=htons(radio->supported_receivers);
+  radio_data.receivers=htons(receivers);
+  radio_data.can_transmit=can_transmit;
+  radio_data.step=htonll(step);
+  radio_data.split=split;
+  radio_data.sat_mode=sat_mode;
+  radio_data.duplex=duplex;
+  radio_data.have_rx_gain=have_rx_gain;
+  radio_data.rx_gain_calibration=htons(rx_gain_calibration);
+  radio_data.filter_board=htons(filter_board);
+
+  int bytes_sent=send_bytes(client->socket,(char *)&radio_data,sizeof(radio_data));
+g_print("send_radio_data: %d\n",bytes_sent);
+  if(bytes_sent<0) {
+    perror("send_radio_data");
+  } else {
+    //g_print("send_radio_data: %d\n",bytes_sent);
+  }
+}
+
+void send_adc_data(REMOTE_CLIENT *client,int i) {
+  ADC_DATA adc_data;
+  adc_data.header.sync=REMOTE_SYNC;
+  adc_data.header.data_type=htons(INFO_ADC);
+  adc_data.header.version=htonl(CLIENT_SERVER_VERSION);
+  adc_data.adc=i;
+  adc_data.filters=htons(adc[i].filters);
+  adc_data.hpf=htons(adc[i].hpf);
+  adc_data.lpf=htons(adc[i].lpf);
+  adc_data.antenna=htons(adc[i].antenna);
+  adc_data.dither=adc[i].dither;
+  adc_data.random=adc[i].random;
+  adc_data.preamp=adc[i].preamp;
+  adc_data.attenuation=htons(adc[i].attenuation);
+  adc_data.adc_attenuation=htons(adc_attenuation[i]);
+  int bytes_sent=send_bytes(client->socket,(char *)&adc_data,sizeof(adc_data));
+  if(bytes_sent<0) {
+    perror("send_adc_data");
+  } else {
+    //g_print("send_adc_data: %d\n",bytes_sent);
+  }
+}
+
+void send_receiver_data(REMOTE_CLIENT *client,int rx) {
+  RECEIVER_DATA receiver_data;
+  receiver_data.header.sync=REMOTE_SYNC;
+  receiver_data.header.data_type=htons(INFO_RECEIVER);
+  receiver_data.header.version=htonl(CLIENT_SERVER_VERSION);
+  receiver_data.rx=rx;
+  receiver_data.adc=htons(receiver[rx]->adc);
+  long long rate=(long long)receiver[rx]->sample_rate;
+  receiver_data.sample_rate=htonll(rate);
+  receiver_data.displaying=receiver[rx]->displaying;
+  receiver_data.display_panadapter=receiver[rx]->display_panadapter;
+  receiver_data.display_waterfall=receiver[rx]->display_waterfall;
+  receiver_data.fps=htons(receiver[rx]->fps);
+  receiver_data.agc=receiver[rx]->agc;
+  short s=(short)receiver[rx]->agc_hang;
+  receiver_data.agc_hang=htons(s);
+  s=(short)receiver[rx]->agc_thresh;
+  receiver_data.agc_thresh=htons(s);
+  receiver_data.nb=receiver[rx]->nb;
+  receiver_data.nb2=receiver[rx]->nb2;
+  receiver_data.nr=receiver[rx]->nr;
+  receiver_data.nr2=receiver[rx]->nr2;
+  receiver_data.anf=receiver[rx]->anf;
+  receiver_data.snb=receiver[rx]->snb;
+  receiver_data.filter_low=htons(receiver[rx]->filter_low);
+  receiver_data.filter_high=htons(receiver[rx]->filter_high);
+  receiver_data.panadapter_low=htons(receiver[rx]->panadapter_low);
+  receiver_data.panadapter_high=htons(receiver[rx]->panadapter_high);
+  receiver_data.panadapter_step=htons(receiver[rx]->panadapter_step);
+  receiver_data.waterfall_low=htons(receiver[rx]->waterfall_low);
+  receiver_data.waterfall_high=htons(receiver[rx]->waterfall_high);
+  receiver_data.waterfall_automatic=receiver[rx]->waterfall_automatic;
+  receiver_data.pixels=htons(receiver[rx]->pixels);
+  receiver_data.zoom=htons(receiver[rx]->zoom);
+  receiver_data.pan=htons(receiver[rx]->pan);
+  receiver_data.width=htons(receiver[rx]->width);
+  receiver_data.height=htons(receiver[rx]->height);
+  receiver_data.x=htons(receiver[rx]->x);
+  receiver_data.y=htons(receiver[rx]->y);
+  s=(short)(receiver[rx]->volume*100.0);
+  receiver_data.volume=htons(s);
+  s=(short)receiver[rx]->rf_gain;
+  receiver_data.rf_gain=htons(s);
+  s=(short)receiver[rx]->agc_gain;
+  receiver_data.agc_gain=htons(s);
+
+  int bytes_sent=send_bytes(client->socket,(char *)&receiver_data,sizeof(receiver_data));
+  if(bytes_sent<0) {
+    perror("send_receiver_data");
+  } else {
+    //g_print("send_receiver_data: bytes sent %d\n",bytes_sent);
+  }
+}
+
+void send_vfo_data(REMOTE_CLIENT *client,int v) {
+  VFO_DATA vfo_data;
+  vfo_data.header.sync=REMOTE_SYNC;
+  vfo_data.header.data_type=htons(INFO_VFO);
+  vfo_data.header.version=htonl(CLIENT_SERVER_VERSION);
+  vfo_data.vfo=v;
+  vfo_data.band=htons(vfo[v].band);
+  vfo_data.bandstack=htons(vfo[v].bandstack);
+  vfo_data.frequency=htonll(vfo[v].frequency);
+  vfo_data.mode=htons(vfo[v].mode);
+  vfo_data.filter=htons(vfo[v].filter);
+  vfo_data.ctun=vfo[v].ctun;
+  vfo_data.ctun_frequency=htonll(vfo[v].ctun_frequency);
+  vfo_data.rit_enabled=vfo[v].rit_enabled;
+  vfo_data.rit=htonll(vfo[v].rit);
+  vfo_data.lo=htonll(vfo[v].lo);
+  vfo_data.offset=htonll(vfo[v].offset);
+
+  int bytes_sent=send_bytes(client->socket,(char *)&vfo_data,sizeof(vfo_data));
+  if(bytes_sent<0) {
+    perror("send_vfo_data");
+  } else {
+    //g_print("send_vfo_data: bytes sent %d\n",bytes_sent);
+  }
+}
+
+static void *server_client_thread(void *arg) {
+  REMOTE_CLIENT *client=(REMOTE_CLIENT *)arg;
+  int bytes_read;
+  HEADER header;
+
+g_print("Client connected on port %d\n",client->address.sin_port);
+  send_radio_data(client);
+  send_adc_data(client,0);
+  send_adc_data(client,1);
+  for(int i=0;i<RECEIVERS;i++) {
+    send_receiver_data(client,i);
+  }
+  send_vfo_data(client,VFO_A);
+  send_vfo_data(client,VFO_B);
+
+  // get and parse client commands
+  while(client->running) {
+    bytes_read=recv_bytes(client->socket,(char *)&header.sync,sizeof(header.sync));
+    if(bytes_read<=0) {
+      g_print("server_client_thread: read %d bytes for HEADER SYNC\n",bytes_read);
+      perror("server_client_thread");
+      client->running=FALSE;
+      continue;
+    }
+
+g_print("header.sync is %x\n",header.sync);
+
+    if(header.sync!=REMOTE_SYNC) {
+g_print("header.sync is %x wanted %x\n",header.sync,REMOTE_SYNC);
+      int syncs=0;
+      char c;
+      while(syncs!=sizeof(header.sync) && client->running) {
+        // try to resync on 2 0xFA bytes
+        bytes_read=recv_bytes(client->socket,(char *)&c,1);
+        if(bytes_read<=0) {
+          g_print("server_client_thread: read %d bytes for HEADER RESYNC\n",bytes_read);
+          perror("server_client_thread");
+          client->running=FALSE;
+          continue;
+        }
+        if(c==(char)0xFA) {
+          syncs++;
+        } else {
+          syncs=0;
+        }
+      }
+    }
+
+    bytes_read=recv_bytes(client->socket,(char *)&header.data_type,sizeof(header)-sizeof(header.sync));
+    if(bytes_read<=0) {
+      g_print("server_client_thread: read %d bytes for HEADER\n",bytes_read);
+      perror("server_client_thread");
+      client->running=FALSE;
+      continue;
+    }
+g_print("header remaining bytes %d\n",bytes_read);
+
+g_print("server_client_thread: received header: type=%d\n",ntohs(header.data_type));
+
+    switch(ntohs(header.data_type)) {
+       case CMD_RESP_SPECTRUM:
+         {
+         SPECTRUM_COMMAND spectrum_command;
+         bytes_read=recv_bytes(client->socket,(char *)&spectrum_command.id,sizeof(SPECTRUM_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for SPECTRUM_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+
+         int rx=spectrum_command.id;
+         int state=spectrum_command.start_stop;
+g_print("server_client_thread: CMD_RESP_SPECTRUM rx=%d state=%d timer_id=%d\n",rx,state,client->spectrum_update_timer_id);
+         if(state) {
+           client->receiver[rx].receiver=rx;
+           client->receiver[rx].spectrum_fps=receiver[rx]->fps;
+           client->receiver[rx].spectrum_port=0;
+           client->receiver[rx].send_spectrum=TRUE;
+           if(client->spectrum_update_timer_id==-1) {
+g_print("start send_spectrum thread: fps=%d\n",client->receiver[rx].spectrum_fps);
+             client->spectrum_update_timer_id=gdk_threads_add_timeout_full(G_PRIORITY_HIGH_IDLE,1000/client->receiver[rx].spectrum_fps, send_spectrum, client, NULL);
+g_print("spectrum_update_timer_id=%d\n",client->spectrum_update_timer_id);
+           } else {
+g_print("send_spectrum thread already running\n");
+           }
+         } else {
+           client->receiver[rx].send_spectrum=FALSE;
+         }
+         }
+         break;
+       case CMD_RESP_RX_FREQ:
+g_print("server_client_thread: CMD_RESP_RX_FREQ\n");
+         {
+         FREQ_COMMAND *freq_command=g_new(FREQ_COMMAND,1);
+         freq_command->header.data_type=header.data_type;
+         freq_command->header.version=header.version;
+         freq_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&freq_command->id,sizeof(FREQ_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for FREQ_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,freq_command);
+         }
+         break;
+       case CMD_RESP_RX_STEP:
+g_print("server_client_thread: CMD_RESP_RX_STEP\n");
+         {
+         STEP_COMMAND *step_command=g_new(STEP_COMMAND,1);
+         step_command->header.data_type=header.data_type;
+         step_command->header.version=header.version;
+         step_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&step_command->id,sizeof(STEP_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for STEP_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,step_command);
+         }
+         break;
+       case CMD_RESP_RX_MOVE:
+g_print("server_client_thread: CMD_RESP_RX_MOVE\n");
+         {
+         MOVE_COMMAND *move_command=g_new(MOVE_COMMAND,1);
+         move_command->header.data_type=header.data_type;
+         move_command->header.version=header.version;
+         move_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&move_command->id,sizeof(MOVE_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for MOVE_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,move_command);
+         }
+         break;
+       case CMD_RESP_RX_MOVETO:
+g_print("server_client_thread: CMD_RESP_RX_MOVETO\n");
+         {
+         MOVE_TO_COMMAND *move_to_command=g_new(MOVE_TO_COMMAND,1);
+         move_to_command->header.data_type=header.data_type;
+         move_to_command->header.version=header.version;
+         move_to_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&move_to_command->id,sizeof(MOVE_TO_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for MOVE_TO_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,move_to_command);
+         }
+         break;
+       case CMD_RESP_RX_ZOOM:
+g_print("server_client_thread: CMD_RESP_RX_ZOOM\n");
+         {
+         ZOOM_COMMAND *zoom_command=g_new(ZOOM_COMMAND,1);
+         zoom_command->header.data_type=header.data_type;
+         zoom_command->header.version=header.version;
+         zoom_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&zoom_command->id,sizeof(ZOOM_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for ZOOM_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,zoom_command);
+         }
+         break;
+       case CMD_RESP_RX_PAN:
+g_print("server_client_thread: CMD_RESP_RX_PAN\n");
+         {
+         PAN_COMMAND *pan_command=g_new(PAN_COMMAND,1);
+         pan_command->header.data_type=header.data_type;
+         pan_command->header.version=header.version;
+         pan_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&pan_command->id,sizeof(PAN_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for PAN_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,pan_command);
+         }
+         break;
+       case CMD_RESP_RX_VOLUME:
+g_print("server_client_thread: CMD_RESP_RX_VOLUME\n");
+         {
+         VOLUME_COMMAND *volume_command=g_new(VOLUME_COMMAND,1);
+         volume_command->header.data_type=header.data_type;
+         volume_command->header.version=header.version;
+         volume_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&volume_command->id,sizeof(VOLUME_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for VOLUME_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,volume_command);
+         }
+         break;
+       case CMD_RESP_RX_AGC:
+g_print("server_client_thread: CMD_RESP_RX_AGC\n");
+         {
+         AGC_COMMAND *agc_command=g_new(AGC_COMMAND,1);
+         agc_command->header.data_type=header.data_type;
+         agc_command->header.version=header.version;
+         agc_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&agc_command->id,sizeof(AGC_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for AGC_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+g_print("CMD_RESP_RX_AGC: id=%d agc=%d\n",agc_command->id,ntohs(agc_command->agc));
+         g_idle_add(ext_remote_command,agc_command);
+         }
+         break;
+       case CMD_RESP_RX_AGC_GAIN:
+g_print("server_client_thread: CMD_RESP_RX_AGC_GAIN\n");
+         {
+         AGC_GAIN_COMMAND *agc_gain_command=g_new(AGC_GAIN_COMMAND,1);
+         agc_gain_command->header.data_type=header.data_type;
+         agc_gain_command->header.version=header.version;
+         agc_gain_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&agc_gain_command->id,sizeof(AGC_GAIN_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for AGC_GAIN_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,agc_gain_command);
+         }
+         break;
+      case CMD_RESP_RX_ATTENUATION:
+g_print("server_client_thread: CMD_RESP_RX_ATTENUATION\n");
+         {
+         ATTENUATION_COMMAND *attenuation_command=g_new(ATTENUATION_COMMAND,1);
+         attenuation_command->header.data_type=header.data_type;
+         attenuation_command->header.version=header.version;
+         attenuation_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&attenuation_command->id,sizeof(ATTENUATION_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for ATTENUATION_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,attenuation_command);
+         }
+         break;
+       case CMD_RESP_RX_SQUELCH:
+g_print("server_client_thread: CMD_RESP_RX_SQUELCH\n");
+         {
+         SQUELCH_COMMAND *squelch_command=g_new(SQUELCH_COMMAND,1);
+         squelch_command->header.data_type=header.data_type;
+         squelch_command->header.version=header.version;
+         squelch_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&squelch_command->id,sizeof(SQUELCH_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for SQUELCH_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,squelch_command);
+         }
+         break;
+       case CMD_RESP_RX_NOISE:
+g_print("server_client_thread: CMD_RESP_RX_NOISE\n");
+         {
+         NOISE_COMMAND *noise_command=g_new(NOISE_COMMAND,1);
+         noise_command->header.data_type=header.data_type;
+         noise_command->header.version=header.version;
+         noise_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&noise_command->id,sizeof(NOISE_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for NOISE_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,noise_command);
+         }
+         break;
+       case CMD_RESP_RX_BAND:
+g_print("server_client_thread: CMD_RESP_RX_BAND\n");
+         {
+         BAND_COMMAND *band_command=g_new(BAND_COMMAND,1);
+         band_command->header.data_type=header.data_type;
+         band_command->header.version=header.version;
+         band_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&band_command->id,sizeof(BAND_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for BAND_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,band_command);
+         }
+         break;
+       case CMD_RESP_RX_MODE:
+g_print("server_client_thread: CMD_RESP_RX_MODE\n");
+         {
+         MODE_COMMAND *mode_command=g_new(MODE_COMMAND,1);
+         mode_command->header.data_type=header.data_type;
+         mode_command->header.version=header.version;
+         mode_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&mode_command->id,sizeof(MODE_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for MODE_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,mode_command);
+         }
+         break;
+       case CMD_RESP_RX_FILTER:
+g_print("server_client_thread: CMD_RESP_RX_FILTER\n");
+         {
+         FILTER_COMMAND *filter_command=g_new(FILTER_COMMAND,1);
+         filter_command->header.data_type=header.data_type;
+         filter_command->header.version=header.version;
+         filter_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&filter_command->id,sizeof(FILTER_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for FILTER_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,filter_command);
+         }
+         break;
+       case CMD_RESP_SPLIT:
+g_print("server_client_thread: CMD_RESP_RX_SPLIT\n");
+         {
+         SPLIT_COMMAND *split_command=g_new(SPLIT_COMMAND,1);
+         split_command->header.data_type=header.data_type;
+         split_command->header.version=header.version;
+         split_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&split_command->split,sizeof(SPLIT_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for SPLIT_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,split_command);
+         }
+         break;
+       case CMD_RESP_SAT:
+g_print("server_client_thread: CMD_RESP_RX_SAT\n");
+         {
+         SAT_COMMAND *sat_command=g_new(SAT_COMMAND,1);
+         sat_command->header.data_type=header.data_type;
+         sat_command->header.version=header.version;
+         sat_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&sat_command->sat,sizeof(SAT_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for SAT_COMMAND\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,sat_command);
+         }
+         break;
+       case CMD_RESP_DUP:
+g_print("server_client_thread: CMD_RESP_DUP\n");
+         {
+         DUP_COMMAND *dup_command=g_new(DUP_COMMAND,1);
+         dup_command->header.data_type=header.data_type;
+         dup_command->header.version=header.version;
+         dup_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&dup_command->dup,sizeof(DUP_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for DUP\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,dup_command);
+         }
+         break;
+       case CMD_RESP_LOCK:
+g_print("server_client_thread: CMD_RESP_LOCK\n");
+         {
+         LOCK_COMMAND *lock_command=g_new(LOCK_COMMAND,1);
+         lock_command->header.data_type=header.data_type;
+         lock_command->header.version=header.version;
+         lock_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&lock_command->lock,sizeof(LOCK_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for LOCK\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,lock_command);
+         }
+         break;
+       case CMD_RESP_CTUN:
+g_print("server_client_thread: CMD_RESP_CTUN\n");
+         {
+         CTUN_COMMAND *ctun_command=g_new(CTUN_COMMAND,1);
+         ctun_command->header.data_type=header.data_type;
+         ctun_command->header.version=header.version;
+         ctun_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&ctun_command->id,sizeof(CTUN_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for CTUN\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,ctun_command);
+         }
+         break;
+       case CMD_RESP_RX_FPS:
+g_print("server_client_thread: CMD_RESP_RX_FPS\n");
+         {
+         FPS_COMMAND *fps_command=g_new(FPS_COMMAND,1);
+         fps_command->header.data_type=header.data_type;
+         fps_command->header.version=header.version;
+         fps_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&fps_command->id,sizeof(FPS_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for FPS\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,fps_command);
+         }
+         break;
+       case CMD_RESP_RX_SELECT:
+g_print("server_client_thread: CMD_RESP_RX_SELECT\n");
+         {
+         RX_SELECT_COMMAND *rx_select_command=g_new(RX_SELECT_COMMAND,1);
+         rx_select_command->header.data_type=header.data_type;
+         rx_select_command->header.version=header.version;
+         rx_select_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&rx_select_command->id,sizeof(RX_SELECT_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for RX_SELECT\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,rx_select_command);
+         }
+         break;
+       case CMD_RESP_VFO:
+g_print("server_client_thread: CMD_RESP_VFO\n");
+         {
+         VFO_COMMAND *vfo_command=g_new(VFO_COMMAND,1);
+         vfo_command->header.data_type=header.data_type;
+         vfo_command->header.version=header.version;
+         vfo_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&vfo_command->id,sizeof(VFO_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for VFO\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,vfo_command);
+         }
+         break;
+       case CMD_RESP_RIT_UPDATE:
+g_print("server_client_thread: CMD_RESP_RIT_UPDATE\n");
+         {
+         RIT_UPDATE_COMMAND *rit_update_command=g_new(RIT_UPDATE_COMMAND,1);
+         rit_update_command->header.data_type=header.data_type;
+         rit_update_command->header.version=header.version;
+         rit_update_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&rit_update_command->id,sizeof(RIT_UPDATE_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for RIT_UPDATE\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,rit_update_command);
+         }
+         break;
+       case CMD_RESP_RIT_CLEAR:
+g_print("server_client_thread: CMD_RESP_RIT_CLEAR\n");
+         {
+         RIT_CLEAR_COMMAND *rit_clear_command=g_new(RIT_CLEAR_COMMAND,1);
+         rit_clear_command->header.data_type=header.data_type;
+         rit_clear_command->header.version=header.version;
+         rit_clear_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&rit_clear_command->id,sizeof(RIT_CLEAR_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for RIT_CLEAR\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,rit_clear_command);
+         }
+         break;
+       case CMD_RESP_RIT:
+g_print("server_client_thread: CMD_RESP_RIT\n");
+         {
+         RIT_COMMAND *rit_command=g_new(RIT_COMMAND,1);
+         rit_command->header.data_type=header.data_type;
+         rit_command->header.version=header.version;
+         rit_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&rit_command->id,sizeof(RIT_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for RIT\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,rit_command);
+         }
+         break;
+       case CMD_RESP_XIT_UPDATE:
+g_print("server_client_thread: CMD_RESP_XIT_UPDATE\n");
+         {
+         XIT_UPDATE_COMMAND *xit_update_command=g_new(XIT_UPDATE_COMMAND,1);
+         xit_update_command->header.data_type=header.data_type;
+         xit_update_command->header.version=header.version;
+         xit_update_command->header.context.client=client;
+         g_idle_add(ext_remote_command,xit_update_command);
+         }
+         break;
+       case CMD_RESP_XIT_CLEAR:
+g_print("server_client_thread: CMD_RESP_XIT_CLEAR\n");
+         {
+         XIT_CLEAR_COMMAND *xit_clear_command=g_new(XIT_CLEAR_COMMAND,1);
+         xit_clear_command->header.data_type=header.data_type;
+         xit_clear_command->header.version=header.version;
+         xit_clear_command->header.context.client=client;
+         g_idle_add(ext_remote_command,xit_clear_command);
+         }
+         break;
+       case CMD_RESP_XIT:
+g_print("server_client_thread: CMD_RESP_XIT\n");
+         {
+         XIT_COMMAND *xit_command=g_new(XIT_COMMAND,1);
+         xit_command->header.data_type=header.data_type;
+         xit_command->header.version=header.version;
+         xit_command->header.context.client=client;
+         g_idle_add(ext_remote_command,xit_command);
+         }
+         break;
+       case CMD_RESP_SAMPLE_RATE:
+g_print("server_client_thread: CMD_RESP_SAMPLE_RATE\n");
+         {
+         SAMPLE_RATE_COMMAND *sample_rate_command=g_new(SAMPLE_RATE_COMMAND,1);
+         sample_rate_command->header.data_type=header.data_type;
+         sample_rate_command->header.version=header.version;
+         sample_rate_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&sample_rate_command->id,sizeof(SAMPLE_RATE_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for SAMPLE_RATE\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,sample_rate_command);
+         }
+         break;
+       case CMD_RESP_RECEIVERS:
+g_print("server_client_thread: CMD_RESP_RECEIVERS\n");
+         {
+         RECEIVERS_COMMAND *receivers_command=g_new(RECEIVERS_COMMAND,1);
+         receivers_command->header.data_type=header.data_type;
+         receivers_command->header.version=header.version;
+         receivers_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&receivers_command->receivers,sizeof(RECEIVERS_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for RECEIVERS\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,receivers_command);
+         }
+         break;
+       case CMD_RESP_RIT_INCREMENT:
+g_print("server_client_thread: CMD_RESP_RIT_INCREMENT\n");
+         {
+         RIT_INCREMENT_COMMAND *rit_increment_command=g_new(RIT_INCREMENT_COMMAND,1);
+         rit_increment_command->header.data_type=header.data_type;
+         rit_increment_command->header.version=header.version;
+         rit_increment_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&rit_increment_command->increment,sizeof(RIT_INCREMENT_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for RIT_INCREMENT\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,rit_increment_command);
+         }
+         break;
+       case CMD_RESP_FILTER_BOARD:
+g_print("server_client_thread: CMD_RESP_FILTER_BOARD\n");
+         {
+         FILTER_BOARD_COMMAND *filter_board_command=g_new(FILTER_BOARD_COMMAND,1);
+         filter_board_command->header.data_type=header.data_type;
+         filter_board_command->header.version=header.version;
+         filter_board_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&filter_board_command->filter_board,sizeof(FILTER_BOARD_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for FILTER_BOARD\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,filter_board_command);
+         }
+         break;
+       case CMD_RESP_SWAP_IQ:
+g_print("server_client_thread: CMD_RESP_SWAP_IQ\n");
+         {
+         SWAP_IQ_COMMAND *swap_iq_command=g_new(SWAP_IQ_COMMAND,1);
+         swap_iq_command->header.data_type=header.data_type;
+         swap_iq_command->header.version=header.version;
+         swap_iq_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&swap_iq_command->iqswap,sizeof(SWAP_IQ_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for SWAP_IQ\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,swap_iq_command);
+         }
+         break;
+       case CMD_RESP_REGION:
+g_print("server_client_thread: CMD_RESP_REGION\n");
+         {
+         REGION_COMMAND *region_command=g_new(REGION_COMMAND,1);
+         region_command->header.data_type=header.data_type;
+         region_command->header.version=header.version;
+         region_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&region_command->region,sizeof(REGION_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for REGION\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,region_command);
+         }
+         break;
+       case CMD_RESP_MUTE_RX:
+g_print("server_client_thread: CMD_RESP_MUTE_RX\n");
+         {
+         MUTE_RX_COMMAND *mute_rx_command=g_new(MUTE_RX_COMMAND,1);
+         mute_rx_command->header.data_type=header.data_type;
+         mute_rx_command->header.version=header.version;
+         mute_rx_command->header.context.client=client;
+         bytes_read=recv_bytes(client->socket,(char *)&mute_rx_command->mute,sizeof(MUTE_RX_COMMAND)-sizeof(header));
+         if(bytes_read<0) {
+           g_print("server_client_thread: read %d bytes for MUTE_RX\n",bytes_read);
+           perror("server_client_thread");
+           // dialog box?
+           return NULL;
+         }
+         g_idle_add(ext_remote_command,mute_rx_command);
+         }
+         break;
+
+
+
+
+
+       default:
+g_print("server_client_thread: UNKNOWN command: %d\n",ntohs(header.data_type));
+         break;
+    }
+
+  }
+
+  // close the socket to force listen to terminate
+g_print("client disconnected\n");
+  if(client->socket!=-1) {
+    close(client->socket);
+    client->socket=-1;
+  }
+  delete_client(client);
+  return NULL;
+}
+
+void send_start_spectrum(int s,int rx) {
+  SPECTRUM_COMMAND command;
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_SPECTRUM);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.start_stop=1;
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_vfo_frequency(int s,int rx,long long hz) {
+  FREQ_COMMAND command;
+
+  g_print("send_vfo_frequency\n");
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RX_FREQ);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.hz=htonll(hz);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_vfo_move_to(int s,int rx,long long hz) {
+  MOVE_TO_COMMAND command;
+  g_print("send_vfo_move_to\n");
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RX_MOVETO);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.hz=htonll(hz);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_vfo_move(int s,int rx,long long hz,int round) {
+  MOVE_COMMAND command;
+
+  g_print("send_vfo_move\n");
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RX_MOVE);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.hz=htonll(hz);
+  command.round=round;
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void update_vfo_move(int rx,long long hz,int round) {
+  g_mutex_lock(&accumulated_mutex);
+  accumulated_hz+=hz;
+  accumulated_round=round;
+  g_mutex_unlock(&accumulated_mutex);
+}
+
+void send_vfo_step(int s,int rx,int steps) {
+  STEP_COMMAND command;
+
+  short stps=(short)steps;
+  g_print("send_vfo_step rx=%d steps=%d s=%d\n",rx,steps,stps);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RX_STEP);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.steps=htons(stps);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void update_vfo_step(int rx,int steps) {
+  g_mutex_lock(&accumulated_mutex);
+  accumulated_steps+=steps;
+  g_mutex_unlock(&accumulated_mutex);
+}
+
+void send_zoom(int s,int rx,int zoom) {
+  ZOOM_COMMAND command;
+  short z=(short)zoom;
+g_print("send_zoom rx=%d zoom=%d\n",rx,zoom);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RX_ZOOM);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.zoom=htons(z);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_pan(int s,int rx,int pan) {
+  PAN_COMMAND command;
+  short p=(short)pan;
+g_print("send_pan rx=%d pan=%d\n",rx,pan);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RX_PAN);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.pan=htons(p);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_volume(int s,int rx,int volume) {
+  VOLUME_COMMAND command;
+  short v=(short)volume;
+g_print("send_volume rx=%d volume=%d\n",rx,volume);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RX_VOLUME);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.volume=htons(v);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_agc(int s,int rx,int agc) {
+  AGC_COMMAND command;
+  short a=(short)agc;
+g_print("send_agc rx=%d agc=%d\n",rx,agc);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RX_AGC);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.agc=htons(a);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_agc_gain(int s,int rx,int gain,int hang,int thresh) {
+  AGC_GAIN_COMMAND command;
+  short g=(short)gain;
+  short h=(short)hang;
+  short t=(short)thresh;
+g_print("send_agc_gain rx=%d gain=%d\n",rx,gain);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RX_AGC_GAIN);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.gain=htons(g);
+  command.hang=htons(h);
+  command.thresh=htons(t);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_attenuation(int s,int rx,int attenuation) {
+  ATTENUATION_COMMAND command;
+  short a=(short)attenuation;
+g_print("send_attenuation rx=%d attenuation=%d\n",rx,attenuation);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RX_ATTENUATION);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.attenuation=htons(a);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_squelch(int s,int rx,int enable,int squelch) {
+  SQUELCH_COMMAND command;
+  short sq=(short)squelch;
+g_print("send_squelch rx=%d enable=%d squelch=%d\n",rx,enable,squelch);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RX_SQUELCH);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.enable=enable;
+  command.squelch=htons(sq);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_noise(int s,int rx,int nb,int nb2,int nr,int nr2,int anf,int snb) {
+  NOISE_COMMAND command;
+g_print("send_noise rx=%d nb=%d nb2=%d nr=%d nr2=%d anf=%d snb=%d\n",rx,nb,nb2,nr,nr2,anf,snb);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RX_NOISE);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.nb=nb;
+  command.nb2=nb2;
+  command.nr=nr;
+  command.nr2=nr2;
+  command.anf=anf;
+  command.snb=snb;
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_band(int s,int rx,int band) {
+  BAND_COMMAND command;
+g_print("send_band rx=%d band=%d\n",rx,band);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RX_BAND);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.band=htons(band);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_mode(int s,int rx,int mode) {
+  MODE_COMMAND command;
+g_print("send_mode rx=%d mode=%d\n",rx,mode);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RX_MODE);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.mode=htons(mode);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_filter(int s,int rx,int filter) {
+  FILTER_COMMAND command;
+g_print("send_filter rx=%d filter=%d\n",rx,filter);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RX_FILTER);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.filter=htons(filter);
+  command.filter_low=htons(receiver[rx]->filter_low);
+  command.filter_high=htons(receiver[rx]->filter_high);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_split(int s,int split) {
+  SPLIT_COMMAND command;
+g_print("send_split split=%d\n",split);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_SPLIT);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.split=split;
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_sat(int s,int sat) {
+  SAT_COMMAND command;
+g_print("send_sat sat=%d\n",sat);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_SAT);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.sat=sat;
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_dup(int s,int dup) {
+  DUP_COMMAND command;
+g_print("send_dup dup=%d\n",dup);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_DUP);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.dup=dup;
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_fps(int s,int rx,int fps) {
+  FPS_COMMAND command;
+g_print("send_fps rx=%d fps=%d\n",rx,fps);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RX_FPS);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.fps=htons(fps);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_lock(int s,int lock) {
+  LOCK_COMMAND command;
+g_print("send_lock lock=%d\n",lock);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_LOCK);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.lock=lock;
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_ctun(int s,int vfo,int ctun) {
+  CTUN_COMMAND command;
+g_print("send_ctun vfo=%d ctun=%d\n",vfo,ctun);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_CTUN);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=vfo;
+  command.ctun=ctun;
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_rx_select(int s,int rx) {
+  RX_SELECT_COMMAND command;
+g_print("send_rx_select rx=%d\n",rx);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RX_SELECT);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_vfo(int s,int action) {
+  VFO_COMMAND command;
+g_print("send_vfo action=%d\n",action);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_VFO);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=action;
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_rit_update(int s,int rx) {
+  RIT_UPDATE_COMMAND command;
+g_print("send_rit_enable rx=%d\n",rx);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RIT_UPDATE);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_rit_clear(int s,int rx) {
+  RIT_CLEAR_COMMAND command;
+g_print("send_rit_clear rx=%d\n",rx);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RIT_CLEAR);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_rit(int s,int rx,int rit) {
+  RIT_COMMAND command;
+g_print("send_rit rx=%d rit=%d\n",rx,rit);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RIT);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.rit=htons(rit);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_xit_update(int s) {
+  XIT_UPDATE_COMMAND command;
+g_print("send_xit_update\n");
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RIT_UPDATE);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_xit_clear(int s) {
+  XIT_CLEAR_COMMAND command;
+g_print("send_xit_clear\n");
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_XIT_CLEAR);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_xit(int s,int xit) {
+  XIT_COMMAND command;
+g_print("send_xit xit=%d\n",xit);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_XIT);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.xit=htons(xit);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_sample_rate(int s,int rx,int sample_rate) {
+  SAMPLE_RATE_COMMAND command;
+
+  long long rate=(long long)sample_rate;
+  g_print("send_sample_rate rx=%d rate=%lld\n",rx,rate);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_SAMPLE_RATE);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.id=rx;
+  command.sample_rate=htonll(rate);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_receivers(int s,int receivers) {
+  RECEIVERS_COMMAND command;
+
+  g_print("send_receivers receivers=%d\n",receivers);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RECEIVERS);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.receivers=receivers;
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+}
+
+void send_rit_increment(int s,int increment) {
+  RIT_INCREMENT_COMMAND command;
+
+g_print("send_rit_increment increment=%d\n",increment);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_RIT_INCREMENT);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.increment=htons(increment);
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+
+}
+
+void send_filter_board(int s,int filter_board) {
+  FILTER_BOARD_COMMAND command;
+
+g_print("send_filter_board filter_board=%d\n",filter_board);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_FILTER_BOARD);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.filter_board=filter_board;
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+
+}
+
+void send_swap_iq(int s,int iqswap) {
+  SWAP_IQ_COMMAND command;
+
+g_print("send_swap_iq iqswap=%d\n",iqswap);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_SWAP_IQ);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.iqswap=iqswap;
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+
+}
+
+void send_region(int s,int region) {
+  REGION_COMMAND command;
+
+g_print("send_region region=%d\n",region);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_REGION);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.region=region;
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+
+}
+
+void send_mute_rx(int s,int mute) {
+  MUTE_RX_COMMAND command;
+
+g_print("send_mute_rx mute=%d\n",mute);
+  command.header.sync=REMOTE_SYNC;
+  command.header.data_type=htons(CMD_RESP_MUTE_RX);
+  command.header.version=htonl(CLIENT_SERVER_VERSION);
+  command.mute=mute;
+  int bytes_sent=send_bytes(s,(char *)&command,sizeof(command));
+  if(bytes_sent<0) {
+    perror("send_command");
+  } else {
+    //g_print("send_command: %d\n",bytes_sent);
+  }
+
+}
+
+
+static void *listen_thread(void *arg) {
+  int address_length;
+  struct sockaddr_in address;
+  REMOTE_CLIENT* client;
+  int rc;
+  int on=1;
+
+g_print("hpsdr_server: listening on port %d\n",listen_port);
+  while(running) {
+    // create TCP socket to listen on
+    listen_socket=socket(AF_INET,SOCK_STREAM,0);
+    if(listen_socket<0) {
+      g_print("listen_thread: socket failed\n");
+      return NULL;
+    }
+
+    setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+    setsockopt(listen_socket, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
+
+    // bind to listening port
+    memset(&address,0,sizeof(address));
+    address.sin_family=AF_INET;
+    address.sin_addr.s_addr=INADDR_ANY;
+    address.sin_port=htons(listen_port);
+    if(bind(listen_socket,(struct sockaddr*)&address,sizeof(address))<0) {
+      g_print("listen_thread: bind failed\n");
+      return NULL;
+    }
+
+  // listen for connections
+    if(listen(listen_socket,5)<0) {
+      g_print("listen_thread: listen failed\n");
+      break;
+    }
+    REMOTE_CLIENT* client=g_new(REMOTE_CLIENT,1);
+    client->spectrum_update_timer_id=-1;
+    client->address_length=sizeof(client->address);
+    client->running=TRUE;
+g_print("hpsdr_server: accept\n");
+    if((client->socket=accept(listen_socket,(struct sockaddr*)&client->address,&client->address_length))<0) {
+      g_print("listen_thread: accept failed\n");
+      g_free(client);
+      continue;
+    }
+ char s[128];
+ inet_ntop(AF_INET, &(((struct sockaddr_in *)&client->address)->sin_addr),s,128);
+g_print("Client_connected from %s\n",s);
+    client->thread_id=g_thread_new("SSDR_client",server_client_thread,client);
+    add_client(client);
+    close(listen_socket);
+    gpointer thread_result=g_thread_join(client->thread_id);
+  }
+  return NULL;
+}
+
+int create_hpsdr_server() {
+  g_print("create_hpsdr_server\n");
+
+  g_mutex_init(&client_mutex);
+  clients=NULL;
+  running=TRUE;
+  listen_thread_id = g_thread_new( "HPSDR_listen", listen_thread, NULL);
+  return 0;
+}
+
+int destroy_hpsdr_server() {
+g_print("destroy_hpsdr_server\n");
+  running=FALSE;
+  return 0;
+}
+
+// CLIENT Code
+
+static gint check_vfo(void *arg) {
+  if(!running) return FALSE;
+
+  g_mutex_lock(&accumulated_mutex);
+
+  if(accumulated_steps!=0) {
+    send_vfo_step(client_socket,active_receiver->id,accumulated_steps);
+    accumulated_steps=0;
+  }
+
+  if(accumulated_hz!=0LL || accumulated_round) {
+    send_vfo_move(client_socket,active_receiver->id,accumulated_hz,accumulated_round);
+    accumulated_hz=0LL;
+    accumulated_round=FALSE;
+  }
+
+  g_mutex_unlock(&accumulated_mutex);
+
+  return TRUE;
+}
+
+static char server_host[128];
+static int delay=0;
+
+gint start_spectrum(void *data) {
+  RECEIVER *rx=(RECEIVER *)data;
+
+  if(delay!=3) {
+    delay++;
+g_print("start_spectrum: delay %d\n",delay);
+    return TRUE;
+  }
+  send_start_spectrum(client_socket,rx->id);
+  return FALSE;
+}
+
+void start_vfo_timer() {
+  g_mutex_init(&accumulated_mutex);
+  check_vfo_timer_id=gdk_threads_add_timeout_full(G_PRIORITY_HIGH_IDLE,100,check_vfo, NULL, NULL);
+g_print("check_vfo_timer_id %d\n",check_vfo_timer_id);
+}
+
+static void *client_thread(void* arg) {
+  gint bytes_read;
+#define MAX_BUFFER 2400
+  char buffer[MAX_BUFFER];
+  char *token;
+  HEADER header;
+  char *server=(char *)arg;
+
+  running=TRUE;
+
+  while(running) {
+    bytes_read=recv_bytes(client_socket,(char *)&header,sizeof(header));
+    if(bytes_read<0) {
+      g_print("client_thread: read %d bytes for HEADER\n",bytes_read);
+      perror("client_thread");
+      // dialog box?
+      return NULL;
+    }
+
+    switch(ntohs(header.data_type)) {
+      case INFO_RADIO:
+        {
+        RADIO_DATA radio_data;
+        bytes_read=recv_bytes(client_socket,(char *)&radio_data.name,sizeof(radio_data)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for RADIO_DATA\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+
+g_print("INFO_RADIO: %d\n",bytes_read);
+        // build a radio (discovered) structure
+        radio=g_new(DISCOVERED,1);
+        strcpy(radio->name,radio_data.name);
+        radio->protocol=ntohs(radio_data.protocol);
+        radio->device=ntohs(radio_data.device);
+        uint64_t temp=ntohll(radio_data.frequency_min);
+        radio->frequency_min=(double)temp;
+        temp=ntohll(radio_data.frequency_max);
+        radio->frequency_max=(double)temp;
+        radio->supported_receivers=ntohs(radio_data.supported_receivers);
+        temp=ntohll(radio_data.sample_rate);
+        radio_sample_rate=(int)temp;
+#ifdef SOAPYSDR
+        if(protocol==SOAPYSDR_PROTOCOL) {
+          radio->info.soapy.sample_rate=(int)temp;
+        }
+#endif
+        display_filled=radio_data.display_filled;
+        locked=radio_data.locked;
+        receivers=ntohs(radio_data.receivers);
+        can_transmit=radio_data.can_transmit;
+//TEMP
+can_transmit=0;
+        step=ntohll(radio_data.step);
+        split=radio_data.split;
+        sat_mode=radio_data.sat_mode;
+        duplex=radio_data.duplex;
+        protocol=radio->protocol;
+        have_rx_gain=radio_data.have_rx_gain;
+        short s=ntohs(radio_data.rx_gain_calibration);
+        rx_gain_calibration=(int)s;
+        filter_board=ntohs(radio_data.filter_board);
+g_print("have_rx_gain=%d rx_gain_calibration=%d filter_board=%d\n",have_rx_gain,rx_gain_calibration,filter_board);
+//
+// A semaphore for safely writing to the props file
+//
+        g_mutex_init(&property_mutex);
+
+        sprintf(title,"piHPSDR: %s remote at %s",radio->name,server);
+        g_idle_add(ext_set_title,(void *)title);
+
+        }
+        break;
+      case INFO_ADC:
+        {
+        ADC_DATA adc_data;
+        bytes_read=recv_bytes(client_socket,(char *)&adc_data.adc,sizeof(adc_data)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for ADC_DATA\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+g_print("INFO_ADC: %d\n",bytes_read);
+        int i=adc_data.adc;
+        adc[i].filters=ntohs(adc_data.filters);
+        adc[i].hpf=ntohs(adc_data.hpf);
+        adc[i].lpf=ntohs(adc_data.lpf);
+        adc[i].antenna=ntohs(adc_data.antenna);
+        adc[i].dither=adc_data.dither;
+        adc[i].random=adc_data.random;
+        adc[i].preamp=adc_data.preamp;
+        adc[i].attenuation=ntohs(adc_data.attenuation);
+        adc_attenuation[i]=ntohs(adc_data.adc_attenuation);
+        }
+        break;
+      case INFO_RECEIVER:
+        {
+        RECEIVER_DATA receiver_data;
+        bytes_read=recv_bytes(client_socket,(char *)&receiver_data.rx,sizeof(receiver_data)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for RECEIVER_DATA\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+
+g_print("INFO_RECEIVER: %d\n",bytes_read);
+        int rx=receiver_data.rx;
+        receiver[rx]=g_new(RECEIVER,1);
+        receiver[rx]->id=rx;
+        receiver[rx]->adc=ntohs(receiver_data.adc);;
+        long long rate=ntohll(receiver_data.sample_rate);
+        receiver[rx]->sample_rate=(int)rate;
+        receiver[rx]->displaying=receiver_data.displaying;
+        receiver[rx]->display_panadapter=receiver_data.display_panadapter;
+        receiver[rx]->display_waterfall=receiver_data.display_waterfall;
+        receiver[rx]->fps=ntohs(receiver_data.fps);
+        receiver[rx]->agc=receiver_data.agc;
+        short s=ntohs(receiver_data.agc_hang);
+        receiver[rx]->agc_hang=(double)s;
+        s=ntohs(receiver_data.agc_thresh);
+        receiver[rx]->agc_thresh=(double)s;
+        receiver[rx]->nb=receiver_data.nb;
+        receiver[rx]->nb2=receiver_data.nb2;
+        receiver[rx]->nr=receiver_data.nr;
+        receiver[rx]->nr2=receiver_data.nr2;
+        receiver[rx]->anf=receiver_data.anf;
+        receiver[rx]->snb=receiver_data.snb;
+        s=ntohs(receiver_data.filter_low);
+        receiver[rx]->filter_low=(int)s;
+        s=ntohs(receiver_data.filter_high);
+        receiver[rx]->filter_high=(int)s;
+        s=ntohs(receiver_data.panadapter_low);
+        receiver[rx]->panadapter_low=(int)s;
+        s=ntohs(receiver_data.panadapter_high);
+        receiver[rx]->panadapter_high=(int)s;
+        s=ntohs(receiver_data.panadapter_step);
+        receiver[rx]->panadapter_step=s;
+        s=ntohs(receiver_data.waterfall_low);
+        receiver[rx]->waterfall_low=(int)s;
+        s=ntohs(receiver_data.waterfall_high);
+        receiver[rx]->waterfall_high=s;
+        receiver[rx]->waterfall_automatic=receiver_data.waterfall_automatic;
+        receiver[rx]->pixels=ntohs(receiver_data.pixels);
+        receiver[rx]->zoom=ntohs(receiver_data.zoom);
+        receiver[rx]->pan=ntohs(receiver_data.pan);
+        receiver[rx]->width=ntohs(receiver_data.width);
+        receiver[rx]->height=ntohs(receiver_data.height);
+        receiver[rx]->x=ntohs(receiver_data.x);
+        receiver[rx]->y=ntohs(receiver_data.y);
+        s=ntohs(receiver_data.volume);
+        receiver[rx]->volume=(double)s/100.0;
+        s=ntohs(receiver_data.rf_gain);
+        receiver[rx]->rf_gain=(double)s;
+        s=ntohs(receiver_data.agc_gain);
+        receiver[rx]->agc_gain=(double)s;
+//
+        receiver[rx]->pixel_samples=NULL;
+        g_mutex_init(&receiver[rx]->display_mutex);
+        receiver[rx]->hz_per_pixel=(double)receiver[rx]->sample_rate/(double)receiver[rx]->pixels;
+
+        receiver[rx]->playback_handle=NULL;
+        receiver[rx]->local_audio_buffer=NULL;
+        receiver[rx]->local_audio_buffer_size=2048;
+        receiver[rx]->local_audio=0;
+        g_mutex_init(&receiver[rx]->local_audio_mutex);
+        receiver[rx]->audio_name=NULL;
+        receiver[rx]->mute_when_not_active=0;
+        receiver[rx]->audio_channel=STEREO;
+        receiver[rx]->audio_device=-1;
+        receiver[rx]->mute_radio=0;
+
+g_print("rx=%d width=%d sample_rate=%d hz_per_pixel=%f pan=%d zoom=%d\n",rx,receiver[rx]->width,receiver[rx]->sample_rate,receiver[rx]->hz_per_pixel,receiver[rx]->pan,receiver[rx]->zoom);
+        }
+        break;
+      case INFO_TRANSMITTER:
+        {
+g_print("INFO_TRANSMITTER\n");
+        }
+        break;
+      case INFO_VFO:
+        {
+        VFO_DATA vfo_data;
+        bytes_read=recv_bytes(client_socket,(char *)&vfo_data.vfo,sizeof(vfo_data)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for VFO_DATA\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+
+g_print("INFO_VFO: %d\n",bytes_read);
+
+        int v=vfo_data.vfo;
+        vfo[v].band=ntohs(vfo_data.band);
+        vfo[v].bandstack=ntohs(vfo_data.bandstack);
+        vfo[v].frequency=ntohll(vfo_data.frequency);
+        vfo[v].mode=ntohs(vfo_data.mode);
+        vfo[v].filter=ntohs(vfo_data.filter);
+        vfo[v].ctun=vfo_data.ctun;
+        vfo[v].ctun_frequency=ntohll(vfo_data.ctun_frequency);
+        vfo[v].rit_enabled=vfo_data.rit_enabled;
+        vfo[v].rit=ntohll(vfo_data.rit);
+        vfo[v].lo=ntohll(vfo_data.lo);
+        vfo[v].offset=ntohll(vfo_data.offset);
+
+        // when VFO-B is initialized we can create the visual. start the MIDI interface and start the data flowing
+        if(v==VFO_B && !remote_started) {
+g_print("g_idle_add: remote_start\n");
+          g_idle_add(remote_start,(gpointer)server);
+        } else if(remote_started) {
+g_print("g_idle_add: ext_vfo_update\n");
+          g_idle_add(ext_vfo_update,(gpointer)NULL);
+        }
+        }
+        break;
+      case INFO_SPECTRUM:
+        {
+        SPECTRUM_DATA spectrum_data;
+        bytes_read=recv_bytes(client_socket,(char *)&spectrum_data.rx,sizeof(spectrum_data)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for SPECTRUM_DATA\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        int r=spectrum_data.rx;
+        long long frequency_a=ntohll(spectrum_data.vfo_a_freq);
+        long long frequency_b=ntohll(spectrum_data.vfo_b_freq);
+        long long ctun_frequency_a=ntohll(spectrum_data.vfo_a_ctun_freq);
+        long long ctun_frequency_b=ntohll(spectrum_data.vfo_b_ctun_freq);
+        long long offset_a=ntohll(spectrum_data.vfo_a_offset);
+        long long offset_b=ntohll(spectrum_data.vfo_b_offset);
+        short meter=ntohs(spectrum_data.meter);
+        receiver[r]->meter=(double)meter;
+        short samples=ntohs(spectrum_data.samples);
+        if(receiver[r]->pixel_samples==NULL) {
+          receiver[r]->pixel_samples=g_new(float,(int)samples);
+        }
+
+        short sample;
+        for(int i=0;i<samples;i++) {
+          sample=ntohs(spectrum_data.sample[i]);
+          receiver[r]->pixel_samples[i]=(float)sample;
+        }
+        if(vfo[VFO_A].frequency!=frequency_a || vfo[VFO_B].frequency!=frequency_b || vfo[VFO_A].ctun_frequency!=ctun_frequency_a || vfo[VFO_B].ctun_frequency!=ctun_frequency_b || vfo[VFO_A].offset!=offset_a || vfo[VFO_B].offset!=offset_b) {
+          vfo[VFO_A].frequency=frequency_a;
+          vfo[VFO_B].frequency=frequency_b;
+          vfo[VFO_A].ctun_frequency=ctun_frequency_a;
+          vfo[VFO_B].ctun_frequency=ctun_frequency_b;
+          vfo[VFO_A].offset=offset_a;
+          vfo[VFO_B].offset=offset_b;
+          g_idle_add(ext_vfo_update,(gpointer)NULL);
+        }
+        g_idle_add(ext_receiver_remote_update_display,receiver[r]);
+        }
+        break;
+      case INFO_AUDIO:
+        {
+        AUDIO_DATA audio_data;
+        bytes_read=recv_bytes(client_socket,(char *)&audio_data.rx,sizeof(audio_data)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for AUDIO_DATA\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        RECEIVER *rx=receiver[audio_data.rx];
+        short left_sample;
+        short right_sample;
+        int samples=ntohs(audio_data.samples);
+        if(rx->local_audio) {
+          for(int i=0;i<samples;i++) {
+            left_sample=ntohs(audio_data.sample[(i*2)]);
+            right_sample=ntohs(audio_data.sample[(i*2)+1]);
+            audio_write(rx,(float)left_sample/32767.0,(float)right_sample/32767.0);
+          }
+        }
+        }
+        break;
+      case CMD_RESP_RX_ZOOM:
+        {
+        ZOOM_COMMAND zoom_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&zoom_cmd.id,sizeof(zoom_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for ZOOM_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        int rx=zoom_cmd.id;
+        short zoom=ntohs(zoom_cmd.zoom);
+g_print("CMD_RESP_RX_ZOOM: zoom=%d rx[%d]->zoom=%d\n",zoom,rx,receiver[rx]->zoom);
+        if(receiver[rx]->zoom!=zoom) {
+          g_idle_add(ext_remote_set_zoom,GINT_TO_POINTER(zoom));
+        } else {
+          receiver_change_zoom(receiver[rx],(double)zoom);
+        }
+        }
+        break;
+      case CMD_RESP_RX_PAN:
+        {
+        PAN_COMMAND pan_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&pan_cmd.id,sizeof(pan_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for PAN_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        int rx=pan_cmd.id;
+        short pan=ntohs(pan_cmd.pan);
+g_print("CMD_RESP_RX_PAN: pan=%d rx[%d]->pan=%d\n",pan,rx,receiver[rx]->pan);
+        g_idle_add(ext_remote_set_pan,GINT_TO_POINTER(pan));
+        }
+        break;
+      case CMD_RESP_RX_VOLUME:
+        {
+        VOLUME_COMMAND volume_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&volume_cmd.id,sizeof(volume_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for VOLUME_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        int rx=volume_cmd.id;
+        short volume=ntohs(volume_cmd.volume);
+g_print("CMD_RESP_RX_VOLUME: volume=%d rx[%d]->volume=%f\n",volume,rx,receiver[rx]->volume);
+        receiver[rx]->volume=(double)volume/100.0;
+        }
+        break;
+      case CMD_RESP_RX_AGC:
+        {
+        AGC_COMMAND agc_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&agc_cmd.id,sizeof(agc_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for AGC_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        int rx=agc_cmd.id;
+        short a=ntohs(agc_cmd.agc);
+g_print("AGC_COMMAND: rx=%d agc=%d\n",rx,a);
+        receiver[rx]->agc=(int)a;
+        g_idle_add(ext_vfo_update,(gpointer)NULL);
+        }
+        break;
+      case CMD_RESP_RX_AGC_GAIN:
+        {
+        AGC_GAIN_COMMAND agc_gain_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&agc_gain_cmd.id,sizeof(agc_gain_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for AGC_GAIN_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        int rx=agc_gain_cmd.id;
+        short gain=ntohs(agc_gain_cmd.gain);
+        short hang=ntohs(agc_gain_cmd.hang);
+        short thresh=ntohs(agc_gain_cmd.thresh);
+        receiver[rx]->agc_gain=(double)gain;
+        receiver[rx]->agc_hang=(double)hang;
+        receiver[rx]->agc_thresh=(double)thresh;
+        }
+        break;
+      case CMD_RESP_RX_ATTENUATION:
+        {
+        ATTENUATION_COMMAND attenuation_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&attenuation_cmd.id,sizeof(attenuation_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for ATTENUATION_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        int rx=attenuation_cmd.id;
+        short attenuation=ntohs(attenuation_cmd.attenuation);
+g_print("CMD_RESP_RX_ATTENUATION: attenuation=%d adc_attenuation[rx[%d]->adc]=%d\n",attenuation,rx,adc_attenuation[receiver[rx]->adc]);
+        adc_attenuation[receiver[rx]->adc]=attenuation;
+        }
+        break;
+      case CMD_RESP_RX_NOISE:
+        {
+        NOISE_COMMAND noise_command;
+        bytes_read=recv_bytes(client_socket,(char *)&noise_command.id,sizeof(noise_command)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for NOISE_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        RECEIVER *rx=receiver[noise_command.id];
+        rx->nb=noise_command.nb;
+        rx->nb2=noise_command.nb2;
+        mode_settings[vfo[rx->id].mode].nb=rx->nb;
+        mode_settings[vfo[rx->id].mode].nb2=rx->nb2;
+        rx->nr=noise_command.nr;
+        rx->nr2=noise_command.nr2;
+        mode_settings[vfo[rx->id].mode].nr=rx->nr;
+        mode_settings[vfo[rx->id].mode].nr2=rx->nr2;
+        rx->snb=noise_command.snb;
+        mode_settings[vfo[rx->id].mode].snb=rx->snb;
+        rx->anf=noise_command.anf;
+        mode_settings[vfo[rx->id].mode].anf=rx->anf;
+        g_idle_add(ext_vfo_update,(gpointer)NULL);
+        }
+        break;
+      case CMD_RESP_RX_MODE:
+        {
+        MODE_COMMAND mode_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&mode_cmd.id,sizeof(mode_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for MODE_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        int rx=mode_cmd.id;
+        short m=ntohs(mode_cmd.mode);
+        vfo[rx].mode=m;
+        g_idle_add(ext_vfo_update,(gpointer)NULL);
+        }
+        break;
+      case CMD_RESP_RX_FILTER:
+        {
+        FILTER_COMMAND filter_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&filter_cmd.id,sizeof(filter_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for FILTER_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        int rx=filter_cmd.id;
+        short low=ntohs(filter_cmd.filter_low);
+        short high=ntohs(filter_cmd.filter_high);
+        receiver[rx]->filter_low=(int)low;
+        receiver[rx]->filter_high=(int)high;
+        g_idle_add(ext_vfo_update,(gpointer)NULL);
+        }
+        break;
+      case CMD_RESP_SPLIT:
+        {
+        SPLIT_COMMAND split_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&split_cmd.split,sizeof(split_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for SPLIT_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        split=split_cmd.split;
+        }
+        g_idle_add(ext_vfo_update,(gpointer)NULL);
+        break;
+      case CMD_RESP_SAT:
+        {
+        SAT_COMMAND sat_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&sat_cmd.sat,sizeof(sat_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for SAT_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        sat_mode=sat_cmd.sat;
+        }
+        g_idle_add(ext_vfo_update,(gpointer)NULL);
+        break;
+      case CMD_RESP_DUP:
+        {
+        DUP_COMMAND dup_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&dup_cmd.dup,sizeof(dup_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for DUP_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        duplex=dup_cmd.dup;
+        }
+        g_idle_add(ext_vfo_update,(gpointer)NULL);
+        break;
+      case CMD_RESP_LOCK:
+        {
+        LOCK_COMMAND lock_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&lock_cmd.lock,sizeof(lock_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for LOCK_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        locked=lock_cmd.lock;
+        }
+        g_idle_add(ext_vfo_update,(gpointer)NULL);
+        break;
+      case CMD_RESP_RX_FPS:
+        {
+        FPS_COMMAND fps_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&fps_cmd.id,sizeof(fps_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for FPS_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        int rx=fps_cmd.id;
+        receiver[rx]->fps=(int)fps_cmd.fps;
+        }
+        g_idle_add(ext_vfo_update,(gpointer)NULL);
+        break;
+      case CMD_RESP_RX_SELECT:
+        {
+        RX_SELECT_COMMAND rx_select_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&rx_select_cmd.id,sizeof(rx_select_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for RX_SELECT_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        int rx=rx_select_cmd.id;
+        active_receiver=receiver[rx];
+        }
+        g_idle_add(ext_vfo_update,(gpointer)NULL);
+        break;
+     case CMD_RESP_SAMPLE_RATE:
+        {
+        SAMPLE_RATE_COMMAND sample_rate_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&sample_rate_cmd.id,sizeof(sample_rate_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for SAMPLE_RATE_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        int rx=(int)sample_rate_cmd.id;
+        long long rate=ntohll(sample_rate_cmd.sample_rate);
+g_print("CMD_RESP_SAMPLE_RATE: rx=%d rate=%lld\n",rx,rate);
+        if(rx==-1) {
+          radio_sample_rate=(int)rate;
+          for(rx=0;rx<receivers;rx++) {
+            receiver[rx]->sample_rate=(int)rate;
+            receiver[rx]->hz_per_pixel=(double)receiver[rx]->sample_rate/(double)receiver[rx]->pixels;
+          }
+        } else {
+          receiver[rx]->sample_rate=(int)rate;
+          receiver[rx]->hz_per_pixel=(double)receiver[rx]->sample_rate/(double)receiver[rx]->pixels;
+        }
+        }
+        break;
+     case CMD_RESP_RECEIVERS:
+        {
+        RECEIVERS_COMMAND receivers_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&receivers_cmd.receivers,sizeof(receivers_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for RECEIVERS_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        int r=(int)receivers_cmd.receivers;
+g_print("CMD_RESP_RECEIVERS: receivers=%d\n",r);
+        radio_change_receivers(r);
+        }
+        break;
+      case CMD_RESP_RIT_INCREMENT:
+        {
+        RIT_INCREMENT_COMMAND rit_increment_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&rit_increment_cmd.increment,sizeof(rit_increment_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for RIT_INCREMENT_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        int increment=ntohs(rit_increment_cmd.increment);
+g_print("CMD_RESP_RIT_INCREMENT: increment=%d\n",increment);
+        rit_increment=increment;
+        }
+        break;
+      case CMD_RESP_FILTER_BOARD:
+        {
+        FILTER_BOARD_COMMAND filter_board_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&filter_board_cmd.filter_board,sizeof(filter_board_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for FILTER_BOARD_CMD\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        filter_board=(int)filter_board_cmd.filter_board;
+g_print("CMD_RESP_FILTER_BOARD: board=%d\n",filter_board);
+        }
+        break;
+      case CMD_RESP_SWAP_IQ:
+        {
+        SWAP_IQ_COMMAND swap_iq_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&swap_iq_cmd.iqswap,sizeof(swap_iq_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for SWAP_IQ_COMMAND\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        iqswap=(int)swap_iq_cmd.iqswap;
+g_print("CMD_RESP_IQ_SWAP: iqswap=%d\n",iqswap);
+        }
+        break;
+      case CMD_RESP_REGION:
+        {
+        REGION_COMMAND region_cmd;
+        bytes_read=recv_bytes(client_socket,(char *)&region_cmd.region,sizeof(region_cmd)-sizeof(header));
+        if(bytes_read<0) {
+          g_print("client_thread: read %d bytes for REGION_COMMAND\n",bytes_read);
+          perror("client_thread");
+          // dialog box?
+          return NULL;
+        }
+        region=(int)region_cmd.region;
+g_print("CMD_RESP_REGION: region=%d\n",region);
+        }
+        break;
+
+      default:
+g_print("client_thread: Unknown type=%d\n",ntohs(header.data_type));
+        break;
+    }
+  }
+  return NULL;
+}
+
+int radio_connect_remote(char *host, int port) {
+  struct sockaddr_in server_address;
+  gint on=1;
+
+g_print("radio_connect_remote: %s:%d\n",host,port);
+  client_socket=socket(AF_INET, SOCK_STREAM, 0); 
+  if(client_socket==-1) { 
+    g_print("radio_connect_remote: socket creation failed...\n"); 
+    return -1;
+  } 
+
+  setsockopt(client_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+  setsockopt(client_socket, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
+
+  struct hostent *server=gethostbyname(host);
+
+  if(server == NULL) {
+    g_print("radio_connect_remote: no such host: %s\n",host);
+    return -1;
+  }
+
+  // assign IP, PORT and bind to address
+  memset(&server_address,0,sizeof(server_address));
+  server_address.sin_family = AF_INET; 
+  bcopy((char *)server->h_addr,(char *)&server_address.sin_addr.s_addr,server->h_length);
+  server_address.sin_port = htons((short)port); 
+
+  if(connect(client_socket, (struct sockaddr *)&server_address, sizeof(server_address)) != 0) { 
+    g_print("client_thread: connect failed\n");
+    perror("client_thread");
+    return -1;
+  }
+
+g_print("radio_connect_remote: socket %d bound to %s:%d\n",client_socket,host,port);
+  sprintf(server_host,"%s:%d",host,port);
+  client_thread_id=g_thread_new("remote_client",client_thread,&server_host);
+  return 0;
+}
diff --git a/client_server.h b/client_server.h
new file mode 100644 (file)
index 0000000..926b93f
--- /dev/null
@@ -0,0 +1,516 @@
+/* Copyright (C)
+* 2020 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#ifndef HPSDR_SERVER_H
+#define HPSDR_SERVER_H
+
+#ifndef __APPLE__
+#define htonll htobe64
+#define ntohll be64toh
+#endif
+
+typedef enum {
+    RECEIVER_DETACHED, RECEIVER_ATTACHED
+} CLIENT_STATE;
+
+enum {
+  INFO_RADIO,
+  INFO_ADC,
+  INFO_RECEIVER,
+  INFO_TRANSMITTER,
+  INFO_VFO,
+  INFO_SPECTRUM,
+  INFO_AUDIO,
+  CMD_RESP_SPECTRUM,
+  CMD_RESP_AUDIO,
+  CMD_RESP_SAMPLE_RATE,
+  CMD_RESP_LOCK,
+  CMD_RESP_CTUN,
+  CMD_RESP_SPLIT,
+  CMD_RESP_SAT,
+  CMD_RESP_DUP,
+  CMD_RESP_STEP,
+  CMD_RESP_RECEIVERS,
+  CMD_RESP_RX_FREQ,
+  CMD_RESP_RX_STEP,
+  CMD_RESP_RX_MOVE,
+  CMD_RESP_RX_MOVETO,
+  CMD_RESP_RX_BAND,
+  CMD_RESP_RX_MODE,
+  CMD_RESP_RX_FILTER,
+  CMD_RESP_RX_AGC,
+  CMD_RESP_RX_NOISE,
+  CMD_RESP_RX_ZOOM,
+  CMD_RESP_RX_PAN,
+  CMD_RESP_RX_VOLUME,
+  CMD_RESP_RX_AGC_GAIN,
+  CMD_RESP_RX_ATTENUATION,
+  CMD_RESP_RX_SQUELCH,
+  CMD_RESP_RX_FPS,
+  CMD_RESP_RX_SELECT,
+  CMD_RESP_VFO,
+  CMD_RESP_RIT_UPDATE,
+  CMD_RESP_RIT_CLEAR,
+  CMD_RESP_RIT,
+  CMD_RESP_XIT_UPDATE,
+  CMD_RESP_XIT_CLEAR,
+  CMD_RESP_XIT,
+  CMD_RESP_RIT_INCREMENT,
+  CMD_RESP_FILTER_BOARD,
+  CMD_RESP_SWAP_IQ,
+  CMD_RESP_REGION,
+  CMD_RESP_MUTE_RX,
+};
+
+enum {
+  VFO_A_TO_B,
+  VFO_B_TO_A,
+  VFO_A_SWAP_B,
+};
+
+#define CLIENT_SERVER_VERSION 0LL
+
+#define SPECTRUM_DATA_SIZE 800
+#define AUDIO_DATA_SIZE 1024
+
+#define REMOTE_SYNC (uint16_t)0xFAFA
+
+typedef struct _remote_rx {
+  gint receiver;
+  gboolean send_audio;
+  gint audio_format;
+  gint audio_port;
+  struct sockaddr_in audio_address;
+  gboolean send_spectrum;
+  gint spectrum_fps;
+  gint spectrum_port;
+  struct sockaddr_in spectrum_address;
+} REMOTE_RX;
+
+typedef struct _remote_client {
+  gboolean running;
+  gint socket;
+  socklen_t address_length;
+  struct sockaddr_in address;
+  GThread *thread_id;
+  CLIENT_STATE state;
+  gint receivers;
+  gint spectrum_update_timer_id;
+  REMOTE_RX receiver[MAX_RECEIVERS];
+  void *next;
+} REMOTE_CLIENT;
+
+typedef struct __attribute__((__packed__)) _header {
+  uint16_t sync;
+  uint16_t data_type;
+  uint64_t version;
+  union {
+    uint64_t i;
+    REMOTE_CLIENT *client;
+  } context;
+} HEADER;
+
+typedef struct __attribute__((__packed__)) _radio_data {
+  HEADER header;
+  char name[32];
+  uint16_t protocol;
+  uint16_t device;
+  uint64_t sample_rate;
+  uint64_t frequency_min;
+  uint64_t frequency_max;
+  uint8_t display_filled;
+  uint8_t locked;
+  uint16_t supported_receivers;
+  uint16_t receivers;
+  uint8_t can_transmit;
+  uint64_t step;
+  uint8_t split;
+  uint8_t sat_mode;
+  uint8_t duplex;
+  uint8_t have_rx_gain;
+  uint16_t rx_gain_calibration;
+  uint16_t filter_board;
+} RADIO_DATA;
+
+typedef struct __attribute__((__packed__)) _adc_data {
+  HEADER header;
+  uint8_t adc;
+  uint16_t filters;
+  uint16_t hpf;
+  uint16_t lpf;
+  uint16_t antenna;
+  uint8_t dither;
+  uint8_t random;
+  uint8_t preamp;
+  uint16_t attenuation;
+  uint16_t adc_attenuation;
+} ADC_DATA;
+
+typedef struct __attribute__((__packed__)) _receiver_data {
+  HEADER header;
+  uint8_t rx;
+  uint16_t adc;
+  uint64_t sample_rate;
+  uint8_t displaying;
+  uint8_t display_panadapter;
+  uint8_t display_waterfall;
+  uint16_t fps;
+  uint8_t agc;
+  uint16_t agc_hang;
+  uint16_t agc_thresh;
+  uint8_t nb;
+  uint8_t nb2;
+  uint8_t nr;
+  uint8_t nr2;
+  uint8_t anf;
+  uint8_t snb;
+  uint16_t filter_low;
+  uint16_t filter_high;
+  uint16_t panadapter_low;
+  uint16_t panadapter_high;
+  uint16_t panadapter_step;
+  uint16_t waterfall_low;
+  uint16_t waterfall_high;
+  uint8_t waterfall_automatic;
+  uint16_t pixels;
+  uint16_t zoom;
+  uint16_t pan;
+  uint16_t width;
+  uint16_t height;
+  uint16_t x;
+  uint16_t y;
+  uint16_t volume;
+  uint16_t rf_gain;
+  uint16_t agc_gain;
+} RECEIVER_DATA;
+
+typedef struct __attribute__((__packed__)) _vfo_data {
+  HEADER header;
+  uint8_t vfo;
+  uint16_t band;
+  uint16_t bandstack;
+  uint64_t frequency;
+  uint16_t mode;
+  uint16_t filter;
+  uint8_t ctun;
+  uint64_t ctun_frequency;
+  uint8_t rit_enabled;
+  uint64_t rit;
+  uint64_t lo;
+  uint64_t offset;
+} VFO_DATA;
+
+typedef struct __attribute__((__packed__)) _spectrum_data {
+  HEADER header;
+  uint8_t rx;
+  uint64_t vfo_a_freq;
+  uint64_t vfo_b_freq;
+  uint64_t vfo_a_ctun_freq;
+  uint64_t vfo_b_ctun_freq;
+  uint64_t vfo_a_offset;
+  uint64_t vfo_b_offset;
+  uint16_t meter;
+  uint16_t samples;
+  uint16_t sample[SPECTRUM_DATA_SIZE];
+} SPECTRUM_DATA;
+
+typedef struct __attribute__((__packed__)) _audio_data {
+  HEADER header;
+  uint8_t rx;
+  uint16_t samples;
+  uint16_t sample[AUDIO_DATA_SIZE*2];
+} AUDIO_DATA;
+
+typedef struct __attribute__((__packed__)) _spectrum_command {
+  HEADER header;
+  int8_t id;
+  uint8_t start_stop;
+} SPECTRUM_COMMAND;
+
+typedef struct __attribute__((__packed__)) _freq_command {
+  HEADER header;
+  uint8_t id;
+  uint64_t hz;
+} FREQ_COMMAND;
+
+typedef struct __attribute__((__packed__)) _step_command {
+  HEADER header;
+  uint8_t id;
+  uint16_t steps;
+} STEP_COMMAND;
+
+typedef struct __attribute__((__packed__)) _sample_rate_command {
+  HEADER header;
+  int8_t id;
+  uint64_t sample_rate;
+} SAMPLE_RATE_COMMAND;
+
+typedef struct __attribute__((__packed__)) _receivers_command {
+  HEADER header;
+  uint8_t receivers;
+} RECEIVERS_COMMAND;
+
+typedef struct __attribute__((__packed__)) _move_command {
+  HEADER header;
+  uint8_t id;
+  uint64_t hz;
+  uint8_t round;
+} MOVE_COMMAND;
+
+typedef struct __attribute__((__packed__)) _move_to_command {
+  HEADER header;
+  uint8_t id;
+  uint64_t hz;
+} MOVE_TO_COMMAND;
+
+typedef struct __attribute__((__packed__)) _zoom_command {
+  HEADER header;
+  uint8_t id;
+  uint16_t zoom;
+} ZOOM_COMMAND;
+
+typedef struct __attribute__((__packed__)) _pan_command {
+  HEADER header;
+  uint8_t id;
+  uint16_t pan;
+} PAN_COMMAND;
+
+typedef struct __attribute__((__packed__)) _volume_command {
+  HEADER header;
+  uint8_t id;
+  uint16_t volume;
+} VOLUME_COMMAND;
+
+typedef struct __attribute__((__packed__)) _band_command {
+  HEADER header;
+  uint8_t id;
+  uint16_t band;
+} BAND_COMMAND;
+
+typedef struct __attribute__((__packed__)) _mode_command {
+  HEADER header;
+  uint8_t id;
+  uint16_t mode;
+} MODE_COMMAND;
+
+typedef struct __attribute__((__packed__)) _filter_command {
+  HEADER header;
+  uint8_t id;
+  uint16_t filter;
+  uint16_t filter_low;
+  uint16_t filter_high;
+} FILTER_COMMAND;
+
+typedef struct __attribute__((__packed__)) _agc_command {
+  HEADER header;
+  uint8_t id;
+  uint16_t agc;
+} AGC_COMMAND;
+
+typedef struct __attribute__((__packed__)) _agc_gain_command {
+  HEADER header;
+  uint8_t id;
+  uint16_t gain;
+  uint16_t hang;
+  uint16_t thresh;
+} AGC_GAIN_COMMAND;
+
+typedef struct __attribute__((__packed__)) _attenuation_command {
+  HEADER header;
+  uint8_t id;
+  uint16_t attenuation;
+} ATTENUATION_COMMAND;
+
+typedef struct __attribute__((__packed__)) _squelch_command {
+  HEADER header;
+  uint8_t id;
+  uint8_t enable;
+  uint16_t squelch;
+} SQUELCH_COMMAND;
+
+typedef struct __attribute__((__packed__)) _noise_command {
+  HEADER header;
+  uint8_t id;
+  uint8_t nb;
+  uint8_t nb2;
+  uint8_t nr;
+  uint8_t nr2;
+  uint8_t anf;
+  uint8_t snb;
+} NOISE_COMMAND;
+
+typedef struct __attribute__((__packed__)) _split_command {
+  HEADER header;
+  uint8_t split;
+} SPLIT_COMMAND;
+
+typedef struct __attribute__((__packed__)) _sat_command {
+  HEADER header;
+  uint8_t sat;
+} SAT_COMMAND;
+
+typedef struct __attribute__((__packed__)) _dup_command {
+  HEADER header;
+  uint8_t dup;
+} DUP_COMMAND;
+
+typedef struct __attribute__((__packed__)) _fps_command {
+  HEADER header;
+  uint8_t id;
+  uint8_t fps;
+} FPS_COMMAND;
+
+typedef struct __attribute__((__packed__)) _ctun_command {
+  HEADER header;
+  uint8_t id;
+  uint8_t ctun;
+} CTUN_COMMAND;
+
+typedef struct __attribute__((__packed__)) _rx_select_command {
+  HEADER header;
+  uint8_t id;
+} RX_SELECT_COMMAND;
+
+typedef struct __attribute__((__packed__)) _vfo_command {
+  HEADER header;
+  uint8_t id;
+} VFO_COMMAND;
+
+typedef struct __attribute__((__packed__)) _lock_command {
+  HEADER header;
+  uint8_t lock;
+} LOCK_COMMAND;
+
+typedef struct __attribute__((__packed__)) _rit_update_command {
+  HEADER header;
+  uint8_t id;
+} RIT_UPDATE_COMMAND;
+
+typedef struct __attribute__((__packed__)) _rit_clear_command {
+  HEADER header;
+  uint8_t id;
+} RIT_CLEAR_COMMAND;
+
+typedef struct __attribute__((__packed__)) _rit_command {
+  HEADER header;
+  uint8_t id;
+  uint16_t rit;
+} RIT_COMMAND;
+
+typedef struct __attribute__((__packed__)) _xit_update_command {
+  HEADER header;
+} XIT_UPDATE_COMMAND;
+
+typedef struct __attribute__((__packed__)) _xit_clear_command {
+  HEADER header;
+} XIT_CLEAR_COMMAND;
+
+typedef struct __attribute__((__packed__)) _xit_command {
+  HEADER header;
+  uint16_t xit;
+} XIT_COMMAND;
+
+typedef struct __attribute__((__packed__)) _rit_increment {
+  HEADER header;
+  uint16_t increment;
+} RIT_INCREMENT_COMMAND;
+
+typedef struct __attribute__((__packed__)) _filter_board {
+  HEADER header;
+  uint8_t filter_board;
+} FILTER_BOARD_COMMAND;
+
+typedef struct __attribute__((__packed__)) _swap_iq {
+  HEADER header;
+  uint8_t iqswap;
+} SWAP_IQ_COMMAND;
+
+typedef struct __attribute__((__packed__)) _region {
+  HEADER header;
+  uint8_t region;
+} REGION_COMMAND;
+
+typedef struct __attribute__((__packed__)) _mute_rx {
+  HEADER header;
+  uint8_t mute;
+} MUTE_RX_COMMAND;
+
+extern gboolean hpsdr_server;
+extern gboolean hpsdr_server;
+extern gint client_socket;
+extern gint start_spectrum(void *data);
+extern void start_vfo_timer();
+extern gboolean remote_started;
+
+
+extern REMOTE_CLIENT *clients;
+
+extern gint listen_port;
+
+extern int create_hpsdr_server();
+extern int destroy_hpsdr_server();
+
+extern int radio_connect_remote(char *host, int port);
+
+extern void send_radio_data(REMOTE_CLIENT *client);
+extern void send_adc_data(REMOTE_CLIENT *client,int i);
+extern void send_receiver_data(REMOTE_CLIENT *client,int rx);
+extern void send_vfo_data(REMOTE_CLIENT *client,int v);
+
+extern void send_start_spectrum(int s,int rx);
+extern void send_vfo_frequency(int s,int rx,long long hz);
+extern void send_vfo_move_to(int s,int rx,long long hz);
+extern void send_vfo_move(int s,int rx,long long hz,int round);
+extern void update_vfo_move(int rx,long long hz,int round);
+extern void send_vfo_step(int s,int rx,int steps);
+extern void update_vfo_step(int rx,int steps);
+extern void send_zoom(int s,int rx,int zoom);
+extern void send_pan(int s,int rx,int pan);
+extern void send_volume(int s,int rx,int volume);
+extern void send_agc(int s,int rx,int agc);
+extern void send_agc_gain(int s,int rx,int gain,int hang,int thresh);
+extern void send_attenuation(int s,int rx,int attenuation);
+extern void send_squelch(int s,int rx,int enable,int squelch);
+extern void send_noise(int s,int rx,int nb,int nb2,int nr,int nr2,int anf,int snb);
+extern void send_band(int s,int rx,int band);
+extern void send_mode(int s,int rx,int mode);
+extern void send_filter(int s,int rx,int filter);
+extern void send_split(int s,int split);
+extern void send_sat(int s,int sat);
+extern void send_dup(int s,int dup);
+extern void send_ctun(int s,int vfo,int ctun);
+extern void send_fps(int s,int rx,int fps);
+extern void send_rx_select(int s,int rx);
+extern void send_vfo(int s,int action);
+extern void send_lock(int s,int lock);
+extern void send_rit_update(int s,int rx);
+extern void send_rit_clear(int s,int rx);
+extern void send_rit(int s,int rx,int rit);
+extern void send_sample_rate(int s,int rx,int sample_rate);
+extern void send_receivers(int s,int receivers);
+extern void send_rit_increment(int s,int increment);
+extern void send_filter_board(int s,int filter_board);
+extern void send_swap_iq(int s,int swap_iq);
+extern void send_region(int s,int region);
+extern void send_mute_rx(int s,int mute);
+
+
+extern void remote_audio(RECEIVER *rx,short left_sample,short right_sample);
+
+#endif
index c6bca2ce7419f1af656d2756fa3a8810a85548c5..dc71bfcb0dbc30a41038184f861691460c547134 100644 (file)
@@ -55,7 +55,7 @@
 #define NEW_DEVICE_HERMES_LITE2 1006
 
 #ifdef SOAPYSDR
-#define SOAPYSDR_USB_DEVICE 0
+#define SOAPYSDR_USB_DEVICE 2000
 #endif
 
 #define STATE_AVAILABLE 2
@@ -67,9 +67,6 @@
 #define SOAPYSDR_PROTOCOL 2
 #endif
 
-#ifdef REMOTE
-#define REMOTE_PROTOCOL 4
-#endif
 #ifdef STEMLAB_DISCOVERY
 // A STEMlab discovered via Avahi will have this protocol until the SDR
 // application itself is started, at which point it will be changed to the old
index 64973ecc20d3062f3b6190dec101b7020b7a7aa8..c9d6c99fafae3e3e13349e6c4a35bb827043ef5e 100644 (file)
@@ -42,9 +42,6 @@
 #ifdef USBOZY
 #include "ozyio.h"
 #endif
-#ifdef REMOTE
-#include "remote_radio.h"
-#endif
 #ifdef STEMLAB_DISCOVERY
 #include "stemlab_discovery.h"
 #endif
 #include "configure.h"
 #endif
 #include "protocols.h"
+#ifdef CLIENT_SERVER
+#include "client_server.h"
+#endif
+#include "property.h"
 
 static GtkWidget *discovery_dialog;
 static DISCOVERED *d;
@@ -67,10 +68,12 @@ GtkWidget *tcpaddr;
 static char ipaddr_tcp_buf[IPADDR_LEN] = "10.10.10.10";
 char *ipaddr_tcp = &ipaddr_tcp_buf[0];
 
-#ifdef SERVER
-GtkWidget *connect_addr_entry;
-static char connect_addr_buffer[30]="0.0.0.0:50000";
-char *connect_addr = &connect_addr_buffer[0];
+#ifdef CLIENT_SERVER
+GtkWidget *host_addr_entry;
+static char host_addr_buffer[128]="g0orx.ddns.net";
+char *host_addr = &host_addr_buffer[0];
+GtkWidget *host_port_spinner;
+gint host_port=45000;
 #endif
 
 static gboolean delete_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data) {
@@ -262,11 +265,30 @@ static gboolean tcp_cb (GtkWidget *widget, GdkEventButton *event, gpointer data)
            return TRUE;
        }
 
-#ifdef SERVER
+#ifdef CLIENT_SERVER
 static gboolean connect_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   // connect to remote host running piHPSDR
-  strncpy(connect_addr, gtk_entry_get_text(GTK_ENTRY(connect_addr_entry)), 30);
-g_print("connect_cb: %s\n",connect_addr);
+  strncpy(host_addr, gtk_entry_get_text(GTK_ENTRY(host_addr_entry)), 30);
+  host_port=gtk_spin_button_get_value(GTK_SPIN_BUTTON(host_port_spinner));
+g_print("connect_cb: %s:%d\n",host_addr,host_port);
+  setProperty("host",host_addr);
+  char temp[16];
+  sprintf(temp,"%d",host_port);
+  setProperty("port",temp);
+  saveProperties("remote.props");
+  if(radio_connect_remote(host_addr,host_port)==0) {
+    gtk_widget_destroy(discovery_dialog);
+  } else {
+    // dialog box to display connection error
+    GtkWidget *dialog=gtk_dialog_new_with_buttons("Remote Connect",GTK_WINDOW(discovery_dialog),GTK_DIALOG_DESTROY_WITH_PARENT,"OK",GTK_RESPONSE_NONE,NULL);
+    GtkWidget *content_area=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+    char message[128];
+    sprintf(message,"Connection failed to %s:%d",host_addr,host_port);
+    GtkWidget *label=gtk_label_new(message);
+    g_signal_connect_swapped(dialog,"response",G_CALLBACK(gtk_widget_destroy),dialog);
+    gtk_container_add(GTK_CONTAINER(content_area),label);
+    gtk_widget_show_all(dialog);
+  }
   return TRUE;
 }
 #endif
@@ -282,7 +304,7 @@ void discovery() {
   // Try to locate IP addr
   FILE *fp=fopen("ip.addr","r");
   if (fp) {
-    fgets(ipaddr_tcp, IPADDR_LEN,fp);
+    char *c=fgets(ipaddr_tcp, IPADDR_LEN,fp);
     fclose(fp);
     ipaddr_tcp[IPADDR_LEN-1]=0;
     // remove possible trailing newline char in ipaddr_tcp
@@ -341,55 +363,6 @@ void discovery() {
 
   status_text("Discovery");
   
-  if(devices==0) {
-    gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_ARROW));
-    discovery_dialog = gtk_dialog_new();
-    gtk_window_set_transient_for(GTK_WINDOW(discovery_dialog),GTK_WINDOW(top_window));
-    gtk_window_set_title(GTK_WINDOW(discovery_dialog),"piHPSDR - Discovery");
-    //gtk_window_set_decorated(GTK_WINDOW(discovery_dialog),FALSE);
-
-    //gtk_widget_override_font(discovery_dialog, pango_font_description_from_string("FreeMono 16"));
-    g_signal_connect(discovery_dialog, "delete_event", G_CALLBACK(delete_event_cb), NULL);
-
-    GdkRGBA color;
-    color.red = 1.0;
-    color.green = 1.0;
-    color.blue = 1.0;
-    color.alpha = 1.0;
-    gtk_widget_override_background_color(discovery_dialog,GTK_STATE_FLAG_NORMAL,&color);
-
-    GtkWidget *content;
-
-    content=gtk_dialog_get_content_area(GTK_DIALOG(discovery_dialog));
-
-    GtkWidget *grid=gtk_grid_new();
-    gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-    gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
-    gtk_grid_set_row_spacing (GTK_GRID(grid),10);
-
-    GtkWidget *label=gtk_label_new("No devices found!");
-    gtk_grid_attach(GTK_GRID(grid),label,0,0,2,1);
-
-    GtkWidget *exit_b=gtk_button_new_with_label("Exit");
-    g_signal_connect (exit_b, "button-press-event", G_CALLBACK(exit_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),exit_b,0,1,1,1);
-
-    GtkWidget *discover_b=gtk_button_new_with_label("Retry Discovery");
-    g_signal_connect (discover_b, "button-press-event", G_CALLBACK(discover_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),discover_b,1,1,1,1);
-
-    GtkWidget *tcp_b=gtk_button_new_with_label("Use new TCP Addr:");
-    g_signal_connect (tcp_b, "button-press-event", G_CALLBACK(tcp_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),tcp_b,0,2,1,1);
-
-    tcpaddr=gtk_entry_new();
-    gtk_entry_set_max_length(GTK_ENTRY(tcpaddr), 20);
-    gtk_grid_attach(GTK_GRID(grid),tcpaddr,1,2,1,1);
-    gtk_entry_set_text(GTK_ENTRY(tcpaddr), ipaddr_tcp);
-
-    gtk_container_add (GTK_CONTAINER (content), grid);
-    gtk_widget_show_all(discovery_dialog);
-  } else {
     fprintf(stderr,"discovery: found %d devices\n", devices);
     gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_ARROW));
     discovery_dialog = gtk_dialog_new();
@@ -416,133 +389,171 @@ void discovery() {
     //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
     gtk_grid_set_row_spacing (GTK_GRID(grid),10);
 
-    int row;
-    char version[16];
-    char text[256];
-    for(row=0;row<devices;row++) {
-      d=&discovered[row];
+    int row=0;
+    if(devices==0) {
+      GtkWidget *label=gtk_label_new("No local devices found!");
+      gtk_grid_attach(GTK_GRID(grid),label,0,row,3,1);
+      row++;
+    } else {
+      char version[16];
+      char text[256];
+      for(row=0;row<devices;row++) {
+        d=&discovered[row];
 fprintf(stderr,"%p Protocol=%d name=%s\n",d,d->protocol,d->name);
-      sprintf(version,"v%d.%d",
-                        d->software_version/10,
-                        d->software_version%10);
-      switch(d->protocol) {
-        case ORIGINAL_PROTOCOL:
-        case NEW_PROTOCOL:
+        sprintf(version,"v%d.%d",
+                          d->software_version/10,
+                          d->software_version%10);
+        switch(d->protocol) {
+          case ORIGINAL_PROTOCOL:
+          case NEW_PROTOCOL:
 #ifdef USBOZY
-          if(d->device==DEVICE_OZY) {
-            sprintf(text,"%s (%s) on USB /dev/ozy", d->name, d->protocol==ORIGINAL_PROTOCOL?"Protocol 1":"Protocol 2");
-          } else {
+            if(d->device==DEVICE_OZY) {
+              sprintf(text,"%s (%s) on USB /dev/ozy", d->name, d->protocol==ORIGINAL_PROTOCOL?"Protocol 1":"Protocol 2");
+            } else {
 #endif
-            sprintf(text,"%s (%s %s) %s (%02X:%02X:%02X:%02X:%02X:%02X) on %s: ",
-                          d->name,
-                          d->protocol==ORIGINAL_PROTOCOL?"Protocol 1":"Protocol 2",
-                          version,
-                          inet_ntoa(d->info.network.address.sin_addr),
-                          d->info.network.mac_address[0],
-                          d->info.network.mac_address[1],
-                          d->info.network.mac_address[2],
-                          d->info.network.mac_address[3],
-                          d->info.network.mac_address[4],
-                          d->info.network.mac_address[5],
-                          d->info.network.interface_name);
+              sprintf(text,"%s (%s %s) %s (%02X:%02X:%02X:%02X:%02X:%02X) on %s: ",
+                            d->name,
+                            d->protocol==ORIGINAL_PROTOCOL?"Protocol 1":"Protocol 2",
+                            version,
+                            inet_ntoa(d->info.network.address.sin_addr),
+                            d->info.network.mac_address[0],
+                            d->info.network.mac_address[1],
+                            d->info.network.mac_address[2],
+                            d->info.network.mac_address[3],
+                            d->info.network.mac_address[4],
+                            d->info.network.mac_address[5],
+                            d->info.network.interface_name);
 #ifdef USBOZY
-          }
+            }
 #endif
-          break;
+            break;
 #ifdef SOAPYSDR
-        case SOAPYSDR_PROTOCOL:
-          sprintf(text,"%s (Protocol SOAPY_SDR %s) on USB",d->name,d->info.soapy.version);
-          break;
+          case SOAPYSDR_PROTOCOL:
+            sprintf(text,"%s (Protocol SOAPY_SDR %s) on USB",d->name,d->info.soapy.version);
+            break;
 #endif
 #ifdef STEMLAB_DISCOVERY
-        case STEMLAB_PROTOCOL:
+          case STEMLAB_PROTOCOL:
 #ifdef NO_AVAHI
-         sprintf(text,"Choose RedPitaya App from %s and start radio: ",inet_ntoa(d->info.network.address.sin_addr));
+            sprintf(text,"Choose RedPitaya App from %s and start radio: ",inet_ntoa(d->info.network.address.sin_addr));
 #else
-          sprintf(text, "STEMlab (%02X:%02X:%02X:%02X:%02X:%02X) on %s",
-                         d->info.network.mac_address[0],
-                         d->info.network.mac_address[1],
-                         d->info.network.mac_address[2],
-                         d->info.network.mac_address[3],
-                         d->info.network.mac_address[4],
-                         d->info.network.mac_address[5],
-                         d->info.network.interface_name);
+            sprintf(text, "STEMlab (%02X:%02X:%02X:%02X:%02X:%02X) on %s",
+                           d->info.network.mac_address[0],
+                           d->info.network.mac_address[1],
+                           d->info.network.mac_address[2],
+                           d->info.network.mac_address[3],
+                           d->info.network.mac_address[4],
+                           d->info.network.mac_address[5],
+                           d->info.network.interface_name);
 #endif
 #endif
-      }
-
-      GtkWidget *label=gtk_label_new(text);
-      gtk_widget_override_font(label, pango_font_description_from_string("Sans 11"));
-      gtk_widget_set_halign (label, GTK_ALIGN_START);
-      gtk_widget_show(label);
-      gtk_grid_attach(GTK_GRID(grid),label,0,row,3,1);
-
-      GtkWidget *start_button=gtk_button_new_with_label("Start");
-      gtk_widget_override_font(start_button, pango_font_description_from_string("Sans 16"));
-      gtk_widget_show(start_button);
-      gtk_grid_attach(GTK_GRID(grid),start_button,3,row,1,1);
-      g_signal_connect(start_button,"button_press_event",G_CALLBACK(start_cb),(gpointer)d);
+        }
 
-      // if not available then cannot start it
-      if(d->status!=STATE_AVAILABLE) {
-        gtk_button_set_label(GTK_BUTTON(start_button),"In Use");
-        gtk_widget_set_sensitive(start_button, FALSE);
-      }
+        GtkWidget *label=gtk_label_new(text);
+        gtk_widget_override_font(label, pango_font_description_from_string("Sans 11"));
+        gtk_widget_set_halign (label, GTK_ALIGN_START);
+        gtk_widget_show(label);
+        gtk_grid_attach(GTK_GRID(grid),label,0,row,3,1);
+
+        GtkWidget *start_button=gtk_button_new_with_label("Start");
+        gtk_widget_override_font(start_button, pango_font_description_from_string("Sans 16"));
+        gtk_widget_show(start_button);
+        gtk_grid_attach(GTK_GRID(grid),start_button,3,row,1,1);
+        g_signal_connect(start_button,"button_press_event",G_CALLBACK(start_cb),(gpointer)d);
+
+        // if not available then cannot start it
+        if(d->status!=STATE_AVAILABLE) {
+          gtk_button_set_label(GTK_BUTTON(start_button),"In Use");
+          gtk_widget_set_sensitive(start_button, FALSE);
+        }
 
 #ifdef SOAPYSDR
-      if(d->device!=SOAPYSDR_USB_DEVICE) {
+        if(d->device!=SOAPYSDR_USB_DEVICE) {
 #endif
-        // if not on the same subnet then cannot start it
-        if((d->info.network.interface_address.sin_addr.s_addr&d->info.network.interface_netmask.sin_addr.s_addr) != (d->info.network.address.sin_addr.s_addr&d->info.network.interface_netmask.sin_addr.s_addr)) {
-          gtk_button_set_label(GTK_BUTTON(start_button),"Subnet!");
-          gtk_widget_set_sensitive(start_button, FALSE);
-        }
+          // if not on the same subnet then cannot start it
+          if((d->info.network.interface_address.sin_addr.s_addr&d->info.network.interface_netmask.sin_addr.s_addr) != (d->info.network.address.sin_addr.s_addr&d->info.network.interface_netmask.sin_addr.s_addr)) {
+            gtk_button_set_label(GTK_BUTTON(start_button),"Subnet!");
+            gtk_widget_set_sensitive(start_button, FALSE);
+          }
 #ifdef SOAPYSDR
-      }
+        }
 #endif
 
 #ifdef STEMLAB_DISCOVERY
-      if (d->protocol == STEMLAB_PROTOCOL) {
-        if (d->software_version == 0) {
-          gtk_button_set_label(GTK_BUTTON(start_button), "Not installed");
-          gtk_widget_set_sensitive(start_button, FALSE);
-        } else {
-          apps_combobox[row] = gtk_combo_box_text_new();
-          gtk_widget_override_font(apps_combobox[row], pango_font_description_from_string("Sans 11"));
-          // We want the default selection priority for the STEMlab app to be
-          // RP-Trx > HAMlab-Trx > Pavel-Trx > Pavel-Rx, so we add in decreasing order and
-          // always set the newly added entry to be active.
-          if ((d->software_version & STEMLAB_PAVEL_RX) != 0) {
-            gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(apps_combobox[row]),
-                "sdr_receiver_hpsdr", "Pavel-Rx");
-            gtk_combo_box_set_active_id(GTK_COMBO_BOX(apps_combobox[row]),
-                "sdr_receiver_hpsdr");
-          }
-          if ((d->software_version & STEMLAB_PAVEL_TRX) != 0) {
-            gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(apps_combobox[row]),
-                "sdr_transceiver_hpsdr", "Pavel-Trx");
-            gtk_combo_box_set_active_id(GTK_COMBO_BOX(apps_combobox[row]),
-                "sdr_transceiver_hpsdr");
-          }
-          if ((d->software_version & HAMLAB_RP_TRX) != 0) {
-            gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(apps_combobox[row]),
-                "hamlab_sdr_transceiver_hpsdr", "HAMlab-Trx");
-            gtk_combo_box_set_active_id(GTK_COMBO_BOX(apps_combobox[row]),
-                "hamlab_sdr_transceiver_hpsdr");
-          }
-          if ((d->software_version & STEMLAB_RP_TRX) != 0) {
-            gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(apps_combobox[row]),
+        if (d->protocol == STEMLAB_PROTOCOL) {
+          if (d->software_version == 0) {
+            gtk_button_set_label(GTK_BUTTON(start_button), "Not installed");
+            gtk_widget_set_sensitive(start_button, FALSE);
+          } else {
+            apps_combobox[row] = gtk_combo_box_text_new();
+            gtk_widget_override_font(apps_combobox[row], pango_font_description_from_string("Sans 11"));
+            // We want the default selection priority for the STEMlab app to be
+            // RP-Trx > HAMlab-Trx > Pavel-Trx > Pavel-Rx, so we add in decreasing order and
+            // always set the newly added entry to be active.
+            if ((d->software_version & STEMLAB_PAVEL_RX) != 0) {
+              gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(apps_combobox[row]),
+                  "sdr_receiver_hpsdr", "Pavel-Rx");
+              gtk_combo_box_set_active_id(GTK_COMBO_BOX(apps_combobox[row]),
+                  "sdr_receiver_hpsdr");
+            }
+            if ((d->software_version & STEMLAB_PAVEL_TRX) != 0) {
+              gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(apps_combobox[row]),
+                  "sdr_transceiver_hpsdr", "Pavel-Trx");
+              gtk_combo_box_set_active_id(GTK_COMBO_BOX(apps_combobox[row]),
+                  "sdr_transceiver_hpsdr");
+            }
+            if ((d->software_version & HAMLAB_RP_TRX) != 0) {
+              gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(apps_combobox[row]),
+                  "hamlab_sdr_transceiver_hpsdr", "HAMlab-Trx");
+              gtk_combo_box_set_active_id(GTK_COMBO_BOX(apps_combobox[row]),
+                  "hamlab_sdr_transceiver_hpsdr");
+            }
+            if ((d->software_version & STEMLAB_RP_TRX) != 0) {
+              gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(apps_combobox[row]),
                 "stemlab_sdr_transceiver_hpsdr", "STEMlab-Trx");
-            gtk_combo_box_set_active_id(GTK_COMBO_BOX(apps_combobox[row]),
-                "stemlab_sdr_transceiver_hpsdr");
+              gtk_combo_box_set_active_id(GTK_COMBO_BOX(apps_combobox[row]),
+                  "stemlab_sdr_transceiver_hpsdr");
+            }
+            gtk_widget_show(apps_combobox[row]);
+            gtk_grid_attach(GTK_GRID(grid), apps_combobox[row], 4, row, 1, 1);
           }
-          gtk_widget_show(apps_combobox[row]);
-          gtk_grid_attach(GTK_GRID(grid), apps_combobox[row], 4, row, 1, 1);
         }
-      }
 #endif
 
+      }
     }
+
+#ifdef CLIENT_SERVER
+
+    loadProperties("remote.props");
+    char *value;
+    value=getProperty("host");
+    if(value!=NULL) strcpy(host_addr_buffer,value);
+    value=getProperty("port");
+    if(value!=NULL) host_port=atoi(value);
+
+    GtkWidget *connect_b=gtk_button_new_with_label("Connect to Server");
+    g_signal_connect (connect_b, "button-press-event", G_CALLBACK(connect_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),connect_b,0,row,1,1);
+
+    host_addr_entry=gtk_entry_new();
+    gtk_entry_set_max_length(GTK_ENTRY(host_addr_entry), 30);
+    gtk_grid_attach(GTK_GRID(grid),host_addr_entry,1,row,1,1);
+    gtk_entry_set_text(GTK_ENTRY(host_addr_entry), host_addr);
+
+    GtkWidget *host_port_label =gtk_label_new(NULL);
+    gtk_label_set_markup(GTK_LABEL(host_port_label), "<b>Server Port</b>");
+    gtk_widget_show(host_port_label);
+    gtk_grid_attach(GTK_GRID(grid),host_port_label,2,row,1,1);
+
+    host_port_spinner =gtk_spin_button_new_with_range(45000,55000,1);
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(host_port_spinner),(double)host_port);
+    gtk_widget_show(host_port_spinner);
+    gtk_grid_attach(GTK_GRID(grid),host_port_spinner,3,row,1,1);
+
+    row++;
+#endif
+
 #ifdef GPIO
     controller=CONTROLLER2_V2;
     gpio_set_defaults(controller);
@@ -594,25 +605,9 @@ fprintf(stderr,"%p Protocol=%d name=%s\n",d,d->protocol,d->name);
     g_signal_connect (exit_b, "button-press-event", G_CALLBACK(exit_cb), NULL);
     gtk_grid_attach(GTK_GRID(grid),exit_b,3,row,1,1);
 
-#ifdef SERVER
-    row++;
-
-    GtkWidget *connect_b=gtk_button_new_with_label("Connect (Addr:Port)");
-    g_signal_connect (connect_b, "button-press-event", G_CALLBACK(connect_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),connect_b,0,row,1,1);
-
-    connect_addr_entry=gtk_entry_new();
-    gtk_entry_set_max_length(GTK_ENTRY(connect_addr_entry), 30);
-    gtk_grid_attach(GTK_GRID(grid),connect_addr_entry,1,row,1,1);
-    gtk_entry_set_text(GTK_ENTRY(connect_addr_entry), connect_addr);
-
-#endif
-    
-
     gtk_container_add (GTK_CONTAINER (content), grid);
     gtk_widget_show_all(discovery_dialog);
 fprintf(stderr,"showing device dialog\n");
-  }
 
 }
 
index d74597ffcb853b804659cefff51244255e5bc0e4..ece8880dca6c0248bdf0712fed57fef2f9673aeb 100644 (file)
@@ -88,22 +88,29 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_d
 }
 
 static gboolean exit_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+g_print("exit_cb\n");
 #ifdef GPIO
   gpio_close();
 #endif
-  switch(protocol) {
-    case ORIGINAL_PROTOCOL:
-      old_protocol_stop();
-      break;
-    case NEW_PROTOCOL:
-      new_protocol_stop();
-      break;
+#ifdef CLIENT_SERVER
+  if(!radio_is_remote) {
+#endif
+    switch(protocol) {
+      case ORIGINAL_PROTOCOL:
+        old_protocol_stop();
+        break;
+      case NEW_PROTOCOL:
+        new_protocol_stop();
+        break;
 #ifdef SOAPYSDR
-    case SOAPYSDR_PROTOCOL:
-      soapy_protocol_stop();
-      break;
+      case SOAPYSDR_PROTOCOL:
+        soapy_protocol_stop();
+        break;
 #endif
+    }
+#ifdef CLIENT_SERVER
   }
+#endif
   radioSaveState();
 
   _exit(0);
@@ -127,7 +134,7 @@ static gboolean reboot_cb (GtkWidget *widget, GdkEventButton *event, gpointer da
 #endif
   }
   radioSaveState();
-  system("reboot");
+  int rc=system("reboot");
   _exit(0);
 }
 
@@ -149,7 +156,7 @@ static gboolean shutdown_cb (GtkWidget *widget, GdkEventButton *event, gpointer
 #endif
   }
   radioSaveState();
-  system("shutdown -h -P now");
+  int rc=system("shutdown -h -P now");
   _exit(0);
 }
 
diff --git a/ext.c b/ext.c
index 29a0c779d091ad2b311326c562b79decdf13ad48..7804134b5e4ae1d60f4478aa60ba6d85a0974509 100644 (file)
--- a/ext.c
+++ b/ext.c
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include <stdint.h>
 #include <gtk/gtk.h>
+#include "main.h"
 #include "discovery.h"
 #include "receiver.h"
 #include "sliders.h"
 #endif
 #include "agc.h"
 #include "filter.h"
+#include "mode.h"
 #include "band.h"
 #include "bandstack.h"
 #include "noise_menu.h"
 #include "wdsp.h"
+#ifdef CLIENT_SERVER
+#include "client_server.h"
+#endif
 #include "ext.h"
 #include "zoompan.h"
 
+
 // The following calls functions can be called usig g_idle_add
 
 int ext_vfo_mode_changed(void * data)
@@ -59,6 +65,23 @@ int ext_discovery(void *data) {
   return 0;
 }
 
+void local_set_frequency(int v,long long f) {
+  int b=get_band_from_frequency(f);
+  if(active_receiver->id==v) {
+    if (b != vfo[v].band) {
+      vfo_band_changed(active_receiver->id,b);
+    }
+    setFrequency(f);
+  } else if(v==VFO_B) {
+    // just  changing VFO-B frequency
+    vfo[v].frequency=f;
+    vfo[v].band=b;
+    if(receivers==2) {
+      // need to change the receiver frequency
+    }
+  }
+}
+
 int ext_set_frequency(void *data) {
   //
   // If new frequency is outside of current band,
@@ -67,20 +90,7 @@ int ext_set_frequency(void *data) {
   //
   SET_FREQUENCY *set_frequency=(SET_FREQUENCY *)data;
 g_print("ext_set_frequency: vfo=%d freq=%lld\n",set_frequency->vfo,set_frequency->frequency);
-  int b=get_band_from_frequency(set_frequency->frequency);
-  if(active_receiver->id==set_frequency->vfo) {
-    if (b != vfo[set_frequency->vfo].band) {
-      vfo_band_changed(b);
-    }
-    setFrequency(set_frequency->frequency);
-  } else if(set_frequency->vfo==VFO_B) {
-    // just  changing VFO-B frequency
-    vfo[set_frequency->vfo].frequency=set_frequency->frequency;
-    vfo[set_frequency->vfo].band=b;
-    if(receivers==2) {
-      // need to change the receiver frequency
-    }
-  }
+  local_set_frequency(set_frequency->vfo,set_frequency->frequency);
   free(data);
   return 0;
 }
@@ -180,7 +190,8 @@ int ext_calc_drive_level(void *data) {
 }
 
 int ext_vfo_band_changed(void *data) {
-  vfo_band_changed(GPOINTER_TO_INT(data));
+  int b=GPOINTER_TO_INT(data);
+  vfo_band_changed(active_receiver->id,b);
   return 0;
 }
 
@@ -348,9 +359,7 @@ int ext_nr_update(void *data) {
     mode_settings[vfo[active_receiver->id].mode].nr=0;
     mode_settings[vfo[active_receiver->id].mode].nr2=0;
   }
-  SetRXAANRRun(active_receiver->id, active_receiver->nr);
-  SetRXAEMNRRun(active_receiver->id, active_receiver->nr2);
-  g_idle_add(ext_vfo_update, NULL);
+  update_noise();
   return 0;
 }
 
@@ -371,9 +380,7 @@ int ext_nb_update(void *data) {
     mode_settings[vfo[active_receiver->id].mode].nb=0;
     mode_settings[vfo[active_receiver->id].mode].nb2=0;
   }
-  SetEXTANBRun(active_receiver->id, active_receiver->nb);
-  SetEXTNOBRun(active_receiver->id, active_receiver->nb2);
-  g_idle_add(ext_vfo_update, NULL);
+  update_noise();
   return 0;
 }
 
@@ -385,15 +392,13 @@ int ext_snb_update(void *data) {
     active_receiver->snb=0;
     mode_settings[vfo[active_receiver->id].mode].snb=0;
   }
-  SetRXASNBARun(active_receiver->id, active_receiver->snb);
-  g_idle_add(ext_vfo_update, NULL);
+  update_noise();
   return 0;
 }
 
-int ext_band_plus(void *data) {
+void band_plus(int id) {
   long long frequency_min=radio->frequency_min;
   long long frequency_max=radio->frequency_max;
-  int id=active_receiver->id;
   int b=vfo[id].band;
   BAND *band;
   int found=0;
@@ -409,18 +414,21 @@ int ext_band_plus(void *data) {
           }
         }
       }
-      vfo_band_changed(b);
+      vfo_band_changed(id,b);
       found=1;
     }
   }
+}
+
+int ext_band_plus(void *data) {
+  band_plus(active_receiver->id);
   return 0;
 }
 
 
-int ext_band_minus(void *data) {
+void band_minus(int id) {
   long long frequency_min=radio->frequency_min;
   long long frequency_max=radio->frequency_max;
-  int id=active_receiver->id;
   int b=vfo[id].band;
   BAND *band;
   int found=0;
@@ -434,10 +442,14 @@ int ext_band_minus(void *data) {
           continue;
         }
       }
-      vfo_band_changed(b);
+      vfo_band_changed(id,b);
       found=1;
     }
   }
+}
+
+int ext_band_minus(void *data) {
+  band_minus(active_receiver->id);
   return 0;
 }
 
@@ -460,22 +472,26 @@ int ext_bandstack_minus(void *data) {
 }
 
 int ext_lock_update(void *data) {
-  locked=locked==1?0:1;
-  g_idle_add(ext_vfo_update, NULL);
+#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
   return 0;
 }
 
 int ext_rit_update(void *data) {
-  vfo[active_receiver->id].rit_enabled=vfo[active_receiver->id].rit_enabled==1?0:1;
-  receiver_frequency_changed(active_receiver);
-  g_idle_add(ext_vfo_update, NULL);
+  vfo_rit_update(active_receiver->id);
   return 0;
 }
 
 int ext_rit_clear(void *data) {
-  vfo[active_receiver->id].rit=0;
-  receiver_frequency_changed(active_receiver);
-  g_idle_add(ext_vfo_update, NULL);
+  vfo_rit_clear(active_receiver->id);
   return 0;
 }
 
@@ -528,14 +544,17 @@ int ext_mode_minus(void *data) {
   return 0;
 }
 
-int ext_ctun_update(void *data) {
-  int id=active_receiver->id;
-  vfo[id].ctun=vfo[id].ctun==1?0:1;
+void ctun_update(int id,int state) {
+  vfo[id].ctun=state;
   if(!vfo[id].ctun) {
     vfo[id].offset=0;
   }
   vfo[id].ctun_frequency=vfo[id].frequency;
-  set_offset(active_receiver,vfo[id].offset);
+  set_offset(receiver[id],vfo[id].offset);
+}
+
+int ext_ctun_update(void *data) {
+  ctun_update(active_receiver->id,vfo[active_receiver->id].ctun==1?0:1);
   g_idle_add(ext_vfo_update, NULL);
   return 0;
 }
@@ -654,52 +673,403 @@ int ext_set_duplex(void *data) {
   return 0;
 }
 
+#ifdef CLIENT_SERVER
 int ext_remote_command(void *data) {
-  REMOTE_COMMAND *p=(REMOTE_COMMAND *)data;
-  switch(p->cmd) {
-    case RX_FREQ_CMD:
+  HEADER *header=(HEADER *)data;
+  REMOTE_CLIENT *client=header->context.client;
+  int temp;
+  switch(ntohs(header->data_type)) {
+    case CMD_RESP_RX_FREQ:
       {
-        int b = get_band_from_frequency(p->data.frequency);
-        if (b != vfo[p->id].band) {
-          vfo_band_changed(b);
-        }
-        setFrequency(p->data.frequency);
+      FREQ_COMMAND *freq_command=(FREQ_COMMAND *)data;
+      temp=active_receiver->pan;
+      int vfo=freq_command->id;
+      long long f=ntohll(freq_command->hz);
+      local_set_frequency(vfo,f);
+      vfo_update();
+      send_vfo_data(client,VFO_A);
+      send_vfo_data(client,VFO_B);
+      if(temp!=active_receiver->pan) {
+        send_pan(client->socket,active_receiver->id,active_receiver->pan);
+      }
+      }
+      break;
+    case CMD_RESP_RX_STEP:
+      {
+      STEP_COMMAND *step_command=(STEP_COMMAND *)data;
+      temp=active_receiver->pan;
+      short steps=ntohs(step_command->steps);
+      vfo_step(steps);
+      //send_vfo_data(client,VFO_A);
+      //send_vfo_data(client,VFO_B);
+      if(temp!=active_receiver->pan) {
+        send_pan(client->socket,active_receiver->id,active_receiver->pan);
+      }
       }
       break;
-    case RX_MOVE_CMD:
-      vfo_move(p->data.frequency,TRUE);
+    case CMD_RESP_RX_MOVE:
+      {
+      MOVE_COMMAND *move_command=(MOVE_COMMAND *)data;
+      temp=active_receiver->pan;
+      long long hz=ntohll(move_command->hz);
+      vfo_move(hz,move_command->round);
+      //send_vfo_data(client,VFO_A);
+      //send_vfo_data(client,VFO_B);
+      if(temp!=active_receiver->pan) {
+        send_pan(client->socket,active_receiver->id,active_receiver->pan);
+      }
+      }
       break;
-    case RX_MOVETO_CMD:
-      vfo_move_to(p->data.frequency);
+    case CMD_RESP_RX_MOVETO:
+      {
+      MOVE_TO_COMMAND *move_to_command=(MOVE_TO_COMMAND *)data;
+      temp=active_receiver->pan;
+      long long hz=ntohll(move_to_command->hz);
+      vfo_move_to(hz);
+      send_vfo_data(client,VFO_A);
+      send_vfo_data(client,VFO_B);
+      if(temp!=active_receiver->pan) {
+        send_pan(client->socket,active_receiver->id,active_receiver->pan);
+      }
+      }
       break;
-    case RX_MODE_CMD:
-      vfo_mode_changed(p->data.mode);
+    case CMD_RESP_RX_ZOOM:
+      {
+      ZOOM_COMMAND *zoom_command=(ZOOM_COMMAND *)data;
+      temp=ntohs(zoom_command->zoom);
+      set_zoom(zoom_command->id,(double)temp);
+      send_zoom(client->socket,active_receiver->id,active_receiver->zoom);
+      send_pan(client->socket,active_receiver->id,active_receiver->pan);
+      }
       break;
-    case RX_FILTER_CMD:
-      vfo_filter_changed(p->data.filter);
+    case CMD_RESP_RX_PAN:
+      {
+      PAN_COMMAND *pan_command=(PAN_COMMAND *)data;
+      temp=ntohs(pan_command->pan);
+      set_pan(pan_command->id,(double)temp);
+      send_pan(client->socket,active_receiver->id,active_receiver->pan);
+      }
       break;
-    case RX_AGC_CMD:
-      active_receiver->agc=p->data.agc;
-      set_agc(active_receiver, active_receiver->agc);
-      vfo_update();
+    case CMD_RESP_RX_VOLUME:
+      {
+      VOLUME_COMMAND *volume_command=(VOLUME_COMMAND *)data;
+      temp=ntohs(volume_command->volume);
+      set_af_gain(volume_command->id,(double)temp/100.0);
+      }
+      break;
+    case CMD_RESP_RX_AGC:
+      {
+      AGC_COMMAND *agc_command=(AGC_COMMAND *)data;
+      RECEIVER *rx=receiver[agc_command->id];
+      rx->agc=ntohs(agc_command->agc);
+g_print("AGC_COMMAND: set_agc id=%d agc=%d\n",rx->id,rx->agc);
+      set_agc(rx,rx->agc);
+      send_agc(client->socket,rx->id,rx->agc);
+      g_idle_add(ext_vfo_update, NULL);
+      }
+      break;
+    case CMD_RESP_RX_AGC_GAIN:
+      {
+      AGC_GAIN_COMMAND *agc_gain_command=(AGC_GAIN_COMMAND *)data;
+      temp=ntohs(agc_gain_command->gain);
+      set_agc_gain(agc_gain_command->id,(double)temp);
+      RECEIVER *rx=receiver[agc_gain_command->id];
+      send_agc_gain(client->socket,rx->id,(int)rx->agc_gain,(int)rx->agc_hang,(int)rx->agc_thresh);
+      }
       break;
-    case RX_NR_CMD:
+    case CMD_RESP_RX_ATTENUATION:
+      {
+      ATTENUATION_COMMAND *attenuation_command=(ATTENUATION_COMMAND *)data;
+      temp=ntohs(attenuation_command->attenuation);
+      set_attenuation(temp);
+      }
       break;
-    case RX_NB_CMD:
+    case CMD_RESP_RX_SQUELCH:
+      {
+      SQUELCH_COMMAND *squelch_command=(SQUELCH_COMMAND *)data;
+      receiver[squelch_command->id]->squelch_enable=squelch_command->enable;
+      temp=ntohs(squelch_command->squelch);
+      receiver[squelch_command->id]->squelch=(double)temp;
+      set_squelch(receiver[squelch_command->id]);
+      }
       break;
-    case RX_SNB_CMD:
+    case CMD_RESP_RX_NOISE:
+      {
+      NOISE_COMMAND *noise_command=(NOISE_COMMAND *)data;
+      RECEIVER *rx=receiver[noise_command->id];
+      rx->nb=noise_command->nb;
+      rx->nb2=noise_command->nb2;
+      mode_settings[vfo[rx->id].mode].nb=rx->nb;
+      mode_settings[vfo[rx->id].mode].nb2=rx->nb2;
+      rx->nr=noise_command->nr;
+      rx->nr2=noise_command->nr2;
+      mode_settings[vfo[rx->id].mode].nr=rx->nr;
+      mode_settings[vfo[rx->id].mode].nr2=rx->nr2;
+      rx->anf=noise_command->anf;
+      mode_settings[vfo[rx->id].mode].anf=rx->anf;
+      rx->snb=noise_command->snb;
+      mode_settings[vfo[rx->id].mode].snb=rx->snb;
+      set_noise();
+      send_noise(client->socket,rx->id,rx->nb,rx->nb2,rx->nr,rx->nr2,rx->anf,rx->snb);
+      }
       break;
-    case RX_SPLIT_CMD:
+    case CMD_RESP_RX_BAND:
+      {
+      BAND_COMMAND *band_command=(BAND_COMMAND *)data;
+      RECEIVER *rx=receiver[band_command->id];
+      short b=htons(band_command->band);
+g_print("BAND_COMMAND: id=%d band=%d\n",rx->id,b);
+      vfo_band_changed(rx->id,b);
+      send_vfo_data(client,VFO_A);
+      send_vfo_data(client,VFO_B);
+      }
       break;
-    case RX_SAT_CMD:
+    case CMD_RESP_RX_MODE:
+      {
+      MODE_COMMAND *mode_command=(MODE_COMMAND *)data;
+      RECEIVER *rx=receiver[mode_command->id];
+      short m=htons(mode_command->mode);
+g_print("MODE_COMMAND: id=%d mode=%d\n",rx->id,m);
+      vfo_mode_changed(m);
+      send_vfo_data(client,VFO_A);
+      send_vfo_data(client,VFO_B);
+      send_filter(client->socket,rx->id,m);
+      }
       break;
-    case RX_DUP_CMD:
+    case CMD_RESP_RX_FILTER:
+      {
+      FILTER_COMMAND *filter_command=(FILTER_COMMAND *)data;
+      RECEIVER *rx=receiver[filter_command->id];
+      short f=htons(filter_command->filter);
+g_print("FILTER_COMMAND: id=%d filter=%d\n",rx->id,f);
+      vfo_filter_changed(f);
+      send_vfo_data(client,VFO_A);
+      send_vfo_data(client,VFO_B);
+      send_filter(client->socket,rx->id,f);
+      }
       break;
+    case CMD_RESP_SPLIT:
+      {
+      SPLIT_COMMAND *split_command=(SPLIT_COMMAND *)data;
+g_print("SPLIT_COMMAND: split=%d\n",split);
+      if(can_transmit) {
+        split=split_command->split;
+        tx_set_mode(transmitter,get_tx_mode());
+        g_idle_add(ext_vfo_update, NULL);
+      }
+      send_split(client->socket,split);
+      }
+      break;
+    case CMD_RESP_SAT:
+      {
+      SAT_COMMAND *sat_command=(SAT_COMMAND *)data;
+      sat_mode=sat_command->sat;
+g_print("SAT_COMMAND: sat_mode=%d\n",sat_mode);
+      g_idle_add(ext_vfo_update, NULL);
+      send_sat(client->socket,sat_mode);
+      }
+      break;
+    case CMD_RESP_DUP:
+      {
+      DUP_COMMAND *dup_command=(DUP_COMMAND *)data;
+      duplex=dup_command->dup;
+g_print("DUP: duplex=%d\n",duplex);
+      g_idle_add(ext_vfo_update, NULL);
+      send_dup(client->socket,duplex);
+      }
+      break;
+    case CMD_RESP_LOCK:
+      {
+      LOCK_COMMAND *lock_command=(LOCK_COMMAND *)data;
+      locked=lock_command->lock;
+g_print("LOCK: locked=%d\n",locked);
+      g_idle_add(ext_vfo_update, NULL);
+      send_lock(client->socket,locked);
+      }
+      break;
+    case CMD_RESP_CTUN:
+      {
+      CTUN_COMMAND *ctun_command=(CTUN_COMMAND *)data;
+g_print("CTUN: vfo=%d ctun=%d\n",ctun_command->id,ctun_command->ctun);
+      int v=ctun_command->id;
+      vfo[v].ctun=ctun_command->ctun;
+      if(!vfo[v].ctun) {
+        vfo[v].offset=0;
+      }
+      vfo[v].ctun_frequency=vfo[v].frequency;
+      set_offset(active_receiver,vfo[v].offset);
+      g_idle_add(ext_vfo_update, NULL);
+      send_ctun(client->socket,v,vfo[v].ctun);
+      send_vfo_data(client,v);
+      }
+      break;
+    case CMD_RESP_RX_FPS:
+      {
+      FPS_COMMAND *fps_command=(FPS_COMMAND *)data;
+      int rx=fps_command->id;
+g_print("FPS: rx=%d fps=%d\n",rx,fps_command->fps);
+      receiver[rx]->fps=fps_command->fps;
+      calculate_display_average(receiver[rx]);
+      set_displaying(receiver[rx],1);
+      send_fps(client->socket,rx,receiver[rx]->fps);
+      }
+      break;
+    case CMD_RESP_RX_SELECT:
+      {
+      RX_SELECT_COMMAND *rx_select_command=(RX_SELECT_COMMAND *)data;
+      int rx=rx_select_command->id;
+g_print("RX_SELECT: rx=%d\n",rx);
+      receiver_set_active(receiver[rx]);
+      send_rx_select(client->socket,rx);
+      }
+      break;
+    case CMD_RESP_VFO:
+      {
+      VFO_COMMAND *vfo_command=(VFO_COMMAND *)data;
+      int action=vfo_command->id;
+g_print("VFO: action=%d\n",action);
+      switch(action) {
+        case VFO_A_TO_B:
+          vfo_a_to_b();
+          break;
+        case VFO_B_TO_A:
+          vfo_b_to_a();
+          break;
+        case VFO_A_SWAP_B:
+          vfo_a_swap_b();
+          break;
+      }
+      send_vfo_data(client,VFO_A);
+      send_vfo_data(client,VFO_B);
+      }
+      break;
+    case CMD_RESP_RIT_UPDATE:
+      {
+      RIT_UPDATE_COMMAND *rit_update_command=(RIT_UPDATE_COMMAND *)data;
+      int rx=rit_update_command->id;
+g_print("RIT_UPDATE: rx=%d\n",rx);
+      vfo_rit_update(rx);
+      send_vfo_data(client,rx);
+      }
+      break;
+    case CMD_RESP_RIT_CLEAR:
+      {
+      RIT_CLEAR_COMMAND *rit_clear_command=(RIT_CLEAR_COMMAND *)data;
+      int rx=rit_clear_command->id;
+g_print("RIT_CLEAR: rx=%d\n",rx);
+      vfo_rit_clear(rx);
+      send_vfo_data(client,rx);
+      }
+      break;
+    case CMD_RESP_RIT:
+      {
+      RIT_COMMAND *rit_command=(RIT_COMMAND *)data;
+      int rx=rit_command->id;
+      short rit=ntohs(rit_command->rit);
+g_print("RIT: rx=%d rit=%d\n",rx,(int)rit);
+      vfo_rit(rx,(int)rit);
+      send_vfo_data(client,rx);
+      }
+      break;
+    case CMD_RESP_XIT_UPDATE:
+      {
+      XIT_UPDATE_COMMAND *xit_update_command=(XIT_UPDATE_COMMAND *)data;
+g_print("XIT_UPDATE\n");
+      send_vfo_data(client,VFO_A);
+      send_vfo_data(client,VFO_B);
+      }
+      break;
+    case CMD_RESP_XIT_CLEAR:
+      {
+      XIT_CLEAR_COMMAND *xit_clear_command=(XIT_CLEAR_COMMAND *)data;
+g_print("XIT_CLEAR\n");
+      send_vfo_data(client,VFO_A);
+      send_vfo_data(client,VFO_B);
+      }
+      break;
+    case CMD_RESP_XIT:
+      {
+      XIT_COMMAND *xit_command=(XIT_COMMAND *)data;
+      short xit=ntohs(xit_command->xit);
+g_print("XIT_CLEAR: xit=%d\n",xit);
+      send_vfo_data(client,VFO_A);
+      send_vfo_data(client,VFO_B);
+      }
+      break;
+    case CMD_RESP_SAMPLE_RATE:
+      {
+      SAMPLE_RATE_COMMAND *sample_rate_command=(SAMPLE_RATE_COMMAND *)data;
+      int rx=(int)sample_rate_command->id;
+      long long rate=ntohll(sample_rate_command->sample_rate);
+g_print("SAMPLE_RATE: rx=%d rate=%d\n",rx,(int)rate);
+      if(rx==-1) {
+        radio_change_sample_rate((int)rate);
+        send_sample_rate(client->socket,-1,radio_sample_rate);
+      } else {
+        receiver_change_sample_rate(receiver[rx],(int)rate);
+        send_sample_rate(client->socket,rx,receiver[rx]->sample_rate);
+      }
+      }
+      break;
+    case CMD_RESP_RECEIVERS:
+      {
+      RECEIVERS_COMMAND *receivers_command=(RECEIVERS_COMMAND *)data;
+      int r=receivers_command->receivers;
+g_print("RECEIVERS: receivers=%d\n",r);
+      radio_change_receivers(r);
+      send_receivers(client->socket,receivers);
+      }
+      break;
+    case CMD_RESP_RIT_INCREMENT:
+      {
+      RIT_INCREMENT_COMMAND *rit_increment_command=(RIT_INCREMENT_COMMAND *)data;
+      short increment=ntohs(rit_increment_command->increment);
+g_print("RIT_INCREMENT: increment=%d\n",increment);
+      rit_increment=(int)increment;
+      send_rit_increment(client->socket,rit_increment);
+      }
+      break;
+    case CMD_RESP_FILTER_BOARD:
+      {
+      FILTER_BOARD_COMMAND *filter_board_command=(FILTER_BOARD_COMMAND *)data;
+g_print("FILTER_BOARD: board=%d\n",(int)filter_board_command->filter_board);
+      filter_board=(int)filter_board_command->filter_board;
+      load_filters();
+      send_filter_board(client->socket,filter_board);
+      }
+      break;
+    case CMD_RESP_SWAP_IQ:
+      {
+      SWAP_IQ_COMMAND *swap_iq_command=(SWAP_IQ_COMMAND *)data;
+g_print("SWAP_IQ: board=%d\n",(int)swap_iq_command->iqswap);
+      iqswap=(int)swap_iq_command->iqswap;
+      send_swap_iq(client->socket,iqswap);
+      }
+      break;
+    case CMD_RESP_REGION:
+      {
+      REGION_COMMAND *region_command=(REGION_COMMAND *)data;
+g_print("REGION: region=%d\n",(int)region_command->region);
+      iqswap=(int)region_command->region;
+      send_region(client->socket,region);
+      }
+      break;
+
+
+
+
   }
   g_free(data);
   return 0;
 }
 
+int ext_receiver_remote_update_display(void *data) {
+  RECEIVER *rx=(RECEIVER *)data;
+  receiver_remote_update_display(rx);
+  return 0;
+}
+#endif
+
 int ext_anf_update(void *data) {
   if(active_receiver->anf==0) {
     active_receiver->anf=1;
@@ -745,3 +1115,22 @@ int ext_pan_set(void *data) {
   }
   return 0;
 }
+
+int ext_remote_set_zoom(void *data) {
+  int zoom=GPOINTER_TO_INT(data);
+g_print("ext_remote_set_zoom: %d\n",zoom);
+  remote_set_zoom(active_receiver->id,(double)zoom);
+  return 0;
+}
+
+int ext_remote_set_pan(void *data) {
+  int pan=GPOINTER_TO_INT(data);
+g_print("ext_remote_set_pan: %d\n",pan);
+  remote_set_pan(active_receiver->id,(double)pan);
+  return 0;
+}
+
+int ext_set_title(void *data) {
+  gtk_window_set_title(GTK_WINDOW(top_window),(char *)data);
+  return 0;
+}
diff --git a/ext.h b/ext.h
index 5af161784b62bb4a27ca582a01de142962a1d693..51f1bcc9c838daa9e6fe07fd9847a5d2f1263b5e 100644 (file)
--- a/ext.h
+++ b/ext.h
 *
 */
 
+#ifdef CLIENT_SERVER
+#include "client_server.h"
+#endif
 
 //
 // The following calls functions can be called usig g_idle_add
 // Use these calls from within the rigclt daemon, or the GPIO or MIDI stuff
 //
 
-enum {
-  RX_FREQ_CMD,
-  RX_MOVE_CMD,
-  RX_MOVETO_CMD,
-  RX_MODE_CMD,
-  RX_FILTER_CMD,
-  RX_AGC_CMD,
-  RX_NR_CMD,
-  RX_NB_CMD,
-  RX_SNB_CMD,
-  RX_SPLIT_CMD,
-  RX_SAT_CMD,
-  RX_DUP_CMD
-};
-  
-typedef struct _REMOTE_COMMAND {
-  int id;
-  int cmd;
-  union {
-    long long frequency;
-    int mode;
-    int filter;
-    int agc;
-    int nr;
-    int nb;
-    int snb;
-    int split;
-    int sat;
-    int dup;
-  } data;
-} REMOTE_COMMAND;
+#ifdef CLIENT_SERVER
+extern int ext_remote_command(void *data);
+extern int ext_receiver_remote_update_display(void *data);
+#endif
 
+extern void local_set_frequency(int v,long long f);
 extern int ext_discovery(void *data);
 extern int ext_vfo_update(void *data);
 extern int ext_set_frequency(void *data);
@@ -78,7 +55,9 @@ extern int ext_nr_update(void *data);
 extern int ext_nb_update(void *data);
 extern int ext_snb_update(void *data);
 extern int ext_anf_update(void *data);
+extern void band_plus(int id);
 extern int ext_band_plus(void *data);
+extern void band_minus(int id);
 extern int ext_band_minus(void *data);
 extern int ext_bandstack_plus(void *data);
 extern int ext_bandstack_minus(void *data);
@@ -94,6 +73,7 @@ extern int ext_mode_plus(void *data);
 extern int ext_mode_minus(void *data);
 extern int ext_b_to_a(void *data);
 extern int ext_a_swap_b(void *data);
+extern void ctun_update(int id,int state);
 extern int ext_ctun_update(void *data);
 extern int ext_agc_update(void *data);
 extern int ext_split_toggle(void *data);
@@ -118,41 +98,45 @@ extern int ext_function_update(void *data);
 extern int ext_tx_set_ps(void *data);
 #endif
 
-int ext_update_vfo_step(void *data);
-int ext_vfo_step(void *data);
-int ext_vfo_id_step(void *data);
-int ext_vfo_mode_changed(void *data);
-int ext_set_af_gain(void *data);
-int ext_set_mic_gain(void *data);
-int ext_set_agc_gain(void *data);
-int ext_set_drive(void *data);
-int ext_vfo_a_swap_b(void *data);
-int ext_vfo_a_to_b(void *data);
-int ext_vfo_b_to_a(void *data);
-int ext_update_att_preamp(void *data);
-int ext_set_alex_attenuation(void *data);
-int ext_set_attenuation_value(void *data);
-int ext_set_compression(void *data);
-
-int ext_start_rx(void *data);
-int ext_start_tx(void *data);
-int ext_diversity_update(void *data);
-int ext_diversity_change_gain(void *data);
-int ext_diversity_change_phase(void *data);
-int ext_sat_update(void *data);
-int ext_set_rf_gain(void *data);
-int ext_set_duplex(void *data);
-
-int ext_update_noise(void *data);
+extern int ext_update_vfo_step(void *data);
+extern int ext_vfo_step(void *data);
+extern int ext_vfo_id_step(void *data);
+extern int ext_vfo_mode_changed(void *data);
+extern int ext_set_af_gain(void *data);
+extern int ext_set_mic_gain(void *data);
+extern int ext_set_agc_gain(void *data);
+extern int ext_set_drive(void *data);
+extern int ext_vfo_a_swap_b(void *data);
+extern int ext_vfo_a_to_b(void *data);
+extern int ext_vfo_b_to_a(void *data);
+extern int ext_update_att_preamp(void *data);
+extern int ext_set_alex_attenuation(void *data);
+extern int ext_set_attenuation_value(void *data);
+extern int ext_set_compression(void *data);
+
+extern int ext_start_rx(void *data);
+extern int ext_start_tx(void *data);
+extern int ext_diversity_update(void *data);
+extern int ext_diversity_change_gain(void *data);
+extern int ext_diversity_change_phase(void *data);
+extern int ext_sat_update(void *data);
+extern int ext_set_rf_gain(void *data);
+extern int ext_set_duplex(void *data);
+
+extern int ext_update_noise(void *data);
 #ifdef PURESIGNAL
-int ext_start_ps(void *data);
+extern int ext_start_ps(void *data);
 #endif
 
-int ext_mute_update(void *data);
+extern int ext_mute_update(void *data);
+
+extern int ext_zoom_update(void *data);
+extern int ext_zoom_set(void *data);
+extern int ext_pan_update(void *data);
+extern int ext_pan_set(void *data);
+
+extern int ext_remote_set_zoom(void *data);
+extern int ext_remote_set_pan(void *data);
+extern int ext_set_title(void *data);
 
-int ext_zoom_update(void *data);
-int ext_zoom_set(void *data);
-int ext_pan_update(void *data);
-int ext_pan_set(void *data);
 
-int ext_remote_command(void *data);
index b378b3afe8d3ac05bd8d1f26d5e31532569b4e03..18803fa4e07fe004ede3c02d561377db19d9cf53 100644 (file)
@@ -120,22 +120,25 @@ static gboolean freqent_select_cb (GtkWidget *widget, gpointer data) {
             f = ((long long)(atof(buffer)*mult)+5)/10;
             sprintf(output, "<big>%lld</big>", f);
             gtk_label_set_markup (GTK_LABEL (label), output);
-            int b=get_band_from_frequency(f);
-            if(b!=band_get_current()) {
-              BAND *band=band_set_current(b);
-              set_mode(active_receiver,entry->mode);
-              FILTER* band_filters=filters[entry->mode];
-              FILTER* band_filter=&band_filters[entry->filter];
-              set_filter(active_receiver,band_filter->low,band_filter->high);
-              if(active_receiver->id==0) {
-                set_alex_rx_antenna(band->alexRxAntenna);
-                set_alex_tx_antenna(band->alexTxAntenna);
-                set_alex_attenuation(band->alexAttenuation);
+            if(radio_is_remote) {
+                send_vfo_frequency(client_socket,active_receiver->id,f);
+            } else {
+              int b=get_band_from_frequency(f);
+              if(b!=band_get_current()) {
+                BAND *band=band_set_current(b);
+                set_mode(active_receiver,entry->mode);
+                FILTER* band_filters=filters[entry->mode];
+                FILTER* band_filter=&band_filters[entry->filter];
+                set_filter(active_receiver,band_filter->low,band_filter->high);
+                if(active_receiver->id==0) {
+                  set_alex_rx_antenna(band->alexRxAntenna);
+                  set_alex_tx_antenna(band->alexTxAntenna);
+                  set_alex_attenuation(band->alexAttenuation);
+                }
               }
+              setFrequency(f);
+              g_idle_add(ext_vfo_update,NULL);
             }
-            setFrequency(f);
-            g_idle_add(ext_vfo_update,NULL);
-      
             set = 1;
         }
     }
diff --git a/gpio.c b/gpio.c
index 4e277e949a9aa3c5c7b514174ab3cd02c238b02d..d6d22d692bc2bfdb44905838fdc58c2c9caf1b38 100644 (file)
--- a/gpio.c
+++ b/gpio.c
@@ -2064,40 +2064,13 @@ static void encoder_changed(int action,int pos) {
       set_drive(value);
       break;
     case ENCODER_RIT:
-      value=(double)vfo[active_receiver->id].rit;
-      value+=(double)(pos*rit_increment);
-      if(value<-10000.0) {
-        value=-10000.0;
-      } else if(value>10000.0) {
-        value=10000.0;
-      }
-      vfo[active_receiver->id].rit=(int)value;
-      receiver_frequency_changed(active_receiver);
-      g_idle_add(ext_vfo_update,NULL);
+      vfo_rit(active_receiver->id,pos);
       break;
     case ENCODER_RIT_RX1:
-      value=(double)vfo[receiver[0]->id].rit;
-      value+=(double)(pos*rit_increment);
-      if(value<-10000.0) {
-        value=-10000.0;
-      } else if(value>10000.0) {
-        value=10000.0;
-      }
-      vfo[receiver[0]->id].rit=(int)value;
-      receiver_frequency_changed(receiver[0]);
-      g_idle_add(ext_vfo_update,NULL);
+      vfo_rit(receiver[0]->id,pos);
       break;
     case ENCODER_RIT_RX2:
-      value=(double)vfo[receiver[1]->id].rit;
-      value+=(double)(pos*rit_increment);
-      if(value<-10000.0) {
-        value=-10000.0;
-      } else if(value>10000.0) {
-        value=10000.0;
-      }
-      vfo[receiver[1]->id].rit=(int)value;
-      receiver_frequency_changed(receiver[1]);
-      g_idle_add(ext_vfo_update,NULL);
+      vfo_rit(receiver[1]->id,pos);
       break;
     case ENCODER_XIT:
       value=(double)transmitter->xit;
@@ -2223,6 +2196,7 @@ static void encoder_changed(int action,int pos) {
       update_diversity_phase((double)pos*0.1);
       break;
     case ENCODER_ZOOM:
+g_print("GPIO: ENCODER_ZOOM: update_zoom: pos=%d\n",pos);
       update_zoom((double)pos);
       break;
     case ENCODER_PAN:
diff --git a/main.c b/main.c
index 39cdbb4eebeab10a70f9045eb633dff21cbaa997..bc292043d2efedb86266ee70610bf9813f2a96ea 100644 (file)
--- a/main.c
+++ b/main.c
@@ -146,19 +146,25 @@ gboolean main_delete (GtkWidget *widget) {
 #ifdef GPIO
     gpio_close();
 #endif
-    switch(protocol) {
-      case ORIGINAL_PROTOCOL:
-        old_protocol_stop();
-        break;
-      case NEW_PROTOCOL:
-        new_protocol_stop();
-        break;
+#ifdef CLIENT_SERVER
+    if(!radio_is_remote) {
+#endif
+      switch(protocol) {
+        case ORIGINAL_PROTOCOL:
+          old_protocol_stop();
+          break;
+        case NEW_PROTOCOL:
+          new_protocol_stop();
+          break;
 #ifdef SOAPYSDR
-      case SOAPYSDR_PROTOCOL:
-        soapy_protocol_stop();
-        break;
+        case SOAPYSDR_PROTOCOL:
+          soapy_protocol_stop();
+          break;
 #endif
+      }
+#ifdef CLIENT_SERVER
     }
+#endif
     radioSaveState();
   }
   _exit(0);
@@ -182,7 +188,7 @@ static int init(void *data) {
   // Depending on the WDSP version, the file is wdspWisdom or wdspWisdom00.
   // sem_trywait() is not elegant, replaced this with wisdom_running variable.
   //
-  getcwd(wisdom_directory, sizeof(wisdom_directory));
+  char *c=getcwd(wisdom_directory, sizeof(wisdom_directory));
   strcpy(&wisdom_directory[strlen(wisdom_directory)],"/");
   fprintf(stderr,"Securing wisdom file in directory: %s\n", wisdom_directory);
   status_text("Creating FFTW Wisdom file ...");
index ba24cfefd66b452653a8bf1d65ce8c29762243fb..0bf1aeb7156b6fefd0336bc297e8a7359bb3f630 100644 (file)
@@ -60,6 +60,9 @@
 #include "gpio.h"
 #include "old_protocol.h"
 #include "new_protocol.h"
+#ifdef CLIENT_SERVER
+#include "server_menu.h"
+#endif
 
 
 static GtkWidget *menu_b=NULL;
@@ -453,6 +456,18 @@ static gboolean test_cb (GtkWidget *widget, GdkEventButton *event, gpointer data
   return TRUE;
 }
 
+#ifdef CLIENT_SERVER
+void start_server() {
+  cleanup();
+  server_menu(top_window);
+}
+
+static gboolean server_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  start_server();
+  return TRUE;
+}
+#endif
+
 void new_menu()
 {
   int i;
@@ -624,6 +639,13 @@ void new_menu()
       i++;
     }
 
+#ifdef CLIENT_SERVER
+    GtkWidget *server_b=gtk_button_new_with_label("Server");
+    g_signal_connect (server_b, "button-press-event", G_CALLBACK(server_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),server_b,(i%5),i/5,1,1);
+    i++;
+#endif
+
     GtkWidget *about_b=gtk_button_new_with_label("About");
     g_signal_connect (about_b, "button-press-event", G_CALLBACK(about_b_cb), NULL);
     gtk_grid_attach(GTK_GRID(grid),about_b,(i%5),i/5,1,1);
index 3fbf6174d25ffd2c1ca2e1d33511e486738461f3..78699d2c612a4dcfdd5f4660f57d6a81040e186a 100644 (file)
@@ -22,6 +22,9 @@ extern void start_diversity();
 #ifdef PURESIGNAL
 extern void start_ps();
 #endif
+#ifdef CLIENT_SERVER
+extern void start_server();
+#endif
 
 extern void encoder_step(int encoder,int step);
 
index 3aef1bd578ee3cf641f8e1d561367d6394c9ee70..40a33e19a6b3c0a01b24167f96bf743fc7fe30ac 100644 (file)
@@ -150,11 +150,6 @@ static long micsamples_sequence=0;
 // This is shared with new_protocol_programmer.c
 int response;
 
-//static sem_t send_high_priority_sem;
-//static int send_high_priority=0;
-//static sem_t send_general_sem;
-//static int send_general=0;
-
 #ifdef __APPLE__
 static sem_t *command_response_sem_ready;
 static sem_t *command_response_sem_buffer;
index bbef41b91c9ba4458031c89d2ac6faf53f50399b..f426b977d2c1c80632090b7f822d95816beb3adb 100644 (file)
@@ -60,7 +60,7 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_d
   return FALSE;
 }
 
-void update_noise() {
+void set_noise() {
   SetEXTANBRun(active_receiver->id, active_receiver->nb);
   SetEXTNOBRun(active_receiver->id, active_receiver->nb2);
   SetRXAANRRun(active_receiver->id, active_receiver->nr);
@@ -70,6 +70,18 @@ void update_noise() {
   g_idle_add(ext_vfo_update,NULL);
 }
 
+void update_noise() {
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_noise(client_socket,active_receiver->id,active_receiver->nb,active_receiver->nb2,active_receiver->nr,active_receiver->nr2,active_receiver->anf,active_receiver->snb);
+  } else {
+#endif
+    set_noise();
+#ifdef CLIENT_SERVER
+  }
+#endif
+}
+
 static void nb_none_cb(GtkToggleButton *widget, gpointer data) {
   if(gtk_toggle_button_get_active(widget)) {
     active_receiver->nb=0;
index c1337274b95a7a8c00343da3f76fec74964d462b..a145076cadf7af614448ef63ff889a5e23072f70 100644 (file)
@@ -20,3 +20,4 @@
 extern void noise_menu(GtkWidget *parent);
 
 extern void update_noise();
+extern void set_noise();
index b985f7607c1dea7be5e45f7e5b3d500b8289c74f..03f440bab6c9a5369297f22aec170d94bddcb76f 100644 (file)
--- a/pa_menu.h
+++ b/pa_menu.h
@@ -18,7 +18,6 @@
 */
 
 #include <gtk/gtk.h>
-#include <semaphore.h>
 #include <stdio.h>
 #include <string.h>
 
diff --git a/radio.c b/radio.c
index 19f6698862843dee9acadf5bf2b344a61839da48..62bba24385dfa090816c242b6f3976862a87808a 100644 (file)
--- a/radio.c
+++ b/radio.c
 #include <semaphore.h>
 #include <math.h>
 #include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <netdb.h>
 
 #include <wdsp.h>
 
@@ -74,8 +77,8 @@
 // we need here to make a strict compiler happy.
 void MIDIstartup();
 #endif
-#ifdef SERVER
-#include "hpsdr_server.h"
+#ifdef CLIENT_SERVER
+#include "client_server.h"
 #endif
 
 #define min(x,y) (x<y?x:y)
@@ -120,13 +123,12 @@ static cairo_surface_t *encoders_surface = NULL;
        static gint save_timer_id;
 
        DISCOVERED *radio=NULL;
+#ifdef CLIENT_SERVER
+       gboolean radio_is_remote=FALSE;
+#endif
 
        char property_path[128];
-#ifdef __APPLE__
-        sem_t *property_sem;
-#else
-        sem_t property_sem;
-#endif
+        GMutex property_mutex;
 
 RECEIVER *receiver[MAX_RECEIVERS];
 RECEIVER *active_receiver;
@@ -193,6 +195,10 @@ int mic_ptt_tip_bias_ring=0;
 
 int receivers=RECEIVERS;
 
+ADC adc[2];
+DAC dac[2];
+int adc_attenuation[2];
+
 int locked=0;
 
 long long step=100;
@@ -344,7 +350,7 @@ g_print("radio_stop: RX1: CloseChannel: %d\n",receiver[1]->id);
 void reconfigure_radio() {
   int i;
   int y;
-//g_print("reconfigure_radio: receivers=%d\n",receivers);
+g_print("reconfigure_radio: receivers=%d\n",receivers);
   rx_height=display_height-VFO_HEIGHT;
   if(display_zoompan) {
     rx_height-=ZOOMPAN_HEIGHT;
@@ -435,6 +441,227 @@ static gboolean menu_cb (GtkWidget *widget, GdkEventButton *event, gpointer data
   return TRUE;
 }
 
+static void create_visual() {
+  int y=0;
+
+  fixed=gtk_fixed_new();
+  g_object_ref(grid);  // so it does not get deleted
+  gtk_container_remove(GTK_CONTAINER(top_window),grid);
+  gtk_container_add(GTK_CONTAINER(top_window), fixed);
+
+//g_print("radio: vfo_init\n");
+  vfo_panel = vfo_init(VFO_WIDTH,VFO_HEIGHT,top_window);
+  gtk_fixed_put(GTK_FIXED(fixed),vfo_panel,0,y);
+
+//g_print("radio: meter_init\n");
+  meter = meter_init(METER_WIDTH,METER_HEIGHT,top_window);
+  gtk_fixed_put(GTK_FIXED(fixed),meter,VFO_WIDTH,y);
+
+
+  GtkWidget *minimize_b=gtk_button_new_with_label("Hide");
+  gtk_widget_override_font(minimize_b, pango_font_description_from_string("FreeMono Bold 10"));
+  gtk_widget_set_size_request (minimize_b, MENU_WIDTH, MENU_HEIGHT);
+  g_signal_connect (minimize_b, "button-press-event", G_CALLBACK(minimize_cb), NULL) ;
+  gtk_fixed_put(GTK_FIXED(fixed),minimize_b,VFO_WIDTH+METER_WIDTH,y);
+  y+=MENU_HEIGHT;
+
+  GtkWidget *menu_b=gtk_button_new_with_label("Menu");
+  gtk_widget_override_font(menu_b, pango_font_description_from_string("FreeMono Bold 10"));
+  gtk_widget_set_size_request (menu_b, MENU_WIDTH, MENU_HEIGHT);
+  g_signal_connect (menu_b, "button-press-event", G_CALLBACK(menu_cb), NULL) ;
+  gtk_fixed_put(GTK_FIXED(fixed),menu_b,VFO_WIDTH+METER_WIDTH,y);
+  y+=MENU_HEIGHT;
+
+
+  rx_height=display_height-VFO_HEIGHT;
+  if(display_zoompan) {
+    rx_height-=ZOOMPAN_HEIGHT;
+  }
+  if(display_sliders) {
+    rx_height-=SLIDERS_HEIGHT;
+  }
+  if(display_toolbar) {
+    rx_height-=TOOLBAR_HEIGHT;
+  }
+
+  //
+  // To be on the safe side, we create ALL receiver panels here
+  // If upon startup, we only should display one panel, we do the switch below
+  //
+  for(int i=0;i<RECEIVERS;i++) {
+#ifdef CLIENT_SERVER
+    if(radio_is_remote) {
+      receiver_create_remote(receiver[i]);
+    } else {
+#endif
+      receiver[i]=create_receiver(i, buffer_size, fft_size, display_width, updates_per_second, display_width, rx_height/RECEIVERS);
+      setSquelch(receiver[i]);
+#ifdef CLIENT_SERVER
+    }
+#endif
+    receiver[i]->x=0;
+    receiver[i]->y=y;
+    // Upon startup, if RIT or CTUN is active, tell WDSP.
+#ifdef CLIENT_SERVER
+    if(!radio_is_remote) {
+#endif
+      set_displaying(receiver[i],1);
+      set_offset(receiver[i],vfo[i].offset);
+#ifdef CLIENT_SERVER
+    }
+#endif
+    gtk_fixed_put(GTK_FIXED(fixed),receiver[i]->panel,0,y);
+    g_object_ref((gpointer)receiver[i]->panel);
+    y+=rx_height/RECEIVERS;
+  }
+  
+  //
+  // Sanity check: in old protocol, all receivers must have the same sample rate
+  //
+  if((protocol==ORIGINAL_PROTOCOL) && (RECEIVERS==2) && (receiver[0]->sample_rate!=receiver[1]->sample_rate)) {
+    receiver[1]->sample_rate=receiver[0]->sample_rate;
+  }
+
+  active_receiver=receiver[0];
+
+// TEMP
+#ifdef CLIENT_SERVER
+if(!radio_is_remote) {
+#endif
+  //g_print("Create transmitter\n");
+  if(can_transmit) {
+    double pk;
+    if(duplex) {
+      transmitter=create_transmitter(CHANNEL_TX, buffer_size, fft_size, updates_per_second, display_width/4, display_height/2);
+    } else {
+      int tx_height=display_height-VFO_HEIGHT;
+      if(display_zoompan) tx_height-=ZOOMPAN_HEIGHT;
+      if(display_sliders) tx_height-=SLIDERS_HEIGHT;
+      if(display_toolbar) tx_height-=TOOLBAR_HEIGHT;
+      transmitter=create_transmitter(CHANNEL_TX, buffer_size, fft_size, updates_per_second, display_width, tx_height);
+    }
+    transmitter->x=0;
+    transmitter->y=VFO_HEIGHT;
+
+    calcDriveLevel();
+
+#ifdef PURESIGNAL
+    tx_set_ps_sample_rate(transmitter,protocol==NEW_PROTOCOL?192000:active_receiver->sample_rate);
+    receiver[PS_TX_FEEDBACK]=create_pure_signal_receiver(PS_TX_FEEDBACK, buffer_size,protocol==ORIGINAL_PROTOCOL?active_receiver->sample_rate:192000,display_width);
+    receiver[PS_RX_FEEDBACK]=create_pure_signal_receiver(PS_RX_FEEDBACK, buffer_size,protocol==ORIGINAL_PROTOCOL?active_receiver->sample_rate:192000,display_width);
+    switch (protocol) {
+      case NEW_PROTOCOL:
+        pk = 0.2899;
+        break;
+      case ORIGINAL_PROTOCOL:
+        switch (device) {
+          case DEVICE_HERMES_LITE2:
+            pk = 0.2300;
+            break;
+          default:
+            pk = 0.4067;
+            break;
+        }
+    }
+    SetPSHWPeak(transmitter->id, pk);
+#endif
+
+  }
+#ifdef CLIENT_SERVER
+}
+#endif
+
+#ifdef AUDIO_WATERFALL
+  audio_waterfall=audio_waterfall_init(200,100);
+  gtk_fixed_put(GTK_FIXED(fixed),audio_waterfall,0,VFO_HEIGHT+20);
+#endif
+
+  gboolean init_gpio=FALSE;
+#ifdef LOCALCW
+  init_gpio=TRUE;
+#endif
+#ifdef PTT
+  init_gpio=TRUE;
+#endif
+#ifdef GPIO
+  init_gpio=TRUE;
+#endif
+
+  if(init_gpio) {
+#ifdef GPIO
+    if(gpio_init()<0) {
+      g_print("GPIO failed to initialize\n");
+    }
+#endif
+  }
+
+#ifdef LOCALCW
+  // init local keyer if enabled
+  if (cw_keyer_internal == 0) {
+       g_print("Initialize keyer.....\n");
+    keyer_update();
+  }
+#endif
+  
+#ifdef CLIENT_SERVER
+  if(!radio_is_remote) {
+#endif
+  switch(protocol) {
+    case ORIGINAL_PROTOCOL:
+      old_protocol_init(0,display_width,receiver[0]->sample_rate);
+      break;
+    case NEW_PROTOCOL:
+      new_protocol_init(display_width);
+      break;
+#ifdef SOAPYSDR
+    case SOAPYSDR_PROTOCOL:
+      soapy_protocol_init(0,false);
+      break;
+#endif
+  }
+#ifdef CLIENT_SERVER
+  }
+#endif
+
+  if(display_zoompan) {
+    zoompan = zoompan_init(display_width,ZOOMPAN_HEIGHT);
+    gtk_fixed_put(GTK_FIXED(fixed),zoompan,0,y);
+    y+=ZOOMPAN_HEIGHT;
+  }
+
+  if(display_sliders) {
+//g_print("create sliders\n");
+    sliders = sliders_init(display_width,SLIDERS_HEIGHT);
+    gtk_fixed_put(GTK_FIXED(fixed),sliders,0,y);
+    y+=SLIDERS_HEIGHT;
+  }
+
+
+  if(display_toolbar) {
+    toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,top_window);
+    gtk_fixed_put(GTK_FIXED(fixed),toolbar,0,y);
+    y+=TOOLBAR_HEIGHT;
+  }
+
+//
+// Now, if there should only one receiver be displayed
+// at startup, do the change. We must momentarily fake
+// the number of receivers otherwise radio_change_receivers
+// will do nothing.
+//
+g_print("create_visual: receivers=%d RECEIVERS=%d\n",receivers,RECEIVERS);
+  if (receivers != RECEIVERS) {
+    int r=receivers;
+    receivers=RECEIVERS;
+g_print("create_visual: calling radio_change_receivers: receivers=%d r=%d\n",receivers,r);
+    radio_change_receivers(r);
+  }
+
+  //gtk_widget_show_all (fixed);
+  gtk_widget_show_all (top_window);
+
+}
+  
 void start_radio() {
   int i;
   int y;
@@ -621,27 +848,12 @@ void start_radio() {
 //
 // A semaphore for safely writing to the props file
 //
-#ifdef __APPLE__
-  sem_unlink("PROPERTY");
-  property_sem=sem_open("PROPERTY", O_CREAT | O_EXCL, 0700, 0);
-  rc=(property_sem == SEM_FAILED);
-#else
-  rc=sem_init(&property_sem, 0, 0);
-#endif
-  if(rc!=0) {
-    g_print("start_radio: sem_init failed for property_sem: %d\n", rc);
-    exit(-1);
-  }
-#ifdef __APPLE__
-  sem_post(property_sem);
-#else
-  sem_post(&property_sem);
-#endif
+  g_mutex_init(&property_mutex);
 
 //
 //  Create text for the top line of the piHPSDR window
 //
-    char text[256];
+    char text[1024];
     switch(protocol) {
       case ORIGINAL_PROTOCOL:
       case NEW_PROTOCOL:
@@ -666,7 +878,7 @@ void start_radio() {
   char version[32];
   char mac[32];
   char ip[32];
-  char iface[32];
+  char iface[64];
 
   switch(protocol) {
     case ORIGINAL_PROTOCOL:
@@ -860,6 +1072,7 @@ void start_radio() {
   if(device==SOAPYSDR_USB_DEVICE) {
     iqswap=1;
     receivers=1;
+    filter_board=NONE;
   }
 #endif
 
@@ -984,194 +1197,7 @@ void start_radio() {
 
   radio_change_region(region);
 
-  y=0;
-
-  fixed=gtk_fixed_new();
-  g_object_ref(grid);  // so it does not get deleted
-  gtk_container_remove(GTK_CONTAINER(top_window),grid);
-  gtk_container_add(GTK_CONTAINER(top_window), fixed);
-
-//g_print("radio: vfo_init\n");
-  vfo_panel = vfo_init(VFO_WIDTH,VFO_HEIGHT,top_window);
-  gtk_fixed_put(GTK_FIXED(fixed),vfo_panel,0,y);
-
-//g_print("radio: meter_init\n");
-  meter = meter_init(METER_WIDTH,METER_HEIGHT,top_window);
-  gtk_fixed_put(GTK_FIXED(fixed),meter,VFO_WIDTH,y);
-
-
-  GtkWidget *minimize_b=gtk_button_new_with_label("Hide");
-  gtk_widget_override_font(minimize_b, pango_font_description_from_string("FreeMono Bold 10"));
-  gtk_widget_set_size_request (minimize_b, MENU_WIDTH, MENU_HEIGHT);
-  g_signal_connect (minimize_b, "button-press-event", G_CALLBACK(minimize_cb), NULL) ;
-  gtk_fixed_put(GTK_FIXED(fixed),minimize_b,VFO_WIDTH+METER_WIDTH,y);
-  y+=MENU_HEIGHT;
-
-  GtkWidget *menu_b=gtk_button_new_with_label("Menu");
-  gtk_widget_override_font(menu_b, pango_font_description_from_string("FreeMono Bold 10"));
-  gtk_widget_set_size_request (menu_b, MENU_WIDTH, MENU_HEIGHT);
-  g_signal_connect (menu_b, "button-press-event", G_CALLBACK(menu_cb), NULL) ;
-  gtk_fixed_put(GTK_FIXED(fixed),menu_b,VFO_WIDTH+METER_WIDTH,y);
-  y+=MENU_HEIGHT;
-
-
-  rx_height=display_height-VFO_HEIGHT;
-  if(display_zoompan) {
-    rx_height-=ZOOMPAN_HEIGHT;
-  }
-  if(display_sliders) {
-    rx_height-=SLIDERS_HEIGHT;
-  }
-  if(display_toolbar) {
-    rx_height-=TOOLBAR_HEIGHT;
-  }
-
-  //
-  // To be on the safe side, we create ALL receiver panels here
-  // If upon startup, we only should display one panel, we do the switch below
-  //
-  for(i=0;i<RECEIVERS;i++) {
-    receiver[i]=create_receiver(i, buffer_size, fft_size, display_width, updates_per_second, display_width, rx_height/RECEIVERS);
-    setSquelch(receiver[i]);
-    receiver[i]->x=0;
-    receiver[i]->y=y;
-    gtk_fixed_put(GTK_FIXED(fixed),receiver[i]->panel,0,y);
-    g_object_ref((gpointer)receiver[i]->panel);
-    set_displaying(receiver[i],1);
-    y+=rx_height/RECEIVERS;
-    // Upon startup, if RIT or CTUN is active, tell WDSP.
-    set_offset(receiver[i],vfo[i].offset);
-  }
-
-  //
-  // Sanity check: in old protocol, all receivers must have the same sample rate
-  //
-  if((protocol==ORIGINAL_PROTOCOL) && (RECEIVERS==2) && (receiver[0]->sample_rate!=receiver[1]->sample_rate)) {
-    receiver[1]->sample_rate=receiver[0]->sample_rate;
-  }
-
-  active_receiver=receiver[0];
-
-  //g_print("Create transmitter\n");
-  if(can_transmit) {
-    double pk;
-    if(duplex) {
-      transmitter=create_transmitter(CHANNEL_TX, buffer_size, fft_size, updates_per_second, display_width/4, display_height/2);
-    } else {
-      int tx_height=display_height-VFO_HEIGHT;
-      if(display_zoompan) tx_height-=ZOOMPAN_HEIGHT;
-      if(display_sliders) tx_height-=SLIDERS_HEIGHT;
-      if(display_toolbar) tx_height-=TOOLBAR_HEIGHT;
-      transmitter=create_transmitter(CHANNEL_TX, buffer_size, fft_size, updates_per_second, display_width, tx_height);
-    }
-    transmitter->x=0;
-    transmitter->y=VFO_HEIGHT;
-
-    calcDriveLevel();
-
-#ifdef PURESIGNAL
-    tx_set_ps_sample_rate(transmitter,protocol==NEW_PROTOCOL?192000:active_receiver->sample_rate);
-    receiver[PS_TX_FEEDBACK]=create_pure_signal_receiver(PS_TX_FEEDBACK, buffer_size,protocol==ORIGINAL_PROTOCOL?active_receiver->sample_rate:192000,display_width);
-    receiver[PS_RX_FEEDBACK]=create_pure_signal_receiver(PS_RX_FEEDBACK, buffer_size,protocol==ORIGINAL_PROTOCOL?active_receiver->sample_rate:192000,display_width);
-    switch (protocol) {
-      case NEW_PROTOCOL:
-        pk = 0.2899;
-        break;
-      case ORIGINAL_PROTOCOL:
-        switch (device) {
-          case DEVICE_HERMES_LITE2:
-            pk = 0.2300;
-            break;
-          default:
-            pk = 0.4067;
-            break;
-        }
-    }
-    SetPSHWPeak(transmitter->id, pk);
-#endif
-
-  }
-
-#ifdef AUDIO_WATERFALL
-  audio_waterfall=audio_waterfall_init(200,100);
-  gtk_fixed_put(GTK_FIXED(fixed),audio_waterfall,0,VFO_HEIGHT+20);
-#endif
-
-  gboolean init_gpio=FALSE;
-#ifdef LOCALCW
-  init_gpio=TRUE;
-#endif
-#ifdef PTT
-  init_gpio=TRUE;
-#endif
-#ifdef GPIO
-  init_gpio=TRUE;
-#endif
-
-  if(init_gpio) {
-#ifdef GPIO
-    if(gpio_init()<0) {
-      g_print("GPIO failed to initialize\n");
-    }
-#endif
-  }
-
-#ifdef LOCALCW
-  // init local keyer if enabled
-  if (cw_keyer_internal == 0) {
-       g_print("Initialize keyer.....\n");
-    keyer_update();
-  }
-#endif
-  
-  switch(protocol) {
-    case ORIGINAL_PROTOCOL:
-      old_protocol_init(0,display_width,receiver[0]->sample_rate);
-      break;
-    case NEW_PROTOCOL:
-      new_protocol_init(display_width);
-      break;
-#ifdef SOAPYSDR
-    case SOAPYSDR_PROTOCOL:
-      soapy_protocol_init(0,false);
-      break;
-#endif
-  }
-
-  if(display_zoompan) {
-    zoompan = zoompan_init(display_width,ZOOMPAN_HEIGHT);
-    gtk_fixed_put(GTK_FIXED(fixed),zoompan,0,y);
-    y+=ZOOMPAN_HEIGHT;
-  }
-
-  if(display_sliders) {
-//g_print("create sliders\n");
-    sliders = sliders_init(display_width,SLIDERS_HEIGHT);
-    gtk_fixed_put(GTK_FIXED(fixed),sliders,0,y);
-    y+=SLIDERS_HEIGHT;
-  }
-
-
-  if(display_toolbar) {
-    toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,top_window);
-    gtk_fixed_put(GTK_FIXED(fixed),toolbar,0,y);
-    y+=TOOLBAR_HEIGHT;
-  }
-
-//
-// Now, if there should only one receiver be displayed
-// at startup, do the change. We must momentarily fake
-// the number of receivers otherwise radio_change_receivers
-// will do nothing.
-//
-  if (receivers != RECEIVERS) {
-    i=receivers,
-    receivers=RECEIVERS;
-    radio_change_receivers(i);
-  }
-
-  gtk_widget_show_all (fixed);
-  
+  create_visual();
 
   // save every 30 seconds
   //save_timer_id=gdk_threads_add_timeout(30000, save_cb, NULL);
@@ -1245,10 +1271,11 @@ void start_radio() {
   MIDIstartup();
 #endif
 
-#ifdef SERVER
-  create_hpsdr_server();
+#ifdef CLIENT_SERVER
+  if(hpsdr_server) {
+    create_hpsdr_server();
+  }
 #endif
-
 }
 
 void disable_rigctl() {
@@ -1258,17 +1285,23 @@ void disable_rigctl() {
  
 
 void radio_change_receivers(int r) {
+g_print("radio_change_receivers: from %d to %d\n",receivers,r);
   // The button in the radio menu will call this function even if the
   // number of receivers has not changed.
   if (receivers == r) return;
-  g_print("radio_change_receivers: from %d to %d\n",receivers,r);
   //
   // When changing the number of receivers, restart the
   // old protocol
   //
-  if (protocol == ORIGINAL_PROTOCOL) {
-    old_protocol_stop();
+#ifdef CLIENT_SERVER
+  if(!radio_is_remote) {
+#endif
+    if (protocol == ORIGINAL_PROTOCOL) {
+      old_protocol_stop();
+    }
+#ifdef CLIENT_SERVER
   }
+#endif
   switch(r) {
     case 1:
        set_displaying(receiver[1],0);
@@ -1283,12 +1316,18 @@ void radio_change_receivers(int r) {
   }
   reconfigure_radio();
   active_receiver=receiver[0];
-  if(protocol==NEW_PROTOCOL) {
-    schedule_high_priority();
-  }
-  if (protocol == ORIGINAL_PROTOCOL) {
-    old_protocol_run();
+#ifdef CLIENT_SERVER
+  if(!radio_is_remote) {
+#endif
+    if(protocol==NEW_PROTOCOL) {
+      schedule_high_priority();
+    }
+    if (protocol == ORIGINAL_PROTOCOL) {
+      old_protocol_run();
+    }
+#ifdef CLIENT_SERVER
   }
+#endif
 }
 
 void radio_change_sample_rate(int rate) {
@@ -1781,20 +1820,29 @@ void set_alex_attenuation(int v) {
 }
 
 void radioRestoreState() {
-    char name[32];
-    char *value;
-    int i;
+  char name[32];
+  char *value;
+  int i;
 
 g_print("radioRestoreState: %s\n",property_path);
-//g_print("sem_wait\n");
-#ifdef __APPLE__
-    sem_wait(property_sem);
-#else
-    sem_wait(&property_sem);
+  g_mutex_lock(&property_mutex);
+  loadProperties(property_path);
+
+  value=getProperty("display_filled");
+  if(value) display_filled=atoi(value);
+  value=getProperty("display_zoompan");
+  if(value) display_zoompan=atoi(value);
+  value=getProperty("display_sliders");
+  if(value) display_sliders=atoi(value);
+  value=getProperty("display_toolbar");
+  if(value) display_toolbar=atoi(value);
+
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+#ifdef CLIENT_SERVER
+#endif
+  } else {
 #endif
-//g_print("sem_wait: returner\n");
-    loadProperties(property_path);
-
     value=getProperty("diversity_enabled");
     if (value) diversity_enabled=atoi(value);
     value=getProperty("diversity_gain");
@@ -1830,8 +1878,6 @@ g_print("radioRestoreState: %s\n",property_path);
     }
     value=getProperty("updates_per_second");
     if(value) updates_per_second=atoi(value);
-    value=getProperty("display_filled");
-    if(value) display_filled=atoi(value);
     value=getProperty("display_detector_mode");
     if(value) display_detector_mode=atoi(value);
     value=getProperty("display_average_mode");
@@ -1842,12 +1888,6 @@ g_print("radioRestoreState: %s\n",property_path);
     if(value) panadapter_high=atoi(value);
     value=getProperty("panadapter_low");
     if(value) panadapter_low=atoi(value);
-    value=getProperty("display_zoompan");
-    if(value) display_zoompan=atoi(value);
-    value=getProperty("display_sliders");
-    if(value) display_sliders=atoi(value);
-    value=getProperty("display_toolbar");
-    if(value) display_toolbar=atoi(value);
     value=getProperty("waterfall_high");
     if(value) waterfall_high=atoi(value);
     value=getProperty("waterfall_low");
@@ -2013,51 +2053,89 @@ g_print("radioRestoreState: %s\n",property_path);
     if(value) mute_rx_while_transmitting=atoi(value);
 
 #ifdef SOAPYSDR
-  if(device==SOAPYSDR_USB_DEVICE) {
-    char name[128];
-    for(int i=0;i<radio->info.soapy.rx_gains;i++) {
-      sprintf(name,"radio.adc[0].rx_gain.%s",radio->info.soapy.rx_gain[i]) ;
-      value=getProperty(name);
-      if(value!=NULL) adc[0].rx_gain[i]=atoi(value);
-    }
-    value=getProperty("radio.adc[0].agc");
-    if(value!=NULL) adc[0].agc=atoi(value);
-    value=getProperty("radio.adc[0].antenna");
-    if(value!=NULL) adc[0].antenna=atoi(value);
-
-    value=getProperty("radio.dac[0].antenna");
-    if(value!=NULL) dac[0].antenna=atoi(value);
-    for(int i=0;i<radio->info.soapy.tx_gains;i++) {
-      sprintf(name,"radio.dac[0].tx_gain.%s",radio->info.soapy.tx_gain[i]);
-      value=getProperty(name);
-      if(value!=NULL) dac[0].tx_gain[i]=atoi(value);
+    if(device==SOAPYSDR_USB_DEVICE) {
+      char name[128];
+      for(int i=0;i<radio->info.soapy.rx_gains;i++) {
+        sprintf(name,"radio.adc[0].rx_gain.%s",radio->info.soapy.rx_gain[i]) ;
+        value=getProperty(name);
+        if(value!=NULL) adc[0].rx_gain[i]=atoi(value);
+      }
+      value=getProperty("radio.adc[0].agc");
+      if(value!=NULL) adc[0].agc=atoi(value);
+      value=getProperty("radio.adc[0].antenna");
+      if(value!=NULL) adc[0].antenna=atoi(value);
+  
+      value=getProperty("radio.dac[0].antenna");
+      if(value!=NULL) dac[0].antenna=atoi(value);
+      for(int i=0;i<radio->info.soapy.tx_gains;i++) {
+        sprintf(name,"radio.dac[0].tx_gain.%s",radio->info.soapy.tx_gain[i]);
+        value=getProperty(name);
+        if(value!=NULL) dac[0].tx_gain[i]=atoi(value);
+      }
     }
-  }
 #endif
 
-  value=getProperty("radio.display_sequence_errors");
-  if(value!=NULL) display_sequence_errors=atoi(value);
+    value=getProperty("radio.display_sequence_errors");
+    if(value!=NULL) display_sequence_errors=atoi(value);
+
+
        
-//g_print("sem_post\n");
-#ifdef __APPLE__
-    sem_post(property_sem);
-#else
-    sem_post(&property_sem);
+#ifdef CLIENT_SERVER
+  }
 #endif
+
+#ifdef CLIENT_SERVER
+  value=getProperty("radio.hpsdr_server");
+  if(value!=NULL) hpsdr_server=atoi(value);
+  value=getProperty("radio.hpsdr_server.listen_port");
+  if(value!=NULL) listen_port=atoi(value);
+#endif
+
+  g_mutex_unlock(&property_mutex);
 }
 
 void radioSaveState() {
-    int i;
-    char value[80];
-    char name[32];
+  int i;
+  char value[80];
+  char name[32];
+
 
 g_print("radioSaveState: %s\n",property_path);
-#ifdef __APPLE__
-    sem_wait(property_sem);
-#else
-    sem_wait(&property_sem);
+  
+  g_mutex_lock(&property_mutex);
+  clearProperties();
+#ifdef GPIO
+  if(controller!=NO_CONTROLLER) {
+    gpio_save_actions();
+  }
+#endif
+  sprintf(value,"%d",receivers);
+  setProperty("receivers",value);
+  for(i=0;i<receivers;i++) {
+    receiver_save_state(receiver[i]);
+  }
+
+  sprintf(value,"%d",display_filled);
+  setProperty("display_filled",value);
+  sprintf(value,"%d",display_zoompan);
+  setProperty("display_zoompan",value);
+  sprintf(value,"%d",display_sliders);
+  setProperty("display_sliders",value);
+  sprintf(value,"%d",display_toolbar);
+  setProperty("display_toolbar",value);
+
+  if(can_transmit) {
+#ifdef PURESIGNAL
+    // The only variables of interest in this receiver are
+    // the alex_antenna an the adc
+    receiver_save_state(receiver[PS_RX_FEEDBACK]);
+#endif
+    transmitter_save_state(transmitter);
+  }
+
+#ifdef CLIENT_SERVER
+  if(!radio_is_remote) {
 #endif
-    clearProperties();
     sprintf(value,"%d",diversity_enabled);
     setProperty("diversity_enabled",value);
     sprintf(value,"%f",div_gain);
@@ -2084,8 +2162,6 @@ g_print("radioSaveState: %s\n",property_path);
     setProperty("tx_out_of_band",value);
     sprintf(value,"%d",updates_per_second);
     setProperty("updates_per_second",value);
-    sprintf(value,"%d",display_filled);
-    setProperty("display_filled",value);
     sprintf(value,"%d",display_detector_mode);
     setProperty("display_detector_mode",value);
     sprintf(value,"%d",display_average_mode);
@@ -2096,12 +2172,6 @@ g_print("radioSaveState: %s\n",property_path);
     setProperty("panadapter_high",value);
     sprintf(value,"%d",panadapter_low);
     setProperty("panadapter_low",value);
-    sprintf(value,"%d",display_zoompan);
-    setProperty("display_zoompan",value);
-    sprintf(value,"%d",display_sliders);
-    setProperty("display_sliders",value);
-    sprintf(value,"%d",display_toolbar);
-    setProperty("display_toolbar",value);
     sprintf(value,"%d",waterfall_high);
     setProperty("waterfall_high",value);
     sprintf(value,"%d",waterfall_low);
@@ -2292,21 +2362,15 @@ g_print("radioSaveState: %s\n",property_path);
     sprintf(value,"%d",iqswap);
     setProperty("iqswap",value);
        
+#ifdef CLIENT_SERVER
+    sprintf(value,"%d",hpsdr_server);
+    setProperty("radio.hpsdr_server",value);
+    sprintf(value,"%d",listen_port);
+    setProperty("radio.hpsdr_server.listen_port",value);
+#endif
+
     vfo_save_state();
     modesettings_save_state();
-    sprintf(value,"%d",receivers);
-    setProperty("receivers",value);
-    for(i=0;i<receivers;i++) {
-      receiver_save_state(receiver[i]);
-    }
-    if(can_transmit) {
-#ifdef PURESIGNAL
-      // The only variables of interest in this receiver are
-      // the alex_antenna an the adc
-      receiver_save_state(receiver[PS_RX_FEEDBACK]);
-#endif
-      transmitter_save_state(transmitter);
-    }
 
     sprintf(value,"%d",duplex);
     setProperty("duplex",value);
@@ -2321,12 +2385,6 @@ g_print("radioSaveState: %s\n",property_path);
     bandSaveState();
     memSaveState();
 
-#ifdef GPIO
-    if(controller!=NO_CONTROLLER) {
-      gpio_save_actions();
-    }
-#endif
-
     sprintf(value,"%d",rigctl_enable);
     setProperty("rigctl_enable",value);
     sprintf(value,"%d",rigctl_port_base);
@@ -2334,14 +2392,12 @@ g_print("radioSaveState: %s\n",property_path);
 
     sprintf(value,"%d",display_sequence_errors);
     setProperty("radio.display_sequence_errors",value);
-
-    saveProperties(property_path);
-g_print("sem_post\n");
-#ifdef __APPLE__
-    sem_post(property_sem);
-#else
-    sem_post(&property_sem);
+#ifdef CLIENT_SERVER
+  }
 #endif
+
+  saveProperties(property_path);
+  g_mutex_unlock(&property_mutex);
 }
 
 void calculate_display_average(RECEIVER *rx) {
@@ -2406,3 +2462,49 @@ void radio_change_region(int r) {
   }
 }
 
+#ifdef CLIENT_SERVER
+int remote_start(void *data) {
+  char *server=(char *)data;
+  sprintf(property_path,"%s@%s.props",radio->name,server);
+  radio_is_remote=TRUE;
+#ifdef GPIO
+  switch(controller) {
+    case CONTROLLER2_V1:
+    case CONTROLLER2_V2:
+      display_zoompan=1;
+      display_sliders=0;
+      display_toolbar=0;
+      break;
+    default:
+      display_zoompan=1;
+      display_sliders=1;
+      display_toolbar=1;
+      break;
+  }
+#else
+  display_zoompan=1;
+  display_sliders=1;
+  display_toolbar=1;
+#endif
+  radioRestoreState();
+  create_visual();
+  for(int i=0;i<receivers;i++) {
+    receiver_restore_state(receiver[i]);
+    if(receiver[i]->local_audio) {
+      audio_open_output(receiver[i]);
+    }
+  }
+  reconfigure_radio();
+  g_idle_add(ext_vfo_update,(gpointer)NULL);
+  gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_ARROW));
+#ifdef MIDI
+  MIDIstartup();
+#endif
+  for(int i=0;i<receivers;i++) {
+    gint timer_id=gdk_threads_add_timeout_full(G_PRIORITY_DEFAULT_IDLE,100, start_spectrum, receiver[i], NULL);
+  }
+  start_vfo_timer();
+  remote_started=TRUE;
+  return 0;
+}
+#endif
diff --git a/radio.h b/radio.h
index 12c00b9bc8ca045acd494195a5ccac6584e2bfb1..e0b834f5d36b79bd1048313767da1603fc7717f8 100644 (file)
--- a/radio.h
+++ b/radio.h
@@ -57,6 +57,9 @@ enum {
 };
 
 extern DISCOVERED *radio;
+#ifdef CLIENT_SERVER
+extern gboolean radio_is_remote;
+#endif
 
 extern GtkWidget *fixed;
 
@@ -171,13 +174,13 @@ extern int mic_ptt_tip_bias_ring;
 //extern int tune_drive_level;
 //extern int drive_level;
 
-int receivers;
+extern int receivers;
 
-ADC adc[2];
-DAC dac[2];
-int adc_attenuation[2];
+extern ADC adc[2];
+extern DAC dac[2];
+extern int adc_attenuation[2];
 
-int locked;
+extern int locked;
 
 extern long long step;
 extern int rit_increment;
@@ -303,6 +306,11 @@ extern double drive_max;
 
 extern gboolean display_sequence_errors;
 extern gint sequence_errors;
+extern GMutex property_mutex;
+
+#ifdef CLIENT_SERVER
+extern gboolean server;
+#endif
 
 extern void radio_stop();
 extern void reconfigure_radio();
@@ -346,4 +354,8 @@ extern void radio_change_region(int region);
 
 extern void disable_rigctl();
 
+#ifdef CLIENT_SERVER
+extern int remote_start(void *data);
+#endif
+
 #endif
index db99059360ea23da2956f8fda3e62b77cc057578..515579abdee36b24db33e7834bf6937c284a228a 100644 (file)
@@ -42,6 +42,9 @@
 #include "gpio.h"
 #include "vfo.h"
 #include "ext.h"
+#ifdef CLIENT_SERVER
+#include "client_server.h"
+#endif
 
 static GtkWidget *parent_window=NULL;
 static GtkWidget *menu_b=NULL;
@@ -251,7 +254,7 @@ static void sat_cb(GtkWidget *widget, gpointer data) {
   g_idle_add(ext_vfo_update, NULL);
 }
 
-static void load_filters(void) {
+void load_filters(void) {
   if(filter_board==N2ADR) {
     // set OC filters
     BAND *band;
@@ -342,8 +345,16 @@ static void n2adr_cb(GtkWidget *widget, gpointer data) {
 
 static void sample_rate_cb(GtkToggleButton *widget, gpointer data) {
   if(gtk_toggle_button_get_active(widget)) {
-    radio_change_sample_rate(GPOINTER_TO_INT(data));
+#ifdef CLIENT_SERVER
+    if(radio_is_remote) {
+      send_sample_rate(client_socket,-1,GPOINTER_TO_INT(data));
+    } else {
+#endif
+      radio_change_sample_rate(GPOINTER_TO_INT(data));
+    }
+#ifdef CLIENT_SERVER
   }
+#endif
 }
 
 static void receivers_cb(GtkToggleButton *widget, gpointer data) {
@@ -357,7 +368,15 @@ static void receivers_cb(GtkToggleButton *widget, gpointer data) {
     return;
   }
   if(gtk_toggle_button_get_active(widget)) {
-    radio_change_receivers(GPOINTER_TO_INT(data));
+#ifdef CLIENT_SERVER
+    if(radio_is_remote) {
+      send_receivers(client_socket,GPOINTER_TO_INT(data));
+    } else {
+#endif
+      radio_change_receivers(GPOINTER_TO_INT(data));
+#ifdef CLIENT_SERVER
+    }
+#endif
   }
 }
 
@@ -652,6 +671,7 @@ void radio_menu(GtkWidget *parent) {
   col++;
   row=1;
 
+#ifdef GPIO
   GtkWidget *vfo_divisor_label=gtk_label_new(NULL);
   gtk_label_set_markup(GTK_LABEL(vfo_divisor_label), "<b>VFO Encoder Divisor:</b>");
   gtk_grid_attach(GTK_GRID(grid),vfo_divisor_label,col,row,1,1);
@@ -662,6 +682,7 @@ void radio_menu(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),vfo_divisor,col,row,1,1);
   g_signal_connect(vfo_divisor,"value_changed",G_CALLBACK(vfo_divisor_value_changed_cb),NULL);
   row++;
+#endif
    
   GtkWidget *iqswap_b=gtk_check_button_new_with_label("Swap IQ");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (iqswap_b), iqswap);
index 7af7eab4f678fc0c0377a9ed901c95bbca317d60..b2d495d231aa4a805e907bd7d4c976bf846ce23b 100644 (file)
@@ -19,3 +19,4 @@
 
 extern void radio_menu(GtkWidget *parent);
 extern void setDuplex(void);
+extern void load_filters(void);
index 8ae57f208a8212885fd3d968fd7a705b6777099c..c6e1ec06529ddbf0a50520dac14d10d8741794b6 100644 (file)
@@ -51,6 +51,9 @@
 #endif
 #include "ext.h"
 #include "new_menu.h"
+#ifdef CLIENT_SERVER
+#include "client_server.h"
+#endif
 
 
 #define min(x,y) (x<y?x:y)
@@ -85,23 +88,34 @@ gboolean receiver_button_press_event(GtkWidget *widget, GdkEventButton *event, g
   return TRUE;
 }
 
+void receiver_set_active(RECEIVER *rx) {
+  active_receiver=rx;
+  g_idle_add(menu_active_receiver_changed,NULL);
+  g_idle_add(ext_vfo_update,NULL);
+  g_idle_add(zoompan_active_receiver_changed,NULL);
+  g_idle_add(sliders_active_receiver_changed,NULL);
+  // setup the transmitter mode and filter
+  if(can_transmit) {
+    tx_set_mode(transmitter,get_tx_mode());
+  }
+}
+
 gboolean receiver_button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer data) {
   RECEIVER *rx=(RECEIVER *)data;
   if(making_active) {
-    active_receiver=rx;
     making_active=FALSE;
-    g_idle_add(menu_active_receiver_changed,NULL);
-    g_idle_add(ext_vfo_update,NULL);
-    g_idle_add(zoompan_active_receiver_changed,NULL);
-    g_idle_add(sliders_active_receiver_changed,NULL);
-    if(event->button==3) {
-      g_idle_add(ext_start_rx,NULL);
-    }
-
-    // setup the transmitter mode and filter
-    tx_set_mode(transmitter,get_tx_mode());
-
-    //g_print("receiver: %d adc=%d attenuation=%d rx_gain_calibration=%d\n",rx->id,rx->adc,adc_attenuation[rx->adc],rx_gain_calibration);
+#ifdef CLIENT_SERVER
+    if(radio_is_remote) {
+      send_rx_select(client_socket,rx->id);
+    } else {
+#endif
+      receiver_set_active(rx);
+      if(event->button==3) {
+        g_idle_add(ext_start_rx,NULL);
+      }
+#ifdef CLIENT_SERVER
+   }
+#endif
   } else {
     if(pressed) {
       int x=(int)event->x;
@@ -161,117 +175,7 @@ void receiver_save_state(RECEIVER *rx) {
   char name[128];
   char value[128];
 
-  sprintf(name,"receiver.%d.alex_antenna",rx->id);
-  sprintf(value,"%d",rx->alex_antenna);
-  setProperty(name,value);
-
-#ifdef PURESIGNAL
-  //
-  // for PS_RX_RECEIVER, *only* save the ALEX antenna setting
-  // and then return quickly.
-  //
-  if (rx->id == PS_RX_FEEDBACK) return;
-#endif
-
-  sprintf(name,"receiver.%d.sample_rate",rx->id);
-  sprintf(value,"%d",rx->sample_rate);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.adc",rx->id);
-  sprintf(value,"%d",rx->adc);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.filter_low",rx->id);
-  sprintf(value,"%d",rx->filter_low);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.filter_high",rx->id);
-  sprintf(value,"%d",rx->filter_high);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.fps",rx->id);
-  sprintf(value,"%d",rx->fps);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.panadapter_low",rx->id);
-  sprintf(value,"%d",rx->panadapter_low);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.panadapter_high",rx->id);
-  sprintf(value,"%d",rx->panadapter_high);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.panadapter_step",rx->id);
-  sprintf(value,"%d",rx->panadapter_step);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.display_waterfall",rx->id);
-  sprintf(value,"%d",rx->display_waterfall);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.waterfall_low",rx->id);
-  sprintf(value,"%d",rx->waterfall_low);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.waterfall_high",rx->id);
-  sprintf(value,"%d",rx->waterfall_high);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.waterfall_automatic",rx->id);
-  sprintf(value,"%d",rx->waterfall_automatic);
-  setProperty(name,value);
-  
-  sprintf(name,"receiver.%d.alex_attenuation",rx->id);
-  sprintf(value,"%d",rx->alex_attenuation);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.volume",rx->id);
-  sprintf(value,"%f",rx->volume);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.rf_gain",rx->id);
-  sprintf(value,"%f",rx->rf_gain);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.agc",rx->id);
-  sprintf(value,"%d",rx->agc);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.agc_gain",rx->id);
-  sprintf(value,"%f",rx->agc_gain);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.agc_slope",rx->id);
-  sprintf(value,"%f",rx->agc_slope);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.agc_hang_threshold",rx->id);
-  sprintf(value,"%f",rx->agc_hang_threshold);
-  setProperty(name,value);
-
-  sprintf(name,"receiver.%d.dither",rx->id);
-  sprintf(value,"%d",rx->dither);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.random",rx->id);
-  sprintf(value,"%d",rx->random);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.preamp",rx->id);
-  sprintf(value,"%d",rx->preamp);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.nb",rx->id);
-  sprintf(value,"%d",rx->nb);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.nb2",rx->id);
-  sprintf(value,"%d",rx->nb2);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.nr",rx->id);
-  sprintf(value,"%d",rx->nr);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.nr2",rx->id);
-  sprintf(value,"%d",rx->nr2);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.anf",rx->id);
-  sprintf(value,"%d",rx->anf);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.snb",rx->id);
-  sprintf(value,"%d",rx->snb);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.nr_agc",rx->id);
-  sprintf(value,"%d",rx->nr_agc);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.nr2_gain_method",rx->id);
-  sprintf(value,"%d",rx->nr2_gain_method);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.nr2_npe_method",rx->id);
-  sprintf(value,"%d",rx->nr2_npe_method);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.nr2_ae",rx->id);
-  sprintf(value,"%d",rx->nr2_ae);
-  setProperty(name,value);
-
+  g_print("receiver_save_state: %d\n",rx->id);
   sprintf(name,"receiver.%d.audio_channel",rx->id);
   sprintf(value,"%d",rx->audio_channel);
   setProperty(name,value);
@@ -296,27 +200,144 @@ void receiver_save_state(RECEIVER *rx) {
   sprintf(value,"%d",rx->mute_radio);
   setProperty(name,value);
 
-  sprintf(name,"receiver.%d.low_latency",rx->id);
-  sprintf(value,"%d",rx->low_latency);
-  setProperty(name,value);
+#ifdef CLIENT_SERVER
+  if(!radio_is_remote) {
+#endif
+    sprintf(name,"receiver.%d.alex_antenna",rx->id);
+    sprintf(value,"%d",rx->alex_antenna);
+    setProperty(name,value);
 
-  sprintf(name,"receiver.%d.deviation",rx->id);
-  sprintf(value,"%d",rx->deviation);
-  setProperty(name,value);
+#ifdef PURESIGNAL
+    //
+    // for PS_RX_RECEIVER, *only* save the ALEX antenna setting
+    // and then return quickly.
+    //
+    if (rx->id == PS_RX_FEEDBACK) return;
+#endif
 
-  sprintf(name,"receiver.%d.squelch_enable",rx->id);
-  sprintf(value,"%d",rx->squelch_enable);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.squelch",rx->id);
-  sprintf(value,"%f",rx->squelch);
-  setProperty(name,value);
+    sprintf(name,"receiver.%d.sample_rate",rx->id);
+    sprintf(value,"%d",rx->sample_rate);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.adc",rx->id);
+    sprintf(value,"%d",rx->adc);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.filter_low",rx->id);
+    sprintf(value,"%d",rx->filter_low);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.filter_high",rx->id);
+    sprintf(value,"%d",rx->filter_high);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.fps",rx->id);
+    sprintf(value,"%d",rx->fps);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.panadapter_low",rx->id);
+    sprintf(value,"%d",rx->panadapter_low);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.panadapter_high",rx->id);
+    sprintf(value,"%d",rx->panadapter_high);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.panadapter_step",rx->id);
+    sprintf(value,"%d",rx->panadapter_step);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.display_waterfall",rx->id);
+    sprintf(value,"%d",rx->display_waterfall);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.waterfall_low",rx->id);
+    sprintf(value,"%d",rx->waterfall_low);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.waterfall_high",rx->id);
+    sprintf(value,"%d",rx->waterfall_high);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.waterfall_automatic",rx->id);
+    sprintf(value,"%d",rx->waterfall_automatic);
+    setProperty(name,value);
+  
+    sprintf(name,"receiver.%d.alex_attenuation",rx->id);
+    sprintf(value,"%d",rx->alex_attenuation);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.volume",rx->id);
+    sprintf(value,"%f",rx->volume);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.rf_gain",rx->id);
+    sprintf(value,"%f",rx->rf_gain);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.agc",rx->id);
+    sprintf(value,"%d",rx->agc);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.agc_gain",rx->id);
+    sprintf(value,"%f",rx->agc_gain);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.agc_slope",rx->id);
+    sprintf(value,"%f",rx->agc_slope);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.agc_hang_threshold",rx->id);
+    sprintf(value,"%f",rx->agc_hang_threshold);
+    setProperty(name,value);
 
-  sprintf(name,"receiver.%d.zoom",rx->id);
-  sprintf(value,"%d",rx->zoom);
-  setProperty(name,value);
-  sprintf(name,"receiver.%d.pan",rx->id);
-  sprintf(value,"%d",rx->pan);
-  setProperty(name,value);
+    sprintf(name,"receiver.%d.dither",rx->id);
+    sprintf(value,"%d",rx->dither);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.random",rx->id);
+    sprintf(value,"%d",rx->random);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.preamp",rx->id);
+    sprintf(value,"%d",rx->preamp);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.nb",rx->id);
+    sprintf(value,"%d",rx->nb);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.nb2",rx->id);
+    sprintf(value,"%d",rx->nb2);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.nr",rx->id);
+    sprintf(value,"%d",rx->nr);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.nr2",rx->id);
+    sprintf(value,"%d",rx->nr2);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.anf",rx->id);
+    sprintf(value,"%d",rx->anf);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.snb",rx->id);
+    sprintf(value,"%d",rx->snb);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.nr_agc",rx->id);
+    sprintf(value,"%d",rx->nr_agc);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.nr2_gain_method",rx->id);
+    sprintf(value,"%d",rx->nr2_gain_method);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.nr2_npe_method",rx->id);
+    sprintf(value,"%d",rx->nr2_npe_method);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.nr2_ae",rx->id);
+    sprintf(value,"%d",rx->nr2_ae);
+    setProperty(name,value);
+
+    sprintf(name,"receiver.%d.low_latency",rx->id);
+    sprintf(value,"%d",rx->low_latency);
+    setProperty(name,value);
+  
+    sprintf(name,"receiver.%d.deviation",rx->id);
+    sprintf(value,"%d",rx->deviation);
+    setProperty(name,value);
+  
+    sprintf(name,"receiver.%d.squelch_enable",rx->id);
+    sprintf(value,"%d",rx->squelch_enable);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.squelch",rx->id);
+    sprintf(value,"%f",rx->squelch);
+    setProperty(name,value);
+  
+    sprintf(name,"receiver.%d.zoom",rx->id);
+    sprintf(value,"%d",rx->zoom);
+    setProperty(name,value);
+    sprintf(name,"receiver.%d.pan",rx->id);
+    sprintf(value,"%d",rx->pan);
+    setProperty(name,value);
+#ifdef CLIENT_SERVER
+  }
+#endif
 }
 
 void receiver_restore_state(RECEIVER *rx) {
@@ -324,137 +345,6 @@ void receiver_restore_state(RECEIVER *rx) {
   char *value;
 
 fprintf(stderr,"receiver_restore_state: id=%d\n",rx->id);
-  sprintf(name,"receiver.%d.alex_antenna",rx->id);
-  value=getProperty(name);
-  if(value) rx->alex_antenna=atoi(value);
-
-#ifdef PURESIGNAL
-  //
-  // for PS_RX_RECEIVER, *only* restore the ALEX antenna and setting
-  // and then return quickly
-  //
-  if (rx->id == PS_RX_FEEDBACK) return;
-#endif
-
-  sprintf(name,"receiver.%d.sample_rate",rx->id);
-  value=getProperty(name);
-  if(value) rx->sample_rate=atoi(value);
-  sprintf(name,"receiver.%d.adc",rx->id);
-  value=getProperty(name);
-  if(value) rx->adc=atoi(value);
-  //
-  // Do not specify a second ADC if there is only one
-  //
-  if (n_adc == 1) rx->adc=0;
-  sprintf(name,"receiver.%d.filter_low",rx->id);
-  value=getProperty(name);
-  if(value) rx->filter_low=atoi(value);
-  sprintf(name,"receiver.%d.filter_high",rx->id);
-  value=getProperty(name);
-  if(value) rx->filter_high=atoi(value);
-  sprintf(name,"receiver.%d.fps",rx->id);
-  value=getProperty(name);
-  if(value) rx->fps=atoi(value);
-/*
-  sprintf(name,"receiver.%d.frequency",rx->id);
-  value=getProperty(name);
-  if(value) rx->frequency=atoll(value);
-  sprintf(name,"receiver.%d.display_frequency",rx->id);
-  value=getProperty(name);
-  if(value) rx->display_frequency=atoll(value);
-  sprintf(name,"receiver.%d.dds_frequency",rx->id);
-  value=getProperty(name);
-  if(value) rx->dds_frequency=atoll(value);
-  sprintf(name,"receiver.%d.dds_offset",rx->id);
-  value=getProperty(name);
-  if(value) rx->dds_offset=atoll(value);
-  sprintf(name,"receiver.%d.rit",rx->id);
-  value=getProperty(name);
-  if(value) rx->rit=atoi(value);
-*/
-  sprintf(name,"receiver.%d.panadapter_low",rx->id);
-  value=getProperty(name);
-  if(value) rx->panadapter_low=atoi(value);
-  sprintf(name,"receiver.%d.panadapter_high",rx->id);
-  value=getProperty(name);
-  if(value) rx->panadapter_high=atoi(value);
-  sprintf(name,"receiver.%d.panadapter_step",rx->id);
-  value=getProperty(name);
-  if(value) rx->panadapter_step=atoi(value);
-  sprintf(name,"receiver.%d.display_waterfall",rx->id);
-  value=getProperty(name);
-  if(value) rx->display_waterfall=atoi(value);
-  sprintf(name,"receiver.%d.waterfall_low",rx->id);
-  value=getProperty(name);
-  if(value) rx->waterfall_low=atoi(value);
-  sprintf(name,"receiver.%d.waterfall_high",rx->id);
-  value=getProperty(name);
-  if(value) rx->waterfall_high=atoi(value);
-  sprintf(name,"receiver.%d.waterfall_automatic",rx->id);
-  value=getProperty(name);
-  if(value) rx->waterfall_automatic=atoi(value);
-
-  sprintf(name,"receiver.%d.alex_attenuation",rx->id);
-  value=getProperty(name);
-  if(value) rx->alex_attenuation=atoi(value);
-  sprintf(name,"receiver.%d.volume",rx->id);
-  value=getProperty(name);
-  if(value) rx->volume=atof(value);
-  sprintf(name,"receiver.%d.rf_gain",rx->id);
-  value=getProperty(name);
-  if(value) rx->rf_gain=atof(value);
-  sprintf(name,"receiver.%d.agc",rx->id);
-  value=getProperty(name);
-  if(value) rx->agc=atoi(value);
-  sprintf(name,"receiver.%d.agc_gain",rx->id);
-  value=getProperty(name);
-  if(value) rx->agc_gain=atof(value);
-  sprintf(name,"receiver.%d.agc_slope",rx->id);
-  value=getProperty(name);
-  if(value) rx->agc_slope=atof(value);
-  sprintf(name,"receiver.%d.agc_hang_threshold",rx->id);
-  value=getProperty(name);
-  if(value) rx->agc_hang_threshold=atof(value);
-
-  sprintf(name,"receiver.%d.dither",rx->id);
-  value=getProperty(name);
-  if(value) rx->dither=atoi(value);
-  sprintf(name,"receiver.%d.random",rx->id);
-  value=getProperty(name);
-  if(value) rx->random=atoi(value);
-  sprintf(name,"receiver.%d.preamp",rx->id);
-  value=getProperty(name);
-  if(value) rx->preamp=atoi(value);
-  sprintf(name,"receiver.%d.nb",rx->id);
-  value=getProperty(name);
-  if(value) rx->nb=atoi(value);
-  sprintf(name,"receiver.%d.nb2",rx->id);
-  value=getProperty(name);
-  if(value) rx->nb2=atoi(value);
-  sprintf(name,"receiver.%d.nr",rx->id);
-  value=getProperty(name);
-  if(value) rx->nr=atoi(value);
-  sprintf(name,"receiver.%d.nr2",rx->id);
-  value=getProperty(name);
-  if(value) rx->nr2=atoi(value);
-  sprintf(name,"receiver.%d.anf",rx->id);
-  value=getProperty(name);
-  if(value) rx->anf=atoi(value);
-  sprintf(name,"receiver.%d.snb",rx->id);
-  value=getProperty(name);
-  if(value) rx->snb=atoi(value);
-  sprintf(name,"receiver.%d.nr_agc",rx->id);
-  value=getProperty(name);
-  if(value) rx->nr_agc=atoi(value);
-  sprintf(name,"receiver.%d.nr2_gain_method",rx->id);
-  value=getProperty(name);
-  if(value) rx->nr2_gain_method=atoi(value);
-  sprintf(name,"receiver.%d.nr2_npe_method",rx->id);
-  value=getProperty(name);
-  if(value) rx->nr2_npe_method=atoi(value);
-  sprintf(name,"receiver.%d.ae",rx->id);
-  value=getProperty(name);
-  if(value) rx->nr2_ae=atoi(value);
 
   sprintf(name,"receiver.%d.audio_channel",rx->id);
   value=getProperty(name);
@@ -482,27 +372,166 @@ fprintf(stderr,"receiver_restore_state: id=%d\n",rx->id);
   sprintf(name,"receiver.%d.mute_radio",rx->id);
   value=getProperty(name);
   if(value) rx->mute_radio=atoi(value);
-  sprintf(name,"receiver.%d.low_latency",rx->id);
-  value=getProperty(name);
-  if(value) rx->low_latency=atoi(value);
 
-  sprintf(name,"receiver.%d.deviation",rx->id);
-  value=getProperty(name);
-  if(value) rx->deviation=atoi(value);
+#ifdef CLIENT_SERVER
+  if(!radio_is_remote) {
+#endif
+    sprintf(name,"receiver.%d.alex_antenna",rx->id);
+    value=getProperty(name);
+    if(value) rx->alex_antenna=atoi(value);
 
-  sprintf(name,"receiver.%d.squelch_enable",rx->id);
+#ifdef PURESIGNAL
+    //
+    // for PS_RX_RECEIVER, *only* restore the ALEX antenna and setting
+    // and then return quickly
+    //
+    if (rx->id == PS_RX_FEEDBACK) return;
+#endif
+
+    sprintf(name,"receiver.%d.sample_rate",rx->id);
+    value=getProperty(name);
+    if(value) rx->sample_rate=atoi(value);
+    sprintf(name,"receiver.%d.adc",rx->id);
+    value=getProperty(name);
+    if(value) rx->adc=atoi(value);
+    //
+    // Do not specify a second ADC if there is only one
+    //
+    if (n_adc == 1) rx->adc=0;
+    sprintf(name,"receiver.%d.filter_low",rx->id);
+    value=getProperty(name);
+    if(value) rx->filter_low=atoi(value);
+    sprintf(name,"receiver.%d.filter_high",rx->id);
+    value=getProperty(name);
+    if(value) rx->filter_high=atoi(value);
+    sprintf(name,"receiver.%d.fps",rx->id);
+    value=getProperty(name);
+    if(value) rx->fps=atoi(value);
+/*
+  sprintf(name,"receiver.%d.frequency",rx->id);
   value=getProperty(name);
-  if(value) rx->squelch_enable=atoi(value);
-  sprintf(name,"receiver.%d.squelch",rx->id);
+  if(value) rx->frequency=atoll(value);
+  sprintf(name,"receiver.%d.display_frequency",rx->id);
   value=getProperty(name);
-  if(value) rx->squelch=atof(value);
-
-  sprintf(name,"receiver.%d.zoom",rx->id);
+  if(value) rx->display_frequency=atoll(value);
+  sprintf(name,"receiver.%d.dds_frequency",rx->id);
   value=getProperty(name);
-  if(value) rx->zoom=atoi(value);
-  sprintf(name,"receiver.%d.pan",rx->id);
+  if(value) rx->dds_frequency=atoll(value);
+  sprintf(name,"receiver.%d.dds_offset",rx->id);
+  value=getProperty(name);
+  if(value) rx->dds_offset=atoll(value);
+  sprintf(name,"receiver.%d.rit",rx->id);
   value=getProperty(name);
-  if(value) rx->pan=atoi(value);
+  if(value) rx->rit=atoi(value);
+*/
+    sprintf(name,"receiver.%d.panadapter_low",rx->id);
+    value=getProperty(name);
+    if(value) rx->panadapter_low=atoi(value);
+    sprintf(name,"receiver.%d.panadapter_high",rx->id);
+    value=getProperty(name);
+    if(value) rx->panadapter_high=atoi(value);
+    sprintf(name,"receiver.%d.panadapter_step",rx->id);
+    value=getProperty(name);
+    if(value) rx->panadapter_step=atoi(value);
+    sprintf(name,"receiver.%d.display_waterfall",rx->id);
+    value=getProperty(name);
+    if(value) rx->display_waterfall=atoi(value);
+    sprintf(name,"receiver.%d.waterfall_low",rx->id);
+    value=getProperty(name);
+    if(value) rx->waterfall_low=atoi(value);
+    sprintf(name,"receiver.%d.waterfall_high",rx->id);
+    value=getProperty(name);
+    if(value) rx->waterfall_high=atoi(value);
+    sprintf(name,"receiver.%d.waterfall_automatic",rx->id);
+    value=getProperty(name);
+    if(value) rx->waterfall_automatic=atoi(value);
+
+    sprintf(name,"receiver.%d.alex_attenuation",rx->id);
+    value=getProperty(name);
+    if(value) rx->alex_attenuation=atoi(value);
+    sprintf(name,"receiver.%d.volume",rx->id);
+    value=getProperty(name);
+    if(value) rx->volume=atof(value);
+    sprintf(name,"receiver.%d.rf_gain",rx->id);
+    value=getProperty(name);
+    if(value) rx->rf_gain=atof(value);
+    sprintf(name,"receiver.%d.agc",rx->id);
+    value=getProperty(name);
+    if(value) rx->agc=atoi(value);
+    sprintf(name,"receiver.%d.agc_gain",rx->id);
+    value=getProperty(name);
+    if(value) rx->agc_gain=atof(value);
+    sprintf(name,"receiver.%d.agc_slope",rx->id);
+    value=getProperty(name);
+    if(value) rx->agc_slope=atof(value);
+    sprintf(name,"receiver.%d.agc_hang_threshold",rx->id);
+    value=getProperty(name);
+    if(value) rx->agc_hang_threshold=atof(value);
+
+    sprintf(name,"receiver.%d.dither",rx->id);
+    value=getProperty(name);
+    if(value) rx->dither=atoi(value);
+    sprintf(name,"receiver.%d.random",rx->id);
+    value=getProperty(name);
+    if(value) rx->random=atoi(value);
+    sprintf(name,"receiver.%d.preamp",rx->id);
+    value=getProperty(name);
+    if(value) rx->preamp=atoi(value);
+    sprintf(name,"receiver.%d.nb",rx->id);
+    value=getProperty(name);
+    if(value) rx->nb=atoi(value);
+    sprintf(name,"receiver.%d.nb2",rx->id);
+    value=getProperty(name);
+    if(value) rx->nb2=atoi(value);
+    sprintf(name,"receiver.%d.nr",rx->id);
+    value=getProperty(name);
+    if(value) rx->nr=atoi(value);
+    sprintf(name,"receiver.%d.nr2",rx->id);
+    value=getProperty(name);
+    if(value) rx->nr2=atoi(value);
+    sprintf(name,"receiver.%d.anf",rx->id);
+    value=getProperty(name);
+    if(value) rx->anf=atoi(value);
+    sprintf(name,"receiver.%d.snb",rx->id);
+    value=getProperty(name);
+    if(value) rx->snb=atoi(value);
+    sprintf(name,"receiver.%d.nr_agc",rx->id);
+    value=getProperty(name);
+    if(value) rx->nr_agc=atoi(value);
+    sprintf(name,"receiver.%d.nr2_gain_method",rx->id);
+    value=getProperty(name);
+    if(value) rx->nr2_gain_method=atoi(value);
+    sprintf(name,"receiver.%d.nr2_npe_method",rx->id);
+    value=getProperty(name);
+    if(value) rx->nr2_npe_method=atoi(value);
+    sprintf(name,"receiver.%d.ae",rx->id);
+    value=getProperty(name);
+    if(value) rx->nr2_ae=atoi(value);
+  
+    sprintf(name,"receiver.%d.low_latency",rx->id);
+    value=getProperty(name);
+    if(value) rx->low_latency=atoi(value);
+
+    sprintf(name,"receiver.%d.deviation",rx->id);
+    value=getProperty(name);
+    if(value) rx->deviation=atoi(value);
+  
+    sprintf(name,"receiver.%d.squelch_enable",rx->id);
+    value=getProperty(name);
+    if(value) rx->squelch_enable=atoi(value);
+    sprintf(name,"receiver.%d.squelch",rx->id);
+    value=getProperty(name);
+    if(value) rx->squelch=atof(value);
+
+    sprintf(name,"receiver.%d.zoom",rx->id);
+    value=getProperty(name);
+    if(value) rx->zoom=atoi(value);
+    sprintf(name,"receiver.%d.pan",rx->id);
+    value=getProperty(name);
+    if(value) rx->pan=atoi(value);
+#ifdef CLIENT_SERVER
+  }
+#endif
 }
 
 void reconfigure_receiver(RECEIVER *rx,int height) {
@@ -512,6 +541,8 @@ void reconfigure_receiver(RECEIVER *rx,int height) {
   // which is the full or half of the height depending on whether BOTH
   // are displayed
   //
+
+  g_mutex_lock(&rx->display_mutex);
   int myheight=(rx->display_panadapter && rx->display_waterfall) ? height/2 : height;
 
   rx->height=height;  // total height
@@ -558,13 +589,14 @@ fprintf(stderr,"reconfigure_receiver: waterfall set_size_request: width:%d heigh
   }
 
   gtk_widget_show_all(rx->panel);
+  g_mutex_unlock(&rx->display_mutex);
 }
 
 static gint update_display(gpointer data) {
   RECEIVER *rx=(RECEIVER *)data;
   int rc;
 
-//fprintf(stderr,"update_display: %d displaying=%d\n",rx->id,rx->displaying);
+//g_print("update_display: rx=%d displaying=%d\n",rx->id,rx->displaying);
 
   if(rx->displaying) {
     if(rx->pixels>0) {
@@ -580,8 +612,8 @@ static gint update_display(gpointer data) {
       }
       g_mutex_unlock(&rx->display_mutex);
       if(active_receiver==rx) {
-        double m=GetRXAMeter(rx->id,smeter)+meter_calibration;
-        meter_update(rx,SMETER,m,0.0,0.0,0.0);
+        rx->meter=GetRXAMeter(rx->id,smeter)+meter_calibration;
+        meter_update(rx,SMETER,rx->meter,0.0,0.0,0.0);
       }
       return TRUE;
     }
@@ -589,14 +621,38 @@ static gint update_display(gpointer data) {
   return FALSE;
 }
 
+void receiver_remote_update_display(RECEIVER *rx) {
+  if(rx->displaying) {
+    if(rx->pixels>0) {
+      g_mutex_lock(&rx->display_mutex);
+      if(rx->display_panadapter) {
+        rx_panadapter_update(rx);
+      }
+      if(rx->display_waterfall) {
+        waterfall_update(rx);
+      }
+      if(active_receiver==rx) {
+        meter_update(rx,SMETER,rx->meter,0.0,0.0,0.0);
+      }
+      g_mutex_unlock(&rx->display_mutex);
+    }
+  }
+}
+
 void set_displaying(RECEIVER *rx,int state) {
   rx->displaying=state;
-  if(state) {
-    if(rx->update_timer_id>=0) g_source_remove(rx->update_timer_id);
-    rx->update_timer_id=gdk_threads_add_timeout_full(G_PRIORITY_HIGH_IDLE,1000/rx->fps, update_display, rx, NULL);
-  } else {
-    rx->update_timer_id=-1;
+#ifdef CLIENT_SERVER
+  if(!radio_is_remote) {
+#endif
+    if(state) {
+      if(rx->update_timer_id>=0) g_source_remove(rx->update_timer_id);
+      rx->update_timer_id=gdk_threads_add_timeout_full(G_PRIORITY_HIGH_IDLE,1000/rx->fps, update_display, rx, NULL);
+    } else {
+      rx->update_timer_id=-1;
+    }
+#ifdef CLIENT_SERVER
   }
+#endif
 }
 
 void set_mode(RECEIVER *rx,int m) {
@@ -1271,22 +1327,29 @@ static void process_rx_buffer(RECEIVER *rx) {
 
     if(rx->local_audio) {
       if((rx!=active_receiver && rx->mute_when_not_active) || rx->mute_radio) {
-        audio_write(rx,0.0F,0.0F);
+        left_sample=0.0;
+        right_sample=0.0;
       } else {
         switch(rx->audio_channel) {
           case STEREO:
-            audio_write(rx,(float)left_sample,(float)right_sample);
             break;
           case LEFT:
-            audio_write(rx,(float)left_sample,0.0F);
+            right_sample=0.0;
             break;
           case RIGHT:
-            audio_write(rx,0.0F,(float)right_sample);
+            left_sample=0.0;
             break;
         }
       }
+      audio_write(rx,(float)left_sample,(float)right_sample);
     }
 
+#ifdef CLIENT_SERVER
+    if(clients!=NULL) {
+      remote_audio(rx,left_audio_sample,right_audio_sample);
+    }
+#endif
+
     if(rx==active_receiver) {
       switch(protocol) {
         case ORIGINAL_PROTOCOL:
@@ -1390,13 +1453,10 @@ void add_div_iq_samples(RECEIVER *rx, double i0, double q0, double i1, double q1
 }
 
 void receiver_change_zoom(RECEIVER *rx,double zoom) {
-  if(rx->pixel_samples!=NULL) {
-    g_free(rx->pixel_samples);
-  }
-  rx->pixels=rx->width*(int)zoom;
-  rx->pixel_samples=g_new(float,rx->pixels);
-  rx->hz_per_pixel=(double)rx->sample_rate/(double)rx->pixels;
+g_print("receiver_change_zoom: %d %f\n",rx->id,zoom);
   rx->zoom=(int)zoom;
+  rx->pixels=rx->width*rx->zoom;
+  rx->hz_per_pixel=(double)rx->sample_rate/(double)rx->pixels;
   if(zoom==1) {
     rx->pan=0;
   } else {
@@ -1409,8 +1469,18 @@ void receiver_change_zoom(RECEIVER *rx,double zoom) {
       rx->pan=(rx->pixels/2)-(rx->width/2);
     }
   }
-  rx->zoom=(int)zoom;
-  init_analyzer(rx);
+#ifdef CLIENT_SERVER
+  if(!radio_is_remote) {
+#endif
+    if(rx->pixel_samples!=NULL) {
+      g_free(rx->pixel_samples);
+    }
+    rx->pixel_samples=g_new(float,rx->pixels);
+    init_analyzer(rx);
+#ifdef CLIENT_SERVER
+  }
+#endif
+g_print("receiver_change_zoom: pixels=%d zoom=%d pan=%d\n",rx->pixels,rx->zoom,rx->pan);
 }
 
 void receiver_change_pan(RECEIVER *rx,double pan) {
@@ -1419,3 +1489,9 @@ void receiver_change_pan(RECEIVER *rx,double pan) {
   }
 }
 
+#ifdef CLIENT_SERVER
+void receiver_create_remote(RECEIVER *rx) {
+  // receiver structure allready setup
+  create_visual(rx);
+}
+#endif
index 2913815883cf0ed7c06d7070e2d3de50aebadcb5..41a7cb0341d7bd43e83f22c5744c95855440790c 100644 (file)
@@ -49,6 +49,8 @@ typedef struct _receiver {
   gdouble agc_gain;
   gdouble agc_slope;
   gdouble agc_hang_threshold;
+  gdouble agc_hang;
+  gdouble agc_thresh;
   gint fps;
   gint displaying;
   audio_t audio_channel;
@@ -68,6 +70,7 @@ typedef struct _receiver {
   gint display_panadapter;
   gint display_waterfall;
   gint update_timer_id;
+  gdouble meter;
 
   gdouble hz_per_pixel;
 
@@ -182,4 +185,13 @@ extern gboolean receiver_scroll_event(GtkWidget *widget, GdkEventScroll *event,
 
 extern void set_displaying(RECEIVER *rx,int state);
 
+extern void receiver_restore_state(RECEIVER *rx);
+
+extern void receiver_set_active(RECEIVER *rx);
+
+#ifdef CLIENT_SERVER
+extern void receiver_create_remote(RECEIVER *rx);
+extern void receiver_remote_update_display(RECEIVER *rx);
+#endif
+
 #endif
index ba0c1b47084f43930533b814068d65d79221f266..2a6f0879a2a0063ba132fc328a4ceab92f7c17c1 100644 (file)
--- a/rigctl.c
+++ b/rigctl.c
@@ -1,4 +1,3 @@
-
 /* TS-2000 emulation via TCP
  * Copyright (C) 2016 Steve Wilson <wevets@gmail.com>
  * This program is free software; you can redistribute it and/or
 #include "store.h"
 #include "ext.h"
 #include "rigctl_menu.h"
+#include "noise_menu.h"
 #include "new_protocol.h"
 #ifdef LOCALCW
 #include "iambic.h"              // declare keyer_update()
 #endif
 #include <math.h>
 
+#define NEW_PARSER
+
 // IP stuff below
 #include <sys/socket.h>
 #include <arpa/inet.h> //inet_addr
 
-//#define RIGCTL_DEBUG
-
 int rigctl_port_base=19090;
 int rigctl_enable=0;
 
@@ -79,7 +79,7 @@ static const int TelnetPortC = 19092;
 // max number of bytes we can get at once
 #define MAXDATASIZE 2000
 
-void parse_cmd ();
+int parse_cmd (void *data);
 int connect_cnt = 0;
 
 int rigctlGetFilterLow();
@@ -91,8 +91,6 @@ int rigctl_busy = 0;  // Used to tell rigctl_menu that launch has already occure
 int cat_control;
 
 extern int enable_tx_equalizer;
-//extern int serial_baud_rate;
-//extern int serial_parity;
 
 typedef struct {GMutex m; } GT_MUTEX;
 GT_MUTEX * mutex_a;
@@ -113,6 +111,7 @@ static GThread *rigctl_cw_thread_id = NULL;
 static int server_running;
 
 static GThread *serial_server_thread_id = NULL;
+static gboolean serial_running=FALSE;
 
 static int server_socket=-1;
 static int server_address_length;
@@ -121,13 +120,17 @@ static struct sockaddr_in server_address;
 static int rigctl_timer = 0;
 
 typedef struct _client {
-  int socket;
-  // Dl1YCF change from int to socklen_t
+  int fd;
   socklen_t address_length;
   struct sockaddr_in address;
   GThread *thread_id;
 } CLIENT;
 
+typedef struct _command {
+  CLIENT *client;
+  char *command;
+} COMMAND;
+
 int fd;  // Serial port file descriptor
 
 static CLIENT client[MAX_CLIENTS];
@@ -166,26 +169,26 @@ void close_rigctl_ports() {
   linger.l_onoff = 1;
   linger.l_linger = 0;
 
-  fprintf(stderr,"close_rigctl_ports: server_socket=%d\n",server_socket);
+  g_print("close_rigctl_ports: server_socket=%d\n",server_socket);
   server_running=0;
   for(i=0;i<MAX_CLIENTS;i++) {
-      if(client[i].socket!=-1) {
-        fprintf(stderr,"setting SO_LINGER to 0 for client_socket: %d\n",client[i].socket);
-        if(setsockopt(client[i].socket,SOL_SOCKET,SO_LINGER,(const char *)&linger,sizeof(linger))==-1) {
+      if(client[i].fd!=-1) {
+        g_print("setting SO_LINGER to 0 for client_socket: %d\n",client[i].fd);
+        if(setsockopt(client[i].fd,SOL_SOCKET,SO_LINGER,(const char *)&linger,sizeof(linger))==-1) {
           perror("setsockopt(...,SO_LINGER,...) failed for client");
         }
-        fprintf(stderr,"closing client socket: %d\n",client[i].socket);
-        close(client[i].socket);
-        client[i].socket=-1;
+        g_print("closing client socket: %d\n",client[i].fd);
+        close(client[i].fd);
+        client[i].fd=-1;
       }
   }
 
   if(server_socket>=0) {
-     fprintf(stderr,"setting SO_LINGER to 0 for server_socket: %d\n",server_socket);
+     g_print("setting SO_LINGER to 0 for server_socket: %d\n",server_socket);
     if(setsockopt(server_socket,SOL_SOCKET,SO_LINGER,(const char *)&linger,sizeof(linger))==-1) {
       perror("setsockopt(...,SO_LINGER,...) failed for server");
     }
-    fprintf(stderr,"closing server_socket: %d\n",server_socket);
+    g_print("closing server_socket: %d\n",server_socket);
     close(server_socket);
     server_socket=-1;
   }
@@ -613,24 +616,24 @@ static gpointer rigctl_cw_thread(gpointer data)
 // This looks up the frequency of the Active receiver with 
 // protection for 1 versus 2 receivers
 long long rigctl_getFrequency() {
-   if(receivers == 1) {
-      return vfo[VFO_A].frequency;
-   } else {
-      return vfo[active_receiver->id].frequency;
-   
+  if(receivers == 1) {
+    return vfo[VFO_A].frequency;
+  } else {
+    return vfo[active_receiver->id].frequency;
+  } 
 }
 // Looks up entry INDEX_NUM in the command structure and
 // returns the command string
 //
-void send_resp (int client_sock,char * msg) {
-    #ifdef  RIGCTL_DEBUG
-        fprintf(stderr,"RIGCTL: RESP=%s\n",msg);
-    #endif
-    if(client_sock == -1) { // Serial port 
-       write(fd,msg,strlen(msg));   
-    } else {  // TCP/IP port
-       write(client_sock, msg, strlen(msg));
-    }
+void send_resp (int fd,char * msg) {
+  if(rigctl_debug) g_print("RIGCTL: RESP=%s\n",msg);
+  int length=strlen(msg);
+  int written=0;
+  
+  while(written<length) {
+    written+=write(fd,&msg[written],length-written);   
+  }
+  
 }
 
 //
@@ -642,7 +645,7 @@ static gpointer rigctl_server(gpointer data) {
   int on=1;
   int i;
 
-  fprintf(stderr,"rigctl_server: starting server on port %d\n",port);
+  g_print("rigctl_server: starting server on port %d\n",port);
 
   server_socket=socket(AF_INET,SOCK_STREAM,0);
   if(server_socket<0) {
@@ -665,7 +668,7 @@ static gpointer rigctl_server(gpointer data) {
   }
 
   for(i=0;i<MAX_CLIENTS;i++) {
-    client[i].socket=-1;
+    client[i].fd=-1;
   }
   server_running=1;
 
@@ -682,27 +685,27 @@ static gpointer rigctl_server(gpointer data) {
 
     // find a spare thread
     for(i=0;i<MAX_CLIENTS;i++) {
-      if(client[i].socket==-1) {
+      if(client[i].fd==-1) {
 
-        fprintf(stderr,"Using client: %d\n",i);
+        g_print("Using client: %d\n",i);
 
-        client[i].socket=accept(server_socket,(struct sockaddr*)&client[i].address,&client[i].address_length);
-        if(client[i].socket<0) {
+        client[i].fd=accept(server_socket,(struct sockaddr*)&client[i].address,&client[i].address_length);
+        if(client[i].fd<0) {
           perror("rigctl_server: client accept failed");
           continue;
         }
 
         client[i].thread_id = g_thread_new("rigctl client", rigctl_client, (gpointer)&client[i]);
         if(client[i].thread_id==NULL) {
-          fprintf(stderr,"g_thread_new failed (n rigctl_client\n");
-          fprintf(stderr,"setting SO_LINGER to 0 for client_socket: %d\n",client[i].socket);
+          g_print("g_thread_new failed (n rigctl_client\n");
+          g_print("setting SO_LINGER to 0 for client_socket: %d\n",client[i].fd);
           struct linger linger = { 0 };
           linger.l_onoff = 1;
           linger.l_linger = 0;
-          if(setsockopt(client[i].socket,SOL_SOCKET,SO_LINGER,(const char *)&linger,sizeof(linger))==-1) {
+          if(setsockopt(client[i].fd,SOL_SOCKET,SO_LINGER,(const char *)&linger,sizeof(linger))==-1) {
             perror("setsockopt(...,SO_LINGER,...) failed for client");
           }
-          close(client[i].socket);
+          close(client[i].fd);
         }
       }
     }
@@ -714,90 +717,59 @@ static gpointer rigctl_server(gpointer data) {
 
 static gpointer rigctl_client (gpointer data) {
    
-   CLIENT *client=(CLIENT *)data;
+  CLIENT *client=(CLIENT *)data;
 
-   fprintf(stderr,"rigctl_client: starting rigctl_client: socket=%d\n",client->socket);
+  g_print("rigctl_client: starting rigctl_client: socket=%d\n",client->fd);
 
-   g_mutex_lock(&mutex_a->m);
-   cat_control++;
-//#ifdef RIGCTL_DEBUG
-   fprintf(stderr,"RIGCTL: CTLA INC cat_contro=%d\n",cat_control);
-//#endif
-   g_mutex_unlock(&mutex_a->m);
-   g_idle_add(ext_vfo_update,NULL);
+  g_mutex_lock(&mutex_a->m);
+  cat_control++;
+  if(rigctl_debug) g_print("RIGCTL: CTLA INC cat_contro=%d\n",cat_control);
+  g_mutex_unlock(&mutex_a->m);
+  g_idle_add(ext_vfo_update,NULL);
 
-   int save_flag = 0; // Used to concatenate two cmd lines together
-   int semi_number = 0;
-   int i;
-   char * work_ptr;
-   char work_buf[MAXDATASIZE];
-   int numbytes;
-   char  cmd_input[MAXDATASIZE] ;
-   char cmd_save[80];
-
-    while(server_running && (numbytes=recv(client->socket , cmd_input , MAXDATASIZE-2 , 0)) > 0 ) {
-         for(i=0;i<numbytes;i++)  { work_buf[i] = cmd_input[i]; }
-         work_buf[i+1] = '\0';
-         #ifdef RIGCTL_DEBUG
-         fprintf(stderr,"RIGCTL: RCVD=%s<-\n",work_buf);
-         #endif
-
-        // Need to handle two cases
-        // 1. Command is short, i.e. no semicolon - that will set save_flag=1 and
-        //    read another line..
-        // 2. 1 to N commands per line. Turns out N1MM sends multiple commands per line
-         
-        if(save_flag == 0) { // Count the number of semicolons if we aren't already in mode 1.
-          semi_number = 0;
-          for(i=0;i<numbytes;i++) {
-             if(cmd_input[i] == ';') { semi_number++;};
-          } 
-        }
-        if((save_flag == 0) && (semi_number == 0)) {
-           cmd_input[numbytes] = '\0';      // Turn it into a C string
-           strcpy(cmd_save,cmd_input);      // And save a copy of it till next time through
-           save_flag = 1;
-        } else if(save_flag == 1) {
-           save_flag = 0;
-           cmd_input[numbytes] = '\0';      // Turn it into a C string
-           strcat(cmd_save,cmd_input);
-           strcpy(cmd_input,cmd_save);      // Cat them together and replace cmd_input
-           numbytes = strlen(cmd_input);
-        } 
-
-        if(save_flag != 1) {
-           work_ptr = strtok(cmd_input,";");
-           while(work_ptr != NULL) {
-               // Lock so only one user goes into this at a time
-               g_mutex_lock(&mutex_b->m);
-               parse_cmd(work_ptr,strlen(work_ptr),client->socket);
-               g_mutex_unlock(&mutex_b->m);
-               work_ptr = strtok(NULL,";");
-           }
-           for(i=0;i<MAXDATASIZE;i++){
-                cmd_input[i] = '\0'; 
-                work_buf[i]  = '\0';  // Clear the input buffer
-           }
-        }
-       // Got here because socket closed 
-    }
-fprintf(stderr,"RIGCTL: Leaving rigctl_client thread");
-  if(client->socket!=-1) {
-    fprintf(stderr,"setting SO_LINGER to 0 for client_socket: %d\n",client->socket);
+  int save_flag = 0; // Used to concatenate two cmd lines together
+  int semi_number = 0;
+  int i;
+  char * work_ptr;
+  char work_buf[MAXDATASIZE];
+  int numbytes;
+  char  cmd_input[MAXDATASIZE] ;
+  char cmd_save[80];
+
+  char *command=g_new(char,MAXDATASIZE);
+  int command_index=0;
+
+   while(server_running && (numbytes=recv(client->fd , cmd_input , MAXDATASIZE-2 , 0)) > 0 ) {
+       for(i=0;i<numbytes;i++) {
+         command[command_index]=cmd_input[i];
+         command_index++;
+         if(cmd_input[i]==';') {
+           command[command_index]='\0';
+           if(rigctl_debug) g_print("RIGCTL: command=%s\n",command);
+           COMMAND *info=g_new(COMMAND,1);
+           info->client=client;
+           info->command=command;
+           g_idle_add(parse_cmd,info);
+           command=g_new(char,MAXDATASIZE);
+           command_index=0;
+         }
+       }
+     }
+g_print("RIGCTL: Leaving rigctl_client thread");
+  if(client->fd!=-1) {
+    g_print("setting SO_LINGER to 0 for client_socket: %d\n",client->fd);
     struct linger linger = { 0 };
     linger.l_onoff = 1;
     linger.l_linger = 0;
-    if(setsockopt(client->socket,SOL_SOCKET,SO_LINGER,(const char *)&linger,sizeof(linger))==-1) {
+    if(setsockopt(client->fd,SOL_SOCKET,SO_LINGER,(const char *)&linger,sizeof(linger))==-1) {
       perror("setsockopt(...,SO_LINGER,...) failed for client");
     }
-    close(client->socket);
-    client->socket=-1;
+    close(client->fd);
+    client->fd=-1;
     // Decrement CAT_CONTROL
     g_mutex_lock(&mutex_a->m);
     cat_control--;
-#ifdef RIGCTL_DEBUG
-    fprintf(stderr,"RIGCTL: CTLA DEC - cat_control=%d\n",cat_control);
-#endif
+    if(rigctl_debug) g_print("RIGCTL: CTLA DEC - cat_control=%d\n",cat_control);
     g_mutex_unlock(&mutex_a->m);
     g_idle_add(ext_vfo_update,NULL);
   }
@@ -828,2930 +800,2256 @@ int rit_on () {
       }
   }
 }
-//
-// TS-2000 parser
-//   -- Now extended with zzid_flag to indicate PSDR extended command set
-// 
-void parse_cmd ( char * cmd_input,int len,int client_sock) {
-        int work_int;     
-        int zzid_flag;
-        double forward;
-        double reverse;
-        double vswr;
-        char msg[200];
-        char buf[200];
-        BANDSTACK_ENTRY *entry;
-        // Parse the cmd_input
-        //int space = command.indexOf(' ');
-        //char cmd_char = com_head->cmd_string[0]; // Assume the command is first thing!
-        char cmd_str[3];
-        struct timespec nap;
-        static struct timespec throttle={0,0};
-
-       
-        // Put in a throttle here - we have an issue with issuing to many 
-        // GUI commands.
-
-       if ((throttle.tv_sec !=0) || (throttle.tv_nsec != 0)) {
-          clock_gettime(CLOCK_MONOTONIC, &nap);
-         // calculate amount of time we should go for a nap.
-          nap.tv_sec =throttle.tv_sec  - nap.tv_sec;
-          nap.tv_nsec=throttle.tv_nsec - nap.tv_nsec + RIGCTL_THROTTLE_NSEC;
-          while (nap.tv_nsec < 0) {
-            nap.tv_nsec += NSEC_PER_SEC;
-            nap.tv_sec--;
-          }
-          nanosleep(&nap, NULL);
-       }
-       // set new time stamp
-       clock_gettime(CLOCK_MONOTONIC, &throttle);
-
-        // On with the rest of the show..
-        cmd_str[0] = cmd_input[0];
-        cmd_str[1] = cmd_input[1];
-        cmd_str[2] = '\0';
-
-        // Added support for PSDR extended command set - they all start
-        // with ZZ so:
-        //
-        // Check to see if first part of string is ZZ - if so
-        //    strip the ZZ out and set the zzid_flag = 1;
-       #ifdef  RIGCTL_DEBUG
-        fprintf(stderr,"RIGCTL: CMD=%s\n",cmd_input);
-       #endif
-        zzid_flag = 0;  // Set to indicate we haven't seen ZZ
-        char * zzid_ptr;
-        char temp[80];
-        int cnt;
-        if(strcmp(cmd_str,"ZZ")==0) {
-           
-           #ifdef  RIGCTL_DEBUG
-           fprintf(stderr,"RIGCTL: Init=%s\n",cmd_str);
-           #endif
-
-           // Adjust the Parse input like there hadn't been a ZZ in front - but 
-           // set the ZZ flag to indicate we saw it.
-           zzid_ptr = &temp[0];
-
-           // It is 4AM and this was the only safe way for me to get a strcpy to work
-           // so - there ya go...
-           for(cnt=2; cnt<=len;cnt++) { 
-               //fprintf(stderr,"[%d]=%c:",cnt,cmd_input[cnt]);
-               *zzid_ptr++= cmd_input[cnt]; 
-           }
-           temp[len+1] = '\0';
-
-           strcpy(cmd_input,temp);
-           #ifdef  RIGCTL_DEBUG
-           fprintf(stderr,"RIGCTL: Cmd_input=%s\n",cmd_input);
-           #endif
-           // 
-           cmd_str[0] = cmd_input[0];
-           cmd_str[1] = cmd_input[1];
-           cmd_str[2] = '\0';
-           zzid_flag = 1;
-           len = strlen (temp);
-        }
-        
-        if(strcmp(cmd_str,"AC")==0)       {  
-                                            // TS-2000 - AC - STEP Command 
-                                            // PiHPSDR - ZZAC - Step Command 
-                                             if(zzid_flag ==1) { // Set or Read the Step Size (replaces ZZST)
-                                                   if(len <= 2) {
-                                                       switch(step) {
-                                                          case  1: work_int = 0; break;  
-                                                          case  10: work_int = 1; break;  
-                                                          case  25: work_int = 2; break;  
-                                                          case  50: work_int = 3; break;  
-                                                          case  100: work_int = 4; break;  
-                                                          case  250: work_int = 5; break;  
-                                                          case  500: work_int = 6; break;  
-                                                          case  1000: work_int = 7; break;  
-                                                          case  2500: work_int = 8; break;  
-                                                          case  5000: work_int = 9; break;  
-                                                          case  6250: work_int = 10; break;  
-                                                          case  9000: work_int = 11; break;  
-                                                          case  10000: work_int = 12; break;  
-                                                          case  12500: work_int = 13; break;  
-                                                          case  15000: work_int = 14; break;  
-                                                          case  20000: work_int = 15; break;  
-                                                          case  25000: work_int = 16; break;  
-                                                          case  30000: work_int = 17; break;  
-                                                          case  50000: work_int = 18; break;  
-                                                          case  100000: work_int = 19; break;  
-                                                          default: 
-                                                              work_int = 0;
-                                                              fprintf(stderr,"RIGCTL: ERROR  step out of range\n");
-                                                              send_resp(client_sock,"?;");
-                                                              break;
-                                                          }
-                                                          #ifdef  RIGCTL_DEBUG
-                                                          fprintf(stderr,"RESP: ZZAC%02d;",work_int);
-                                                          #endif
-                                                          sprintf(msg,"ZZAC%02d;",work_int);
-                                                          send_resp(client_sock,msg);
-                                              
-                                                    } else { // Legal vals between 00 and 22.
-                                                       switch(atoi(&cmd_input[2])) {
-                                                          case  0: step = 1; break;  
-                                                          case  1: step = 10; break;  
-                                                          case  2: step = 25; break;  
-                                                          case  3: step = 50; break;  
-                                                          case  4: step = 100; break;  
-                                                          case  5: step = 250; break;  
-                                                          case  6: step = 500; break;  
-                                                          case  7: step = 1000; break;  
-                                                          case  8: step = 2500; break;  
-                                                          case  9: step = 5000; break;  
-                                                          case  10: step = 6250; break;  
-                                                          case  11: step = 9000; break;  
-                                                          case  12: step = 10000; break;  
-                                                          case  13: step = 12500; break;  
-                                                          case  14: step = 15000; break;  
-                                                          case  15: step = 20000; break;  
-                                                          case  16: step = 25000; break;  
-                                                          case  17: step = 30000; break;  
-                                                          case  18: step = 50000; break;  
-                                                          case  19: step = 100000; break;  
-                                                          default: 
-                                                              fprintf(stderr,"RIGCTL: ERROR - ZZAC out of range\n");
-                                                              send_resp(client_sock,"?;");
-                                                          }
-                                                          g_idle_add(ext_vfo_update,NULL);
-                                                       }
-                                                 } else { // Sets or reads the internal antenna tuner status
-                                                      // P1 0:RX-AT Thru, 1: RX-AT IN
-                                                      // P2 0: TX-AT Thru 1: TX-AT In
-                                                      // 
-                                                        if(len <= 2) {
-                                                          send_resp(client_sock,"AC000;");
-                                                        }
-                                              }
-                                          }
-        else if((strcmp(cmd_str,"AD")==0) && (zzid_flag==1)) { 
-                                            // PiHPSDR - ZZAD - Move VFO A Down by step
-                                              //vfo_step(-1);
-                                              int lcl_step = -1;
-                                              g_idle_add(ext_vfo_step,(gpointer)(long)lcl_step);
-                                              g_idle_add(ext_vfo_update,NULL);
-                                         }
-        else if(strcmp(cmd_str,"AG")==0) {  
-                                            if(zzid_flag == 1) { 
-                                            // PiHPSDR - ZZAG - Set/read Audio Gain
-                                            // Values are 000-100 
-                                                if(len<=2) { // Send ZZAGxxx; - active_receiver->volume 0.00-1.00
-                                                     sprintf(msg,"ZZAG%03d;",(int) (roundf(active_receiver->volume *100.0)));
-                                                     send_resp(client_sock,msg);
-                                                } else { // Set Audio Gain
-                                                    work_int = atoi(&cmd_input[2]);
-                                                    active_receiver->volume = ((double) work_int)/100.0;
-                                                    g_idle_add(ext_update_af_gain,NULL);               
-                                                }
-                                             } else { 
-                                            // TS-2000 - AG - Set Audio Gain 
-                                            // AG123; Value of 0-
-                                            // AG1 = Sub receiver - what is the value set
-                                            // Response - AG<0/1>123; Where 123 is 0-260
-                                                int lcl_receiver;
-                                                if(receivers == 1) {
-                                                    lcl_receiver = 0;
-                                                } else {
-                                                    lcl_receiver = active_receiver->id;
-                                                }
-                                                if(len>4) { // Set Audio Gain
-                                                   if((atoi(&cmd_input[3]) >=0) && (atoi(&cmd_input[3])<=260)) {
-                                                      active_receiver->volume = ((double) atoi(&cmd_input[3]))/260; 
-                                                      g_idle_add(ext_update_af_gain,NULL);               
-                                                   } else {
-                                                     send_resp(client_sock,"?;");
-                                                   }
-                                                } else { // Read Audio Gain
-                                                  sprintf(msg,"AG%1d%03d;",lcl_receiver,(int) (260 * active_receiver->volume));
-                                                  send_resp(client_sock,msg);
-                                                }
-                                             }
-                                          }
-        else if((strcmp(cmd_str,"AI")==0) && (zzid_flag == 0))  {  
-                                            // TS-2000 - AI- Allow rebroadcast of set frequency after set - not supported
-                                             if(len <=2) {
-                                                //send_resp(client_sock,"AI0;");
-                                                send_resp(client_sock,"?;");
-                                             } 
-                                          }
-        else if((strcmp(cmd_str,"AL")==0) && (zzid_flag == 0))  {  
-                                            // TS-2000 - AL - Set/Reads the auto Notch level - not supported
-                                             if(len <=2) {
-                                                //send_resp(client_sock,"AL000;");
-                                                send_resp(client_sock,"?;");
-                                             } 
-                                          }
-        else if((strcmp(cmd_str,"AM")==0) && (zzid_flag == 0))  {  
-                                            // TS-2000 - AM - Sets or reads the Auto Mode - not supported
-                                             if(len <=2) {
-                                                //send_resp(client_sock,"AM0;");
-                                                send_resp(client_sock,"?;");
-                                             } 
-                                          }
-        else if((strcmp(cmd_str,"AN")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - AN - Selects the antenna connector (ANT1/2) - not supported
-                                             if(len <=2) {
-                                                //send_resp(client_sock,"AN0;");
-                                                send_resp(client_sock,"?;");
-                                             } 
-                                          }
-        else if((strcmp(cmd_str,"AP")==0) && (zzid_flag == 1)) { 
-                                            // PiHPSDR - ZZAP - Set/Read Power Amp Settings.
-                                            //                  format - P1P1P1 P2P2.P2 
-                                            //                  P1 - Band P2 - 3.1 float WITH decimal point required!
-                                               #ifdef  RIGCTL_DEBUG
-                                               fprintf(stderr,"RIGCTL: ZZAP len=%d\n",len);
-                                               #endif
-                                               if(len<=5) { // Read Command
-                                                 work_int = lookup_band(atoi(&cmd_input[2]));
-                                                 #ifdef  RIGCTL_DEBUG
-                                                 fprintf(stderr,"RIGCTL ZZAP work_int=%d\n",work_int);
-                                                 #endif
-                                                 BAND *band = band_get_band(work_int);
-                                                 sprintf(msg,"ZZAP%03d%3.1f;",atoi(&cmd_input[2]),band->pa_calibration);
-                                                 send_resp(client_sock,msg);
-                                              } else {
-                                                 /* isolate the command band from the value */ 
-                                                 char lcl_char = cmd_input[5];;
-                                                 cmd_input[5]='\0'; // Make a temp string
-                                                 work_int = atoi(&cmd_input[2]);
-                                                 cmd_input[5] = lcl_char; // Restore the orig string..
-                                                 double lcl_float = atof(&cmd_input[5]);
-                                                 #ifdef  RIGCTL_DEBUG
-                                                 fprintf(stderr,"RIGCTL ZZAP - band=%d setting=%3.1f\n",work_int, lcl_float); 
-                                                 #endif 
-                                                 work_int = lookup_band(work_int);
-
-                                                 // Sequence below lifted from pa_menu
-                                                 BAND *band = band_get_band(work_int);
-                                                 band->pa_calibration = lcl_float;
-                                                 work_int = VFO_A;
-                                                 if(split) work_int = VFO_B;
-                                                 int b = vfo[work_int].band;
-                                                 BAND *current = band_get_band(b);
-                                                 if(band == current) {
-                                                     g_idle_add( ext_calc_drive_level,(gpointer) NULL);
-                                                     //g_idle_add( ext_calc_tune_drive_level,(gpointer) NULL);
-                                                 } 
-                                              } 
-                                          }
-        else if(strcmp(cmd_str,"AR")==0)  { 
-                                            if(zzid_flag ==1) { 
-                                            // PiHPSDR - ZZAR - Set or reads the RX1 AGC Threshold Control
-                                                 if(len <=2) { // Read Response
-                                                    // X is +/- sign
-                                                    if(active_receiver->agc_gain >=0) {
-                                                       sprintf(msg,"ZZAR+%03d;",(int)active_receiver->agc_gain);
-                                                    } else {
-                                                       sprintf(msg,"ZZAR-%03d;",abs((int)active_receiver->agc_gain));
-                                                    }
-                                                    send_resp(client_sock,msg);
-                                                 } else {
-                                                    double new_gain = (double) atoi(&cmd_input[2]);
-                                                    double *p_gain=malloc(sizeof(double));
-                                                    *p_gain=new_gain;
-                                                    g_idle_add(ext_update_agc_gain,(gpointer)p_gain);
-                                                 } 
-                                            } else {     
-                                            // TS-2000 - AR - Sets or reads the ASC function on/off - not supported
-                                                 if(len <=2) {
-                                                    //send_resp(client_sock,"AR0;");
-                                                    send_resp(client_sock,"?;");
-                                                 } 
-                                            }
-                                          }
-        else if((strcmp(cmd_str,"AS")==0) && (zzid_flag == 0))  {  
-                                            // TS-2000 - AS - Sets/reads automode function parameters
-                                            // AS<P1><2xP2><11P3><P4>;
-                                            // AS<P1><2xP2><11P3><P4>;
-                                             if(len < 6) {  
-                                            /*   sprintf(msg,"AS%1d%02d%011lld%01d;",
-                                                             0, // P1
-                                                             0, // Automode 
-                                                             getFrequency(),
-                                                             rigctlGetMode());
-                                                send_resp(client_sock,msg);*/
-                                                send_resp(client_sock,"?;");
-                               
-                                             } 
-                                          }
-        else if((strcmp(cmd_str,"AT")==0) && (zzid_flag==1)) { 
-                                            // PiHPSDR - ZZAT - Move VFO A Up by step
-                                              //vfo_step(1);
-                                              int lcl_step = 1;
-                                              g_idle_add(ext_vfo_step,(gpointer)(long) lcl_step);
-                                              g_idle_add(ext_vfo_update,NULL);
-                                         }
-                                           // PiHPSDR - ZZAU - Reserved for Audio UDP stream start/stop
-        else if((strcmp(cmd_str,"BC")==0) && (zzid_flag == 0))  {  
-                                            // TS-2000 - BC - Beat Cancellor OFF - not supported
-                                             if(len <=2) {
-                                                //send_resp(client_sock,"BC0;");
-                                                send_resp(client_sock,"?;");
-                                             } 
-                                          }
-        else if(strcmp(cmd_str,"BD")==0)  {  
-                                            // PiHPSDR - ZZBD - Moves down the frequency band selector
-                                            // TS-2000 - BD - Moves down the frequency band selector
-                                            // No response 
-                                             // This reacts to both BD and ZZBD - only works for active receiver
-                                             int cur_band = vfo[active_receiver->id].band;
-                                             #ifdef  RIGCTL_DEBUG
-                                             fprintf(stderr,"RIGCTL: BD - current band=%d\n",cur_band);
-                                             #endif
-                                             if(cur_band == 0) {
-                                                #ifdef SOAPYSDR
-                                                    cur_band = band472;
-                                                #else
-                                                    cur_band = band6;
-                                                #endif
-                                             } else {
-                                                --cur_band;
-                                             } 
-                                             #ifdef  RIGCTL_DEBUG
-                                             fprintf(stderr,"RIGCTL: BD - new band=%d\n",cur_band);
-                                             #endif 
-                                             g_idle_add(ext_vfo_band_changed,(gpointer)(long)cur_band);
-                                          }
-        else if((strcmp(cmd_str,"BP")==0) && (zzid_flag == 0))  {  
-                                            // TS-2000 - BP - Reads the manual beat canceller freq - not supported 
-                                             if(len <=2) {
-                                                //send_resp(client_sock,"BP000;");
-                                                send_resp(client_sock,"?;");
-                                             } 
-                                          }
-        else if(strcmp(cmd_str,"BS")==0)  {  
-                                            if(zzid_flag == 1) {
-                                            // PiHPSDR - ZZBS - Read the RX1 Band switch
-                                                 int cur_band = vfo[active_receiver->id].band;
-                                                 #ifdef  RIGCTL_DEBUG
-                                                 fprintf(stderr,"RIGCTL: BS - band=%d\n",cur_band);
-                                                 #endif 
-                         
-                                                 switch(cur_band) {
-                                                    case 0:  work_int = 160;  break;
-                                                    case 1:  work_int = 80;  break;
-                                                    case 2:  work_int = 60;  break;
-                                                    case 3:  work_int = 40;  break;
-                                                    case 4:  work_int = 30;  break;
-                                                    case 5:  work_int = 20;  break;
-                                                    case 6:  work_int = 17;  break;
-                                                    case 7:  work_int = 15;  break;
-                                                    case 8:  work_int = 12;  break;
-                                                    case 9:  work_int = 10;  break;
-                                                    case 10:  work_int = 6;  break;
-                                                    case 11: work_int = 888; break;
-                                                    case 12: work_int = 999; break;
-                                                    case 13: work_int = 136; break;
-                                                    case 14: work_int = 472; break;
-                                                    }
-                                                 sprintf(msg,"ZZBS%03d;",work_int);
-                                                 send_resp(client_sock,msg);
-
-                                             } else {
-                                                 // Sets or reads Beat Canceller status
-                                                if(len <=2) {
-                                                   //send_resp(client_sock,"BS0;");
-                                                   send_resp(client_sock,"?;");
-                                                } 
-                                             }
-                                          }
-        else if(strcmp(cmd_str,"BU")==0)  {  
-                                            // PiHPSDR - ZZBU - Moves Up the frequency band
-                                            // TS-2000 - BU - Moves Up the frequency band
-                                             // No response 
-                                             int cur_band = vfo[active_receiver->id].band;
-                                             #ifdef  RIGCTL_DEBUG
-                                             fprintf(stderr,"RIGCTL: BU - Max Band = %d current band=%d\n",BANDS,cur_band);
-                                             #endif
-                                             if(cur_band >= 10) {
-                                                    cur_band = band160;
-                                             } else {
-                                                ++cur_band;
-                                             } 
-                                             #ifdef  RIGCTL_DEBUG
-                                             fprintf(stderr,"RIGCTL: BU - new band=%d\n",cur_band);
-                                             #endif
-                                             g_idle_add(ext_vfo_band_changed,(gpointer)(long)cur_band);
-                                          }
-        else if((strcmp(cmd_str,"BY")==0) && (zzid_flag == 0))  {
-                                            // TS-2000 - BY - Read the busy signal status
-                                             if(len <=2) {
-                                                //send_resp(client_sock,"BY00;");
-                                                send_resp(client_sock,"?;");
-                                             } 
-                                          }
-        else if((strcmp(cmd_str,"CA")==0) && (zzid_flag == 0))  {
-                                            // TS-2000 - CA - Sets/reads cw auto tune f(x) status - not supported
-                                             if(len <=2) {
-                                                //send_resp(client_sock,"CA0;");
-                                                send_resp(client_sock,"?;");
-                                             } 
-                                          }
-        else if((strcmp(cmd_str,"CB")==0) && (zzid_flag==1)) {
-                                            // PIHPSDR - ZZCB - Sets/reads CW Break In checkbox status
-                                            // P1 = 0 for disabled, 1 for enabled
-                                            if(len <= 2) {
-                                                 sprintf(msg,"ZZCB%01d;",cw_breakin);
-                                                 send_resp(client_sock,msg);
-                                            } else {
-                                                cw_breakin = atoi(&cmd_input[2]);
-                                            }
-                                          }
-        else if((strcmp(cmd_str,"CG")==0) && (zzid_flag == 0))  { 
-                                            // TS-2000 - CD - Sets/Reads the carrier gain status - not supported
-                                            // 0-100 legal values
-                                            if(len <=2) {
-                                                //send_resp(client_sock,"CG000;");
-                                                send_resp(client_sock,"?;");
-                                            } 
-                                          }
-        else if((strcmp(cmd_str,"CH")==0) && (zzid_flag == 0)) { 
-                                            // TS-2000 - CH - Sets the current frequency to call Channel -no response 
-                                          }
-        else if((strcmp(cmd_str,"CI")==0) && (zzid_flag == 0)) { 
-                                            // TS-2000 - CI - In VFO md or Mem recall md, sets freq 2 call channel - no response
-                                          }
-        else if((strcmp(cmd_str,"CL")==0) && (zzid_flag == 1)) {  
-                                            // PiHPSDR - ZZCL - CW Pitch set
-                                            // 0200 - 1200
-                                             if(len <=2) {
-                                                 sprintf(msg,"ZZCL%04d;",cw_keyer_sidetone_frequency);
-                                                 send_resp(client_sock,msg);
-                                             } else {
-                                                int local_freq = atoi(&cmd_input[2]);
-                                                if((local_freq >= 200) && (local_freq <=1200)) {
-                                                   cw_keyer_sidetone_frequency = atoi(&cmd_input[2]);
-                                                   g_idle_add(ext_vfo_update,NULL);
-                                                } else {
-                                                   fprintf(stderr,"RIGCTL: ZZCL illegal freq=%d\n",local_freq);
-                                                }
-                                             }
-                                          }
-        else if((strcmp(cmd_str,"CM")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - CM - Sets or reads the packet cluster tune f(x) on/off -not supported
-                                            // 0-100 legal values
-                                             if(len <=2) {
-                                                //send_resp(client_sock,"CM0;");
-                                                send_resp(client_sock,"?;");
-                                             } 
-                                          }
-        else if((strcmp(cmd_str,"CN")==0) && (zzid_flag == 0))  {  
-                                            // TS-2000 - CN - Sets and reads CTSS function - 01-38 legal values
-                                            // Stored locally in rigctl - not used.
-                                            if(len >2) {
-                                                ctcss_tone = atoi(&cmd_input[2]);
-                                                if((ctcss_tone > 0) && (ctcss_tone <= 39)) {
-                                                    switch(ctcss_tone) {
-                                                      case  1: transmitter->ctcss_frequency = (double) 67.0;break;
-                                                      case  2: transmitter->ctcss_frequency = (double) 71.9;break;
-                                                      case  3: transmitter->ctcss_frequency = (double) 74.4;break;
-                                                      case  4: transmitter->ctcss_frequency = (double) 77.0;break;
-                                                      case  5: transmitter->ctcss_frequency = (double) 79.7;break;
-                                                      case  6: transmitter->ctcss_frequency = (double) 82.5;break;
-                                                      case  7: transmitter->ctcss_frequency = (double) 85.4;break;
-                                                      case  8: transmitter->ctcss_frequency = (double) 88.5;break;
-                                                      case  9: transmitter->ctcss_frequency = (double) 91.5;break;
-                                                      case 10: transmitter->ctcss_frequency = (double) 94.8;break;
-                                                      case 11: transmitter->ctcss_frequency = (double) 97.4;break;
-                                                      case 12: transmitter->ctcss_frequency = (double) 100.0;break;
-                                                      case 13: transmitter->ctcss_frequency = (double) 103.5;break;
-                                                      case 14: transmitter->ctcss_frequency = (double) 107.2;break;
-                                                      case 15: transmitter->ctcss_frequency = (double) 110.9;break;
-                                                      case 16: transmitter->ctcss_frequency = (double) 114.8;break;
-                                                      case 17: transmitter->ctcss_frequency = (double) 118.8;break;
-                                                      case 18: transmitter->ctcss_frequency = (double) 123.0;break;
-                                                      case 19: transmitter->ctcss_frequency = (double) 127.3;break;
-                                                      case 20: transmitter->ctcss_frequency = (double) 131.8;break;
-                                                      case 21: transmitter->ctcss_frequency = (double) 136.5;break;
-                                                      case 22: transmitter->ctcss_frequency = (double) 141.3;break;
-                                                      case 23: transmitter->ctcss_frequency = (double) 146.2;break;
-                                                      case 24: transmitter->ctcss_frequency = (double) 151.4;break;
-                                                      case 25: transmitter->ctcss_frequency = (double) 156.7;break;
-                                                      case 26: transmitter->ctcss_frequency = (double) 162.2;break;
-                                                      case 27: transmitter->ctcss_frequency = (double) 167.9;break;
-                                                      case 28: transmitter->ctcss_frequency = (double) 173.8;break;
-                                                      case 29: transmitter->ctcss_frequency = (double) 179.9;break;
-                                                      case 30: transmitter->ctcss_frequency = (double) 186.2;break;
-                                                      case 31: transmitter->ctcss_frequency = (double) 192.8;break;
-                                                      case 32: transmitter->ctcss_frequency = (double) 203.5;break;
-                                                      case 33: transmitter->ctcss_frequency = (double) 210.7;break;
-                                                      case 34: transmitter->ctcss_frequency = (double) 218.1;break;
-                                                      case 35: transmitter->ctcss_frequency = (double) 225.7;break;
-                                                      case 36: transmitter->ctcss_frequency = (double) 233.6;break;
-                                                      case 37: transmitter->ctcss_frequency = (double) 241.8;break;
-                                                      case 38: transmitter->ctcss_frequency = (double) 250.3;break;
-                                                      case 39: transmitter->ctcss_frequency = (double) 1750.0;break;
-                                                    }
-                                                    transmitter_set_ctcss(transmitter,transmitter->ctcss,transmitter->ctcss_frequency);
-                                                  }
-                                               } else {
-                                                    ctcss_tone = -1; 
-                                                    if(transmitter->ctcss_frequency == (double) 67.0) {
-                                                       ctcss_tone = 1; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 71.9) {
-                                                       ctcss_tone = 2; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 74.4) {
-                                                       ctcss_tone = 3; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 77.0) {
-                                                       ctcss_tone = 4; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 79.7) {
-                                                       ctcss_tone = 5; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 82.5) {
-                                                       ctcss_tone = 6; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 85.4) {
-                                                       ctcss_tone = 7; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 88.5) {
-                                                       ctcss_tone = 8; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 91.5) {
-                                                       ctcss_tone = 9; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 94.8) {
-                                                       ctcss_tone = 10; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 97.4) {
-                                                       ctcss_tone = 11; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 100.0) {
-                                                       ctcss_tone = 12; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 103.5) {
-                                                       ctcss_tone = 13; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 107.2) {
-                                                       ctcss_tone = 14; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 110.9) {
-                                                       ctcss_tone = 15; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 114.8) {
-                                                       ctcss_tone = 16; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 118.8) {
-                                                       ctcss_tone = 17; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 123.0) {
-                                                       ctcss_tone = 18; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 127.3) {
-                                                       ctcss_tone = 19; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 131.8) {
-                                                       ctcss_tone = 20; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 136.5) {
-                                                       ctcss_tone = 21; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 141.3) {
-                                                       ctcss_tone = 22; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 146.2) {
-                                                       ctcss_tone = 23; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 151.4) {
-                                                       ctcss_tone = 24; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 156.7) {
-                                                       ctcss_tone = 25; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 162.2) {
-                                                       ctcss_tone = 26; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 167.9) {
-                                                       ctcss_tone = 27; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 173.8) {
-                                                       ctcss_tone = 28; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 179.9) {
-                                                       ctcss_tone = 29; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 186.2) {
-                                                       ctcss_tone = 30; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 192.8) {
-                                                       ctcss_tone = 31; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 203.5) {
-                                                       ctcss_tone = 32; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 210.7) {
-                                                       ctcss_tone = 33; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 218.1) {
-                                                       ctcss_tone = 34; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 225.7) {
-                                                       ctcss_tone = 35; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 233.6) {
-                                                       ctcss_tone = 36; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 241.8) {
-                                                       ctcss_tone = 37; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 250.3) {
-                                                       ctcss_tone = 38; 
-                                                    } else if (transmitter->ctcss_frequency == (double) 1750.0) {
-                                                       ctcss_tone = 39; 
-                                                    } else {
-                                                       send_resp(client_sock,"?;");
-                                                    }
-                                                    if(ctcss_tone != -1) {
-                                                       sprintf(msg,"CN%02d;",ctcss_tone);
-                                                       send_resp(client_sock,msg);
-                                                    }
-                                                }
-                                          }
-        // ZZCS - Keyer Speed implemented within "KS" command
-        else if((strcmp(cmd_str,"CT")==0) && (zzid_flag == 0))  {  
-                                            // TS-2000 - CS - Sets and reads CTSS function status 
-                                            // Stored locally in rigctl - not used.
-                                            if(len <=2) {
-                                                sprintf(msg,"CT%01d;",transmitter->ctcss);
-                                                send_resp(client_sock,msg);
-                                            } else {
-                                                if((atoi(&cmd_input[2]) == 0) ||(atoi(&cmd_input[2]) == 1)) {
-                                                   transmitter->ctcss = atoi(&cmd_input[2]);
-                                                   transmitter_set_ctcss(transmitter,transmitter->ctcss,transmitter->ctcss_frequency);
-                                                } else {
-                                                   send_resp(client_sock,"?;");
-                                                }
-                                            }
-                                          }
-        else if((strcmp(cmd_str,"DA")==0) && (zzid_flag == 1))  { 
-                                            // PiHPSDR - DA - Set/Clear Waterfall Automatic on Display Menu
-                                            if(len <=2) {
-                                                sprintf(msg,"ZZDA%0d;",active_receiver->waterfall_automatic);
-                                                send_resp(client_sock,msg);
-                                            } else {
-                                               if((cmd_input[2] == '0') || (cmd_input[2] == '1')) {
-                                                  active_receiver->waterfall_automatic = atoi(&cmd_input[2]);
-                                               }  else {
-                                                  send_resp(client_sock,"?;");
-                                               }
-                                            } 
-                                          }
-        else if((strcmp(cmd_str,"DC")==0) && (zzid_flag == 0))  { 
-                                            // TS-2000 - DC - Sets/Reads TX band status
-                                            if(len <=2) {
-                                                //send_resp(client_sock,"DC00;");
-                                                send_resp(client_sock,"?;");
-                                            } 
-                                          }
-        else if(strcmp(cmd_str,"DN")==0)  {  
-                                            // TS-2000 - DN - Emulate Mic down key  - Not supported
-                                            // PiHPSDR - ZZDN - Set/Read Waterfall Lo Limit 
-                                             int lcl_waterfall_low;
-                                             #ifdef  RIGCTL_DEBUG
-                                             fprintf(stderr,"RIGCTL: DN - init val=%d\n",active_receiver->waterfall_low);
-                                             #endif
-                                             if(zzid_flag == 1) { // ZZDN
-                                               if(len<=2) {
-                                                  if(active_receiver->waterfall_low <0) {
-                                                     sprintf(msg,"ZZDN-%03d;",abs(active_receiver->waterfall_low));
-                                                  } else {
-                                                     sprintf(msg,"ZZDN+%03d;",active_receiver->waterfall_low);
-                                                  }
-                                                  send_resp(client_sock,msg);
-                                               } else {
-                                                  lcl_waterfall_low = atoi(&cmd_input[3]);
-                                                  if((lcl_waterfall_low >= -200) && (lcl_waterfall_low <=200)) {
-                                                     if(cmd_input[2]=='-') {
-                                                         //waterfall_low = lcl_waterfall_low;
-                                                         active_receiver->waterfall_low = -lcl_waterfall_low;
-                                                     } else {
-                                                         active_receiver->waterfall_low =  lcl_waterfall_low;
-                                                     }
-                                                     #ifdef  RIGCTL_DEBUG
-                                                     fprintf(stderr,"RIGCTL: DN - fin val=%d\n",active_receiver->waterfall_low);
-                                                     #endif
-                                                  } else {
-                                                    fprintf(stderr,"RIGCTL: ZZDN illegal val=%d\n",lcl_waterfall_low);
-                                                    send_resp(client_sock,"?;");
-                                                  }
-                                               }
-                                             }
-                                          }
-        else if((strcmp(cmd_str,"DO")==0) && zzid_flag == 1)  {  
-                                            // PiHPSDR - ZZDO - Set/Read Waterfall Hi Limit 
-                                               if(len<=2) {
-                                                  if(active_receiver->waterfall_high <0) {
-                                                     sprintf(msg,"ZZDO-%03d;",abs(active_receiver->waterfall_high));
-                                                  } else {
-                                                     sprintf(msg,"ZZDO+%03d;",active_receiver->waterfall_high);
-                                                  }
-                                                  send_resp(client_sock,msg);
-                                               } else {
-                                                  int lcl_waterfall_high = atoi(&cmd_input[3]);
-                                                  if((lcl_waterfall_high >= -200) && (lcl_waterfall_high <=200)) {
-                                                     if(cmd_input[2]=='-') {
-                                                         active_receiver->waterfall_high = -lcl_waterfall_high;
-                                                     } else {
-                                                         active_receiver->waterfall_high =  lcl_waterfall_high;
-                                                     }
-                                                  } else {
-                                                    fprintf(stderr,"RIGCTL: ZZDO illegal val=%d\n",lcl_waterfall_high);
-                                                    send_resp(client_sock,"?;");
-                                                  }
-                                               }
-                                          }
-        else if((strcmp(cmd_str,"DQ")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - DQ - ETs/and reads the DCS function status - not supported
-                                             if(len <=2) {
-                                                //send_resp(client_sock,"DQ0;");
-                                                send_resp(client_sock,"?;");
-                                             } 
-                                          }
-        else if((strcmp(cmd_str,"DU")==0) && zzid_flag ==1)   {  
-                                            // PiHPSDR - ZZDU - Read Status Word - NOT compatible with PSDR!!
-                                             int smeter = (int) GetRXAMeter(active_receiver->id, smeter) ;
-                                             sprintf(msg,"ZZDU%1d%1d%1d%1d%1d%1d%1d%1d%1d%06d%1d%03d%1c%1d%1d%1d%1c%06lld%1d%011lld%011lld%c%03d%1d%1d%1d%1d;",
-                                                              split,  //P1
-                                                              tune,   // P2,
-                                                              mox,    // P3 
-                                                              receivers, // P4
-                                                              active_receiver->id, // P5
-                                                              active_receiver->alex_antenna, // P6
-                                                              rit_on(),  // P7 
-                                                              active_receiver->agc, // P8
-                                                              vfo[active_receiver->id].mode, //P9
-                                                              (int) step,  // P10
-                                                              vfo[active_receiver->id].band, // P11 6d
-                                                              ((int) transmitter->drive)*100, // P12
-                                                              (int)active_receiver->agc_gain >=0 ? '+' : '-', // P13 sign
-                                                              (int)active_receiver->agc_gain, // P13 3d
-                                                              (int)active_receiver->volume, // P14 3d
-                                                              vfo[active_receiver->id].rit_enabled,
-                                                              vfo[active_receiver->id].rit >=0 ? '+' : '-', // P15 sign
-                                                              vfo[active_receiver->id].rit, // P15 6d
-                                                              vfo[active_receiver->id].ctun, // P16 1d
-                                                              vfo[active_receiver->id].frequency, // P17 11d
-                                                              vfo[active_receiver->id].ctun_frequency, // P18 11d
-                                                              smeter>=0 ? '+': '-',
-                                                              abs(smeter),
-                                                              active_receiver->nr  , active_receiver->nr2  ,
-                                                              active_receiver->anf , active_receiver->snb);
-                                                  send_resp(client_sock,msg);
-                                          }
-
-        else if((strcmp(cmd_str,"EA")==0) && zzid_flag ==1)   {  
-                                            // PiHPSDR - ZZEA - sets/reads RX EQ values
-                                            if(len<=2) {
-                                                    sprintf(msg,"ZZEA%1d%1c%03d%1c%03d%1c%03d%1c%03d;",
-                                                             enable_rx_equalizer,
-                                                             rx_equalizer[0]>=0? '+' : '-',
-                                                             abs((int) rx_equalizer[0]),
-                                                             rx_equalizer[1]>=0? '+' : '-',
-                                                             abs((int) rx_equalizer[1]),
-                                                             rx_equalizer[2]>=0? '+' : '-',
-                                                             abs((int) rx_equalizer[2]),
-                                                             rx_equalizer[3]>=0? '+' : '-',
-                                                             abs((int) rx_equalizer[3]));
-                                                     send_resp(client_sock,msg);
-                                           
-                                            } else {
-                                                 //if(len !=19) {
-                                                 //    fprintf(stderr,"RIGCTL: ZZEA - incorrect number of arguments\n"); 
-                                                 //    send_resp(client_sock,"?;");
-                                                 //    return;
-                                                // }
-                                                 double work_do;
-                                                 enable_rx_equalizer = atoi(&cmd_input[2]); 
-                                                 work_do = (double) atoi(&cmd_input[3]); 
-                                                 if((work_do < -12) || (work_do > 15)) {
-                                                     fprintf(stderr,"RIGCTL: ZZEA - Preamp arg out of range=%d \n",(int) work_do); 
-                                                     send_resp(client_sock,"?;");
-                                                     return;
-                                                 }
-                                                 rx_equalizer[0]  = work_do;
-
-                                                 work_do = (double) atoi(&cmd_input[7]); 
-                                                 if((work_do < -12) || (work_do > 15)) {
-                                                     fprintf(stderr,"RIGCTL: ZZEA - Low arg out of range=%d \n",(int) work_do); 
-                                                     send_resp(client_sock,"?;");
-                                                     return;
-                                                 }
-                                                 rx_equalizer[1]  = work_do;
-
-                                                 work_do  = (double) atoi(&cmd_input[11]); 
-                                                 if((work_do < -12) || (work_do > 15)) {
-                                                     fprintf(stderr,"RIGCTL: ZZEA - Mid arg out of range=%d \n",(int) work_do); 
-                                                     send_resp(client_sock,"?;");
-                                                     return;
-                                                 }
-                                                 rx_equalizer[2]  = work_do;
-
-                                                 work_do  = (double) atoi(&cmd_input[15]); 
-                                                 if((work_do < -12) || (work_do > 15)) {
-                                                     fprintf(stderr,"RIGCTL: ZZEA - Hi arg out of range=%d \n",(int) work_do); 
-                                                     send_resp(client_sock,"?;");
-                                                     return;
-                                                 }
-                                                 rx_equalizer[3]  = work_do;
-
-                                                 SetRXAGrphEQ(active_receiver->id, rx_equalizer);
-                                            }
-                                          }
-        else if((strcmp(cmd_str,"EB")==0) && zzid_flag ==1)   {  
-                                            // PiHPSDR - ZZEB - sets/reads TX EQ values
-                                             if(len<=2) {
-                                                    sprintf(msg,"ZZEB%1d%1c%03d%1c%03d%1c%03d%1c%03d;",
-                                                             enable_tx_equalizer,
-                                                             tx_equalizer[0]>=0? '+' : '-',
-                                                             abs((int) tx_equalizer[0]),
-                                                             tx_equalizer[1]>=0? '+' : '-',
-                                                             abs((int) tx_equalizer[1]),
-                                                             tx_equalizer[2]>=0? '+' : '-',
-                                                             abs((int) tx_equalizer[2]),
-                                                             tx_equalizer[3]>=0? '+' : '-',
-                                                             abs((int) tx_equalizer[3]));
-                                                     send_resp(client_sock,msg);
-                                           
-                                             } else {
-                                                 if(len !=19) {
-                                                     fprintf(stderr,"RIGCTL: ZZEB - incorrect number of arguments\n"); 
-                                                     send_resp(client_sock,"?;");
-                                                     return;
-                                                 }
-                                                 double work_do;
-                                                 enable_tx_equalizer = atoi(&cmd_input[2]); 
-
-                                                 work_do = (double) atoi(&cmd_input[3]); 
-                                                 if((work_do < -12) || (work_do > 15)) {
-                                                     fprintf(stderr,"RIGCTL: ZZEB - Preamp arg out of range=%d \n",(int) work_do); 
-                                                     send_resp(client_sock,"?;");
-                                                     return;
-                                                 }
-                                                 tx_equalizer[0]  = work_do;
-
-                                                 work_do = (double) atoi(&cmd_input[7]); 
-                                                 if((work_do < -12) || (work_do > 15)) {
-                                                     fprintf(stderr,"RIGCTL: ZZEB - Low arg out of range=%d \n",(int) work_do); 
-                                                     send_resp(client_sock,"?;");
-                                                     return;
-                                                 }
-                                                 tx_equalizer[1]  = work_do;
-
-                                                 work_do  = (double) atoi(&cmd_input[11]); 
-                                                 if((work_do < -12) || (work_do > 15)) {
-                                                     fprintf(stderr,"RIGCTL: ZZEB - Mid arg out of range=%d \n",(int) work_do); 
-                                                     send_resp(client_sock,"?;");
-                                                     return;
-                                                 }
-                                                 tx_equalizer[2]  = work_do;
-
-                                                 work_do  = (double) atoi(&cmd_input[15]); 
-                                                 if((work_do < -12) || (work_do > 15)) {
-                                                     fprintf(stderr,"RIGCTL: ZZEB - Hi arg out of range=%d \n",(int) work_do); 
-                                                     send_resp(client_sock,"?;");
-                                                     return;
-                                                 }
-                                                 tx_equalizer[3]  = work_do;
-
-                                                 SetTXAGrphEQ(transmitter->id, tx_equalizer);
-                                             }
-                                          }
-        else if(strcmp(cmd_str,"EX")==0)  {  // Set/reads the extension menu
-                                             // This routine only can look up specific information;
-                                             // And only performs reads at this point..
-                                             // EX P1 P1 P1 P2 P2 P3 P4 ; - Read command                                      
-                                             int p5=0;
-                                             strncpy(buf,cmd_input,9); // Get the front of the response
-                                             if(len == 10) {  // Read command                                                
-                                                 // CW Sidetone frequendcy
-                                                 if(strncmp(&cmd_input[2],"031",3) == 0) {
-                                                   if(cw_keyer_sidetone_frequency <=400) {
-                                                     p5 = 0; 
-                                                   } else if (cw_keyer_sidetone_frequency <=450) {
-                                                     p5 = 1; 
-                                                   } else if (cw_keyer_sidetone_frequency <=500) {
-                                                     p5 = 2; 
-                                                   } else if (cw_keyer_sidetone_frequency <=550) {
-                                                     p5 = 3; 
-                                                   } else if (cw_keyer_sidetone_frequency <=600) {
-                                                     p5 = 4; 
-                                                   } else if (cw_keyer_sidetone_frequency <=650) {
-                                                     p5 = 5; 
-                                                   } else if (cw_keyer_sidetone_frequency <=700) {
-                                                     p5 = 6; 
-                                                   } else if (cw_keyer_sidetone_frequency <=750) {
-                                                     p5 = 7; 
-                                                   } else if (cw_keyer_sidetone_frequency <=800) {
-                                                     p5 = 8; 
-                                                   } else if (cw_keyer_sidetone_frequency <=850) {
-                                                     p5 = 9; 
-                                                   }     
-                                                   sprintf(msg,"%s%01d;",buf,p5); 
-                                                   send_resp(client_sock,msg);
-                                                  // SPLIT
-                                                 } else if(strncmp(&cmd_input[2],"06A",3) == 0) {
-                                                   sprintf(msg,"%s%01d;",buf,split); 
-                                                   send_resp(client_sock,msg);
-                                                } else  { 
-                                                   send_resp(client_sock,"?;");
-                                                }
-                                            }
-                                          }
-        else if(strcmp(cmd_str,"FA")==0) { 
-                                            // PiHPSDR - ZZFA - VFO A frequency 
-                                            // TS2000 - FA - VFO A frequency
-                                            // LEN=7 - set frequency
-                                            // Next data will be rest of freq
-                                            if(len == 13) { //We are receiving freq info
-                                               new_freqA = atoll(&cmd_input[2]);
-                                               long long *p=malloc(sizeof(long long));
-                                               *p= new_freqA;
-                                               g_idle_add(ext_set_frequency,(gpointer)p);
-                                               g_idle_add(ext_vfo_update,NULL);
-                                               return;
-                                            } else {
-                                               if(len==2) {
-                                                  if(zzid_flag == 0) {
-                                                     if(vfo[VFO_A].ctun == 1) {
-                                                        sprintf(msg,"FA%011lld;",vfo[VFO_A].frequency+vfo[VFO_A].offset);
-                                                     } else {
-                                                        sprintf(msg,"FA%011lld;",vfo[VFO_A].frequency);
-                                                     }
-                                                  } else {
-                                                     if(vfo[VFO_A].ctun == 1) {
-                                                        sprintf(msg,"ZZFA%011lld;",vfo[VFO_A].frequency+vfo[VFO_A].offset);
-                                                     } else {
-                                                        sprintf(msg,"ZZFA%011lld;",vfo[VFO_A].frequency);
-                                                     }
-                                                  }
-                                                  //fprintf(stderr,"RIGCTL: FA=%s\n",msg);
-                                                  send_resp(client_sock,msg);
-                                               }
-                                            }
-                                         }
-        else if(strcmp(cmd_str,"FB")==0) {  
-                                            // TS-2000 - FB - VFO B frequency
-                                            // PiHPSDR - ZZFB - VFO B frequency 
-                                            if(len==13) { //We are receiving freq info
-                                               new_freqB = atoll(&cmd_input[2]);
-                                               long long *p=malloc(sizeof(long long));
-                                               *p=new_freqB;
-                                               g_idle_add(ext_set_frequency,(gpointer)p);
-                                               g_idle_add(ext_vfo_update,NULL);
-                                               //new_freqB = atoll(&cmd_input[2]); 
-                                               //set_freqB(new_freqB);
-                                               //setFrequency(new_freqA);
-                                               //g_idle_add(ext_vfo_update,NULL);
-                                            } else if(len == 2) {
-                                               if(zzid_flag == 0) {
-                                                  if(vfo[VFO_B].ctun == 1) {
-                                                     sprintf(msg,"FB%011lld;",vfo[VFO_B].frequency + vfo[VFO_B].offset);
-                                                  } else {
-                                                     sprintf(msg,"FB%011lld;",vfo[VFO_B].frequency);
-                                                  }
-                                               } else {
-                                                  if(vfo[VFO_B].ctun == 1) {
-                                                     sprintf(msg,"ZZFB%011lld;",vfo[VFO_B].frequency + vfo[VFO_B].offset);
-                                                  } else {
-                                                     sprintf(msg,"ZZFB%011lld;",vfo[VFO_B].frequency);
-                                                  }
-                                               }
-                                               send_resp(client_sock,msg);
-                                            }
-                                         }
-        /* Not supported */
-        else if(strcmp(cmd_str,"FC")==0) {  // Set Sub receiver freq
-                                            // LEN=7 - set frequency
-                                            // Next data will be rest of freq
-                                            // Len<7 - frequency?
-                                            if(len>4) { //We are receiving freq info
-                                               //long long new_freqA = atoll(&cmd_input[2]);              
-                                               //setFrequency(new_freqA);
-                                            } else {
-                                               sprintf(msg,"FC%011lld;",rigctl_getFrequency());
-                                               send_resp(client_sock,"?;");
-                                            }
-                                         }
-        else if((strcmp(cmd_str,"FD")==0) & (zzid_flag==0))  {  
-                                            // TS-2000 - FD - Read the filter display dot pattern
-                                            send_resp(client_sock,"FD00000000;");
-                                          }
-        else if((strcmp(cmd_str,"FH")==0) & (zzid_flag==1))  {
-                                            // PiHPSDR - ZZFH - Set/Read Selected current DSP Filter Low High
-                                            // P1 = (0)XXXX 5 chars --9999-09999
-                                            if(len<=2) {
-                                               sprintf(msg,"ZZFH%05d;",active_receiver->filter_high);
-                                               send_resp(client_sock,msg);
-                                            } else {
-                                               // Insure that we have a variable filter selected!
-                                               if(vfo[active_receiver->id].filter > 9) {
-                                                  work_int = atoi(&cmd_input[2]); 
-                                                  if((work_int >= -9999) && (work_int <=9999)) {
-                                                      active_receiver->filter_high = work_int;
-                                                  } else {
-                                                     fprintf(stderr,"RIGCTL Warning ZZFH Value=%d out of range\n",work_int);
-                                                     send_resp(client_sock,"?;");
-                                                  }
-                                               } else {
-                                                  fprintf(stderr,"RIGCTL Warning ZZFH not applied - VAR1/2 not selected\n");
-                                                  send_resp(client_sock,"?;");
-                                               }
-                                            } 
-                                          }
-        else if((strcmp(cmd_str,"FI")==0) & (zzid_flag==1))  {
-                                            // PiHPSDR - ZZFI - Set/Read current DSP filter selected filter
-                                            if(len<=2) {
-                                               sprintf(msg,"ZZFI%02d;",vfo[active_receiver->id].filter);
-                                               send_resp(client_sock,msg);
-                                            } else {
-                                               work_int = atoi(&cmd_input[2]);
-                                               if((work_int >=0) && (work_int<=11)) {
-                                                  g_idle_add(filter_select,(gpointer)(long)work_int);
-                                               } else { 
-                                                  fprintf(stderr,"RIGCTL: ERROR ZZFI incorrect filter value=%d",work_int);
-                                                  send_resp(client_sock,"?;");
-                                               }
-                                            } 
-                                          }
-        else if((strcmp(cmd_str,"FL")==0) & (zzid_flag==1))  {
-                                            // PiHPSDR - ZZFL - Set/Read Selected current DSP Filter Low 
-                                            // P1 = (0)XXXX 5 chars --9999-09999
-                                            if(len<=2) {
-                                               sprintf(msg,"ZZFL%05d;",active_receiver->filter_low);
-                                               send_resp(client_sock,msg);
-                                            } else {
-                                               // Insure that we have a variable filter selected!
-                                               if(vfo[active_receiver->id].filter > 9) {
-                                                  work_int = atoi(&cmd_input[2]); 
-                                                  if((work_int >= -9999) && (work_int <=9999)) {
-                                                      active_receiver->filter_low = work_int;
-                                                  } else {
-                                                     fprintf(stderr,"RIGCTL Warning ZZFH Value=%d out of range\n",work_int);
-                                                     send_resp(client_sock,"?;");
-                                                  }
-                                               } else {
-                                                  fprintf(stderr,"RIGCTL Warning ZZFH not applied - VAR1/2 not selected\n");
-                                                  send_resp(client_sock,"?;");
-                                               }
-                                            } 
-                                          }
-        else if((strcmp(cmd_str,"FR")==0) && (zzid_flag == 0))  { 
-                                            // TS-2000 - FR - Set/reads the extension menu
-                                             if(len <=2) {
-                                                if(receivers == 1) {
-                                                   sprintf(msg,"FR0;");
-                                                } else {
-                                                   sprintf(msg,"FR%1d;",active_receiver->id);
-                                                }
-                                                send_resp(client_sock,msg); 
-                                             }  else if (receivers != 1)  {
-                                                 lcl_cmd = atoi(&cmd_input[2]);                
-                                                 if(active_transmitter != lcl_cmd) {
-                                                     split = 1;
-                                                 } 
-                                                 if(active_receiver->id != lcl_cmd) {
-                                                    //active_receiver->id = lcl_cmd; 
-                                                    active_receiver = receiver[lcl_cmd];
-                                                    g_idle_add(ext_vfo_update,NULL);
-                                                    // SDW
-                                                    //g_idle_add(active_receiver_changed,NULL);
-                                                 } 
-                                             }
-                                          }
-        else if((strcmp(cmd_str,"FS")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - FS - Set/reads fine funct status -
-                                             if(len <=2) {
-                                                sprintf(msg,"FS%1d;",fine);
-                                                send_resp(client_sock,msg);
-                                             } else {
-                                                int lcl_fine;
-                                                lcl_fine = atoi(&cmd_input[2]); 
-                                                if((lcl_fine >=0) && (lcl_fine <=1)) {
-                                                    fine = lcl_fine;
-                                                } else {
-                                                   send_resp(client_sock,"?;");
-                                                }
-                                             }
-                                          }
-        else if(strcmp(cmd_str,"FT")==0)  { 
-                                            // TS-2000 - FT - Set/Read Active Transmitter
-                                            // PiHPSDR - ZZFT - Set/Read Active Transmitter
-                                             if(len <=2) {
-                                                 if(zzid_flag == 0) {
-                                                   sprintf(msg,"FT%1d;",active_transmitter);
-                                                 } else {
-                                                   sprintf(msg,"ZZFT%1d;",active_transmitter);
-                                                 }
-                                                 send_resp(client_sock,msg); 
-                                             } else {
-                                                 lcl_cmd = atoi(&cmd_input[2]);                
-                                                 if((lcl_cmd ==0) ||(lcl_cmd == 1)) {
-                                                    if(lcl_cmd != active_receiver->id) {
-                                                        split = 1;
-                                                    } else {
-                                                        split = 0;
-                                                    }
-                                                    active_transmitter = lcl_cmd;
-                                                    #ifdef  RIGCTL_DEBUG
-                                                    fprintf(stderr,"RIGCTL: FT New=%d\n",active_transmitter); 
-                                                    #endif
-                                                    g_idle_add(ext_vfo_update,NULL);
-                                                 } else {
-                                                    send_resp(client_sock,"?;");
-                                                 }
-                                             } 
-                                          }  
-        else if((strcmp(cmd_str,"FW")==0) & (zzid_flag==0)) {  
-                                            // TS-2000 - FW - Sets/Read DSP receive filter width in hz 0-9999hz 
-                                            // CW - legal values  50  80  100 150 200 300 400 500 600 1000 2000
-                                            //      Pi HPSDR map  50  100 100 100 250 250 400 500 600 1000
-                                            //                    25                                   750
-                                             BAND *band=band_get_band(vfo[active_receiver->id].band);
-                                             BANDSTACK *bandstack=band->bandstack;
-                                             BANDSTACK_ENTRY *entry=&bandstack->entry[vfo[active_receiver->id].bandstack];
-                                             FILTER* band_filters=filters[vfo[active_receiver->id].mode];
-                                             FILTER* band_filter=&band_filters[vfo[active_receiver->id].filter];
-                                             int cur_rad_mode= vfo[active_receiver->id].mode;
-                                             // SDW1
-                                             #ifdef  RIGCTL_DEBUG
-                                             fprintf(stderr,"RIGCTL: FW - active recv mode =%d\n",cur_rad_mode);
-                                             #endif
-                                             if((cur_rad_mode == modeCWL) || (cur_rad_mode == modeCWU)) {
-                                               if(len <=2) {
-                                                // CW filter high and low are always the same and the filter value is 2*filter val
-                                                int filter_val = abs(band_filter->high * 2);
-                                                #ifdef  RIGCTL_DEBUG
-                                                fprintf(stderr,"RIGCTL: Filter Value=%d\n",filter_val);
-                                                #endif
-                                                switch(filter_val) {
-                                                 case 25:  
-                                                 case 50:
-                                                        work_int = 50;
-                                                        break;
-                                                 case 100:
-                                                        work_int = 100; 
-                                                        break;
-                                                 case 250:
-                                                        work_int = 300; 
-                                                        break;
-                                                 case 400:
-                                                        work_int = 400; 
-                                                        break;
-                                                 case 500:
-                                                        work_int = 500; 
-                                                        break;
-                                                 case 600:
-                                                        work_int = 600; 
-                                                        break;
-                                                 case 750:
-                                                        work_int = 1000; 
-                                                        break;
-                                                 case 800:
-                                                        work_int = 1000; 
-                                                        break;
-                                                 case 1000:
-                                                        work_int = 1000; 
-                                                        break;
-                                                 default: work_int = 500; 
-                                                        break;
-                                                } 
-                                                sprintf(msg,"FW%04d;",work_int);
-                                                #ifdef  RIGCTL_DEBUG
-                                                    fprintf(stderr,"RIGCTL: FW Filter Act=%d work_int=%d\n",band_filter->high,work_int);
-                                                #endif
-                                                send_resp(client_sock,msg);
-                                               } else {
-                                                 int f;
-                                                 // Try to set filters here!
-                                                 // CW - legal values  50  80  100 150 200 300 400 500 600 1000 2000
-                                                 //      Pi HPSDR map  50  100 100 100 250 250 400 500 600 1000
-                                                 //                    25                                   750
-                                                 work_int = atoi(&cmd_input[2]);
-                                                 switch (work_int) {
-                                                    case 50:   f= 8; break;
-                                                    case 80:   f= 7; break;
-                                                    case 100:  f= 7; break;
-                                                    case 150:  f= 7; break;
-                                                    case 200:  f= 6; break;
-                                                    case 300:  f= 6; break;
-                                                    case 400:  f= 5; break;
-                                                    case 500:  f= 4; break;
-                                                    case 600:  f= 3; break;
-                                                    case 1000: f= 0; break;
-                                                    case 2000: f= 0; break;
-                                                    default:   f=10; break;
-                                                 }
-                                               #ifdef  RIGCTL_DEBUG
-                                                 fprintf(stderr,"RIGCTL: FW CW Filter width=%d piHPSDR type=%d\n", work_int, f);
-                                               #endif
-                                               g_idle_add(ext_vfo_filter_changed,(gpointer)(long)f);
-                                              }
-                                            } else {
-                                                /* Not in CW mode */
-                                                send_resp(client_sock,"?;");
-                                            }
-                                          }  
-        else if(strcmp(cmd_str,"GT")==0)  { 
-                                            // TS-2000 - GT - Sets/Reads AGC Constant
-                                            // PiHPSDR - ZZGT - AGC Constant 0-4 are legal values
-                                           if(zzid_flag == 0) {
-                                            // Sets/Read AGC constant status 000-020
-                                            // Map 000 - Off, 001-4 - Fast, 4-9 - Medium 10-14 Slow 15-20 Long
-                                             //fprintf(stderr,"GT command seen\n");
-                                             int agc_resp = 0;
-                                             if(len <=2) {
-                                                
-                                                switch(active_receiver->agc) {
-                                                   case AGC_OFF :   agc_resp = 0; break;
-                                                   case AGC_FAST:   agc_resp = 5; break;
-                                                   case AGC_MEDIUM: agc_resp = 10; break;
-                                                   case AGC_SLOW:   agc_resp = 15; break;
-                                                   case AGC_LONG:   agc_resp = 20; break;
-                                                   default: agc_resp = 0;
-                                                }
-                                                if(zzid_flag == 0) { 
-                                                   sprintf(msg,"GT%03d;",agc_resp);
-                                                } else {
-                                                   sprintf(msg,"ZZGT%03d;",agc_resp);
-                                                }
-                                                send_resp(client_sock,msg);
-                                             } else {
-                                                //fprintf(stderr,"GT command Set\n");
-                                                agc_resp = atoi(&cmd_input[2]);
-                                                
-                                                // AGC powers of 84 is broken Hamlib... 
-                                                // Hamlib TS 2000 is broken here
-                    
-                                                if(agc_resp == 0) {
-                                                   active_receiver->agc = AGC_OFF;
-                                                } else if((agc_resp >0 && agc_resp <= 5) || (agc_resp == 84)) {
-                                                   active_receiver->agc = AGC_FAST;
-                                                  //  fprintf(stderr,"GT command FAST\n");
-                                                } else if((agc_resp >6 && agc_resp <= 10) || (agc_resp == 2*84)) {
-                                                   active_receiver->agc = AGC_MEDIUM;
-                                                  // fprintf(stderr,"GT command MED\n");
-                                                } else if((agc_resp >11 && agc_resp <= 15) || (agc_resp == 3*84)) {
-                                                   active_receiver->agc = AGC_SLOW;
-                                                   //fprintf(stderr,"GT command SLOW\n");
-                                                } else if((agc_resp >16 && agc_resp <= 20) || (agc_resp == 4*84)) {
-                                                   active_receiver->agc = AGC_LONG;
-                                                   // fprintf(stderr,"GT command LONG\n");
-                                                }
-                                                g_idle_add(ext_vfo_update,NULL);
-
-                                             }
-                                            } else {
-                                                if(len<=2) {
-                                                   sprintf(msg,"ZZGT%01d;",active_receiver->agc);
-                                                   send_resp(client_sock,msg);
-                                                } else {
-                                                   int lcl_agc = atoi(&cmd_input[2]);
-                                                   if(lcl_agc >= AGC_OFF && lcl_agc<=AGC_FAST) {
-                                                      active_receiver->agc = lcl_agc;
-                                                      g_idle_add(ext_vfo_update,NULL);
-                                                   }
-                                                }
-                                           }
-                                          }  
-        else if(strcmp(cmd_str,"ID")==0)  { 
-                                            // TS-2000 - ID - Read ID - Default to TS-2000 which is type 019.
-                                            // PiHPSDR - ZZID - Read ID - 240, i.e. hamlib number
-                                              if(zzid_flag == 0) {
-                                                   sprintf(msg,"ID019;");
-                                              } else {
-                                                   sprintf(msg,"ZZID240;");
-                                              } 
-                                              send_resp(client_sock,msg);
-                                          }
-        else if((strcmp(cmd_str,"IF")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - IF - Reads Transceiver status
-                                            // IF
-                                            //  P1: FFFFFFFFFFF -11 chars : Frequency in Hz (blanks are "0")
-                                            //  P2: OFFS        - 4 chars : Offset in powers of 10
-                                            //  P3: RITXIT      - 6 chars : RIT/XIT Frequency, Not supported = "000000"
-                                            //  P4: R           - 1 char  : RIT Status "1"= On, "0"= off
-                                            //  P5: X           - 1 char  : XIT Status "1"= On, "0"= off
-                                            //  P6: 0           - 1 char  : Channel Bank number - not used (see MC command)
-                                            //  P7: 00          - 2 chars : Channel Bank number - not used
-                                            //  P8: C           - 1 char  : Mox Status "1"= TX, "0"= RX
-                                            //  P9: M           - 1 char  : Operating mode (see MD command)
-                                            // P10: V           - 1 char  : VFO Split status - not supported
-                                            // P11: 0           - 1 char  : Scan status - not supported
-                                            // P12: A           - 1 char  : same as FT command
-                                            // P13: 0           - 1 char  : CTCSS tone - not used
-                                            // P14: 00          - 2 chars : More tone control
-                                            // P15: 0           - 1 char  : Shift status
-
-                                            // convert first half of the msg
-                                                      // IF     P1    P2  P3  P4  P5  P6
-                                            sprintf(msg,"IF%011lld%04lld%06lld%01d%01d%01d",
-                                                         //getFrequency(),
-                                                         rigctl_getFrequency(), // P1
-                                                         step,  // P2
-                                                         vfo[active_receiver->id].rit,  // P3
-                                                         rit_on(), // P4
-                                                         rit_on(), // P5
-                                                         0  // P6
-                                                         );
-
-                                            // convert second half of the msg
-                                                         //   P7  P8  P9 P10 P11 P12 P13 P14 P15;
-                                            sprintf(msg+26,"%02d%01d%01d%01d%01d%01d%01d%02d%01d;",
-                                                         0,  // P7
-                                                         mox,  // P8
-                                                         rigctlGetMode(),  // P9
-                                                         0,  // P10
-                                                         0,  // P11
-                                                         ft_read(), // P12
-                                                         transmitter->ctcss,  // P14
-                                                         convert_ctcss(),  // P13
-                                                         0); // P15
-                                            send_resp(client_sock,msg);
-                                         }
-        else if(strcmp(cmd_str,"IS")==0)  { // Sets/Reas IF shift funct status
-                                             if(len <=2) {
-                                                send_resp(client_sock,"IS00000;");
-                                             } 
-                                          }  
-        else if(((strcmp(cmd_str,"KS")==0) && (zzid_flag == 0)) ||                               // Dl1YCF added () to improve readablity
-                ((strcmp(cmd_str,"CS")==0) && (zzid_flag==1)))  {                                // Dl1YCF added () to improve readablity
-                                            // TS-2000 - KS - Set/Reads keying speed 0-060 max
-                                            // PiHPSDR - ZZCS - Sets/Reads Keying speed
-                                             if(len <=2) {
-                                                if(zzid_flag ==0) {
-                                                    sprintf(msg,"KS%03d;",cw_keyer_speed);
-                                                } else {
-                                                    sprintf(msg,"ZZCS%02d;",cw_keyer_speed);
-                                                }
-                                                send_resp(client_sock,msg);
-                                             } else {
-                                                int key_speed;
-                                                key_speed = atoi(&cmd_input[2]);
-                                                #ifdef  RIGCTL_DEBUG
-                                                fprintf(stderr,"RIGCTL: Set CW speed=%d",key_speed);
-                                                #endif
-                                                if(key_speed >= 1 && key_speed <= 60) {
-                                                   cw_keyer_speed=key_speed;
-#ifdef LOCALCW
-                                                  // tell keyer
-                                                  keyer_update();
-#endif
-                                                   g_idle_add(ext_vfo_update,NULL);
-                                                } else {
-                                                   send_resp(client_sock,"?;");
-                                                } 
-                                            }
-                                          }  
-        else if((strcmp(cmd_str,"KY")==0) && (zzid_flag == 0))
-                                   { 
-                                       if (cw_busy < 0) cat_cw_seen=1;
-                                       //
-                                       // Hamlib produces timeout errors if we are busy here for
-                                       // seconds. Therefore we just move the data into a buffer
-                                       // that is processed by a separate thread.
-                                       // Note that here we only makes a 0 --> 1 transition for cw_busy,
-                                       // and the CW thread only makes a 1 --> 0 transition, so we do not
-                                       // need a mutex and/or atomic updates here.
-                                       //
-                                       // Note: The "KY;" command is used to query if we are busy. We return:
-                                       //  - if we can accept new data (buffer space available) : "KY0;"
-                                       //  - if buffer is full: "KY1;"
-                                       //
-                                       // Note: cw_busy == -1 indicates a "purge KY" situation, where
-                                       //       all KY commands are accepted and data is discared silently
-                                       //       In this case cw_busy is left untouched here.
-                                       //
-                                        if (len <= 2) {
-                                           if (cw_busy == 1) {
-                                               send_resp(client_sock,"KY1;");
-                                           } else {
-                                               send_resp(client_sock,"KY0;");
-                                               }
-                                       } else {
-                                           // - We silently ignore buffer overruns. This does not happen  if
-                                           //   "busy" is correctly queried.
-                                           // - Note further that the space immediately following "KY" is *not*
-                                           //   part of the message.
-                                           if ((cw_busy==0)  && (len > 3)) {
-                                               // A CW text will be sent. Copy incoming data to buffer
-                                               strncpy(cw_buf, cmd_input+3, 29);
-                                               // Kenwood protocol allows for at most 24 characters, so
-                                               // this seems pure paranoia -- but who knows?
-                                               cw_buf[29]=0;
-                                               cw_busy=1;
-                                           }
-                                           // cwbusy == -1 or empty text: do nothing
-                                       }  
-                                   }
-        else if(strcmp(cmd_str,"LK")==0)  { 
-                                            // TS-2000 - LK - Set/read key lock function status
-                                            // PiHPSDR - ZZLK - Set/read key lock function status
-                                             if(len <=2) {
-                                                if(zzid_flag == 0) {
-                                                   sprintf(msg,"LK%01d%01d;",locked,locked);
-                                                } else {
-                                                   sprintf(msg,"ZZLK%01d%01d;",locked,locked);
-                                                }
-                                                send_resp(client_sock,msg);
-                                             }  else {
-                                                  if((cmd_input[2] == '1') || (cmd_input[3]=='1'))  {
-                                                      locked = 1;
-                                                  } else {
-                                                      locked = 0;
-                                                  }
-                                                  g_idle_add(ext_vfo_update,NULL);
-                                             }
-                                          }  
-        else if(strcmp(cmd_str,"LM")==0)  { 
-                                            // TS-2000 - LM - Set/Read DRU 3A keyer recording status - not supported
-                                             if(len <=2) {
-                                                send_resp(client_sock,"?;");
-                                             } 
-                                          }  
-        else if(strcmp(cmd_str,"LT")==0)  { 
-                                            // TS-2000 - LT - Set/read Alt function - not supported
-                                             if(len <=2) {
-                                                send_resp(client_sock,"?;");
-                                             } 
-                                          }  
-        else if(strcmp(cmd_str,"MC")==0) {  
-                                            // TS-2000 - MC - Recalls or reads memory channel - not supported
-                                             if(len <=2) {
-                                               send_resp(client_sock,"?;"); // Link this to band stack at some point
-                                             }
-                                         }
-        else if((strcmp(cmd_str,"MD")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - MD - Set/Read Mode
-                                            // Mode - digit selects mode
-                                            // 1 = LSB
-                                            // 2 = USB
-                                            // 3 = CWU
-                                            // 4 = FM
-                                            // 5 = AM
-                                            // 6 = DIGL
-                                            // 7 = CWL
-                                            // 9 = DIGU 
-                                            int new_mode;
-                                            if(len > 2) { // Set Mode
-                                               switch(atoi(&cmd_input[2])) {   
-                                                 case 1:  
-                                                     new_mode = modeLSB;
-                                                     break;
-                                                 case 2:  
-                                                     new_mode = modeUSB;
-                                                     break;
-                                                 case 3:  
-                                                     new_mode = modeCWU;
-                                                     break;
-                                                 case 4:  
-                                                     new_mode = modeFMN;
-                                                     break;
-                                                 case 5:  
-                                                     new_mode = modeAM;
-                                                     break;
-                                                 case 6:  
-                                                     new_mode = modeDIGL;
-                                                     break;
-                                                 case 7:  
-                                                     new_mode = modeCWL;
-                                                     break;
-                                                 case 9:  
-                                                     new_mode = modeDIGU;
-                                                     break;
-                                                 default:
-                                                     break;
-                                                     #ifdef RIGCTL_DEBUG
-                                                     fprintf(stderr,"MD command Unknown\n");
-                                                     #endif
-                                               }
-                                           g_idle_add(ext_vfo_mode_changed, (void *) (long) new_mode);
-                                            }  else {     // Read Mode
-                                               int curr_mode;
-                                               switch (vfo[active_receiver->id].mode) {
-                                                  case modeLSB: curr_mode = 1; 
-                                                          break;   
-                                                  case modeUSB: curr_mode = 2;
-                                                          break;
-                                                  case modeCWL: curr_mode = 7; // CWL
-                                                          break;
-                                                  case modeCWU: curr_mode = 3; // CWU
-                                                          break;
-                                                  case modeFMN: curr_mode = 4; // FMN
-                                                          break;
-                                                         case modeAM: curr_mode = 5; // AM
-                                                                 break;
-                                                         case modeDIGU: curr_mode = 9; // DIGU
-                                                                 break;
-                                                         case modeDIGL: curr_mode = 6; // DIGL
-                                                                 break;
-                                                         default: 
-                                                                 #ifdef RIGCTL_DEBUG
-                                                                   fprintf(stderr,
-                                                                   "RIGCTL: MD command doesn't support %d\n",
-                                                                   vfo[active_receiver->id].mode);
-                                                                 #endif
-                                                                 break;
-                                                      }
-                                                      sprintf(msg,"MD%1d;",curr_mode);
-                                                      send_resp(client_sock,msg);
-                                                   }
-                                                }
-               else if((strcmp(cmd_str,"MD")==0) && (zzid_flag == 1)) {  
-                                                   // PiHPSDR - ZZMD - Set/Read Modulation Mode
-                                                   if(len <= 2) { // Set Mode
-                                                      sprintf(msg,"ZZMD%02d;",vfo[active_receiver->id].mode);
-                                                      send_resp(client_sock,msg);
-                                                   } else {
-                                                      work_int = atoi(&cmd_input[2]);
-                                                      if((work_int >=0) && (work_int <=11)) {
-                                                         // Other stuff to switch modes goes here..
-                                                         // since new_mode has the interpreted command in 
-                                                         // in it now.
-                                                         entry= (BANDSTACK_ENTRY *) 
-                                                            bandstack_entry_get_current();
-                                                         entry->mode=work_int;
-                                                         set_mode(active_receiver,entry->mode);
-                                                         FILTER* band_filters=filters[entry->mode];
-                                                         FILTER* band_filter=&band_filters[entry->filter];
-                                                         //setFilter(band_filter->low,band_filter->high);
-                                                         set_filter(active_receiver,band_filter->low,band_filter->high);
-                                                         /* Need a way to update VFO info here..*/
-                                                         g_idle_add(ext_vfo_update,NULL);
-                                                      } else {
-                                                         fprintf(stderr,"RIGCTL: Error - ZZMD - Illegal cmd received=%d",work_int);
-                                                      }
-                                                   } 
-                                                }
-               else if((strcmp(cmd_str,"MF")==0) && (zzid_flag == 0)) {  
-                                                   // TS-2000 - MF - Set/read menu A/B - not supported
-                                                    if(len <=2) {
-                                                      send_resp(client_sock,"?;"); 
-                                                    }
-                                                }
-               else if(strcmp(cmd_str,"MG")==0) {  
-                                                   // PiHPSDR - ZZMG - Mic Gain P1=+/-P2=2digits (-10-50)
-                                                   // TS-2000 - MG - Mike Gain - 3 digits
-                                                   if(zzid_flag == 0) {
-                                                      if(len <=2) {
-                                                         work_int = (int) ((mic_gain +10.0)* 100.0/60.0);
-                                                         sprintf(msg,"MG%03d;",work_int);
-                                                         send_resp(client_sock,msg);
-                                                      } else {
-                                                         int tval = atoi(&cmd_input[2]);                
-                                                         new_vol = (double) (tval * 60/100) - 10; 
-                                                         double *p_mic_gain=malloc(sizeof(double));
-                                                         *p_mic_gain=new_vol;
-                                                         g_idle_add(ext_set_mic_gain,(void *)p_mic_gain);
-                                                      }
-                                                   } else {
-                                                      if(len <=2) {
-                                                         sprintf(msg,"ZZMG%c%02d;",mic_gain>=0 ? '+' : '-',abs((int)mic_gain));
-                                                         send_resp(client_sock,msg);
-                                                      } else {
-                                                         int new_vol = atoi(&cmd_input[2]);                
-                                                          if((new_vol >= -10) && (new_vol <= 50)) {
-                                                            double *p_mic_gain=malloc(sizeof(double));
-                                                            *p_mic_gain=new_vol;
-                                                            g_idle_add(ext_set_mic_gain,(void *)p_mic_gain);
-                                                          } else {
-                                                             send_resp(client_sock,"?;");
-                                                          }
-                                                      }
-                                                   }
-                                                }
-               else if((strcmp(cmd_str,"ML")==0) && (zzid_flag == 0)) {  
-                                                   // TS-2000 - ML - Set/read the monitor function level - not supported
-                                                    if(len <=2) {
-                                                      send_resp(client_sock,"?;"); 
-                                                    }
-                                                }
-               else if(strcmp(cmd_str,"MO")==0) {  
-                                                   // TS-2000 - MO - Set Monitor on/off - not supported
-                                                    if(len <=2) {
-                                                      send_resp(client_sock,"?;"); 
-                                                    }
-                                                }
-               else if((strcmp(cmd_str,"MR")==0) && (zzid_flag == 0)) {  
-                                                    #ifdef RIGCTL_DEBUG
-                                                    fprintf(stderr,"RIGCTL: Command seen\n"); 
-                                                     #endif
-        
-                                                    // TS-2000 - MR - Read Memory Channel data
-                                                    sprintf(msg,"MR%1d%1d%02d%011lld%1d%1d%1d%02d%02d%03d%1d%1d%09d%02d%1d%08d;",
-                                                             0, // P1 - Rx Freq - 1 Tx Freq
-                                                             0, // P2 Bankd and channel number -- see MC comment
-                                                             0, // P3 - see MC comment 
-                                                             rigctl_getFrequency(), // P4 - frequency
-                                                             rigctlGetMode(), // P5 - Mode
-                                                             locked, // P6 - Locked status
-                                                             transmitter->ctcss, // P7 - O-off, 1-tone, 2-CTCSS, 3 =DCS
-                                                             convert_ctcss(),    // P8 - Tone Number - see page 35
-                                                             convert_ctcss(),    // P9 - CTCSS tone number - see CN command
-                                                             0, // P10 - DCS code - see QC command 
-                                                             0, // P11 - Reverse status
-                                                             0, // P12 - Shift status - see OS command
-                                                             0, // P13 - Offset freq - see OS command
-                                                             0, // P14 - Step Size - see ST command
-                                                             0, // P15 - Memory Group Number (0-9)
-                                                             0);  // P16 - Memory Name - 8 char max
-                                                      send_resp(client_sock,msg);
-                                                      //send_resp(client_sock,"?;");
-                                                }
-               else if((strcmp(cmd_str,"MT")==0) && (zzid_flag == 1)) {  
-                                                   #ifdef RIGCTL_DEBUG
-                                                   fprintf(stderr,"RIGCTL: MT Command seen\n");
-                                                    #endif
-                                                   // PiHPSDR - ZZMT - Read TX Meter Mode
-                                                   // Mapped from PSDR
-                                                   // 0= ALC Peak
-                                                   // 1= ALC Average
-                                                   // 2= ALG Gain
-                                                      int * p_alc; 
-                                                     if(len<=2) { 
-                                                         switch((int)alc) {
-                                                            case TXA_ALC_PK:  work_int = 0; break;
-                                                            case TXA_ALC_AV:  work_int = 1; break;
-                                                            case TXA_ALC_GAIN: work_int = 2; break;
-                                                            default: work_int = 0;
-                                                         }
-                                                         sprintf(msg,"ZZMT%01d;",(int)work_int);
-                                                         send_resp(client_sock,msg);
-                                                     } else {
-                                                         work_int = atoi(&cmd_input[2]);
-                                                         switch (work_int)  {
-                                                             case 0: work_int = TXA_ALC_PK; break;
-                                                             case 1: work_int = TXA_ALC_AV; break;
-                                                             case 2: work_int = TXA_ALC_GAIN; break;
-                                                             default: work_int = TXA_ALC_PK;
-                                                           }
-                                                          p_alc=(int *) malloc(sizeof(double));
-                                                          *p_alc=work_int;
-                                                          g_idle_add(set_alc,(gpointer )p_alc);
-                                                     }
-                                                }
-               else if(strcmp(cmd_str,"MU")==0) {   if(zzid_flag == 1) {  
-                                                   #ifdef RIGCTL_DEBUG
-                                                   fprintf(stderr,"RIGCTL: MU Command seen\n");
-                                                    #endif
-                                                   // PiHPSDR - ZZMU - Sets or Read the MultiRX status
-                                                        if(len<=2) {
-                                                           #ifdef RIGCTL_DEBUG
-                                                           fprintf(stderr,"ZZMU =%d\n",receivers);
-                                                            #endif
-                                                           sprintf(msg,"ZZMU%1d;",receivers);
-                                                           send_resp(client_sock,msg);
-                                                        } else {
-                                                          int lcl_rcvr = atoi(&cmd_input[2]);
-                                                          #ifdef RIGCTL_DEBUG
-                                                          fprintf(stderr,"ZZMU Set=%d\n",lcl_rcvr);
-                                                           #endif
-                                                          /*if (lcl_rcvr <1 || lcl_rcvr >2) {
-                                                             fprintf(stderr,"RIGCTL: ZZMU - illegal recevier number\n");
-                                                             return;
-                                                          }*/
-                                                          g_idle_add(ext_radio_change_sample_rate,(gpointer)(long)lcl_rcvr);
-                                                          g_idle_add(ext_vfo_update,NULL);
-                                                        }
-        
-                                                    } else { 
-                                                   // TS-2000 - MU - Set/Read Memory Group Data - not supported
-                                                        if(len <=2) {
-                                                          send_resp(client_sock,"MU0000000000;"); 
-                                                        }
-                                                    }
-                                                }
-               else if((strcmp(cmd_str,"MW")==0) && (zzid_flag == 0)) {  
-                                                   #ifdef RIGCTL_DEBUG
-                                                   fprintf(stderr,"RIGCTL: MW Command seen\n");
-                                                    #endif
-                                                   // TS-2000 - MW - Store Data to Memory Channel -not supported
-                                                }
-               else if(strcmp(cmd_str,"NB")==0) {  
-                                                   // PiHPSDR - ZZNB - Set/Read Noise Blanker func status (on/off)
-                                                   // TS-2000 - NB - Set/Read Noise Blanker func status (on/off)
-                                                    if(len <=2) {
-                                                       if (zzid_flag == 0) {
-                                                         sprintf(msg,"NB%1d;",active_receiver->snb);
-                                                       } else {
-                                                         sprintf(msg,"ZZNB%1d;",active_receiver->snb);
-                                                       }
-                                                      send_resp(client_sock,msg);
-                                                    } else {
-                                                      if(cmd_input[2]=='0') { // Turn off ANF
-                                                         active_receiver->snb=0;
-                                                      } else { // Turn on ANF
-                                                         active_receiver->snb=1;
-                                                      }
-                                                      // Update filters
-                                                      SetRXASNBARun(active_receiver->id, active_receiver->snb);
-                                                      g_idle_add(ext_vfo_update,NULL);
-                                                    }
-                                                }
-               else if((strcmp(cmd_str,"NE")==0) && (zzid_flag == 1)) {  
-                                                   // PiHPSDR - ZZNE - NPS AE FIlter - DSP Menu
-                                                   //   P1 - 0=Off
-                                                   //   P1 - 1=On
-                                                      if(len<=2) {
-                                                        sprintf(msg,"ZZNE%1d;",(int) active_receiver->nr2_ae); 
-                                                        send_resp(client_sock,msg);
-                                                      } else {
-                                                        work_int = atoi(&cmd_input[2]);
-                                                        if(work_int >=0 && work_int <=1) {
-                                                          active_receiver->nr2_ae = work_int; 
-                                                          SetRXAEMNRaeRun(active_receiver->id, active_receiver->nr2_ae);
-                                                        } else {
-                                                          fprintf(stderr,"RIGCTL: ZZNE - ERROR illegal value=%d s/b 0 to 2\n",work_int);
-                                                          send_resp(client_sock,"?;");
-                                                        }
-                                                      }
-                                                  }
-               else if((strcmp(cmd_str,"NG")==0) && (zzid_flag == 1)) {  
-                                                   // PiHPSDR - ZZNG - NR Pre AGC/Post AGC- DSP Menu
-                                                      if(len<=2) {
-                                                        sprintf(msg,"ZZNG%1d;",(int) active_receiver->nr_agc); 
-                                                        send_resp(client_sock,msg);
-                                                      } else {
-                                                        work_int = atoi(&cmd_input[2]);
-                                                        if(work_int >=0 && work_int <=1) {
-                                                            active_receiver->nr_agc = atoi(&cmd_input[2]);
-                                                            SetRXAEMNRPosition(active_receiver->id, active_receiver->nr_agc);
-                                                        } else { 
-                                                          fprintf(stderr,"RIGCTL: ZZNG - illegal value=%d s/b 0 or 1\n",work_int);
-                                                          send_resp(client_sock,"?;");
-                                                        }
-                                                      }
-                                                  }
-
-               else if((strcmp(cmd_str,"NM")==0) && (zzid_flag == 1)) {  
-                                                   // PiHPSDR - ZZNM - NR2 Gain Method - DSP Menu
-                                                   //   P1 - 0=Linear
-                                                   //   P1 - 1=Log
-                                                                       //   P1 - 2=Gamma
-                                                      if(len<=2) {
-                                                        sprintf(msg,"ZZNM%1d;",(int) active_receiver->nr2_gain_method); 
-                                                        send_resp(client_sock,msg);
-                                                      } else {
-                                                        work_int = atoi(&cmd_input[2]);
-                                                        if(work_int >=0 && work_int <=2) {
-                                                          active_receiver->nr2_gain_method = work_int; 
-                                                          SetRXAEMNRgainMethod(active_receiver->id, active_receiver->nr2_gain_method);
-                                                        } else {
-                                                          fprintf(stderr,"RIGCTL: ZZNM - illegal value=%d s/b 0 to 2\n",work_int);
-                                                          send_resp(client_sock,"?;");
-                                                        }
-                                                      }
-                                                }
-               else if(strcmp(cmd_str,"AB")==0) { 
-                                                   #ifdef RIGCTL_DEBUG
-                                                     fprintf(stderr,"RIGCTL: Command seen\n"); 
-                                                    #endif
-                                                 }
-               else if((strcmp(cmd_str,"NP")==0) && (zzid_flag == 1)) {  
-                                                   // PiHPSDR - ZZNP - NPS Method - DSP Menu
-                                                   //   P1 - 0=OSMS
-                                                   //   P1 - 1=MMSE
-                                                      if(len<=2) {
-                                                        sprintf(msg,"ZZNP%1d;",(int) active_receiver->nr2_npe_method); 
-                                                        send_resp(client_sock,msg);
-                                                      } else {
-                                                        work_int = atoi(&cmd_input[2]);
-                                                        if(work_int >=0 && work_int <=1) {
-                                                          active_receiver->nr2_npe_method = work_int; 
-                                                          SetRXAEMNRnpeMethod(active_receiver->id, active_receiver->nr2_npe_method);
-                                                        } else {
-                                                          fprintf(stderr, "RIGCTL: ZZNP - ERROR illegal value=%d s/b 0 to 2\n",work_int);
-                                                          send_resp(client_sock,"?;");
-                                                        }
-                                                      }
-                                                }
-               else if(strcmp(cmd_str,"NL")==0) {if(zzid_flag == 0) { 
-                                                   // TS-2000 - NL - Set/Read Noise Reduction  Level - Not Supported
-                                                    if(len <=2) {
-                                                      send_resp(client_sock,"?;"); 
-                                                    }
-                                                 } else {
-                                                   // PiHPSDR - ZZNL - AGC Hang Threshold - DSP Menu slider
-                                                    //         P1P1P1 - 0 - 100
-                                                    if(len <=2) {
-                                                       sprintf(msg,"ZZNL%03d;",(int) active_receiver->agc_hang_threshold);
-                                                       send_resp(client_sock,msg);
-                                                    } else {
-                                                       work_int = atoi(&cmd_input[2]);
-                                                       if((work_int >= 0) && (work_int<=100)) {
-                                                          active_receiver->agc_hang_threshold = work_int;
-                                                          if(active_receiver->agc==AGC_LONG || active_receiver->agc==AGC_SLOW) {
-                                                              SetRXAAGCHangThreshold(active_receiver->id, (int)active_receiver->agc_hang_threshold);
-                                                          }
-                                                       }
-                                                    }
-                                                 }
-                                                }
-               else if(strcmp(cmd_str,"NR")==0) {  
-                                                   // TS-2000 - NR - Set/Read Noise Reduction function status
-                                                   // PiHPSDR - ZZNR - Set/Read Noise Reduction function status
-                                                   if(len <=2) {
-                                                      if(zzid_flag == 0) {
-                                                         if (active_receiver->nr==1 && active_receiver->nr2==0) { 
-                                                            send_resp(client_sock,"NR1;"); 
-                                                         } else if (active_receiver->nr==1 && active_receiver->nr2==1) { 
-                                                           send_resp(client_sock,"NR2;"); 
-                                                         } else {
-                                                           send_resp(client_sock,"NR0;"); 
-                                                         }
-                                                      } else {
-                                                         if (active_receiver->nr==1 && active_receiver->nr2==0) { 
-                                                            send_resp(client_sock,"ZZNR1;"); 
-                                                         } else if (active_receiver->nr==1 && active_receiver->nr2==1) { 
-                                                           send_resp(client_sock,"ZZNR2;"); 
-                                                         } else {
-                                                           send_resp(client_sock,"ZZNR0;"); 
-                                                         }
-                                                      }
-                                                    } else {
-                                                      if((atoi(&cmd_input[2]) >=0) && (atoi(&cmd_input[2]) <=2)) {
-                                                         if(cmd_input[2] == '0') {
-                                                            active_receiver->nr = 0;
-                                                            active_receiver->nr2 = 0;
-                                                         } else if(cmd_input[2] == '1') {
-                                                            active_receiver->nr = 1;
-                                                         } else if(cmd_input[2] == '2') {
-                                                           active_receiver->nr2 = 1;
-                                                         }
-                                                         SetRXAANRRun(active_receiver->id, active_receiver->nr);
-                                                         SetRXAEMNRRun(active_receiver->id, active_receiver->nr2);
-                                                         g_idle_add(ext_vfo_update,NULL);
-                                                      } else {
-                                                        send_resp(client_sock,"?;"); 
-                                                      }
-                                                   } 
-                                         }
-        else if(strcmp(cmd_str,"NT")==0) {  
-                                            // TS-2000 - NT - Set/Read autonotch function - 
-                                            // PiHPSDR - ZZNT - Sets/reads ANF status
-                                             if(len <=2) {
-                                               if(zzid_flag == 0) {
-                                                  sprintf(msg,"NT%1d;",active_receiver->anf);
-                                               } else {
-                                                  sprintf(msg,"ZZNT%1d;",active_receiver->anf);
-                                               }
-                                               send_resp(client_sock,msg);
-                                             } else {
-                                               if((atoi(&cmd_input[2]) >=0) && (atoi(&cmd_input[2]) <=1)) {
-                                                  if(cmd_input[2] == '0') { // Clear ANF
-                                                    active_receiver->anf = 0;
-                                                  } else { // Set ANF
-                                                    active_receiver->anf = 1;
-                                                  }
-                                               } else {
-                                                  send_resp(client_sock,"?;"); 
-                                               }
-                                             }
-                                             SetRXAANFRun(active_receiver->id, active_receiver->anf);
-                                             g_idle_add(ext_vfo_update,NULL);
-                                         }
-        else if((strcmp(cmd_str,"OA")==0) && (zzid_flag ==1)) {  
-                                            // PiHPSDR - ZZOA - Set/Read RX Antenna by band
-                                            //           P1P1P1 - Band
-                                            //           P2 - 1,2,3,EXT1,EXT2, XVTR
-                                             int int_band;
-                                             int b;
-                                             if(len<=5) {
-                                                int_band = atoi(&cmd_input[2]);
-                                               #ifdef RIGCTL_DEBUG
-                                                fprintf(stderr,"RIGCTL OA band =%d\n",int_band);
-                                                #endif
-                                                //b = lookup_band(int_band);
-                                                BAND *band=band_get_band(int_band);
-                                                work_int = band->alexRxAntenna;
-                                                sprintf(msg,"ZZOA%03d%1d;",int_band,work_int);
-                                                send_resp(client_sock,msg);
-                                             } else {
-                                                char lcl_char = cmd_input[5];
-                                                cmd_input[5] = '\0';
-                                                b = atoi(&cmd_input[2]);
-                                                //b = lookup_band(int_band);
-                                                cmd_input[5] = lcl_char;
-                                                work_int = atoi(&cmd_input[5]);
-                                                if(work_int >=0 && work_int <=5) {
-                                                  #ifdef RIGCTL_DEBUG
-                                                   fprintf(stderr,"RIGCTL ZZOA Band=%d Val=%d\n",b,work_int);
-                                                   #endif
-                                                   BAND *band=band_get_band(b);
-                                                   band->alexRxAntenna = work_int;
-                                                } else {
-                                                   fprintf(stderr,"RIGCTL ZZOA illegal val Band=%d Val=%d\n",b,work_int);
-                                                }
-                                             }
-                                         }
-        else if((strcmp(cmd_str,"OB")==0) && (zzid_flag ==1)) {  
-                                            // PiHPSDR - ZZOB - Set/Read TX Antenna by band
-                                            //           P1P1P1 - Band
-                                            //           P2 - 1,2,3
-                                             int int_band;
-                                             int b ;
-                                             if(len<=5) {
-                                                int_band = atoi(&cmd_input[2]);
-                                                //b = lookup_band(int_band);
-                                                b = int_band;
-                                                BAND *band=band_get_band(b);
-                                                work_int = band->alexTxAntenna;
-                                                sprintf(msg,"ZZOB%03d%1d;",int_band,work_int);
-                                                send_resp(client_sock,msg);
-
-                                             } else {
-                                                char lcl_char = cmd_input[5];
-                                                cmd_input[5] = '\0';
-                                                int_band = atoi(&cmd_input[2]);
-                                                //b = lookup_band(int_band);
-                                                b = int_band;
-                                                cmd_input[5] = lcl_char;
-                                                work_int = atoi(&cmd_input[5]);
-                                                if(work_int >=0 && work_int <=2) {
-                                                  #ifdef RIGCTL_DEBUG
-                                                   fprintf(stderr,"RIGCTL ZZOB Band=%d Val=%d\n",int_band,work_int);
-                                                   #endif
-                                                   BAND *band=band_get_band(b);
-                                                   band->alexTxAntenna = work_int;
-                                                } else {
-                                                   fprintf(stderr,"RIGCTL ZZOB illegal val Band=%d Val=%d\n",int_band,work_int);
-                                                }
-                                             }
-                                         }
-        else if((strcmp(cmd_str,"OF")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - OF - Set/Read Offset freq (9 digits - hz) -not supported
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"OF000000000;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        /* Not Supported */
-        else if((strcmp(cmd_str,"OI")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - OI - Read Memory Channel Data - not supported
-                                             /*if(len <=2) {
-                                               sprintf(msg,"OI%011lld%04d%06d%1d%1d%1d%02d%1d%1d%1d%1d%1d%1d%02d%1d;",
-                                                  rigctl_getFrequency(),
-                                                  0, // P2 - Freq Step size
-                                                  0, // P3 - Rit/Xit Freq 
-                                                  0, // P4 - RIT off/Rit On
-                                                  0, // P5 - XIT off/on
-                                                  0, // P6 - Channel
-                                                  0, // P7 - Bank
-                                                  0, // P8 - 0RX, 1TX
-                                                  rigctlGetMode(),  // P10 - MD
-                                                  0, // P11 - SC command
-                                                  0, // P12 Split op - SP command
-                                                  0, // P13 Off, 1, 2, 
-                                                  0,// P14 Tone freq - See TN command
-                                                  0,0);
-                                              */
-                                               send_resp(client_sock,"?;");
-                                         }
-        else if(strcmp(cmd_str,"OS")==0) {  
-                                            // TS-2000 - OS - Set/Read Offset freq (9 digits - hz) -not supported
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"OS0;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if(strcmp(cmd_str,"PA")==0) { 
-                                            // TS-2000 - PA - Set/Read Preamp function status
-                                            // PiHPSDR - ZZPA - Set/Read Preamp function status
-                                           // Note that currently, preamp switching is only done for CHARLY25
-                                             if(len <=2) {
-                                                if(zzid_flag == 0) {
-                                                   sprintf(msg,"PA%1d%1d;",active_receiver->preamp,active_receiver->preamp);
-                                                } else {
-                                                   sprintf(msg,"ZZPA%1d;",active_receiver->preamp);
-                                                }
-                                               send_resp(client_sock,msg);
-                                             } else {
-                                                work_int = atoi(&cmd_input[2]);
-                                                if((work_int >= 0) && (work_int <= 1)) {
-                                                    active_receiver->preamp = work_int;  
-                                                } else {
-                                                    send_resp(client_sock,"?;");
-                                                }
-                                             }
-                                         }
-        else if(strcmp(cmd_str,"PB")==0) { 
-                                            // TS-2000 - PB - DRU-3A Playback status - not supported
-                                             if(len <=2) {
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if(strcmp(cmd_str,"PC")==0) {  
-                                            // TS-2000 - PC - Set/Read Drive Power output
-                                            // PiHPSDR - ZZPC - Set/Read Drive Power output
-                                            if(len<=2) {
-                                                if(zzid_flag == 0) {
-                                                  sprintf(msg,"PC%03d;",(int) transmitter->drive);
-                                                } else {
-                                                  sprintf(msg,"ZZPC%03d;",(int) transmitter->drive);
-                                                }
-                                              send_resp(client_sock,msg); 
-                                            } else {
-                                              int lcl_pc = atoi(&cmd_input[2]); 
-                                             #ifdef RIGCTL_DEBUG
-                                              fprintf(stderr,"RIGCTL: PC received=%d\n",lcl_pc);
-                                              #endif
-                                              if((lcl_pc >=0) && (lcl_pc<=100)) {
-                                                  // Power Control - 3 digit number- 0 to 100
-                                                  //Scales to 0.00-1.00
-                                                
-                                                  double drive_val = 
-                                                      (double)(atoi(&cmd_input[2])); 
-                                                  // setDrive(drive_val);
-                                                  double *p_drive=malloc(sizeof(double));
-                                                  *p_drive=drive_val;
-                                                  g_idle_add(update_drive,(gpointer)p_drive);
-                                                  //set_drive(drive_val);
-                                              } else {
-                                                  fprintf(stderr,"RIGCTL: PC received=%d - Illegal value\n",lcl_pc);
-                                                  send_resp(client_sock,"?;");
-                                              }
-                                            }
-                                         }
-        else if((strcmp(cmd_str,"PI")==0) && (zzid_flag == 0)) 
-                                         {  
-                                            // TS-2000 - PI - Store the programmable memory channel - not supported
-                                         }
-        else if(strcmp(cmd_str,"PK")==0) {  
-                                            // TS-2000 - PK - Reads the packet cluster data - not supported
-                                            //  send_resp(client_sock,"PK000000000000000000000000000000000000000000000000;"); 
-                                             send_resp(client_sock,"?;"); 
-                                            
-                                         }
-        else if((strcmp(cmd_str,"PL")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - PL - Set/Read Speech processor level 
-                                            // PL 000 000 ;
-                                            // P1 000 - min-100 max
-                                            // P2 000 - min - 100 max
-                                             double lcl_comp_level;
-                                             if(len <=2) {
-                                             //  send_resp(client_sock,"PL000000;"); 
-                                                lcl_comp_level = 100 *(transmitter->compressor_level)/20;
-                                                sprintf(msg,"PL%03d000;",(int)lcl_comp_level);
-                                                send_resp(client_sock,msg); 
-                                             } else {
-                                                // Isolate 1st command
-                                                cmd_input[5] = '\0';
-                                                lcl_comp_level = 20.0 *(((double)atoi(&cmd_input[2]))/100.0);
-                                               #ifdef RIGCTL_DEBUG
-                                                fprintf(stderr,"RIGCTL - PR new level=%f4.1",lcl_comp_level);
-                                                #endif
-                                                transmitter_set_compressor_level(transmitter,lcl_comp_level);
-                                                g_idle_add(ext_vfo_update,NULL);
-                                                //transmitter->compressor_level = lcl_comp_level;
-                                             }
-                                         }
-        else if((strcmp(cmd_str,"PM")==0) && ( zzid_flag == 0)) {  
-                                            // TS-2000 - PM - Recalls the Programmable memory - not supported
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"PM0;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if((strcmp(cmd_str,"PR")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - PR - Sets/reads the speech processor function on/off 
-                                            // 0 - off, 1=on
-                                             if(len <=2) {
-                                               sprintf(msg,"PR%01d;",transmitter->compressor);
-                                               send_resp(client_sock,msg);
-                                             } else {
-                                               transmitter_set_compressor(transmitter,atoi(&cmd_input[2]));
-                                               g_idle_add(ext_vfo_update,NULL);
-                                               //transmitter->compressor = atoi(&cmd_input[2]);
-                                             }
-                                         }
-        else if(strcmp(cmd_str,"PS")==0) {  
-                                            // PiHPSDR - ZZPS - Sets/reads Power on/off state- always on
-                                            // TS-2000 - PS - Sets/reads Power on/off state
-                                            // 0 - off, 1=on
-                                             if(len <=2) {
-                                               send_resp(client_sock,"PS1;"); // Lets pretend we're powered up ;-) 
-                                             }
-                                         }
-        else if(strcmp(cmd_str,"PZ")==0) {   if(zzid_flag == 1) {  
-                                            // PiHPSDR - ZZPZ - Sets/Reads  Radio Sample Rate
-                                            // Valid values are 048000, 096000, 192000, 384000
-                                               #ifdef RIGCTL_DEBUG
-                                                 fprintf(stderr,"ZZPZ command\n");
-                                                #endif 
-                                                 if(len<=2) {
-                                                 sprintf(msg,"ZZPZ%06d;",active_receiver->sample_rate);
-                                                 send_resp(client_sock,msg);
-                                                 } else {
-                                                   long lcl_rate = atoi(&cmd_input[2]);
-                                                  #ifdef RIGCTL_DEBUG
-                                                   fprintf(stderr,"ZZPZ Set=%ld\n",lcl_rate);
-                                                   #endif
-                                                   if (lcl_rate !=48000L && lcl_rate !=96000L  &&
-                                                       lcl_rate !=192000L && lcl_rate != 384000L) {
-                                                      fprintf(stderr,"RIGCTL: ZZPZ - illegal frequency=%ld\n",lcl_rate);
-                                                      send_resp(client_sock,"?;");
-                                                      return;
-                                                   }
-                                                   
-                                                   g_idle_add(ext_radio_change_sample_rate,(gpointer)(long)lcl_rate);
-                                                   g_idle_add(ext_vfo_update,NULL);
-                                                 }
-                                              } 
-                                         }
-        else if(strcmp(cmd_str,"QC")==0) {  
-                                            // TS-2000 - QC - Sets/reads DCS code - not supported
-                                            // Codes numbered from 000 to 103.
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"QC000;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if(strcmp(cmd_str,"QI")==0) {  
-                                            // TS-2000 - QI - Store the settings in quick memory - not supported
-                                         }
-        else if(strcmp(cmd_str,"QR")==0) {  
-                                            // TS-2000 - QR - Send the Quick memory channel data - not supported
-                                            // P1 - Quick mem off, 1 quick mem on
-                                            // P2 - Quick mem channel number
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"QR00;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-
-        else if((strcmp(cmd_str,"RA")==0) && (zzid_flag == 0)) {  
-#ifdef NOTSUPPORTED
-                                            // TS-2000 - RA - Sets/reads Attenuator function status
-                                            // 00-off, 1-99 -on - Main and sub receivers reported
-                                            int lcl_attenuation;
-                                            float calc_atten;
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"RA0000;"); 
-                                               calc_atten = round((float)adc_attenuation[active_receiver->adc]*99.0/30.0);
-                                               if(calc_atten > 99.0) {
-                                                  calc_atten = 99.0;
-                                               } 
-                                               sprintf(msg,"RA%02d%02d;",(int)calc_atten,(int)calc_atten); 
-                                               send_resp(client_sock,msg);
-                                             } else {
-                                                lcl_attenuation = atoi(&cmd_input[2]); 
-                                                if((lcl_attenuation >=0) && (lcl_attenuation <= 99)) {
-                                                  lcl_attenuation = (int)((float)lcl_attenuation * 30.0/99.0);
-                                                 #ifdef RIGCTL_DEBUG
-                                                  fprintf(stderr,"RIGCTL: lcl_att=%d\n",lcl_attenuation);
-                                                  #endif
-                                                  //set_attenuation(lcl_attenuation);
-                                                  set_attenuation_value((double) lcl_attenuation);
-                                                  g_idle_add(ext_vfo_update,NULL);
-                                                } else {
-#endif
-                                                  send_resp(client_sock,"?;"); 
-                                                //}
-                                             //}
-                                         }
-        else if(strcmp(cmd_str,"RC")==0) {  
-                                            // TS-2000 - RC - Clears the RIT offset freq
-                                            // PiHPSDR - ZZRC - Clears the RIT offset freq
-                                            vfo[active_receiver->id].rit = 0;
-                                            g_idle_add(ext_vfo_update,NULL);
-                                         }
-        else if(strcmp(cmd_str,"RD")==0) {  // 
-                                            // TS-2000 - RD - Move the RIT offset freq down - P1=rit_increment! 
-                                            //                P1=No Argument - decrement frequency
-                                            //                P1=NonZero - load rit offset
-                                            //                FS controls fine variable 1 or 0. rit increment 1 hz or 10hz
-                                            // PiHPSDR - ZZRD - Move the RIT offset freq down by rit_increment
-                                             int lcl_rit;
-                                             int lcl_rit_increment = fine ? 1 : 10;
-                                             if(len <=2) {
-                                               vfo[active_receiver->id].rit = vfo[active_receiver->id].rit-lcl_rit_increment;
-                                             } else {
-                                                if(len > 3) {
-                                                   lcl_rit = atoi(&cmd_input[2]);   
-                                                   if((lcl_rit >=0) &&(lcl_rit <=99999)) {
-                                                       vfo[active_receiver->id].rit = -lcl_rit;
-                                                   } else {
-                                                       send_resp(client_sock,"?;");
-                                                   }
-                                                } 
-                                             }
-                                             g_idle_add(ext_vfo_update,NULL);
-                                         }
-        else if((strcmp(cmd_str,"RF")==0) && (zzid_flag == 1)) {  
-                                            // PiHPSDR - ZZRR - Read Forward Power
-                                            forward = transmitter->fwd;
-                                            sprintf(msg,"RF%09.7f;",forward);
-                                            send_resp(client_sock,msg);
-                                         }
-        else if(strcmp(cmd_str,"RG")==0) {  
-                                            // TS-2000 - RG - RF Gain Control
-                                            // PiHPSDR - ZZRG - AGC Gain Control -20 to 120 legal range
-                                            // TS 2000 settings 0-255 value scaled to -20 to 120 range
-                                            if(zzid_flag == 0) {
-                                              if(len>4) { // Set Audio Gain
-                                                 int base_value = atoi(&cmd_input[2]);
-                                                 double new_gain = roundf(((((double) base_value+1)/256.0) * 141.0))- 21.0; 
-                                                 //set_agc_gain(new_gain);               
-                                                 double *p_gain=malloc(sizeof(double));
-                                                 *p_gain=new_gain;
-                                                 g_idle_add(ext_update_agc_gain,(gpointer)p_gain);
-                                              } else { // Read Audio Gain
-                                                 double lcl_gain = (active_receiver->agc_gain+21.0)/141.0;
-                                                 sprintf(msg,"RG%03d;",(int)((256.0 * lcl_gain) -1));
-                                                 send_resp(client_sock,msg);
-                                              }
-                                            } else {
-                                              // Pi HPSDR  version
-                                              if(len <= 2) {
-                                                 if(active_receiver->agc_gain<0) {
-                                                    sprintf(msg,"ZZRG-%03d;",(int) abs((int)active_receiver->agc_gain));
-                                                 } else {
-                                                     sprintf(msg,"ZZRG+%03d;",(int)active_receiver->agc_gain);
-                                                 }
-                                                 send_resp(client_sock,msg);
-                                                 
-                                              } else {
-                                                 work_int = atoi(&cmd_input[3]);
-                                                 if(cmd_input[2] == '-') {  // Negative number found
-                                                    work_int = -work_int;
-                                                 }
-                                                 if((work_int >= -20) && (work_int <=120)) {
-                                                    double *p_gain=malloc(sizeof(double));
-                                                    *p_gain=(double) work_int;
-                                                    g_idle_add(ext_update_agc_gain,(gpointer)p_gain);
-                                                 } else {
-                                                    fprintf(stderr,"RIGCTL: ZZRG ERROR - Illegal AGC Value=%d\n", work_int);
-                                                    send_resp(client_sock,"?;");
-                                                 }
-                                              }
-                                            }
-                                            g_idle_add(ext_vfo_update,NULL);
-                                         }
-        else if((strcmp(cmd_str,"RL")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - RL - Set/read Noise reduction level - not supported
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"RL00;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if((strcmp(cmd_str,"RM")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - RM - Set/read Meter function - not supported
-                                            // P1- 0, unsel, 1 SWR, 2 Comp, 3 ALC
-                                            // P2 - 4 dig - Meter value in dots - 000-0030
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"RM00000;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if((strcmp(cmd_str,"RR")==0) && (zzid_flag == 1)) {  
-                                            // PiHPSDR - ZZRR - Read Reverse Power
-                                            reverse = transmitter->rev;
-                                            sprintf(msg,"RR%09.7f;",reverse);
-                                            send_resp(client_sock,msg);
-                                         }
-        else if((strcmp(cmd_str,"RS")==0) && (zzid_flag == 1)) {  
-                                            // PiHPSDR - ZZRS - Read SWR
-                                            forward = transmitter->fwd;
-                                            reverse = transmitter->rev;
-                                            vswr = (forward+reverse)/(forward-reverse);
-                                            sprintf(msg,"RS%04.2f;",vswr);
-                                            send_resp(client_sock,msg);
-                                         }   
-        else if(strcmp(cmd_str,"RT")==0) {  
-                                            // TS-2000 - RT - Set/read the RIT function status
-                                            // PiHPSDR - ZZRT - Set/read the RIT function status
-                                             int lcl_rit_val;
-                                             if(len <=2) {
-                                                if(zzid_flag == 0) {
-                                                    sprintf(msg,"RT%01d;",rit_on());
-                                                } else {
-                                                    sprintf(msg,"ZZRT%01d;",rit_on());
-                                                }
-                                                send_resp(client_sock,msg); 
-                                             } else {
-                                                lcl_rit_val = atoi(&cmd_input[2]);
-                                                if((lcl_rit_val >=0) && (lcl_rit_val <=1)) {
-                                                   vfo[active_receiver->id].rit = lcl_rit_val;
-                                                } else {
-                                                   send_resp(client_sock,"?;"); 
-                                                }
-                                             }
-                                         }
-        else if(strcmp(cmd_str,"RU")==0) {  
-                                            // TS-2000 - RU - Set/move RIT frequency up
-                                            // PiHPSDR - ZZRU - Set/move RIT frequency up
-                                             int lcl_incr;
-                                             if(len <=2) {
-                                               lcl_incr = fine ? 1 : 10;
-                                               vfo[active_receiver->id].rit = vfo[active_receiver->id].rit+lcl_incr;
-                                             } else {
-                                                if(len > 3) {
-                                                   lcl_incr = atoi(&cmd_input[2]);    
-                                                   if((lcl_incr >=0) && (lcl_incr <= 99999)) {
-                                                      vfo[active_receiver->id].rit = lcl_incr;
-                                                   } else {
-                                                      send_resp(client_sock,"?;"); 
-                                                   }
-                                                } 
-                                             }
-                                             g_idle_add(ext_vfo_update,NULL);
-                                         }
-        else if(strcmp(cmd_str,"RX")==0) {  
-                                            // TS-2000 - RX - Unkey Xmitter
-                                            // PiHPSDR - ZZRX - Unkey Xmitter
-                                            //setMox(0);
-                                            if(!((vfo[active_receiver->id].mode == modeCWL) ||
-                                                 (vfo[active_receiver->id].mode == modeCWU))) {
-                                              #ifdef RIGCTL_DEBUG
-                                               fprintf(stderr, "RIGCTL: Inside RX command\n");
-                                               #endif
-                                               mox_state=0;
-                                               g_idle_add(ext_mox_update,(gpointer)(long)mox_state); 
-                                               g_idle_add(ext_vfo_update,NULL);
-                                            } else {
-                                               // Clear External MOX in CW mode
-                                               g_idle_add(ext_mox_update,(gpointer)(long)0); // Turn on xmitter (set Mox)
-                                            }
-                                         }
-        else if(strcmp(cmd_str,"SA")==0) {  
-                                            // TS-2000 - SA - Set/reads satellite mode status - not supported
-                                            // 0-main, 1=sub
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"SA000000000000000;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if(strcmp(cmd_str,"SB")==0) {  
-                                            // TS-2000 - SB - Set/read the SUB TF-W status - not supported
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"SB0;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if(strcmp(cmd_str,"SC")==0) {  
-                                            // TS-2000 - SC - Set/read the Scan function status - not supported
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"SC0;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if(((strcmp(cmd_str,"SD")==0) && (zzid_flag == 0)) ||   // Dl1YCF added () to improve readablity
-                ((strcmp(cmd_str,"CD")==0) && (zzid_flag ==1))) {    // Dl1YCF added () to improve readablity
-                                            // PiHPSDR - ZZCD - Set/Read CW Keyer Hang Time
-                                            // TS-2000 - SD - Set/Read Break In Delay
-                                            // 
-                                            // 0000-1000 ms (in steps of 50 ms) 0000 is full break in
-                                                int local_cw_breakin=cw_keyer_hang_time;
-                                                // Limit report value to 1000 for TS 2000
-                                                if(local_cw_breakin > 1000) { local_cw_breakin = 1000; }
-                                                if(len <=2) {
-                                                  if(zzid_flag == 0) { // TS 2000
-                                                       sprintf(msg,"SD%04d;",local_cw_breakin);
-                                                  } else {   // ZZ command response
-                                                       sprintf(msg,"ZZCD%04d;",local_cw_breakin);
-                                                  }
-                                                  send_resp(client_sock,msg);
-                                                } else {
-                                                  local_cw_breakin = atoi(&cmd_input[2]); 
-                                                  if(cw_keyer_hang_time <= 1000) {
-                                                     if(local_cw_breakin==0) {
-                                                         cw_breakin = 1;
-                                                     }  else {
-                                                         cw_breakin = 0;
-                                                     } 
-                                                     cw_keyer_hang_time = local_cw_breakin; 
-                                                 }
-                                                }
-                                             
-                                         }
-        else if(strcmp(cmd_str,"SH")==0) {  
-                                            // TS-2000 - SH - Set/read the DSP filter settings - not supported
-                                             if(len <=2) {
-                                              // send_resp(client_sock,"SH00;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if(strcmp(cmd_str,"SI")==0) {  
-                                            // TS-2000 - SI - Enters the satellite memory name - not supported
-                                         }
-        else if(strcmp(cmd_str,"SL")==0) {  
-                                            // TS-2000 - SL - Set/read the DSP filter settings - not supported
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"SL00;");
-                                               send_resp(client_sock,"?;"); 
-                                             } 
-                                         }
-        else if(strcmp(cmd_str,"SM")==0) {  
-                                            // PiHPSDR - ZZSM - Read SMeter - same range as TS 2000
-                                            // TI-2000 - SM - Read SMETER
-                                            // SM0:  main receiver, SM1: sub receiver
-                                            // Resp= SM0xxxx or SM1yyyy; xxxx between 0000 and 0030, yyyy between 0000 and 0015.
-                                            double level=0.0;
-
-                                            int r=0;
-                                            if(cmd_input[2] == '0') { 
-                                              r=0;
-                                            } else if(cmd_input[2] == '1') { 
-                                              if(receivers==2) {
-                                                r=1;
-                                              }
-                                            }
-                                            level = GetRXAMeter(receiver[r]->id, smeter); 
-
-                                            if(r == 0) { 
-                                               // DL1YCF: In the "main" bar graph, each bar counts 4 dB.
-                                               // S9+60 has 30 bars, S9 has 15 bars, S7 has 12 bars, and so on
-                                               // since S9 is about -73 dBm, the correct formula for converting
-                                               // dBm to bars is 15 + (level+73)/4 or 0.25*level + 33.25.
-                                               // The problem is now that S1 has 3 bars, such that 0 bars would
-                                               // correspond to S0 - 6dB. If one assumes that S0 corresponds
-                                               // to 0 bars, then it follows that the slope is 2 dB per bar
-                                               // below S1. This assumption is used in hamlib, and thus followed here.
-                                               if (level <= -121.0) {
-                                                   new_level = (int) round(0.50*level+63.50);   // valid up to S1 = -48 dBm
-                                               } else {
-                                                   new_level = (int) round(0.25*level+33.25);   // valid if at least S1
-                                               }
-                                               // Clip
-                                               if(new_level < 0) { new_level = 0; }
-                                               if(new_level > 30) { new_level = 30;}
-                                            } else {
-                                               // DL1YCF: studying the pictures in the TS2000 manual,
-                                               // for the "sub" display we have 0-9 small bars for S0 -S9, and in addition 1-6
-                                               // large bars for S9+10, ..., S9+60. So the slope is 6 dB per par
-                                               // up to S9, and 10 dB per bar beyond.
-                                               if (level <= -73.0) {
-                                                   new_level = (int) round(0.16667*level+21.16667);   // valid up to S9
-                                               } else {
-                                                   new_level = (int) round(0.1*level+16.3);           // valid if at least S9
-                                               }
-                                               // Clip
-                                               if(new_level < 0) { new_level = 0; }
-                                               if(new_level > 15) { new_level = 15;}
-                                           }
-
-                                            if(zzid_flag == 0) {
-                                               sprintf(msg,"SM%1c%04d;",
-                                                           cmd_input[2],new_level);
-                                            } else {
-                                               sprintf(msg,"ZZSM%1c%04d;",
-                                                           cmd_input[2],new_level);
-                                            }
-                                            send_resp(client_sock,msg);
-                                         }   
-
-        else if(strcmp(cmd_str,"SQ")==0) {  
-                                            // TS-2000 - SQ - Set/read the squelch level - not supported
-                                            // P1 - 0- main, 1=sub
-                                            // P2 - 0-255
-                                            float float_sq;
-                                             
-                                             if(len <=3) {
-                                                 float_sq = (float) active_receiver->squelch;
-                                                 float_sq = roundf((float_sq/100.0)*256.0);
-                                                #ifdef RIGCTL_DEBUG
-                                                     fprintf(stderr,"RIGCTL: float_sq=%6.2f\n",
-                                                                  float_sq); 
-                                                #endif
-                                                 sprintf(msg,"SQ0%03d;",(int) float_sq);
-                                                 send_resp(client_sock,msg);
-                                             } else {  // Set the value
-                                               int lcl_sq = atoi(&cmd_input[3]); // Note we skip the first char!
-                                               if((lcl_sq >= 0) && (lcl_sq <=255)) {
-                                                   float_sq = roundf(((float)lcl_sq/256.0)*100);
-                                                   active_receiver->squelch = (int)float_sq; 
-                                                  #ifdef RIGCTL_DEBUG
-                                                     fprintf(stderr,"RIGCTL: SetSq float_sq=%6.2f\n",
-                                                                  float_sq); 
-                                                  #endif
-                                                
-                                                 //setSquelch(active_receiver);
-                                                 g_idle_add(ext_update_squelch,NULL);
-                                                 g_idle_add(ext_vfo_update,NULL);
-                                               } else {
-                                                 send_resp(client_sock,"?;");
-                                               }
-                                             }
-                                           }
-
-        else if(strcmp(cmd_str,"SR")==0) {  
-                                            // TS-2000 - SR - Resets the transceiver - not supported
-                                         }
-        else if(strcmp(cmd_str,"SS")==0) {  
-                                            // TS-2000 - SS - Set/read Scan pause freq - not supported
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"SS0;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if(strcmp(cmd_str,"ST")==0) {  
-                                            // TS-2000 - ST - Set/read the multi/ch control freq steps
-                                            // PiHPSDR - ZZST - Set/read the multi/ch control freq steps
-                                            // SSB/CW/FSK - values 00-03
-                                            // 00: 1KHz, 01: 2.5Khz 02:5KHz 03: 10Khz
-                                            // AM/FM mode 00-09
-                                            // 00: 5KHz, 
-                                            // 01: 6.25KHz, 
-                                            // 02: 10Khz, 
-                                            // 03: 12.5Khz,
-                                            // 04: 15Khz, 
-                                            // 05: 20Khz, 
-                                            // 06: 25KHz
-                                            // 07: 30Khz
-                                            // 08: 50Khz
-                                            // 09: 100Khz 
-                                            if(zzid_flag == 0) {
-                                             int coded_step_val;
-                                             entry= (BANDSTACK_ENTRY *) 
-                                                bandstack_entry_get_current();
-                                             if(len <=2) {
-                                                 switch(entry->mode) {
-                                                     case modeLSB: 
-                                                     case modeUSB: 
-                                                     case modeCWL: 
-                                                     case modeCWU: 
-                                                     case modeDIGU: 
-                                                     case modeDIGL: 
-                                                        if(step >0 && step <= 1000)  {
-                                                          coded_step_val = 0; 
-                                                        } else if (step >1000 && step <=2500) {
-                                                          coded_step_val = 1; 
-                                                        } else if (step >2500 && step <=5000) {
-                                                          coded_step_val = 2; 
-                                                        } else {
-                                                          coded_step_val = 3; 
-                                                        }
-                                                        break;
-                                                     case modeFMN: 
-                                                     case modeAM:  
-                                                        if(step >0 && step <= 5000)  {
-                                                          coded_step_val = 0; 
-                                                        } else if (step >5000 && step <=6250) {
-                                                          coded_step_val = 1; 
-                                                        } else if (step >6250 && step <=10000) {
-                                                          coded_step_val = 2; 
-                                                        } else if (step >10000 && step <=12500) {
-                                                          coded_step_val = 3; 
-                                                        } else if (step >12500 && step <=15000) {
-                                                          coded_step_val = 4; 
-                                                        } else if (step >15000 && step <=20000) {
-                                                          coded_step_val = 5; 
-                                                        } else if (step >20000 && step <=25000) {
-                                                          coded_step_val = 6; 
-                                                        } else if (step >25000 && step <=30000) {
-                                                          coded_step_val = 7; 
-                                                        } else if (step >30000 && step <=50000) {
-                                                          coded_step_val = 8; 
-                                                        } else if (step >50000 && step <=100000) {
-                                                          coded_step_val = 9; 
-                                                        } else {
-                                                          coded_step_val = 0; 
-                                                        }
-                                                        break;
-                                                 } 
-                                                 sprintf(msg,"ST%02d;",coded_step_val);
-                                                 send_resp(client_sock,msg); 
-                                             } else {
-                                                 coded_step_val = atoi(&cmd_input[2]);   
-                                                 switch(entry->mode) {
-                                                     case modeLSB: 
-                                                     case modeUSB: 
-                                                     case modeCWL: 
-                                                     case modeCWU: 
-                                                     case modeDIGU: 
-                                                     case modeDIGL: 
-                                                        if(coded_step_val==0) { step = 1000;}
-                                                        if(coded_step_val==1) { step = 2500;}
-                                                        if(coded_step_val==2) { step = 5000;}
-                                                        if(coded_step_val==3) { step = 10000;}
-                                                        break; 
-                                                     case modeFMN: 
-                                                     case modeAM:  
-                                                         switch(coded_step_val) {
-                                                            case 0: step = 5000; break;
-                                                            case 1: step = 6250; break;
-                                                            case 2: step = 10000; break;
-                                                            case 3: step = 12500; break;
-                                                            case 4: step = 15000; break;
-                                                            case 5: step = 20000; break;
-                                                            case 6: step = 25000; break;
-                                                            case 7: step = 30000; break;
-                                                            case 8: step = 50000; break;
-                                                            case 9: step = 100000; break;
-                                                            default: break; // No change if not a valid number
-                                                         } 
-                                                     default: break; // No change if not a valid number
-                                                 } 
-                                             }
-                                            } else {
-                                                // Pi HPSDR handling
-                                               if(len <= 2) {
-                                                   sprintf(msg,"ZZST%06lld;", step);
-                                                   send_resp(client_sock,msg);
-                                                }  else {
-                                                   int okay= 0;
-                                                   work_int = atoi(&cmd_input[2]);
-                                                   switch(work_int) {
-                                                         case 100000: okay = 1; break;
-                                                         case  50000: okay = 1; break;
-                                                         case  30000: okay = 1; break;
-                                                         case  25000: okay = 1; break;
-                                                         case  20000: okay = 1; break;
-                                                         case  15000: okay = 1; break;
-                                                         case  12500: okay = 1; break;
-                                                         case  10000: okay = 1; break;
-                                                         case   9000: okay = 1; break;
-                                                         case   6250: okay = 1; break;
-                                                         case   5000: okay = 1; break;
-                                                         case   2500: okay = 1; break;
-                                                         case   1000: okay = 1; break;
-                                                         case    500: okay = 1; break;
-                                                         case    250: okay = 1; break;
-                                                         case    100: okay = 1; break;
-                                                         case     50: okay = 1; break;
-                                                         case     10: okay = 1; break;
-                                                         case      1: okay = 1; break;
-                                                         default:     okay = 0; break;
-                                                   }
-                                                   if(okay == 0) {
-                                                         fprintf(stderr,"RIGCTL: ZZST ERROR - illegal  step val=%d\n",work_int);
-                                                         send_resp(client_sock,"?;");
-                                                   } else {
-                                                      step = work_int; 
-                                                   }
-                                                }
-                                            }
-                                            g_idle_add(ext_vfo_update,NULL);
-                                         }
-        else if((strcmp(cmd_str,"SU")==0) && (zzid_flag == 0)) {
-                                            // TS-2000 - SU - Set/read the scan pause freq - not supported
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"SU00000000000;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if((strcmp(cmd_str,"SV")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - SV - Execute the memory transfer function - not supported
-                                         }
-        else if((strcmp(cmd_str,"TC")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - TC - Set/read the internal TNC mode - not supported
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"TC00;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if((strcmp(cmd_str,"TD")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - TD - Sends the DTMF memory channel - not supported
-                                         }
-        else if((strcmp(cmd_str,"TI")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - TI - Reads the TNC LED status - not supported
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"TI00;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if((strcmp(cmd_str,"TN")==0) && (zzid_flag == 0))  {  
-                                            // TS-2000 - TN - Set/Read sub tone freq - not supported
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"TN00;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if((strcmp(cmd_str,"TO")==0) && (zzid_flag == 0)) {  
-                                            // TI-2000 - TO - Set/Read tone function - not supported
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"TO0;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if((strcmp(cmd_str,"TS")==0) && (zzid_flag == 0)) {  
-                                            // TI-2000 - TS - Set/Read TF Set function status
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"TS0;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if(strcmp(cmd_str,"TX")==0)  { 
-                                            // TS-2000 - TX - Key Xmitter - P1 - transmit on main/sub freq
-                                            // PiHPSDR - ZZTX - Key Xmitter - P1 - transmit on main/sub freq
-                                            if(!((vfo[active_receiver->id].mode == modeCWL) ||
-                                                 (vfo[active_receiver->id].mode == modeCWU))) {
-                                                 //*if(len >=3) { 
-                                                 // K5JAE: The TS 2000 real hardware does not respond 
-                                                 // to this command, thus hamlib is not expecting response.
-                                                 //send_resp(client_sock,"TX0;");  */
-                                               mox_state = 1;
-                                               g_idle_add(ext_mox_update,(gpointer)(long)mox_state); 
-                                               g_idle_add(ext_vfo_update,NULL);
-                                            } else {
-                                              g_idle_add(ext_mox_update,(gpointer)(long)1); // Turn on External MOX
-                                            }
-                                         }
-        else if(strcmp(cmd_str,"TY")==0) {  
-                                            // TI-2000 - TY -- Set/Read uP firmware type
-                                             if(len <=2) {
-                                               send_resp(client_sock,"TY000;"); 
-                                             }
-                                         }
-        else if((strcmp(cmd_str,"UA")==0) && (zzid_flag == 1)) {  
-                                            // PiHPSDR - ZZUA - Xvrt Set/Read 
-                                            //        RW P1 - 1 Char - Entry number 0-7
-                                            //         W P1 - Disable PA - 1 char
-                                            //         W P2 - 15 Char -  Title - 16th char with last being '\0'
-                                            //         W P3 - 11 Chars - Min Freq HZ
-                                            //         W P4 - 11 Chars - Max Freq HZ
-                                            //         W P5 - 11 Chars - Low Freq HZ
-                                            char lcl_buf[] = "                "; 
-                                            char tempc;
-                                            if(len<=3) {
-                                               work_int = atoi(&cmd_input[2]);
-                                               if((work_int >=0) && (work_int <=7)) {
-                                                  BAND *xvtr=band_get_band(BANDS+work_int);
-                                                  strcpy(lcl_buf,xvtr->title);
-                                                  lcl_buf[strlen(lcl_buf)] = ' '; // Replace the last entry with ' ';
-                                                  lcl_buf[15] = '\0';
-                                                  sprintf(msg,"ZZUA%1d%1d%s%011lld%011lld%011lld;",work_int,xvtr->disablePA,lcl_buf,
-                                                                              xvtr->frequencyMin,xvtr->frequencyMax,xvtr->frequencyLO);
-                                                  send_resp(client_sock,msg);
-                                               }
-                                            } else if(len==52) {
-                                              
-                                               tempc = cmd_input[3];
-                                               cmd_input[3] = '\0';
-                                               work_int = atoi(&cmd_input[2]);
-                                               cmd_input[3] = tempc;
-                                               if((work_int >=0) && (work_int <=7)) {
-
-                                                  BAND *xvtr=band_get_band(BANDS+work_int);
-                                                  tempc = cmd_input[4]; 
-                                                  cmd_input[4]='\0';
-                                                  xvtr->disablePA = atoi(&cmd_input[3]); 
-                                                  cmd_input[4]=tempc;
-                                                  
-                                                  /* Get the title of the XVTR */
-                                                  tempc = cmd_input[19];
-                                                  cmd_input[19] = '\0';
-                                                  strncpy(xvtr->title,&cmd_input[4],16); 
-                                                  cmd_input[19] = tempc;
-
-                                                  /* Pull out the Min freq */
-                                                  tempc = cmd_input[30];
-                                                  cmd_input[30]='\0';
-                                                  xvtr->frequencyMin = (long long) atoi(&cmd_input[19]); 
-                                                  cmd_input[30] = tempc;
-
-                                                  /* Pull out the Max freq */
-                                                  tempc = cmd_input[41];
-                                                  cmd_input[41]='\0';
-                                                  xvtr->frequencyMax = (long long) atoi(&cmd_input[30]); 
-                                                  cmd_input[41] = tempc;
-                                                  
-
-                                                  /* Pull out the LO freq */
-                                                  xvtr->frequencyLO = (long long) atoi(&cmd_input[41]); 
-                                                } else {
-                                                  fprintf(stderr,"RIGCTL: ERROR ZZUA - incorrect length command received=%d",len);
-                                                  send_resp(client_sock,"?;");
-                                                }
-                                            } 
-                                         }
-        else if((strcmp(cmd_str,"UL")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - UL - Detects the PLL unlock status - not supported
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"UL0;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                         }
-        else if((strcmp(cmd_str,"UP")==0) && (zzid_flag == 0))  {
-                                            // TS-2000 - UP - Emulates the mic up key
-                                         }
-        else if(strcmp(cmd_str,"VD")==0) {  
-                                            // TS-2000 - VD - Sets/Reads VOX delay time - 0000-3000ms in steps of 150
-                                            // PiHPSDR - ZZVD - Sets/Reads VOX Hang time
-                                            // We want vox_hang variable in Pi HPSDR
-                                            // Max value in variable in ms... so 250 = 250ms
-                                             if(len <=2) {
-                                               work_int = (int) vox_hang;
-                                               if(zzid_flag == 0) {
-                                                  sprintf(msg,"VD%04d;",work_int); 
-                                               } else {
-                                                  sprintf(msg,"ZZVD%04d;",work_int); 
-                                               }
-                                               send_resp(client_sock,msg);
-                                             } else {
-                                                  work_int = atoi(&cmd_input[2]);
-                                                  // Bounds check for legal values for Pi HPSDR
-                                                  if(work_int > 1000) { work_int = 1000; }
-                                                  if(work_int < 0) { work_int = 0; }
-                                                  vox_hang = (double) work_int;
-                                                  #ifdef RIGCTL_DEBUG
-                                                  fprintf(stderr,"RIGCTL: Vox hang=%0.20f\n",vox_hang);
-                                                  #endif
-                                             }
-                                         }
-        else if(strcmp(cmd_str,"VG")==0) {  
-                                            // TI-2000 - VG - Sets/Reads VOX gain 000-009
-                                            // PiHPSDR - ZZVG - Set/Read VOX Threshold - 0-1000
-                                            // We want vox_threshold variable in Pi HPSDR
-                                            // Max value in variable 0.1 
-                                            // 3 char 000-009 valid ranges
-                                            if(len <=2) {
-                                               if(zzid_flag == 0) {
-                                                    work_int = (int) ((vox_threshold) * 100.0);
-                                                    sprintf(msg,"VG00%1d;",work_int);
-                                               } else {
-                                                    work_int = (int) ((vox_threshold) * 1000.0);
-                                                    sprintf(msg,"ZZVG%04d;",work_int);
-                                               }
-                                               send_resp(client_sock,msg);
-                                             } else {
-                                               work_int = atoi(&cmd_input[2]);
-                                               if((work_int >=0) && (work_int<=9)) {
-                                                  if(zzid_flag == 0) {
-                                                     // Set the threshold here
-                                                     vox_threshold = ((double) work_int)/10.0;
-                                                     #ifdef RIGCTL_DEBUG
-                                                     fprintf(stderr,"RIGCTL: Vox thresh=%0.20f\n",vox_threshold);
-                                                     #endif
-                                                  } else {
-                                                     vox_threshold = ((double) work_int)/1000.0;
-                                                     #ifdef RIGCTL_DEBUG
-                                                     fprintf(stderr,"RIGCTL: Vox thresh=%0.20f\n",vox_threshold);
-                                                     #endif
-                                                  }
-                                                } else {
-                                                     send_resp(client_sock,"?;");
-                                                }
-                                             }
-                                         }
-        else if((strcmp(cmd_str,"VR")==0) && (zzid_flag == 0)) {  
-                                            // TS-2000 - VR - Emulates the voice 1/2 key - not supported
-                                         }
-        else if(strcmp(cmd_str,"VX")==0) {  
-                                            // TS-2000 - VX - Sets/reads vox f(x) state
-                                            // PiHPSDR - ZZVX - Set/Read VOX enabled
-                                             if(len <=2) {
-                                               if(zzid_flag == 0 ) {
-                                                   sprintf(msg,"VX%1d;",vox_enabled); 
-                                               } else {
-                                                   sprintf(msg,"ZZVX%1d;",vox_enabled); 
-                                               } 
-                                               send_resp(client_sock,msg);
-                                             } else {
-                                               work_int = atoi(&cmd_input[2]);
-                                               if(work_int==1) { vox_enabled = 1; vox= 1;}
-                                               if(work_int!=1) { vox_enabled = 0; vox=0; }
-                                             }
-                                         }
-        else if((strcmp(cmd_str,"XC")==0) && (zzid_flag == 1)) {  
-                                            // PiHPSDR - ZZXC  - Terminate "CW" via ZZXO/ZZXT (Key up and MOX off)
-                                           cw_hold_key(0);
-                                            g_idle_add(ext_mox_update,(gpointer)(long)0);
-                                           CAT_cw_is_active=0;
-                                         }
-        else if((strcmp(cmd_str,"XI")==0) && (zzid_flag == 1)) {  
-                                            // PiHPSDR - ZZXI - Prepeare for "CW" via ZZXO/ZZXT (MOX on)
-                                           CAT_cw_is_active=1;
-                                            g_idle_add(ext_mox_update,(gpointer)(long)1);
-                                         }
-       else if((strcmp(cmd_str,"XO")==0) && (zzid_flag == 1)) {  
-                                            // PiHPSDR - ZZXO - Turn CW Note off when in CW mode
-                                           cw_hold_key(0);
-                                         }
-        else if(strcmp(cmd_str,"XT")==0) {  
-                                           if(zzid_flag == 0 ) {
-                                            // TS-2000 - XT - Sets/reads the XIT f(x) state - not supported
-                                             if(len <=2) {
-                                               //send_resp(client_sock,"XT0;"); 
-                                               send_resp(client_sock,"?;"); 
-                                             }
-                                           } else {
-                                            // PiHPSDR - ZZXT - Turn CW Note on when in CW mode
-                                           cw_hold_key(1);
-                                           }
-                                         }
-        else if((strcmp(cmd_str,"XX")==0) && (zzid_flag == 0)) {  // 
-                                            // Format RL01234: First dig 0=neg, 1=pos number
-                                            //                 1-4- digital offset in hertz.
-                                            if(len > 4) { // It is set instead of a read
-                                               digl_pol = (cmd_input[2]=='0') ? -1 : 1;
-                                               digl_offset = atoi(&cmd_input[3]); 
-                                               #ifdef RIGCTL_DEBUG
-                                               fprintf(stderr,"RIGCTL:RL set %d %d\n",digl_pol,digl_offset); 
-                                               #endif
-                                            } else {
-                                               if(digl_pol==1) { // Nah - its a read
-                                                 sprintf(msg,"RL1%04d;",0);
-                                               } else {
-                                                 sprintf(msg,"RL0%04d;",0);
-                                               }         
-                                               send_resp(client_sock,msg);
-                                               #ifdef RIGCTL_DEBUG
-                                               fprintf(stderr,":%s\n",msg);
-                                               #endif
-                                            }
-                                         }
-        else if(strcmp(cmd_str,"XY")==0) {  // set/read RTTY DIGL offset frequency - Not available - just store values
-                                            // Format RL01234: First dig 0=neg, 1=pos number
-                                            //                 1-4- digital offset in hertz.
-                                            if(len > 4) { // It is set instead of a read
-                                               digl_pol = (cmd_input[2]=='0') ? -1 : 1;
-                                               digl_offset = atoi(&cmd_input[3]); 
-                                               #ifdef RIGCTL_DEBUG
-                                               fprintf(stderr,"RIGCTL:RL set %d %d\n",digl_pol,digl_offset); 
-                                               #endif
-                                            } else {
-                                               if(digl_pol==1) { // Nah - its a read
-                                                 sprintf(msg,"RL1%04d;",0);
-                                               } else {
-                                                 sprintf(msg,"RL0%04d;",0);
-                                               }         
-                                               send_resp(client_sock,msg);
-                                               #ifdef RIGCTL_DEBUG
-                                               fprintf(stderr,":%s\n",msg);
-                                               #endif
-                                            }
-                                         }
-        else                             {
-                                            fprintf(stderr,"RIGCTL: UNKNOWN=%s\n",cmd_str);
-                                         }
+
+gboolean parse_extended_cmd (char *command,CLIENT *client) {
+  gboolean implemented=TRUE;
+  char reply[256];
+  reply[0]='\0';
+  switch(command[2]) {
+    case 'A': //ZZAx
+      switch(command[3]) {
+        case 'A': //ZZAA
+          implemented=FALSE;
+          break;
+        case 'B': //ZZAB
+          implemented=FALSE;
+          break;
+        case 'C': //ZZAC
+          // sets or reads the Step Size
+          if(command[4]==';') {
+            // read the step size
+            int i=0;
+            for(i=0;i<=14;i++) {
+              if(steps[i]==step) break;
+            }
+            if(i<=14) {
+              // send reply back
+              sprintf(reply,"ZZAC%02d;",i);
+              send_resp(client->fd,reply) ;
+            }
+          } else if(command[6]==';') {
+            // set the step size
+            int i=atoi(&command[4]) ;
+            if(i>=0 && i<=14) {
+              step=steps[i];
+              vfo_update();
+            }
+          } else {
+          }
+          break;
+        case 'D': //ZZAD
+          // move VFO A down by selected step
+          if(command[6]==';') {
+            int step_index=atoi(&command[4]);
+            long long hz=0;
+            if(step_index>=0 && step_index<=14) {
+              hz=(long long)steps[step_index];
+            }
+            if(hz!=0LL) {
+              vfo_id_move(VFO_A,-hz,FALSE);
+            }
+          } else {
+          }
+          break;
+        case 'E': //ZZAE
+          // move VFO A down nn tune steps
+          if(command[6]==';') {
+            int steps=atoi(&command[4]);
+            vfo_id_step(VFO_A,-steps);
+          }
+          break;
+        case 'F': //ZZAF
+          // move VFO A up nn tune steps
+          if(command[6]==';') {
+            int steps=atoi(&command[4]);
+            vfo_id_step(VFO_A,steps);
+          }
+          break;
+        case 'G': //ZZAG
+          // read/set audio gain
+          if(command[4]==';') {
+            // send reply back
+            sprintf(reply,"ZZAG%03d;",(int)(active_receiver->volume*100.0));
+            send_resp(client->fd,reply) ;
+          } else {
+            int gain=atoi(&command[4]);
+            active_receiver->volume=(double)gain/100.0;
+            update_af_gain();
+          }
+          break;
+        case 'I': //ZZAI
+          implemented=FALSE;
+          break;
+        case 'P': //ZZAP
+          implemented=FALSE;
+          break;
+        case 'R': //ZZAR
+          // read/set RX0 AGC Threshold
+          if(command[4]==';') {
+            // send reply back
+            sprintf(reply,"ZZAR%+04d;",(int)(receiver[0]->agc_gain));
+            send_resp(client->fd,reply) ;
+          } else {
+            int threshold=atoi(&command[4]);
+            set_agc_gain(VFO_A,(double)threshold);
+          }
+          break;
+        case 'S': //ZZAS
+          // read/set RX1 AGC Threshold
+          if(receivers==2) {
+            if(command[4]==';') {
+              // send reply back
+              sprintf(reply,"ZZAS%+04d;",(int)(receiver[1]->agc_gain));
+              send_resp(client->fd,reply) ;
+            } else {
+              int threshold=atoi(&command[4]);
+              set_agc_gain(VFO_B,(double)threshold);
+            }
+          }
+          break;
+        case 'T': //ZZAT
+          implemented=FALSE;
+          break;
+        case 'U': //ZZAU
+          // move VFO A up by selected step
+          if(command[6]==';') {
+            int step_index=atoi(&command[4]);
+            long long hz=0;
+            if(step_index>=0 && step_index<=14) {
+              hz=(long long)steps[step_index];
+            }
+            if(hz!=0LL) {
+              vfo_id_move(VFO_A,hz,FALSE);
+            }
+          } else {
+          }
+          break;
+        default:
+           implemented=FALSE;
+           break;
+      }
+      break;
+    case 'B': //ZZBx
+      switch(command[3]) {
+        case 'A': //ZZBA
+          // move RX2 down one band
+          if(command[4]==';') {
+            if(receivers==2) {
+              band_minus(receiver[1]->id);
+            }
+          }
+          break;
+        case 'B': //ZZBB
+          // move RX2 up one band
+          if(command[4]==';') {
+            if(receivers==2) {
+              band_plus(receiver[1]->id);
+            }
+          }
+          break;
+        case 'D': //ZZBD
+          // move RX1 down one band
+          if(command[4]==';') {
+            band_minus(receiver[0]->id);
+          }
+          break;
+        case 'E': //ZZBE
+          // move VFO B down nn tune steps
+          if(command[6]==';') {
+            int steps=atoi(&command[4]);
+            vfo_id_step(VFO_B,-steps);
+          }
+
+          break;
+        case 'F': //ZZBF
+          // move VFO B up nn tune steps
+          if(command[6]==';') {
+            int steps=atoi(&command[4]);
+            vfo_id_step(VFO_B,+steps);
+          }
+          break;
+        case 'G': //ZZBG
+          implemented=FALSE;
+          break;
+        case 'I': //ZZBI
+          implemented=FALSE;
+          break;
+        case 'M': //ZZBM
+          // move VFO B down by selected step
+          if(command[6]==';') {
+            int step_index=atoi(&command[4]);
+            long long hz=0;
+            if(step_index>=0 && step_index<=14) {
+              hz=(long long)steps[step_index];
+            }
+            if(hz!=0LL) {
+              vfo_id_move(VFO_B,-hz,FALSE);
+            }
+          } else {
+          }
+
+          break;
+        case 'P': //ZZBP
+          // move VFO B up by selected step
+          if(command[6]==';') {
+            int step_index=atoi(&command[4]);
+            long long hz=0;
+            if(step_index>=0 && step_index<=14) {
+              hz=(long long)steps[step_index];
+            }
+            if(hz!=0LL) {
+              vfo_id_move(VFO_B,hz,FALSE);
+            }
+          } else {
+          }
+          break;
+        case 'R': //ZZBR
+          implemented=FALSE;
+          break;
+        case 'S': //ZZBS
+          // set/read RX1 band switch
+          if(command[4]==';') {
+            int b;
+            switch(vfo[VFO_A].band) {
+              case band136:
+                b=136;
+                break;
+              case band472:
+                b=472;
+                break;
+              case band160:
+                b=160;
+                break;
+              case band80:
+                b=80;
+                break;
+              case band60:
+                b=60;
+                break;
+              case band40:
+                b=40;
+                break;
+              case band30:
+                b=30;
+                break;
+              case band20:
+                b=20;
+                break;
+              case band17:
+                b=17;
+                break;
+              case band15:
+                b=15;
+                break;
+              case band12:
+                b=12;
+                break;
+              case band10:
+                b=10;
+                break;
+              case band6:
+                b=6;
+                break;
+              case bandGen:
+                b=888;
+                break;
+              case bandWWV:
+                b=999;
+                break;
+              default:
+                b=20;
+                break;
+            }
+            sprintf(reply,"ZZBS%03d;",b);
+            send_resp(client->fd,reply) ;
+          } else if(command[7]==';') {
+            int band=band20;
+            int b=atoi(&command[4]);
+            switch(b) {
+              case 136:
+                band=band136;
+                break;
+              case 472:
+                band=band472;
+                break;
+              case 160:
+                band=band160;
+                break;
+              case 80:
+                band=band80;
+                break;
+              case 60:
+                band=band60;
+                break;
+              case 40:
+                band=band40;
+                break;
+              case 30:
+                band=band30;
+                break;
+              case 20:
+                band=band20;
+                break;
+              case 17:
+                band=band17;
+                break;
+              case 15:
+                band=band15;
+                break;
+              case 12:
+                band=band12;
+                break;
+              case 10:
+                band=band10;
+                break;
+              case 6:
+                band=band6;
+                break;
+              case 888:
+                band=bandGen;
+                break;
+              case 999:
+                band=bandWWV;
+                break;
+            }
+            vfo_band_changed(VFO_A,band);
+          }
+          break;
+        case 'T': //ZZBT
+          // set/read RX2 band switch
+          break;
+        case 'U': //ZZBU
+          // move RX1 up one band
+          if(command[4]==';') {
+            band_plus(receiver[0]->id);
+          }
+          break;
+        case 'Y': //ZZBY
+          // closes console (ignored)
+          break;
+        default:
+           implemented=FALSE;
+           break;
+      }
+      break;
+    case 'C': //ZZCx
+      switch(command[3]) {
+        case 'B': //ZZCB
+          implemented=FALSE;
+          break;
+        case 'D': //ZZCD
+          implemented=FALSE;
+          break;
+        case 'F': //ZZCF
+          implemented=FALSE;
+          break;
+        case 'I': //ZZCI
+          implemented=FALSE;
+          break;
+        case 'L': //ZZCL
+          implemented=FALSE;
+          break;
+        case 'M': //ZZCM
+          implemented=FALSE;
+          break;
+        case 'N': //ZZCN
+          // set/read VFO A CTUN
+          if(command[4]==';') {
+            // return the CTUN status
+            sprintf(reply,"ZZCN%d;",vfo[VFO_A].ctun);
+            send_resp(client->fd,reply) ;
+          } else if(command[5]==';') {
+            int state=atoi(&command[4]);
+            ctun_update(VFO_A,state);
+            vfo_update();
+          }
+          break;
+        case 'O': //ZZCO
+          // set/read VFO B CTUN
+          if(command[4]==';') {
+            // return the CTUN status
+            sprintf(reply,"ZZCO%d;",vfo[VFO_B].ctun);
+            send_resp(client->fd,reply) ;
+          } else if(command[5]==';') {
+            int state=atoi(&command[4]);
+            ctun_update(VFO_B,state);
+            vfo_update();
+          }
+          break;
+        case 'P': //ZZCP
+          // set/read compander
+          if(command[4]==';') {
+            sprintf(reply,"ZZCP%d;",0);
+            send_resp(client->fd,reply) ;
+          } else if(command[5]==';') {
+            // ignore
+          }
+          break;
+        case 'S': //ZZCS
+          implemented=FALSE;
+          break;
+        case 'T': //ZZCT
+          implemented=FALSE;
+          break;
+        case 'U': //ZZCU
+          implemented=FALSE;
+          break;
+        default:
+           implemented=FALSE;
+           break;
+      }
+      break;
+    case 'D': //ZZDx
+      switch(command[3]) {
+        case 'A': //ZZDA
+          break;
+        case 'B': //ZZDB
+          // set/read RX Reference
+          if(command[4]==';') {
+            sprintf(reply,"ZZDB%d;",0); // currently always 0
+            send_resp(client->fd,reply) ;
+          } else if(command[5]==';') {
+            // ignore
+          }
+          break;
+        case 'C': //ZZDC
+          // set/get diversity gain
+          if(command[4]==';') {
+            sprintf(reply,"ZZDC%04d;",(int)div_gain);
+            send_resp(client->fd,reply) ;
+          } else if(command[8]==';') {
+            // ignore
+          }
+          break;
+        case 'D': //ZZDD
+          // set/get diversity phase
+          if(command[4]==';') {
+            sprintf(reply,"ZZDD%04d;",(int)div_phase);
+            send_resp(client->fd,reply) ;
+          } else if(command[8]==';') {
+            // ignore
+          }
+        case 'E': //ZZDE
+          implemented=FALSE;
+          break;
+        case 'F': //ZZDF
+          implemented=FALSE;
+          break;
+        case 'M': //ZZDM
+          // set/read Display Mode
+          if(command[4]==';') {
+            int v=0;
+            if(active_receiver->display_waterfall) {
+              v=8;
+            } else {
+              v=2;
+            }
+            sprintf(reply,"ZZDM%d;",v);
+            send_resp(client->fd,reply) ;
+          } else {
+          }
+          break;
+        case 'N': //ZZDN
+          // set/read waterfall low
+          if(command[4]==';') {
+            sprintf(reply,"ZZDN%+4d;",active_receiver->waterfall_low);
+            send_resp(client->fd,reply) ;
+          } else {
+          }
+          break;
+        case 'O': //ZZDO
+          // set/read waterfall high
+          if(command[4]==';') {
+            sprintf(reply,"ZZDO%+4d;",active_receiver->waterfall_high);
+            send_resp(client->fd,reply) ;
+          } else {
+          }
+          break;
+        case 'P': //ZZDP
+          // set/read panadapter high
+          if(command[4]==';') {
+            sprintf(reply,"ZZDP%+4d;",active_receiver->panadapter_high);
+            send_resp(client->fd,reply) ;
+          } else {
+          }
+          break;
+        case 'Q': //ZZDQ
+          // set/read panadapter low
+          if(command[4]==';') {
+            sprintf(reply,"ZZDQ%+4d;",active_receiver->panadapter_low);
+            send_resp(client->fd,reply) ;
+          } else {
+          }
+          break;
+        case 'R': //ZZDR
+          // set/read panadapter step
+          if(command[4]==';') {
+            sprintf(reply,"ZZDR%2d;",active_receiver->panadapter_step);
+            send_resp(client->fd,reply) ;
+          } else {
+          }
+          break;
+        case 'U': //ZZDU
+          implemented=FALSE;
+          break;
+        case 'X': //ZZDX
+          implemented=FALSE;
+          break;
+        case 'Y': //ZZDY
+          implemented=FALSE;
+          break;
+        default:
+           implemented=FALSE;
+           break;
+      }
+      break;
+    case 'E': //ZZEx
+      switch(command[3]) {
+        case 'A': //ZZEA
+          // set/read rx equalizer values
+          if(command[4]==';') {
+            sprintf(reply,"ZZEA%03d%03d%03d%03d%03d00000000000000000000;",3,rx_equalizer[0],rx_equalizer[1],rx_equalizer[2],rx_equalizer[3]);
+            send_resp(client->fd,reply) ;
+          } else if(command[37]==';') {
+            char temp[4];
+            temp[3]='\0';
+            strncpy(temp,&command[4],3);
+            int bands=atoi(temp);
+            if(bands==3) {
+              strncpy(temp,&command[7],3);
+              rx_equalizer[0]=atoi(temp);
+              strncpy(temp,&command[10],3);
+              rx_equalizer[1]=atoi(temp);
+              strncpy(temp,&command[13],3);
+              rx_equalizer[2]=atoi(temp);
+            } else {
+            }
+          } else {
+          }
+          break;
+        case 'B': //ZZEB
+          // set/read tx equalizer values
+          if(command[4]==';') {
+            sprintf(reply,"ZZEB%03d%03d%03d%03d%03d00000000000000000000;",3,tx_equalizer[0],tx_equalizer[1],tx_equalizer[2],tx_equalizer[3]);
+            send_resp(client->fd,reply) ;
+          } else if(command[37]==';') {
+            char temp[4];
+            temp[3]='\0';
+            strncpy(temp,&command[4],3);
+            int bands=atoi(temp);
+            if(bands==3) {
+              strncpy(temp,&command[7],3);
+              tx_equalizer[0]=atoi(temp);
+              strncpy(temp,&command[10],3);
+              tx_equalizer[1]=atoi(temp);
+              strncpy(temp,&command[13],3);
+              tx_equalizer[2]=atoi(temp);
+            } else {
+            }
+          } else {
+          }
+          break;
+        case 'M': //ZZEM
+          implemented=FALSE;
+          break;
+        case 'R': //ZZER
+          // set/read rx equalizer
+          if(command[4]==';') {
+            sprintf(reply,"ZZER%d;",enable_rx_equalizer);
+            send_resp(client->fd,reply) ;
+          } else if(command[5]==';') {
+            enable_rx_equalizer=atoi(&command[4]);
+          } else {
+          }
+          break;
+        case 'T': //ZZET
+          // set/read tx equalizer
+          if(command[4]==';') {
+            sprintf(reply,"ZZET%d;",enable_tx_equalizer);
+            send_resp(client->fd,reply) ;
+          } else if(command[5]==';') {
+            enable_tx_equalizer=atoi(&command[4]);
+          } else {
+          }
+          break;
+        default:
+           implemented=FALSE;
+           break;
+      }
+      break;
+    case 'F': //ZZFx
+      switch(command[3]) {
+        case 'A': //ZZFA
+          // set/read VFO-A frequency
+          if(command[4]==';') {
+            if(vfo[VFO_A].ctun) {
+              sprintf(reply,"ZZFA%011lld;",vfo[VFO_A].ctun_frequency);
+            } else {
+              sprintf(reply,"ZZFA%011lld;",vfo[VFO_A].frequency);
+            }
+            send_resp(client->fd,reply) ;
+          } else if(command[15]==';') {
+            long long f=atoll(&command[4]);
+            local_set_frequency(VFO_A,f);
+            vfo_update();
+          }
+          break;
+        case 'B': //ZZFB
+          // set/read VFO-B frequency
+          if(command[4]==';') {
+            if(vfo[VFO_B].ctun) {
+              sprintf(reply,"ZZFB%011lld;",vfo[VFO_B].ctun_frequency);
+            } else {
+              sprintf(reply,"ZZFB%011lld;",vfo[VFO_B].frequency);
+            }
+            send_resp(client->fd,reply) ;
+          } else if(command[15]==';') {
+            long long f=atoll(&command[4]);
+            local_set_frequency(VFO_B,f);
+            vfo_update();
+          }
+          break;
+        case 'D': //ZZFD
+          // set/read deviation
+          if(command[4]==';') {
+            sprintf(reply,"ZZFD%d;",active_receiver->deviation==2500?0:1);
+            send_resp(client->fd,reply) ;
+          } else if(command[5]==';') {
+            int d=atoi(&command[4]);
+            if(d==0) {
+              active_receiver->deviation=2500;
+            } else if(d==1) {
+              active_receiver->deviation=5000;
+            } else {
+            }
+            vfo_update();
+          }
+          break;
+        case 'H': //ZZFH
+          // set/read RX1 filter high
+          if(command[4]==';') {
+            sprintf(reply,"ZZFH%05d;",receiver[0]->filter_high);
+            send_resp(client->fd,reply) ;
+          } else if(command[9]==';') {
+            int fh=atoi(&command[4]);
+            fh=fmin(9999,fh);
+            fh=fmax(-9999,fh);
+            // make sure filter is filterVar1
+            if(vfo[VFO_A].filter!=filterVar1) {
+              vfo_filter_changed(filterVar1);
+            }
+            FILTER *mode_filters=filters[vfo[VFO_A].mode];
+            FILTER *filter=&mode_filters[filterVar1];
+            filter->high=fh;
+            vfo_filter_changed(filterVar1);
+          }
+          break;
+        case 'I': //ZZFI
+          // set/read RX1 DSP receive filter
+          if(command[4]==';') {
+            sprintf(reply,"ZZFI%02d;",vfo[VFO_A].filter);
+            send_resp(client->fd,reply) ;
+          } else if(command[6]==';') {
+            int filter=atoi(&command[4]);
+            // update RX1 filter
+          }
+          break;
+        case 'J': //ZZFJ
+          // set/read RX2 DSP receive filter
+          if(command[4]==';') {
+            sprintf(reply,"ZZFJ%02d;",vfo[VFO_B].filter);
+            send_resp(client->fd,reply) ;
+          } else if(command[6]==';') {
+            int filter=atoi(&command[4]);
+            // update RX2 filter
+          }
+          break;
+        case 'L': //ZZFL
+          // set/read RX1 filter low
+          if(command[4]==';') {
+            sprintf(reply,"ZZFL%05d;",receiver[0]->filter_low);
+            send_resp(client->fd,reply) ;
+          } else if(command[9]==';') {
+            int fl=atoi(&command[4]);
+            fl=fmin(9999,fl);
+            fl=fmax(-9999,fl);
+            // make sure filter is filterVar1
+            if(vfo[VFO_A].filter!=filterVar1) {
+              vfo_filter_changed(filterVar1);
+            }
+            FILTER *mode_filters=filters[vfo[VFO_A].mode];
+            FILTER *filter=&mode_filters[filterVar1];
+            filter->low=fl;
+            vfo_filter_changed(filterVar1);
+          }
+          break;
+        case 'M': //ZZFM
+          implemented=FALSE;
+          break;
+        case 'R': //ZZFR
+          implemented=FALSE;
+          break;
+        case 'S': //ZZFS
+          implemented=FALSE;
+          break;
+        case 'V': //ZZFV
+          implemented=FALSE;
+          break;
+        case 'W': //ZZFW
+          implemented=FALSE;
+          break;
+        case 'X': //ZZFX
+          implemented=FALSE;
+          break;
+        case 'Y': //ZZFY
+          implemented=FALSE;
+          break;
+        default:
+           implemented=FALSE;
+           break;
+      }
+      break;
+    case 'G': //ZZGx
+      switch(command[3]) {
+        case 'E': //ZZGE
+          implemented=FALSE;
+          break;
+        case 'L': //ZZGL
+          implemented=FALSE;
+          break;
+        case 'T': //ZZGT
+          // set/read RX1 AGC
+          if(command[4]==';') {
+            sprintf(reply,"ZZGT%d;",receiver[0]->agc);
+            send_resp(client->fd,reply) ;
+          } else if(command[5]==';') {
+            int agc=atoi(&command[4]);
+            // update RX1 AGC
+            receiver[0]->agc=agc;
+            vfo_update();
+          }
+          break;
+        case 'U': //ZZGU
+          // set/read RX2 AGC
+          if(command[4]==';') {
+            sprintf(reply,"ZZGU%d;",receiver[1]->agc);
+            send_resp(client->fd,reply) ;
+          } else if(command[5]==';') {
+            int agc=atoi(&command[4]);
+            // update RX2 AGC
+            receiver[1]->agc=agc;
+            vfo_update();
+          }
+          break;
+        default:
+           implemented=FALSE;
+           break;
+      }
+      break;
+    case 'H': //ZZHx
+      switch(command[3]) {
+        case 'A': //ZZHA
+          implemented=FALSE;
+          break;
+        case 'R': //ZZHR
+          implemented=FALSE;
+          break;
+        case 'T': //ZZHT
+          implemented=FALSE;
+          break;
+        case 'U': //ZZHU
+          implemented=FALSE;
+          break;
+        case 'V': //ZZHV
+          implemented=FALSE;
+          break;
+        case 'W': //ZZHW
+          implemented=FALSE;
+          break;
+        case 'X': //ZZHX
+          implemented=FALSE;
+          break;
+        default:
+           implemented=FALSE;
+           break;
+      }
+      break;
+    case 'I': //ZZIx
+      switch(command[3]) {
+        case 'D': //ZZID
+          strcpy(reply,"ZZID240;");
+          send_resp(client->fd,reply) ;
+          break;
+        case 'F': //ZZIF
+          implemented=FALSE;
+          break;
+        case 'O': //ZZIO
+          implemented=FALSE;
+          break;
+        case 'S': //ZZIS
+          implemented=FALSE;
+          break;
+        case 'T': //ZZIT
+          implemented=FALSE;
+          break;
+        case 'U': //ZZIU
+          implemented=FALSE;
+          break;
+        default:
+           implemented=FALSE;
+           break;
+      }
+      break;
+    case 'K': //ZZKx
+      switch(command[3]) {
+        case 'M': //ZZIM
+          implemented=FALSE;
+          break;
+        case 'O': //ZZIO
+          implemented=FALSE;
+          break;
+        case 'S': //ZZIS
+          implemented=FALSE;
+          break;
+        case 'Y': //ZZIY
+          implemented=FALSE;
+          break;
+        default:
+           implemented=FALSE;
+           break;
+      }
+      break;
+    case 'L': //ZZLx
+      switch(command[3]) {
+        case 'A': //ZZLA
+          // read/set RX0 gain
+          if(command[4]==';') {
+            // send reply back
+            sprintf(reply,"ZZLA%03d;",(int)(receiver[0]->volume*100.0));
+            send_resp(client->fd,reply) ;
+          } else {
+            int gain=atoi(&command[4]);
+            receiver[0]->volume=(double)gain/100.0;
+            update_af_gain();
+          }
+          break;
+        case 'B': //ZZLB
+          implemented=FALSE;
+          break;
+        case 'C': //ZZLC
+          // read/set RX1 gain
+          if(receivers==2) {
+            if(command[4]==';') {
+              // send reply back
+              sprintf(reply,"ZZLC%03d;",(int)(receiver[1]->volume*100.0));
+              send_resp(client->fd,reply) ;
+            } else {
+              int gain=atoi(&command[4]);
+              receiver[1]->volume=(double)gain/100.0;
+              update_af_gain();
+            }
+          }
+          break;
+        case 'D': //ZZLD
+          implemented=FALSE;
+          break;
+        case 'E': //ZZLE
+          implemented=FALSE;
+          break;
+        case 'F': //ZZLF
+          implemented=FALSE;
+          break;
+        case 'G': //ZZLG
+          implemented=FALSE;
+          break;
+        case 'H': //ZZLH
+          implemented=FALSE;
+          break;
+        case 'I': //ZZLI
+          if(transmitter!=NULL) {
+            if(command[4]==';') {
+              // send reply back
+              sprintf(reply,"ZZLI%d;",transmitter->puresignal);
+              send_resp(client->fd,reply) ;
+            } else {
+              int ps=atoi(&command[4]);
+              transmitter->puresignal=ps;
+            }
+            vfo_update();
+          }
+          break;
+        default:
+           implemented=FALSE;
+           break;
+      }
+      break;
+    case 'M': //ZZMx
+      switch(command[3]) {
+        case 'A': //ZZMA
+          implemented=FALSE;
+          break;
+        case 'B': //ZZMB
+          implemented=FALSE;
+          break;
+        case 'D': //ZZMD
+          // set/read RX1 operating mode
+          if(command[4]==';') {
+            sprintf(reply,"ZZMD%02d;",vfo[VFO_A].mode);
+            send_resp(client->fd,reply);
+          } else if(command[6]==';') {
+            vfo_mode_changed(atoi(&command[4]));
+          }
+          break;
+        case 'E': //ZZME
+          // set/read RX2 operating mode
+          if(command[4]==';') {
+            sprintf(reply,"ZZMD%02d;",vfo[VFO_B].mode);
+            send_resp(client->fd,reply);
+          } else if(command[6]==';') {
+            vfo_mode_changed(atoi(&command[4]));
+          }
+          break;
+        case 'G': //ZZMG
+          // set/read mic gain
+          if(command[4]==';') {
+            sprintf(reply,"ZZMG%03d;",(int)mic_gain);
+            send_resp(client->fd,reply);
+          } else if(command[7]==';') {
+            mic_gain=(double)atoi(&command[4]);
+          }
+          break;
+        case 'L': //ZZML
+          // read DSP modes and indexes
+          if(command[4]==';') {
+            sprintf(reply,"ZZML LSB00: USB01: DSB02: CWL03: CWU04: FMN05:  AM06:DIGU07:SPEC08:DIGL09: SAM10: DRM11;");
+            send_resp(client->fd,reply);
+          }
+          break;
+        case 'N': //ZZMN
+          // read Filter Names and indexes
+          if(command[6]==';') {
+            int mode=atoi(&command[4])-1;
+            FILTER *f=filters[mode];
+            sprintf(reply,"ZZMN");
+            char temp[32];
+            for(int i=0;i<FILTERS;i++) {
+              sprintf(temp,"%5s%5d%5d",f[i].title,f[i].high,f[i].low);
+              strcat(reply,temp);
+            }
+            strcat(reply,";");
+            send_resp(client->fd,reply);
+          }
+          break;
+        case 'O': //ZZMO
+          // set/read MON status
+          if(command[4]==';') {
+            sprintf(reply,"ZZMO%d;",0);
+            send_resp(client->fd,reply);
+          }
+          break;
+        case 'R': //ZZMR
+          // set/read RX Meter mode
+          if(command[4]==';') {
+            sprintf(reply,"ZZMR%d;",smeter+1);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            smeter=atoi(&command[4])-1;
+          }
+          break;
+        case 'S': //ZZMS
+          implemented=FALSE;
+          break;
+        case 'T': //ZZMT
+          if(command[4]==';') {
+            sprintf(reply,"ZZMT%02d;",1); // forward power
+            send_resp(client->fd,reply);
+          } else {
+          }
+          break;
+        case 'U': //ZZMU
+          implemented=FALSE;
+          break;
+        case 'V': //ZZMV
+          implemented=FALSE;
+          break;
+        case 'W': //ZZMW
+          implemented=FALSE;
+          break;
+        case 'X': //ZZMX
+          implemented=FALSE;
+          break;
+        case 'Y': //ZZMY
+          implemented=FALSE;
+          break;
+        case 'Z': //ZZMZ
+          implemented=FALSE;
+          break;
+        default:
+           implemented=FALSE;
+           break;
+
+      }
+      break;
+    case 'N': //ZZNx
+      switch(command[3]) {
+        case 'A': //ZZNA
+          // set/read RX1 NB1
+          if(command[4]==';') {
+            sprintf(reply,"ZZNA%d;",receiver[0]->nb);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            receiver[0]->nb=atoi(&command[4]);
+            if(receiver[0]->nb) {
+              receiver[0]->nb2=0;
+            }
+            update_noise();
+          }
+          break;
+        case 'B': //ZZNB
+          // set/read RX1 NB2
+          if(command[4]==';') {
+            sprintf(reply,"ZZNB%d;",receiver[0]->nb2);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            receiver[0]->nb2=atoi(&command[4]);
+            if(receiver[0]->nb2) {
+              receiver[0]->nb=0;
+            }
+            update_noise();
+          }
+          break;
+        case 'C': //ZZNC
+          // set/read RX2 NB1
+          if(command[4]==';') {
+            sprintf(reply,"ZZNC%d;",receiver[1]->nb);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            receiver[1]->nb=atoi(&command[4]);
+            if(receiver[1]->nb) {
+              receiver[1]->nb2=0;
+            }
+            update_noise();
+          }
+          break;
+        case 'D': //ZZND
+          // set/read RX2 NB2
+          if(command[4]==';') {
+            sprintf(reply,"ZZND%d;",receiver[1]->nb2);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            receiver[1]->nb2=atoi(&command[4]);
+            if(receiver[1]->nb2) {
+              receiver[1]->nb=0;
+            }
+            update_noise();
+          }
+          break;
+        case 'L': //ZZNL
+          // set/read NB1 threshold
+          implemented=FALSE;
+          break;
+        case 'M': //ZZNM
+          // set/read NB2 threshold
+          implemented=FALSE;
+          break;
+        case 'N': //ZZNN
+          // set/read RX1 SNB status
+          if(command[4]==';') {
+            sprintf(reply,"ZZNN%d;",receiver[0]->snb);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            receiver[0]->snb=atoi(&command[4]);
+            update_noise();
+          }
+          break;
+        case 'O': //ZZNO
+          // set/read RX2 SNB status
+          if(command[4]==';') {
+            sprintf(reply,"ZZNO%d;",receiver[1]->snb);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            receiver[1]->snb=atoi(&command[4]);
+            update_noise();
+          }
+          break;
+        case 'R': //ZZNR
+          // set/read RX1 NR
+          if(command[4]==';') {
+            sprintf(reply,"ZZNR%d;",receiver[0]->nr);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            receiver[0]->nr=atoi(&command[4]);
+            if(receiver[0]->nr) {
+              receiver[0]->nr2=0;
+            }
+            update_noise();
+          }
+          break;
+        case 'S': //ZZNS
+          // set/read RX1 NR2
+          if(command[4]==';') {
+            sprintf(reply,"ZZNS%d;",receiver[0]->nr2);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            receiver[0]->nr2=atoi(&command[4]);
+            if(receiver[0]->nr2) {
+              receiver[0]->nr=0;
+            }
+            update_noise();
+          }
+          break;
+        case 'T': //ZZNT
+          // set/read RX1 ANF
+          if(command[4]==';') {
+            sprintf(reply,"ZZNT%d;",receiver[0]->anf);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            receiver[0]->anf=atoi(&command[4]);
+            update_noise();
+          }
+          break;
+        case 'U': //ZZNU
+          // set/read RX2 ANF
+          if(command[4]==';') {
+            sprintf(reply,"ZZNU%d;",receiver[1]->anf);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            receiver[1]->anf=atoi(&command[4]);
+            update_noise();
+          }
+          break;
+        case 'V': //ZZNV
+          // set/read RX2 NR
+          if(command[4]==';') {
+            sprintf(reply,"ZZNV%d;",receiver[1]->nr);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            receiver[1]->nr=atoi(&command[4]);
+            if(receiver[1]->nr) {
+              receiver[1]->nr2=0;
+            }
+            update_noise();
+          }
+          break;
+        case 'W': //ZZNW
+          // set/read RX2 NR2
+          if(command[4]==';') {
+            sprintf(reply,"ZZNW%d;",receiver[1]->nr2);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            receiver[1]->nr2=atoi(&command[4]);
+            if(receiver[1]->nr2) {
+              receiver[1]->nr=0;
+            }
+            update_noise();
+          }
+          break;
+        default:
+           implemented=FALSE;
+           break;
+      }
+    case 'O': //ZZOx
+      switch(command[3]) {
+        default:
+           implemented=FALSE;
+           break;
+      }
+      break;
+    case 'P': //ZZPx
+      switch(command[3]) {
+        case 'A': //ZZPA
+          // set/read preamp setting
+          if(command[4]==';') {
+            int a=adc[receiver[0]->adc].attenuation;
+            if(a==0) {
+              a=1;
+            } else if(a<=-30) {
+              a=4;
+            } else if(a<=-20) {
+              a=0;
+            } else if(a<=-10) {
+              a=2;
+            } else {
+              a=3;
+            }
+            sprintf(reply,"ZZPA%d;",a);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            int a=atoi(&command[4]);
+            switch(a) {
+              case 0:
+                adc[receiver[0]->adc].attenuation=-20;
+                break;
+              case 1:
+                adc[receiver[0]->adc].attenuation=0;
+                break;
+              case 2:
+                adc[receiver[0]->adc].attenuation=-10;
+                break;
+              case 3:
+                adc[receiver[0]->adc].attenuation=-20;
+                break;
+              case 4:
+                adc[receiver[0]->adc].attenuation=-30;
+                break;
+              default:
+                adc[receiver[0]->adc].attenuation=0;
+                break;
+            }
+          }
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'Q': //ZZQx
+      switch(command[3]) {
+        default:
+           implemented=FALSE;
+           break;
+      }
+      break;
+    case 'R': //ZZRx
+      switch(command[3]) {
+        case 'C': //ZZRC
+          // clear RIT frequency
+          if(command[4]==';') {
+            vfo[VFO_A].rit=0;
+            vfo_update();
+          }
+          break;
+        case 'D': //ZZRD
+          // decrement RIT frequency
+          if(command[4]==';') {
+            if(vfo[VFO_A].mode==modeCWL || vfo[VFO_A].mode==modeCWU) {
+              vfo[VFO_A].rit-=10;
+            } else {
+              vfo[VFO_A].rit-=50;
+            }
+            vfo_update();
+          } else if(command[9]==';') {
+            vfo[VFO_A].rit=atoi(&command[4]);
+            vfo_update();
+          }
+          break;
+        case 'F': //ZZRF
+          // set/read RIT frequency
+          if(command[4]==';') {
+            sprintf(reply,"ZZRF%+5lld;",vfo[VFO_A].rit);
+            send_resp(client->fd,reply);
+          } else if(command[9]==';') {
+            vfo[VFO_A].rit=atoi(&command[4]);
+            vfo_update();
+          }
+          break;
+        case 'M': //ZZRM
+          // read meter value
+          if(command[5]==';') {
+            int m=atoi(&command[4]);
+            sprintf(reply,"ZZRM%d%20d;",smeter,(int)receiver[0]->meter);
+            send_resp(client->fd,reply);
+          }
+          break;
+        case 'S': //ZZRS
+          // set/read RX2 enable
+          if(command[4]==';') {
+            sprintf(reply,"ZZRS%d;",receivers==2);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            int state=atoi(&command[4]);
+            if(state) {
+              radio_change_receivers(2);
+            } else {
+              radio_change_receivers(1);
+            }
+          }
+          break;
+        case 'T': //ZZRT
+          // set/read RIT enable
+          if(command[4]==';') {
+            sprintf(reply,"ZZRT%d;",vfo[VFO_A].rit_enabled);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            vfo[VFO_A].rit_enabled=atoi(&command[4]);
+            vfo_update();
+          }
+          break;
+        case 'U': //ZZRU
+          // increments RIT Frequency
+          if(command[4]==';') {
+            if(vfo[VFO_A].mode==modeCWL || vfo[VFO_A].mode==modeCWU) {
+              vfo[VFO_A].rit+=10;
+            } else {
+              vfo[VFO_A].rit+=50;
+            }
+            vfo_update();
+          } else if(command[9]==';') {
+            vfo[VFO_A].rit=atoi(&command[4]);
+            vfo_update();
+          }
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+    case 'S': //ZZSx
+      switch(command[3]) {
+        case 'A': //ZZSA
+          // move VFO A down one step 
+          if(command[4]==';') {
+            vfo_step(-1);
+          }
+          break;
+        case 'B': //ZZSB
+          // move VFO A up one step 
+          if(command[4]==';') {
+            vfo_step(1);
+          }
+          break;
+        case 'D': //ZZSD
+          implemented=FALSE;
+          break;
+        case 'F': //ZZSF
+          implemented=FALSE;
+          break;
+        case 'G': //ZZSG
+          // move VFO B down 1 step
+          if(command[4]==';') {
+            vfo_id_step(VFO_B,-1);
+          }
+          break;
+        case 'H': //ZZSH
+          // move VFO B up 1 step
+          if(command[4]==';') {
+            vfo_id_step(VFO_B,1);
+          }
+          break;
+        case 'M': //ZZSM
+          // reads the S Meter (in dB)
+          if(command[5]==';') {
+            int v=atoi(&command[4]);
+            if(v==VFO_A || v==VFO_B) {
+              double m=receiver[v]->meter;
+              m=fmax(-140.0,m);
+              m=fmin(-10.0,m);
+              sprintf(reply,"ZZSM%d%03d;",v,(int)((m+140.0)*2));
+              send_resp(client->fd,reply);
+            }
+          }
+          break;
+        case 'N': //ZZSN
+          implemented=FALSE;
+          break;
+        case 'P': //ZZSP
+          // set/read split
+          if(command[4]==';') {
+            sprintf(reply,"ZZSP%d;",split);
+            send_resp(client->fd,reply) ;
+          } else if(command[5]==';') {
+            split=atoi(&command[4]);
+            tx_set_mode(transmitter,get_tx_mode());
+            vfo_update();
+          }
+          break;
+        case 'R': //ZZSR
+          implemented=FALSE;
+          break;
+        case 'S': //ZZSS
+          implemented=FALSE;
+          break;
+        case 'T': //ZZST
+          implemented=FALSE;
+          break;
+        case 'U': //ZZSU
+          implemented=FALSE;
+          break;
+        case 'V': //ZZSV
+          implemented=FALSE;
+          break;
+        case 'W': //ZZSW
+          // set/read split
+          if(command[4]==';') {
+            sprintf(reply,"ZZSW%d;",split);
+            send_resp(client->fd,reply) ;
+          } else if(command[5]==';') {
+            split=atoi(&command[4]);
+            tx_set_mode(transmitter,get_tx_mode());
+            vfo_update();
+          }
+          break;
+        case 'Y': //ZZSY
+          implemented=FALSE;
+          break;
+        case 'Z': //ZZSZ
+          implemented=FALSE;
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'T': //ZZTx
+      switch(command[3]) {
+        case 'A': //ZZTA
+          implemented=FALSE;
+          break;
+        case 'B': //ZZTB
+          implemented=FALSE;
+          break;
+        case 'F': //ZZTF
+          implemented=FALSE;
+          break;
+        case 'H': //ZZTH
+          implemented=FALSE;
+          break;
+        case 'I': //ZZTI
+          implemented=FALSE;
+          break;
+        case 'L': //ZZTL
+          implemented=FALSE;
+          break;
+        case 'M': //ZZTM
+          implemented=FALSE;
+          break;
+        case 'O': //ZZTO
+          implemented=FALSE;
+          break;
+        case 'P': //ZZTP
+          implemented=FALSE;
+          break;
+        case 'S': //ZZTS
+          implemented=FALSE;
+          break;
+        case 'U': //ZZTU
+          // sets or reads TUN status
+          if(command[4]==';') {
+            sprintf(reply,"ZZTU%d;",tune);
+            send_resp(client->fd,reply) ;
+          } else if(command[5]==';') {
+            tune_update(atoi(&command[4]));
+          }
+          break;
+        case 'V': //ZZTV
+          implemented=FALSE;
+          break;
+        case 'X': //ZZTX
+          // sets or reads MOX status
+          if(command[4]==';') {
+            sprintf(reply,"ZZTX%d;",mox);
+            send_resp(client->fd,reply) ;
+          } else if(command[5]==';') {
+            mox_update(atoi(&command[4]));
+          }
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'U': //ZZUx
+      switch(command[3]) {
+        case 'A': //ZZUA
+          implemented=FALSE;
+          break;
+        case 'S': //ZZUS
+          implemented=FALSE;
+          break;
+        case 'T': //ZZUT
+          implemented=FALSE;
+          break;
+        case 'X': //ZZUX
+          implemented=FALSE;
+          break;
+        case 'Y': //ZZUY
+          implemented=FALSE;
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'V': //ZZVx
+      switch(command[3]) {
+        case 'A': //ZZVA
+          implemented=FALSE;
+          break;
+        case 'B': //ZZVB
+          implemented=FALSE;
+          break;
+        case 'C': //ZZVC
+          implemented=FALSE;
+          break;
+        case 'D': //ZZVD
+          implemented=FALSE;
+          break;
+        case 'E': //ZZVE
+          implemented=FALSE;
+          break;
+        case 'F': //ZZVF
+          implemented=FALSE;
+          break;
+        case 'H': //ZZVH
+          implemented=FALSE;
+          break;
+        case 'I': //ZZVI
+          implemented=FALSE;
+          break;
+        case 'J': //ZZVJ
+          implemented=FALSE;
+          break;
+        case 'K': //ZZVK
+          implemented=FALSE;
+          break;
+        case 'L': //ZZVL
+          // set/get VFO Lock
+          implemented=FALSE;
+          break;
+        case 'M': //ZZVM
+          implemented=FALSE;
+          break;
+        case 'N': //ZZVN
+          implemented=FALSE;
+          break;
+        case 'O': //ZZVO
+          implemented=FALSE;
+          break;
+        case 'P': //ZZVP
+          implemented=FALSE;
+          break;
+        case 'Q': //ZZVQ
+          implemented=FALSE;
+          break;
+        case 'R': //ZZVR
+          implemented=FALSE;
+          break;
+        case 'S': //ZZVS
+          implemented=FALSE;
+          break;
+        case 'T': //ZZVT
+          implemented=FALSE;
+          break;
+        case 'U': //ZZVU
+          implemented=FALSE;
+          break;
+        case 'V': //ZZVV
+          implemented=FALSE;
+          break;
+        case 'W': //ZZVW
+          implemented=FALSE;
+          break;
+        case 'X': //ZZVX
+          implemented=FALSE;
+          break;
+        case 'Y': //ZZVY
+          implemented=FALSE;
+          break;
+        case 'Z': //ZZVZ
+          implemented=FALSE;
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'W': //ZZWx
+      switch(command[3]) {
+        case 'A': //ZZWA
+          implemented=FALSE;
+          break;
+        case 'B': //ZZWB
+          implemented=FALSE;
+          break;
+        case 'C': //ZZWC
+          implemented=FALSE;
+          break;
+        case 'D': //ZZWD
+          implemented=FALSE;
+          break;
+        case 'E': //ZZWE
+          implemented=FALSE;
+          break;
+        case 'F': //ZZWF
+          implemented=FALSE;
+          break;
+        case 'G': //ZZWG
+          implemented=FALSE;
+          break;
+        case 'H': //ZZWH
+          implemented=FALSE;
+          break;
+        case 'J': //ZZWJ
+          implemented=FALSE;
+          break;
+        case 'K': //ZZWK
+          implemented=FALSE;
+          break;
+        case 'L': //ZZWL
+          implemented=FALSE;
+          break;
+        case 'M': //ZZWM
+          implemented=FALSE;
+          break;
+        case 'N': //ZZWN
+          implemented=FALSE;
+          break;
+        case 'O': //ZZWO
+          implemented=FALSE;
+          break;
+        case 'P': //ZZWP
+          implemented=FALSE;
+          break;
+        case 'Q': //ZZWQ
+          implemented=FALSE;
+          break;
+        case 'R': //ZZWR
+          implemented=FALSE;
+          break;
+        case 'S': //ZZWS
+          implemented=FALSE;
+          break;
+        case 'T': //ZZWT
+          implemented=FALSE;
+          break;
+        case 'U': //ZZWU
+          implemented=FALSE;
+          break;
+        case 'V': //ZZWV
+          implemented=FALSE;
+          break;
+        case 'W': //ZZWW
+          implemented=FALSE;
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'X': //ZZXx
+      switch(command[3]) {
+        case 'C': //ZZXC
+          // clear transmitter XIT
+          if(command[4]==';') {
+            transmitter->xit=0;
+            vfo_update();
+          }
+          break;
+        case 'F': //ZZXF
+          // set/read XIT
+          if(command[4]==';') {
+            sprintf(reply,"ZZXT%+05lld;",transmitter->xit);
+            send_resp(client->fd,reply) ;
+          } else if(command[9]==';') {
+            transmitter->xit=(long long)atoi(&command[4]);
+            vfo_update();
+          }
+          break;
+        case 'H': //ZZXH
+          implemented=FALSE;
+          break;
+        case 'N': //ZZXN
+          // read combined RX1 status
+          if(command[4]==';') {
+            int status=0;
+            status=status|((receiver[0]->agc)&0x03);
+            int a=adc[receiver[0]->adc].attenuation;
+            if(a==0) {
+              a=1;
+            } else if(a<=-30) {
+              a=4;
+            } else if(a<=-20) {
+              a=0;
+            } else if(a<=-10) {
+              a=2;
+            } else {
+              a=3;
+            }
+            status=status|((a&0x03)<<3);
+            status=status|((receiver[0]->squelch_enable&0x01)<<6);
+            status=status|((receiver[0]->nb&0x01)<<7);
+            status=status|((receiver[0]->nb2&0x01)<<8);
+            status=status|((receiver[0]->nr&0x01)<<9);
+            status=status|((receiver[0]->nr2&0x01)<<10);
+            status=status|((receiver[0]->snb&0x01)<<11);
+            status=status|((receiver[0]->anf&0x01)<<12);
+            sprintf(reply,"ZZXN%04d;",status);
+            send_resp(client->fd,reply);
+          }
+          break;
+        case 'O': //ZZXO
+          // read combined RX2 status
+          if(receivers==2) {
+            if(command[4]==';') {
+              int status=0;
+              status=status|((receiver[1]->agc)&0x03);
+              int a=adc[receiver[1]->adc].attenuation;
+              if(a==0) {
+                a=1;
+              } else if(a<=-30) {
+                a=4;
+              } else if(a<=-20) {
+                a=0;
+              } else if(a<=-10) {
+                a=2;
+              } else {
+                a=3;
+              }
+              status=status|((a&0x03)<<3);
+              status=status|((receiver[1]->squelch_enable&0x01)<<6);
+              status=status|((receiver[1]->nb&0x01)<<7);
+              status=status|((receiver[1]->nb2&0x01)<<8);
+              status=status|((receiver[1]->nr&0x01)<<9);
+              status=status|((receiver[1]->nr2&0x01)<<10);
+              status=status|((receiver[1]->snb&0x01)<<11);
+              status=status|((receiver[1]->anf&0x01)<<12);
+              sprintf(reply,"ZZXO%04d;",status);
+              send_resp(client->fd,reply);
+            }
+          }
+          break;
+        case 'S': //ZZXS
+          /// set/read XIT enable
+          if(command[4]==';') {
+            sprintf(reply,"ZZXS%d;",transmitter->xit_enabled);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            transmitter->xit_enabled=atoi(&command[4]);
+            vfo_update();
+          }
+          break;
+        case 'T': //ZZXT
+          implemented=FALSE;
+          break;
+        case 'V': //ZZXV
+          // read combined VFO status
+          if(command[4]==';') {
+            int status=0;
+            if(vfo[VFO_A].rit_enabled) {
+              status=status|0x01;
+            }
+            if(locked) {
+              status=status|0x02;
+              status=status|0x04;
+            }
+            if(split) {
+              status=status|0x08;
+            }
+            if(vfo[VFO_A].ctun) {
+              status=status|0x10;
+            }
+            if(vfo[VFO_B].ctun) {
+              status=status|0x20;
+            }
+            if(mox) {
+              status=status|0x40;
+            }
+            if(tune) {
+              status=status|0x80;
+            }
+            sprintf(reply,"ZZXV%03d;",status);
+            send_resp(client->fd,reply);
+          }
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'Y': //ZZYx
+      switch(command[3]) {
+       case 'A': //ZZYA
+          implemented=FALSE;
+          break;
+       case 'B': //ZZYB
+          implemented=FALSE;
+          break;
+       case 'C': //ZZYC
+          implemented=FALSE;
+          break;
+       case 'R': //ZZYR
+          // switch receivers
+          if(command[5]==';') {
+            int v=atoi(&command[4]);
+            if(v==0) {
+              active_receiver=receiver[0];
+            } else if(v==1) {
+              if(receivers==2) {
+                active_receiver=receiver[1];
+              }
+            }
+            vfo_update();
+          }
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'Z': //ZZZx
+      switch(command[3]) {
+        case 'A': //ZZZA
+          implemented=FALSE;
+          break;
+       case 'B': //ZZZB
+          implemented=FALSE;
+          break;
+       case 'Z': //ZZZZ
+          implemented=FALSE;
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    default:
+       implemented=FALSE;
+       break;
+  }
+  return implemented;
 }
-//
-// End of Parser
-// 
 
+// called with g_idle_add so that the processing is running on the main thread
+int parse_cmd(void *data) {
+  COMMAND *info=(COMMAND *)data;
+  CLIENT *client=info->client;
+  char *command=info->command;
+  char reply[80];
+  reply[0]='\0';
+  gboolean implemented=TRUE;
+
+  switch(command[0]) {
+    case 'A':
+      switch(command[1]) {
+        case 'G': //AG
+          // set/read AF Gain
+          if(command[3]==';') {
+            // send reply back
+            sprintf(reply,"AG0%03d;",(int)(receiver[0]->volume*100.0));
+            send_resp(client->fd,reply) ;
+          } else if(command[6]==';') {
+            int gain=atoi(&command[3]);
+            receiver[0]->volume=(double)gain/100.0;
+            update_af_gain();
+          }
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'B':
+      switch(command[1]) {
+        case 'D': //BD
+          //band down 1 band
+          band_minus(receiver[0]->id);
+          break;
+        case 'U': //BU
+          //band up 1 band
+          band_plus(receiver[0]->id);
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'C':
+      switch(command[1]) {
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'D':
+      switch(command[1]) {
+        case 'N': //DN
+          // move VFO A down 1 step size
+          vfo_id_step(VFO_A,-1);
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'E':
+      switch(command[1]) {
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'F':
+      switch(command[1]) {
+        case 'A': //FA
+          // set/read VFO-A frequency
+          if(command[2]==';') {
+            if(vfo[VFO_A].ctun) {
+              sprintf(reply,"FA%011lld;",vfo[VFO_A].ctun_frequency);
+            } else {
+              sprintf(reply,"FA%011lld;",vfo[VFO_A].frequency);
+            }
+            send_resp(client->fd,reply) ;
+          } else if(command[13]==';') {
+            long long f=atoll(&command[2]);
+            local_set_frequency(VFO_A,f);
+            vfo_update();
+          }
+          break;
+        case 'B': //FB
+          // set/read VFO-B frequency
+          if(command[2]==';') {
+            if(vfo[VFO_B].ctun) {
+              sprintf(reply,"FB%011lld;",vfo[VFO_B].ctun_frequency);
+            } else {
+              sprintf(reply,"FB%011lld;",vfo[VFO_B].frequency);
+            }
+            send_resp(client->fd,reply) ;
+          } else if(command[13]==';') {
+            long long f=atoll(&command[2]);
+            local_set_frequency(VFO_B,f);
+            vfo_update();
+          }
+          break;
+        case 'R': //FR
+          // set/read transceiver receive VFO
+          if(command[2]==';') {
+            sprintf(reply,"FR0;");
+            send_resp(client->fd,reply) ;
+          } else if(command[3]==';') {
+            // ignore set command
+          }
+          break;
+        case 'T': //FT
+          // set/read transceiver transmit VFO
+          if(command[2]==';') {
+            sprintf(reply,"FT%d;",split);
+            send_resp(client->fd,reply) ;
+          } else if(command[3]==';') {
+            split=atoi(&command[2]);
+            tx_set_mode(transmitter,get_tx_mode());
+            vfo_update();
+          }
+          break;
+        case 'W': //FW
+          // set/read filter width
+          implemented=FALSE;
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'G':
+      switch(command[1]) {
+        case 'T': //GT
+          // set/read RX1 AGC
+          if(command[2]==';') {
+            sprintf(reply,"GT%03d;",receiver[0]->agc);
+            send_resp(client->fd,reply) ;
+          } else if(command[5]==';') {
+            // update RX1 AGC
+            receiver[0]->agc=atoi(&command[2]);
+            vfo_update();
+          }
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'H':
+      switch(command[1]) {
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'I':
+      switch(command[1]) {
+        case 'D': //ID
+          // get ID
+          strcpy(reply,"ID019;");
+          send_resp(client->fd,reply);
+          break;
+        case 'F': //IF
+          sprintf(reply,"IF%011lld%04lld%+06lld%d%d000%d%d%d0%d0000;",
+                  vfo[VFO_A].ctun?vfo[VFO_A].ctun_frequency:vfo[VFO_A].frequency,
+                  step,vfo[VFO_A].rit,vfo[VFO_A].rit_enabled,transmitter==NULL?0:transmitter->xit_enabled,
+                  mox,split,0,split?1:0);
+          send_resp(client->fd,reply);
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'J':
+      switch(command[1]) {
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'K':
+      switch(command[1]) {
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'L':
+      switch(command[1]) {
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'M':
+      switch(command[1]) {
+        case 'D': //MD
+          // set/read operating mode
+          if(command[2]==';') {
+            sprintf(reply,"MD%d;",vfo[VFO_A].mode+1);
+            send_resp(client->fd,reply);
+          } else if(command[3]==';') {
+            vfo_mode_changed(atoi(&command[2])-1);
+          }
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'N':
+      switch(command[1]) {
+        case 'B': //NB
+          // set/read NB1
+          if(command[2]==';') {
+            sprintf(reply,"NB%d;",active_receiver->nb);
+            send_resp(client->fd,reply);
+          } else if(command[3]==';') {
+            active_receiver->nb=atoi(&command[2]);
+            if(active_receiver->nb) {
+              active_receiver->nb2=0;
+            }
+            update_noise();
+          }
+          break;
+        case 'T': //NT
+          // set/read ANF
+          if(command[2]==';') {
+            sprintf(reply,"NT%d;",active_receiver->anf);
+            send_resp(client->fd,reply);
+          } else if(command[3]==';') {
+            active_receiver->anf=atoi(&command[2]);
+            SetRXAANFRun(active_receiver->id, active_receiver->anf);
+            vfo_update();
+          }
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'O':
+      switch(command[1]) {
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'P':
+      switch(command[1]) {
+        case 'C': //PC
+          // set/read PA Power
+          if(command[2]==';') {
+            sprintf(reply,"PC%03d;",(int)transmitter->drive);
+            send_resp(client->fd,reply);
+          } else if(command[5]==';') {
+            setDrive((double)atoi(&command[2]));
+          }
+          break;
+        case 'S': //PS
+          // set/read Power (always ON)
+          if(command[2]==';') {
+            sprintf(reply,"PS1;");
+            send_resp(client->fd,reply);
+          } else if(command[3]==';') {
+            // ignore set
+          }
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'Q':
+      switch(command[1]) {
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'R':
+      switch(command[1]) {
+        case 'C': //RC
+          // clears RIT
+          if(command[2]==';') {
+            vfo[VFO_A].rit=0;
+            vfo_update();
+          }
+          break;
+        case 'D': //RD
+          // decrements RIT Frequency
+          if(command[2]==';') {
+            if(vfo[VFO_A].mode==modeCWL || vfo[VFO_A].mode==modeCWU) {
+              vfo[VFO_A].rit-=10;
+            } else {
+              vfo[VFO_A].rit-=50;
+            }
+            vfo_update();
+          } else if(command[7]==';') {
+            vfo[VFO_A].rit=atoi(&command[2]);
+            vfo_update();
+          }
+          break;
+        case 'T': //RT
+          // set/read RIT enable
+          if(command[2]==';') {
+            sprintf(reply,"RT%d;",vfo[VFO_A].rit_enabled);
+            send_resp(client->fd,reply);
+          } else if(command[3]==';') {
+            vfo[VFO_A].rit_enabled=atoi(&command[2]);
+            vfo_update();
+          }
+          break;
+        case 'U': //RU
+          // increments RIT Frequency
+          if(command[2]==';') {
+            if(vfo[VFO_A].mode==modeCWL || vfo[VFO_A].mode==modeCWU) {
+              vfo[VFO_A].rit+=10;
+            } else {
+              vfo[VFO_A].rit+=50;
+            }
+            vfo_update();
+          } else if(command[7]==';') {
+            vfo[VFO_A].rit=atoi(&command[2]);
+            vfo_update();
+          }
+          break;
+        case 'X': //RX
+          // set transceiver to RX mode
+          if(command[2]==';') {
+            mox_update(0);
+          }
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'S':
+      switch(command[1]) {
+        case 'M': //SM
+          // read the S meter
+          if(command[3]==';') {
+            int id=atoi(&command[2]);
+            if(id==0 || id==1) {
+              sprintf(reply,"SM%04d;",(int)receiver[id]->meter);
+              send_resp(client->fd,reply);
+            }
+          }
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'T':
+      switch(command[1]) {
+        case 'X': //TX
+          // set transceiver to TX mode
+          if(command[2]==';') {
+            mox_update(1);
+          }
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'U':
+      switch(command[1]) {
+        case 'P': //UP
+          // move VFO A up by step
+          if(command[2]==';') {
+            vfo_step(1);
+          }
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'V':
+      switch(command[1]) {
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'W':
+      switch(command[1]) {
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'X':
+      switch(command[1]) {
+        case 'T': //XT
+          // set/read XIT enable
+          if(command[2]==';') {
+            sprintf(reply,"XT%d;",transmitter->xit_enabled);
+            send_resp(client->fd,reply);
+          } else if(command[3]==';') {
+            transmitter->xit_enabled=atoi(&command[2]);
+            vfo_update();
+          }
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'Y':
+      switch(command[1]) {
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    case 'Z':
+      switch(command[1]) {
+        case 'Z':
+          implemented=parse_extended_cmd (command,client);
+          break;
+        default:
+          implemented=FALSE;
+          break;
+      }
+      break;
+    default:
+      implemented=FALSE;
+      break;
+  }
+
+  if(!implemented) {
+    g_print("RIGCTL: UNIMPLEMENTED COMMAND: %s\n",info->command);
+  }
+
+  g_free(info->command);
+  g_free(info);
+  return 0;
+}
 
 // Serial Port Launch
 int set_interface_attribs (int fd, int speed, int parity)
@@ -3760,7 +3058,7 @@ int set_interface_attribs (int fd, int speed, int parity)
         memset (&tty, 0, sizeof tty);
         if (tcgetattr (fd, &tty) != 0)
         {
-                fprintf (stderr,"RIGCTL: Error %d from tcgetattr", errno);
+                g_print ("RIGCTL: Error %d from tcgetattr", errno);
                 return -1;
         }
 
@@ -3789,7 +3087,7 @@ int set_interface_attribs (int fd, int speed, int parity)
 
         if (tcsetattr (fd, TCSANOW, &tty) != 0)
         {
-                fprintf(stderr, "RIGCTL: Error %d from tcsetattr", errno);
+                g_print( "RIGCTL: Error %d from tcsetattr", errno);
                 return -1;
         }
         return 0;
@@ -3801,113 +3099,99 @@ void set_blocking (int fd, int should_block)
         memset (&tty, 0, sizeof tty);
         if (tcgetattr (fd, &tty) != 0)
         {
-                fprintf (stderr,"RIGCTL: Error %d from tggetattr\n", errno);
+                g_print ("RIGCTL: Error %d from tggetattr\n", errno);
                 return;
         }
         tty.c_cc[VMIN]  = should_block ? 1 : 0;
         tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout
 
         if (tcsetattr (fd, TCSANOW, &tty) != 0)
-                fprintf (stderr,"RIGCTL: error %d setting term attributes\n", errno);
+                g_print("RIGCTL: error %d setting term attributes\n", errno);
 }
+
 static gpointer serial_server(gpointer data) {
      // We're going to Read the Serial port and
      // when we get data we'll send it to parse_cmd
-     char ser_buf[MAXDATASIZE];
-     char work_buf[MAXDATASIZE];
-     char *p;
-     char *d;
-     char save_buf[MAXDATASIZE] = "";
-     int str_len;
+     CLIENT *client=(CLIENT *)data;
+     char cmd_input[MAXDATASIZE];
+     char *command=g_new(char,MAXDATASIZE);
+     int command_index=0;
+     int numbytes;
+     int i;
      cat_control++;
-     while(1) {
-        int num_chars = read (fd, ser_buf, sizeof ser_buf);
-        if( num_chars != 0) {
-           //fprintf(stderr,"RIGCTL: RECEVIED=%s<<\n",ser_buf);
-           strcat(work_buf,ser_buf);
-           strcpy(ser_buf,"");  // Clear away serial buffer
-           p = &work_buf[0]; 
-           while((d=strstr(p,";")) != NULL) {
-                 *d = '\0';
-                 g_mutex_lock(&mutex_b->m);
-                 
-                 g_mutex_unlock(&mutex_b->m);
-                 p = ++d;
-                 //fprintf(stderr,"RIGCTL: STRLEFT=%s\n",p);
-           }
-           strcpy(save_buf,p);
-           for(str_len=0; str_len<=1999; str_len++) {
-             ser_buf[str_len] = '\0';
-             work_buf[str_len] = '\0';
-           }
-           strcpy(work_buf,save_buf);
-           for(str_len=0; str_len<=1999; str_len++) {
-             save_buf[str_len] = '\0';
+     serial_running=TRUE;
+     while(serial_running) {
+       numbytes = read (fd, cmd_input, sizeof cmd_input);
+       if(numbytes>0) {
+         for(i=0;i<numbytes;i++) {
+           command[command_index]=cmd_input[i];
+           command_index++;
+           if(cmd_input[i]==';') { 
+             command[command_index]='\0';
+             if(rigctl_debug) g_print("RIGCTL: command=%s\n",command);
+             COMMAND *info=g_new(COMMAND,1);
+             info->client=client;
+             info->command=command;
+             g_mutex_lock(&mutex_busy->m);
+             g_idle_add(parse_cmd,info);
+             g_mutex_unlock(&mutex_busy->m);
+
+             command=g_new(char,MAXDATASIZE);
+             command_index=0;
            }
-/*
-           if(strstr(ser_buf,";") != NULL) {
-              p = strtok(ser_buf,s);
-              fprintf(stderr,"RIGCTL: Tok=%s\n",p);
-              while(p != NULL) {
-                 strcpy(work_buf,p);
-                 g_mutex_lock(&mutex_b->m);
-                 parse_cmd(work_buf,strlen(work_buf),-1);
-                 g_mutex_unlock(&mutex_b->m);
-                 p = strtok(NULL,s);
-                 fprintf(stderr,"RIGCTL: Tok=%s\n",p);
-              }
-           } else {
-               strcat(work_buf,ser_buf);
-               fprintf(stderr,"RIGCTL: Work_buf=%s\n",work_buf);
-           }
-*/
-        } /*else {
-           usleep(100L);
-        }*/
+         }
+       } else if(numbytes<0) {
+         break;
+       }
+       //usleep(100L);
      }
+     close(client->fd);
+     cat_control--;
 }
 
 int launch_serial () {
-     fprintf(stderr,"RIGCTL: Launch Serial port %s\n",ser_port);
-
-
+     g_print("RIGCTL: Launch Serial port %s\n",ser_port);
      if(mutex_b_exists == 0) {
         mutex_b = g_new(GT_MUTEX,1);
         g_mutex_init(&mutex_b->m);
         mutex_b_exists = 1;
      }
+
+     if(mutex_busy==NULL) {
+       mutex_busy = g_new(GT_MUTEX,1);
+       g_print("launch_serial: mutex_busy=%p\n",mutex_busy);
+       g_mutex_init(&mutex_busy->m);
+     }
      
      fd = open (ser_port, O_RDWR | O_NOCTTY | O_SYNC);   
      if (fd < 0)
      {
-        fprintf (stderr,"RIGCTL: Error %d opening %s: %s\n", errno, ser_port, strerror (errno));
+        g_print("RIGCTL: Error %d opening %s: %s\n", errno, ser_port, strerror (errno));
         return 0 ;
      }
-     //set_interface_attribs (fd, B38400, 0);  // set speed to 115,200 bps, 8n1 (no parity)
-     set_interface_attribs (fd, serial_baud_rate, 0); 
-     /*
-     if(serial_parity == 1) {
-         set_interface_attribs (fd, PARENB, 0); 
-     }
-     if(serial_parity == 2) {
-         set_interface_attribs (fd, PARODD, 0); 
-     }
-     */
+
+     g_print("serial port fd=%d\n",fd);
+
+     set_interface_attribs (fd, serial_baud_rate, serial_parity); 
      set_blocking (fd, 1);                   // set no blocking
 
-     
-     serial_server_thread_id = g_thread_new( "Serial server", serial_server, NULL);
-     if( ! serial_server_thread_id )
+     CLIENT *serial_client=g_new(CLIENT,1);
+     serial_client->fd=fd;
+
+     serial_server_thread_id = g_thread_new( "Serial server", serial_server, serial_client);
+     if(!serial_server_thread_id )
      {
-       fprintf(stderr,"g_thread_new failed on serial_server\n");
+       g_free(serial_client);
+       g_print("g_thread_new failed on serial_server\n");
        return 0;
      }
      return 1;
 }
+
 // Serial Port close
 void disable_serial () {
-     fprintf(stderr,"RIGCTL: Disable Serial port %s\n",ser_port);
-     cat_control--;
+     g_print("RIGCTL: Disable Serial port %s\n",ser_port);
+     serial_running=FALSE;
 }
 
 //
@@ -3916,7 +3200,7 @@ void disable_serial () {
 //
 void launch_rigctl () {
    
-   fprintf(stderr, "LAUNCHING RIGCTL!!\n");
+   g_print( "LAUNCHING RIGCTL!!\n");
 
    rigctl_busy = 1;
    mutex_a = g_new(GT_MUTEX,1);
@@ -3931,11 +3215,15 @@ void launch_rigctl () {
    mutex_c = g_new(GT_MUTEX,1);
    g_mutex_init(&mutex_c->m);
 
+   mutex_busy = g_new(GT_MUTEX,1);
+g_print("launch_rigctl: mutex_busy=%p\n",mutex_busy);
+   g_mutex_init(&mutex_busy->m);
+
    // This routine encapsulates the thread call
    rigctl_server_thread_id = g_thread_new( "rigctl server", rigctl_server, (gpointer)(long)rigctl_port_base);
    if( ! rigctl_server_thread_id )
    {
-     fprintf(stderr,"g_thread_new failed on rigctl_server\n");
+     g_print("g_thread_new failed on rigctl_server\n");
    }
 }
 
@@ -3964,7 +3252,7 @@ void set_freqB(long long new_freqB) {
 int set_alc(gpointer data) {
     int * lcl_ptr = (int *) data;
     alc = *lcl_ptr;
-    fprintf(stderr,"RIGCTL: set_alc=%d\n",alc);
+    g_print("RIGCTL: set_alc=%d\n",alc);
     return 0;
 }
 
@@ -3990,3 +3278,5 @@ int lookup_band(int val) {
      }
      return work_int;
 }
+
+
index de45624e953ddebb662a5c412f01a80b7ffc02d5..289c2dd2e43bfc03240a8e445e41aa4381b8ec50 100644 (file)
 #include "vfo.h"
 
 int  serial_enable;
-char ser_port[64]="/dev/ttyUSB0";
-int serial_baud_rate = B4800;
+char ser_port[64]="/dev/ttyACM0";
+int serial_baud_rate = B9600;
 int serial_parity = 0; // 0=none, 1=even, 2=odd
+gboolean rigctl_debug=FALSE;
 
 static GtkWidget *parent_window=NULL;
-
 static GtkWidget *menu_b=NULL;
-
 static GtkWidget *dialog=NULL;
+static GtkWidget *serial_port_entry;
 
 static void cleanup() {
   if(dialog!=NULL) {
@@ -66,10 +66,14 @@ static void rigctl_value_changed_cb(GtkWidget *widget, gpointer data) {
 }
 
 static void serial_value_changed_cb(GtkWidget *widget, gpointer data) {
-     sprintf(ser_port,"/dev/ttyUSB%0d",(int) gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget))); 
+     sprintf(ser_port,"/dev/ttyACM%0d",(int) gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget))); 
      fprintf(stderr,"RIGCTL_MENU: New Serial port=%s\n",ser_port);
 }
 
+static void rigctl_debug_cb(GtkWidget *widget, gpointer data) {
+  rigctl_debug=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+}
+
 static void rigctl_enable_cb(GtkWidget *widget, gpointer data) {
   rigctl_enable=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
   if(rigctl_enable) {
@@ -80,6 +84,7 @@ static void rigctl_enable_cb(GtkWidget *widget, gpointer data) {
 }
 
 static void serial_enable_cb(GtkWidget *widget, gpointer data) {
+  strcpy(ser_port,gtk_entry_get_text(GTK_ENTRY(serial_port_entry)));
   serial_enable=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
   if(serial_enable) {
      if(launch_serial() == 0) {
@@ -93,7 +98,7 @@ static void serial_enable_cb(GtkWidget *widget, gpointer data) {
 // Set Baud Rate
 static void baud_rate_cb(GtkWidget *widget, gpointer data) {
    serial_baud_rate = GPOINTER_TO_INT(data);
-   fprintf(stderr,"RIGCTL_MENU: Baud rate changed\n");
+   fprintf(stderr,"RIGCTL_MENU: Baud rate changed: %d\n",serial_baud_rate);
 }
 
 // Set Parity 0=None, 1=Even, 2=0dd
@@ -130,7 +135,12 @@ void rigctl_menu(GtkWidget *parent) {
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
-
+  GtkWidget *rigctl_debug_b=gtk_check_button_new_with_label("Debug");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rigctl_debug_b), rigctl_debug);
+  gtk_widget_show(rigctl_debug_b);
+  gtk_grid_attach(GTK_GRID(grid),rigctl_debug_b,3,0,1,1);
+  g_signal_connect(rigctl_debug_b,"toggled",G_CALLBACK(rigctl_debug_cb),NULL);
   GtkWidget *rigctl_enable_b=gtk_check_button_new_with_label("Rigctl Enable");
   //gtk_widget_override_font(tx_out_of_band_b, pango_font_description_from_string("Arial 18"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rigctl_enable_b), rigctl_enable);
@@ -148,7 +158,7 @@ void rigctl_menu(GtkWidget *parent) {
   //gtk_widget_override_font(rigctl_r, pango_font_description_from_string("Arial 18"));
   gtk_spin_button_set_value(GTK_SPIN_BUTTON(rigctl_port_spinner),(double)19090);
   gtk_widget_show(rigctl_port_spinner);
-  gtk_grid_attach(GTK_GRID(grid),rigctl_port_spinner,1,2,1,1);
+  gtk_grid_attach(GTK_GRID(grid),rigctl_port_spinner,1,2,2,1);
   g_signal_connect(rigctl_port_spinner,"value_changed",G_CALLBACK(rigctl_value_changed_cb),NULL);
 
   /* Put the Serial Port stuff here */
@@ -159,14 +169,21 @@ void rigctl_menu(GtkWidget *parent) {
   g_signal_connect(serial_enable_b,"toggled",G_CALLBACK(serial_enable_cb),NULL);
 
   GtkWidget *serial_text_label=gtk_label_new(NULL);
-  gtk_label_set_markup(GTK_LABEL(serial_text_label), "<b>Serial Port: /dev/ttyUSB</b>");
+  gtk_label_set_markup(GTK_LABEL(serial_text_label), "<b>Serial Port: </b>");
   gtk_grid_attach(GTK_GRID(grid),serial_text_label,0,4,1,1);
 
+  serial_port_entry=gtk_entry_new();
+  gtk_entry_set_text(GTK_ENTRY(serial_port_entry),ser_port);
+  gtk_widget_show(serial_port_entry);
+  gtk_grid_attach(GTK_GRID(grid),serial_port_entry,1,4,2,1);
+
+/*
   GtkWidget *serial_port_spinner =gtk_spin_button_new_with_range(0,7,1);
   gtk_spin_button_set_value(GTK_SPIN_BUTTON(serial_port_spinner),(double)0);
   gtk_widget_show(serial_port_spinner);
   gtk_grid_attach(GTK_GRID(grid),serial_port_spinner,1,4,1,1);
   g_signal_connect(serial_port_spinner,"value_changed",G_CALLBACK(serial_value_changed_cb),NULL);
+*/
 
   // Serial baud rate here
   GtkWidget *baud_rate_label =gtk_label_new(NULL);
@@ -198,8 +215,8 @@ void rigctl_menu(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),baud_rate_b38400,4,5,1,1);
   g_signal_connect(baud_rate_b38400,"toggled",G_CALLBACK(baud_rate_cb),(gpointer *) B38400);
 
-  // Serial parity
 /*
+  // Serial parity
   GtkWidget *parity_label =gtk_label_new("Parity:");
   gtk_widget_show(parity_label);
   gtk_grid_attach(GTK_GRID(grid),parity_label,0,6,1,1);
@@ -223,6 +240,7 @@ void rigctl_menu(GtkWidget *parent) {
   g_signal_connect(parity_odd_b,"toggled",G_CALLBACK(parity_cb),(gpointer *) 1);
 */
 
+
   // Below stays put
   gtk_container_add(GTK_CONTAINER(content),grid);
 
index bfb2719f0d9ec30483f556b682b1ce4caa5ae5e4..64a9d27664bb5dd6c09d349199b9def289d61a5e 100644 (file)
@@ -18,7 +18,6 @@
 */
 
 #include <gtk/gtk.h>
-#include <semaphore.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -29,3 +28,5 @@ extern void disable_serial();
 
 extern int serial_baud_rate;
 extern int serial_parity;
+
+extern gboolean rigctl_debug;
index a05a45c0d0c9b443dbf05896ee1f27c905621122..56bee4952f17345e527229438d13cff13543333e 100644 (file)
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <semaphore.h>
+#include <arpa/inet.h>
 
 #include <wdsp.h>
 
@@ -40,6 +41,9 @@
 #ifdef GPIO
 #include "gpio.h"
 #endif
+#ifdef CLIENT_SERVER
+#include "client_server.h"
+#endif
 
 //static float panadapter_max=-60.0;
 //static float panadapter_min=-160.0;
@@ -396,27 +400,35 @@ void rx_panadapter_update(RECEIVER *rx) {
     }
   }
             
-  // agc
-  if(rx->agc!=AGC_OFF) {
-    double hang=0.0;
-    double thresh=0;
+#ifdef CLIENT_SERVER
+  if(clients!=NULL) {
+    cairo_select_font_face(cr, "FreeMono",
+              CAIRO_FONT_SLANT_NORMAL,
+              CAIRO_FONT_WEIGHT_NORMAL);
+    cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
+    cairo_set_font_size(cr, 22);
+    inet_ntop(AF_INET, &(((struct sockaddr_in *)&clients->address)->sin_addr),text,64);
+    cairo_text_extents(cr, text, &extents);
+    cairo_move_to(cr, ((double)display_width/2.0)-(extents.width/2.0), (double)display_height/2.0);
+    cairo_show_text(cr, text);
+  }
+#endif
 
-    GetRXAAGCHangLevel(rx->id, &hang);
-    GetRXAAGCThresh(rx->id, &thresh, 4096.0, (double)rx->sample_rate);
 
-    double knee_y=thresh+(double)adc_attenuation[rx->adc];
+  // agc
+  if(rx->agc!=AGC_OFF) {
+    double knee_y=rx->agc_thresh+(double)adc_attenuation[rx->adc];
     if (filter_board == ALEX && rx->adc == 0) knee_y += (double)(10*rx->alex_attenuation);
     knee_y = floor((rx->panadapter_high - knee_y)
                         * (double) display_height
                         / (rx->panadapter_high - rx->panadapter_low));
 
-    double hang_y=hang+(double)adc_attenuation[rx->adc];
+    double hang_y=rx->agc_hang+(double)adc_attenuation[rx->adc];
     if (filter_board == ALEX && rx->adc == 0) hang_y += (double)(10*rx->alex_attenuation);
     hang_y = floor((rx->panadapter_high - hang_y)
                         * (double) display_height
                         / (rx->panadapter_high - rx->panadapter_low));
 
-//fprintf(stderr,"hang=%f thresh=%f hang_y=%f knee_y=%f\n",rx1_hang,rx1_thresh,hang_y,knee_y);
     if(rx->agc!=AGC_MEDIUM && rx->agc!=AGC_FAST) {
       if(active) {
         cairo_set_source_rgb (cr, 1.0, 1.0, 0.0);
@@ -463,13 +475,21 @@ void rx_panadapter_update(RECEIVER *rx) {
   // signal
   double s1,s2;
 
-  samples[rx->pan]=-200.0;
-  samples[display_width-1+rx->pan]=-200.0;
+  int pan=rx->pan;
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    pan=0;
+  }
+#endif
+
+  samples[pan]=-200.0;
+  samples[display_width-1+pan]=-200.0;
   if(have_rx_gain) {
-    s1=(double)samples[rx->pan]+rx_gain_calibration-adc_attenuation[rx->adc];
+    s1=(double)samples[pan]+rx_gain_calibration-adc_attenuation[rx->adc];
   } else {
-    s1=(double)samples[rx->pan]+(double)adc_attenuation[rx->adc];
+    s1=(double)samples[pan]+(double)adc_attenuation[rx->adc];
   }
+  cairo_move_to(cr, 0.0, s1);
   if (filter_board == ALEX && rx->adc == 0) s1 += (double)(10*rx->alex_attenuation);
   if (filter_board == CHARLY25) {
     if (rx->preamp) s1 -= 18.0;
@@ -487,9 +507,9 @@ void rx_panadapter_update(RECEIVER *rx) {
   cairo_move_to(cr, 0.0, s1);
   for(i=1;i<display_width;i++) {
     if(have_rx_gain) {
-      s2=(double)samples[i+rx->pan]+rx_gain_calibration-adc_attenuation[rx->adc];
+      s2=(double)samples[i+pan]+rx_gain_calibration-adc_attenuation[rx->adc];
     } else {
-      s2=(double)samples[i+rx->pan]+(double)adc_attenuation[rx->adc];
+      s2=(double)samples[i+pan]+(double)adc_attenuation[rx->adc];
     }
     if (filter_board == ALEX && rx->adc == 0) s2 += (double)(10*rx->alex_attenuation);
     if (filter_board == CHARLY25) {
diff --git a/server_menu.c b/server_menu.c
new file mode 100644 (file)
index 0000000..5de9827
--- /dev/null
@@ -0,0 +1,121 @@
+
+/* Copyright (C)
+* 2020 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "new_menu.h"
+#include "server_menu.h"
+#include "radio.h"
+#include "client_server.h"
+
+static GtkWidget *parent_window=NULL;
+
+static GtkWidget *menu_b=NULL;
+
+static GtkWidget *dialog=NULL;
+
+static void cleanup() {
+  if(dialog!=NULL) {
+    gtk_widget_destroy(dialog);
+    dialog=NULL;
+    sub_menu=NULL;
+  }
+}
+
+static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  cleanup();
+  return TRUE;
+}
+
+static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
+  cleanup();
+  return FALSE;
+}
+
+static void server_enable_cb(GtkWidget *widget, gpointer data) {
+  hpsdr_server=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+  if(hpsdr_server) {
+     create_hpsdr_server();
+  } else {
+     destroy_hpsdr_server();
+  }
+}
+
+static void port_value_changed_cb(GtkWidget *widget, gpointer data) {
+   listen_port = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
+}
+
+void server_menu(GtkWidget *parent) {
+  parent_window=parent;
+
+  dialog=gtk_dialog_new();
+  gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - Server");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
+
+  GdkRGBA color;
+  color.red = 1.0;
+  color.green = 1.0;
+  color.blue = 1.0;
+  color.alpha = 1.0;
+  gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color);
+
+  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+  GtkWidget *grid=gtk_grid_new();
+  gtk_grid_set_column_spacing (GTK_GRID(grid),10);
+
+  GtkWidget *close_b=gtk_button_new_with_label("Close");
+  g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
+  gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
+
+
+  GtkWidget *server_enable_b=gtk_check_button_new_with_label("Server Enable");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (server_enable_b), hpsdr_server);
+  gtk_widget_show(server_enable_b);
+  gtk_grid_attach(GTK_GRID(grid),server_enable_b,0,1,1,1);
+  g_signal_connect(server_enable_b,"toggled",G_CALLBACK(server_enable_cb),NULL);
+  GtkWidget *server_port_label =gtk_label_new(NULL);
+  gtk_label_set_markup(GTK_LABEL(server_port_label), "<b>Server Port</b>");
+  gtk_widget_show(server_port_label);
+  gtk_grid_attach(GTK_GRID(grid),server_port_label,0,2,1,1);
+
+  GtkWidget *server_port_spinner =gtk_spin_button_new_with_range(45000,55000,1);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(server_port_spinner),(double)listen_port);
+  gtk_widget_show(server_port_spinner);
+  gtk_grid_attach(GTK_GRID(grid),server_port_spinner,1,2,1,1);
+  g_signal_connect(server_port_spinner,"value_changed",G_CALLBACK(port_value_changed_cb),NULL);
+
+  gtk_container_add(GTK_CONTAINER(content),grid);
+
+  sub_menu=dialog;
+
+  gtk_widget_show_all(dialog);
+
+}
+
diff --git a/server_menu.h b/server_menu.h
new file mode 100644 (file)
index 0000000..33aea78
--- /dev/null
@@ -0,0 +1,20 @@
+/* Copyright (C)
+* 2020 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+extern void server_menu(GtkWidget *parent);
index 37fa7a344a0bb70f301c15a21585440d433844e2..5fb8acf5a4a9d54f6ab9dc9eb20ab74b1e929978 100644 (file)
--- a/sliders.c
+++ b/sliders.c
@@ -56,6 +56,9 @@
 #include "property.h"
 #include "main.h"
 #include "ext.h"
+#ifdef CLIENT_SERVER
+#include "client_server.h"
+#endif
 
 static int width;
 static int height;
@@ -141,19 +144,16 @@ int scale_timeout_cb(gpointer data) {
 }
 
 static void attenuation_value_changed_cb(GtkWidget *widget, gpointer data) {
-  if (have_rx_gain) {
-    //redfined the att slider to a rx-gain slider.
-    //AD9866 contains a pga amplifier from -12 - 48 dB
-    //from -12 to 0; the rx-gain slider functions as an att slider
-    //from 0 - 48 db; the rx-gain slider functions as a gain slider with att = 0;
-    //att set to 20 for good power measurement.
-    int rx_gain_slider_value = (int)gtk_range_get_value(GTK_RANGE(attenuation_scale));
-    adc_attenuation[active_receiver->adc]= rx_gain_slider_value;
-    set_attenuation(adc_attenuation[active_receiver->adc]);
+  adc_attenuation[active_receiver->adc]=(int)gtk_range_get_value(GTK_RANGE(attenuation_scale));
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_attenuation(client_socket,active_receiver->id,(int)adc_attenuation[active_receiver->adc]);
   } else {
-    adc_attenuation[active_receiver->adc]=(int)gtk_range_get_value(GTK_RANGE(attenuation_scale));
+#endif
     set_attenuation(adc_attenuation[active_receiver->adc]);
+#ifdef CLIENT_SERVER
   }
+#endif
 }
 
 void set_attenuation_value(double value) {
@@ -277,12 +277,24 @@ static void c25_preamp_combobox_changed(GtkWidget *widget, gpointer data) {
 
 static void agcgain_value_changed_cb(GtkWidget *widget, gpointer data) {
   active_receiver->agc_gain=gtk_range_get_value(GTK_RANGE(agc_scale));
-  SetRXAAGCTop(active_receiver->id, active_receiver->agc_gain);
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_agc_gain(client_socket,active_receiver->id,(int)active_receiver->agc_gain,(int)active_receiver->agc_hang,(int)active_receiver->agc_thresh);
+  } else {
+#endif
+    SetRXAAGCTop(active_receiver->id, active_receiver->agc_gain);
+    GetRXAAGCHangLevel(active_receiver->id, &active_receiver->agc_hang);
+    GetRXAAGCThresh(active_receiver->id, &active_receiver->agc_thresh, 4096.0, (double)active_receiver->sample_rate);
+#ifdef CLIENT_SERVER
+  }
+#endif
 }
 
 void set_agc_gain(int rx,double value) {
   receiver[rx]->agc_gain=value;
   SetRXAAGCTop(receiver[rx]->id, receiver[rx]->agc_gain);
+  GetRXAAGCHangLevel(receiver[rx]->id, &receiver[rx]->agc_hang);
+  GetRXAAGCThresh(receiver[rx]->id, &receiver[rx]->agc_thresh, 4096.0, (double)receiver[rx]->sample_rate);
   if(display_sliders) {
     gtk_range_set_value (GTK_RANGE(agc_scale),receiver[rx]->agc_gain);
   } else {
@@ -322,7 +334,17 @@ void update_agc_gain(double gain) {
 
 static void afgain_value_changed_cb(GtkWidget *widget, gpointer data) {
     active_receiver->volume=gtk_range_get_value(GTK_RANGE(af_gain_scale))/100.0;
-    SetRXAPanelGain1 (active_receiver->id, active_receiver->volume);
+
+#ifdef CLIENT_SERVER
+    if(radio_is_remote) {
+      int v=(int)(active_receiver->volume*100.0);
+      send_volume(client_socket,active_receiver->id,v);
+    } else {
+#endif
+      SetRXAPanelGain1 (active_receiver->id, active_receiver->volume);
+#ifdef CLIENT_SERVER
+    }
+#endif
 }
 
 void update_af_gain() {
@@ -605,12 +627,28 @@ int update_drive(void *data) {
 
 static void squelch_value_changed_cb(GtkWidget *widget, gpointer data) {
   active_receiver->squelch=gtk_range_get_value(GTK_RANGE(widget));
-  setSquelch(active_receiver);
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_squelch(client_socket,active_receiver->id,active_receiver->squelch_enable,active_receiver->squelch);
+  } else {
+#endif
+    setSquelch(active_receiver);
+#ifdef CLIENT_SERVER
+  }
+#endif
 }
 
 static void squelch_enable_cb(GtkWidget *widget, gpointer data) {
   active_receiver->squelch_enable=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
-  setSquelch(active_receiver);
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_squelch(client_socket,active_receiver->id,active_receiver->squelch_enable,active_receiver->squelch);
+  } else {
+#endif
+    setSquelch(active_receiver);
+#ifdef CLIENT_SERVER
+  }
+#endif
 }
 
 static void compressor_value_changed_cb(GtkWidget *widget, gpointer data) {
@@ -624,7 +662,6 @@ static void compressor_enable_cb(GtkWidget *widget, gpointer data) {
   transmitter_set_compressor(transmitter,gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
   // This value is now also reflected in the VFO panel
   g_idle_add(ext_vfo_update, NULL);
-
 }
 
 void set_squelch() {
index 8b50de9ed2c6e4d4a0e4bb55b096e01cd1a96d1b..a41da2aa6c52b24858ee13f2841443113967ec7a 100644 (file)
@@ -258,11 +258,13 @@ fprintf(stderr,"Tx gains: \n");
 void soapy_discovery() {
   size_t length;
   int i,j;
+  SoapySDRKwargs input_args={};
   SoapySDRKwargs args={};
 
 fprintf(stderr,"soapy_discovery\n");
   rtlsdr_count=0;
-  SoapySDRKwargs *results = SoapySDRDevice_enumerate(NULL, &length);
+  SoapySDRKwargs_set(&input_args, "hostname", "pluto.local");
+  SoapySDRKwargs *results = SoapySDRDevice_enumerate(&input_args, &length);
 fprintf(stderr,"soapy_discovery: length=%d\n",(int)length);
   for (i = 0; i < length; i++) {
     for (size_t j = 0; j < results[i].size; j++) {
index 23ce1814084c4229a60e2c12351eb0989c2916c9..c10550ad319edfd951311bfc2bdb63354e0b49c5 100644 (file)
@@ -52,7 +52,7 @@
 #include "ext.h"
 #include "error_handler.h"
 
-static double bandwidth=2500000.0;
+static double bandwidth=2000000.0;
 
 static SoapySDRDevice *soapy_device;
 static SoapySDRStream *rx_stream;
index 991b45698eeb6303852cc2289d1d8ee6c1df8536..fa0805627322d065064702c2001cab26a50924db 100644 (file)
--- a/toolbar.c
+++ b/toolbar.c
@@ -46,6 +46,9 @@
 #include "new_menu.h"
 #include "button_text.h"
 #include "ext.h"       
+#ifdef CLIENT_SERVER
+#include "client_server.h"
+#endif
 
 int function=0;
 
@@ -82,13 +85,7 @@ static gint xit_minus_timer=-1;
 
 static gboolean rit_timer_cb(gpointer data) {
   int i=GPOINTER_TO_INT(data);
-  vfo[active_receiver->id].rit+=(i*rit_increment);
-  if(vfo[active_receiver->id].rit>10000) vfo[active_receiver->id].rit=10000;
-  if(vfo[active_receiver->id].rit<-10000) vfo[active_receiver->id].rit=-10000;
-  if(protocol==NEW_PROTOCOL) {
-    schedule_high_priority();
-  }
-  g_idle_add(ext_vfo_update,NULL);
+  vfo_rit(active_receiver->id,i);
   return TRUE;
 }
 
@@ -253,87 +250,168 @@ void noise_cb(GtkWidget *widget, gpointer data) {
 
 void ctun_cb (GtkWidget *widget, gpointer data) {
   int id=active_receiver->id;
-  vfo[id].ctun=vfo[id].ctun==1?0:1;
-  if(!vfo[id].ctun) {
-    vfo[id].offset=0;
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_ctun(client_socket,id,vfo[id].ctun==1?0:1);
+  } else {
+#endif
+    vfo[id].ctun=vfo[id].ctun==1?0:1;
+    if(!vfo[id].ctun) {
+      vfo[id].offset=0;
+    }
+    vfo[id].ctun_frequency=vfo[id].frequency;
+    set_offset(active_receiver,vfo[id].offset);
+    g_idle_add(ext_vfo_update,NULL);
+#ifdef CLIENT_SERVER
   }
-  vfo[id].ctun_frequency=vfo[id].frequency;
-  set_offset(active_receiver,vfo[id].offset);
-  g_idle_add(ext_vfo_update,NULL);
+#endif
 }
 
 static void atob_cb (GtkWidget *widget, gpointer data) {
-  vfo_a_to_b();
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_vfo(client_socket,VFO_A_TO_B);
+  } else {
+#endif
+    vfo_a_to_b();
+#ifdef CLIENT_SERVER
+  }
+#endif
 }
 
 static void btoa_cb (GtkWidget *widget, gpointer data) {
-  vfo_b_to_a();
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_vfo(client_socket,VFO_B_TO_A);
+  } else {
+#endif
+    vfo_b_to_a();
+#ifdef CLIENT_SERVER
+  }
+#endif
 }
 
 static void aswapb_cb (GtkWidget *widget, gpointer data) {
-  vfo_a_swap_b();
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_vfo(client_socket,VFO_A_SWAP_B);
+  } else {
+#endif
+    vfo_a_swap_b();
+#ifdef CLIENT_SERVER
+  }
+#endif
 }
 
 static void split_cb (GtkWidget *widget, gpointer data) {
-  g_idle_add(ext_split_toggle,NULL);
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_split(client_socket,split==1?0:1);
+  } else {
+#endif
+    g_idle_add(ext_split_toggle,NULL);
+#ifdef CLIENT_SERVER
+  }
+#endif
 }
 
 static void duplex_cb (GtkWidget *widget, gpointer data) {
   if(can_transmit && !isTransmitting()) {
-    duplex=(duplex==1)?0:1;
-    g_idle_add(ext_set_duplex,NULL);
+#ifdef CLIENT_SERVER
+    if(radio_is_remote) {
+      send_dup(client_socket,duplex==1?0:1);
+    } else {
+#endif
+      duplex=(duplex==1)?0:1;
+      g_idle_add(ext_set_duplex,NULL);
+#ifdef CLIENT_SERVER
+    }
+#endif
   }
 }
 
 static void sat_cb (GtkWidget *widget, gpointer data) {
+  int temp;
   if(can_transmit) {
     if(sat_mode==SAT_MODE) {
-      sat_mode=SAT_NONE;
+      temp=SAT_NONE;
     } else {
-      sat_mode=SAT_MODE;
+      temp=SAT_MODE;
     }
-    g_idle_add(ext_vfo_update,NULL);
+#ifdef CLIENT_SERVER
+    if(radio_is_remote) {
+      send_sat(client_socket,temp);
+    } else {
+#endif
+      sat_mode=temp;
+      g_idle_add(ext_vfo_update,NULL);
+#ifdef CLIENT_SERVER
+    }
+#endif
   }
 }
 
 static void rsat_cb (GtkWidget *widget, gpointer data) {
+  int temp;
   if(can_transmit) {
     if(sat_mode==RSAT_MODE) {
-      sat_mode=SAT_NONE;
+      temp=SAT_NONE;
     } else {
-      sat_mode=RSAT_MODE;
+      temp=RSAT_MODE;
     }
-    g_idle_add(ext_vfo_update,NULL);
+#ifdef CLIENT_SERVER
+    if(radio_is_remote) {
+      send_sat(client_socket,temp);
+    } else {
+#endif
+      sat_mode=temp;
+      g_idle_add(ext_vfo_update,NULL);
+#ifdef CLIENT_SERVER
+    }
+#endif
   }
 }
 
 static void rit_enable_cb(GtkWidget *widget, gpointer data) {
-  vfo[active_receiver->id].rit_enabled=vfo[active_receiver->id].rit_enabled==1?0:1;
-  if(protocol==NEW_PROTOCOL) {
-    schedule_high_priority();
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_rit_update(client_socket,active_receiver->id);
+  } else {
+#endif
+    vfo_rit_update(active_receiver->id);
+#ifdef CLIENT_SERVER
   }
-  g_idle_add(ext_vfo_update,NULL);
+#endif
 }
 
 static void rit_cb(GtkWidget *widget, gpointer data) {
   int i=GPOINTER_TO_INT(data);
-  vfo[active_receiver->id].rit+=i*rit_increment;
-  if(vfo[active_receiver->id].rit>10000) vfo[active_receiver->id].rit=10000;
-  if(vfo[active_receiver->id].rit<-10000) vfo[active_receiver->id].rit=-10000;
-  if(protocol==NEW_PROTOCOL) {
-    schedule_high_priority();
-  }
-  g_idle_add(ext_vfo_update,NULL);
-  if(i<0) {
-    rit_minus_timer=g_timeout_add(200,rit_timer_cb,GINT_TO_POINTER(i));
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_rit(client_socket,active_receiver->id,i);
   } else {
-    rit_plus_timer=g_timeout_add(200,rit_timer_cb,GINT_TO_POINTER(i));
+#endif
+    vfo_rit(active_receiver->id,i);
+    if(i<0) {
+      rit_minus_timer=g_timeout_add(200,rit_timer_cb,GINT_TO_POINTER(i));
+    } else {
+      rit_plus_timer=g_timeout_add(200,rit_timer_cb,GINT_TO_POINTER(i));
+    }
+#ifdef CLIENT_SERVER
   }
+#endif
 }
 
 static void rit_clear_cb(GtkWidget *widget, gpointer data) {
-  vfo[active_receiver->id].rit=0;
-  g_idle_add(ext_vfo_update,NULL);
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_rit_clear(client_socket,active_receiver->id);
+  } else {
+#endif
+    vfo_rit_clear(active_receiver->id);
+#ifdef CLIENT_SERVER
+  }
+#endif
 }
 
 static void xit_enable_cb(GtkWidget *widget, gpointer data) {
@@ -405,7 +483,7 @@ static void yes_cb(GtkWidget *widget, gpointer data) {
 
 static void halt_cb(GtkWidget *widget, gpointer data) {
   stop();
-  system("shutdown -h -P now");
+  int rc=system("shutdown -h -P now");
   _exit(0);
 }
 
@@ -453,8 +531,16 @@ static void exit_cb(GtkWidget *widget, gpointer data) {
 }
 
 void lock_cb(GtkWidget *widget, gpointer data) {
-  locked=locked==1?0:1;
-  g_idle_add(ext_vfo_update,NULL);
+#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
 }
 
 void mox_cb(GtkWidget *widget, gpointer data) {
index 8487fac872a6de15072ca681cd9e4c57bc056f22..63acc33a105fb98802d03c9ff682a6f9760d79f8 100644 (file)
--- a/update.c
+++ b/update.c
@@ -23,7 +23,7 @@ int check_update() {
 
   FILE* f=fopen("latest","r");
   if(f) {
-    fgets(new_version,sizeof(new_version),f);
+    char *c=fgets(new_version,sizeof(new_version),f);
     fclose(f);
   } else {
     fprintf(stderr,"check_update: could not read latest version\n");
diff --git a/vfo.c b/vfo.c
index 16a00f7baaf100fb999fa5aca203f8b42d4e3fb1..78fcd529a630e1220deb0ae602f57a503948317b 100644 (file)
--- a/vfo.c
+++ b/vfo.c
@@ -52,6 +52,9 @@
 #include "wdsp.h"
 #include "new_menu.h"
 #include "rigctl.h"
+#ifdef CLIENT_SERVER
+#include "client_server.h"
+#endif
 #include "ext.h"
 
 static GtkWidget *parent_window;
@@ -61,8 +64,8 @@ static int my_height;
 static GtkWidget *vfo_panel;
 static cairo_surface_t *vfo_surface = NULL;
 
-int steps[]={1,10,25,50,100,250,500,1000,2500,5000,6250,9000,10000,12500,15000,20000,25000,30000,50000,100000,0};
-char *step_labels[]={"1Hz","10Hz","25Hz","50Hz","100Hz","250Hz","500Hz","1kHz","2.5kHz","5kHz","6.25kHz","9kHz","10kHz","12.5kHz","15kHz","20kHz","25kHz","30kHz","50kHz","100kHz",0};
+int steps[]={1,10,25,50,100,250,500,1000,5000,9000,10000,100000,250000,500000,1000000,0};
+char *step_labels[]={"1Hz","10Hz","25Hz","50Hz","100Hz","250Hz","500Hz","1kHz","5kHz","9kHz","10kHz","100kHz","250KHz","500KHz","1MHz",0};
 
 static GtkWidget* menu=NULL;
 static GtkWidget* band_menu=NULL;
@@ -263,10 +266,15 @@ void vfo_xvtr_changed() {
   }
 }
 
-void vfo_band_changed(int b) {
+void vfo_band_changed(int id,int b) {
   BANDSTACK *bandstack;
 
-  int id=active_receiver->id;
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_band(client_socket,id,b);
+    return;
+  }
+#endif
 
   if(id==0) {
     vfo_save_bandstack();
@@ -390,6 +398,13 @@ void vfo_bandstack_changed(int b) {
 
 void vfo_mode_changed(int m) {
   int id=active_receiver->id;
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_mode(client_socket,id,m);
+    return;
+  }
+#endif
+
   vfo[id].mode=m;
 //
 // Change to the filter/NR combination stored for this mode
@@ -432,6 +447,12 @@ void vfo_mode_changed(int m) {
 
 void vfo_filter_changed(int f) {
   int id=active_receiver->id;
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_filter(client_socket,id,f);
+    return;
+  }
+#endif
 
   // store changed filter in the mode settings
   mode_settings[vfo[id].mode].filter = f;
@@ -545,6 +566,14 @@ void vfo_step(int steps) {
   int sid;
   RECEIVER *other_receiver;
 
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    //send_vfo_step(client_socket,id,steps);
+    update_vfo_step(id,steps);
+    return;
+  }
+#endif
+
   if(!locked) {
 
     if(vfo[id].ctun) {
@@ -660,12 +689,19 @@ void vfo_id_step(int id, int steps) {
   }
 }
 
-void vfo_move(long long hz,int round) {
-  int id=active_receiver->id;
+void vfo_id_move(int id,long long hz,int round) {
   long long delta;
   int sid;
   RECEIVER *other_receiver;
 
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    //send_vfo_move(client_socket,id,hz,round);
+    update_vfo_move(id,hz,round);
+    return;
+  }
+#endif
+
   if(!locked) {
     if(vfo[id].ctun) {
       // don't let ctun go beyond end of passband
@@ -726,11 +762,15 @@ void vfo_move(long long hz,int round) {
         }
         break;
     }
-    receiver_frequency_changed(active_receiver);
+    receiver_frequency_changed(receiver[id]);
     g_idle_add(ext_vfo_update,NULL);
   }
 }
 
+void vfo_move(long long hz,int round) {
+  vfo_id_move(active_receiver->id,hz,round);
+}
+
 void vfo_move_to(long long hz) {
   // hz is the offset from the min displayed frequency
   int id=active_receiver->id;
@@ -741,6 +781,13 @@ void vfo_move_to(long long hz) {
   int sid;
   RECEIVER *other_receiver;
 
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    send_vfo_move_to(client_socket,id,hz);
+    return;
+  }
+#endif
+
   if(vfo[id].mode!=modeCWL && vfo[id].mode!=modeCWU) {
     offset=(hz/step)*step;
   }
@@ -1232,3 +1279,28 @@ long long get_tx_freq() {
     return vfo[txvfo].frequency;
   }
 }
+void vfo_rit_update(int rx) {
+  vfo[receiver[rx]->id].rit_enabled=vfo[receiver[rx]->id].rit_enabled==1?0:1;
+  receiver_frequency_changed(receiver[rx]);
+  g_idle_add(ext_vfo_update, NULL);
+}
+
+void vfo_rit_clear(int rx) {
+  vfo[receiver[rx]->id].rit=0;
+  receiver_frequency_changed(receiver[rx]);
+  g_idle_add(ext_vfo_update, NULL);
+}
+
+void vfo_rit(int rx,int i) {
+  double value=(double)vfo[receiver[rx]->id].rit;
+  value+=(double)(i*rit_increment);
+  if(value<-10000.0) {
+    value=-10000.0;
+  } else if(value>10000.0) {
+    value=10000.0;
+  }
+  vfo[receiver[rx]->id].rit=(int)value;
+  receiver_frequency_changed(receiver[rx]);
+  g_idle_add(ext_vfo_update,NULL);
+}
+
diff --git a/vfo.h b/vfo.h
index 9efd1b51825a76e065db48cf50b307627c274f5b..4204c3a34a90fe67275609812852f978c11f5170 100644 (file)
--- a/vfo.h
+++ b/vfo.h
@@ -72,6 +72,7 @@ extern GtkWidget* vfo_init(int width,int height,GtkWidget *parent);
 extern void vfo_step(int steps);
 extern void vfo_id_step(int id, int steps);
 extern void vfo_move(long long hz,int round);
+extern void vfo_id_move(int id,long long hz,int round);
 extern void vfo_move_to(long long hz);
 extern void vfo_update();
 extern void set_frequency();
@@ -81,7 +82,7 @@ extern void vfo_restore_state();
 extern void modesettings_save_state();
 extern void modesettings_restore_state();
 
-extern void vfo_band_changed(int b);
+extern void vfo_band_changed(int id,int b);
 extern void vfo_bandstack_changed(int b);
 extern void vfo_mode_changed(int m);
 extern void vfo_filter_changed(int f);
@@ -94,4 +95,9 @@ extern int get_tx_mode();
 extern long long get_tx_freq();
 
 extern void vfo_xvtr_changed();
+
+extern void vfo_rit_update(int rx);
+extern void vfo_rit_clear(int rx);
+extern void vfo_rit(int rx,int i);
+
 #endif
index 47ad316a99f9c8b34c447890d6262c0fd3dce5a8..c8689895ff1fb28b28fd7eb7f4b542b4bcb8ea0c 100644 (file)
@@ -150,10 +150,18 @@ static gboolean freqent_select_cb (GtkWidget *widget, gpointer data) {
       f = ((long long)(atof(buffer)*mult)+5)/10;
       sprintf(output, "<big>%lld</big>", f);
       gtk_label_set_markup (GTK_LABEL (label), output);
-      fp=g_new(SET_FREQUENCY,1);
-      fp->vfo=v;
-      fp->frequency = f;
-      g_idle_add(ext_set_frequency, fp);
+#ifdef CLIENT_SERVER
+      if(radio_is_remote) {
+        send_vfo_frequency(client_socket,active_receiver->id,f);
+      } else {
+#endif
+        fp=g_new(SET_FREQUENCY,1);
+        fp->vfo=v;
+        fp->frequency = f;
+        g_idle_add(ext_set_frequency, fp);
+#ifdef CLIENT_SERVER
+      }
+#endif
       set = 1;
     }
   }
index 8166d0883ce898bf472f9ccc4e13ad1f7df59721..479398c4ae8e7c0d1bbeb1f2098260b8496b801d 100644 (file)
@@ -27,6 +27,9 @@
 #include "radio.h"
 #include "vfo.h"
 #include "waterfall.h"
+#ifdef CLIENT_SERVER
+#include "client_server.h"
+#endif
 
 
 static int colorLowR=0; // black
@@ -171,11 +174,18 @@ void waterfall_update(RECEIVER *rx) {
     unsigned char *p;
     p=pixels;
     samples=rx->pixel_samples;
+    int pan=rx->pan;
+#ifdef CLIENT_SERVER
+    if(radio_is_remote) {
+      pan=0;
+    }
+#endif
+
     for(i=0;i<width;i++) {
             if(have_rx_gain) {
-              sample=samples[i+rx->pan]+(float)(rx_gain_calibration-adc_attenuation[rx->adc]);
+              sample=samples[i+pan]+(float)(rx_gain_calibration-adc_attenuation[rx->adc]);
             } else {
-              sample=samples[i+rx->pan]+(float)adc_attenuation[rx->adc];
+              sample=samples[i+pan]+(float)adc_attenuation[rx->adc];
             }
             average+=(int)sample;
             if(sample<(float)rx->waterfall_low) {
index 3fc6bc5774dab632f82e0cd9d999a3a4753b668a..8d46e311f38463637b1d30b61f0396d292fabe4a 100644 (file)
--- a/zoompan.c
+++ b/zoompan.c
@@ -29,6 +29,9 @@
 #include "vfo.h"
 #include "sliders.h"
 #include "zoompan.h"
+#ifdef CLIENT_SERVER
+#include "client_server.h"
+#endif
 
 static int width;
 static int height;
@@ -36,41 +39,61 @@ static int height;
 static GtkWidget *zoompan;
 static GtkWidget *zoom_label;
 static GtkWidget *zoom_scale;
+static gulong zoom_signal_id;
 static GtkWidget *pan_label;
 static GtkWidget *pan_scale;
+static gulong pan_signal_id;
+static GMutex pan_zoom_mutex;
 
 static GdkRGBA white;
 static GdkRGBA gray;
 
 int zoompan_active_receiver_changed(void *data) {
   if(display_zoompan) {
+    g_mutex_lock(&pan_zoom_mutex);
     gtk_range_set_value(GTK_RANGE(zoom_scale),active_receiver->zoom);
     gtk_range_set_range(GTK_RANGE(pan_scale),0.0,(double)(active_receiver->zoom==1?active_receiver->pixels:active_receiver->pixels-active_receiver->width));
     gtk_range_set_value (GTK_RANGE(pan_scale),active_receiver->pan);
     if(active_receiver->zoom == 1) {
       gtk_widget_set_sensitive(pan_scale, FALSE);
     }
+    g_mutex_unlock(&pan_zoom_mutex);
   }
   return FALSE;
 }
 
 static void zoom_value_changed_cb(GtkWidget *widget, gpointer data) {
+g_print("zoom_value_changed_cb\n");
+  g_mutex_lock(&pan_zoom_mutex);
   g_mutex_lock(&active_receiver->display_mutex);
-  receiver_change_zoom(active_receiver,gtk_range_get_value(GTK_RANGE(zoom_scale)));
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    int zoom=(int)gtk_range_get_value(GTK_RANGE(zoom_scale));
+    active_receiver->zoom=zoom;
+    send_zoom(client_socket,active_receiver->id,zoom);
+  } else {
+#endif
+    receiver_change_zoom(active_receiver,gtk_range_get_value(GTK_RANGE(zoom_scale)));
+#ifdef CLIENT_SERVER
+  }
+#endif
+  g_signal_handler_block(G_OBJECT(pan_scale),pan_signal_id);
   gtk_range_set_range(GTK_RANGE(pan_scale),0.0,(double)(active_receiver->zoom==1?active_receiver->pixels:active_receiver->pixels-active_receiver->width));
   gtk_range_set_value (GTK_RANGE(pan_scale),active_receiver->pan);
+  g_signal_handler_unblock(G_OBJECT(pan_scale),pan_signal_id);
   if(active_receiver->zoom==1) {
     gtk_widget_set_sensitive(pan_scale, FALSE);
   } else {
     gtk_widget_set_sensitive(pan_scale, TRUE);
   }
   g_mutex_unlock(&active_receiver->display_mutex);
+  g_mutex_unlock(&pan_zoom_mutex);
   vfo_update();
 }
 
 void set_zoom(int rx,double value) {
+g_print("set_zoom: %f\n",value);
   receiver[rx]->zoom=value;
-  receiver_change_zoom(active_receiver,value);
   if(display_zoompan) {
     gtk_range_set_value (GTK_RANGE(zoom_scale),receiver[rx]->zoom);
   } else {
@@ -104,7 +127,20 @@ void set_zoom(int rx,double value) {
   vfo_update();
 }
 
+void remote_set_zoom(int rx,double value) {
+g_print("remote_set_zoom: rx=%d zoom=%f\n",rx,value);
+  g_mutex_lock(&pan_zoom_mutex);
+  g_signal_handler_block(G_OBJECT(zoom_scale),zoom_signal_id);
+  g_signal_handler_block(G_OBJECT(pan_scale),pan_signal_id);
+  set_zoom(rx,value);
+  g_signal_handler_unblock(G_OBJECT(pan_scale),pan_signal_id);
+  g_signal_handler_unblock(G_OBJECT(zoom_scale),zoom_signal_id);
+  g_mutex_unlock(&pan_zoom_mutex);
+g_print("remote_set_zoom: EXIT\n");
+}
+
 void update_zoom(double zoom) {
+g_print("update_zoom: %f\n",zoom);
   int z=active_receiver->zoom+(int)zoom;
   if(z>MAX_ZOOM) z=MAX_ZOOM;
   if(z<1) z=1;
@@ -112,10 +148,22 @@ void update_zoom(double zoom) {
 }
 
 static void pan_value_changed_cb(GtkWidget *widget, gpointer data) {
+g_print("pan_value_changed_cb\n");
+  g_mutex_lock(&pan_zoom_mutex);
+#ifdef CLIENT_SERVER
+  if(radio_is_remote) {
+    int pan=(int)gtk_range_get_value(GTK_RANGE(pan_scale));
+    send_pan(client_socket,active_receiver->id,pan);
+    g_mutex_unlock(&pan_zoom_mutex);
+    return;
+  }
+#endif
   receiver_change_pan(active_receiver,gtk_range_get_value(GTK_RANGE(pan_scale)));
+  g_mutex_unlock(&pan_zoom_mutex);
 }
 
 void set_pan(int rx,double value) {
+g_print("set_pan: %f\n",value);
   receiver[rx]->pan=(int)value;
   if(display_zoompan) {
     gtk_range_set_value (GTK_RANGE(pan_scale),receiver[rx]->pan);
@@ -149,13 +197,26 @@ void set_pan(int rx,double value) {
   }
 }
 
+void remote_set_pan(int rx,double value) {
+g_print("remote_set_pan: rx=%d pan=%f\n",rx,value);
+  g_mutex_lock(&pan_zoom_mutex);
+  g_signal_handler_block(G_OBJECT(pan_scale),pan_signal_id);
+  gtk_range_set_range(GTK_RANGE(pan_scale),0.0,(double)(receiver[rx]->zoom==1?receiver[rx]->pixels:receiver[rx]->pixels-receiver[rx]->width));
+  set_pan(rx,value);
+  g_signal_handler_unblock(G_OBJECT(pan_scale),pan_signal_id);
+  g_mutex_unlock(&pan_zoom_mutex);
+g_print("remote_set_pan: EXIT\n");
+}
+
 void update_pan(double pan) {
+  g_mutex_lock(&pan_zoom_mutex);
   if(active_receiver->zoom>1) {
     int p=active_receiver->pan+(int)pan;
     if(p<0) p=0;
     if(p>(active_receiver->pixels-active_receiver->width)) p=active_receiver->pixels-active_receiver->width;
     set_pan(active_receiver->id,(double)p);
   }
+  g_mutex_lock(&pan_zoom_mutex);
 }
 
 GtkWidget *zoompan_init(int my_width, int my_height) {
@@ -180,25 +241,27 @@ fprintf(stderr,"zoompan_init: width=%d height=%d\n", width,height);
   gtk_range_set_value (GTK_RANGE(zoom_scale),active_receiver->zoom);
   gtk_widget_show(zoom_scale);
   gtk_grid_attach(GTK_GRID(zoompan),zoom_scale,1,0,2,1);
-  g_signal_connect(G_OBJECT(zoom_scale),"value_changed",G_CALLBACK(zoom_value_changed_cb),NULL);
+  zoom_signal_id=g_signal_connect(G_OBJECT(zoom_scale),"value_changed",G_CALLBACK(zoom_value_changed_cb),NULL);
 
   pan_label=gtk_label_new("Pan:");
   gtk_widget_override_font(pan_label, pango_font_description_from_string("Sans 10"));
   gtk_widget_show(pan_label);
   gtk_grid_attach(GTK_GRID(zoompan),pan_label,3,0,1,1);
 
-  pan_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0,active_receiver->zoom==1?active_receiver->pixels:active_receiver->pixels-active_receiver->width,1.0);
+  pan_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0,active_receiver->zoom==1?active_receiver->width:active_receiver->width*(active_receiver->zoom-1),1.0);
   gtk_widget_override_font(pan_scale, pango_font_description_from_string("Sans 10"));
   gtk_scale_set_draw_value (GTK_SCALE(pan_scale), FALSE);
   gtk_range_set_increments (GTK_RANGE(pan_scale),10.0,10.0);
   gtk_range_set_value (GTK_RANGE(pan_scale),active_receiver->pan);
   gtk_widget_show(pan_scale);
   gtk_grid_attach(GTK_GRID(zoompan),pan_scale,4,0,5,1);
-  g_signal_connect(G_OBJECT(pan_scale),"value_changed",G_CALLBACK(pan_value_changed_cb),NULL);
+  pan_signal_id=g_signal_connect(G_OBJECT(pan_scale),"value_changed",G_CALLBACK(pan_value_changed_cb),NULL);
 
   if(active_receiver->zoom == 1) {
     gtk_widget_set_sensitive(pan_scale, FALSE);
   }
 
+  g_mutex_init(&pan_zoom_mutex);
+
   return zoompan;
 }
index 833d6f7b04d629fa26d545a6997cb94a0cbd493e..c4f36df35df0d151686b656bf5facb751f393aa3 100644 (file)
--- a/zoompan.h
+++ b/zoompan.h
@@ -28,4 +28,7 @@ extern void update_zoom(double zoom);
 
 extern void set_pan(int rx,double value);
 extern void set_zoom(int rx,double value);
+
+extern void remote_set_pan(int rx,double value);
+extern void remote_set_zoom(int rx,double value);
 #endif