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 /** \file rig-state.c
30 * \brief Load and save rig state
31 *
32 * The rig state is a snapshot of the current settings in the rig-data
33 * object. The rig state is saved to a file using the glib key/value
34 * infrastructure.
35 *
36 */
37 #include <gtk/gtk.h>
38 #include <glib/gi18n.h>
39 #include <hamlib/rig.h>
40 #ifdef HAVE_CONFIG_H
41 # include <config.h>
42 #endif
43 #include "rig-utils.h"
44 #include "grig-debug.h"
45 #include "rig-daemon.h"
46 #include "rig-data.h"
47 #include "rig-state.h"
48
49
50
51 extern GtkWidget *grigapp;
52
53 #define GEN_GRP "GENERAL"
54 #define DEV_GRP "DEVICE"
55 #define FREQ_GRP "FREQUENCY"
56 #define LEVEL_GRP "LEVELS"
57 #define MODE_GRP "MODE"
58
59
60 static gint rig_state_write_data (GKeyFile *cfgdata, const gchar *file);
61 static gboolean ask_cfm (gint state_id, gint rig_id);
62 static gboolean read_and_check_level (GKeyFile *cfgdata,
63 const gchar *group,
64 const gchar *key,
65 gfloat *param,
66 gboolean *newflag);
67
68 static gboolean read_and_check_double (GKeyFile *cfgdata,
69 const gchar *group,
70 const gchar *key,
71 gdouble *param,
72 gboolean *newflag);
73
74 static gboolean read_and_check_int (GKeyFile *cfgdata,
75 const gchar *group,
76 const gchar *key,
77 gint *param,
78 gboolean *newflag);
79
80 static gboolean read_and_check_bool (GKeyFile *cfgdata,
81 const gchar *group,
82 const gchar *key,
83 gboolean *param,
84 gboolean *newflag);
85
86
87 /** \brief Get connection info about radio
88 *
89 * This fiunction will return connection details found in the
90 * specified rig state file. This can be used to re-establish
91 * the link to a radio when the rig state file is loaded via
92 * the command line. When the rig state is read via the menu
93 * bar, grig is already running a connection and this can not
94 * be changed. In those cases this function has no use.
95 */
96 /* gint */
97 /* rig_state_get_link_info (const gchar *file, */
98 /* rig_model_t *model, */
99 /* gchar *model, */
100 /* gchar *mfg, */
101 /* gchar *port, */
102 /* int *ser_rate) */
103 /* { */
104
105 /* } */
106
107
108
109 /** \brief Load the rig state
110 *
111 * This function first asks the user for a file name via the
112 * GtkFileChooser dialog, whereafter it calls rig_state_load
113 * with the specified file name.
114 * An error message is generated if the file does not exist or
115 * the contents could not be read.
116 */
117 void
rig_state_load_cb(GtkWidget * widget,gpointer data)118 rig_state_load_cb (GtkWidget *widget, gpointer data)
119 {
120 GtkWidget *dialog; /* file chooser dialog */
121 GtkFileFilter *filter1; /* *.rig filter used in the dialog */
122 GtkFileFilter *filter2; /* filter used in the dialog for all files */
123 gchar *filename; /* file name selected by user */
124
125 GtkWidget *msgdiag; /* message dialog */
126 gint status; /* error status */
127
128
129 /* create file chooser dialog */
130 dialog = gtk_file_chooser_dialog_new (_("Load Rig State"),
131 GTK_WINDOW (grigapp),
132 GTK_FILE_CHOOSER_ACTION_OPEN,
133 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
134 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
135 NULL);
136
137 /* Add filters for .rig files and all files */
138 filter1 = gtk_file_filter_new ();
139 gtk_file_filter_set_name (filter1, _("Rig state files (*.rig)"));
140 gtk_file_filter_add_pattern (filter1, "*.rig");
141 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter1);
142
143 filter2 = gtk_file_filter_new ();
144 gtk_file_filter_set_name (filter2, _("All files"));
145 gtk_file_filter_add_pattern (filter2, "*");
146 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter2);
147
148
149 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
150
151 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
152
153 /* check that file exists and it is a regular file */
154 if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
155
156 status = rig_state_load (filename);
157
158 if (status) {
159 msgdiag = gtk_message_dialog_new (GTK_WINDOW (grigapp),
160 GTK_DIALOG_MODAL |
161 GTK_DIALOG_DESTROY_WITH_PARENT,
162 GTK_MESSAGE_ERROR,
163 GTK_BUTTONS_OK,
164 _("There was an error reading "\
165 "the settings from:\n\n "\
166 "%s\n\n "\
167 "Examine the log messages "\
168 "for further info."),
169 filename);
170 gtk_dialog_run (GTK_DIALOG (msgdiag));
171 gtk_widget_destroy (msgdiag);
172 }
173
174 }
175 else {
176 /* tell user to select an existing file */
177 msgdiag = gtk_message_dialog_new (GTK_WINDOW (grigapp),
178 GTK_DIALOG_MODAL |
179 GTK_DIALOG_DESTROY_WITH_PARENT,
180 GTK_MESSAGE_ERROR,
181 GTK_BUTTONS_OK,
182 _("The selected file:\n "\
183 "%s\n "\
184 "does not exist or is not "\
185 "a regular file."),
186 filename);
187 gtk_dialog_run (GTK_DIALOG (msgdiag));
188 gtk_widget_destroy (msgdiag);
189 }
190
191 g_free (filename);
192 }
193
194 gtk_file_chooser_remove_filter (GTK_FILE_CHOOSER (dialog), filter1);
195 gtk_file_chooser_remove_filter (GTK_FILE_CHOOSER (dialog), filter2);
196 gtk_widget_destroy (dialog);
197
198 }
199
200
201 /** \brief Save the rig state
202 *
203 * This function first asks the user for a file name via the
204 * GtkFileChooser dialog, whereafter it calls rig_state_save
205 * with the specified file name.
206 * If the file already exists it will ask the user whether to
207 * replace the contents or not. If not, the code returns to the
208 * file chooser.
209 *
210 * The complete algorithm:
211 *
212 * while (!done) {
213 * if (run_file_chooser == YES) {
214 * get_filename
215 * if (file_exists) {
216 * create_cfm_dialog
217 * if (do_overwrite) {
218 * save_file
219 * if (error)
220 * show_error_message
221 * done = TRUE
222 * } else {
223 * done = FALSE
224 * }
225 * destroy_cfm_dialog
226 * } else {
227 * save_file
228 * if (error)
229 * show_error_message
230 * done = TRUE
231 * }
232 * } else {
233 * done = TRUE
234 * }
235 * }
236 */
237 void
rig_state_save_cb(GtkWidget * widget,gpointer data)238 rig_state_save_cb (GtkWidget *widget, gpointer data)
239 {
240 GtkWidget *dialog; /* file chooser dialog */
241 GtkFileFilter *filter1; /* *.rig filter used in the dialog */
242 GtkFileFilter *filter2; /* filter used in the dialog for all files */
243 gchar *filename; /* file name selected by user */
244
245 GtkWidget *msgdiag; /* message dialog */
246 gint status; /* error status */
247
248 gboolean done = FALSE; /* flag to indicate whether we are done or not */
249 GtkWidget *cfmdiag; /* configrmation dialog */
250
251
252 /* create file chooser dialog */
253 dialog = gtk_file_chooser_dialog_new (_("Save Rig State"),
254 GTK_WINDOW (grigapp),
255 GTK_FILE_CHOOSER_ACTION_SAVE,
256 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
257 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
258 NULL);
259
260 /* Add filters for .rig files and all files */
261 filter1 = gtk_file_filter_new ();
262 gtk_file_filter_set_name (filter1, _("Rig state files (*.rig)"));
263 gtk_file_filter_add_pattern (filter1, "*.rig");
264 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter1);
265
266 filter2 = gtk_file_filter_new ();
267 gtk_file_filter_set_name (filter2, _("All files"));
268 gtk_file_filter_add_pattern (filter2, "*");
269 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter2);
270
271
272 /* loop until we save the settings or the user selects cancel
273 in the file chooser dialog
274 */
275 while (!done) {
276
277 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
278
279 /* user selected OK */
280 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
281 rig_utils_chk_ext (&filename, ".rig");
282 grig_debug_local (RIG_DEBUG_VERBOSE,
283 _("%s: User selected new file:\n%s"),
284 __FUNCTION__, filename);
285
286 /* if file exists warn user and ask for confirmation */
287 if (g_file_test (filename, G_FILE_TEST_EXISTS)) {
288
289 /* create warning/confirmation dialog */
290 cfmdiag = gtk_message_dialog_new (GTK_WINDOW (dialog),
291 GTK_DIALOG_MODAL |
292 GTK_DIALOG_DESTROY_WITH_PARENT,
293 GTK_MESSAGE_QUESTION,
294 GTK_BUTTONS_YES_NO,
295 _("Selected file already exists.\n"\
296 "Overwrite file?"));
297
298 /* if user says YES, save file and bail out */
299 if (gtk_dialog_run (GTK_DIALOG (cfmdiag)) == GTK_RESPONSE_YES) {
300
301 status = rig_state_save (filename);
302
303 if (status) {
304
305 /* save function returned non-zero value
306 => show error dialog
307 */
308 msgdiag = gtk_message_dialog_new (GTK_WINDOW (grigapp),
309 GTK_DIALOG_MODAL |
310 GTK_DIALOG_DESTROY_WITH_PARENT,
311 GTK_MESSAGE_ERROR,
312 GTK_BUTTONS_OK,
313 _("There was an error saving "\
314 "the settings to:\n\n "\
315 "%s\n\n "\
316 "Examine the log messages "\
317 "for further info."),
318 filename);
319 gtk_dialog_run (GTK_DIALOG (msgdiag));
320 gtk_widget_destroy (msgdiag);
321
322 }
323 done = TRUE;
324
325 } else {
326 /* else bail out and re-run file chooser */
327 done = FALSE;
328 }
329
330 gtk_widget_destroy (cfmdiag);
331
332 } else {
333
334 /* otherwise just save the file and we are done */
335 status = rig_state_save (filename);
336
337 if (status) {
338
339 /* save function returned non-zero value
340 => show error dialog
341 */
342 msgdiag = gtk_message_dialog_new (GTK_WINDOW (grigapp),
343 GTK_DIALOG_MODAL |
344 GTK_DIALOG_DESTROY_WITH_PARENT,
345 GTK_MESSAGE_ERROR,
346 GTK_BUTTONS_OK,
347 _("There was an error saving "\
348 "the settings to:\n\n "\
349 "%s\n\n "\
350 "Examine the log messages "\
351 "for further info."),
352 filename);
353 gtk_dialog_run (GTK_DIALOG (msgdiag));
354 gtk_widget_destroy (msgdiag);
355
356 }
357
358 /* set flag so that process can terminate */
359 done = TRUE;
360 }
361
362 g_free (filename);
363
364 } else {
365
366 /* user pressed CANCEL; terminate process */
367 done = TRUE;
368
369 }
370 }
371
372 gtk_file_chooser_remove_filter (GTK_FILE_CHOOSER (dialog), filter1);
373 gtk_file_chooser_remove_filter (GTK_FILE_CHOOSER (dialog), filter2);
374 gtk_widget_destroy (dialog);
375 }
376
377
378
379 /** \brief Load rig state from file
380 * \param file The file to read the rig state from
381 *
382 * The file parameter may not be NULL. If you need to open
383 * the file selector use the callback functions instead.
384 */
385 gint
rig_state_load(const gchar * file)386 rig_state_load (const gchar *file)
387 {
388 GKeyFile *cfgdata; /* the data */
389 GError *error = NULL; /* error buffer */
390 grig_settings_t *state; /* pointer to current rig state */
391 grig_cmd_avail_t *newval; /* pointer to new flag struct */
392 gint vali;
393 gboolean valb;
394 gboolean errorflag = 0;
395 gboolean loadstate = 1; /* flag to indicate whether to laod state */
396
397
398
399 cfgdata = g_key_file_new ();
400 g_key_file_load_from_file (cfgdata, file, G_KEY_FILE_NONE, &error);
401
402 if (error != NULL) {
403
404 /* send an error message */
405 grig_debug_local (RIG_DEBUG_ERR,
406 _("%s: Error loading rig file (%s)"),
407 __FUNCTION__, error->message);
408
409 g_clear_error (&error);
410
411 errorflag |= 1;
412 }
413 else {
414 /* get and check rig id */
415 vali = g_key_file_get_integer (cfgdata, DEV_GRP, "ID", &error);
416 if (error != NULL) {
417 vali = 1;
418 grig_debug_local (RIG_DEBUG_ERR,
419 _("%s: Error reading rig id (%s)"),
420 __FUNCTION__, error->message);
421 g_clear_error (&error);
422 errorflag |= 1;
423 loadstate = FALSE;
424 }
425 else {
426 /* check rig id */
427 if (vali != rig_daemon_get_rig_id ()) {
428
429 grig_debug_local (RIG_DEBUG_WARN,
430 _("%s: ID mismatch detected: state id is %d\n"\
431 "while current rig id is %d"),
432 __FUNCTION__,
433 vali,
434 rig_daemon_get_rig_id ());
435
436 /* ask user whether to apply settings */
437 loadstate = ask_cfm (vali, rig_daemon_get_rig_id ());
438
439 }
440 else {
441
442 loadstate = TRUE;
443 }
444 }
445
446
447 if (loadstate) {
448 grig_debug_local (RIG_DEBUG_VERBOSE,
449 _("%s: Applying settings (model=%d)"),
450 __FUNCTION__, vali);
451
452 /* disable daemon */
453 rig_daemon_set_suspend (TRUE);
454
455 /* link state to rig-data.set */
456 state = rig_data_get_set_addr ();
457
458 /* link newval to rig-data.new */
459 newval = rig_data_get_new_addr ();
460
461 /* read frequencies, vfo, rit, xit, split and lock */
462 errorflag |= read_and_check_double (cfgdata,
463 FREQ_GRP, "FREQ1",
464 &(state->freq1),
465 &(newval->freq1));
466
467 errorflag |= read_and_check_double (cfgdata,
468 FREQ_GRP, "FREQ2",
469 &(state->freq2),
470 &(newval->freq2));
471
472 /* RIT and XIT need to be converted */
473 errorflag |= read_and_check_int (cfgdata,
474 FREQ_GRP, "RIT",
475 &vali,
476 &(newval->rit));
477 state->rit = (shortfreq_t) vali;
478 errorflag |= read_and_check_int (cfgdata,
479 FREQ_GRP, "XIT",
480 &vali,
481 &(newval->xit));
482 state->xit = (shortfreq_t) vali;
483
484 errorflag |= read_and_check_int (cfgdata,
485 FREQ_GRP, "VFO",
486 (int *)&(state->vfo),
487 &(newval->vfo));
488 errorflag |= read_and_check_bool (cfgdata,
489 FREQ_GRP, "SPLIT",
490 &valb,
491 &(newval->split));
492 state->split = (split_t) valb;
493
494 errorflag |= read_and_check_bool (cfgdata,
495 FREQ_GRP, "LOCK",
496 &(state->lock),
497 &(newval->lock));
498
499 /* mode and filter */
500 errorflag |= read_and_check_int (cfgdata,
501 MODE_GRP, "MODE",
502 &vali,
503 &(newval->mode));
504 state->mode = (rmode_t) vali;
505 errorflag |= read_and_check_int (cfgdata,
506 MODE_GRP, "FILTER",
507 &vali,
508 &(newval->pbw));
509 state->pbw = (rig_data_pbw_t) vali;
510
511 /* ATT/PREAMP/AGC */
512 errorflag |= read_and_check_int (cfgdata,
513 LEVEL_GRP, "ATT",
514 &(state->att),
515 &(newval->att));
516 errorflag |= read_and_check_int (cfgdata,
517 LEVEL_GRP, "PREAMP",
518 &(state->preamp),
519 &(newval->preamp));
520 errorflag |= read_and_check_int (cfgdata,
521 LEVEL_GRP, "AGC",
522 &(state->agc),
523 &(newval->agc));
524
525
526 /* TX levels */
527 errorflag |= read_and_check_level (cfgdata,
528 LEVEL_GRP, "POWER",
529 &(state->power),
530 &(newval->power));
531
532 /* enable daemon */
533 rig_daemon_set_suspend (FALSE);
534 }
535 }
536
537 if (cfgdata != NULL) {
538 g_key_file_free (cfgdata);
539 }
540
541 return errorflag;
542 }
543
544
545 /** \brief Save rig state to file
546 * \param file The file to save the rig state to
547 *
548 * The file parameter may not be NULL. If you need to open
549 * the file selector use the callback functions instead.
550 * existing file will be replaced without any warning!
551 */
552 gint
rig_state_save(const gchar * file)553 rig_state_save (const gchar *file)
554 {
555 GKeyFile *cfgdata; /* the data */
556 grig_settings_t *state; /* pointer to current rig state */
557 gboolean errorflag = 0;
558 gint vali;
559 gchar *buff;
560
561
562 /* disable daemon */
563 rig_daemon_set_suspend (TRUE);
564
565 /* link state to rig-data.get */
566 state = rig_data_get_get_addr ();
567
568 /* create data */
569 cfgdata = g_key_file_new ();
570
571 /* save grig version */
572 g_key_file_set_string (cfgdata, GEN_GRP, "VERSION", VERSION);
573
574 /* save rigid */
575 vali = rig_daemon_get_rig_id ();
576 if (vali < 1) {
577 /* got to be a bug */
578 grig_debug_local (RIG_DEBUG_BUG,
579 _("%s: RIG ID is invalid (%d)"),
580 __FUNCTION__, vali);
581
582 /* try recovery by using dummy id */
583 vali = 1;
584 }
585 g_key_file_set_integer (cfgdata, DEV_GRP, "ID", vali);
586
587 /* save port */
588
589 /* if serial, save serial speed, too */
590
591 /* conf parameters */
592
593 /* frequencies, incl. vfo, rit, xit, split and lock */
594 buff = g_strdup_printf ("%.0f", state->freq1);
595 g_key_file_set_string (cfgdata, FREQ_GRP, "FREQ1", buff);
596 g_free (buff);
597
598 buff = g_strdup_printf ("%.0f", state->freq2);
599 g_key_file_set_string (cfgdata, FREQ_GRP, "FREQ2", buff);
600 g_free (buff);
601
602 g_key_file_set_integer (cfgdata, FREQ_GRP, "RIT", state->rit);
603 g_key_file_set_integer (cfgdata, FREQ_GRP, "XIT", state->xit);
604 g_key_file_set_integer (cfgdata, FREQ_GRP, "VFO", state->vfo);
605 g_key_file_set_boolean (cfgdata, FREQ_GRP, "SPLIT", state->split);
606 g_key_file_set_boolean (cfgdata, FREQ_GRP, "LOCK", state->lock);
607
608 /* Mode and filter */
609 g_key_file_set_integer (cfgdata, MODE_GRP, "MODE", state->mode);
610 g_key_file_set_integer (cfgdata, MODE_GRP, "FILTER", state->pbw);
611
612 /* ATT/PREAMP/AGC */
613 g_key_file_set_integer (cfgdata, LEVEL_GRP, "ATT", state->att);
614 g_key_file_set_integer (cfgdata, LEVEL_GRP, "PREAMP", state->preamp);
615 g_key_file_set_integer (cfgdata, LEVEL_GRP, "AGC", state->agc);
616
617 /* TX levels */
618 g_key_file_set_integer (cfgdata, LEVEL_GRP, "POWER", (gint)(state->power*100));
619
620 /* write data to file */
621 errorflag |= rig_state_write_data (cfgdata, file);
622
623 g_key_file_free (cfgdata);
624
625 /* enable daemon */
626 rig_daemon_set_suspend (FALSE);
627
628
629 return errorflag;
630 }
631
632
633 /** \brief Write rig state to file.
634 *
635 * This function takes the rig state in the form of a GKeyFile
636 * and writes it to the specified file.
637 */
638 static gint
rig_state_write_data(GKeyFile * cfgdata,const gchar * file)639 rig_state_write_data (GKeyFile *cfgdata, const gchar *file)
640 {
641 GError *error = NULL; /* error buffer */
642 gchar *cfgstr; /* data in string form */
643 GIOChannel *cfgfile; /* data file */
644 gsize length; /* length of cfg data */
645 gsize written; /* bytes written to file */
646 gboolean errorflag = 0;
647
648
649 /* save the data */
650 cfgstr = g_key_file_to_data (cfgdata, &length, &error);
651
652 if (error != NULL) {
653 grig_debug_local (RIG_DEBUG_ERR,
654 _("%s: Error building state data (%s)"),
655 __FUNCTION__, error->message);
656 g_clear_error (&error);
657 errorflag |= 1;
658 }
659 else {
660
661 cfgfile = g_io_channel_new_file (file, "w", &error);
662
663 if (error != NULL) {
664 grig_debug_local (RIG_DEBUG_ERR,
665 _("%s: Could not create data file (%s)\n%s"),
666 __FUNCTION__, error->message, file);
667 g_clear_error (&error);
668 errorflag |= 1;
669 }
670 else {
671 g_io_channel_write_chars (cfgfile,
672 cfgstr,
673 length,
674 &written,
675 &error);
676
677 g_io_channel_shutdown (cfgfile, TRUE, NULL);
678 g_io_channel_unref (cfgfile);
679
680 if (error != NULL) {
681 grig_debug_local (RIG_DEBUG_ERR,
682 _("%s: Error writing config data (%s)"),
683 __FUNCTION__, error->message);
684 g_clear_error (&error);
685 errorflag |= 1;
686 }
687 else if (length != written) {
688 grig_debug_local (RIG_DEBUG_ERR,
689 _("%s: Wrote only %d instead of %d chars"),
690 __FUNCTION__, written, length);
691 errorflag |= 1;
692 }
693 else {
694 grig_debug_local (RIG_DEBUG_VERBOSE,
695 _("%s: Rig state saved successfully to\n%s."),
696 __FUNCTION__, file);
697 errorflag |= 0;
698 }
699 }
700
701 g_free (cfgstr);
702
703 }
704
705
706 return errorflag;
707 }
708
709
710 /** \brief Ask user whether to apply state if current rig
711 * id is different from rig id in rig file.
712 * \return TRUE if the user says YES, FALSE otherwise.
713 */
714 static gboolean
ask_cfm(gint state_id,gint rig_id)715 ask_cfm (gint state_id, gint rig_id)
716 {
717 GtkWidget *dialog;
718 gint response;
719
720 dialog = gtk_message_dialog_new (GTK_WINDOW (grigapp),
721 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
722 GTK_MESSAGE_QUESTION,
723 GTK_BUTTONS_YES_NO,
724 _("Selected rig state has been saved for model %d,\n"\
725 "while the current rig model is %d.\n"\
726 "Do you want to try to apply settings?"),
727 state_id, rig_id);
728
729 response = gtk_dialog_run (GTK_DIALOG (dialog));
730
731 gtk_widget_destroy (dialog);
732
733 if (response == GTK_RESPONSE_YES)
734 return TRUE;
735
736
737 return FALSE;
738 }
739
740
741
742 /** \brief Read and check parameter of type gfloat.
743 * \param cfgdata The GKeyFile data structure to read from.
744 * \param group The name of the configuration group.
745 * \param key The name of the configuiration key.
746 * \param param Pointer to the parameter where the value should be stored.
747 * \param newflag Pointer to the new flag of the parameter.
748 * \return TRUE if an error has occured during read, FALSE otherwise.
749 *
750 * \note Float type values are usually levels and constrained to [0.0;1.0]
751 * freq_t is double :P
752 */
753 static gboolean
read_and_check_level(GKeyFile * cfgdata,const gchar * group,const gchar * key,gfloat * param,gboolean * newflag)754 read_and_check_level (GKeyFile *cfgdata,
755 const gchar *group,
756 const gchar *key,
757 gfloat *param,
758 gboolean *newflag)
759 {
760 GError *error = NULL;
761 gint lev;
762 gboolean errflag = FALSE;
763
764
765 lev = g_key_file_get_integer (cfgdata, group, key, &error);
766
767 /* IO error */
768 if (error != NULL) {
769
770 grig_debug_local (RIG_DEBUG_ERR,
771 _("%s:%d: Could nor read param %s::%s\n(%s)"),
772 __FILE__, __LINE__,
773 group, key, error->message);
774
775 g_clear_error (&error);
776 errflag = TRUE;
777 *newflag = FALSE;
778 }
779 else {
780 *param = ((gfloat) lev) / 100.0;
781
782 if ((*param >= 0.0) && (*param <= 1.0)) {
783 *newflag = TRUE;
784 }
785 else {
786 /* possible range check error */
787 grig_debug_local (RIG_DEBUG_ERR,
788 _("%s:%d:\nFLOAT value out of range: %.2f\n"\
789 "Floats expected to be between 0.0 and 1.0"),
790 __FILE__, __LINE__, *param);
791 errflag = TRUE;
792 }
793
794 }
795
796 return errflag;
797 }
798
799
800
801 /** \brief Read and check parameter of type gdouble.
802 * \param cfgdata The GKeyFile data structure to read from.
803 * \param group The name of the configuration group.
804 * \param key The name of the configuiration key.
805 * \param param Pointer to the parameter where the value should be stored.
806 * \param newflag Pointer to the new flag of the parameter.
807 * \return TRUE if an error has occured during read, FALSE otherwise.
808 */
809 static gboolean
read_and_check_double(GKeyFile * cfgdata,const gchar * group,const gchar * key,gdouble * param,gboolean * newflag)810 read_and_check_double (GKeyFile *cfgdata,
811 const gchar *group,
812 const gchar *key,
813 gdouble *param,
814 gboolean *newflag)
815 {
816 GError *error = NULL;
817 gchar *buff;
818 gboolean errflag = FALSE;
819
820
821 buff = g_key_file_get_string (cfgdata, group, key, &error);
822
823 if (error != NULL) {
824
825 grig_debug_local (RIG_DEBUG_ERR,
826 _("%s:%d: Could nor read param %s::%s\n(%s)"),
827 __FILE__, __LINE__,
828 group, key, error->message);
829
830 g_clear_error (&error);
831 errflag = TRUE;
832 *newflag = FALSE;
833 }
834 else {
835 *param = g_ascii_strtod (buff, NULL);
836 *newflag = TRUE;
837
838 g_free (buff);
839 }
840
841 return errflag;
842 }
843
844
845
846 /** \brief Read and check parameter of type integer.
847 * \param cfgdata The GKeyFile data structure to read from.
848 * \param group The name of the configuration group.
849 * \param key The name of the configuiration key.
850 * \param param Pointer to the parameter where the value should be stored.
851 * \param newflag Pointer to the new flag of the parameter.
852 * \return TRUE if an error has occured during read, FALSE otherwise.
853 */
read_and_check_int(GKeyFile * cfgdata,const gchar * group,const gchar * key,gint * param,gboolean * newflag)854 static gboolean read_and_check_int (GKeyFile *cfgdata,
855 const gchar *group,
856 const gchar *key,
857 gint *param,
858 gboolean *newflag)
859 {
860 GError *error = NULL;
861 gboolean errflag = FALSE;
862 gint val;
863
864 val = g_key_file_get_integer (cfgdata, group, key, &error);
865
866 if (error != NULL) {
867
868 grig_debug_local (RIG_DEBUG_ERR,
869 _("%s:%d: Could nor read param %s::%s\n(%s)"),
870 __FILE__, __LINE__,
871 group, key, error->message);
872
873 g_clear_error (&error);
874 errflag = TRUE;
875 *newflag = FALSE;
876 }
877 else {
878 *param = val;
879 *newflag = TRUE;
880 }
881
882 return errflag;
883 }
884
885
886 /** \brief Read and check parameter of type boolean.
887 * \param cfgdata The GKeyFile data structure to read from.
888 * \param group The name of the configuration group.
889 * \param key The name of the configuiration key.
890 * \param param Pointer to the parameter where the value should be stored.
891 * \param newflag Pointer to the new flag of the parameter.
892 * \return TRUE if an error has occured during read, FALSE otherwise.
893 */
read_and_check_bool(GKeyFile * cfgdata,const gchar * group,const gchar * key,gboolean * param,gboolean * newflag)894 static gboolean read_and_check_bool (GKeyFile *cfgdata,
895 const gchar *group,
896 const gchar *key,
897 gboolean *param,
898 gboolean *newflag)
899 {
900 GError *error = NULL;
901 gboolean errflag = FALSE;
902 gboolean val;
903
904 val = g_key_file_get_boolean (cfgdata, group, key, &error);
905
906 if (error != NULL) {
907
908 grig_debug_local (RIG_DEBUG_ERR,
909 _("%s:%d: Could nor read param %s::%s\n(%s)"),
910 __FILE__, __LINE__,
911 group, key, error->message);
912
913 g_clear_error (&error);
914 errflag = TRUE;
915 *newflag = FALSE;
916 }
917 else {
918 *param = val;
919 *newflag = TRUE;
920 }
921
922 return errflag;
923
924 }
925
926