Browse Source

Add --interactive switch for command line UI

Matthias Vogelgesang 9 years ago
parent
commit
8b67df0391
2 changed files with 173 additions and 10 deletions
  1. 1 0
      Makefile
  2. 172 10
      lamino.c

+ 1 - 0
Makefile

@@ -1,5 +1,6 @@
 PKG_DEPS = ufo
 SRC=lamino.c
 BIN=lamino
+LDFLAGS=-lreadline
 
 include c.mk

+ 172 - 10
lamino.c

@@ -1,7 +1,11 @@
 #include <stdlib.h>
+#include <readline/readline.h>
+#include <readline/history.h>
 #include <ufo/ufo.h>
 
+
 typedef struct {
+    gboolean interactive;
     gchar *radios;
     gchar *darks;
     gchar *flats;
@@ -19,12 +23,22 @@ typedef struct {
     gdouble px_variation;
     gdouble v_origin[3];
     guint v_size[3];
+    GOptionEntry *entries;
 } Params;
 
+typedef void (*CommandFunction)(Params *, gchar **argv);
+
+typedef struct {
+    const gchar *command;
+    CommandFunction func;
+} CommandMap;
+
+
 const int COLOR_RED = 31;
 const int COLOR_GREEN = 32;
 const int COLOR_YELLOW = 33;
 
+
 static void
 check (GError *error)
 {
@@ -112,8 +126,20 @@ print_dots (gpointer user)
         g_print (".");
 }
 
+static gboolean
+params_okay (Params *params)
+{
+    return params->width != 0 &&
+           params->height != 0 &&
+           params->num_radios != 0 &&
+           params->radios != NULL &&
+           params->theta < G_MAXDOUBLE &&
+           params->px < G_MAXDOUBLE &&
+           params->py < G_MAXDOUBLE;
+}
+
 static void
-run_reconstruction (Params *params)
+run_reconstruction (Params *params, gchar **argv)
 {
     guint xl, xr, yt, yb;
     guint padded_width;
@@ -139,6 +165,11 @@ run_reconstruction (Params *params)
     UfoTaskNode *writer = NULL;
     GError *error = NULL;
 
+    if (!params_okay (params)) {
+        err ("Parameters missing.\n");
+        return;
+    }
+
     pm = ufo_plugin_manager_new (NULL);
     graph = UFO_TASK_GRAPH (ufo_task_graph_new ());
 
@@ -275,6 +306,127 @@ run_reconstruction (Params *params)
     }
 }
 
+static void
+print (Params *params, gchar **argv)
+{
+    for (gint i = 0; params->entries[i].long_name != NULL; i++) {
+        GOptionEntry *entry;
+
+        entry = &params->entries[i];
+
+        if (argv[0] == NULL || g_strcmp0 (entry->long_name, argv[0]) == 0) {
+            switch (entry->arg) {
+                case G_OPTION_ARG_STRING:
+                    info ("%-15s%s\n", entry->long_name, *((gchar **) entry->arg_data));
+                    break;
+                case G_OPTION_ARG_INT:
+                    info ("%-15s%i\n", entry->long_name, *((gint *) entry->arg_data));
+                    break;
+                case G_OPTION_ARG_DOUBLE:
+                    info ("%-15s%f\n", entry->long_name, *((gdouble *) entry->arg_data));
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+}
+
+static void
+set (Params *params, gchar **argv)
+{
+    if (argv[0] == NULL) {
+        warn ("No parameter given\n");
+        return;
+    }
+
+    if (argv[1] == NULL) {
+        warn ("No value given\n");
+        return;
+    }
+
+    for (gint i = 0; params->entries[i].long_name != NULL; i++) {
+        GOptionEntry *entry;
+
+        entry = &params->entries[i];
+
+        if (g_strcmp0 (entry->long_name, argv[0]) == 0) {
+            switch (entry->arg) {
+                case G_OPTION_ARG_STRING:
+                    {
+                        gchar *s;
+
+                        s = *((gchar **) entry->arg_data);
+                        g_free (s);
+                        *(gchar **) entry->arg_data = g_strjoinv (" ", &argv[1]);
+                    }
+                    break;
+                case G_OPTION_ARG_INT:
+                    *(gint *) entry->arg_data = atoi (argv[1]);
+                    break;
+                case G_OPTION_ARG_DOUBLE:
+                    *(gdouble *) entry->arg_data = atof (argv[1]);
+                    break;
+                default:
+                    break;
+            }
+
+            /* print (params, arg); */
+            break;
+        }
+    }
+}
+
+static void
+quit (Params *params, gchar **argv)
+{
+    exit (0);
+}
+
+static void
+start_shell (Params *params)
+{
+    static CommandMap map[] = {
+        { "run", run_reconstruction },
+        { "print", print },
+        { "set", set },
+        { "quit", quit },
+        { NULL },
+    };
+
+    while (1) {
+        gchar *line;
+        gint i;
+        gchar **split = NULL;
+
+        line = readline ("> ");
+
+        if (line && *line && (g_strchomp (line) == g_strchug (line))) {
+            add_history (line);
+        }
+        else {
+            goto cleanup_line;
+        }
+
+        split = g_strsplit (line, " ", 0);
+
+        for (i = 0; map[i].command != NULL; i++) {
+            /* Run command even if only partially written out */
+            if (g_str_has_prefix (map[i].command, split[0])) {
+                map[i].func (params, &split[1]);
+                break;
+            }
+        }
+
+        if (map[i].command == NULL)
+            warn ("Unknown command `%s'\n", split[0]);
+
+cleanup_line:
+        g_free (line);
+        g_strfreev (split);
+    }
+}
+
 static void
 parse_params (Params *params, int argc, char **argv)
 {
@@ -303,10 +455,11 @@ parse_params (Params *params, int argc, char **argv)
         { "vw", 0, 0, G_OPTION_ARG_INT, &params->v_size[0], "Width of box", "[int]" },
         { "vh", 0, 0, G_OPTION_ARG_INT, &params->v_size[1], "Height of box", "[int]" },
         { "vd", 0, 0, G_OPTION_ARG_INT, &params->v_size[2], "Depth of box", "[int]" },
+        { "interactive", 0, 0, G_OPTION_ARG_NONE, &params->interactive, "Start interactive mode", "" },
         { NULL }
     };
 
-    context = g_option_context_new ("- test tree model performance");
+    context = g_option_context_new ("- laminographic reconstruction");
     g_option_context_add_main_entries (context, entries, NULL);
 
     if (!g_option_context_parse (context, &argc, &argv, &error)) {
@@ -314,15 +467,19 @@ parse_params (Params *params, int argc, char **argv)
         exit (1);
     }
 
-    if (params->width == 0 || params->height == 0 || params->num_radios == 0 ||
-        params->radios == NULL ||
-        params->theta == G_MAXDOUBLE ||
-        params->px == G_MAXDOUBLE || params->py == G_MAXDOUBLE) {
-            err ("Parameters missing.\n\n");
-            g_print ("%s\n", g_option_context_get_help (context, TRUE, NULL));
-            exit (1);
+    /* Copy entry information for later reference */
+    params->entries = g_memdup (entries, sizeof (entries));
+
+    if (params->interactive)
+        goto parse_params_cleanup;
+
+    if (!params_okay (params)) {
+        err ("Parameters missing.\n\n");
+        g_print ("%s\n", g_option_context_get_help (context, TRUE, NULL));
+        exit (1);
     }
 
+parse_params_cleanup:
     g_option_context_free (context);
 }
 
@@ -330,6 +487,7 @@ int
 main (int argc, char **argv)
 {
     Params params = {
+        .interactive = FALSE,
         .radios = NULL,
         .darks = NULL,
         .flats = NULL,
@@ -354,7 +512,11 @@ main (int argc, char **argv)
 #endif
 
     parse_params (&params, argc, argv);
-    run_reconstruction (&params);
+
+    if (params.interactive)
+        start_shell (&params);
+    else
+        run_reconstruction (&params, NULL);
 
     return 0;
 }