Logo Search packages:      
Sourcecode: baycomusb version File versions  Download package

main.c

/*****************************************************************************/

/*
 *      main.c  --  Trx Control Application.
 *
 *      Copyright (C) 2000-2001
 *        Thomas Sailer (t.sailer@alumni.ethz.ch)
 *
 *      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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*****************************************************************************/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>

#include <glib.h>

#include "interface.h"
#include "support.h"
#include "signalhist.h"
#include "callbacks.h"

#ifndef WIN32
#include <sys/socket.h>
#include <sys/ioctl.h>
#endif

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#ifdef HAVE_GETOPT_H
#include <getopt.h>
#else
#include "getopt.h"
#endif

#include "trxapp.h"
#include "trxapi.h"
#include "widgets.h"

/* ---------------------------------------------------------------------- */

#include "option1.xpm"
#include "option2.xpm"

/* ---------------------------------------------------------------------- */

static GtkWidget *mainwindow, *terminalwindow, *chmemorywindow, *chprogwindow, *freqlistwindow, *newstnwindow;
static GtkWidget *modemselectwindow, *configwindow, *dtmfwindow, *spkscopewindow, *spkspectrumwindow;
static GtkWidget *micscopewindow, *micspectrumwindow, *paramwindow, *audiopwrwindow;
static unsigned int ledstatus = 0;

static struct {
      struct trxapi *trx;
        const struct trxapi_description *desc;
      trxapi_mode_t mode;
      float rssimul;
} trx = { NULL, NULL, trxapi_mode_unspec };

static struct {
      trxapi_frequency_t rx, tx;
      guint fchginhibit;
} freq = { 0, 0, 0 };

static struct {
      int sel;
      int del;
} freql = { -1, -1 };

static int selectmodem_sel = -1;
static unsigned int notebook_pagemask = 0;
static unsigned long rxuartptr = 0;
static unsigned int pttmask = 0;
#define PTTMASK_MANUAL 1
#define PTTMASK_1750   2
#define PTTMASK_DTMF   4

static struct {
      unsigned char enaptt;
} params = { 0 };

static struct {
        unsigned int lptr;
        unsigned char rxline[256];
} uartline = { 0, };

static struct {
        int rx, tx;
} chmem[10];

/* ---------------------------------------------------------------------- */

static void updatechmemwindow(void);

/* ---------------------------------------------------------------------- */

static void paramstodialog(void)
{
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtk_object_get_data(GTK_OBJECT(paramwindow), "paramenablepttpkt")), params.enaptt);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "buttonptt")), trx.mode == trxapi_mode_audio || (trx.mode == trxapi_mode_packet && params.enaptt));
}

static void trxnewmode(trxapi_mode_t newmode)
{
      if (trx.mode != newmode) {
            gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "audio")), newmode == trxapi_mode_audio);
            gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "buttonptt")), newmode == trxapi_mode_audio || (newmode == trxapi_mode_packet && params.enaptt));
            gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "button1750")), newmode == trxapi_mode_audio);
      }
      trx.mode = newmode;
}

static void updatepttmask(void)
{
      if (trx.trx == NULL)
            return;
      if (trxapi_set_ptt(trx.trx, !!pttmask))
            lprintf(1, "trxapi_set_ptt error\n");
}

static void closetrx(void)
{
      if (trx.trx)
            trxapi_close(trx.trx);
      trx.trx = NULL;
      trx.desc = NULL;
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "modemconfig")), FALSE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "audio")), FALSE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "expert")), FALSE);
      trxnewmode(trxapi_mode_unspec);
      pttmask = 0;
      updatepttmask();
}

static void newtrx(struct trxapi *api, const struct trxapi_description *desc)
{
      const struct trxapi_baycomusb_adapter_audio_devs *audiodevs;
      float f;
      unsigned int i;
      char buf[1024];
      GtkSpinButton *rxqrg, *txqrg;
      trxapi_frequency_t fmin, fmax, fstep;

      closetrx();
      trx.trx = api;
      trx.desc = desc;
      /* set RSSI limits */
      f = desc->rssimax - desc->rssimin;
      if (f < 0.0001)
            trx.rssimul = 0;
      else
            trx.rssimul = 255.0 / f;
      gtk_progress_configure(GTK_PROGRESS(gtk_object_get_data(GTK_OBJECT(mainwindow), "rssi")), 
                         desc->rssimin, desc->rssimin, desc->rssimax);
      /* set rxuart pointer to current value */
      rxuartptr = 0;
      trxapi_uart_receive(trx.trx, &rxuartptr, buf, sizeof(buf));
      /* clear UART received line */
      uartline.lptr = 0;
      /* clear T7F memory */
      for (i = 0; i < 10; i++)
            chmem[i].rx = chmem[i].tx = -1;
      updatechmemwindow();
      /* cause T7F to transmit channel memory */
      if (trxapi_uart_send(trx.trx, "\rE\r"))
            lprintf(1, "trxapi_uart_send error\n");
      /* set frequency limits */    
      rxqrg = GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(mainwindow), "rxqrg"));
      txqrg = GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(mainwindow), "txqrg"));
      fmin = ~0ULL;
      fmax = 0ULL;
      fstep = 1000000ULL;
      for (i = 0; i < desc->nrrxbands; i++) {
            if (desc->rxbands[i].low < fmin)
                  fmin = desc->rxbands[i].low;
            if (desc->rxbands[i].high > fmax)
                  fmax = desc->rxbands[i].high;
            if (fstep > desc->rxbands[i].step)
                  fstep = desc->rxbands[i].step;
      }
      gtk_spin_button_set_adjustment(rxqrg, GTK_ADJUSTMENT(gtk_adjustment_new(fmin * (1.0 / 1000000.0), fmin * (1.0 / 1000000.0),
                                                            fmax * (1.0 / 1000000.0), fstep * (1.0 / 1000000.0), 1, 1)));
      fmin = ~0ULL;
      fmax = 0ULL;
      fstep = 1000000ULL;
      for (i = 0; i < desc->nrtxbands; i++) {
            if (desc->txbands[i].low < fmin)
                  fmin = desc->txbands[i].low;
            if (desc->txbands[i].high > fmax)
                  fmax = desc->txbands[i].high;
            if (fstep > desc->txbands[i].step)
                  fstep = desc->txbands[i].step;
      }
      gtk_spin_button_set_adjustment(txqrg, GTK_ADJUSTMENT(gtk_adjustment_new(fmin * (1.0 / 1000000.0), fmin * (1.0 / 1000000.0),
                                                            fmax * (1.0 / 1000000.0), fstep * (1.0 / 1000000.0), 1, 1)));
      gtk_widget_set_sensitive(GTK_WIDGET(rxqrg), FALSE);
      gtk_widget_set_sensitive(GTK_WIDGET(txqrg), FALSE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "stnname")), FALSE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "modemconfig")), TRUE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "expert")), TRUE);
      freq.rx = freq.tx = 0;
      paramstodialog();
      pttmask = 0;
      updatepttmask();
      /* Update dialog with list of audio devices */
      audiodevs = trxapi_baycomusb_adapter_get_audiodevices(trx.trx);
      if (audiodevs) {
            GList *list;
            list = NULL;
            for (i = 0; i < audiodevs->nraudiodevsin; i++)
                  list = g_list_append(list, audiodevs->audiodevsin[i]);
            if (list) {
                  gtk_combo_set_popdown_strings(GTK_COMBO(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptaudiodevin")), list);
                  g_list_free(list);
            }
            list = NULL;
            for (i = 0; i < audiodevs->nraudiodevsout; i++)
                  list = g_list_append(list, audiodevs->audiodevsout[i]);
            if (list) {
                  gtk_combo_set_popdown_strings(GTK_COMBO(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptaudiodevout")), list);
                  g_list_free(list);
            }
      }
}

static void trxopenbyindex(unsigned int index)
{
      struct trxapi *api;
        const struct trxapi_description *desc;

        if (!(api = trxapi_open_byindex(index)))
                return;
      if (!(desc = trxapi_get_description(api))) {
                trxapi_close(api);
            return;
      }
      newtrx(api, desc);
}

static void trxopenbymfgmodelserial(const char *mfg, const char *model, const char *serial)
{
      struct trxapi *api;
        const struct trxapi_description *desc;
      unsigned int i;

      for (i = 0; ; i++) {
            if (!(api = trxapi_open_byindex(i)))
                  return;
            if (!(desc = trxapi_get_description(api))) {
                  trxapi_close(api);
                  continue;
            }
            if (!strcmp(desc->manufacturer, mfg) && !strcmp(desc->model, model) && !strcmp(desc->instid, serial)) {
                  newtrx(api, desc);
                  return;
            }
            trxapi_close(api);
      }
}

/* ---------------------------------------------------------------------- */

static void setled(GtkPixmap *pixmap, int on)
{
      GdkColormap *colormap;
      GdkPixmap *gdkpixmap;
      GdkBitmap *mask;

      colormap = gtk_widget_get_colormap(mainwindow);
      gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL, colormap, &mask, NULL, on ? option2_xpm : option1_xpm);
      gtk_pixmap_set(pixmap, gdkpixmap, mask);
      gdk_pixmap_unref(gdkpixmap);
      gdk_bitmap_unref(mask);
}

GtkWidget* create_led_pixmap(gchar *widget_name, gchar *string1, gchar *string2, gint int1, gint int2)
{
      GtkWidget *pixmap, *wnd;
      GdkColormap *colormap;
      GdkPixmap *gdkpixmap;
      GdkBitmap *mask;

      wnd = gtk_window_new (GTK_WINDOW_TOPLEVEL);
      gtk_widget_ref(wnd);
      colormap = gtk_widget_get_colormap(wnd);
      gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL, colormap, &mask, NULL, option1_xpm);
      pixmap = gtk_pixmap_new(gdkpixmap, mask);
      gdk_pixmap_unref(gdkpixmap);
      gdk_bitmap_unref(mask);
      gtk_widget_unref(wnd);
      return pixmap;
}

/* ---------------------------------------------------------------------- */

static void updatechmemwindow(void)
{
        char buf[8] = "ch0a";
        char buf2[32];
        unsigned int i;

        for (i = 0; i < 10; i++) {
                buf[2] = '0'+i;
                buf[3] = 'a';
                if (chmem[i].rx == -1)
                        snprintf(buf2, sizeof(buf2), "-");
                else
                        snprintf(buf2, sizeof(buf2), "%8.4fMHz", 430+chmem[i].rx * 0.0125);
                gtk_label_set_text(GTK_LABEL(gtk_object_get_data(GTK_OBJECT(chmemorywindow), buf)), buf2);
                buf[3] = 'b';
                if (chmem[i].tx == -1)
                        snprintf(buf2, sizeof(buf2), "-");
                else
                        snprintf(buf2, sizeof(buf2), "%8.4fMHz", 430+chmem[i].tx * 0.0125);
                gtk_label_set_text(GTK_LABEL(gtk_object_get_data(GTK_OBJECT(chmemorywindow), buf)), buf2);
                buf[3] = 'c';
                if (chmem[i].rx == -1)
                        snprintf(buf2, sizeof(buf2), "-");
                else
                        snprintf(buf2, sizeof(buf2), "%8.4fMHz", 430+chmem[i].rx * 0.025);
                gtk_label_set_text(GTK_LABEL(gtk_object_get_data(GTK_OBJECT(chmemorywindow), buf)), buf2);
                buf[3] = 'd';
                if (chmem[i].tx == -1)
                        snprintf(buf2, sizeof(buf2), "-");
                else
                        snprintf(buf2, sizeof(buf2), "%8.4fMHz", 430+chmem[i].tx * 0.025);
                gtk_label_set_text(GTK_LABEL(gtk_object_get_data(GTK_OBJECT(chmemorywindow), buf)), buf2);
        }
}

static void setstns(void)
{
      GList *list = NULL;

      list = g_list_append(list, "-");
      list = stndb_list(list);
      gtk_combo_set_popdown_strings(GTK_COMBO(gtk_object_get_data(GTK_OBJECT(mainwindow), "stnname")), list);
      g_list_free(list);
      stndb_clist(GTK_CLIST(gtk_object_get_data(GTK_OBJECT(freqlistwindow), "freqlist")));
}

/* ---------------------------------------------------------------------- */

static void processuart(char *str)
{
        static int chparse = -1;
        unsigned int tx, rx;

        printf("Processuart: \"%s\"\n", str);
        if (!strcmp(str, "E")) {
                chparse = 0;
                return;
        }
        if (chparse >= 0 && sscanf(str, " %x %x", &tx, &rx) == 2) {
                chmem[chparse].rx = rx;
                chmem[chparse].tx = tx;
                chparse++;
                if (chparse > 9)
                        chparse = -1;
                updatechmemwindow();
                return;
        }
        chparse = -1;
}

/* ---------------------------------------------------------------------- */

static void on_aboutok_clicked(GtkButton *button, gpointer user_data)
{
        gtk_widget_hide(GTK_WIDGET(user_data));
        gtk_widget_destroy(GTK_WIDGET(user_data));
}

void on_about_activate(GtkMenuItem *menuitem, gpointer user_data)
{
        GtkWidget *dlg = create_aboutwindow();

        gtk_signal_connect(GTK_OBJECT(gtk_object_get_data(GTK_OBJECT(dlg), "aboutok")), 
                           "clicked", GTK_SIGNAL_FUNC(on_aboutok_clicked), dlg);
        gtk_widget_show(dlg);
}

static void on_errorok_clicked(GtkButton *button, gpointer user_data)
{
        gtk_widget_hide(GTK_WIDGET(user_data));
        gtk_widget_destroy(GTK_WIDGET(user_data));
}

void error_dialog(const gchar *text)
{
        GtkWidget *dlg = create_errordialog();

        gtk_signal_connect(GTK_OBJECT(gtk_object_get_data(GTK_OBJECT(dlg), "errorok")), 
                           "clicked", GTK_SIGNAL_FUNC(on_errorok_clicked), dlg);
        gtk_label_set_text(GTK_LABEL(gtk_object_get_data(GTK_OBJECT(dlg), "errorlabel")), text);
        gtk_widget_show(dlg);
}

gboolean on_mainwindow_destroy_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
        gtk_main_quit();
        return TRUE;
}

gboolean on_mainwindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
        gtk_main_quit();
        return FALSE;
}

void on_quit_activate(GtkMenuItem *menuitem, gpointer user_data)
{
      gtk_main_quit();
}

void on_terminal_activate(GtkMenuItem *menuitem, gpointer user_data)
{
      gtk_widget_show(terminalwindow);
}

gboolean on_terminalwindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
      gtk_widget_hide(terminalwindow);
      return TRUE;
}

void on_buttonptt_toggled(GtkToggleButton *togglebutton, gpointer user_data)
{
      if (trx.trx == NULL)
            return;
      if (gtk_toggle_button_get_active(togglebutton))
            pttmask |= PTTMASK_MANUAL;
      else
            pttmask &= ~PTTMASK_MANUAL;
      updatepttmask();
}

void on_button1750_pressed(GtkButton *button, gpointer user_data)
{
      if (trx.trx == NULL)
            return;
      pttmask |= PTTMASK_1750;
      updatepttmask();
      if (trx.mode == trxapi_mode_audio) {
            if (trxapi_set_audio_dtmf(trx.trx, 16))
                  lprintf(1, "trxapi_set_audio_dtmf error\n");
      }
}


void on_button1750_released(GtkButton *button, gpointer user_data)
{
      if (trx.trx == NULL)
            return;
      pttmask &= ~PTTMASK_1750;
      updatepttmask();
      if (trx.mode == trxapi_mode_audio) {
            if (trxapi_set_audio_dtmf(trx.trx, -1))
                  lprintf(1, "trxapi_set_audio_dtmf error\n");
      }
}

gboolean on_text_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
        GtkText *txt;
        char c = event->keyval;
      char buf[2];

      buf[0] = c;
      buf[1] = 0;
        printf("on_text_keypress_event: 0x%x %c  state %u\n", event->keyval, (c >= ' ' && c <= 0x7f) ? c : '.', event->state);
      if (trx.trx == NULL)
            return FALSE;
        txt = GTK_TEXT(gtk_object_get_data(GTK_OBJECT(terminalwindow), "text"));
        if (event->keyval == GDK_Return) {
            buf[0] = '\r';
            c = '\n';
            if (!trxapi_uart_send(trx.trx, buf))
                  gtk_text_insert(txt, NULL, &(GTK_WIDGET(txt)->style->fg[GTK_WIDGET_STATE(GTK_WIDGET(txt))]), NULL, &c, 1);
            return TRUE;
        }
        if (event->keyval >= 32 && event->keyval < 128) {
            if (!trxapi_uart_send(trx.trx, buf))
                  gtk_text_insert(txt, NULL, &(GTK_WIDGET(txt)->style->fg[GTK_WIDGET_STATE(GTK_WIDGET(txt))]), NULL, &c, 1);
                return TRUE;
        }
      return FALSE;
}

gboolean on_text_key_release_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
        char c = event->keyval;

        printf("on_text_keyrelease_event: 0x%x %c  state %u\n", event->keyval, (c >= ' ' && c <= 0x7f) ? c : '.', event->state);
        return TRUE;
}

/* ---------------------------------------------------------------------- */

static void set_frequencies(trxapi_frequency_t rx, trxapi_frequency_t tx)
{
      GtkSpinButton *rxqrg, *txqrg;

      rxqrg = GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(mainwindow), "rxqrg"));
      txqrg = GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(mainwindow), "txqrg"));
      gtk_signal_disconnect_by_func(GTK_OBJECT(rxqrg), GTK_SIGNAL_FUNC(on_qrg_changed), NULL);
      gtk_signal_disconnect_by_func(GTK_OBJECT(txqrg), GTK_SIGNAL_FUNC(on_qrg_changed), NULL);
      gtk_spin_button_set_value(rxqrg, rx * (1.0 / 1000000.0));
            gtk_spin_button_set_value(txqrg, tx * (1.0 / 1000000.0));
      gtk_signal_connect(GTK_OBJECT(rxqrg), "changed", GTK_SIGNAL_FUNC(on_qrg_changed), NULL);
      gtk_signal_connect(GTK_OBJECT(txqrg), "changed", GTK_SIGNAL_FUNC(on_qrg_changed), NULL);
}

static void set_stnname(const char *name)
{
      GtkEntry *entry;

      entry = GTK_ENTRY(GTK_COMBO(gtk_object_get_data(GTK_OBJECT(mainwindow), "stnname"))->entry);
      gtk_signal_disconnect_by_func(GTK_OBJECT(entry), GTK_SIGNAL_FUNC(on_stn_changed), NULL);
      gtk_entry_set_text(entry, name);
      gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(on_stn_changed), NULL);
}

static gint fchgtimeout(gpointer user_data)
{
      freq.fchginhibit = 0;
      return FALSE;
}

static void set_station(const char *name)
{
      struct stndb_entry stnent;
      struct trxapi_baycomusb_adapter_config adaptcfg;

      if (!name)
            return;
      memset(&stnent, 0, sizeof(stnent));
      stnent.mode = -1;
      strncpy(stnent.name, name, sizeof(stnent.name));
      if (stndb_retrieve(&stnent)) {
            printf("Station \"%s\" not found in database\n", stnent.name);
            return;
      }
      if (trx.trx != NULL) {
            if (stnent.mode == trxapi_baycomusb_mode_fsk ||
                stnent.mode == trxapi_baycomusb_mode_afsk ||
                stnent.mode == trxapi_baycomusb_mode_external ||
                stnent.mode == trxapi_baycomusb_mode_audio) {
                  if (trxapi_baycomusb_adapter_get_config(trx.trx, &adaptcfg)) {
                        lprintf(1, "trxapi_baycomusb_adapter_get_config error\n");
                  } else {
                        adaptcfg.mode = stnent.mode;
                        if (stnent.mode == trxapi_baycomusb_mode_fsk) {
                              adaptcfg.bitraterx = stnent.bitraterx;
                              adaptcfg.bitratetx = stnent.bitratetx;
                        }
                        if (trxapi_baycomusb_adapter_set_config(trx.trx, &adaptcfg))
                              lprintf(1, "trxapi_baycomusb_adapter_set_config error\n");
                  }
            }
            if (trxapi_set_frequency(trx.trx, stnent.rx, stnent.tx)) {
                  lprintf(1, "trxapi_set_frequency error\n");
                  return;
            }
      }
      set_frequencies(stnent.rx, stnent.tx);
      //set_stnname(stnent.name);
      freq.rx = stnent.rx;
      freq.tx = stnent.tx;
      if (freq.fchginhibit)
            gtk_timeout_remove(freq.fchginhibit);
      freq.fchginhibit = gtk_timeout_add(3000, fchgtimeout, NULL);
}

void on_qrg_changed(GtkEditable *editable, gpointer user_data)
{
      gfloat rxqrg, txqrg;
      struct stndb_entry stnent;

      printf("on_qrg_changed\n");
      memset(&stnent, 0, sizeof(stnent));
      rxqrg = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(mainwindow), "rxqrg")));
      txqrg = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(mainwindow), "txqrg")));
      stnent.rx = rxqrg * 1000000;
      stnent.tx = txqrg * 1000000;
      stnent.rx = (stnent.rx + 50) / 100 * 100;
      stnent.tx = (stnent.tx + 50) / 100 * 100;
      if (trx.trx != NULL) {
            if (trxapi_set_frequency(trx.trx, stnent.rx, stnent.tx)) {
                  lprintf(1, "trxapi_set_frequency error\n");
                  return;
            }
      }
      freq.rx = stnent.rx;
      freq.tx = stnent.tx;
      if (freq.fchginhibit)
            gtk_timeout_remove(freq.fchginhibit);
      freq.fchginhibit = gtk_timeout_add(3000, fchgtimeout, NULL);
      stnent.mode = -1;
      if (trx.trx != NULL) {
            struct trxapi_baycomusb_adapter_config adaptcfg;

            if (trxapi_baycomusb_adapter_get_config(trx.trx, &adaptcfg)) {
                  lprintf(1, "trxapi_baycomusb_adapter_get_config error\n");
            } else {
                    stnent.mode = adaptcfg.mode;
                  stnent.bitraterx = adaptcfg.bitraterx;
                  stnent.bitratetx = adaptcfg.bitratetx;
            }
      }
      if (stndb_retrieve(&stnent) || !stnent.name[0])
            strncpy(stnent.name, "-", sizeof(stnent.name));
      set_stnname(stnent.name);
}

void on_stn_changed(GtkEditable *editable, gpointer user_data)
{
      gchar *stnname = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(gtk_object_get_data(GTK_OBJECT(mainwindow), "stnname"))->entry));

      printf("Station Name Change: %s\n", stnname);
      if (!strcmp(stnname, "-"))
            return;
      set_station(stnname);
}

/* ---------------------------------------------------------------------- */

void on_chprog_raster_toggled(GtkToggleButton *togglebutton, gpointer user_data)
{
      unsigned int raster, rx, tx;
      GtkSpinButton *rxqrg, *txqrg;
      gfloat rxv, txv;

      raster = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_object_get_data(GTK_OBJECT(chprogwindow), "raster")));
      rxqrg = GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(chprogwindow), "rxqrg"));
      txqrg = GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(chprogwindow), "txqrg"));
      rxv = gtk_spin_button_get_value_as_float(rxqrg);
      txv = gtk_spin_button_get_value_as_float(txqrg);
      if (raster) {
            rx = (rxv + (0.0125 / 2 - 430)) * (1.0 / 0.0125);
            tx = (txv + (0.0125 / 2 - 430)) * (1.0 / 0.0125);
            if (rx >= 800)
                  rx = 799;
            if (tx >= 800)
                  tx = 799;
            rxv = 430 + rx * 0.0125;
            txv = 430 + tx * 0.0125;
            gtk_spin_button_set_adjustment(rxqrg, GTK_ADJUSTMENT(gtk_adjustment_new(rxv, 430, 440, 0.0125, 1, 1)));
            gtk_spin_button_set_adjustment(txqrg, GTK_ADJUSTMENT(gtk_adjustment_new(txv, 430, 440, 0.0125, 1, 1)));
      } else {
            rx = (rxv + (0.025 / 2 - 430)) * (1.0 / 0.025);
            tx = (txv + (0.025 / 2 - 430)) * (1.0 / 0.025);
            if (rx >= 400)
                  rx = 399;
            if (tx >= 400)
                  tx = 399;
            rxv = 430 + rx * 0.025;
            txv = 430 + tx * 0.025;
            gtk_spin_button_set_adjustment(rxqrg, GTK_ADJUSTMENT(gtk_adjustment_new(rxv, 430, 440, 0.025, 1, 1)));
            gtk_spin_button_set_adjustment(txqrg, GTK_ADJUSTMENT(gtk_adjustment_new(txv, 430, 440, 0.025, 1, 1)));
      }
      gtk_spin_button_set_value(rxqrg, rxv);
      gtk_spin_button_set_value(txqrg, txv);
}

void on_chprog_channel_changed(GtkEditable *editable, gpointer user_data)
{
      unsigned int ch, raster, divmax;
      gfloat r;
      
      ch = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(chprogwindow), "channel")));
      raster = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_object_get_data(GTK_OBJECT(chprogwindow), "raster")));
      r = raster ? 0.0125 : 0.025;
      divmax = raster ? 800 : 400;
      if (ch < 10) {
            if (chmem[ch].rx >= 0 && chmem[ch].rx <= divmax)
                  gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(chprogwindow), "rxqrg")), 430 + r * chmem[ch].rx);
            if (chmem[ch].tx >= 0 && chmem[ch].tx <= divmax)
                  gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(chprogwindow), "txqrg")), 430 + r * chmem[ch].tx);
      }
}

void on_chprogok_clicked(GtkButton *button, gpointer user_data)
{
      unsigned int ch, raster, rx, tx, divmax;
      float rxqrg, txqrg, rst, rnd;
      char buf[256];

      gtk_widget_hide(chprogwindow);
      ch = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(chprogwindow), "channel")));
      raster = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_object_get_data(GTK_OBJECT(chprogwindow), "raster")));
      rxqrg = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(chprogwindow), "rxqrg")));
      txqrg = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(chprogwindow), "txqrg")));
      rnd = raster ? (0.0125 / 2 - 430) : (0.025 / 2 - 430);
      rst = raster ? (1.0 / 0.0125) : (1.0 / 0.025);
      divmax = raster ? 800 : 400;
      rx = (rxqrg - rnd) * rst;
      tx = (txqrg - rnd) * rst;
      if (rx > divmax)
            rx = divmax;
      if (tx > divmax)
            tx = divmax;
      snprintf(buf, sizeof(buf), "\rC%1d%03d%03d\rE\r", ch, tx, rx);
      if (trx.trx == NULL)
            return;
      if (trxapi_uart_send(trx.trx, buf))
            lprintf(1, "trxapi_uart_send error\n");
}

void on_chprogcancel_clicked(GtkButton *button, gpointer user_data)
{
      gtk_widget_hide(chprogwindow);
}


void on_channelwindow_activate(GtkMenuItem *menuitem, gpointer user_data)
{
      gtk_widget_show(chmemorywindow);
}


void on_progchmem_activate(GtkMenuItem *menuitem, gpointer user_data)
{
      gtk_widget_show(chprogwindow);
}

gboolean on_chmemorywindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
      gtk_widget_hide(chmemorywindow);
      return TRUE;
}

gboolean on_chprogwindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
      gtk_widget_hide(chprogwindow);
      return TRUE;
}

/* ---------------------------------------------------------------------- */

gboolean on_newstationwindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
      gtk_widget_hide(newstnwindow);
      return TRUE;
}

void on_newstnok_clicked(GtkButton *button, gpointer user_data)
{
      struct stndb_entry stnent;
      gfloat rxqrg, txqrg;
      gchar *text;
      GtkCList *clist;

      memset(&stnent, 0, sizeof(stnent));
      rxqrg = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(newstnwindow), "rxqrg")));
      txqrg = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(newstnwindow), "txqrg")));
      stnent.rx = rxqrg * 1000000;
      stnent.tx = txqrg * 1000000;
      stnent.rx = (stnent.rx + 50) / 100 * 100;
      stnent.tx = (stnent.tx + 50) / 100 * 100;
      text = gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(newstnwindow), "stnname")));
      if (!text || !*text || !strcmp(text, "-")) {
            error_dialog("Invalid Name");
            return;
      }
      strncpy(stnent.name, text, sizeof(stnent.name));
      text = gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(newstnwindow), "modeentry")));
      if (!text)
            stnent.mode = -1;
      else if (!strcmp(text, "fsk"))
            stnent.mode = trxapi_baycomusb_mode_fsk;
      else if (!strcmp(text, "afsk"))
            stnent.mode = trxapi_baycomusb_mode_afsk;
      else if (!strcmp(text, "external"))
            stnent.mode = trxapi_baycomusb_mode_external;
      else if (!strcmp(text, "audio"))
            stnent.mode = trxapi_baycomusb_mode_audio;
      else
            stnent.mode = -1;
      stnent.bitraterx = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(newstnwindow), "bitraterx")));
      stnent.bitratetx = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(newstnwindow), "bitratetx")));
      if (freql.del != -1) {
            clist = GTK_CLIST(gtk_object_get_data(GTK_OBJECT(freqlistwindow), "freqlist"));
            gtk_clist_get_text(clist, freql.del, 0, &text);
            stndb_delete(text);
      }
      freql.del = -1;
      if (stndb_write(&stnent)) {
            error_dialog("Cannot store station");
            return;
      }
      gtk_widget_hide(newstnwindow);
      setstns();
}

void on_newstncancel_clicked(GtkButton *button, gpointer user_data)
{
      gtk_widget_hide(newstnwindow);
}

void on_newstnmodeentry_changed(GtkEditable *editable, gpointer user_data)
{
      gboolean sensitive = !strcmp(gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(newstnwindow), "modeentry"))), "fsk");
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(newstnwindow), "bitraterx")), sensitive);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(newstnwindow), "bitratetx")), sensitive);
}

void on_freqlist_activate(GtkMenuItem *menuitem, gpointer user_data)
{
      gtk_widget_show(freqlistwindow);
}

gboolean on_freqlistwindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
      gtk_widget_hide(newstnwindow);
      gtk_widget_hide(freqlistwindow);
      return TRUE;
}

void on_freqlistset_clicked(GtkButton *button, gpointer user_data)
{
      gchar *text;
      GtkCList *clist;

      if (freql.sel == -1)
            return;
      clist = GTK_CLIST(gtk_object_get_data(GTK_OBJECT(freqlistwindow), "freqlist"));
      gtk_clist_get_text(clist, freql.sel, 0, &text);
      set_station(text);
      set_stnname(text);
}

void on_freqlistnew_clicked(GtkButton *button, gpointer user_data)
{
      freql.del = -1;
      gtk_widget_show(newstnwindow);
      gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(newstnwindow), "stnname")), "");
}

void on_freqlistupdate_clicked(GtkButton *button, gpointer user_data)
{
      struct stndb_entry stnent;
      gchar *text;
      GtkCList *clist;

      freql.del = freql.sel;
      gtk_widget_show(newstnwindow);
      if (freql.sel == -1)
            return;
      clist = GTK_CLIST(gtk_object_get_data(GTK_OBJECT(freqlistwindow), "freqlist"));
      gtk_clist_get_text(clist, freql.sel, 0, &text);
      memset(&stnent, 0, sizeof(stnent));
      stnent.mode = -1;
      strncpy(stnent.name, text, sizeof(stnent.name));
      if (stndb_retrieve(&stnent)) {
            printf("Cannot retrieve station \"%s\"\n", text);
            return;
      }
      gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(newstnwindow), "stnname")), stnent.name);
      gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(newstnwindow), "rxqrg")), stnent.rx*1e-6);
      gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(newstnwindow), "txqrg")), stnent.tx*1e-6);
      switch (stnent.mode) {
      case trxapi_baycomusb_mode_fsk:
            text = "fsk";
            break;

      case trxapi_baycomusb_mode_external:
            text = "external";
            break;

      case trxapi_baycomusb_mode_afsk:
            text = "afsk";
            break;

      case trxapi_baycomusb_mode_audio:
            text = "audio";
            break;

      default:
            text = "-";
            break;
      }
      gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(newstnwindow), "modeentry")), text);
      gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(newstnwindow), "bitraterx")), stnent.bitraterx);
      gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(newstnwindow), "bitratetx")), stnent.bitratetx);
}

void on_freqlistdelete_clicked(GtkButton *button, gpointer user_data)
{
      gchar *text;
      GtkCList *clist;

      if (freql.sel == -1)
            return;
      clist = GTK_CLIST(gtk_object_get_data(GTK_OBJECT(freqlistwindow), "freqlist"));
      gtk_clist_get_text(clist, freql.sel, 0, &text);
      stndb_delete(text);
      setstns();
      gtk_clist_select_row(clist, freql.sel, 0);
}

void on_freqlist_select_row(GtkCList *clist, gint row, gint column, GdkEvent *event, gpointer user_data)
{
      printf("Select row: %d\n", row);
      freql.sel = row;
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(freqlistwindow), "buttonset")), TRUE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(freqlistwindow), "buttonupdate")), TRUE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(freqlistwindow), "buttondelete")), TRUE);
}

void on_freqlist_unselect_row(GtkCList *clist, gint row, gint column, GdkEvent *event, gpointer user_data)
{
      printf("Unselect row: %d\n", row);
      freql.sel = -1;
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(freqlistwindow), "buttonset")), FALSE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(freqlistwindow), "buttonupdate")), FALSE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(freqlistwindow), "buttondelete")), FALSE);
}

/* ---------------------------------------------------------------------- */

void on_selectmodem_activate(GtkMenuItem *menuitem, gpointer user_data)
{
      struct trxapi *api;
        const struct trxapi_description *desc;
      unsigned int i;
      GtkCList *clist;
      gchar *buf[3];

      clist = GTK_CLIST(gtk_object_get_data(GTK_OBJECT(modemselectwindow), "modemlist"));
      gtk_clist_freeze(clist);
      gtk_clist_clear(clist);
      for (i = 0; ; i++) {
            if (!(api = trxapi_open_byindex(i)))
                  break;
            if (!(desc = trxapi_get_description(api))) {
                  trxapi_close(api);
                  continue;
            }
            /* explicit conversion to discard const */
            buf[0] = (char *)desc->manufacturer;
            buf[1] = (char *)desc->model;
            buf[2] = (char *)desc->instid;
            gtk_clist_append(clist, buf);
            trxapi_close(api);
      }
      gtk_clist_thaw(clist);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(modemselectwindow), "modemselok")), FALSE);
      selectmodem_sel = -1;
      gtk_widget_show(modemselectwindow);
}

void on_modemlist_select_row(GtkCList *clist, gint row, gint column, GdkEvent *event, gpointer user_data)
{
      selectmodem_sel = row;
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(modemselectwindow), "modemselok")), TRUE);
}

void on_modemlist_unselect_row(GtkCList *clist, gint row, gint column, GdkEvent *event, gpointer user_data)
{
      selectmodem_sel = -1;
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(modemselectwindow), "modemselok")), FALSE);
}

void on_modemselok_clicked(GtkButton *button, gpointer user_data)
{
      GtkCList *clist;
      gchar *mfg, *model, *serial;

      if (selectmodem_sel != -1) {
            clist = GTK_CLIST(gtk_object_get_data(GTK_OBJECT(modemselectwindow), "modemlist"));
            gtk_clist_get_text(clist, selectmodem_sel, 0, &mfg);
            gtk_clist_get_text(clist, selectmodem_sel, 1, &model);
            gtk_clist_get_text(clist, selectmodem_sel, 2, &serial);
            trxopenbymfgmodelserial(mfg, model, serial);
      }
      gtk_widget_hide(modemselectwindow);
}


void on_modemselcancel_clicked(GtkButton *button, gpointer user_data)
{
      gtk_widget_hide(modemselectwindow);
}

gboolean on_modemselectwindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
      gtk_widget_hide(modemselectwindow);
      return TRUE;
}

static const char *filtmodestr[3] = {
        "0 - Default",
        "1 - Precomputed Filter",
        "2 - Ideal Lowpass Filter"
};

static const char *loopbackstr[3] = {
        "Off",
        "Scrambler",
        "Modem"
};

static const char *mdiscrxcstr[2] = {
      "Normal",
      "RxClock"
};

static const char *mdisctxcstr[2] = {
      "Normal",
      "TxClock"
};

static const char *mdisctxdstr[2] = {
      "Normal",
      "TxData"
};

void on_modemconfig_activate(GtkMenuItem *menuitem, gpointer user_data)
{
      GtkNotebook *notebk;
      struct trxapi_baycomusb_adapter_config adaptcfg;
      struct trxapi_channel_access_config chacccfg;
      struct trxapi_interface_config ifcfg;
      struct trxapi_modem_disconnect_config mdisccfg;
      unsigned int i;
      char buf[16];
      char mbuf[8];

      notebk = GTK_NOTEBOOK(gtk_object_get_data(GTK_OBJECT(configwindow), "confignotebook"));
      notebook_pagemask = 0;
        gtk_widget_hide(gtk_notebook_get_nth_page(notebk, 0));
        gtk_widget_hide(gtk_notebook_get_nth_page(notebk, 1));
        gtk_widget_hide(gtk_notebook_get_nth_page(notebk, 2));
        gtk_widget_hide(gtk_notebook_get_nth_page(notebk, 3));
        gtk_widget_hide(gtk_notebook_get_nth_page(notebk, 4));
      if (!trx.trx) {
            gtk_widget_show(configwindow);
            return;
      }
      if (!trxapi_baycomusb_adapter_get_config(trx.trx, &adaptcfg)) {
            gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptmodeentry")),
                           (adaptcfg.mode == trxapi_baycomusb_mode_external) ? "external" :
                           (adaptcfg.mode == trxapi_baycomusb_mode_afsk) ? "afsk" :
                           (adaptcfg.mode == trxapi_baycomusb_mode_audio) ? "audio" : "fsk");
            gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptfclk")),
                                adaptcfg.fclk);
            gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptbitraterx")),
                                adaptcfg.bitraterx);
            gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptbitratetx")),
                                adaptcfg.bitratetx);
            if (adaptcfg.loopback > 2)
                  adaptcfg.loopback = 2;
            gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptloopbackentry")),
                           loopbackstr[adaptcfg.loopback]);
            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptpttmute")),
                                   adaptcfg.pttmute);
            if (adaptcfg.filtmode > 2)
                  adaptcfg.filtmode = 2;
            gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptfiltmodeentry")),
                           filtmodestr[adaptcfg.filtmode]);
            gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptsamplerate")),
                                adaptcfg.samplerate);
            gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptgain")),
                                adaptcfg.gain);
            gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptaudiodevinentry")), adaptcfg.audiodevin);
            gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptaudiodevoutentry")), adaptcfg.audiodevout);
            //gtk_adjustment_set_value(gtk_range_get_adjustment(GTK_RANGE(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptrfsquelch"))),
            //                 adaptcfg.rfsquelch);
            gtk_range_set_adjustment(GTK_RANGE(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptrfsquelch")),
                               GTK_ADJUSTMENT(gtk_adjustment_new(adaptcfg.rfsquelch, trx.desc->rssimin, trx.desc->rssimax, 1, 1, 1)));
            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptaudiosquelch")),
                                   adaptcfg.audiosquelch);
            notebook_pagemask |= (1 << 0) | (1 << 1);
            gtk_widget_show(gtk_notebook_get_nth_page(notebk, 0));
            gtk_widget_show(gtk_notebook_get_nth_page(notebk, 1));
      }
      if (!trxapi_channel_access_get_config(trx.trx, &chacccfg)) {
            gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "chacctxdelay")),
                                chacccfg.txdelay);
            gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "chaccslottime")),
                                chacccfg.slottime);
            gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "chacctxtail")),
                                chacccfg.txtail);
            gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "chaccppersistence")),
                                chacccfg.ppersistence);
            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "chaccfullduplex")),
                                   chacccfg.fullduplex);
            notebook_pagemask |= 1 << 2;
            gtk_widget_show(gtk_notebook_get_nth_page(notebk, 2));
      }
      if (!trxapi_interface_get_config(trx.trx, &ifcfg)) {
            gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfgifnameentry")), ifcfg.ifname);
            gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfghwaddr")), ifcfg.hwaddr);
            snprintf(buf, sizeof(buf), "%u.%u.%u.%u", ifcfg.ipaddr[0], ifcfg.ipaddr[1], ifcfg.ipaddr[2], ifcfg.ipaddr[3]);
            gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfgipaddr")), buf);
            snprintf(buf, sizeof(buf), "%u.%u.%u.%u", ifcfg.netmask[0], ifcfg.netmask[1], ifcfg.netmask[2], ifcfg.netmask[3]);
            gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfgnetmask")), buf);
            snprintf(buf, sizeof(buf), "%u.%u.%u.%u", ifcfg.broadcast[0], ifcfg.broadcast[1], ifcfg.broadcast[2], ifcfg.broadcast[3]);
            gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfgbroadcast")), buf);
            gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfggwhwaddr")), ifcfg.gwhwaddr);
            snprintf(buf, sizeof(buf), "%u.%u.%u.%u", ifcfg.gwipaddr[0], ifcfg.gwipaddr[1], ifcfg.gwipaddr[2], ifcfg.gwipaddr[3]);
            gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfggwipaddr")), buf);
            snprintf(buf, sizeof(buf), "%u.%u.%u.%u", ifcfg.gwnetmask[0], ifcfg.gwnetmask[1], ifcfg.gwnetmask[2], ifcfg.gwnetmask[3]);
            gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfggwnetmask")), buf);
            gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfggwipmodeentry")),
                           (ifcfg.gwipmode == 'V') ? _("Virtual Circuit") :
                           (ifcfg.gwipmode == 'D') ? _("Datagram") :
                           (ifcfg.gwipmode == 'C') ? _("Compressed") : _("Default"));
            notebook_pagemask |= 1 << 3;
            gtk_widget_show(gtk_notebook_get_nth_page(notebk, 3));
      }
      if (!trxapi_modem_disconnect_get_config(trx.trx, &mdisccfg)) {
            strncpy(mbuf, "mdisc0l", sizeof(mbuf));
            for (i = 0; i < 8; i++) {
                  mbuf[5] = '0'+i;
                  if (mdisccfg.direction & (1 << i))
                        mbuf[6] = 't';
                  else if (mdisccfg.output & (1 << i))
                        mbuf[6] = 'h';
                  else
                        mbuf[6] = 'l';
                  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), mbuf)), TRUE);
            }
            if (mdisccfg.rxc > 1)
                  mdisccfg.rxc = 1;
            gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "mdiscrxcentry")),
                           mdiscrxcstr[mdisccfg.rxc]);
            if (mdisccfg.txc > 1)
                  mdisccfg.txc = 1;
            gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "mdisctxcentry")),
                           mdisctxcstr[mdisccfg.txc]);
            if (mdisccfg.txd > 1)
                  mdisccfg.txd = 1;
            gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "mdisctxdentry")),
                           mdisctxdstr[mdisccfg.txd]);
            notebook_pagemask |= 1 << 4;
            gtk_widget_show(gtk_notebook_get_nth_page(notebk, 4));
      }
      gtk_widget_show(configwindow);
}

static void parseip(trxapi_ip_address_t addr, const char *cp)
{
      unsigned int r1, r2, r3, r4;
      
      if (!cp || sscanf(cp, "%u.%u.%u.%u", &r1, &r2, &r3, &r4) != 4) {
            addr[0] = addr[1] = addr[2] = addr[3] = 0;
            return;
      }
      addr[0] = r1;
      addr[1] = r2;
      addr[2] = r3;
      addr[3] = r4;
}

void on_configwindowok_clicked(GtkButton *button, gpointer user_data)
{
      struct trxapi_baycomusb_adapter_config adaptcfg;
      struct trxapi_channel_access_config chacccfg;
      struct trxapi_interface_config ifcfg;
      struct trxapi_modem_disconnect_config mdisccfg;
      char *cp;
      unsigned int dir, out, i, j;
      char mbuf[8];

      if (notebook_pagemask & ((1 << 0)|(1 << 1))) {
            cp = gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptmodeentry")));
            if (!strcmp(cp, "fsk")) {
                  adaptcfg.mode = trxapi_baycomusb_mode_fsk;
            } else if (!strcmp(cp, "external")) {
                  adaptcfg.mode = trxapi_baycomusb_mode_external;
            } else if (!strcmp(cp, "afsk")) {
                  adaptcfg.mode = trxapi_baycomusb_mode_afsk;
            } else if (!strcmp(cp, "audio")) {
                  adaptcfg.mode = trxapi_baycomusb_mode_audio;
            } else
                  adaptcfg.mode = trxapi_baycomusb_mode_fsk;
            adaptcfg.fclk = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptfclk")));
            adaptcfg.bitraterx = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptbitraterx")));
            adaptcfg.bitratetx = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptbitratetx")));
            cp = gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptloopbackentry")));
            for (i = j = 0; i < 3; i++)
                  if (!strcmp(cp, loopbackstr[i]))
                        j = i;
            adaptcfg.loopback = j;
            adaptcfg.pttmute = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptpttmute")));
            cp = gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptfiltmodeentry")));
            for (i = j = 0; i < 3; i++)
                  if (!strcmp(cp, filtmodestr[i]))
                        j = i;
            adaptcfg.filtmode = j;
            adaptcfg.samplerate = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptsamplerate")));
            adaptcfg.gain = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptgain")));
            strncpy(adaptcfg.audiodevin, gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptaudiodevinentry"))), sizeof(adaptcfg.audiodevin));
            strncpy(adaptcfg.audiodevout, gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptaudiodevoutentry"))), sizeof(adaptcfg.audiodevout));
            adaptcfg.rfsquelch = gtk_range_get_adjustment(GTK_RANGE(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptrfsquelch")))->value;
            adaptcfg.audiosquelch = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptaudiosquelch")));
            if (trx.trx != NULL) {
                  if (adaptcfg.rfsquelch < trx.desc->rssimin)
                        adaptcfg.rfsquelch = trx.desc->rssimin;
                  if (adaptcfg.rfsquelch > trx.desc->rssimax)
                        adaptcfg.rfsquelch = trx.desc->rssimax;
            }
            if (trxapi_baycomusb_adapter_set_config(trx.trx, &adaptcfg))
                  lprintf(1, "Error setting adapter config\n");
      }
      if (notebook_pagemask & (1 << 2)) {
            chacccfg.txdelay = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "chacctxdelay")));
            chacccfg.slottime = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "chaccslottime")));
            chacccfg.txtail = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "chacctxtail")));
            chacccfg.ppersistence = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "chaccppersistence")));
            chacccfg.fullduplex = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), "chaccfullduplex")));
            if (trxapi_channel_access_set_config(trx.trx, &chacccfg))
                  lprintf(1, "Error setting channel access parameters\n");
      }
      if (notebook_pagemask & (1 << 3)) {
            strncpy(ifcfg.ifname, gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfgifnameentry"))), sizeof(ifcfg.ifname));
            strncpy(ifcfg.hwaddr, gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfghwaddr"))), sizeof(ifcfg.hwaddr));
            parseip(ifcfg.ipaddr, gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfgipaddr"))));
            parseip(ifcfg.netmask, gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfgnetmask"))));
            parseip(ifcfg.broadcast, gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfgbroadcast"))));
            strncpy(ifcfg.gwhwaddr, gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfggwhwaddr"))), sizeof(ifcfg.gwhwaddr));
            parseip(ifcfg.gwipaddr, gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfggwipaddr"))));
            parseip(ifcfg.gwnetmask, gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfggwnetmask"))));
            cp = gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "ifcfggwipmodeentry")));
            if (!strcmp(cp, _("Virtual Circuit")))
                  ifcfg.gwipmode = 'V';
            else if (!strcmp(cp, _("Datagram")))
                  ifcfg.gwipmode = 'D';
            else if (!strcmp(cp, _("Compressed")))
                  ifcfg.gwipmode = 'C';
            else 
                  ifcfg.gwipmode = ' ';
            if (trxapi_interface_set_config(trx.trx, &ifcfg))
                  lprintf(1, "Error setting interface parameters\n");
      }
      if (notebook_pagemask & (1 << 4)) {
            strncpy(mbuf, "mdisc0l", sizeof(mbuf));
            for (dir = out = i = 0; i < 8; i++) {
                  mbuf[5] = '0'+i;
                  mbuf[6] = 't';
                  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), mbuf))))
                        dir |= (1 << i);
                  mbuf[6] = 'h';
                  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_object_get_data(GTK_OBJECT(configwindow), mbuf))))
                        out |= (1 << i);
            }
            mdisccfg.output = out;
            mdisccfg.direction = dir;
            cp = gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "mdiscrxcentry")));
            for (i = j = 0; i < 2; i++)
                  if (!strcmp(cp, mdiscrxcstr[i]))
                        j = i;
            mdisccfg.rxc = j;
            cp = gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "mdisctxcentry")));
            for (i = j = 0; i < 2; i++)
                  if (!strcmp(cp, mdisctxcstr[i]))
                        j = i;
            mdisccfg.txc = j;
            cp = gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(configwindow), "mdisctxdentry")));
            for (i = j = 0; i < 2; i++)
                  if (!strcmp(cp, mdisctxdstr[i]))
                        j = i;
            mdisccfg.txd = j;
            if (trxapi_modem_disconnect_set_config(trx.trx, &mdisccfg))
                  lprintf(1, "Error setting modem disconnect parameters\n");
      }
      gtk_widget_hide(configwindow);
}

void on_configwindowcancel_clicked(GtkButton *button, gpointer user_data)
{
      gtk_widget_hide(configwindow);
}

gboolean on_configwindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
      gtk_widget_hide(configwindow);
      return TRUE;
}

/* ---------------------------------------------------------------------- */

static gint periodic(gpointer user_data)
{
      struct trxapi_state status;
      struct trxapi_audio_state audiostate;
      unsigned char audiosamples[1024];
      gint16 audiosamp[1024];
      char buf[256];
      unsigned int i;
      int rssi;
        GtkText *txt;
      unsigned char *cp1, *cp2;
      GtkToggleButton *manualptt;
      struct stndb_entry stnent;

      if (trx.trx == NULL) {
            /* should do reopen */
            return TRUE;
      }
      if (trxapi_get_state(trx.trx, &status)) {
            lprintf(1, "Error getting status\n");
            closetrx();
            /* should initialise reopening */
            return TRUE;
      }
      trxnewmode(status.mode);
      /* update PTT & DCD leds */
      i = (status.ptt ? 1 : 0) | (status.dcd ? 2 : 0);
      if ((ledstatus ^ i) & 2)
            setled(GTK_PIXMAP(gtk_object_get_data(GTK_OBJECT(mainwindow), "leddcd")), i & 2);
      if ((ledstatus ^ i) & 1)
            setled(GTK_PIXMAP(gtk_object_get_data(GTK_OBJECT(mainwindow), "ledptt")), i & 1);
      ledstatus = i;
      /* update RSSI */
      gtk_progress_set_value(GTK_PROGRESS(gtk_object_get_data(GTK_OBJECT(mainwindow), "rssi")), status.rssi);
      /* add RSSI to running display */
      rssi = (status.rssi - trx.desc->rssimin) * trx.rssimul;
      if (rssi < 0)
            rssi = 0;
      if (rssi > 255)
            rssi = 255;
      signalhistory_newdata(SIGNALHISTORY(gtk_object_get_data(GTK_OBJECT(mainwindow), "rssihistory")),
                        status.ptt ? 250 : rssi, status.ptt ? 2 : (status.dcd ? 1 : 0));
      /* check changes in rx/tx frequency */
      if (!freq.fchginhibit && (status.rxfreq != freq.rx || status.txfreq != freq.tx)) {
            memset(&stnent, 0, sizeof(stnent));
            stnent.rx = freq.rx = status.rxfreq;
            stnent.tx = freq.tx = status.txfreq;
            stnent.mode = -1;
            set_frequencies(freq.rx, freq.tx);
            if (trx.trx != NULL) {
                  struct trxapi_baycomusb_adapter_config adaptcfg;

                  if (!trxapi_baycomusb_adapter_get_config(trx.trx, &adaptcfg)) {
                        stnent.mode = adaptcfg.mode;
                        stnent.bitraterx = adaptcfg.bitraterx;
                        stnent.bitratetx = adaptcfg.bitratetx;
                  }
            }
            if (stndb_retrieve(&stnent) || !stnent.name[0])
                  strncpy(stnent.name, "-", sizeof(stnent.name));
            set_stnname(stnent.name);
            gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "rxqrg")), freq.rx != 0);
            gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "txqrg")), freq.tx != 0);
            gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "stnname")), freq.rx != 0 || freq.tx != 0);
      }
      /* check manual PTT */
      manualptt = GTK_TOGGLE_BUTTON(gtk_object_get_data(GTK_OBJECT(mainwindow), "buttonptt"));
      if ((!gtk_toggle_button_get_active(manualptt)) != (!status.manualptt)) {
            gtk_signal_disconnect_by_func(GTK_OBJECT(manualptt), GTK_SIGNAL_FUNC(on_buttonptt_toggled), NULL);
            gtk_toggle_button_set_active(manualptt, status.manualptt);
            gtk_signal_connect(GTK_OBJECT(manualptt), "toggled", GTK_SIGNAL_FUNC(on_buttonptt_toggled), NULL);
      }
      /* check if UART received chars */
      if (!trxapi_uart_receive(trx.trx, &rxuartptr, buf, sizeof(buf))) {
            /* process input for widget */
                for (cp1 = cp2 = buf; *cp2; cp2++) {
                        if (*cp2 == '\r') {
                                *cp1++ = '\n';
                        uartline.rxline[uartline.lptr] = 0;
                        processuart(uartline.rxline);
                        uartline.lptr = 0;
                        } else if (*cp2 != '\n') {
                                *cp1++ = *cp2;
                        if (*cp2 >= 32 && *cp2 <= 127 && uartline.lptr < sizeof(uartline.rxline)-1)
                              uartline.rxline[uartline.lptr++] = *cp2;
                  }
                }
            if (buf != (char *)cp1) {
                  txt = GTK_TEXT(gtk_object_get_data(GTK_OBJECT(terminalwindow), "text"));
                  gtk_text_insert(txt, NULL, NULL, NULL, buf, cp1-(unsigned char *)buf);
            }
      }
      /* scope/spectrum windows */
      if (trx.mode == trxapi_mode_audio) {
            if (trxapi_get_audio_state(trx.trx, &audiostate)) {
                  lprintf(1, "trxapi_get_audio_state error\n");
            } else {
                  /* update audio levels */
                  gtk_progress_set_value(GTK_PROGRESS(gtk_object_get_data(GTK_OBJECT(audiopwrwindow), "audiomicsig")), audiostate.micsigpwr);
                  gtk_progress_set_value(GTK_PROGRESS(gtk_object_get_data(GTK_OBJECT(audiopwrwindow), "audiospksig")), audiostate.spksigpwr);
                  gtk_progress_set_value(GTK_PROGRESS(gtk_object_get_data(GTK_OBJECT(audiopwrwindow), "audiospknoise")), audiostate.spknoisepwr);
                  /* send samples to scope and spectrum */
                  if (GTK_WIDGET_DRAWABLE(micscopewindow) || GTK_WIDGET_DRAWABLE(micspectrumwindow)) {
                        if (trxapi_get_audio_mic_samples(trx.trx, (audiostate.micbufptr + audiostate.micbufsz - 1024) % audiostate.micbufsz, 1024, audiosamples)) {
                              lprintf(1, "trxapi_get_audio_mic_samples error\n");
                        } else {
                              for (i = 0; i < 1024; i++)
                                    audiosamp[i] = audiosamples[i] << 8;
                              if (GTK_WIDGET_DRAWABLE(micscopewindow))
                                    scope_addvalues(SCOPE(gtk_object_get_data(GTK_OBJECT(micscopewindow), "scope")), 1024, NULL, audiosamp);
                              if (GTK_WIDGET_DRAWABLE(micspectrumwindow))
                                    spectrum_addvalues(SPECTRUM(gtk_object_get_data(GTK_OBJECT(micspectrumwindow), "spec")), 1024, audiosamp);
                        }
                  }
                  if (GTK_WIDGET_DRAWABLE(spkscopewindow) || GTK_WIDGET_DRAWABLE(spkspectrumwindow)) {
                        if (trxapi_get_audio_spk_samples(trx.trx, (audiostate.spkbufptr + audiostate.spkbufsz - 1024) % audiostate.spkbufsz, 1024, audiosamples)) {
                              lprintf(1, "trxapi_get_audio_spk_samples error\n");
                        } else {
                              for (i = 0; i < 1024; i++)
                                    audiosamp[i] = audiosamples[i] << 8;
                              if (GTK_WIDGET_DRAWABLE(spkscopewindow))
                                    scope_addvalues(SCOPE(gtk_object_get_data(GTK_OBJECT(spkscopewindow), "scope")), 1024, NULL, audiosamp);
                              if (GTK_WIDGET_DRAWABLE(spkspectrumwindow))
                                    spectrum_addvalues(SPECTRUM(gtk_object_get_data(GTK_OBJECT(spkspectrumwindow), "spec")), 1024, audiosamp);
                        }
                  }
            }
      }
      return TRUE;
}

/* ---------------------------------------------------------------------- */

void on_dtmfclear_clicked(GtkButton *button, gpointer user_data)
{
        GtkEntry *entry;
        
        entry = GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(dtmfwindow), "dtmfentry"));
        gtk_entry_set_text(entry, "");
}

static gint dtmfkeyfunc(gpointer data)
{
        return on_dtmfwindow_key_event(NULL, NULL, data);
}

gboolean on_dtmfwindow_key_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
        static const char dtmfkeys[] = "0123456789ABCD*#";
        static guint tmo = 0;
        static guint lastkey = -1;
        static guint currentkey = 0;
        GtkButton *but;
        gchar bname[6] = "dtmf0";
        char *cp, c;

        if (!event) {
                tmo = 0;
                lastkey = currentkey;
                bname[4] += lastkey & 15;
                if ((lastkey & 15) >= 10)
                        bname[4] += 'a'-'0'-10;
                but = GTK_BUTTON(gtk_object_get_data(GTK_OBJECT(dtmfwindow), bname));
                if (lastkey & 16)
                        gtk_button_pressed(but);
                else
                        gtk_button_released(but);
                return FALSE;  /* don't get called again */
        }
        c = event->keyval;
        if (c >= 'a' && c <= 'z')
                c += 'A'-'a';
        if (!(cp = strchr(dtmfkeys, c)))
                return FALSE;
        currentkey = cp - dtmfkeys + (event->type == GDK_KEY_PRESS ? 16 : 0);
        if (tmo)
                gtk_timeout_remove(tmo);
        if (currentkey != lastkey)
                tmo = gtk_timeout_add(10, dtmfkeyfunc, NULL);
        return TRUE;
}

void on_dtmf_key(GtkButton *button, gpointer user_data)
{
        static const char dtmfkeys[] = "0123456789ABCD*#";
        GtkEntry *entry;
        gchar txt[2];
        guint key = (guint)user_data;
      
        printf("DTMF key: %u\n", key);
      if (trx.trx == NULL)
            return;
        if (key & 16)
                pttmask |= PTTMASK_DTMF;
        else 
                pttmask &= ~PTTMASK_DTMF;
      updatepttmask();
      if (trx.mode == trxapi_mode_audio) {
            if (trxapi_set_audio_dtmf(trx.trx, (key & 16) ? (key & 15) : -1))
                  lprintf(1, "trxapi_set_audio_dtmf error\n");
      }
        if (key < 0x10 || key > 0x1f)
                return;
        txt[0] = dtmfkeys[key & 0xf];
        txt[1] = 0;
        entry = GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(dtmfwindow), "dtmfentry"));
        gtk_entry_append_text(entry, txt);
}

gboolean on_dtmfwindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
        gtk_widget_hide(dtmfwindow);
        return TRUE;
}

void on_audiopwrs_activate(GtkMenuItem *menuitem, gpointer user_data)
{
      gtk_widget_show(audiopwrwindow);
}

void on_audiodtmf_activate(GtkMenuItem *menuitem, gpointer user_data)
{
        gtk_widget_show(dtmfwindow);
}


void on_audioparams_activate(GtkMenuItem *menuitem, gpointer user_data)
{
      gtk_widget_show(paramwindow);
}

void on_spkscope_activate(GtkMenuItem *menuitem, gpointer user_data)
{
      gtk_widget_show(spkscopewindow);
}


void on_spkspectrum_activate(GtkMenuItem *menuitem, gpointer user_data)
{
      gtk_widget_show(spkspectrumwindow);
}

void on_micscope_activate(GtkMenuItem *menuitem, gpointer user_data)
{
      gtk_widget_show(micscopewindow);
}


void on_micspectrum_activate(GtkMenuItem *menuitem, gpointer user_data)
{
      gtk_widget_show(micspectrumwindow);
}

void on_paramwindowok_clicked(GtkButton *button, gpointer user_data)
{
      gtk_widget_hide(paramwindow);
      params.enaptt = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_object_get_data(GTK_OBJECT(paramwindow), "paramenablepttpkt")));
      paramstodialog();
}

void on_paramwindowcancel_clicked(GtkButton *button, gpointer user_data)
{
      gtk_widget_hide(paramwindow);
      paramstodialog();
}

gboolean on_paramwindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
      gtk_widget_hide(paramwindow);
      return TRUE;
}

gboolean on_spkscopewindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
        gtk_widget_hide(spkscopewindow);
        return TRUE;
}

gboolean on_spkspectrumwindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
        gtk_widget_hide(spkspectrumwindow);
        return TRUE;
}

gboolean on_micscopewindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
        gtk_widget_hide(micscopewindow);
        return TRUE;
}

gboolean on_micspectrumwindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
        gtk_widget_hide(micspectrumwindow);
        return TRUE;
}

gboolean on_audiopwrwindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
      gtk_widget_hide(audiopwrwindow);
        return TRUE;
}

/* ---------------------------------------------------------------------- */

static void init_popdown(void)
{
      static const char *modestr[] = { "fsk", "afsk", "external", "audio" };
      GList *items;
      GtkCombo *combo;
      unsigned int i;

      combo = GTK_COMBO(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptfiltmode"));
      items = NULL;
      for (i = 0; i < sizeof(filtmodestr)/sizeof(filtmodestr[0]); i++)
            items = g_list_append(items, (gpointer)filtmodestr[i]);
      gtk_combo_set_popdown_strings(combo, items);
      gtk_entry_set_text(GTK_ENTRY(combo->entry), items->data);
      g_list_free(items);
      combo = GTK_COMBO(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptloopback"));
      items = NULL;
      for (i = 0; i < sizeof(loopbackstr)/sizeof(loopbackstr[0]); i++)
            items = g_list_append(items, (gpointer)loopbackstr[i]);
      gtk_combo_set_popdown_strings(combo, items);
      gtk_entry_set_text(GTK_ENTRY(combo->entry), items->data);
      g_list_free(items);
      combo = GTK_COMBO(gtk_object_get_data(GTK_OBJECT(configwindow), "adaptmode"));
      items = NULL;
      for (i = 0; i < sizeof(modestr)/sizeof(modestr[0]); i++)
            items = g_list_append(items, (gpointer)modestr[i]);
      gtk_combo_set_popdown_strings(combo, items);
      gtk_entry_set_text(GTK_ENTRY(combo->entry), items->data);
      g_list_free(items);
      combo = GTK_COMBO(gtk_object_get_data(GTK_OBJECT(newstnwindow), "mode"));
      items = g_list_append(NULL, "-");
      for (i = 0; i < sizeof(modestr)/sizeof(modestr[0]); i++)
            items = g_list_append(items, (gpointer)modestr[i]);
      gtk_combo_set_popdown_strings(combo, items);
      gtk_entry_set_text(GTK_ENTRY(combo->entry), items->data);
      g_list_free(items);
      combo = GTK_COMBO(gtk_object_get_data(GTK_OBJECT(configwindow), "mdiscrxc"));
      items = NULL;
      for (i = 0; i < sizeof(mdiscrxcstr)/sizeof(mdiscrxcstr[0]); i++)
            items = g_list_append(items, (gpointer)mdiscrxcstr[i]);
      gtk_combo_set_popdown_strings(combo, items);
      gtk_entry_set_text(GTK_ENTRY(combo->entry), items->data);
      g_list_free(items);
      combo = GTK_COMBO(gtk_object_get_data(GTK_OBJECT(configwindow), "mdisctxc"));
      items = NULL;
      for (i = 0; i < sizeof(mdisctxcstr)/sizeof(mdisctxcstr[0]); i++)
            items = g_list_append(items, (gpointer)mdisctxcstr[i]);
      gtk_combo_set_popdown_strings(combo, items);
      gtk_entry_set_text(GTK_ENTRY(combo->entry), items->data);
      g_list_free(items);
      combo = GTK_COMBO(gtk_object_get_data(GTK_OBJECT(configwindow), "mdisctxd"));
      items = NULL;
      for (i = 0; i < sizeof(mdisctxdstr)/sizeof(mdisctxdstr[0]); i++)
            items = g_list_append(items, (gpointer)mdisctxdstr[i]);
      gtk_combo_set_popdown_strings(combo, items);
      gtk_entry_set_text(GTK_ENTRY(combo->entry), items->data);
      g_list_free(items);
}

/* ---------------------------------------------------------------------- */

int main(int argc, char *argv[])
{
      static const struct option long_options[] = {
            { "--expert", 0, 0, 'e' },
                { 0, 0, 0, 0 }
        };
        int c, err = 0;
      unsigned int expert = 0;
      guint tmid;
 
      printf("Baycom USB Transceiver Controller v" VERSION "\n");
#ifdef ENABLE_NLS
      bindtextdomain(PACKAGE, PACKAGE_LOCALE_DIR);
      textdomain(PACKAGE);
#endif

      verboselevel = ~0;
      syslogmsg = 1;

      if (trxapi_init(&argc, argv))
            exit(1);

      gtk_set_locale();
      gtk_init(&argc, &argv);

      add_pixmap_directory(PACKAGE_DATA_DIR "/pixmaps");
      add_pixmap_directory(PACKAGE_SOURCE_DIR "/pixmaps");

        while ((c = getopt_long(argc, argv, "e", long_options, NULL)) != EOF) {
                switch (c) {
            case 'e':
                  expert = 1;
                  break;

                default:
                        err++;
                        break;
                }
        }
        if (err) {
                fprintf(stderr, "usage: %s [--expert]\n", argv[0]);
            exit(1);
      }
      stndb_open();
      /*
       * The following code was added by Glade to create one of each component
       * (except popup menus), just so that you see something after building
       * the project. Delete any components that you don't want shown initially.
       */
      mainwindow = create_mainwindow();
      gtk_progress_configure(GTK_PROGRESS(gtk_object_get_data(GTK_OBJECT(mainwindow), "rssi")), -120, -120, -35);
      terminalwindow = create_terminalwindow();
      chmemorywindow = create_chmemorywindow();
      chprogwindow = create_chprogwindow();
      freqlistwindow = create_freqlistwindow();
      newstnwindow = create_newstationwindow();
      modemselectwindow = create_modemselectwindow();
      configwindow = create_configwindow();
        dtmfwindow = create_dtmfwindow();
        spkscopewindow = create_spkscopewindow();
        spkspectrumwindow = create_spkspectrumwindow();
      micscopewindow = create_micscopewindow();
        micspectrumwindow = create_micspectrumwindow();
      paramwindow = create_paramwindow();
      audiopwrwindow = create_audiopwrwindow();
      init_popdown();
      updatechmemwindow();
      setstns();
      paramstodialog();
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(freqlistwindow), "buttonset")), FALSE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(freqlistwindow), "buttonupdate")), FALSE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(freqlistwindow), "buttondelete")), FALSE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(modemselectwindow), "modemselok")), FALSE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "rxqrg")), FALSE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "txqrg")), FALSE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "stnname")), FALSE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "modemconfig")), FALSE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "audio")), FALSE);
      if (!expert)
            gtk_widget_hide(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "expert")));
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "buttonptt")), FALSE);
      gtk_widget_set_sensitive(GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(mainwindow), "button1750")), FALSE);
      trx.mode = trxapi_mode_unspec;
      gtk_widget_show(mainwindow);
      trxopenbyindex(0);
        tmid = gtk_timeout_add(250, periodic, NULL);
      gtk_main();
      gtk_timeout_remove(tmid);
      stndb_close();
      if (trx.trx)
            trxapi_close(trx.trx);
      return 0;
}

Generated by  Doxygen 1.6.0   Back to index