1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3     Grig:  Gtk+ user interface for the Hamradio Control Libraries.
4 
5     Copyright (C)  2001-2007  Alexandru Csete.
6 
7     Authors: Alexandru Csete <oz9aec@gmail.com>
8 
9     Comments, questions and bugreports should be submitted via
10     http://sourceforge.net/projects/groundstation/
11     More details can be found at the project home page:
12 
13             http://groundstation.sourceforge.net/
14 
15     This program is free software; you can redistribute it and/or modify
16     it under the terms of the GNU General Public License as published by
17     the Free Software Foundation; either version 2 of the License, or
18     (at your option) any later version.
19 
20     This program is distributed in the hope that it will be useful,
21     but WITHOUT ANY WARRANTY; without even the implied warranty of
22     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     GNU General Public License for more details.
24 
25     You should have received a copy of the GNU General Public License
26     along with this program; if not, visit http://www.fsf.org/
27 
28 
29 
30 
31 */
32 #include <gtk/gtk.h>
33 #include <hamlib/rig.h>
34 #include <glib/gi18n.h>
35 #include "rig-data.h"
36 #include "rig-utils.h"
37 #include "grig-gtk-workarounds.h"
38 #include "grig-debug.h"
39 #include "rig-gui-vfo.h"
40 
41 
42 
43 
44 
45 /* private function prototypes */
46 
47 /* VFO frame */
48 static GtkWidget *rig_gui_vfo_create_toggle       (void);
49 static GtkWidget *rig_gui_vfo_create_eq_button    (void);
50 static GtkWidget *rig_gui_vfo_create_xchg_button  (void);
51 static GtkWidget *rig_gui_vfo_create_split_button (void);
52 static GtkWidget *rig_gui_vfo_create_mem_button (void);
53 
54 static void rig_gui_vfo_toggle_cb  (GtkWidget *, gpointer);
55 static void rig_gui_vfo_eq_cb      (GtkWidget *, gpointer);
56 static void rig_gui_vfo_xchg_cb    (GtkWidget *, gpointer);
57 static void rig_gui_vfo_split_cb   (GtkWidget *, gpointer);
58 static void rig_gui_vfo_memory_cb  (GtkWidget *, gpointer);
59 
60 /* MEM Frame */
61 
62 
63 /* Band frame */
64 
65 
66 /** \brief Create VFO operation controls.
67  *  \return a composite widget containing the controls.
68  *
69  */
70 GtkWidget *
rig_gui_vfo_create()71 rig_gui_vfo_create ()
72 {
73 /*    GtkWidget *hbox;
74     GtkWidget *vfobox;
75     GtkWidget *bandbox;
76 */
77     GtkWidget *grid;
78 
79     /* VFO Frame */
80 /*    vfobox = gtk_vbutton_box_new ();
81     gtk_button_box_set_layout (GTK_BUTTON_BOX (vfobox), GTK_BUTTONBOX_START);
82     gtk_container_add (GTK_CONTAINER (vfobox), rig_gui_vfo_create_toggle ());
83     gtk_container_add (GTK_CONTAINER (vfobox), rig_gui_vfo_create_split_button ());
84     gtk_container_add (GTK_CONTAINER (vfobox), rig_gui_vfo_create_eq_button ());
85     gtk_container_add (GTK_CONTAINER (vfobox), rig_gui_vfo_create_xchg_button ());*/
86 
87     grid = gtk_table_new (4, 3, TRUE);
88     gtk_table_attach_defaults (GTK_TABLE (grid), rig_gui_vfo_create_toggle (), 0, 1, 0, 1);
89     gtk_table_attach_defaults (GTK_TABLE (grid), rig_gui_vfo_create_split_button (), 1, 2, 0, 1);
90     gtk_table_attach_defaults (GTK_TABLE (grid), rig_gui_vfo_create_eq_button (), 0, 1, 1, 2);
91     gtk_table_attach_defaults (GTK_TABLE (grid), rig_gui_vfo_create_xchg_button (),    1, 2, 1, 2);
92     gtk_table_attach_defaults (GTK_TABLE (grid), rig_gui_vfo_create_mem_button (), 0, 1, 2, 3);
93 
94     /* BAND UP/DOWN */
95     /* XXX not yet implemented */
96 /*
97     bandbox = gtk_hbutton_box_new ();
98     gtk_button_box_set_layout (GTK_BUTTON_BOX (bandbox), GTK_BUTTONBOX_END);
99 */
100     return grid;
101 }
102 
103 
104 /**** A/B button ****/
105 
106 
107 static GtkWidget *
rig_gui_vfo_create_toggle()108 rig_gui_vfo_create_toggle ()
109 {
110     GtkWidget   *button;
111     gint         vfos;
112 
113     /* Create button widget.
114            The label will be "A/B" if the rig has VFO_A and VFO_B
115            or Main/Sub if the rig has those two.
116         */
117     vfos = rig_data_get_vfos ();
118     if (vfos & RIG_VFO_MAIN) {
119         button = gtk_button_new_with_label (_("Main / Sub"));
120         gtk_widget_set_tooltip_text (button, _("Toggle active VFO"));
121     }
122     else {
123         button = gtk_button_new_with_label (_("A / B"));
124         gtk_widget_set_tooltip_text (button, _("Toggle between available VFOs"));
125     }
126 
127 
128         /* Disable control if the rig has no capability of
129            either setting a specific VFO or to toggle
130         */
131     if (!(rig_data_has_vfo_op_toggle () ||
132               (rig_data_has_set_vfo () && rig_data_has_get_vfo ())) ){
133         gtk_widget_set_sensitive (button, FALSE);
134     }
135 
136 
137     /* connect "toggle" signal */
138     g_signal_connect (G_OBJECT (button), "pressed",
139                   G_CALLBACK (rig_gui_vfo_toggle_cb),
140                   NULL);
141 
142 
143     return button;
144 }
145 
146 
147 
148 
149 static void
rig_gui_vfo_toggle_cb(GtkWidget * widget,gpointer data)150 rig_gui_vfo_toggle_cb (GtkWidget *widget, gpointer data)
151 {
152 
153     if (rig_data_has_vfo_op_toggle ()) {
154         rig_data_vfo_op_toggle ();
155     }
156     else if (rig_data_has_set_vfo () &&
157                  rig_data_has_get_vfo ()) {
158 
159         /* do not toggle in memory mode */
160         /* XXX disable other VFO buttons? */
161         if (rig_data_get_vfo() == RIG_VFO_MEM)
162             return;
163 
164                 /* do we have VFO A and B? */
165                 if (rig_data_get_vfos() & (RIG_VFO_A | RIG_VFO_B)) {
166 
167                         if (rig_data_get_vfo () == RIG_VFO_A) {
168                                 rig_data_set_vfo (RIG_VFO_B);
169                         }
170                         else {
171                                 rig_data_set_vfo (RIG_VFO_A);
172                         }
173 
174                 }
175                 /* else try MAIN/SUB */
176                 else if (rig_data_get_vfos () & (RIG_VFO_MAIN | RIG_VFO_SUB)) {
177 
178                         if (rig_data_get_vfo () == RIG_VFO_MAIN) {
179                                 rig_data_set_vfo (RIG_VFO_SUB);
180                         }
181                         else {
182                                 rig_data_set_vfo (RIG_VFO_MAIN);
183                         }
184                 }
185 
186                 /* it's a bug, because button should be disabled */
187                 else {
188                         grig_debug_local (RIG_DEBUG_BUG,
189                       "%s: VFO_TOGGLE button should have been disabled "\
190                       "(neither A/B nor MAIN/SUB)\n", __FUNCTION__);
191                 }
192     }
193 
194         /* it's a bug, because button should be disabled */
195         else {
196         grig_debug_local (RIG_DEBUG_BUG,
197                   "%s: VFO_TOGGLE button should have been disabled "\
198                   "(no way to toggle)\n", __FUNCTION__);
199         }
200 
201 }
202 
203 static void
rig_gui_vfo_memory_cb(GtkWidget * widget,gpointer data)204 rig_gui_vfo_memory_cb(GtkWidget *widget, gpointer data)
205 {
206     if (rig_data_has_set_vfo() && rig_data_has_get_vfo()) {
207 
208             if (rig_data_get_vfo() != RIG_VFO_MEM) {
209             g_object_set_data(G_OBJECT(widget),
210                 "vfo", (gpointer) rig_data_get_vfo());
211 
212              rig_data_set_vfo(RIG_VFO_MEM);
213 
214         } else {
215              rig_data_set_vfo((vfo_t) g_object_get_data(G_OBJECT(widget),
216                         "vfo"));
217         }
218     }
219 }
220 
221 /**** A=B button ****/
222 
223 static GtkWidget *
rig_gui_vfo_create_eq_button()224 rig_gui_vfo_create_eq_button ()
225 {
226     GtkWidget   *button;
227     gint         vfos;
228 
229     /* Create button widget.
230            The label will be "A=B" if the rig has VFO_A and VFO_B
231            or Main=Sub if the rig has those two.
232         */
233     vfos = rig_data_get_vfos ();
234     if (vfos & RIG_VFO_MAIN) {
235         button = gtk_button_new_with_label (_("Main = Sub"));
236         gtk_widget_set_tooltip_text (button,_("Set Main VFO = Sub VFO"));
237     }
238     else {
239         button = gtk_button_new_with_label (_("A = B"));
240         gtk_widget_set_tooltip_text (button, _("Set VFO B = VFO A"));
241     }
242         /* Disable control if the rig has no capability of
243            either setting a specific VFO or to toggle
244         */
245     if (!(rig_data_has_vfo_op_toggle () ||
246               (rig_data_has_set_vfo () && rig_data_has_get_vfo ())) ){
247         gtk_widget_set_sensitive (button, FALSE);
248     }
249 
250 
251     /* connect "toggle" signal */
252     g_signal_connect (G_OBJECT (button), "pressed",
253                   G_CALLBACK (rig_gui_vfo_eq_cb),
254                   NULL);
255 
256 
257     return button;
258 }
259 
260 
261 
262 
263 static void
rig_gui_vfo_eq_cb(GtkWidget * widget,gpointer data)264 rig_gui_vfo_eq_cb (GtkWidget *widget, gpointer data)
265 {
266 
267     if (rig_data_has_vfo_op_copy ()) {
268         rig_data_vfo_op_copy ();
269     }
270     else if (rig_data_has_set_vfo () &&
271                  rig_data_has_get_vfo ()) {
272 
273         grig_debug_local (RIG_DEBUG_BUG,
274                   "%s: VFO COPY without RIG_OP_COPY not imlemented\n",
275                   __FUNCTION__);
276 
277     }
278 
279         /* it's a bug, because button should be disabled */
280         else {
281         grig_debug_local (RIG_DEBUG_BUG,
282                   "%s: VFO_EQ button should have been disabled "\
283                   "(no way to equalise)\n", __FUNCTION__);
284         }
285 
286 }
287 
288 
289 
290 /**** A<->B button ****/
291 
292 static GtkWidget *
rig_gui_vfo_create_xchg_button()293 rig_gui_vfo_create_xchg_button ()
294 {
295     GtkWidget   *button;
296     gint         vfos;
297 
298     /* Create button widget.
299            The label will be "A<->B" if the rig has VFO_A and VFO_B
300            or Main<->Sub if the rig has those two.
301         */
302     vfos = rig_data_get_vfos ();
303     if (vfos & RIG_VFO_MAIN) {
304         button = gtk_button_new_with_label (_("Main\302\253\302\273Sub"));
305         gtk_widget_set_tooltip_text (button, _("Exchange Main and sub VFOs"));
306     }
307     else {
308         button = gtk_button_new_with_label (_("A\302\253\302\273B"));
309         gtk_widget_set_tooltip_text (button, _("Exchange VFO A and B"));
310     }
311 
312 
313         /* Disable control if the rig has no capability of
314            either setting a specific VFO or to toggle
315         */
316     if (!(rig_data_has_vfo_op_xchg () ||
317               (rig_data_has_set_vfo () && rig_data_has_get_vfo ())) ){
318         gtk_widget_set_sensitive (button, FALSE);
319     }
320 
321 
322     /* connect "toggle" signal */
323     g_signal_connect (G_OBJECT (button), "pressed",
324                   G_CALLBACK (rig_gui_vfo_xchg_cb),
325                   NULL);
326 
327 
328     return button;
329 }
330 
331 
332 
333 
334 static void
rig_gui_vfo_xchg_cb(GtkWidget * widget,gpointer data)335 rig_gui_vfo_xchg_cb (GtkWidget *widget, gpointer data)
336 {
337 
338     if (rig_data_has_vfo_op_xchg ()) {
339         rig_data_vfo_op_xchg ();
340     }
341     else if (rig_data_has_set_vfo () &&
342                  rig_data_has_get_vfo ()) {
343 
344         grig_debug_local (RIG_DEBUG_BUG,
345                   "%s: VFO XCHG without RIG_OP_XCHG not imlemented\n",
346                   __FUNCTION__);
347 
348     }
349 
350         /* it's a bug, because button should be disabled */
351         else {
352         grig_debug_local (RIG_DEBUG_BUG,
353                   "%s: VFO_XCHG button should have been disabled "\
354                   "(no way to exchange)\n", __FUNCTION__);
355         }
356 
357 }
358 
359 
360 
361 
362 /**** SPLIT button ****/
363 /** FIXME: need readback from RIG **/
364 static GtkWidget *
rig_gui_vfo_create_split_button()365 rig_gui_vfo_create_split_button ()
366 {
367     GtkWidget   *button;
368 
369 
370     button = gtk_toggle_button_new_with_label (_("Split"));
371     gtk_widget_set_tooltip_text (button, _("Toggle split mode operation"));
372 
373     /* set button status before we do anything else */
374     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
375                       rig_data_get_split ());
376 
377         /* Disable control if the rig has no capability of
378            either setting a specific VFO or to toggle
379         */
380     if (!(rig_data_has_set_split ()))  {
381         gtk_widget_set_sensitive (button, FALSE);
382     }
383 
384 
385     /* connect "toggle" signal */
386     g_signal_connect (G_OBJECT (button), "toggled",
387                   G_CALLBACK (rig_gui_vfo_split_cb),
388                   NULL);
389 
390 
391     return button;
392 }
393 
394 static GtkWidget *
rig_gui_vfo_create_mem_button()395 rig_gui_vfo_create_mem_button()
396 {
397     GtkWidget   *button;
398 
399     button = gtk_button_new_with_label(_("M / V"));
400     gtk_widget_set_tooltip_text (button, _("Toggle between memory and VFO"));
401 
402     /* Disable control if the rig has no memory vfo */
403     if (!(rig_data_get_vfos() & RIG_VFO_MEM))  {
404         gtk_widget_set_sensitive(button, FALSE);
405     }
406 
407     g_object_set_data(G_OBJECT(button), "vfo", (gpointer) RIG_VFO_VFO);
408 
409     g_signal_connect(G_OBJECT (button), "pressed",
410             G_CALLBACK (rig_gui_vfo_memory_cb), NULL);
411     return button;
412 }
413 
414 static void
rig_gui_vfo_split_cb(GtkWidget * widget,gpointer data)415 rig_gui_vfo_split_cb (GtkWidget *widget, gpointer data)
416 {
417     if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
418         rig_data_set_split (TRUE);
419     }
420     else {
421         rig_data_set_split (FALSE);
422     }
423 }
424