/** \brief Save rotator configuration. * \param conf Pointer to the rotator configuration. * * This function saves the rotator configuration stored in conf to a * .rig file. conf->name must contain the file name of the configuration * (no path, just file name and without the .rot extension). */ void rotor_conf_save (rotor_conf_t *conf) { GKeyFile *cfg = NULL; gchar *confdir; gchar *fname; if (conf->name == NULL) return; /* create a config structure */ cfg = g_key_file_new(); g_key_file_set_string (cfg, GROUP, KEY_HOST, conf->host); g_key_file_set_integer (cfg, GROUP, KEY_PORT, conf->port); g_key_file_set_integer (cfg, GROUP, KEY_AZTYPE, conf->aztype); g_key_file_set_double (cfg, GROUP, KEY_MINAZ, conf->minaz); g_key_file_set_double (cfg, GROUP, KEY_MAXAZ, conf->maxaz); g_key_file_set_double (cfg, GROUP, KEY_MINEL, conf->minel); g_key_file_set_double (cfg, GROUP, KEY_MAXEL, conf->maxel); /* build filename */ confdir = get_hwconf_dir(); fname = g_strconcat (confdir, G_DIR_SEPARATOR_S, conf->name, ".rot", NULL); g_free (confdir); /* save information */ gpredict_save_key_file (cfg, fname); /* cleanup */ g_free (fname); g_key_file_free (cfg); }
/** \brief Save rotator configuration. * \param conf Pointer to the rotator configuration. * * This function saves the rotator configuration stored in conf to a * .rig file. conf->name must contain the file name of the configuration * (no path, just file name and without the .rot extension). */ void rotor_conf_save (rotor_conf_t *conf) { GKeyFile *cfg = NULL; gchar *confdir; gchar *fname; gchar *data; gsize len; if (conf->name == NULL) return; /* create a config structure */ cfg = g_key_file_new(); g_key_file_set_string (cfg, GROUP, KEY_HOST, conf->host); g_key_file_set_integer (cfg, GROUP, KEY_PORT, conf->port); g_key_file_set_integer (cfg, GROUP, KEY_AZTYPE, conf->aztype); g_key_file_set_double (cfg, GROUP, KEY_MINAZ, conf->minaz); g_key_file_set_double (cfg, GROUP, KEY_MAXAZ, conf->maxaz); g_key_file_set_double (cfg, GROUP, KEY_MINEL, conf->minel); g_key_file_set_double (cfg, GROUP, KEY_MAXEL, conf->maxel); /* convert to text sdata */ data = g_key_file_to_data (cfg, &len, NULL); confdir = get_hwconf_dir(); fname = g_strconcat (confdir, G_DIR_SEPARATOR_S, conf->name, ".rot", NULL); g_free (confdir); g_file_set_contents (fname, data, len, NULL); g_free (fname); g_free (data); g_key_file_free (cfg); }
/** \brief Read rotator configuration. * \param conf Pointer to a rotor_conf_t structure where the data will be * stored. * * This function reads a rotoator configuration from a .rot file into conf. * conf->name must contain the file name of the configuration (no path, just * file name and without the .rot extension). */ gboolean rotor_conf_read (rotor_conf_t *conf) { GKeyFile *cfg = NULL; gchar *confdir; gchar *fname; GError *error = NULL; if (conf->name == NULL) { sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s: NULL configuration name!"), __func__); return FALSE; } confdir = get_hwconf_dir(); fname = g_strconcat (confdir, G_DIR_SEPARATOR_S, conf->name, ".rot", NULL); g_free (confdir); /* open .grc file */ cfg = g_key_file_new (); g_key_file_load_from_file(cfg, fname, 0, NULL); if (cfg == NULL) { sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s: Could not load file %s\n"), __func__, fname); g_free (fname); return FALSE; } g_free (fname); /* read parameters */ conf->host = g_key_file_get_string (cfg, GROUP, KEY_HOST, &error); if (error != NULL) { sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s: Error reading rotor conf from %s (%s)."), __func__, conf->name, error->message); g_clear_error (&error); g_key_file_free (cfg); return FALSE; } conf->port = g_key_file_get_integer (cfg, GROUP, KEY_PORT, &error); if (error != NULL) { sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s: Error reading rotor conf from %s (%s)."), __func__, conf->name, error->message); g_clear_error (&error); g_key_file_free (cfg); return FALSE; } conf->aztype = g_key_file_get_integer (cfg, GROUP, KEY_AZTYPE, &error); if (error != NULL) { sat_log_log (SAT_LOG_LEVEL_WARN, _("%s: Az type not defined for %s. Assuming 0..360\302\260"), __func__, conf->name); g_clear_error (&error); conf->aztype = ROT_AZ_TYPE_360; } conf->minaz = g_key_file_get_double (cfg, GROUP, KEY_MINAZ, &error); if (error != NULL) { sat_log_log (SAT_LOG_LEVEL_WARN, _("%s: MinAz not defined for %s. Assuming 0\302\260."), __func__, conf->name); g_clear_error (&error); conf->minaz = 0.0; } conf->maxaz = g_key_file_get_double (cfg, GROUP, KEY_MAXAZ, &error); if (error != NULL) { sat_log_log (SAT_LOG_LEVEL_WARN, _("%s: MaxAz not defined for %s. Assuming 360\302\260."), __func__, conf->name); g_clear_error (&error); conf->maxaz = 360.0; } conf->minel = g_key_file_get_double (cfg, GROUP, KEY_MINEL, &error); if (error != NULL) { sat_log_log (SAT_LOG_LEVEL_WARN, _("%s: MinEl not defined for %s. Assuming 0\302\260."), __func__, conf->name); g_clear_error (&error); conf->minel = 0.0; } conf->maxel = g_key_file_get_double (cfg, GROUP, KEY_MAXEL, &error); if (error != NULL) { sat_log_log (SAT_LOG_LEVEL_WARN, _("%s: MaxEl not defined for %s. Assuming 90\302\260."), __func__, conf->name); g_clear_error (&error); conf->maxel = 90.0; } g_key_file_free (cfg); return TRUE; }
/** \brief User pressed OK. Any changes should be stored in config. * * First, all .rot files are deleted, whereafter the rotator configurations in * the rotlist are saved one by one. */ void sat_pref_rot_ok () { GDir *dir = NULL; /* directory handle */ GError *error = NULL; /* error flag and info */ gchar *buff,*dirname; const gchar *filename; GtkTreeIter iter; /* new item added to the list store */ GtkTreeModel *model; guint i,n; rotor_conf_t conf = { .name = NULL, .host = NULL, .port = 4533, .minaz = 0, .maxaz = 360, .minel = 0, .maxel = 90, .aztype = ROT_AZ_TYPE_360, }; /* delete all .rot files */ dirname = get_hwconf_dir (); dir = g_dir_open (dirname, 0, &error); if (dir) { /* read each .rot file */ while ((filename = g_dir_read_name (dir))) { if (g_str_has_suffix (filename, ".rot")) { buff = g_strconcat (dirname, G_DIR_SEPARATOR_S, filename, NULL); g_remove (buff); g_free (buff); } } } g_free (dirname); g_dir_close (dir); /* create new .rot files for the radios in the rotlist */ model = gtk_tree_view_get_model (GTK_TREE_VIEW (rotlist)); n = gtk_tree_model_iter_n_children (model, NULL); for (i = 0; i < n; i++) { /* get radio conf */ if (gtk_tree_model_iter_nth_child (model, &iter, NULL, i)) { /* store conf */ gtk_tree_model_get (model, &iter, ROT_LIST_COL_NAME, &conf.name, ROT_LIST_COL_HOST, &conf.host, ROT_LIST_COL_PORT, &conf.port, ROT_LIST_COL_MINAZ, &conf.minaz, ROT_LIST_COL_MAXAZ, &conf.maxaz, ROT_LIST_COL_MINEL, &conf.minel, ROT_LIST_COL_MAXEL, &conf.maxel, ROT_LIST_COL_AZTYPE, &conf.aztype, -1); rotor_conf_save (&conf); /* free conf buffer */ if (conf.name) g_free (conf.name); if (conf.host) g_free (conf.host); } else { sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s: Failed to get ROT %s"), __func__, i); } } } /** \brief Add a new rotor configuration * \param button Pointer to the Add button. * \param data User data (null). * * This function executes the rotor configuration editor. */ static void add_cb (GtkWidget *button, gpointer data) { GtkTreeIter item; /* new item added to the list store */ GtkListStore *liststore; (void) button; /* avoid unused parameter compiler warning */ (void) data; /* avoid unused parameter compiler warning */ rotor_conf_t conf = { .name = NULL, .host = NULL, .port = 4533, .minaz = 0, .maxaz = 360, .minel = 0, .maxel = 90, .aztype = ROT_AZ_TYPE_360, }; /* run rot conf editor */ sat_pref_rot_editor_run (&conf); /* add new rot to the list */ if (conf.name != NULL) { liststore = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (rotlist))); gtk_list_store_append (liststore, &item); gtk_list_store_set (liststore, &item, ROT_LIST_COL_NAME, conf.name, ROT_LIST_COL_HOST, conf.host, ROT_LIST_COL_PORT, conf.port, ROT_LIST_COL_MINAZ, conf.minaz, ROT_LIST_COL_MAXAZ, conf.maxaz, ROT_LIST_COL_MINEL, conf.minel, ROT_LIST_COL_MAXEL, conf.maxel, ROT_LIST_COL_AZTYPE, conf.aztype, -1); g_free (conf.name); if (conf.host != NULL) g_free (conf.host); } } /** \brief Add a new rotor configuration * \param button Pointer to the Add button. * \param data User data (null). * * This function executes the rotor configuration editor. * */ static void edit_cb (GtkWidget *button, gpointer data) { GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW(rotlist)); GtkTreeModel *selmod; GtkTreeSelection *selection; GtkTreeIter iter; (void) button; /* avoid unused parameter compiler warning */ (void) data; /* avoid unused parameter compiler warning */ rotor_conf_t conf = { .name = NULL, .host = NULL, .port = 4533, .minaz = 0, .maxaz = 360, .minel = 0, .maxel = 90, .aztype = ROT_AZ_TYPE_360, }; /* If there are no entries, we have a bug since the button should have been disabled. */ if (gtk_tree_model_iter_n_children (model, NULL) < 1) { sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s:%s: Edit button should have been disabled."), __FILE__, __func__); //gtk_widget_set_sensitive (button, FALSE); return; } /* get selected row FIXME: do we really need to work with two models? */ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (rotlist)); if (gtk_tree_selection_get_selected(selection, &selmod, &iter)) { gtk_tree_model_get (model, &iter, ROT_LIST_COL_NAME, &conf.name, ROT_LIST_COL_HOST, &conf.host, ROT_LIST_COL_PORT, &conf.port, ROT_LIST_COL_MINAZ, &conf.minaz, ROT_LIST_COL_MAXAZ, &conf.maxaz, ROT_LIST_COL_MINEL, &conf.minel, ROT_LIST_COL_MAXEL, &conf.maxel, ROT_LIST_COL_AZTYPE, &conf.aztype, -1); } else { GtkWidget *dialog; dialog = gtk_message_dialog_new (GTK_WINDOW (window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Select the rotator you want to edit\n"\ "and try again!")); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); return; } /* run radio configuration editor */ sat_pref_rot_editor_run (&conf); /* apply changes */ if (conf.name != NULL) { gtk_list_store_set (GTK_LIST_STORE(model), &iter, ROT_LIST_COL_NAME, conf.name, ROT_LIST_COL_HOST, conf.host, ROT_LIST_COL_PORT, conf.port, ROT_LIST_COL_MINAZ, conf.minaz, ROT_LIST_COL_MAXAZ, conf.maxaz, ROT_LIST_COL_MINEL, conf.minel, ROT_LIST_COL_MAXEL, conf.maxel, ROT_LIST_COL_AZTYPE, conf.aztype, -1); } /* clean up memory */ if (conf.name) g_free (conf.name); if (conf.host != NULL) g_free (conf.host); } /** \brief Delete selected rotator configuration * * This function is called when the user clicks the Delete button. * */ static void delete_cb (GtkWidget *button, gpointer data) { GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW(rotlist)); GtkTreeSelection *selection; GtkTreeIter iter; (void) button; /* avoid unused parameter compiler warning */ (void) data; /* avoid unused parameter compiler warning */ /* If there are no entries, we have a bug since the button should have been disabled. */ if (gtk_tree_model_iter_n_children (model, NULL) < 1) { sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s:%s: Delete button should have been disabled."), __FILE__, __func__); //gtk_widget_set_sensitive (button, FALSE); return; } /* get selected row */ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (rotlist)); if (gtk_tree_selection_get_selected(selection, NULL, &iter)) { gtk_list_store_remove (GTK_LIST_STORE(model), &iter); } else { GtkWidget *dialog; dialog = gtk_message_dialog_new (GTK_WINDOW (window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Select the rotator you want to delete\n"\ "and try again!")); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); } }
/** \brief Create data storage for rotator configuration list. */ static GtkTreeModel *create_and_fill_model () { GtkListStore *liststore; /* the list store data structure */ GtkTreeIter item; /* new item added to the list store */ GDir *dir = NULL; /* directory handle */ GError *error = NULL; /* error flag and info */ gchar *dirname; /* directory name */ gchar **vbuff; const gchar *filename; /* file name */ rotor_conf_t conf; /* create a new list store */ liststore = gtk_list_store_new (ROT_LIST_COL_NUM, G_TYPE_STRING, // name G_TYPE_STRING, // host G_TYPE_INT, // port G_TYPE_DOUBLE, // Min Az G_TYPE_DOUBLE, // Max Az G_TYPE_DOUBLE, // Min El G_TYPE_DOUBLE, // Max El G_TYPE_INT // Az type ); gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE(liststore),ROT_LIST_COL_NAME,GTK_SORT_ASCENDING); /* open configuration directory */ dirname = get_hwconf_dir (); dir = g_dir_open (dirname, 0, &error); if (dir) { /* read each .rot file */ while ((filename = g_dir_read_name (dir))) { if (g_str_has_suffix (filename, ".rot")) { vbuff = g_strsplit (filename, ".rot", 0); conf.name = g_strdup (vbuff[0]); g_strfreev (vbuff); if (rotor_conf_read (&conf)) { /* insert conf into liststore */ gtk_list_store_append (liststore, &item); gtk_list_store_set (liststore, &item, ROT_LIST_COL_NAME, conf.name, ROT_LIST_COL_HOST, conf.host, ROT_LIST_COL_PORT, conf.port, ROT_LIST_COL_MINAZ, conf.minaz, ROT_LIST_COL_MAXAZ, conf.maxaz, ROT_LIST_COL_MINEL, conf.minel, ROT_LIST_COL_MAXEL, conf.maxel, ROT_LIST_COL_AZTYPE, conf.aztype, -1); sat_log_log (SAT_LOG_LEVEL_DEBUG, _("%s:%d: Read %s"), __FILE__, __LINE__, filename); /* clean up memory */ if (conf.name) g_free (conf.name); if (conf.host) g_free (conf.host); } else { /* there was an error */ sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s:%d: Failed to read %s"), __FILE__, __LINE__, conf.name); g_free (conf.name); } } } } else { sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s:%d: Failed to open hwconf dir (%s)"), __FILE__, __LINE__, error->message); g_clear_error (&error); } g_free (dirname); g_dir_close (dir); return GTK_TREE_MODEL (liststore); }