[gegl] bin: expose some of the ui process internals as settable properties



commit cf831253685916c283f4689ebfd1b690ac50d2ea
Author: Øyvind Kolås <pippin gimp org>
Date:   Sun Jan 6 18:59:09 2019 +0100

    bin: expose some of the ui process internals as settable properties

 bin/argvs.c |  34 ++-
 bin/ui.c    | 711 +++++++++++++++++++++++++++++++++++++++++-------------------
 2 files changed, 519 insertions(+), 226 deletions(-)
---
diff --git a/bin/argvs.c b/bin/argvs.c
index 2f15051dd..4c4e7e1bd 100644
--- a/bin/argvs.c
+++ b/bin/argvs.c
@@ -25,18 +25,42 @@ extern Mrg *mrg;
 extern MrgList *scrollback;
 extern int use_ui;
 
+
 #define printf(foo...) \
    do{ MrgString *str = mrg_string_new_printf (foo);\
-       if (use_ui) \
-       mrg_list_prepend (&scrollback, mrg_string_dissolve (str));\
+       if (use_ui) {\
+       MrgString *line = mrg_string_new (scrollback?scrollback->data:"");\
+       for (char *p= str->str; *p; p++) { \
+         if (*p == '\n') { \
+           char *old = scrollback ? scrollback->data : NULL;\
+           if (old)\
+           {\
+             mrg_list_remove (&scrollback, old);\
+           }\
+           mrg_list_prepend (&scrollback, strdup (line->str));\
+           mrg_list_prepend (&scrollback, strdup (""));\
+           mrg_string_set (line, "");\
+         } else { \
+           char *old = scrollback ? scrollback->data : NULL;\
+           mrg_string_append_byte (line, *p);\
+           if (old)\
+           {\
+             mrg_list_remove (&scrollback, old);\
+           }\
+           mrg_list_prepend (&scrollback, strdup (line->str));\
+         } \
+       } \
+       mrg_string_free (line, 1);\
+       }\
        else \
-       {\
-       fprintf (stdout, "%s", str->str);\
-       mrg_string_free (str, 1);\
+       { fprintf (stdout, "%s", str->str);\
        }\
+       mrg_string_free (str, 1);\
    }while(0)
 #endif
 
+
+
 typedef struct _CmdIterator CmdIterator;
 typedef struct _CmdEntry CmdEntry;
 
diff --git a/bin/ui.c b/bin/ui.c
index 243b0cd40..39ba4d3e3 100644
--- a/bin/ui.c
+++ b/bin/ui.c
@@ -27,6 +27,30 @@
 
 #if HAVE_MRG
 
+const char *css =
+"a { color: yellow; text-decoration: none;  }\n"
+"div.colorinfo { font-size: 1.0em; color: white; }\n"
+"div.colorspaceinfo {  }\n"
+"div.colorname { margin-bottom: 0.5em; margin-top: 1.0em; }\n"
+"div.colorspacename { font-weight:bold; float:left; clear: left; width: 5em; height: 1.0em; }\n"
+"div.colortriplet {  }\n"
+"div.palitem { float:left;width:6em;height:6em; }\n"
+
+"span.palitemlabel { color: white; }\n"
+"span.bright { color: black; }\n"
+
+"div.append { background-color:transparent; }\n"
+"div.shell { font-size: 0.8em; background-color:rgba(0,0,0,0.5);color:white; }\n"
+"div.shellline { font-size: 0.8em; background-color:rgba(0,0,0,0.5);color:white; }\n"
+"div.prompt { color:#7aa; display: inline; }\n"
+"div.commandline { color:white; display: inline; }\n"
+"div.palettetoolbar {height: 3em;color:white}\n"
+"div.palettetool {border: 2px solid green; }\n"
+"";
+
+
+
+
 #include <ctype.h>
 #include <string.h>
 #include <sys/types.h>
@@ -87,22 +111,32 @@ static GeglNode *gegl_node_get_consumer_no (GeglNode *node,
   return consumer;
 }
 
-int use_ui = 0;
+int use_ui = 1;
 
 #define printf(foo...) \
    do{ MrgString *str = mrg_string_new_printf (foo);\
        if (use_ui) {\
-       MrgString *line = mrg_string_new ("");\
+       MrgString *line = mrg_string_new (scrollback?scrollback->data:"");\
        for (char *p= str->str; *p; p++) { \
          if (*p == '\n') { \
+           char *old = scrollback ? scrollback->data : NULL;\
+           if (old)\
+           {\
+             mrg_list_remove (&scrollback, old);\
+           }\
            mrg_list_prepend (&scrollback, strdup (line->str));\
+           mrg_list_prepend (&scrollback, strdup (""));\
            mrg_string_set (line, "");\
          } else { \
+           char *old = scrollback ? scrollback->data : NULL;\
            mrg_string_append_byte (line, *p);\
+           if (old)\
+           {\
+             mrg_list_remove (&scrollback, old);\
+           }\
+           mrg_list_prepend (&scrollback, strdup (line->str));\
          } \
        } \
-       if (line->str[0]) \
-         mrg_list_prepend (&scrollback, strdup (line->str));\
        mrg_string_free (line, 1);\
        }\
        else \
@@ -135,16 +169,22 @@ typedef struct _State State;
 struct _State {
   void      (*ui) (Mrg *mrg, void *state);
   Mrg        *mrg;
-  char       *path;
-  char       *save_path;
-  GList      *paths;
-  GeglBuffer *buffer;
-  GeglNode   *gegl;
-  GeglNode   *sink;
-  GeglNode   *source;
-  GeglNode   *save;
-  GeglNode   *active;
-  GThread    *thread;
+  char       *path;      /* path of edited file..  */
+
+  char       *src_path; /* path to (immutable) source image. */
+
+  char       *save_path; /* the exported .gegl file, or .png with embedded .gegl file,
+                            the file that is written to on save. This differs depending
+                            on type of input file.
+                          */
+  GList         *paths;
+  GeglBuffer    *buffer;
+  GeglNode      *gegl;
+  GeglNode      *sink;
+  GeglNode      *source;
+  GeglNode      *save;
+  GeglNode      *active;
+  GThread       *thread;
 
   GeglNode      *processor_node; /* the node we have a processor for */
   GeglProcessor *processor;
@@ -153,13 +193,17 @@ struct _State {
   int            editing_op_name;
   char           new_opname[1024];
   int            rev;
+
   float          u, v;
   float          scale;
-  int            show_graph;
-  int            show_controls;
   float          render_quality;
   float          preview_quality;
+
+  int            show_graph;
+  int            show_controls;
   int            controls_timeout;
+  int            frame_no;
+
   char         **ops; // the operations part of the commandline, if any
   float          slide_pause;
   int            slide_enabled;
@@ -168,12 +212,56 @@ struct _State {
   GeglNode      *gegl_decode;
   GeglNode      *decode_load;
   GeglNode      *decode_store;
+  int            playing;
+
   int            is_video;
-  int            frame_no;
   int            prev_frame_played;
   double         prev_ms;
 };
 
+
+typedef struct Setting {
+  char *name;
+  char *description;
+  int   offset;
+  int   type;
+  int   read_only;
+} Setting;
+
+#define FLOAT_PROP(name, description) \
+  {#name, description, offsetof (State, name), 1, 0}
+#define INT_PROP(name, description) \
+  {#name, description, offsetof (State, name), 0, 0}
+#define STRING_PROP(name, description) \
+  {#name, description, offsetof (State, name), 2, 0}
+#define FLOAT_PROP_RO(name, description) \
+  {#name, description, offsetof (State, name), 1, 1}
+#define INT_PROP_RO(name, description) \
+  {#name, description, offsetof (State, name), 0, 1}
+#define STRING_PROP_RO(name, description) \
+  {#name, description, offsetof (State, name), 2, 1}
+
+Setting settings[]=
+{
+  STRING_PROP_RO(path, "path of current document"),
+  STRING_PROP_RO(save_path, "save path, might be different from path if current path is an immutable source 
image itself"),
+  STRING_PROP_RO(src_path, "source path the immutable source image currently being edited"),
+
+  FLOAT_PROP(u, "horizontal coordinate of top-left in display/scaled by scale factor coordinates"),
+  FLOAT_PROP(v, "vertical coordinate of top-left in display/scaled by scale factor coordinates"),
+  FLOAT_PROP(scale, "display scale factor"),
+  FLOAT_PROP(render_quality, "1.0 = normal 2.0 = render at 2.0 zoom factor 4.0 render at 25%"),
+  FLOAT_PROP(preview_quality, "preview quality for use during some interactions, same scale as 
render-quality"),
+  INT_PROP(show_graph, "show the graph (and commandline)"),
+  INT_PROP(show_controls, "show image viewer controls (maybe merge with show-graph and give better name)"),
+  INT_PROP(slide_enabled, "slide show going"),
+  INT_PROP_RO(is_video, ""),
+  INT_PROP(playing, "wheter we are playing or not set to 0 for pause 1 for playing"),
+
+  INT_PROP(frame_no, "current frame number in video/animation")
+
+};
+
 static char *suffix = "-gegl";
 
 
@@ -864,7 +952,7 @@ static int slide_cb (Mrg *mrg, void *data)
 {
   State *o = data;
   o->slide_timeout = 0;
-  argvs_eval ("go-next");
+  argvs_eval ("next");
   return 0;
 }
 
@@ -904,7 +992,7 @@ static void ui_viewer (State *o)
   else
     cairo_new_path (cr);
   cairo_rectangle (cr, 0.0, 0.8, 0.2, 0.2);
-  mrg_listen (mrg, MRG_PRESS, run_command, "go-prev", NULL);
+  mrg_listen (mrg, MRG_PRESS, run_command, "prev", NULL);
   cairo_new_path (cr);
 
   cairo_move_to (cr, 0.8, 0.8);
@@ -917,7 +1005,7 @@ static void ui_viewer (State *o)
   else
     cairo_new_path (cr);
   cairo_rectangle (cr, 0.8, 0.8, 0.2, 0.2);
-  mrg_listen (mrg, MRG_PRESS, run_command, "go-next", NULL);
+  mrg_listen (mrg, MRG_PRESS, run_command, "next", NULL);
   cairo_new_path (cr);
 
   cairo_arc (cr, 0.9, 0.1, 0.1, 0.0, G_PI * 2);
@@ -930,19 +1018,18 @@ static void ui_viewer (State *o)
   mrg_listen (mrg, MRG_PRESS, run_command, "toggle-graph", NULL);
   cairo_new_path (cr);
 
-
-  mrg_add_binding (mrg, "left", NULL, NULL,  run_command, "pan-left");
-  mrg_add_binding (mrg, "right", NULL, NULL, run_command, "pan-right");
-  mrg_add_binding (mrg, "up", NULL, NULL,    run_command, "pan-up");
-  mrg_add_binding (mrg, "down", NULL, NULL,  run_command, "pan-down");
+  mrg_add_binding (mrg, "left", NULL, NULL,  run_command, "pan -0.1 0");
+  mrg_add_binding (mrg, "right", NULL, NULL, run_command, "pan 0.1 0");
+  mrg_add_binding (mrg, "up", NULL, NULL,    run_command, "pan 0 -0.1");
+  mrg_add_binding (mrg, "down", NULL, NULL,  run_command, "pan 0 0.1");
 
   if (!edited_prop && !o->editing_op_name)
   {
-    mrg_add_binding (mrg, "control-m", NULL, NULL,       run_command, "zoom-fit");
+    mrg_add_binding (mrg, "control-m", NULL, NULL,       run_command, "zoom fit");
     mrg_add_binding (mrg, "control-delete", NULL, NULL,  run_command, "discard");
-    mrg_add_binding (mrg, "space", NULL, NULL,           run_command, "go-next");
-    mrg_add_binding (mrg, "n", NULL, NULL,               run_command, "go-next");
-    mrg_add_binding (mrg, "p", NULL, NULL,               run_command, "go-prev");
+    mrg_add_binding (mrg, "space", NULL, NULL,           run_command, "next");
+    mrg_add_binding (mrg, "n", NULL, NULL,               run_command, "next");
+    mrg_add_binding (mrg, "p", NULL, NULL,               run_command, "prev");
   }
 
   if (o->slide_enabled && o->slide_timeout == 0)
@@ -1336,7 +1423,7 @@ int cmd_activate_input (COMMAND_ARGS) /* "activate-input", 0, "", "Activates nod
   if (o->active == NULL)
     return -1;
   ref = gegl_node_get_producer (o->active, "input", NULL);
-  if (ref && ref != o->source)
+  if (ref) //&& ref != o->source)
     o->active = ref;
   mrg_queue_draw (o->mrg, NULL);
   return 0;
@@ -1349,7 +1436,17 @@ int cmd_activate_aux (COMMAND_ARGS) /* "activate-aux", 0, "", ""*/
   GeglNode *ref;
   if (o->active == NULL)
     return -1;
+
+  if (!gegl_node_has_pad (o->active, "aux"))
+    return -2;
+
   ref = gegl_node_get_producer (o->active, "aux", NULL);
+
+  if (!ref)
+  {
+    ref = add_aux (o, o->active, "gegl:nop");
+  }
+
   if (ref && ref != o->source)
     o->active = ref;
   mrg_queue_draw (o->mrg, NULL);
@@ -1817,8 +1914,8 @@ int cmd_pick (COMMAND_ARGS) /* "pick", 0, "", "changes to pick tool"*/
   tool = TOOL_PICK;
   return 0;
 }
-  int cmd_pan (COMMAND_ARGS);
-int cmd_pan (COMMAND_ARGS) /* "pan", 0, "", "changes to pan tool"*/
+  int cmd_tpan (COMMAND_ARGS);
+int cmd_tpan (COMMAND_ARGS) /* "tpan", 0, "", "changes to pan tool"*/
 {
   tool = TOOL_PICK;
   return 0;
@@ -1841,41 +1938,12 @@ static void commandline_run (MrgEvent *event, void *data1, void *data2)
   mrg_event_stop_propagate (event);
 }
 
-static void gegl_ui (Mrg *mrg, void *data)
+static void iterate_frame (State *o)
 {
-  State *o = data;
-
-  switch (renderer)
-  {
-     case GEGL_RENDERER_BLIT:
-     case GEGL_RENDERER_BLIT_MIPMAP:
-       mrg_gegl_blit (mrg,
-                      0, 0,
-                      mrg_width (mrg), mrg_height (mrg),
-                      o->sink,
-                      o->u, o->v,
-                      o->scale,
-                      o->render_quality);
-     break;
-     case GEGL_RENDERER_THREAD:
-     case GEGL_RENDERER_IDLE:
-       if (o->processor_buffer)
-       {
-         GeglBuffer *buffer = g_object_ref (o->processor_buffer);
-         mrg_gegl_buffer_blit (mrg,
-                               0, 0,
-                               mrg_width (mrg), mrg_height (mrg),
-                               buffer,
-                               o->u, o->v,
-                               o->scale,
-                               o->render_quality);
-         g_object_unref (buffer);
-       }
-       break;
-  }
+  Mrg *mrg = o->mrg;
 
-  if (g_str_has_suffix (o->path, ".gif") ||
-      g_str_has_suffix (o->path, ".GIF"))
+  if (g_str_has_suffix (o->src_path, ".gif") ||
+      g_str_has_suffix (o->src_path, ".GIF"))
    {
      int frames = 0;
      int frame_delay = 0;
@@ -1901,15 +1969,16 @@ static void gegl_ui (Mrg *mrg, void *data)
        o->frame_no = 0;
      gegl_node_set (o->source, "frame", o->frame_no, NULL);
      mrg_queue_draw (o->mrg, NULL);
-   }
-
-  if (o->is_video)
-  {
-    GeglAudioFragment *audio = NULL;
-    gdouble fps;
-    gegl_node_get (o->source, "audio", &audio, "frame-rate", &fps, NULL);
-    if (audio)
     {
+      GeglAudioFragment *audio = NULL;
+      gdouble fps;
+      /* XXX:
+           this currently goes wrong with threaded rendering, since we miss audio frames
+           from the renderer thread, moving this to the render thread would solve that.
+       */
+      gegl_node_get (o->source, "audio", &audio, "frame-rate", &fps, NULL);
+      if (audio)
+      {
        int sample_count = gegl_audio_fragment_get_sample_count (audio);
        if (sample_count > 0)
        {
@@ -1929,14 +1998,113 @@ static void gegl_ui (Mrg *mrg, void *data)
          mrg_pcm_queue (mrg, (void*)&temp_buf[0], sample_count);
          }
 
-         while (mrg_pcm_get_queued (mrg) > 2000)
+         while (mrg_pcm_get_queued (mrg) > sample_count)
             g_usleep (50);
+
          o->prev_frame_played = o->frame_no;
          deferred_redraw (mrg, NULL);
        }
        g_object_unref (audio);
+      }
     }
   }
+}
+
+static void ui_commandline (Mrg *mrg, void *data)
+{
+  State *o = data;
+  float em = mrg_em (mrg);
+  float h = mrg_height (mrg);
+  cairo_t *cr = mrg_cr (mrg);
+  int row = 1;
+  cairo_save (cr);
+  mrg_set_xy (mrg, em, h - em * 1.2 * row);
+  mrg_start (mrg, "div.shell", NULL);
+  mrg_set_edge_left (mrg, em);
+  mrg_start (mrg, "div.prompt", NULL);
+  mrg_printf (mrg, "> ");
+  mrg_end (mrg);
+  mrg_start (mrg, "div.commandline", NULL);
+    mrg_edit_start (mrg, update_commandline, o);
+    mrg_printf (mrg, "%s", commandline);
+    mrg_edit_end (mrg);
+    mrg_end (mrg);
+  mrg_edit_end (mrg);
+  row++;
+
+  mrg_set_xy (mrg, em, h * 0.5);
+
+  {
+    MrgList *lines = NULL;
+    for (MrgList *l = scrollback; l; l = l->next)
+      mrg_list_prepend (&lines, l->data);
+
+    for (MrgList *l = lines; l; l = l->next)
+    {
+      mrg_start (mrg, "div.shellline", NULL);
+      mrg_printf (mrg, "%s", l->data);
+      mrg_end (mrg);
+    }
+    {
+      if (mrg_y (mrg) > h - em * 1.2 * 1)
+      {
+        char *data;
+        mrg_list_reverse (&scrollback);
+        data = scrollback->data;
+        mrg_list_remove (&scrollback, data);
+        mrg_list_reverse (&scrollback);
+        free (data);
+        mrg_queue_draw (mrg, NULL);
+      }
+    }
+    mrg_list_free (&lines);
+
+  }
+  mrg_end (mrg);
+
+  mrg_add_binding (mrg, "return", NULL, NULL, commandline_run, o);
+  cairo_restore (cr);
+}
+
+
+static void gegl_ui (Mrg *mrg, void *data)
+{
+  State *o = data;
+  mrg_stylesheet_add (mrg, css, NULL, 0, NULL);
+
+  switch (renderer)
+  {
+     case GEGL_RENDERER_BLIT:
+     case GEGL_RENDERER_BLIT_MIPMAP:
+       mrg_gegl_blit (mrg,
+                      0, 0,
+                      mrg_width (mrg), mrg_height (mrg),
+                      o->sink,
+                      o->u, o->v,
+                      o->scale,
+                      o->render_quality);
+     break;
+     case GEGL_RENDERER_THREAD:
+     case GEGL_RENDERER_IDLE:
+       if (o->processor_buffer)
+       {
+         GeglBuffer *buffer = g_object_ref (o->processor_buffer);
+         mrg_gegl_buffer_blit (mrg,
+                               0, 0,
+                               mrg_width (mrg), mrg_height (mrg),
+                               buffer,
+                               o->u, o->v,
+                               o->scale,
+                               o->render_quality);
+         g_object_unref (buffer);
+       }
+       break;
+  }
+
+  if (o->playing)
+  {
+    iterate_frame (o);
+  }
 
   if (o->show_controls)
   {
@@ -1968,7 +2136,7 @@ static void gegl_ui (Mrg *mrg, void *data)
       ui_dir_viewer (o);
     }
 
-    mrg_add_binding (mrg, "escape", NULL, NULL, run_command, "go-parent");
+    mrg_add_binding (mrg, "escape", NULL, NULL, run_command, "parent");
     mrg_add_binding (mrg, "return", NULL, NULL, run_command, "toggle-graph");
   }
 
@@ -1991,31 +2159,22 @@ static void gegl_ui (Mrg *mrg, void *data)
     mrg_add_binding (mrg, "tab", NULL, NULL, run_command, "toggle-controls");
     mrg_add_binding (mrg, "control-f", NULL, NULL,  run_command, "toggle-fullscreen");
     if(1)mrg_add_binding (mrg, "control-a", NULL, NULL, run_command, "toggle-slideshow");
-    mrg_add_binding (mrg, "control-r", NULL, NULL, run_command, "preview-less");
-    mrg_add_binding (mrg, "control-t", NULL, NULL, run_command, "preview-more");
 
-    mrg_add_binding (mrg, "control-n", NULL, NULL, run_command, "go-next");
-    mrg_add_binding (mrg, "control-p", NULL, NULL, run_command, "go-prev");
+    mrg_add_binding (mrg, "control-n", NULL, NULL, run_command, "next");
+    mrg_add_binding (mrg, "control-p", NULL, NULL, run_command, "prev");
 
     if (commandline[0]==0)
     {
-      mrg_add_binding (mrg, "+", NULL, NULL, run_command, "zoom-in");
-      mrg_add_binding (mrg, "=", NULL, NULL, run_command, "zoom-out");
-      mrg_add_binding (mrg, "-", NULL, NULL, run_command, "zoom-out");
+      mrg_add_binding (mrg, "+", NULL, NULL, run_command, "zoom in");
+      mrg_add_binding (mrg, "=", NULL, NULL, run_command, "zoom out");
+      mrg_add_binding (mrg, "-", NULL, NULL, run_command, "zoom out");
       mrg_add_binding (mrg, "1", NULL, NULL, run_command, "zoom-1");
     }
   }
 
   if (!edited_prop && !o->editing_op_name)
   {
-    mrg_set_edge_left (mrg, mrg_em (mrg) * 2);
-    mrg_start_with_style (mrg, ".item", NULL, "color:rgb(255,255,255);background-color: rgba(0,0,0,0.5);");
-    mrg_set_xy (mrg, mrg_em (mrg) *2, mrg_height (mrg) - mrg_em (mrg) * 2);
-    mrg_edit_start (mrg, update_commandline, o);
-    mrg_printf (mrg, "%s", commandline);
-    mrg_edit_end (mrg);
-    mrg_end (mrg);
-    mrg_add_binding (mrg, "return", NULL, NULL, commandline_run, o);
+    ui_commandline (mrg, o);
 
     if (commandline[0]==0)
       mrg_add_binding (mrg, "right", NULL, NULL, run_command, "activate-aux");
@@ -2065,9 +2224,15 @@ static char *unsuffix_path (const char *path)
 
 static int is_gegl_path (const char *path)
 {
+  int ret = 0;
   if (g_str_has_suffix (path, ".gegl"))
-    return 1;
-  return 0;
+  {
+    char *unsuffixed = unsuffix_path (path);
+    if (access (unsuffixed, F_OK) != -1)
+      ret = 1;
+    free (unsuffixed);
+  }
+  return ret;
 }
 
 static void contrasty_stroke (cairo_t *cr)
@@ -2090,21 +2255,40 @@ static void load_path (State *o)
   char *path;
   char *meta;
   populate_path_list (o);
+
+  if (o->src_path)
+    free (o->src_path);
+
+  o->playing = 0;
+
   if (is_gegl_path (o->path))
   {
     if (o->save_path)
       free (o->save_path);
     o->save_path = o->path;
-    o->path = unsuffix_path (o->save_path);
+    o->path = unsuffix_path (o->save_path); // or maybe decode first line?
+    o->src_path = strdup (o->path);
   }
   else
   {
     if (o->save_path)
       free (o->save_path);
-    o->save_path = suffix_path (o->path);
+    if (g_str_has_suffix (o->path, ".gegl"))
+    {
+      //fprintf (stderr, "oooo\n");
+      o->save_path = strdup (o->path);
+    }
+    else
+    {
+      o->save_path = suffix_path (o->path);
+      o->src_path = strdup (o->path);
+    }
   }
   path  = o->path;
 
+  fprintf (stderr, "%i %i\n", is_gegl_path(o->path), is_gegl_path(o->save_path));
+  fprintf (stderr, "%s %s\n", o->path, o->save_path);
+
   if (access (o->save_path, F_OK) != -1)
   {
     /* XXX : fix this in the fuse layer of zn! XXX XXX XXX XXX */
@@ -2145,42 +2329,53 @@ static void load_path (State *o)
   else
   {
     meta = NULL;
-    if (is_gegl_path (path))
+    if (is_gegl_path (path) || g_str_has_suffix (path, ".gegl"))
       g_file_get_contents (path, &meta, NULL, NULL);
-    //meta = gegl_meta_get (path);
     if (meta)
     {
-      GSList *nodes, *n;
+      GeglNode *iter;
+      GeglNode *prev = NULL;
       char *containing_path = get_path_parent (o->path);
       o->gegl = gegl_node_new_from_serialized (meta, containing_path);
       free (containing_path);
-      o->sink = gegl_node_new_child (o->gegl,
-                       "operation", "gegl:nop", NULL);
+      o->sink = o->gegl;
       o->source = NULL;
-      gegl_node_link_many (
-        gegl_node_get_producer (o->gegl, "input", NULL), o->sink, NULL);
-      nodes = gegl_node_get_children (o->gegl);
-      for (n = nodes; n; n=n->next)
+
+      for (iter = o->sink; iter; iter = gegl_node_get_producer (iter, "input", NULL))
       {
-        const char *op_name = gegl_node_get_operation (n->data);
+        const char *op_name = gegl_node_get_operation (iter);
         if (!strcmp (op_name, "gegl:load"))
         {
-          GeglNode *load;
           gchar *path;
-          gegl_node_get (n->data, "path", &path, NULL);
-          load_into_buffer (o, path);
-          gegl_node_set (n->data, "operation", "gegl:nop", NULL);
-          o->source = n->data;
-          load = gegl_node_new_child (o->gegl, "operation", "gegl:buffer-source",
-                                               "buffer", o->buffer, NULL);
-          gegl_node_link_many (load, o->source, NULL);
+          gegl_node_get (iter, "path", &path, NULL);
+
+          if (g_str_has_suffix (path, ".gif"))
+          {
+             o->source = gegl_node_new_child (o->gegl,
+             "operation", "gegl:gif-load", "path", path, "frame", o->frame_no, NULL);
+             gegl_node_link_many (o->source, prev, NULL);
+          }
+          else
+          {
+            load_into_buffer (o, path);
+             o->source = gegl_node_new_child (o->gegl, "operation", "gegl:buffer-source",
+                                             "buffer", o->buffer, NULL);
+
+            gegl_node_link_many (o->source, prev, NULL);
+          }
+          if (o->src_path)
+            free (o->src_path);
+          o->src_path = strdup (path);
+
+          o->save = gegl_node_new_child (o->gegl, "operation", "gegl:save",
+                                              "path", o->save_path,
+                                              NULL);
           g_free (path);
           break;
         }
+        prev = iter;
       }
-      o->save = gegl_node_new_child (o->gegl, "operation", "gegl:save",
-                                              "path", path,
-                                              NULL);
+
     }
     else
     {
@@ -2188,6 +2383,9 @@ static void load_path (State *o)
       o->sink = gegl_node_new_child (o->gegl,
                          "operation", "gegl:nop", NULL);
       load_into_buffer (o, path);
+      if (o->src_path)
+        free (o->src_path);
+      o->src_path = strdup (path);
       o->source = gegl_node_new_child (o->gegl,
                                      "operation", "gegl:buffer-source",
                                      NULL);
@@ -2210,6 +2408,8 @@ static void load_path (State *o)
         zoom_to_fit (o);
     }
   }
+  
+  o->playing = o->is_video;
   if (o->ops)
   {
     GeglNode *ret_sink = NULL;
@@ -2281,8 +2481,20 @@ static void go_prev (State *o)
   }
 }
 
- int cmd_go_next (COMMAND_ARGS);
-int cmd_go_next (COMMAND_ARGS) /* "go-next", 0, "", ""*/
+ int cmd_clear (COMMAND_ARGS);
+int cmd_clear (COMMAND_ARGS) /* "clear", 0, "", ""*/
+{
+  while (scrollback)
+  {
+    char *data = scrollback->data;
+    mrg_list_remove (&scrollback, data);
+    free (data);
+  }
+  return 0;
+}
+
+ int cmd_next (COMMAND_ARGS);
+int cmd_next (COMMAND_ARGS) /* "next", 0, "", "next sibling element in current collection/folder"*/
 {
   State *o = hack_state;
   if (o->rev)
@@ -2292,8 +2504,8 @@ int cmd_go_next (COMMAND_ARGS) /* "go-next", 0, "", ""*/
   return 0;
 }
 
- int cmd_go_parent (COMMAND_ARGS);
-int cmd_go_parent (COMMAND_ARGS) /* "go-parent", 0, "", ""*/
+ int cmd_parent (COMMAND_ARGS);
+int cmd_parent (COMMAND_ARGS) /* "parent", 0, "", "enter parent collection (switches to folder mode)"*/
 {
   State *o = hack_state;
   if (o->rev)
@@ -2303,8 +2515,8 @@ int cmd_go_parent (COMMAND_ARGS) /* "go-parent", 0, "", ""*/
   return 0;
 }
 
- int cmd_go_prev (COMMAND_ARGS);
-int cmd_go_prev (COMMAND_ARGS) /* "go-prev", 0, "", ""*/
+ int cmd_prev (COMMAND_ARGS);
+int cmd_prev (COMMAND_ARGS) /* "prev", 0, "", "previous sibling element in current collection/folder"*/
 {
   State *o = hack_state;
   if (o->rev)
@@ -2419,7 +2631,7 @@ static void load_into_buffer (State *o, const char *path)
   else
     {
       GeglRectangle extent = {0,0,1,1}; /* segfaults with NULL / 0,0,0,0*/
-      o->buffer = gegl_buffer_new (&extent, babl_format("R'G'B' u8"));
+      o->buffer = gegl_buffer_new (&extent, babl_format("RaGaBaA float"));
     }
 }
 
@@ -2505,56 +2717,74 @@ int cmd_zoom_fit_buffer (COMMAND_ARGS) /* "zoom-fit-buffer", 0, "", ""*/
   return 0;
 }
 
-  int cmd_zoom_fit (COMMAND_ARGS);
-int cmd_zoom_fit (COMMAND_ARGS) /* "zoom-fit", 0, "", ""*/
-{
-  zoom_to_fit (hack_state);
-  return 0;
-}
-
-static int deferred_zoom_to_fit (Mrg *mrg, void *data)
+static void zoom_at (State *o, float screen_cx, float screen_cy, float factor)
 {
-  argvs_eval ("zoom-fit");
-  return 0;
-}
+  float x, y;
+  get_coords (o, screen_cx, screen_cy, &x, &y);
+  o->scale *= factor;
+  o->u = x * o->scale - screen_cx;
+  o->v = y * o->scale - screen_cy;
 
-  int cmd_pan_left (COMMAND_ARGS);
-int cmd_pan_left (COMMAND_ARGS) /* "pan-left", 0, "", ""*/
-{
-  State *o = hack_state;
-  float amount = mrg_width (o->mrg) * 0.1;
-  o->u = o->u - amount;
+  o->renderer_state = 0;
   mrg_queue_draw (o->mrg, NULL);
-  return 0;
 }
 
-  int cmd_pan_right (COMMAND_ARGS);
-int cmd_pan_right (COMMAND_ARGS) /* "pan-right", 0, "", ""*/
+
+
+  int cmd_pan (COMMAND_ARGS);
+int cmd_pan (COMMAND_ARGS) /* "pan", 2, "<rel-x> <rel-y>", "pans viewport"*/
 {
   State *o = hack_state;
-  float amount = mrg_width (o->mrg) * 0.1;
-  o->u = o->u + amount;
-  mrg_queue_draw (o->mrg, NULL);
+  float amount_u = mrg_width (o->mrg)  * g_strtod (argv[1], NULL);
+  float amount_v = mrg_height (o->mrg) * g_strtod (argv[2], NULL);
+  o->u += amount_u;
+  o->v += amount_v;
   return 0;
 }
 
-  int cmd_pan_down (COMMAND_ARGS);
-int cmd_pan_down (COMMAND_ARGS) /* "pan-down", 0, "", ""*/
+  int cmd_zoom (COMMAND_ARGS);
+int cmd_zoom (COMMAND_ARGS) /* "zoom", -1, "<fit|in [amt]|out [amt]|zoom-level>", "Changes zoom level, 
asbolsute or relative, around middle of screen."*/
 {
   State *o = hack_state;
-  float amount = mrg_width (o->mrg) * 0.1;
-  o->v = o->v + amount;
-  mrg_queue_draw (o->mrg, NULL);
+
+  if (!argv[1]) return -1;
+  if (!strcmp(argv[1], "fit"))
+  {
+    zoom_to_fit (o);
+  }
+  else if (!strcmp(argv[1], "in"))
+  {
+    float zoom_factor = 0.1;
+    if (argv[2])
+      zoom_factor = g_strtod (argv[2], NULL);
+    zoom_factor += 1.0;
+
+    zoom_at (o, mrg_width(o->mrg)/2, mrg_height(o->mrg)/2, zoom_factor);
+  }
+  else if (!strcmp(argv[1], "out"))
+  {
+    float zoom_factor = 0.1;
+    if (argv[2])
+      zoom_factor = g_strtod (argv[2], NULL);
+    zoom_factor += 1.0;
+
+    zoom_at (o, mrg_width(o->mrg)/2, mrg_height(o->mrg)/2, 1.0f/zoom_factor);
+  }
+  else
+  {
+    float x, y;
+    get_coords (o, mrg_width(o->mrg)/2, mrg_height(o->mrg)/2, &x, &y);
+    o->scale = g_strtod(argv[1], NULL);
+    o->u = x * o->scale - mrg_width(o->mrg)/2;
+    o->v = y * o->scale - mrg_height(o->mrg)/2;
+    printf ("uhandled argument to zoom %s\n", argv[1]);
+  }
   return 0;
 }
 
-  int cmd_pan_up (COMMAND_ARGS);
-int cmd_pan_up (COMMAND_ARGS) /* "pan-up", 0, "", ""*/
+static int deferred_zoom_to_fit (Mrg *mrg, void *data)
 {
-  State *o = hack_state;
-  float amount = mrg_width (o->mrg) * 0.1;
-  o->v = o->v - amount;
-  mrg_queue_draw (o->mrg, NULL);
+  argvs_eval ("zoom fit");
   return 0;
 }
 
@@ -2565,26 +2795,6 @@ static void get_coords (State *o, float screen_x, float screen_y, float *gegl_x,
   *gegl_y = (o->v + screen_y) / scale;
 }
 
-  int cmd_preview_more(COMMAND_ARGS);
-int cmd_preview_more (COMMAND_ARGS) /* "preview-more", 0, "", ""*/
-{
-  State *o = hack_state;
-  o->render_quality *= 2;
-  mrg_queue_draw (o->mrg, NULL);
-  return 0;
-}
-
-  int cmd_preview_less(COMMAND_ARGS);
-int cmd_preview_less (COMMAND_ARGS) /* "preview-less", 0, "", ""*/
-{
-  State *o = hack_state;
-  o->render_quality /= 2;
-  if (o->render_quality <= 1.0)
-    o->render_quality = 1.0;
-  mrg_queue_draw (o->mrg, NULL);
-  return 0;
-}
-
   int cmd_zoom_1 (COMMAND_ARGS);
 int cmd_zoom_1 (COMMAND_ARGS) /* "zoom-1", 0, "", ""*/
 {
@@ -2599,50 +2809,115 @@ int cmd_zoom_1 (COMMAND_ARGS) /* "zoom-1", 0, "", ""*/
   return 0;
 }
 
-static void zoom_at (State *o, float screen_cx, float screen_cy, float factor)
-{
-  float x, y;
-  get_coords (o, screen_cx, screen_cy, &x, &y);
-  o->scale *= factor;
-  o->u = x * o->scale - screen_cx;
-  o->v = y * o->scale - screen_cy;
 
-  o->renderer_state = 0;
-  mrg_queue_draw (o->mrg, NULL);
+static void scroll_cb (MrgEvent *event, void *data1, void *data2)
+{
+  switch (event->scroll_direction)
+  {
+     case MRG_SCROLL_DIRECTION_DOWN:
+       /* XXX : passing floating point values string formatted is awkard in C,
+                so we use the utility function instead - this could be two extra
+                relative coordinate args to the zoom command */
+       zoom_at (data1, event->device_x, event->device_y, 1.0/1.05);
+       break;
+     case MRG_SCROLL_DIRECTION_UP:
+       zoom_at (data1, event->device_x, event->device_y, 1.05);
+       break;
+     default:
+       break;
+  }
 }
 
-  int cmd_zoom_in (COMMAND_ARGS);
-int cmd_zoom_in (COMMAND_ARGS) /* "zoom-in", 0, "", ""*/
+static void print_setting (Setting *setting)
 {
   State *o = hack_state;
-  zoom_at (o, mrg_width(o->mrg)/2, mrg_height(o->mrg)/2, 1.1);
-  return 0;
+  switch (setting->type)
+  {
+    case 0:
+      printf ("%s %i%s\n  %s\n", setting->name,
+        (*(int*)(((char *)o) + setting->offset)), setting->read_only?"  (RO)":"", setting->description);
+    break;
+    case 1:
+      printf ("%s %f%s\n  %s\n", setting->name,
+        (*(float*)(((char *)o) + setting->offset)), setting->read_only?" (RO)":"", setting->description);
+     break;
+    case 2:
+      {
+        char *value = NULL;
+        memcpy (&value, (((char *)o) + setting->offset), sizeof (void*));
+        printf ("%s %s%s\n  %s\n", setting->name, value, setting->read_only?" (RO)":"", 
setting->description);
+      }
+    break;
+  }
 }
 
-  int cmd_zoom_out (COMMAND_ARGS);
-int cmd_zoom_out (COMMAND_ARGS) /* "zoom-out", 0, "", ""*/
+static int set_setting (Setting *setting, const char *value)
 {
   State *o = hack_state;
-  zoom_at (o, mrg_width(o->mrg)/2, mrg_height(o->mrg)/2, 1.0/1.1);
+  if (setting->read_only)
+    return -1;
+  switch (setting->type)
+  {
+    case 0:
+        (*(int*)(((char *)o) + setting->offset)) = atoi (value);
+    break;
+    case 1:
+        (*(float*)(((char *)o) + setting->offset)) = g_strtod (value, NULL);
+    break;
+    case 2:
+        memcpy ((((char *)o) + setting->offset), strdup(value), sizeof (void*));
+    break;
+  }
   return 0;
 }
 
-
-static void scroll_cb (MrgEvent *event, void *data1, void *data2)
+  int cmd_set (COMMAND_ARGS);
+int cmd_set (COMMAND_ARGS) /* "set", -1, "<setting> | <setting> <new value>| empty", "query/set various 
settings"*/
 {
-  switch (event->scroll_direction)
+  char *key = NULL;
+  char *value = NULL;
+  int n_settings = sizeof (settings)/sizeof(settings[0]);
+
+  if (argv[1])
   {
-     case MRG_SCROLL_DIRECTION_DOWN:
-       zoom_at (data1, event->device_x, event->device_y, 1.0/1.05);
-       break;
-     case MRG_SCROLL_DIRECTION_UP:
-       zoom_at (data1, event->device_x, event->device_y, 1.05);
-       break;
-     default:
-       break;
+    key = argv[1];
+    if (argv[2])
+      value = argv[2];
   }
+  else
+  {
+    for (int i = 0; i < n_settings; i++)
+    {
+      print_setting (&settings[i]);
+    }
+    return 0;
+  }
+
+  if (value)
+  {
+    for (int i = 0; i < n_settings; i++)
+    {
+      if (!strcmp (key, settings[i].name))
+      {
+        return set_setting (&settings[i], value);
+      }
+    }
+  }
+  else
+  {
+    for (int i = 0; i < n_settings; i++)
+    {
+      if (!strcmp (key, settings[i].name))
+      {
+        print_setting (&settings[i]);
+        break;
+      }
+    }
+  }
+  return 0;
 }
 
+
   int cmd_toggle_graph (COMMAND_ARGS);
 int cmd_toggle_graph (COMMAND_ARGS) /* "toggle-graph", 0, "", ""*/
 {
@@ -2668,10 +2943,10 @@ int cmd_discard (COMMAND_ARGS) /* "discard", 0, "", "moves the current image to
   char *old_path = strdup (o->path);
   char *tmp;
   char *lastslash;
-  argvs_eval ("go-next");
+  argvs_eval ("next");
   if (!strcmp (old_path, o->path))
    {
-     argvs_eval ("go-prev");
+     argvs_eval ("prev");
    }
   tmp = strdup (old_path);
   lastslash  = strrchr (tmp, '/');
@@ -2699,29 +2974,23 @@ int cmd_discard (COMMAND_ARGS) /* "discard", 0, "", "moves the current image to
   int cmd_save (COMMAND_ARGS);
 int cmd_save (COMMAND_ARGS) /* "save", 0, "", ""*/
 {
-  GeglNode *load;
   State *o = hack_state;
-  gchar *path;
   char *serialized;
 
-  gegl_node_link_many (o->sink, o->save, NULL);
-  gegl_node_process (o->save);
-  gegl_node_get (o->save, "path", &path, NULL);
-  fprintf (stderr, "saved to %s\n", path);
-
-  load = gegl_node_new_child (o->gegl, "operation", "gegl:load",
-                                    "path", o->path,
-                                    NULL);
-  gegl_node_link_many (load, o->source, NULL);
   {
-    char *containing_path = get_path_parent (o->path);
-    serialized = gegl_serialize (NULL, o->sink, containing_path, 
GEGL_SERIALIZE_TRIM_DEFAULTS|GEGL_SERIALIZE_VERSION|GEGL_SERIALIZE_INDENT);
+    char *containing_path = get_path_parent (o->save_path);
+    serialized = gegl_serialize (o->source,
+                   gegl_node_get_producer (o->sink, "input", NULL),
+ containing_path, GEGL_SERIALIZE_TRIM_DEFAULTS|GEGL_SERIALIZE_VERSION|GEGL_SERIALIZE_INDENT);
     free (containing_path);
   }
-  gegl_node_remove_child (o->gegl, load);
 
-  g_file_set_contents (path, serialized, -1, NULL);
-  fprintf (stderr, "%s\n", serialized);
+  {
+    char *prepended = g_strdup_printf ("gegl:load path=%s\n%s", basename(o->src_path), serialized);
+    g_file_set_contents (o->save_path, prepended, -1, NULL);
+    g_free (prepended);
+  }
+
   g_free (serialized);
   o->rev = 0;
   return 0;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]