Run rig-ctrl in its own thread

Issue #45.
This commit is contained in:
Patrick Dohmen 2017-12-08 22:39:40 +01:00 committed by Alexandru Csete
parent 1e203ca737
commit 677ebd8826
4 changed files with 440 additions and 230 deletions

View file

@ -4,6 +4,7 @@
Copyright (C) 2001-2009 Alexandru Csete, OZ9AEC.
Authors: Alexandru Csete <oz9aec@gmail.com>
Patrick Dohmen <dl4pd@darc.de>
Comments, questions and bugreports should be submitted via
http://sourceforge.net/projects/gpredict/
@ -24,6 +25,15 @@
You should have received a copy of the GNU General Public License
along with this program; if not, visit http://www.fsf.org/
*/
/** \brief FREQ control.
*
* More info...
*
* 1 222.333 444 MHz
*
* \bug This should be a generic widget, not just frequency specific
*
*/
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <math.h>
@ -35,15 +45,17 @@
static void gtk_freq_knob_class_init(GtkFreqKnobClass * class);
static void gtk_freq_knob_init(GtkFreqKnob * list);
static void gtk_freq_knob_destroy(GtkWidget * widget);
static void gtk_freq_knob_update(GtkFreqKnob * knob);
static void gtk_freq_knob_destroy(GtkObject * object);
static void *gtk_freq_knob_update(GtkFreqKnob * knob);
static void button_clicked_cb(GtkWidget * button, gpointer data);
static gboolean on_button_press(GtkWidget * digit, GdkEventButton * event,
gpointer data);
static gboolean on_button_scroll(GtkWidget * digit, GdkEventScroll * event,
gpointer data);
static GtkBoxClass *parent_class = NULL;
G_LOCK_DEFINE_STATIC(updatelock);
static GtkHBoxClass *parent_class = NULL;
#define FMTSTR "<span size='xx-large'>%c</span>"
@ -63,12 +75,14 @@ static const guint idx[] = {
static guint freq_changed_signal = 0;
GType gtk_freq_knob_get_type()
{
static GType gtk_freq_knob_type = 0;
if (!gtk_freq_knob_type)
{
static const GTypeInfo gtk_freq_knob_info = {
sizeof(GtkFreqKnobClass),
NULL, /* base_init */
@ -81,7 +95,8 @@ GType gtk_freq_knob_get_type()
(GInstanceInitFunc) gtk_freq_knob_init,
NULL,
};
gtk_freq_knob_type = g_type_register_static(GTK_TYPE_BOX,
gtk_freq_knob_type = g_type_register_static(GTK_TYPE_VBOX,
"GtkFreqKnob",
&gtk_freq_knob_info, 0);
}
@ -91,16 +106,23 @@ GType gtk_freq_knob_get_type()
static void gtk_freq_knob_class_init(GtkFreqKnobClass * class)
{
GtkWidgetClass *widget_class = (GtkWidgetClass *) class;
widget_class->destroy = gtk_freq_knob_destroy;
/*GObjectClass *gobject_class; */
GtkObjectClass *object_class;
/*GtkWidgetClass *widget_class; */
/*GtkContainerClass *container_class; */
/*gobject_class = G_OBJECT_CLASS (class); */
object_class = (GtkObjectClass *) class;
/*widget_class = (GtkWidgetClass*) class; */
/*container_class = (GtkContainerClass*) class; */
parent_class = g_type_class_peek_parent(class);
object_class->destroy = gtk_freq_knob_destroy;
/* create freq changed signal */
freq_changed_signal = g_signal_new("freq-changed",
G_TYPE_FROM_CLASS(class),
G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
0,
freq_changed_signal = g_signal_new("freq-changed", G_TYPE_FROM_CLASS(class), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, 0, //G_STRUCT_OFFSET (GtkFreqKnobClass, tictactoe),
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
@ -114,17 +136,16 @@ static void gtk_freq_knob_init(GtkFreqKnob * knob)
}
static void gtk_freq_knob_destroy(GtkWidget * widget)
static void gtk_freq_knob_destroy(GtkObject * object)
{
(*GTK_WIDGET_CLASS(parent_class)->destroy) (widget);
(*GTK_OBJECT_CLASS(parent_class)->destroy) (object);
}
/**
* Create a new Frequency control widget.
*
* @param val The initial value of the control.
* @param buttons Flag indicating whether buttons should be shown
* @return A new frequency control widget.
* \brief Create a new Frequency control widget.
* \param[in] val The initial value of the control.
* \param[in] buttons Flag indicating whether buttons should be shown
* \return A new frequency control widget.
*
*/
GtkWidget *gtk_freq_knob_new(gdouble val, gboolean buttons)
@ -135,6 +156,7 @@ GtkWidget *gtk_freq_knob_new(gdouble val, gboolean buttons)
guint i;
gint delta;
widget = g_object_new(GTK_TYPE_FREQ_KNOB, NULL);
GTK_FREQ_KNOB(widget)->value = val;
@ -158,6 +180,7 @@ GtkWidget *gtk_freq_knob_new(gdouble val, gboolean buttons)
else
{
/* active widget that allows changing the value */
gtk_widget_set_tooltip_text(GTK_FREQ_KNOB(widget)->digits[i],
_
("Use mouse buttons and wheel to change value"));
@ -172,12 +195,14 @@ GtkWidget *gtk_freq_knob_new(gdouble val, gboolean buttons)
GTK_FREQ_KNOB(widget)->evtbox[i], idx[i],
idx[i] + 1, 1, 2, GTK_SHRINK,
GTK_FILL | GTK_EXPAND, 0, 0);
g_signal_connect(GTK_FREQ_KNOB(widget)->evtbox[i],
"button_press_event", (GCallback) on_button_press,
widget);
g_signal_connect(GTK_FREQ_KNOB(widget)->evtbox[i], "scroll_event",
(GCallback) on_button_scroll, widget);
/* UP buttons */
GTK_FREQ_KNOB(widget)->buttons[i] = gtk_button_new();
@ -230,7 +255,8 @@ GtkWidget *gtk_freq_knob_new(gdouble val, gboolean buttons)
gtk_table_attach(GTK_TABLE(table), label, 13, 14, 1, 2,
GTK_SHRINK, GTK_SHRINK, 0, 0);
gtk_freq_knob_update(GTK_FREQ_KNOB(widget));
g_idle_add((GSourceFunc) gtk_freq_knob_update, GTK_FREQ_KNOB(widget));
gtk_container_add(GTK_CONTAINER(widget), table);
gtk_widget_show_all(widget);
@ -239,10 +265,9 @@ GtkWidget *gtk_freq_knob_new(gdouble val, gboolean buttons)
}
/**
* Set the value of the frequency control widget.
*
* @param knob The frequency control widget.
* @param val The new value.
* \brief Set the value of the frequency control widget.
* \param[in] knob The frequency control widget.
* \param[in] val The new value.
*
*/
void gtk_freq_knob_set_value(GtkFreqKnob * knob, gdouble val)
@ -253,15 +278,14 @@ void gtk_freq_knob_set_value(GtkFreqKnob * knob, gdouble val)
knob->value = val;
/* update the display */
gtk_freq_knob_update(knob);
g_idle_add((GSourceFunc) gtk_freq_knob_update, knob);
}
}
/**
* Get the current value of the frequency control widget.
*
* @param knob The frequency control widget.
* @return The current value.
* \brief Get the current value of the frequency control widget.
* \param[in] knob The frequency control widget.
* \return The current value.
*
* Hint: For reading the value you can also access knob->value.
*
@ -272,17 +296,19 @@ gdouble gtk_freq_knob_get_value(GtkFreqKnob * knob)
}
/**
* Update frequency display widget.
*
* @param knob The frequency control widget.
* \brief Update frequency display widget.
* \param[in] knob The frequency control widget.
*
*/
static void gtk_freq_knob_update(GtkFreqKnob * knob)
static void *gtk_freq_knob_update(GtkFreqKnob * knob)
{
gchar b[11];
gchar *buff;
guint i;
/* Enter critical section! */
G_LOCK(updatelock);
g_ascii_formatd(b, 11, "%10.0f", fabs(knob->value));
/* set label markups */
@ -292,13 +318,16 @@ static void gtk_freq_knob_update(GtkFreqKnob * knob)
gtk_label_set_markup(GTK_LABEL(knob->digits[i]), buff);
g_free(buff);
}
/* Leave critical section! */
G_UNLOCK(updatelock);
return FALSE;
}
/**
* Button clicked event.
*
* @param button The button that was clicked.
* @param data Pointer to the GtkFreqKnob widget.
* \brief Button clicked event.
* \param button The button that was clicked.
* \param data Pointer to the GtkFreqKnob widget.
*
*/
static void button_clicked_cb(GtkWidget * button, gpointer data)
@ -316,19 +345,18 @@ static void button_clicked_cb(GtkWidget * button, gpointer data)
knob->value += delta;
}
gtk_freq_knob_update(knob);
g_idle_add((GSourceFunc) gtk_freq_knob_update, knob);
/* emit "freq_changed" signal */
g_signal_emit(G_OBJECT(data), freq_changed_signal, 0);
}
/**
* Manage button press events
*
* @param digit Pointer to the event box that received the event
* @param event Pointer to the GdkEventButton that contains details for te event
* @param data Pointer to the GtkFreqKnob widget (we need it to update the value)
* @return Always TRUE to prevent further propagation of the event
* \brief Manage button press events
* \param digit Pointer to the event box that received the event
* \param event Pointer to the GdkEventButton that contains details for te event
* \param data Pointer to the GtkFreqKnob widget (we need it to update the value)
* \return Always TRUE to prevent further propagation of the event
*
* This function is called when a mouse button is pressed on a digit. This is used
* to increment or decrement the value:
@ -336,13 +364,16 @@ static void button_clicked_cb(GtkWidget * button, gpointer data)
* - Right button: down
* - Middle button: set digit to 0 (TBC)
*
* Wheel up/down are managed in a separate callback since these are treated as scroll events
* rather than button press events (they used to be button press events though)
* Wheel up/down are managed in a separate callback since these are treated as
* scroll events rather than button press events (they used to be button press
* events though)
*
* The digit labels are stored in an array. To get the amount of change corresponding to the
* clicked label we can convert the index (attached to the evtbox): delta = 10^(9-index)
* The digit labels are stored in an array. To get the amount of change corresponding
* to the clicked label we can convert the index (attached to the evtbox):
* delta = 10^(9-index)
*
* Whether the delta is positive or negative depends on which mouse button triggered the event.
* Whether the delta is positive or negative depends on which mouse button triggered
* the event.
*/
static gboolean on_button_press(GtkWidget * evtbox,
GdkEventButton * event, gpointer data)
@ -394,21 +425,21 @@ static gboolean on_button_press(GtkWidget * evtbox,
}
/**
* Manage scroll wheel events
* \brief Manage scroll wheel events
* \param digit Pointer to the event box that received the event
* \param event Pointer to the GdkEventScroll that contains details for te event
* \param data Pointer to the GtkFreqKnob widget (we need it to update the value)
* \return Always TRUE to prevent further propagation of the event
*
* @param digit Pointer to the event box that received the event
* @param event Pointer to the GdkEventScroll that contains details for te event
* @param data Pointer to the GtkFreqKnob widget (we need it to update the value)
* @return Always TRUE to prevent further propagation of the event
*
* This function is called when the mouse wheel is moved up or down. This is used to increment
* or decrement the value.
* This function is called when the mouse wheel is moved up or down. This is used
* to increment or decrement the value.
*
* Button presses are managed in a separate callback since these are treated as different
* events.
* Button presses are managed in a separate callback since these are treated as
* different events.
*
* The digit labels are stored in an array. To get the amount of change corresponding to the
* clicked label we can convert the index (attached to the evtbox): delta = 10^(9-index)
* The digit labels are stored in an array. To get the amount of change corresponding
* to the clicked label we can convert the index (attached to the evtbox):
* delta = 10^(9-index)
*
* Whether the delta is positive or negative depends on the scroll direction.
*/
@ -421,6 +452,7 @@ static gboolean on_button_scroll(GtkWidget * evtbox,
gdouble delta = pow(10, 9 - idx);
gdouble value;
if (delta < 0.01)
{
/* no change, user clicked on sign or decimal separator */
@ -435,6 +467,7 @@ static gboolean on_button_scroll(GtkWidget * evtbox,
switch (event->direction)
{
/* decrease value by delta */
case GDK_SCROLL_DOWN:
case GDK_SCROLL_LEFT:

View file

@ -35,12 +35,13 @@
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* *INDENT-ON* */
/* *INDENT-OO* */
#define GTK_TYPE_FREQ_KNOB (gtk_freq_knob_get_type ())
#define GTK_FREQ_KNOB(obj) G_TYPE_CHECK_INSTANCE_CAST (obj,\
gtk_freq_knob_get_type (),\
GtkFreqKnob)
gtk_freq_knob_get_type (),\
GtkFreqKnob)
#define GTK_FREQ_KNOB_CLASS(klass) G_TYPE_CHECK_CLASS_CAST (klass,\
gtk_freq_knob_get_type (),\
@ -48,29 +49,32 @@ extern "C" {
#define IS_GTK_FREQ_KNOB(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, gtk_freq_knob_get_type ())
typedef struct _gtk_freq_knob GtkFreqKnob;
typedef struct _GtkFreqKnobClass GtkFreqKnobClass;
struct _gtk_freq_knob {
GtkBox box;
typedef struct _gtk_freq_knob GtkFreqKnob;
typedef struct _GtkFreqKnobClass GtkFreqKnobClass;
GtkWidget *digits[10]; /*!< Labels for the digits */
GtkWidget *evtbox[10]; /*!< Event boxes to catch mouse events over the digits */
GtkWidget *buttons[20]; /*!< Buttons; 0..9 up; 10..19 down */
gdouble min;
gdouble max;
gdouble value;
struct _gtk_freq_knob
{
GtkVBox vbox;
GtkWidget *digits[10]; /*!< Labels for the digits */
GtkWidget *evtbox[10]; /*!< Event boxes to catch mouse events over the digits */
GtkWidget *buttons[20]; /*!< Buttons; 0..9 up; 10..19 down */
gdouble min;
gdouble max;
gdouble value;
};
struct _GtkFreqKnobClass {
GtkBoxClass parent_class;
struct _GtkFreqKnobClass
{
GtkVBoxClass parent_class;
};
GType gtk_freq_knob_get_type(void);
GtkWidget *gtk_freq_knob_new(gdouble val, gboolean buttons);
void gtk_freq_knob_set_value(GtkFreqKnob * knob, gdouble val);
gdouble gtk_freq_knob_get_value(GtkFreqKnob * knob);
GType gtk_freq_knob_get_type (void);
GtkWidget* gtk_freq_knob_new (gdouble val, gboolean buttons);
void gtk_freq_knob_set_value (GtkFreqKnob *knob, gdouble val);
gdouble gtk_freq_knob_get_value (GtkFreqKnob *knob);
/* *INDENT-OFF* */

View file

@ -4,6 +4,7 @@
Copyright (C) 2001-2013 Alexandru Csete, OZ9AEC.
Authors: Alexandru Csete <oz9aec@gmail.com>
Patrick Dohmen <dl4pd@darc.de>
Comments, questions and bugreports should be submitted via
http://sourceforge.net/projects/gpredict/
@ -76,7 +77,7 @@
static void gtk_rig_ctrl_class_init(GtkRigCtrlClass * class);
static void gtk_rig_ctrl_init(GtkRigCtrl * list);
static void gtk_rig_ctrl_destroy(GtkWidget * widget);
static void gtk_rig_ctrl_destroy(GtkObject * object);
static GtkWidget *create_downlink_widgets(GtkRigCtrl * ctrl);
static GtkWidget *create_uplink_widgets(GtkRigCtrl * ctrl);
@ -145,6 +146,13 @@ static inline gboolean check_get_response(gchar * buff, gboolean retcode,
static gint sat_name_compare(sat_t * a, sat_t * b);
static gint rig_name_compare(const gchar * a, const gchar * b);
/* add thread for hamlib communication */
gpointer rigctl_run(gpointer data);
static void rigctrl_open(GtkRigCtrl * data);
static void rigctrl_close(GtkRigCtrl * data);
static void setconfig(gpointer data);
static void remove_timer(GtkRigCtrl * data);
static void start_timer(GtkRigCtrl * data);
static GtkVBoxClass *parent_class = NULL;
@ -179,11 +187,20 @@ GType gtk_rig_ctrl_get_type()
static void gtk_rig_ctrl_class_init(GtkRigCtrlClass * class)
{
GtkWidgetClass *widget_class = (GtkWidgetClass *) class;
//GObjectClass *gobject_class;
GtkObjectClass *object_class;
widget_class->destroy = gtk_rig_ctrl_destroy;
//GtkWidgetClass *widget_class;
//GtkContainerClass *container_class;
//gobject_class = G_OBJECT_CLASS (class);
object_class = (GtkObjectClass *) class;
//widget_class = (GtkWidgetClass*) class;
//container_class = (GtkContainerClass*) class;
parent_class = g_type_class_peek_parent(class);
object_class->destroy = gtk_rig_ctrl_destroy;
}
static void gtk_rig_ctrl_init(GtkRigCtrl * ctrl)
@ -211,13 +228,23 @@ static void gtk_rig_ctrl_init(GtkRigCtrl * ctrl)
ctrl->last_toggle_tx = -1;
}
static void gtk_rig_ctrl_destroy(GtkWidget * widget)
static void gtk_rig_ctrl_destroy(GtkObject * object)
{
GtkRigCtrl *ctrl = GTK_RIG_CTRL(widget);
GtkRigCtrl *ctrl = GTK_RIG_CTRL(object);
/* stop timer */
if (ctrl->timerid > 0)
g_source_remove(ctrl->timerid);
if (ctrl->rigctl_thread != NULL)
{
g_mutex_lock(&ctrl->widgetsync);
ctrl->engaged = 0;
setconfig(ctrl);
/* synchronization */
g_cond_wait(&ctrl->widgetready, &ctrl->widgetsync);
g_mutex_unlock(&ctrl->widgetsync);
ctrl->rigctl_thread = NULL;
}
/* free configuration */
if (ctrl->conf != NULL)
@ -242,12 +269,7 @@ static void gtk_rig_ctrl_destroy(GtkWidget * widget)
ctrl->trsplist = NULL;
}
/* close sockets if they are open */
if (ctrl->sock)
close_rigctld_socket(&(ctrl->sock));
if (ctrl->sock2)
close_rigctld_socket(&(ctrl->sock2));
(*GTK_WIDGET_CLASS(parent_class)->destroy) (widget);
(*GTK_OBJECT_CLASS(parent_class)->destroy) (object);
}
/**
@ -310,10 +332,6 @@ GtkWidget *gtk_rig_ctrl_new(GtkSatModule * module)
gtk_container_add(GTK_CONTAINER(widget), table);
GTK_RIG_CTRL(widget)->timerid = g_timeout_add(GTK_RIG_CTRL(widget)->delay,
rig_ctrl_timeout_cb,
GTK_RIG_CTRL(widget));
if (module->target > 0)
gtk_rig_ctrl_select_sat(GTK_RIG_CTRL(widget), module->target);
@ -333,6 +351,9 @@ void gtk_rig_ctrl_update(GtkRigCtrl * ctrl, gdouble t)
gdouble satfreq;
gchar *buff;
/* Enter critical section! */
g_mutex_lock(&ctrl->rig_ctrl_updatelock);
if (ctrl->target)
{
/* update Az/El */
@ -401,6 +422,8 @@ void gtk_rig_ctrl_update(GtkRigCtrl * ctrl, gdouble t)
ctrl->pass = get_next_pass(ctrl->target, ctrl->qth, 3.0);
}
}
/* Leave critical section! */
g_mutex_unlock(&ctrl->rig_ctrl_updatelock);
}
/** Select a satellite */
@ -941,7 +964,6 @@ static void sat_selected_cb(GtkComboBox * satsel, gpointer data)
free_pass(ctrl->pass);
ctrl->pass = NULL;
}
}
}
@ -1075,10 +1097,10 @@ static void delay_changed_cb(GtkSpinButton * spin, gpointer data)
ctrl->delay = (guint) gtk_spin_button_get_value(spin);
if (ctrl->timerid > 0)
g_source_remove(ctrl->timerid);
ctrl->timerid = g_timeout_add(ctrl->delay, rig_ctrl_timeout_cb, ctrl);
if (ctrl->engaged)
{
start_timer(ctrl);
}
}
/**
@ -1283,74 +1305,21 @@ static void rig_engaged_cb(GtkToggleButton * button, gpointer data)
gtk_widget_set_sensitive(ctrl->DevSel, TRUE);
gtk_widget_set_sensitive(ctrl->DevSel2, TRUE);
ctrl->engaged = FALSE;
ctrl->lasttxf = 0.0;
ctrl->lastrxf = 0.0;
if ((ctrl->conf->type == RIG_TYPE_TOGGLE_AUTO) ||
(ctrl->conf->type == RIG_TYPE_TOGGLE_MAN))
{
unset_toggle(ctrl, ctrl->sock);
}
if (ctrl->conf2 != NULL)
{
close_rigctld_socket(&(ctrl->sock2));
}
close_rigctld_socket(&(ctrl->sock));
/* stop worker thread... */
setconfig(ctrl);
ctrl->rigctl_thread = NULL;
}
else
{
gtk_widget_set_sensitive(ctrl->DevSel, FALSE);
gtk_widget_set_sensitive(ctrl->DevSel2, FALSE);
ctrl->engaged = TRUE;
ctrl->wrops = 0;
open_rigctld_socket(ctrl->conf, &(ctrl->sock));
/* set initial frequency */
if (ctrl->conf2 != NULL)
{
open_rigctld_socket(ctrl->conf2, &(ctrl->sock2));
/* set initial dual mode */
exec_dual_rig_cycle(ctrl);
}
else
{
switch (ctrl->conf->type)
{
case RIG_TYPE_RX:
exec_rx_cycle(ctrl);
break;
case RIG_TYPE_TX:
exec_tx_cycle(ctrl);
break;
case RIG_TYPE_TRX:
exec_trx_cycle(ctrl);
break;
case RIG_TYPE_DUPLEX:
/* set rig into SAT mode (hamlib needs it even if rig already in SAT) */
setup_split(ctrl);
exec_duplex_cycle(ctrl);
break;
case RIG_TYPE_TOGGLE_AUTO:
case RIG_TYPE_TOGGLE_MAN:
set_toggle(ctrl, ctrl->sock);
ctrl->last_toggle_tx = -1;
exec_toggle_cycle(ctrl);
break;
default:
/* this is an error! */
ctrl->conf->type = RIG_TYPE_RX;
exec_rx_cycle(ctrl);
break;
}
}
/* start worker thread... */
ctrl->rigctlq = g_async_queue_new();
ctrl->rigctl_thread = g_thread_new("rigctl_run", rigctl_run, ctrl);
setconfig(ctrl);
}
}
@ -1367,7 +1336,7 @@ static void rig_engaged_cb(GtkToggleButton * button, gpointer data)
static gboolean setup_split(GtkRigCtrl * ctrl)
{
gchar *buff;
gchar buffback[128];
gchar buffback[256 /*128 */ ]; /* issues with receiving rigctld answer (assertion failed) */
gboolean retcode;
/* select TX VFO */
@ -1458,7 +1427,7 @@ static gboolean rig_ctrl_timeout_cb(gpointer data)
sat_log_log(SAT_LOG_LEVEL_ERROR,
_("%s: Controller does not have a valid configuration"),
__func__);
return (TRUE);
return FALSE;
}
@ -1469,63 +1438,8 @@ static gboolean rig_ctrl_timeout_cb(gpointer data)
return TRUE;
}
check_aos_los(ctrl);
if (ctrl->conf2 != NULL)
{
exec_dual_rig_cycle(ctrl);
}
else
{
/* Execute controller cycle depending on primary radio type */
switch (ctrl->conf->type)
{
case RIG_TYPE_RX:
exec_rx_cycle(ctrl);
break;
case RIG_TYPE_TX:
exec_tx_cycle(ctrl);
break;
case RIG_TYPE_TRX:
exec_trx_cycle(ctrl);
break;
case RIG_TYPE_DUPLEX:
exec_duplex_cycle(ctrl);
break;
case RIG_TYPE_TOGGLE_AUTO:
case RIG_TYPE_TOGGLE_MAN:
exec_toggle_cycle(ctrl);
break;
default:
/* invalid mode */
sat_log_log(SAT_LOG_LEVEL_ERROR,
_("%s: Invalid radio type %d. Setting type to "
"RIG_TYPE_RX"), __func__, ctrl->conf->type);
ctrl->conf->type = RIG_TYPE_RX;
}
}
/* perform error count checking */
if (ctrl->errcnt >= MAX_ERROR_COUNT)
{
/* disengage device */
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ctrl->LockBut), FALSE);
ctrl->engaged = FALSE;
ctrl->errcnt = 0;
sat_log_log(SAT_LOG_LEVEL_ERROR,
_("%s: MAX_ERROR_COUNT (%d) reached. Disengaging device!"),
__func__, MAX_ERROR_COUNT);
//g_print ("ERROR. WROPS = %d\n", ctrl->wrops);
}
//g_print (" WROPS = %d\n", ctrl->wrops);
/* push event */
setconfig(ctrl);
g_mutex_unlock(&(ctrl->busy));
@ -1890,7 +1804,6 @@ static void exec_toggle_tx_cycle(GtkRigCtrl * ctrl)
}
/**
* \brief Execute TX cycle for full duplex radios.
* \param ctrl Pointer to the GtkRigCtrl structure.
@ -2058,8 +1971,7 @@ static void exec_dual_rig_cycle(GtkRigCtrl * ctrl)
{
satfreqd = readfreq + ctrl->conf->lo;
}
gtk_freq_knob_set_value(GTK_FREQ_KNOB(ctrl->SatFreqDown),
satfreqd);
gtk_freq_knob_set_value(GTK_FREQ_KNOB(ctrl->SatFreqDown), satfreqd);
/* Update uplink if locked to downlink */
if (ctrl->trsplock)
@ -2301,6 +2213,7 @@ static gboolean get_ptt(GtkRigCtrl * ctrl, gint sock)
pttstat = g_ascii_strtoull(vbuff[0], NULL, 0); //FIXME base = 0 ok?
g_strfreev(vbuff);
}
g_free(buff);
return (pttstat == 1) ? TRUE : FALSE;
@ -2326,8 +2239,8 @@ static gboolean set_ptt(GtkRigCtrl * ctrl, gint sock, gboolean ptt)
buff = g_strdup_printf("T 0\x0aq\x0a");
retcode = send_rigctld_command(ctrl, sock, buff, buffback, 128);
g_free(buff);
return (check_set_response(buffback, retcode, __func__));
}
@ -2511,6 +2424,7 @@ static gboolean get_freq_simplex(GtkRigCtrl * ctrl, gint sock, gdouble * freq)
retval = FALSE;
}
//g_free(buff);
return retval;
}
@ -2554,6 +2468,7 @@ static gboolean get_freq_toggle(GtkRigCtrl * ctrl, gint sock, gdouble * freq)
retval = FALSE;
}
//g_free(buff);
return retval;
}
@ -2886,6 +2801,9 @@ gboolean send_rigctld_command(GtkRigCtrl * ctrl, gint sock, gchar * buff,
gint written;
gint size;
/* Enter critical section! */
g_mutex_lock(&ctrl->writelock);
/* added by Marcel Cimander; win32 newline -> \10\13 */
#ifdef WIN32
size = strlen(buff) - 1;
@ -2933,6 +2851,9 @@ gboolean send_rigctld_command(GtkRigCtrl * ctrl, gint sock, gchar * buff,
}
ctrl->wrops++;
/* Leave critical section! */
g_mutex_unlock(&ctrl->writelock);
return TRUE;
}
@ -2961,7 +2882,7 @@ static gboolean key_press_cb(GtkWidget * widget, GdkEventKey * pKey,
switch (pKey->keyval)
{
/* keyvals not in API docs. See <gdk/gdkkeysyms.h> for a complete list */
case GDK_KEY_space:
case GDK_space:
sat_log_log(SAT_LOG_LEVEL_INFO,
_("%s: Detected SPACEBAR pressed event"), __func__);
@ -3175,8 +3096,8 @@ static inline gboolean check_set_response(gchar * buffback, gboolean retcode,
if (strncmp(buffback, "RPRT 0", 6) != 0)
{
sat_log_log(SAT_LOG_LEVEL_ERROR,
_("%s: %s rigctld returned error (%s)"),
__FILE__, function, buffback);
_("%s:%s: %s rigctld returned error (%s)"),
__FILE__, __func__, function, buffback);
retcode = FALSE;
}
@ -3200,8 +3121,8 @@ static inline gboolean check_get_response(gchar * buffback, gboolean retcode,
if (strncmp(buffback, "RPRT", 4) == 0)
{
sat_log_log(SAT_LOG_LEVEL_ERROR,
_("%s: %s rigctld returned error (%s)"),
__FILE__, function, buffback);
_("%s:%s: %s rigctld returned error (%s)"),
__FILE__, __func__, function, buffback);
retcode = FALSE;
}
@ -3209,3 +3130,245 @@ static inline gboolean check_get_response(gchar * buffback, gboolean retcode,
return retcode;
}
static void rigctrl_close(GtkRigCtrl * data)
{
GtkRigCtrl *ctrl = GTK_RIG_CTRL(data);
ctrl->lasttxf = 0.0;
ctrl->lastrxf = 0.0;
remove_timer(ctrl);
if ((ctrl->conf->type == RIG_TYPE_TOGGLE_AUTO) ||
(ctrl->conf->type == RIG_TYPE_TOGGLE_MAN))
{
unset_toggle(ctrl, ctrl->sock);
}
if (ctrl->conf2 != NULL)
{
close_rigctld_socket(&(ctrl->sock2));
}
close_rigctld_socket(&(ctrl->sock));
}
static void rigctrl_open(GtkRigCtrl * data)
{
GtkRigCtrl *ctrl = GTK_RIG_CTRL(data);
ctrl->wrops = 0;
start_timer(ctrl);
open_rigctld_socket(ctrl->conf, &(ctrl->sock));
/* set initial frequency */
if (ctrl->conf2 != NULL)
{
open_rigctld_socket(ctrl->conf2, &(ctrl->sock2));
/* set initial dual mode */
exec_dual_rig_cycle(ctrl);
}
else
{
switch (ctrl->conf->type)
{
case RIG_TYPE_RX:
exec_rx_cycle(ctrl);
break;
case RIG_TYPE_TX:
exec_tx_cycle(ctrl);
break;
case RIG_TYPE_TRX:
exec_trx_cycle(ctrl);
break;
case RIG_TYPE_DUPLEX:
/* set rig into SAT mode (hamlib needs it even if rig already in SAT) */
setup_split(ctrl);
exec_duplex_cycle(ctrl);
break;
case RIG_TYPE_TOGGLE_AUTO:
case RIG_TYPE_TOGGLE_MAN:
set_toggle(ctrl, ctrl->sock);
ctrl->last_toggle_tx = -1;
exec_toggle_cycle(ctrl);
break;
default:
/* this is an error! */
ctrl->conf->type = RIG_TYPE_RX;
exec_rx_cycle(ctrl);
break;
}
}
}
/**
* \brief Communication thread for hamlib rigctld
* \param data
* \return NULL
*/
gpointer rigctl_run(gpointer data)
{
GtkRigCtrl *ctrl = GTK_RIG_CTRL(data);
GtkRigCtrl *t_ctrl = GTK_RIG_CTRL(data);
while (1)
{
t_ctrl = GTK_RIG_CTRL(g_async_queue_pop(ctrl->rigctlq));
ctrl = t_ctrl;
while (g_main_context_iteration(NULL, FALSE));
if (t_ctrl == NULL)
{
sat_log_log(SAT_LOG_LEVEL_ERROR,
_("%s:%s: ERROR: NO VALID ctrl-struct"), __FILE__,
__func__);
continue;
}
if (t_ctrl->engaged)
{
if (!t_ctrl->sock)
{
rigctrl_open(t_ctrl);
}
if (!t_ctrl->timerid)
{
start_timer(t_ctrl);
}
}
else
{
g_mutex_lock(&t_ctrl->widgetsync);
if (t_ctrl->sock > 0)
{
rigctrl_close(t_ctrl);
}
if (t_ctrl->timerid)
{
remove_timer(t_ctrl);
}
g_cond_signal(&t_ctrl->widgetready);
g_mutex_unlock(&t_ctrl->widgetsync);
break;
}
check_aos_los(t_ctrl);
if (t_ctrl->conf2 != NULL)
{
exec_dual_rig_cycle(t_ctrl);
}
else
{
/* Execute controller cycle depending on primary radio type */
switch (t_ctrl->conf->type)
{
case RIG_TYPE_RX:
exec_rx_cycle(t_ctrl);
break;
case RIG_TYPE_TX:
exec_tx_cycle(t_ctrl);
break;
case RIG_TYPE_TRX:
exec_trx_cycle(t_ctrl);
break;
case RIG_TYPE_DUPLEX:
exec_duplex_cycle(t_ctrl);
break;
case RIG_TYPE_TOGGLE_AUTO:
case RIG_TYPE_TOGGLE_MAN:
exec_toggle_cycle(t_ctrl);
break;
default:
/* invalid mode */
sat_log_log(SAT_LOG_LEVEL_ERROR,
_("%s:%s: Invalid radio type %d. Setting type to "
"RIG_TYPE_RX"), __FILE__, __func__,
t_ctrl->conf->type);
t_ctrl->conf->type = RIG_TYPE_RX;
}
}
/* perform error count checking */
if (t_ctrl->errcnt >= MAX_ERROR_COUNT)
{
/* disengage device */
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(t_ctrl->LockBut),
FALSE);
t_ctrl->engaged = FALSE;
t_ctrl->errcnt = 0;
sat_log_log(SAT_LOG_LEVEL_ERROR,
_
("%s:%s: MAX_ERROR_COUNT (%d) reached. Disengaging device!"),
__FILE__, __func__, MAX_ERROR_COUNT);
//g_print ("ERROR. WROPS = %d\n", ctrl->wrops);
}
//g_print (" WROPS = %d\n", ctrl->wrops);
}
/* let's have a clean exit: */
if (t_ctrl->sock > 0)
{
rigctrl_close(t_ctrl);
}
if (t_ctrl->timerid)
{
remove_timer(t_ctrl);
}
return NULL;
}
void start_timer(GtkRigCtrl * data)
{
GtkRigCtrl *ctrl = GTK_RIG_CTRL(data);
/* start timeout timer here ("Cycle")! */
if (ctrl->timerid > 0)
g_source_remove(ctrl->timerid);
ctrl->timerid =
gdk_threads_add_timeout(ctrl->delay, rig_ctrl_timeout_cb, ctrl);
}
void remove_timer(GtkRigCtrl * data)
{
GtkRigCtrl *ctrl = GTK_RIG_CTRL(data);
/* stop timer */
if (ctrl->timerid > 0)
g_source_remove(ctrl->timerid);
ctrl->timerid = 0;
}
void setconfig(gpointer data)
{
/* something has changed... */
GtkRigCtrl *ctrl = GTK_RIG_CTRL(data);
if (ctrl != NULL)
{
g_async_queue_push(ctrl->rigctlq, ctrl);
}
}

View file

@ -108,6 +108,16 @@ struct _gtk_rig_ctrl {
/* debug related */
guint wrops;
guint rdops;
/* DL4PD */
/* threads related stuff */
/* add mutexes etc, to make threads reentrant! */
GMutex writelock; /*!< Mutex for blocking write operation */
GMutex rig_ctrl_updatelock; /*!< Mutex wile updating widgets etc */
GMutex widgetsync; /*!< Mutex used while leaving (sync stuff) */
GCond widgetready; /*!< Condition when work is done (sync stuff) */
GAsyncQueue *rigctlq; /*!< Message queue to indicate something has changed */
GThread *rigctl_thread; /*!< Pointer to current rigctl-thread */
};
struct _GtkRigCtrlClass {