[gimp/wip/animation: 192/197] plug-ins: add a spinner to indicate animation frames still rendering.



commit ee4be4703afbeddab5559ae36b7873698e0c822f
Author: Jehan <jehan girinstud io>
Date:   Thu Aug 17 23:17:10 2017 +0200

    plug-ins: add a spinner to indicate animation frames still rendering.
    
    It doesn't give much details on how many frames, or which ones. But at
    least there is some activity indicator which may give hints about why a
    playback is not as expected.

 plug-ins/animation-play/core/animation-playback.c  |   62 +++++++++++++---
 plug-ins/animation-play/core/animation-playback.h  |    6 +-
 plug-ins/animation-play/core/animation-renderer.c  |   34 ++++++++-
 plug-ins/animation-play/core/animation-renderer.h  |    2 +
 plug-ins/animation-play/widgets/animation-dialog.c |   77 ++++++++++++++------
 plug-ins/animation-play/widgets/animation-xsheet.c |    8 +-
 6 files changed, 148 insertions(+), 41 deletions(-)
---
diff --git a/plug-ins/animation-play/core/animation-playback.c 
b/plug-ins/animation-play/core/animation-playback.c
index ac53b2e..eadb192 100644
--- a/plug-ins/animation-play/core/animation-playback.c
+++ b/plug-ins/animation-play/core/animation-playback.c
@@ -34,9 +34,10 @@ enum
   START,
   STOP,
   RANGE,
-  RENDER,
+  POSITION,
   LOW_FRAMERATE,
   PROXY_CHANGED,
+  RENDERING,
   LAST_SIGNAL
 };
 
@@ -88,6 +89,9 @@ static void       on_duration_changed                       (Animation         *
 static void       on_cache_updated                          (AnimationRenderer *renderer,
                                                              gint               position,
                                                              AnimationPlayback *playback);
+static void       on_rendering                              (AnimationRenderer *renderer,
+                                                             gboolean           rendering,
+                                                             AnimationPlayback *playback);
 
 /* Timer callback for playback. */
 static gboolean   animation_playback_advance_frame_callback (AnimationPlayback *playback);
@@ -167,21 +171,22 @@ animation_playback_class_init (AnimationPlaybackClass *klass)
                   G_TYPE_INT,
                   G_TYPE_INT);
   /**
-   * AnimationPlayback::render:
+   * AnimationPlayback::position:
    * @playback: the #AnimationPlayback.
-   * @position: current position to be rendered.
+   * @position: current position to be displayed.
    * @buffer: the #GeglBuffer for the frame at @position.
    * @must_draw_null: meaning of a %NULL @buffer.
    * %TRUE means we have to draw an empty frame.
    * %FALSE means the new frame is same as the current frame.
    *
-   * Sends a request for render to the GUI.
+   * This signal indicates that playback position has changed so that
+   * the GUI can display it and process other updates.
    */
-  animation_playback_signals[RENDER] =
-    g_signal_new ("render",
+  animation_playback_signals[POSITION] =
+    g_signal_new ("position",
                   G_TYPE_FROM_CLASS (klass),
                   G_SIGNAL_RUN_FIRST,
-                  G_STRUCT_OFFSET (AnimationPlaybackClass, render),
+                  G_STRUCT_OFFSET (AnimationPlaybackClass, position),
                   NULL, NULL,
                   NULL,
                   G_TYPE_NONE,
@@ -227,6 +232,27 @@ animation_playback_class_init (AnimationPlaybackClass *klass)
                   1,
                   G_TYPE_DOUBLE);
 
+  /**
+   * AnimationPlayback::rendering:
+   * @playback: the #AnimationPlayback.
+   * @has_queue: whether there is more to render.
+   *
+   * The ::rendering signal will be emitted when the renderer has queued
+   * frames, and a last time with @has_queue as #TRUE when all is
+   * rendered. It mostly passes along AnimationRenderer::rendering
+   * signal, since only @playback has access to the renderer object.
+   */
+  animation_playback_signals[RENDERING] =
+    g_signal_new ("rendering",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  G_STRUCT_OFFSET (AnimationRendererClass, rendering),
+                  NULL, NULL,
+                  NULL,
+                  G_TYPE_NONE,
+                  1,
+                  G_TYPE_BOOLEAN);
+
   object_class->finalize     = animation_playback_finalize;
   object_class->set_property = animation_playback_set_property;
   object_class->get_property = animation_playback_get_property;
@@ -416,7 +442,7 @@ animation_playback_next (AnimationPlayback *playback)
       buffer = animation_renderer_get_buffer (renderer,
                                               playback->priv->position);
     }
-  g_signal_emit (playback, animation_playback_signals[RENDER], 0,
+  g_signal_emit (playback, animation_playback_signals[POSITION], 0,
                  playback->priv->position, buffer, ! identical);
   if (buffer != NULL)
     {
@@ -452,7 +478,7 @@ animation_playback_prev (AnimationPlayback *playback)
     {
       buffer = animation_renderer_get_buffer (renderer, playback->priv->position);
     }
-  g_signal_emit (playback, animation_playback_signals[RENDER], 0,
+  g_signal_emit (playback, animation_playback_signals[POSITION], 0,
                  playback->priv->position, buffer, ! identical);
   if (buffer)
     g_object_unref (buffer);
@@ -484,7 +510,7 @@ animation_playback_jump (AnimationPlayback *playback,
     {
       buffer = animation_renderer_get_buffer (renderer, playback->priv->position);
     }
-  g_signal_emit (playback, animation_playback_signals[RENDER], 0,
+  g_signal_emit (playback, animation_playback_signals[POSITION], 0,
                  playback->priv->position, buffer, ! identical);
   if (buffer)
     g_object_unref (buffer);
@@ -663,6 +689,8 @@ animation_playback_set_property (GObject      *object,
           playback->priv->renderer = animation_renderer_new (object);
           g_signal_connect (playback->priv->renderer, "cache-updated",
                             G_CALLBACK (on_cache_updated), playback);
+          g_signal_connect (playback->priv->renderer, "rendering",
+                            G_CALLBACK (on_rendering), playback);
         }
       break;
 
@@ -733,7 +761,7 @@ on_cache_updated (AnimationRenderer *renderer,
 
       renderer = ANIMATION_RENDERER (playback->priv->renderer);
       buffer = animation_renderer_get_buffer (renderer, position);
-      g_signal_emit (playback, animation_playback_signals[RENDER], 0,
+      g_signal_emit (playback, animation_playback_signals[POSITION], 0,
                      position, buffer, TRUE);
       if (buffer)
         {
@@ -742,6 +770,18 @@ on_cache_updated (AnimationRenderer *renderer,
     }
 }
 
+static void
+on_rendering (AnimationRenderer *renderer,
+              gboolean           rendering,
+              AnimationPlayback *playback)
+{
+  /* Just transform the renderer's "rendering" signal into a playback's
+   * one to pass the information along to the GUI.
+   */
+  g_signal_emit (playback, animation_playback_signals[RENDERING], 0,
+                 rendering);
+}
+
 static gboolean
 animation_playback_advance_frame_callback (AnimationPlayback *playback)
 {
diff --git a/plug-ins/animation-play/core/animation-playback.h 
b/plug-ins/animation-play/core/animation-playback.h
index 12f59ab..ed3c11f 100644
--- a/plug-ins/animation-play/core/animation-playback.h
+++ b/plug-ins/animation-play/core/animation-playback.h
@@ -49,14 +49,16 @@ struct _AnimationPlaybackClass
   void       (*range)            (AnimationPlayback *playback,
                                   gint               start,
                                   gint               stop);
-  void       (*render)           (AnimationPlayback *playback,
+  void       (*position)         (AnimationPlayback *playback,
                                   gint               position,
                                   GeglBuffer        *buffer,
                                   gboolean           must_draw_null);
   void       (*low_framerate)    (AnimationPlayback *playback,
                                   gdouble            actual_fps);
-  void       (*proxy_changed)    (Animation         *animation,
+  void       (*proxy_changed)    (AnimationPlayback *animation,
                                   gdouble            ratio);
+  void       (*rendering)        (AnimationPlayback *renderer,
+                                  gboolean           has_render_queue);
 };
 
 GType         animation_playback_get_type (void);
diff --git a/plug-ins/animation-play/core/animation-renderer.c 
b/plug-ins/animation-play/core/animation-renderer.c
index 100c618..1262087 100644
--- a/plug-ins/animation-play/core/animation-renderer.c
+++ b/plug-ins/animation-play/core/animation-renderer.c
@@ -32,6 +32,7 @@
 enum
 {
   CACHE_UPDATED,
+  RENDERING,
   LAST_SIGNAL
 };
 enum
@@ -102,8 +103,8 @@ animation_renderer_class_init (AnimationRendererClass *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   /**
-   * Animation::cache-updated:
-   * @animation: the animation.
+   * AnimationRenderer::cache-updated:
+   * @renderer: the #AnimationRenderer.
    * @position: the frame position whose cache was updated.
    *
    * The ::cache-updated signal will be emitted when the contents
@@ -119,6 +120,25 @@ animation_renderer_class_init (AnimationRendererClass *klass)
                   G_TYPE_NONE,
                   1,
                   G_TYPE_INT);
+  /**
+   * AnimationRenderer::rendering:
+   * @renderer: the #AnimationRenderer.
+   * @has_queue: whether there is more to render.
+   *
+   * The ::rendering signal will be emitted when the renderer has queued
+   * frames, and a last time with @has_queue as #TRUE when all is
+   * rendered.
+   */
+  signals[RENDERING] =
+    g_signal_new ("rendering",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  G_STRUCT_OFFSET (AnimationRendererClass, rendering),
+                  NULL, NULL,
+                  NULL,
+                  G_TYPE_NONE,
+                  1,
+                  G_TYPE_BOOLEAN);
 
   object_class->finalize     = animation_renderer_finalize;
   object_class->set_property = animation_renderer_set_property;
@@ -329,7 +349,7 @@ animation_renderer_idle_update (AnimationRenderer *renderer)
   while ((p = g_async_queue_try_pop (renderer->priv->ack_queue)))
     {
       gint frame = GPOINTER_TO_INT (p) - 1;
-      g_signal_emit_by_name (renderer, "cache-updated", frame);
+      g_signal_emit (renderer, signals[CACHE_UPDATED], 0, frame);
     }
   /* Make sure the UI gets updated regularly. */
   while (g_main_context_pending (NULL))
@@ -344,6 +364,11 @@ animation_renderer_idle_update (AnimationRenderer *renderer)
     {
       retval = G_SOURCE_REMOVE;
       renderer->priv->idle_id = 0;
+      g_signal_emit (renderer, signals[RENDERING], 0, FALSE);
+    }
+  else if (renderer->priv && renderer->priv->queue)
+    {
+      g_signal_emit (renderer, signals[RENDERING], 0, TRUE);
     }
 
   return retval;
@@ -395,6 +420,7 @@ on_proxy_changed (AnimationPlayback *playback,
                                   */
                                  0);
     }
+  g_signal_emit (renderer, signals[RENDERING], 0, TRUE);
   renderer->priv->idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE,
                                              (GSourceFunc) animation_renderer_idle_update,
                                              renderer, NULL);
@@ -438,6 +464,7 @@ on_frames_changed (Animation         *animation,
                                                    (GSourceFunc) animation_renderer_idle_update,
                                                    renderer, NULL);
     }
+  g_signal_emit (renderer, signals[RENDERING], 0, TRUE);
 }
 
 static void
@@ -520,6 +547,7 @@ on_invalidate_cache (Animation         *animation,
                                  0);
     }
   g_list_free (update);
+  g_signal_emit (renderer, signals[RENDERING], 0, TRUE);
   renderer->priv->idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE,
                                              (GSourceFunc) animation_renderer_idle_update,
                                              renderer, NULL);
diff --git a/plug-ins/animation-play/core/animation-renderer.h 
b/plug-ins/animation-play/core/animation-renderer.h
index 0de5115..86e7126 100644
--- a/plug-ins/animation-play/core/animation-renderer.h
+++ b/plug-ins/animation-play/core/animation-renderer.h
@@ -45,6 +45,8 @@ struct _AnimationRendererClass
 
   void         (*cache_updated)  (AnimationRenderer *renderer,
                                   gint               position);
+  void         (*rendering)      (AnimationRenderer *renderer,
+                                  gboolean           has_render_queue);
 };
 
 GType       animation_renderer_get_type    (void);
diff --git a/plug-ins/animation-play/widgets/animation-dialog.c 
b/plug-ins/animation-play/widgets/animation-dialog.c
index 4a05e37..422de0a 100755
--- a/plug-ins/animation-play/widgets/animation-dialog.c
+++ b/plug-ins/animation-play/widgets/animation-dialog.c
@@ -80,6 +80,7 @@ struct _AnimationDialogPrivate
   /* Bar above the preview. */
   GtkWidget         *upper_bar;
   GtkWidget         *zoomcombo;
+  GtkWidget         *render_spinner;
   GtkWidget         *refresh;
   GtkWidget         *export;
   gboolean           cancel_export;
@@ -250,6 +251,9 @@ static void        framerate_changed         (Animation         *animation,
 static void        low_framerate_cb          (AnimationPlayback *playback,
                                               gdouble            real_framerate,
                                               AnimationDialog   *dialog);
+static void        playback_rendering        (AnimationPlayback *playback,
+                                              gboolean           is_rendering,
+                                              AnimationDialog   *dialog);
 
 /* Rendering/Playing Functions */
 static gboolean    repaint_da                (GtkWidget        *darea,
@@ -277,7 +281,7 @@ static gboolean    shape_released            (GtkWidget        *widget);
 static gboolean    shape_motion              (GtkWidget        *widget,
                                               GdkEventMotion   *event);
 
-static void        render_callback           (AnimationPlayback *animation,
+static void        position_callback         (AnimationPlayback *animation,
                                               gint              frame_number,
                                               GeglBuffer       *buffer,
                                               gboolean          must_draw_null,
@@ -746,6 +750,10 @@ animation_dialog_constructed (GObject *object)
   gtk_box_pack_end (GTK_BOX (priv->upper_bar), widget, FALSE, FALSE, 0);
   gtk_widget_show (widget);
 
+  /* Status progress bar for render info. */
+  priv->render_spinner = gtk_spinner_new ();
+  gtk_box_pack_end (GTK_BOX (priv->upper_bar), priv->render_spinner, FALSE, FALSE, 0);
+
   /***********/
   /* Drawing */
   /***********/
@@ -1296,27 +1304,33 @@ animation_dialog_set_animation (AnimationDialog *dialog,
   if (priv->animation)
     {
       g_signal_handlers_disconnect_by_func (priv->animation,
-                                            G_CALLBACK (proxy_changed),
-                                            dialog);
-      g_signal_handlers_disconnect_by_func (priv->animation,
                                             G_CALLBACK (framerate_changed),
                                             dialog);
-      g_signal_handlers_disconnect_by_func (priv->playback,
-                                            G_CALLBACK (playback_range_changed),
-                                            dialog);
-
       g_signal_handlers_disconnect_by_func (priv->animation,
                                             (GCallback) show_loading_progress,
                                             dialog);
       g_signal_handlers_disconnect_by_func (priv->animation,
-                                            (GCallback) update_progress,
+                                            (GCallback) check_cancel_loading,
                                             dialog);
       g_signal_handlers_disconnect_by_func (priv->animation,
-                                            G_CALLBACK (render_callback),
+                                            (GCallback) update_progress,
+                                            dialog);
+
+      g_signal_handlers_disconnect_by_func (priv->playback,
+                                            G_CALLBACK (proxy_changed),
+                                            dialog);
+      g_signal_handlers_disconnect_by_func (priv->playback,
+                                            G_CALLBACK (playback_range_changed),
+                                            dialog);
+      g_signal_handlers_disconnect_by_func (priv->playback,
+                                            G_CALLBACK (position_callback),
                                             dialog);
       g_signal_handlers_disconnect_by_func (priv->playback,
                                             G_CALLBACK (low_framerate_cb),
                                             dialog);
+      g_signal_handlers_disconnect_by_func (priv->playback,
+                                            G_CALLBACK (playback_rendering),
+                                            dialog);
     }
 
   /* Block all handlers on UI widgets. */
@@ -1497,10 +1511,6 @@ animation_dialog_set_animation (AnimationDialog *dialog,
   g_signal_connect (priv->animation, "framerate-changed",
                     G_CALLBACK (framerate_changed),
                     dialog);
-  g_signal_connect (priv->playback, "range",
-                    G_CALLBACK (playback_range_changed),
-                    dialog);
-
   g_signal_connect (priv->animation, "loading",
                     (GCallback) show_loading_progress,
                     dialog);
@@ -1515,12 +1525,18 @@ animation_dialog_set_animation (AnimationDialog *dialog,
   g_signal_connect (priv->playback, "proxy-changed",
                     G_CALLBACK (proxy_changed),
                     dialog);
-  g_signal_connect (priv->playback, "render",
-                    G_CALLBACK (render_callback),
+  g_signal_connect (priv->playback, "range",
+                    G_CALLBACK (playback_range_changed),
+                    dialog);
+  g_signal_connect (priv->playback, "position",
+                    G_CALLBACK (position_callback),
                     dialog);
   g_signal_connect (priv->playback, "low-framerate",
                     G_CALLBACK (low_framerate_cb),
                     dialog);
+  g_signal_connect (priv->playback, "rendering",
+                    G_CALLBACK (playback_rendering),
+                    dialog);
 
   /* Set the playback and its default state. */
   animation_playback_set_animation (priv->playback, animation, xml);
@@ -2398,6 +2414,25 @@ low_framerate_cb (AnimationPlayback *playback,
                                      dialog);
 }
 
+static void
+playback_rendering (AnimationPlayback *playback,
+                    gboolean           is_rendering,
+                    AnimationDialog   *dialog)
+{
+  AnimationDialogPrivate *priv = GET_PRIVATE (dialog);
+
+  if (is_rendering)
+    {
+      gtk_widget_show (priv->render_spinner);
+      gtk_spinner_start (GTK_SPINNER (priv->render_spinner));
+    }
+  else
+    {
+      gtk_spinner_stop (GTK_SPINNER (priv->render_spinner));
+      gtk_widget_hide (priv->render_spinner);
+    }
+}
+
 /* Rendering Functions */
 
 static gboolean
@@ -2739,11 +2774,11 @@ shape_motion (GtkWidget      *widget,
 }
 
 static void
-render_callback (AnimationPlayback *playback,
-                 gint               frame_number,
-                 GeglBuffer        *buffer,
-                 gboolean           must_draw_null,
-                 AnimationDialog   *dialog)
+position_callback (AnimationPlayback *playback,
+                   gint               frame_number,
+                   GeglBuffer        *buffer,
+                   gboolean           must_draw_null,
+                   AnimationDialog   *dialog)
 {
   render_frame (dialog, buffer, must_draw_null);
 
diff --git a/plug-ins/animation-play/widgets/animation-xsheet.c 
b/plug-ins/animation-play/widgets/animation-xsheet.c
index 1420556..bd0eebd 100755
--- a/plug-ins/animation-play/widgets/animation-xsheet.c
+++ b/plug-ins/animation-play/widgets/animation-xsheet.c
@@ -164,7 +164,7 @@ static void     on_camera_keyframe_deleted     (AnimationCamera   *camera,
 /* Callbacks on playback. */
 static void     on_playback_stopped            (AnimationPlayback *playback,
                                                 AnimationXSheet   *xsheet);
-static void     on_playback_rendered           (AnimationPlayback *animation,
+static void     on_playback_position           (AnimationPlayback *animation,
                                                 gint               frame_number,
                                                 GeglBuffer        *buffer,
                                                 gboolean           must_draw_null,
@@ -333,7 +333,7 @@ animation_xsheet_new (AnimationCelAnimation *animation,
                          NULL);
   ANIMATION_XSHEET (xsheet)->priv->playback = playback;
   g_signal_connect (ANIMATION_XSHEET (xsheet)->priv->playback,
-                    "render", G_CALLBACK (on_playback_rendered),
+                    "position", G_CALLBACK (on_playback_position),
                     xsheet);
   g_signal_connect (ANIMATION_XSHEET (xsheet)->priv->playback,
                     "stop", G_CALLBACK (on_playback_stopped),
@@ -449,7 +449,7 @@ animation_xsheet_finalize (GObject *object)
   AnimationXSheet *xsheet = ANIMATION_XSHEET (object);
 
   g_signal_handlers_disconnect_by_func (ANIMATION_XSHEET (xsheet)->priv->playback,
-                                        G_CALLBACK (on_playback_rendered),
+                                        G_CALLBACK (on_playback_position),
                                         xsheet);
   g_signal_handlers_disconnect_by_func (ANIMATION_XSHEET (xsheet)->priv->playback,
                                         G_CALLBACK (on_playback_stopped),
@@ -1339,7 +1339,7 @@ on_playback_stopped (AnimationPlayback *playback,
 }
 
 static void
-on_playback_rendered (AnimationPlayback *playback,
+on_playback_position (AnimationPlayback *playback,
                       gint               frame_number,
                       GeglBuffer        *buffer,
                       gboolean           must_draw_null,


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