[gimp-gap] windows specific fixes (audio resample via sox, Story attr preview rendering) create storyboard from



commit 038683ca82e8883b2a48fc3b8f3932bb2e6960fd
Author: Wolfgang Hofer <wolfgangh svn gnome org>
Date:   Wed Jan 16 20:05:20 2013 +0100

    windows specific fixes (audio resample via sox, Story attr preview rendering) create storyboard from video extract dlg.

 ChangeLog                                |   60 ++++++++
 autogen.sh                               |    5 +-
 docs/reference/txt/gap_gimprc_params.txt |    7 +
 gap/gap_story_att_trans_dlg.c            |  144 ++++++++++----------
 gap/gap_story_dialog.c                   |  164 ++++++++++++++++++++--
 gap/gap_story_dialog.h                   |    2 +-
 gap/gap_story_main.c                     |  135 +++++++++++++++++--
 gap/gap_story_main.h                     |   34 +++++-
 gap/gap_story_render_audio.c             |   79 +++++++++---
 gap/gap_story_render_processor.c         |   20 +++-
 gap/gap_story_render_processor.h         |    2 +
 gap/gap_vex_dialog.c                     |  214 +++++++++++++----------------
 gap/gap_vex_dialog.h                     |    2 +-
 gap/gap_vex_exec.c                       |  221 ++++++++++++++++++++++++++----
 gap/gap_vex_exec.h                       |    2 +-
 gap/gap_vex_main.c                       |   10 +-
 gap/gap_vex_main.h                       |   39 ++++-
 vid_common/gap_cme_gui.c                 |    8 +-
 18 files changed, 871 insertions(+), 277 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index a79c45e..36ac2a0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,63 @@
+2013-01-16 Wolfgang Hofer <hof gimp org>
+
+- fixed bug in the storybard master properties that truncated framerate to integer values.
+
+- audio resample via external tool (sox) did not work in WINDOWS environment.
+  The old code was restricted to Unix only.
+  Fixed the parameter substitution and use g_spawn_sync for the external audio converter call
+  that now shall work on other operating systems than unix.
+  
+  tests on windows with sox as external converter were successful,
+  but only in case when the external converter was configured with
+  the full absolute path.
+  sox is available on Linux, Windows, and MacOSX
+  see http://sox.sourceforge.net/
+
+- Support audio rendering of an audiotrack that is an extracted audiotrack from a videofile.
+  I used this as workarond in case of unsupported audio codec.
+  The workaround allows extract the audio with another external tool (that supports the codec)
+  and then refere the external audiotrack in same way as internal audiotracks. 
+  (e.g. access it in the storyboard by frame numbers via AUD_PLAY_MOVIE)
+    
+    ==> manually edit the Storyboard and 
+          replace AUD_PLAY_MOVIE .... "my_video.mpg"
+          by      AUD_PLAY_MOVIE .... "my_video_extracted_audio.wav"
+
+- Added a new feature that creates a storyboard triggered by
+  the video extract plug-in.
+  The new output mode creates the stroryboard from the videofile,
+  adds the current selected range as initial clip,
+  and opens the created storyboard in the storyboard editor dialog.
+
+- new boolean gimprc parameter video-enable-storyboard-debug-features
+  enables the debug menu in the storyboard dialog
+  and preview image extraction by click on the preview image 
+  in the storyboard attributes dialog window.
+
+- fixed a bug in rendering the preview of clip type movie 
+  in the storyboard attributes dialog window.
+  (This bug did occure with gimp-2.6.11 running on Windows7
+   but did not occure with gimp-2.6.11 on Linux)
+
+- automake version check support for automake-1.12
+
+  * autogen.sh
+ 
+  * gap/gap_story_sox.c
+  * gap/gap_story_render_audio.c
+  * gap/gap_story_main.c [.h]
+  * gap/gap_story_dialog.c [.h]
+  * gap/gap_story_att_trans_dlg.c
+  * gap/gap_story_render_processor.c [.h]
+  * gap/gap_vex_dialog.c [.h]
+  * gap/gap_vex_exec.c [.h]
+  * gap/gap_vex_main.c [.h]
+  
+  * docs/reference/txt/gap_gimprc_params.txt
+  
+  * vid_common/gap_cme_gui.c   
+ 
+    
 2012-09-30 Wolfgang Hofer <hof gimp org>
 
 - fixed german menuname translations. Translated message must keep the prefix "<Image>"
diff --git a/autogen.sh b/autogen.sh
index b53db5d..2a9097e 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -88,7 +88,10 @@ fi
 
 
 echo -n "checking for automake >= $AUTOMAKE_REQUIRED_VERSION ... "
-if (automake-1.11 --version) < /dev/null > /dev/null 2>&1; then
+if (automake-1.12 --version) < /dev/null > /dev/null 2>&1; then
+   AUTOMAKE=automake-1.12
+   ACLOCAL=aclocal-1.12
+elif (automake-1.11 --version) < /dev/null > /dev/null 2>&1; then
    AUTOMAKE=automake-1.11
    ACLOCAL=aclocal-1.11
 elif (automake-1.10 --version) < /dev/null > /dev/null 2>&1; then
diff --git a/docs/reference/txt/gap_gimprc_params.txt b/docs/reference/txt/gap_gimprc_params.txt
index 41d0e62..b4e73ff 100644
--- a/docs/reference/txt/gap_gimprc_params.txt
+++ b/docs/reference/txt/gap_gimprc_params.txt
@@ -386,3 +386,10 @@ If you edit gimprc files by hand, you must do this before you startup GIMP.
 # rotate transformations on very small angles.
 # default is 0.0125 degree
 (video-move-path-rotate-threshold "0.0125")
+
+
+# enables the debug menu in the storyboard dialog
+# and preview image extraction by click on the preview image 
+# in the storyboard attributes dialog window.
+# default is no
+(video-enable-storyboard-debug-features "no")
diff --git a/gap/gap_story_att_trans_dlg.c b/gap/gap_story_att_trans_dlg.c
old mode 100755
new mode 100644
index 3816484..7e8cd9c
--- a/gap/gap_story_att_trans_dlg.c
+++ b/gap/gap_story_att_trans_dlg.c
@@ -39,6 +39,7 @@
 #include <libgimp/gimp.h>
 #include <libgimp/gimpui.h>
 
+#include "gap_base.h"
 #include "gap_story_main.h"
 #include "gap_story_undo.h"
 #include "gap_story_dialog.h"
@@ -166,7 +167,7 @@ static void     p_create_transformed_layer(gint32 image_id
                     , gint32 stackposition
                     , const char *layername
                     , GapStbAttrWidget *attw
-		    , gint img_idx
+                    , gint img_idx
                     , gboolean enableMovepath
                     );
 static gboolean p_calculate_prefetch_visibility(GapStbAttrWidget *attw, gint img_idx);
@@ -331,14 +332,14 @@ p_attw_prop_response(GtkWidget *widget
           /* force close in case file selection dialog is still open */
           p_attw_movepath_filesel_pw_close_cb(attw->movepath_filesel, attw);
         }
-        
+
         if(attw->movepath_edit_dialog != NULL)
         {
           /* force close of the movepath edit dialog that is still open */
           gtk_widget_destroy(attw->movepath_edit_dialog);
           attw->movepath_edit_dialog = NULL;
         }
-      
+
         p_delete_gfx_images(attw);
         if(attw->go_timertag >= 0)
         {
@@ -436,10 +437,10 @@ p_attw_prop_reset_all(GapStbAttrWidget *attw)
 
         gtk_adjustment_set_value(GTK_ADJUSTMENT(attw->att_rows[ii].spinbutton_from_adj)
                                 , attw->stb_elem_refptr->att_arr_value_from[ii] *
-				p_getConvertFactor(ii));
+                                p_getConvertFactor(ii));
         gtk_adjustment_set_value(GTK_ADJUSTMENT(attw->att_rows[ii].spinbutton_to_adj)
                                 , attw->stb_elem_refptr->att_arr_value_to[ii] *
-				p_getConvertFactor(ii));
+                                p_getConvertFactor(ii));
         gtk_adjustment_set_value(GTK_ADJUSTMENT(attw->att_rows[ii].spinbutton_dur_adj)
                                 , attw->stb_elem_refptr->att_arr_value_dur[ii]);
 
@@ -604,7 +605,7 @@ p_attw_update_sensitivity(GapStbAttrWidget *attw)
   sensitive = ((attw->stb_elem_refptr->att_fit_width == TRUE)
             || (attw->stb_elem_refptr->att_fit_height == TRUE));
   gtk_widget_set_sensitive(attw->keep_proportions_toggle, sensitive);
-  
+
   sensitive = FALSE;
   if(attw->stb_elem_refptr->att_movepath_file_xml != NULL)
   {
@@ -956,7 +957,7 @@ p_attw_accel_adjustment_callback(GtkObject *obj, gint32 *val)
       {
         p_attw_push_undo_and_set_unsaved_changes(attw);
         *val = l_val;
-        
+
       }
     }
   }
@@ -1039,6 +1040,8 @@ p_attw_preview_events_cb (GtkWidget *widget
   GdkEventButton *bevent;
   GapStbMainGlobalParams  *sgpp;
   gint                     img_idx;
+  gboolean                 enableStoryboardDebugFeatures;
+
 
   if ((attw->stb_elem_refptr == NULL)
   ||  (attw->stb_refptr == NULL))
@@ -1063,7 +1066,9 @@ p_attw_preview_events_cb (GtkWidget *widget
       // TODO: define actions when button pressed.
 
       /* debug code to display a copy of the image */
-      if(1==0)
+      enableStoryboardDebugFeatures =
+          gap_base_get_gimprc_gboolean_value(GAP_GIMPRC_ENABLE_STORYBOARD_DEBUG_FEATURES, FALSE);
+      if(enableStoryboardDebugFeatures)
       {
         p_debug_dup_image(attw->gfx_tab[img_idx].image_id);
       }
@@ -1519,14 +1524,14 @@ p_is_width_or_height_fixed(gboolean fit_width, gboolean fit_height, gboolean kee
   {
     return (TRUE);
   }
-  
+
   if ((fit_width != fit_height) && (keep_proportions == FALSE))
   {
     return (TRUE);
   }
-  
+
   return (FALSE);
-  
+
 }  /* end p_is_width_or_height_fixed */
 
 
@@ -1558,7 +1563,7 @@ p_create_transformed_layer_movepath(gint32 image_id
   gint32   mov_obj_layer_id;
   gdouble  att_tab[GAP_STB_ATT_GFX_ARRAY_MAX][GAP_STB_ATT_TYPES_ARRAY_MAX];
   gint     ii;
-  
+
   if(attw == NULL)
   {
     printf("** INTERNAL ERROR p_create_transformed_layer_movepath called with attw is NULL\n");
@@ -1569,12 +1574,12 @@ p_create_transformed_layer_movepath(gint32 image_id
     printf("** INTERNAL ERROR p_create_transformed_layer_movepath called with stb_refptr is NULL\n");
     return (FALSE);
   }
-  
+
   if(attw->movepath_file_xml_is_valid != TRUE)
   {
     return (FALSE);
   }
-  
+
   master_width = attw->stb_refptr->master_width;
   master_height = attw->stb_refptr->master_height;
   keep_proportions = attw->stb_elem_refptr->att_keep_proportions;
@@ -1604,7 +1609,7 @@ p_create_transformed_layer_movepath(gint32 image_id
     return (FALSE);
   }
 
-  
+
   /* recreate the current layer at stackposition 2 */
 
   /* create image with 1:1 copy of the origsize_layer_id */
@@ -1627,7 +1632,7 @@ p_create_transformed_layer_movepath(gint32 image_id
     gimp_image_add_layer(mov_obj_image_id, mov_obj_layer_id, 0);
     gimp_layer_set_offsets(mov_obj_layer_id, 0, 0);
   }
- 
+
   //if(img_idx == 0)
   //{
   //  p_debug_dup_image(mov_obj_image_id);
@@ -1641,7 +1646,7 @@ p_create_transformed_layer_movepath(gint32 image_id
   {
     gint scaled_width;
     gint scaled_height;
-    
+
     scaled_width = gimp_image_width(mov_obj_image_id) * gimp_image_width(image_id) / master_width;
     scaled_height = gimp_image_height(mov_obj_image_id) * gimp_image_height(image_id) / master_height;
     gimp_image_scale(mov_obj_image_id, scaled_width, scaled_height);
@@ -1649,7 +1654,7 @@ p_create_transformed_layer_movepath(gint32 image_id
 
   /* call storyboard processor that does movepath and other transformations
    * (note that processing is done at size of the preview image that is 2 times larger
-   * than the wanted result because 
+   * than the wanted result because
    */
   new_layer_id = gap_story_render_transform_with_movepath_processing(image_id
                               , mov_obj_image_id
@@ -1711,7 +1716,7 @@ p_create_transformed_layer_movepath(gint32 image_id
  * -----------------------------------------
  * create transformed copy of the specified origsize_layer_id,
  * according to calculated transformation settings.
- * 
+ *
  */
 static void
 p_create_transformed_layer(gint32 image_id
@@ -1739,8 +1744,8 @@ p_create_transformed_layer(gint32 image_id
       }
     }
   }
-  
-  /* if size is not equal calculated size 
+
+  /* if size is not equal calculated size
    * or movepath rendering necessary then remove curr layer
    * to force recreation in desired size
    */
@@ -1764,7 +1769,7 @@ p_create_transformed_layer(gint32 image_id
     if(movepath_file_xml != NULL)
     {
       gboolean movepathOk;
-      
+
       movepathOk = p_create_transformed_layer_movepath(image_id
                  , origsize_layer_id
                  , layer_id_ptr
@@ -1784,7 +1789,7 @@ p_create_transformed_layer(gint32 image_id
     new_layer_id = gimp_layer_copy(origsize_layer_id);
     gimp_image_add_layer (image_id, new_layer_id, stackposition);
     gimp_drawable_set_name(new_layer_id, layername);
-    
+
     gimp_layer_scale(new_layer_id, calculated->width, calculated->height, 0);
 
 
@@ -2191,7 +2196,7 @@ p_orig_layer_frame_fetcher(GapStbAttrWidget *attw
                              ,stb_ret
                              ,l_filename
                              );
-                             
+
          if(is_up_to_date)
          {
            g_free(stb_ret);
@@ -2199,7 +2204,7 @@ p_orig_layer_frame_fetcher(GapStbAttrWidget *attw
            {
              g_free(l_filename);
            }
-        
+
            return;  /* orig_layer is still up to date, done */
          }
 
@@ -2246,9 +2251,9 @@ p_orig_layer_frame_fetcher(GapStbAttrWidget *attw
                                    , stb_ret->stb_elem->color_red
                                    , stb_ret->stb_elem->color_green
                                    , stb_ret->stb_elem->color_blue
-                                   , stb_ret->stb_elem->color_alpha 
+                                   , stb_ret->stb_elem->color_alpha
                                    );
-         
+
            linfo->layer_record_type = stb_ret->stb_elem->record_type;
            linfo->layer_local_framenr = 0;
            linfo->layer_seltrack = 1;
@@ -2547,14 +2552,16 @@ p_fetch_video_frame_as_layer(GapStbMainGlobalParams *sgpp
                           , img_width
                           , img_height);
 
+
+    gimp_drawable_flush (drawable);
+    gimp_drawable_detach(drawable);
+
     if(! gimp_drawable_has_alpha (l_new_layer_id))
     {
       /* implicitly add an alpha channel before we try to raise */
       gimp_layer_add_alpha(l_new_layer_id);
     }
 
-    gimp_drawable_flush (drawable);
-    gimp_drawable_detach(drawable);
     gimp_image_add_layer (image_id,l_new_layer_id, LAYERSTACK_TOP);
   }
 
@@ -2593,7 +2600,7 @@ p_fetch_imagefile_as_layer (const char *img_filename
 
     gimp_image_undo_disable (l_tmp_image_id);
     l_layer_id = gap_image_merge_visible_layers(l_tmp_image_id, GIMP_CLIP_TO_IMAGE);
-    
+
     if(!gimp_drawable_has_alpha(l_layer_id))
     {
       gimp_layer_add_alpha(l_layer_id);
@@ -2616,14 +2623,14 @@ p_fetch_imagefile_as_layer (const char *img_filename
   }
 
   return(l_new_layer_id);
-  
+
 }  /* end p_fetch_imagefile_as_layer */
 
 
 /* ---------------------------------
  * p_fetch_layer_from_animimage
  * ---------------------------------
- * pick layer at specified localframe_index (e.g. layerstack_position) from specified 
+ * pick layer at specified localframe_index (e.g. layerstack_position) from specified
  * multilayer animimage on disk (specified via filename)
  * and add a copy of this layer as new layer on top of layerstack in the specified image_id.
  */
@@ -2661,7 +2668,7 @@ p_fetch_layer_from_animimage (const char *img_filename
     gint32       *l_layers_list;
 
     gimp_image_undo_disable (l_tmp_image_id);
-    
+
     l_layers_list = gimp_image_get_layers(l_tmp_image_id, &l_nlayers);
 
     if(gap_debug)
@@ -2688,7 +2695,7 @@ p_fetch_layer_from_animimage (const char *img_filename
             gimp_layer_remove_mask(l_layers_list[localframe_index], GIMP_MASK_APPLY);
           }
           gimp_layer_resize_to_image_size(l_layers_list[localframe_index]);
-          
+
           /* copy the picked layer from the temp image to the preview multilayer image */
           l_new_layer_id = gap_layer_copy_to_dest_image(image_id,
                                    l_layers_list[localframe_index],
@@ -2699,11 +2706,11 @@ p_fetch_layer_from_animimage (const char *img_filename
                                    );
 
           gimp_image_add_layer (image_id, l_new_layer_id, LAYERSTACK_TOP);
-          
+
        }
        g_free (l_layers_list);
     }
-    
+
     /* destroy the tmp image */
     gimp_image_delete(l_tmp_image_id);
   }
@@ -2834,7 +2841,7 @@ p_create_movepath_edit_resources(GapStbAttrWidget *attw)
   gint32   image_id;
   gint32   bg_layer_id;
   gint32   origsize_layer_id;
-  
+
   /* create the frame image */
   image_id = gimp_image_new(attw->stb_refptr->master_width
                            ,attw->stb_refptr->master_height
@@ -2842,8 +2849,8 @@ p_create_movepath_edit_resources(GapStbAttrWidget *attw)
                            );
   attw->movepath_frame_image_id = image_id;
   gimp_image_undo_disable (image_id);
- 
-  /* add a transparent layer */ 
+
+  /* add a transparent layer */
   bg_layer_id = gimp_layer_new(image_id
                   , "background"
                   , gimp_image_width(image_id)
@@ -2858,9 +2865,9 @@ p_create_movepath_edit_resources(GapStbAttrWidget *attw)
 
   // TODO: in case the storyboard has more tracks
   // the frame image should be rendered by the storyboard processor at master size
-  // based on a modified storyboard that contains only tracks that render behind the current track 
+  // based on a modified storyboard that contains only tracks that render behind the current track
+
 
-  
   /* create an image that holds the moving object layer */
   origsize_layer_id = attw->gfx_tab[0].orig_layer_id;
   attw->movepath_obj_image_id = gimp_image_new( gimp_drawable_width(origsize_layer_id)
@@ -2873,14 +2880,14 @@ p_create_movepath_edit_resources(GapStbAttrWidget *attw)
   gimp_drawable_set_visible(attw->movepath_obj_layer_id, TRUE);
 
 
-  /* create default values for movepath 
+  /* create default values for movepath
    * (will be overwritten in case xml_paramfile contains already valid settings)
    */
   attw->pvals = gap_mov_exec_new_GapMovValues();
   attw->pvals->dst_image_id = attw->movepath_frame_image_id;
 
   attw->ainfo_ptr = gap_lib_alloc_ainfo_unsaved_image(attw->movepath_frame_image_id);
-  
+
 }  /* end p_create_movepath_edit_resources */
 
 
@@ -2893,9 +2900,9 @@ static void
 p_edit_movepath_closed_callback(gpointer ptr)
 {
   GapStbAttrWidget *attw;
-  
+
   attw = (GapStbAttrWidget *)ptr;
-  
+
   if(attw != NULL)
   {
     if(gap_debug)
@@ -2903,22 +2910,22 @@ p_edit_movepath_closed_callback(gpointer ptr)
       printf("p_edit_movepath_closed_callback frame_image_id:%d obj_image_id:%d\n"
         ,(int)attw->movepath_frame_image_id
         ,(int)attw->movepath_obj_image_id
-	);
+        );
     }
     attw->movepath_edit_dialog = NULL;
-    
+
     if(attw->pvals != NULL)
     {
       g_free(attw->pvals);
       attw->pvals = NULL;
     }
-    
+
     if(attw->ainfo_ptr != NULL)
     {
       gap_lib_free_ainfo(&attw->ainfo_ptr);
       attw->ainfo_ptr = NULL;
     }
-    
+
     if(attw->movepath_frame_image_id >= 0)
     {
       gimp_image_delete(attw->movepath_frame_image_id);
@@ -2932,12 +2939,12 @@ p_edit_movepath_closed_callback(gpointer ptr)
     }
     p_attw_movepath_file_validity_check(attw);
     p_update_full_preview_gfx(attw);
-    
-    /* make attributes dialog sensitive again (after movepath edit dialog was closed) */ 
+
+    /* make attributes dialog sensitive again (after movepath edit dialog was closed) */
     gtk_widget_set_sensitive(attw->attw_prop_dialog, TRUE);
 
   }
-  
+
 }  /* end p_edit_movepath_closed_callback */
 
 
@@ -2954,7 +2961,7 @@ p_attw_movepath_edit_button_cb ( GtkWidget *w
                        , GapStbAttrWidget *attw)
 {
   gint32 nframes;
-  
+
   if(attw->attw_prop_dialog == NULL)
   {
      return;
@@ -2993,9 +3000,9 @@ p_attw_movepath_edit_button_cb ( GtkWidget *w
       printf("p_attw_movepath_edit_button_cb frame_image_id:%d obj_image_id:%d obj_layer_id:%d attw:%d\n"
         ,(int)attw->movepath_frame_image_id
         ,(int)attw->movepath_obj_image_id
-	,(int)attw->movepath_obj_layer_id
-	,(int)attw
-	);
+        ,(int)attw->movepath_obj_layer_id
+        ,(int)attw
+        );
   }
 
 
@@ -3028,7 +3035,7 @@ p_attw_movepath_file_validity_check(GapStbAttrWidget *attw)
 {
   if(attw == NULL) { return; }
   attw->movepath_file_xml_is_valid = FALSE;
-  
+
   if(attw->stb_elem_refptr == NULL) { return; }
 
 
@@ -3456,10 +3463,10 @@ p_create_and_attach_att_arr_widgets(const char *row_title
 
     accelerationCharacteristic = *att_arr_value_accel_ptr;
     accel_wgt = gap_accel_new(ACC_WGT_WIDTH, ACC_WGT_HEIGHT, accelerationCharacteristic);
-    
+
     /* the Acceleration characteristic value spinbutton */
     adj = accel_wgt->adj;
-    
+
     spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0);
     attw->att_rows[att_type_idx].spinbutton_accel_adj = adj;
     attw->att_rows[att_type_idx].spinbutton_accel = spinbutton;
@@ -3472,17 +3479,17 @@ p_create_and_attach_att_arr_widgets(const char *row_title
     gimp_help_set_help_data (spinbutton, accel_tooltip, NULL);
 
     g_object_set_data(G_OBJECT(adj), OBJ_DATA_KEY_ATTW, attw);
-    
+
     gtk_table_attach( GTK_TABLE(table), accel_wgt->da_widget, col, col+1, row, row+1,
                         GTK_FILL, 0, 4, 0 );
     gtk_widget_show (accel_wgt->da_widget);
-    
-    
-    
+
+
+
     g_signal_connect (G_OBJECT (adj), "value_changed",
                       G_CALLBACK (p_attw_accel_adjustment_callback),
                       att_arr_value_accel_ptr);
- 
+
   }
 
 
@@ -3955,7 +3962,7 @@ gap_story_attw_properties_dialog (GapStbAttrWidget *attw)
                      attw);
     gtk_widget_show (entry);
     attw->movepath_file_entry = entry;
-    
+
     /* the filesel invoker button */
     button = gtk_button_new_with_label ("...");
     gtk_table_attach_defaults (GTK_TABLE(table), button, 8, 10, row, row+1);
@@ -3964,7 +3971,7 @@ gap_story_attw_properties_dialog (GapStbAttrWidget *attw)
                      attw);
     gtk_widget_show (button);
 
-    
+
     /* the movepath record/edit dialog invoker button */
     button = gtk_button_new_with_label ("edit");
     attw->movepath_edit_button = button;
@@ -3973,7 +3980,7 @@ gap_story_attw_properties_dialog (GapStbAttrWidget *attw)
                      G_CALLBACK(p_attw_movepath_edit_button_cb),
                      attw);
     gtk_widget_show (button);
-    
+
   }
 
   row++;
@@ -4129,6 +4136,3 @@ gap_story_att_fw_properties_dialog (GapStbFrameWidget *fw)
     gap_story_att_stb_elem_properties_dialog(tabw, fw->stb_elem_refptr, fw->stb_refptr);
   }
 }  /* end gap_story_att_fw_properties_dialog */
-
-
-
diff --git a/gap/gap_story_dialog.c b/gap/gap_story_dialog.c
index 7e68e0c..b4a821e 100644
--- a/gap/gap_story_dialog.c
+++ b/gap/gap_story_dialog.c
@@ -426,6 +426,11 @@ static void    p_get_gimprc_render_settings(GapStbMainGlobalParams *sgpp);
 
 
 static void    p_reset_progress_bars(GapStbMainGlobalParams *sgpp);
+static void    p_storyboard_init_from_creation_params( GapStbTabWidgets *tabw
+                   , GapStbMainGlobalParams *sgpp
+                   , GapStoryBoard *stb
+                   , GapStbCreationParams  *scrp
+                   );
 static void    p_call_external_image_viewer(GapStbFrameWidget *fw);
 
 
@@ -452,11 +457,15 @@ static gboolean
 p_is_debug_menu_enabled(void)
 {
   gboolean enable;
+  gboolean enableStoryboardDebugFeatures;
   char *filename;
 
   enable = FALSE;
+  enableStoryboardDebugFeatures =
+          gap_base_get_gimprc_gboolean_value(GAP_GIMPRC_ENABLE_STORYBOARD_DEBUG_FEATURES, FALSE);
 
   if((gap_debug)
+  || (enableStoryboardDebugFeatures)
   || (g_file_test(GAP_DEBUG_STORYBOARD_CONFIG_FILE, G_FILE_TEST_EXISTS)))
   {
     return(TRUE);
@@ -1817,10 +1826,10 @@ p_story_call_player(GapStbMainGlobalParams *sgpp
       return;  /* in case of errors: NO playback possible */
       sgpp->in_player_call = FALSE;
     }
-    
+
     if(sgpp->stb_preview_render_full_size != TRUE)
     {
-      /* if the storboard duplicate (stb_dup) includes at least one unscalable clip 
+      /* if the storboard duplicate (stb_dup) includes at least one unscalable clip
        * (where either with or height is fixed to original size)
        * then we must force slow internal rendering at full size.
        */
@@ -1853,12 +1862,12 @@ p_story_call_player(GapStbMainGlobalParams *sgpp
           previewWidth = 320;
           previewHeight = previewWidth * (stb_dup->master_height / MAX(stb_dup->master_width,1));
         }
-      
+
         stb_dup->master_width = MIN(stb_dup->master_width, previewWidth);
         stb_dup->master_height = MIN(stb_dup->master_height, previewHeight);
       }
     }
-    
+
   }
 
   if(sgpp->plp)
@@ -5424,7 +5433,7 @@ p_menu_win_render_properties_cb (GtkWidget *widget, GapStbMainGlobalParams *sgpp
 {
   static GapArrArg  argv[8];
   gint l_ii;
-  
+
   gint l_stb_max_open_videofile_idx;
   gint l_stb_fcache_size_per_videofile_idx;
   gint l_ffetch_max_img_cache_elements_idx;
@@ -5432,7 +5441,7 @@ p_menu_win_render_properties_cb (GtkWidget *widget, GapStbMainGlobalParams *sgpp
   gint l_stb_preview_render_full_size_idx;
   gint l_stb_isMultithreadEnabled_idx;
   gint l_stb_isMultithreadFfEncoderEnabled_idx;
-  
+
   gint multithreadDefaultFlag;
   gboolean l_rc;
 
@@ -5532,7 +5541,7 @@ p_menu_win_render_properties_cb (GtkWidget *widget, GapStbMainGlobalParams *sgpp
   argv[l_ii].constraint = TRUE;
   argv[l_ii].label_txt = _("Multiprocessor Storyboard Support:");
   argv[l_ii].help_txt  = _("ON: Rendering of composite storyboard frames uses more than one processor. "
-                           "(reading frames from videoclips is done by parallel running prefetch processing) " 
+                           "(reading frames from videoclips is done by parallel running prefetch processing) "
                            "OFF: Rendering of composite frames uses only one processor.");
   argv[l_ii].int_ret   = (gint)sgpp->stb_isMultithreadEnabled;
   argv[l_ii].has_default = TRUE;
@@ -5544,7 +5553,7 @@ p_menu_win_render_properties_cb (GtkWidget *widget, GapStbMainGlobalParams *sgpp
   argv[l_ii].constraint = TRUE;
   argv[l_ii].label_txt = _("Multiprocessor Encoder Support:");
   argv[l_ii].help_txt  = _("ON: Video encoders shall use more than one processor where implemented. "
-                           "The ffmpeg based video encoder implementation supports parallel processing. " 
+                           "The ffmpeg based video encoder implementation supports parallel processing. "
                            "OFF: Video encoders use only one processor.");
   argv[l_ii].int_ret   = (gint)gap_base_get_gimprc_gboolean_value(
                               GAP_GIMPRC_VIDEO_ENCODER_FFMPEG_MULTIPROCESSOR_ENABLE
@@ -5568,7 +5577,7 @@ p_menu_win_render_properties_cb (GtkWidget *widget, GapStbMainGlobalParams *sgpp
   if(l_rc == TRUE)
   {
     gboolean isFFMpegEncoderMultiprocessorSupport;
-    
+
     sgpp->stb_max_open_videofile         = argv[l_stb_max_open_videofile_idx].int_ret;
     sgpp->stb_fcache_size_per_videofile  = argv[l_stb_fcache_size_per_videofile_idx].int_ret;
     sgpp->ffetch_max_img_cache_elements  = argv[l_ffetch_max_img_cache_elements_idx].int_ret;
@@ -5581,7 +5590,7 @@ p_menu_win_render_properties_cb (GtkWidget *widget, GapStbMainGlobalParams *sgpp
     p_save_gimprc_gboolean_value(GAP_GIMPRC_VIDEO_ENCODER_FFMPEG_MULTIPROCESSOR_ENABLE
                               , isFFMpegEncoderMultiprocessorSupport
                               );
-    
+
   }
 }  /* end p_menu_win_render_properties_cb  */
 
@@ -8430,6 +8439,129 @@ p_reset_progress_bars(GapStbMainGlobalParams *sgpp)
 }  /* end p_reset_progress_bars */
 
 
+/* --------------------------------------
+ * p_storyboard_init_from_creation_params
+ * --------------------------------------
+ * creates an inital storyboard that includes one inital clip
+ * from the specified GapStbCreationParams.
+ */
+static void
+p_storyboard_init_from_creation_params(
+     GapStbTabWidgets *tabw
+   , GapStbMainGlobalParams *sgpp
+   , GapStoryBoard *stb
+   , GapStbCreationParams  *scrp
+   )
+{
+    GapStoryRecordType record_type;
+
+    stb->master_width = scrp->vid_width;
+    stb->master_height = scrp->vid_height;
+    stb->master_framerate = scrp->framerate;
+
+    stb->master_volume = 1.0;
+    stb->master_samplerate = scrp->samplerate;
+
+    stb->master_aspect_ratio = scrp->aspect_ratio;  /* 0.0 for none */
+    stb->master_aspect_width = scrp->aspect_width;
+    stb->master_aspect_height = scrp->aspect_height;
+
+    stb->stb_section = NULL;
+    stb->storyboardfile = NULL;
+    if(scrp->storyboard_filename[0] != '\0')
+    {
+      stb->storyboardfile = g_strdup(scrp->storyboard_filename);
+    }
+
+    if (scrp->preferred_decoder[0] != '\0')
+    {
+      stb->preferred_decoder = g_strdup(scrp->preferred_decoder);
+    }
+
+     /* refresh storyboard layout and thumbnail list widgets */
+     p_recreate_tab_widgets( stb
+                            ,tabw
+                            ,tabw->mount_col
+                            ,tabw->mount_row
+                            ,sgpp
+                            );
+     p_render_all_frame_widgets(tabw);
+     p_widget_sensibility(sgpp);
+
+     /* creation of one inital clip */
+
+     switch (scrp->record_type_int)
+     {
+       case 0:
+         record_type = GAP_STBREC_VID_MOVIE;
+         break;
+       case 1:
+         record_type = GAP_STBREC_VID_IMAGE;
+         break;
+       case 2:
+         record_type = GAP_STBREC_VID_FRAMES;
+         break;
+       case 3:
+         record_type = GAP_STBREC_VID_ANIMIMAGE;
+         break;
+       default:
+         record_type = GAP_STBREC_VID_UNKNOWN;
+         break;
+     }
+
+     if (record_type != GAP_STBREC_VID_UNKNOWN)
+     {
+       GapStoryElem      *stb_elem;
+
+       stb_elem = gap_story_new_elem(record_type);
+       if(stb_elem)
+       {
+         stb_elem->orig_filename = g_strdup(scrp->filename);
+         stb_elem->track = tabw->vtrack;
+         stb_elem->from_frame = scrp->from_frame;
+         stb_elem->to_frame = scrp->to_frame;
+         stb_elem->nloop = scrp->nloop;
+         stb_elem->nframes = (1 + abs(scrp->to_frame - scrp->from_frame) ) * scrp->nloop;
+
+         stb_elem->seltrack     = scrp->vidtrack;
+         stb_elem->exact_seek   = scrp->exact_seek;
+         stb_elem->delace       = 0.0;
+         if (scrp->delace_mode != 0)
+         {
+           stb_elem->delace = scrp->delace_mode + CLAMP(scrp->delace_threshold, 0.0, 0.999999);
+         }
+
+         if (scrp->preferred_decoder[0] != '\0')
+         {
+           stb_elem->preferred_decoder = g_strdup(scrp->preferred_decoder);
+         }
+
+
+
+         gap_stb_undo_group_begin(tabw);
+         gap_stb_undo_push(tabw, GAP_STB_FEATURE_CREATE_CLIP);
+
+         gap_story_list_append_elem(stb, stb_elem);
+
+         /* refresh storyboard layout and thumbnail list widgets */
+         p_recreate_tab_widgets( stb
+                                 ,tabw
+                                 ,tabw->mount_col
+                                 ,tabw->mount_row
+                                 ,sgpp
+                                 );
+         p_render_all_frame_widgets(tabw);
+         // gap_story_stb_elem_properties_dialog(tabw, stb_elem, stb);
+         gap_stb_undo_group_end(tabw);
+       }
+
+       p_tabw_update_frame_label_and_rowpage_limits(tabw, sgpp);
+
+     }
+
+
+}  /* end p_storyboard_new_from_creation_params */
+
 
 
 /* -----------------------------
@@ -8437,7 +8569,7 @@ p_reset_progress_bars(GapStbMainGlobalParams *sgpp)
  * -----------------------------
  */
 void
-gap_storyboard_dialog(GapStbMainGlobalParams *sgpp)
+gap_storyboard_dialog(GapStbMainGlobalParams *sgpp, GapStbCreationParams  *scrp)
 {
   GtkWidget *dialog;
   GtkWidget  *vbox;
@@ -8784,6 +8916,14 @@ gap_storyboard_dialog(GapStbMainGlobalParams *sgpp)
      */
     ffetch_user_id = gap_frame_fetch_register_user("gap_storyboard_dialog");
 
+    if (scrp != NULL)
+    {
+      /* create an initial cliplist according to creation parameters */
+      sgpp->cll = gap_story_new_story_board(NULL);
+      sgpp->cll->master_type = GAP_STB_MASTER_TYPE_CLIPLIST;
+      p_storyboard_init_from_creation_params(sgpp->cll_widgets, sgpp, sgpp->cll, scrp);
+    }
+
     gtk_main ();
     gdk_flush ();
 
@@ -9338,7 +9478,7 @@ p_tabw_master_prop_dialog(GapStbTabWidgets *tabw, gboolean new_flag)
 
      stb_dst->master_width = (gint32)(argv[l_ii_width].int_ret);
      stb_dst->master_height = (gint32)(argv[l_ii_height].int_ret);
-     stb_dst->master_framerate = (gint32)(argv[l_ii_framerate].flt_ret);
+     stb_dst->master_framerate = (gdouble)(argv[l_ii_framerate].flt_ret);
      stb_dst->master_vtrack1_is_toplayer = (argv[l_ii_vtrack1_is_toplayer].int_ret != 0);
 
      p_parse_aspect_width_and_height(buf_aspect_string
diff --git a/gap/gap_story_dialog.h b/gap/gap_story_dialog.h
index da63ebb..61a6ca7 100644
--- a/gap/gap_story_dialog.h
+++ b/gap/gap_story_dialog.h
@@ -32,7 +32,7 @@
 #include "gap_story_main.h"
 #include "gap_story_properties.h"
 
-void    gap_storyboard_dialog(GapStbMainGlobalParams *gpp);
+void    gap_storyboard_dialog(GapStbMainGlobalParams *sgpp, GapStbCreationParams  *scrp);
 
 void    gap_story_dlg_attw_render_all(GapStbAttrWidget *attw);
 
diff --git a/gap/gap_story_main.c b/gap/gap_story_main.c
index 2fd123a..2ab5a2b 100644
--- a/gap/gap_story_main.c
+++ b/gap/gap_story_main.c
@@ -50,7 +50,7 @@ static char *plug_in_version_fmt =  "%d.%d.%d; 2004/01/26";
 #define PLUG_IN_COPYRIGHT   "Wolfgang Hofer"
 
 
-int gap_debug = 0;  /* 1 == print debug infos , 0 dont print debug infos */ 
+int gap_debug = 0;  /* 1 == print debug infos , 0 dont print debug infos */
 
 static GapStbMainGlobalParams global_params =
 {
@@ -151,6 +151,31 @@ static GimpParamDef in_args[] = {
                   { GIMP_PDB_DRAWABLE, "drawable", "UNUSED"},
   };
 
+
+static GimpParamDef in_create_args[] = {
+                  { GIMP_PDB_INT32,  "run_mode", "Interactive, non-interactive"},
+                  { GIMP_PDB_IMAGE,  "image", "Input image" },
+                  { GIMP_PDB_STRING, "storyboard_filename", "name of the storyboard file (to be created)"},
+                  { GIMP_PDB_STRING, "filename", "name of the video or image file (to be added as initial clip)"},
+                  { GIMP_PDB_STRING, "preferred_decoder", "NULL, or one of: libmpeg3, quicktime4linux, libavformat"},
+                  { GIMP_PDB_INT32,  "vid_width",  "storyboard master width in pixels"},
+                  { GIMP_PDB_INT32,  "vid_height", "storyboard master height in pixels"},
+                  { GIMP_PDB_FLOAT,  "framerate", "storyboard master frame rate in frames per second"},
+                  { GIMP_PDB_FLOAT,  "aspect_ratio", "aspect ratio (0.0 for undefined)"},
+                  { GIMP_PDB_INT32,  "aspect_width", "aspect width (optional 16 for 16:9)"},
+                  { GIMP_PDB_INT32,  "aspect_height", "aspect height (optional 9 for 16:9)"},
+                  { GIMP_PDB_FLOAT,  "samplerate", "audio samplerate in Hz"},
+                  { GIMP_PDB_INT32,  "record_type_int", "0: video, 1:image, 2:frame images, 3:anim image"},
+                  { GIMP_PDB_INT32,  "from_frame",  "frame number for start of clip range"},
+                  { GIMP_PDB_INT32,  "to_frame",  "frame number for end of clip range"},
+                  { GIMP_PDB_INT32,  "vidtrack",  "selected video track (first valid track number is 1)"},
+                  { GIMP_PDB_INT32,  "delace_mode", "0:no deinterlacing, 1: odd rows 2: even rows 3: odd first 4: even first"},
+                  { GIMP_PDB_FLOAT,  "delace_threshold", "deinterlace threshold"},
+                  { GIMP_PDB_INT32,  "exact_seek",  "0: NO (enable faster seek ops if available), 1: YES use only sequential read ops, will find exact framenumbers"},
+                  { GIMP_PDB_INT32,  "nloop",  "number of repetitions for this clip"},
+  };
+
+
 /* Functions */
 
 MAIN ()
@@ -165,7 +190,7 @@ static void query (void)
                                     ,GAP_MINOR_VERSION
                                     ,GAP_MICRO_VERSION
                                     );
-  
+
   gimp_plugin_domain_register (GETTEXT_PACKAGE, LOCALEDIR);
 
   /* the actual installation of the plugin */
@@ -185,10 +210,30 @@ static void query (void)
                           in_args,
                           NULL      /* out_args */
                           );
- 
+
   // gimp_plugin_menu_branch_register("<Image>", "Video");
   gimp_plugin_menu_register (GAP_STORY_PLUG_IN_PROC, N_("<Image>/Video/"));
-  
+
+
+  /* register additional create and edit plug in (API to be called from other plug-ins) */
+  gimp_install_procedure (GAP_STORY_PLUG_IN_PROC_CREATION,
+                          "Storyboard create and edit",
+                          "This plug-in is an interactive GUI to create and edit storyboard level1 files, "
+                          "This procedure is an API intended to be called from other plug-ins"
+                          "(see example call in the video extraction plug-in)",
+                          PLUG_IN_AUTHOR,
+                          PLUG_IN_COPYRIGHT,
+                          l_plug_in_version,
+                          NULL,                   /* do not appear in menu */
+                          PLUG_IN_IMAGE_TYPES,
+                          GIMP_PLUGIN,
+                          G_N_ELEMENTS (in_create_args),
+                          0,        /* G_N_ELEMENTS (out_args) */
+                          in_create_args,
+                          NULL      /* out_args */
+                          );
+
+
   g_free(l_plug_in_version);
 }  /* end query */
 
@@ -199,15 +244,19 @@ run (const gchar *name,          /* name of plugin */
      gint *nreturn_vals,         /* number of out-parameters */
      GimpParam ** return_vals)   /* out-parameters */
 {
+  GapStbCreationParams  creationParams;
+  GapStbCreationParams  *scrp;
   const gchar *l_env;
   gint32       image_id = -1;
   GapStbMainGlobalParams  *sgpp = &global_params;
 
+  scrp = NULL;
+
   /* Get the runmode from the in-parameters */
   GimpRunMode run_mode = param[0].data.d_int32;
 
   /* status variable, use it to check for errors in invocation usualy only
-   * during non-interactive calling 
+   * during non-interactive calling
    */
   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
 
@@ -236,6 +285,8 @@ run (const gchar *name,          /* name of plugin */
   image_id = param[1].data.d_int32;
 
 
+
+
   switch (run_mode)
   {
    case GIMP_RUN_INTERACTIVE:
@@ -244,14 +295,18 @@ run (const gchar *name,          /* name of plugin */
       break;
 
     case GIMP_RUN_NONINTERACTIVE:
-      /* check to see if invoked with the correct number of parameters */
-      /* if (nparams == G_N_ELEMENTS (in_args)) */
+      if (strcmp (name, GAP_STORY_PLUG_IN_PROC) == 0)
       {
         printf("%s: noninteractive call NOT supported.\n"
               , GAP_STORY_PLUG_IN_PROC
               );
         status = GIMP_PDB_CALLING_ERROR;
       }
+      /* Note that the API GAP_STORY_PLUG_IN_PROC_CREATION)
+       * is typically called from other plug-ins with runmode GIMP_RUN_NONINTERACTIVE
+       * (this also runs the interactive editor dialog but creates an initial storyboard
+       * from the parameters of the non-interactive call..)
+       */
       break;
 
     case GIMP_RUN_WITH_LAST_VALS:
@@ -264,17 +319,77 @@ run (const gchar *name,          /* name of plugin */
       break;
   }
 
+  /* check for the additional create+edit API */
+  if (strcmp (name, GAP_STORY_PLUG_IN_PROC_CREATION) == 0)
+  {
+    /* check to see if invoked with the correct number of parameters */
+    if (nparams == G_N_ELEMENTS (in_create_args))
+    {
+        gint ii;
+
+        scrp = &creationParams;
+        ii = 2;
+        if(param[ii].data.d_string != NULL)
+        {
+          strncpy(scrp->storyboard_filename, param[ii].data.d_string, GAP_STORY_MAX_STORYFILENAME_LEN -1);
+          scrp->storyboard_filename[GAP_STORY_MAX_STORYFILENAME_LEN -1] = '\0';
+        }
+        ii++;
+
+        if(param[ii].data.d_string != NULL)
+        {
+          strncpy(scrp->filename, param[ii].data.d_string, GAP_STORY_MAX_STORYFILENAME_LEN -1);
+          scrp->filename[GAP_STORY_MAX_STORYFILENAME_LEN -1] = '\0';
+        }
+        ii++;
+
+        if(param[ii].data.d_string != NULL)
+        {
+          strncpy(scrp->preferred_decoder, param[ii].data.d_string, GAP_STORY_MAX_STORYFILENAME_LEN -1);
+          scrp->preferred_decoder[GAP_STORY_MAX_STORYFILENAME_LEN -1] = '\0';
+        }
+        ii++;
+
+        scrp->vid_width           = param[ii++].data.d_int32;
+        scrp->vid_height          = param[ii++].data.d_int32;
+        scrp->framerate           = param[ii++].data.d_float;
+        scrp->aspect_ratio        = param[ii++].data.d_float;;
+        scrp->aspect_width        = param[ii++].data.d_int32;
+        scrp->aspect_height       = param[ii++].data.d_int32;
+        scrp->samplerate          = param[ii++].data.d_float;
+
+        /* Clip parameters */
+        scrp->record_type_int   = param[ii++].data.d_int32;
+        scrp->from_frame        = param[ii++].data.d_int32;
+        scrp->to_frame          = param[ii++].data.d_int32;
+        scrp->vidtrack          = param[ii++].data.d_int32;
+        scrp->delace_mode       = param[ii++].data.d_int32;
+        scrp->delace_threshold  = param[ii++].data.d_float;
+        scrp->exact_seek        = param[ii++].data.d_int32;
+        scrp->nloop             = param[ii++].data.d_int32;
+    }
+    else
+    {
+        printf("%s: wrong number of parameters got: %d but expected:%d.\n"
+              , name
+              , nparams
+              , G_N_ELEMENTS (in_create_args)
+              );
+        status = GIMP_PDB_CALLING_ERROR;
+    }
+  }
+
   if (status == GIMP_PDB_SUCCESS)
   {
-    
+
     sgpp->image_id = image_id;
     sgpp->initialized = FALSE;
     sgpp->run_mode = run_mode;
     sgpp->plp = NULL;
     sgpp->stb = NULL;
     sgpp->cll = NULL;
-    gap_storyboard_dialog(sgpp);
-  
+    gap_storyboard_dialog(sgpp, scrp);
+
     /* Store variable states for next run */
     if (run_mode == GIMP_RUN_INTERACTIVE)
       gimp_set_data (GAP_STORY_PLUG_IN_PROC, sgpp, sizeof (GapStbMainGlobalParams));
diff --git a/gap/gap_story_main.h b/gap/gap_story_main.h
old mode 100755
new mode 100644
index 056ec41..b25af4e
--- a/gap/gap_story_main.h
+++ b/gap/gap_story_main.h
@@ -40,6 +40,7 @@
 
 #define GAP_STORY_PLUG_IN_PROC            "plug_in_gap_storyboard_edit"
 #define GAP_STORYBOARD_EDIT_HELP_ID       "plug-in-gap-storyboard-edit"
+#define GAP_STORY_PLUG_IN_PROC_CREATION   "plug_in_gap_storyboard_create_and_edit"
 
 #define GAP_STORY_MAX_STORYFILENAME_LEN 2048
 #define GAP_STORY_MAX_CLIP_WIDGETS 2000
@@ -55,6 +56,7 @@ typedef gpointer t_GVA_Handle;
 #endif
 #endif
 
+#define GAP_GIMPRC_ENABLE_STORYBOARD_DEBUG_FEATURES "video-enable-storyboard-debug-features"
 
 
 #define GAP_STB_ATT_GFX_ARRAY_MAX 2
@@ -323,7 +325,7 @@ typedef struct GapStbAttrWidget  /* nickname: attw */
   GtkWidget  *button_overlap_dur;
 
   GtkWidget   *comment_entry;
-  
+
   GtkWidget   *movepath_edit_button;
   GtkWidget   *movepath_file_entry;
   GtkWidget   *movepath_filesel;
@@ -518,4 +520,34 @@ typedef struct GapStbMainGlobalParams  /* nickname: sgpp */
 } GapStbMainGlobalParams;
 
 
+typedef struct GapStbCreationParams  /* nickname: scrp */
+{
+  gchar         storyboard_filename[GAP_STORY_MAX_STORYFILENAME_LEN];
+  gint32        vid_width;
+  gint32        vid_height;
+  gdouble       framerate;
+
+  gdouble       aspect_ratio;
+  gint32        aspect_width;
+  gint32        aspect_height;
+
+  gdouble       samplerate;   // from audio track or default 44100 if no audio available...
+  gchar         preferred_decoder[GAP_STORY_MAX_STORYFILENAME_LEN];
+
+  /* Clip parameters */
+  gint32        record_type_int;
+
+
+  gchar         filename[GAP_STORY_MAX_STORYFILENAME_LEN];
+  gint32        from_frame;
+  gint32        to_frame;
+  gint32        vidtrack;
+  gdouble       delace_threshold;
+  gint32        delace_mode;
+  gint32        exact_seek;
+  gint32        nloop;
+
+
+} GapStbCreationParams;
+
 #endif
diff --git a/gap/gap_story_render_audio.c b/gap/gap_story_render_audio.c
index d8e380e..4e020ff 100644
--- a/gap/gap_story_render_audio.c
+++ b/gap/gap_story_render_audio.c
@@ -4,12 +4,29 @@
  *  GAP storyboard audio rendering.
  *
  */
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
 
 /*
  * 2006.06.25  hof  - created (moved stuff from the former gap_gve_story modules to this  new module)
  *
  */
- 
+
 #include <config.h>
 
 /* SYTEM (UNIX) includes */
@@ -201,7 +218,7 @@ gap_story_render_remove_tmp_audiofiles(GapStoryRenderVidHandle *vidhand)
         printf("gap_story_render_remove_tmp_audiofiles tmp_audiofile: %s\n"
               , aud_elem->tmp_audiofile);
       }
-      
+
       /* delete tmp_audiofile if still exists
        * (more aud_elements may refere to the same tmp_audiofile)
        */
@@ -821,7 +838,7 @@ p_extract_audioblock(t_GVA_Handle *gvahand
     }
 
     l_to_read = MIN(l_left_to_read, l_block_read);
-    
+
     /* handle progress */
     *vidhand->progress = (gdouble) (MAX((samples_to_extract - l_left_to_read), 0))
                        / (gdouble) (MAX(samples_to_extract, 1)) ;
@@ -880,7 +897,7 @@ p_extract_audiopart(t_GVA_Handle *gvahand
   {
     printf("p_extract_audiopart: START\n");
   }
-  
+
   l_audio_channels = gvahand->audio_cannels;
   l_sample_rate    = gvahand->samplerate;
 
@@ -889,7 +906,7 @@ p_extract_audiopart(t_GVA_Handle *gvahand
   {
     return;
   }
-  
+
   samples_to_skip = min_play_sec * (gdouble)l_sample_rate;
 
   GVA_seek_audio(gvahand, 0.0, GVA_UPOS_SECS);
@@ -1121,7 +1138,7 @@ gap_story_render_audio_new_audiorange_element(GapStoryRenderAudioType  aud_type
          printf("gap_story_render_audio_new_audiorange_element: list of known audiofiles is empty (NULL)\n");
        }
      }
-     
+
      /* check the list for known audioranges
       * if audiofile is already known, we can skip the file scan
       * (that can save lot of time when the file must be converted or resampled)
@@ -1169,9 +1186,37 @@ gap_story_render_audio_new_audiorange_element(GapStoryRenderAudioType  aud_type
      }
      if(l_audscan_required)
      {
-#ifdef GAP_ENABLE_VIDEOAPI_SUPPORT
+        gboolean movieIsExtractedAudio = FALSE;
+
         if(aud_type == GAP_AUT_MOVIE)
         {
+             long samplerate;
+             long channels;
+             long bytes_per_sample;
+             long bits;
+             long samples;
+             int      l_rc;
+
+             l_rc = gap_audio_wav_file_check(aud_elem->audiofile
+                     , &samplerate, &channels
+                     , &bytes_per_sample, &bits, &samples);
+             if (l_rc == 0)
+             {
+               /* the movie filename refers to an already extracted RIFF WAVE audiofile.
+                * Assume that this external audiotrack has full videolength.
+                * in this case force audio processing without offset (e.g. set min_play_sec to 0).
+                * Note that this special case is a workarond in case of unsupported audio codec
+                * where the extraction my be done manually via other tools (that supports the codec)
+                * and allows to access the extracted (external) audiotrack
+                * in the storyboard by frame numbers just like a movie internal audiotrack.
+                */
+               movieIsExtractedAudio = TRUE;
+               min_play_sec = 0;
+             }
+        }
+#ifdef GAP_ENABLE_VIDEOAPI_SUPPORT
+        if((aud_type == GAP_AUT_MOVIE) && (movieIsExtractedAudio == FALSE))
+        {
            t_GVA_Handle *gvahand;
 
            if(preferred_decoder)
@@ -1196,7 +1241,7 @@ gap_story_render_audio_new_audiorange_element(GapStoryRenderAudioType  aud_type
              aud_elem->bytes_per_sample  = gvahand->audio_cannels * 2;  /* API operates with 16 bit per sample */
              aud_elem->samples           = gvahand->total_aud_samples;  /* sometimes this is not an exact value, but just a guess */
              aud_elem->byteoffset_data   = 0;                           /* no headeroffset for audiopart loaded from videofiles */
-             
+
              if(gap_debug)
              {
                printf("AFTER GVA_open_read: %s\n", aud_elem->audiofile);
@@ -1254,8 +1299,8 @@ gap_story_render_audio_new_audiorange_element(GapStoryRenderAudioType  aud_type
                                           , vidhand
                                           );
                        GVA_close(gvahand);
-                       
-                       
+
+
                        if(vidhand->status_msg)
                        {
                          g_snprintf(vidhand->status_msg, vidhand->status_msg_len
@@ -1348,8 +1393,8 @@ gap_story_render_audio_new_audiorange_element(GapStoryRenderAudioType  aud_type
            }
         }
 #endif
-        
-        if(aud_type == GAP_AUT_AUDIOFILE)
+
+        if((aud_type == GAP_AUT_AUDIOFILE) || (movieIsExtractedAudio == TRUE))
         {
           if(g_file_test(aud_elem->audiofile, G_FILE_TEST_EXISTS))
           {
@@ -1402,7 +1447,7 @@ gap_story_render_audio_new_audiorange_element(GapStoryRenderAudioType  aud_type
              {
                if(create_audio_tmp_files)
                {
-                       
+
                   if(vidhand->status_msg)
                   {
                     g_snprintf(vidhand->status_msg, vidhand->status_msg_len
@@ -1411,7 +1456,7 @@ gap_story_render_audio_new_audiorange_element(GapStoryRenderAudioType  aud_type
                   }
                   /* fake some dummy progress */
                   *vidhand->progress = 0.05;
-                       
+
                   /* aud_elem->tmp_audiofile = g_strdup_printf("%s.tmp.wav", aud_elem->audiofile); */
                   aud_elem->tmp_audiofile = gimp_temp_name("tmp.wav");
                   gap_story_sox_exec_resample(aud_elem->audiofile
@@ -1427,7 +1472,7 @@ gap_story_render_audio_new_audiorange_element(GapStoryRenderAudioType  aud_type
                   l_rc = gap_audio_wav_file_check(aud_elem->tmp_audiofile
                           , &samplerate, &channels
                           , &bytes_per_sample, &bits, &samples);
-  
+
                   if((l_rc == 0)
                   && ((bits == 16)    || (bits == 8))
                   && ((channels == 2) || (channels == 1))
@@ -1447,14 +1492,14 @@ gap_story_render_audio_new_audiorange_element(GapStoryRenderAudioType  aud_type
                   {
                     char *l_errtxt;
                     /* conversion failed, cant use that file, delete tmp_audiofile now */
-  
+
                     if(aud_elem->tmp_audiofile)
                     {
                        g_remove(aud_elem->tmp_audiofile);
                        g_free(aud_elem->tmp_audiofile);
                        aud_elem->tmp_audiofile = NULL;
                     }
-  
+
                     l_errtxt = g_strdup_printf(_("cant use file:  %s as audioinput"), aud_elem->audiofile);
                     gap_story_render_set_stb_error(sterr, l_errtxt);
                     g_free(l_errtxt);
diff --git a/gap/gap_story_render_processor.c b/gap/gap_story_render_processor.c
index b9d7dd1..bbf6440 100644
--- a/gap/gap_story_render_processor.c
+++ b/gap/gap_story_render_processor.c
@@ -365,6 +365,8 @@ static GapStoryRenderVidHandle * p_open_video_handle_private(    gboolean ignore
                       , gdouble delace
                       , gboolean compensate_framerange
                       , GapStoryBoard *stb_mem_ptr
+                      , char *util_sox
+                      , char *util_sox_options
                       );
 static gint32     p_exec_filtermacro(gint32 image_id
                          , gint32 layer_id
@@ -3588,6 +3590,8 @@ p_open_mask_vidhand(GapStoryElem *stb_elem, GapStoryRenderMaskDefElem *maskdef_e
                             ,stb_elem->delace
                             ,FALSE                      /* compensate_framerange */
                             ,NULL                       /* stb_mem_ptr */
+                            ,NULL                       /* util_sox */
+                            ,NULL                       /* util_sox_options */
                             );
   if(maskdef_elem->mask_vidhand)
   {
@@ -4086,6 +4090,8 @@ p_open_video_handle_private(    gboolean ignore_audio
                       , gdouble delace
                       , gboolean compensate_framerange
                       , GapStoryBoard *stb_mem_ptr
+                      , char *util_sox
+                      , char *util_sox_options
                       )
 {
   GapStoryRenderVidHandle *vidhand;
@@ -4147,8 +4153,10 @@ p_open_video_handle_private(    gboolean ignore_audio
   vidhand->master_height = 0;
   vidhand->master_samplerate = 44100;    /* 44.1 kHZ CD standard Quality */
   vidhand->master_volume     = 1.0;
-  vidhand->util_sox          = NULL;     /* use DEFAULT resample program (sox), where needed */
-  vidhand->util_sox_options  = NULL;     /* use DEFAULT options */
+  vidhand->util_sox          = NULL;
+  vidhand->util_sox_options  = NULL;
+  gap_story_render_set_audio_resampling_program(vidhand, util_sox, util_sox_options);
+  
   vidhand->ignore_audio      = ignore_audio;
   vidhand->ignore_video      = ignore_video;
   vidhand->create_audio_tmp_files = create_audio_tmp_files;
@@ -4509,6 +4517,8 @@ gap_story_render_open_extended_video_handle(    gboolean ignore_audio
                       , gint32  frame_from
                       , gint32  frame_to
                       , gint32 *frame_count   /* output total frame_count , or 0 on failure */
+                      , char *util_sox
+                      , char *util_sox_options
                       )
 {
   return(p_open_video_handle_private( ignore_audio  /* ignore_audio */
@@ -4532,6 +4542,8 @@ gap_story_render_open_extended_video_handle(    gboolean ignore_audio
                             ,0.0            /* delace */
                             ,TRUE           /* compensate_framerange */
                             ,NULL           /* stb_mem_ptr */
+                            ,util_sox
+                            ,util_sox_options
                             )
          );
 
@@ -4581,6 +4593,8 @@ gap_story_render_open_vid_handle_from_stb(GapStoryBoard *stb_mem_ptr
                             ,0.0            /* delace */
                             ,TRUE           /* compensate_framerange */
                             ,stb_mem_ptr    /* stb_mem_ptr */
+                            ,NULL           /* util_sox */
+                            ,NULL           /* util_sox_options */
                             );
   }
 
@@ -4645,6 +4659,8 @@ gap_story_render_open_vid_handle(GapLibTypeInputRange input_mode
                             ,0.0            /* delace */
                             ,TRUE           /* compensate_framerange */
                             ,NULL           /* stb_mem_ptr */
+                            ,NULL           /* util_sox */
+                            ,NULL           /* util_sox_options */
                             );
 
   if(imagename)
diff --git a/gap/gap_story_render_processor.h b/gap/gap_story_render_processor.h
index 891ca9b..0827305 100644
--- a/gap/gap_story_render_processor.h
+++ b/gap/gap_story_render_processor.h
@@ -334,6 +334,8 @@ GapStoryRenderVidHandle *  gap_story_render_open_extended_video_handle(
                           ,gint32  frame_from
                           ,gint32  frame_to
                           ,gint32 *frame_count   /* output total frame_count , or 0 on failure */
+                          ,char *util_sox
+                          ,char *util_sox_options
                           );
 
 void    gap_story_render_close_vid_handle(GapStoryRenderVidHandle *vidhand);
diff --git a/gap/gap_vex_dialog.c b/gap/gap_vex_dialog.c
index beb30b9..e5eb972 100644
--- a/gap/gap_vex_dialog.c
+++ b/gap/gap_vex_dialog.c
@@ -87,6 +87,8 @@ static void        on_mw__combo_preferred_decoder  (GtkWidget     *widget,
                                                    GapVexMainGlobalParams *gpp);
 static void        on_mw__combo_deinterlace  (GtkWidget     *widget,
                                               GapVexMainGlobalParams *gpp);
+static void        on_mw__combo_mode_multilayer  (GtkWidget     *widget,
+                                              GapVexMainGlobalParams *gpp);
 
 static void        on_mw__checkbutton_bluebox_toggled (GtkToggleButton *togglebutton,
                                         GapVexMainGlobalParams *gpp);
@@ -116,8 +118,6 @@ static void        on_mw__entry_audiofile_changed         (GtkEditable     *edit
                                         GapVexMainGlobalParams *gpp);
 static void        on_mw__button_audiofile_clicked        (GtkButton       *button,
                                         GapVexMainGlobalParams *gpp);
-static void        on_mw__checkbutton_multilayer_toggled  (GtkToggleButton *togglebutton,
-                                        GapVexMainGlobalParams *gpp);
 static void        on_mw__button_vrange_dialog_clicked    (GtkButton       *button,
                                         GdkEventButton  *bevent,
                                         GapVexMainGlobalParams *gpp);
@@ -392,7 +392,7 @@ p_update_wgt_sensitivity(GapVexMainGlobalParams *gpp)
 
   gtk_widget_set_sensitive(gpp->mw__spinbutton_basenum, sensitive);
   gtk_widget_set_sensitive(gpp->mw__combo_deinterlace, sensitive);
-  gtk_widget_set_sensitive(gpp->mw__checkbutton_multilayer, sensitive);
+  gtk_widget_set_sensitive(gpp->mw__combo_mode_multilayer, sensitive);
 
   gtk_widget_set_sensitive(gpp->mw__checkbutton_generate_alpha_via_bluebox, sensitive);
   if(gpp->val.generate_alpha_via_bluebox != TRUE)
@@ -492,11 +492,6 @@ p_init_mw__main_window_widgets (GapVexMainGlobalParams *gpp)
  entry = GTK_ENTRY(gpp->mw__entry_preferred_decoder);
  gtk_entry_set_text(entry, gpp->val.preferred_decoder);
 
-
- wgt = gpp->mw__checkbutton_multilayer;
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wgt),
-                               gpp->val.multilayer );
-
  wgt = gpp->mw__checkbutton_disable_mmx;
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wgt),
                                gpp->val.disable_mmx );
@@ -696,30 +691,6 @@ p_call_player_widget(GapVexMainGlobalParams *gpp
 
 
 /* -------------------
- * p_check_aspect
- * -------------------
- */
-gboolean
-p_check_aspect(gdouble aspect_ratio, gint width, gint height)
-{
-  gdouble w_div_h;
-
-  if(height)
-  {
-    w_div_h = (gdouble)width / (gdouble)height;
-
-    if ((aspect_ratio <=  w_div_h + 0.001)
-    &&  (aspect_ratio >=  w_div_h - 0.001))
-    {
-      return(TRUE);
-    }
-  }
-
-  return (FALSE);
-}  /* end p_check_aspect */
-
-
-/* -------------------
  * p_check_videofile
  * -------------------
  * check videofile compatibility
@@ -912,7 +883,7 @@ on_mw__combo_preferred_decoder  (GtkWidget     *widget,
      break;
  }
  g_snprintf(gpp->val.preferred_decoder, sizeof(gpp->val.preferred_decoder)
-	    , "%s", preferred_decoder
+            , "%s", preferred_decoder
                );
  entry = GTK_ENTRY(gpp->mw__entry_preferred_decoder);
  if(entry)
@@ -963,6 +934,34 @@ on_mw__combo_deinterlace  (GtkWidget     *widget,
 }  /* end on_mw__combo_deinterlace */
 
 
+/* ------------------------------
+ * on_mw__combo_mode_multilayer
+ * ------------------------------
+ */
+static void
+on_mw__combo_mode_multilayer  (GtkWidget     *widget,
+                           GapVexMainGlobalParams *gpp)
+{
+  gint       l_idx;
+  gint       value;
+  gboolean   sensitive;
+
+  if(gap_debug) printf("CB: on_mw__combo_mode_multilayer\n");
+
+  if(gpp == NULL) return;
+
+  gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &value);
+  l_idx = value;
+
+  if(gap_debug) printf("CB: on_mw__combo_mode_multilayer index: %d\n", (int)l_idx);
+
+  gpp->val.multilayer = l_idx;
+
+  p_update_wgt_sensitivity(gpp);
+
+}  /* end on_mw__combo_mode_multilayer */
+
+
 /* --------------------------------
  * on_mw__checkbutton_bluebox_toggled
  * --------------------------------
@@ -1368,32 +1367,6 @@ on_mw__button_audiofile_clicked        (GtkButton       *button,
  }
 }
 
-/* --------------------------------
- * on_mw__checkbutton_multilayer_toggled
- * --------------------------------
- */
-static void
-on_mw__checkbutton_multilayer_toggled  (GtkToggleButton *togglebutton,
-                                        GapVexMainGlobalParams *gpp)
-{
- GtkWidget *wgt;
-
- if(gap_debug) printf("CB: on_mw__checkbutton_multilayer_toggled\n");
- if(gpp == NULL) return;
-
- wgt = gpp->mw__checkbutton_multilayer;
-
- if (GTK_TOGGLE_BUTTON (wgt)->active)
- {
-    gpp->val.multilayer = TRUE;
- }
- else
- {
-    gpp->val.multilayer = FALSE;
- }
- p_update_wgt_sensitivity(gpp);
-}
-
 
 /* --------------------------------
  * on_mw__button_vrange_dialog_clicked
@@ -1993,7 +1966,7 @@ gap_vex_dlg_create_mw__main_window (GapVexMainGlobalParams *gpp)
   GtkWidget *mw__label_audifile;
   GtkWidget *mw__entry_audiofile;
   GtkWidget *mw__button_audiofile;
-  GtkWidget *mw__checkbutton_multilayer;
+  GtkWidget *mw__combo_mode_multilayer;
   GtkWidget *mw__combo_deinterlace;
   GtkObject *mw__spinbutton_delace_threshold_adj;
   GtkWidget *mw__spinbutton_delace_threshold;
@@ -2337,11 +2310,7 @@ gap_vex_dlg_create_mw__main_window (GapVexMainGlobalParams *gpp)
                                 "libavformat",           GAP_VEX_DECODER_LIBAVFORMAT,
                                 "quicktime4linux",       GAP_VEX_DECODER_QUICKTIME,
                               NULL);
-
-  gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (mw__combo_preferred_decoder),
-                             GAP_VEX_DECODER_NONE,   /* initial value */
-                             G_CALLBACK (on_mw__combo_preferred_decoder),
-                             gpp);
+  gpp->mw__combo_preferred_decoder = mw__combo_preferred_decoder;
 
   gtk_widget_show (mw__combo_preferred_decoder);
   wgt_array[wgt_idx] = mw__combo_preferred_decoder;
@@ -2443,16 +2412,20 @@ gap_vex_dlg_create_mw__main_window (GapVexMainGlobalParams *gpp)
                     (GtkAttachOptions) (GTK_FILL),
                     (GtkAttachOptions) (0), 0, 0);
 
-  /* the multilayer checkbox (decide if extract writes to frames on disc or to one image) */
-  mw__checkbutton_multilayer = gtk_check_button_new_with_label (_("Create only one multilayer Image"));
-  gtk_widget_show (mw__checkbutton_multilayer);
-  gtk_table_attach (GTK_TABLE (mw__table_out), mw__checkbutton_multilayer, 1, 2, out_row, out_row+1,
+  /* the multilayer combo box (decide if extract writes to frames on disc or to one image or storyboard) */
+  mw__combo_mode_multilayer =
+    gimp_int_combo_box_new (_("extracted frames are written to frame files on disc"),  0,
+                            _("extracted frames are stored in one multilayer image"),  1,
+                            _("create a storyboard from selected video clip"),         2,
+                           NULL);
+    gpp->mw__combo_mode_multilayer = mw__combo_mode_multilayer;
+
+
+
+  gtk_widget_show (mw__combo_mode_multilayer);
+  gtk_table_attach (GTK_TABLE (mw__table_out), mw__combo_mode_multilayer, 1, 2, out_row, out_row+1,
                     (GtkAttachOptions) (GTK_FILL),
                     (GtkAttachOptions) (0), 0, 0);
-  gimp_help_set_help_data (mw__checkbutton_multilayer
-                          , _("On: extracted frames are stored in one multilayer image\n"
-                              "Off: extracted frames are written to frame files on disc")
-                          , NULL);
 
 
   out_row++;
@@ -2668,11 +2641,7 @@ gap_vex_dlg_create_mw__main_window (GapVexMainGlobalParams *gpp)
                               _("deinterlace frames x 2 (odd 1st)"),  GAP_VEX_DELACE_ODD_X2,
                               _("deinterlace frames x 2 (even 1st)"), GAP_VEX_DELACE_EVEN_X2,
                               NULL);
-
-  gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (mw__combo_deinterlace),
-                             GAP_VEX_DELACE_NONE,   /* initial value */
-                             G_CALLBACK (on_mw__combo_deinterlace),
-                             gpp);
+  gpp->mw__combo_deinterlace = mw__combo_deinterlace;
 
 
   gtk_widget_show (mw__combo_deinterlace);
@@ -2726,6 +2695,41 @@ gap_vex_dlg_create_mw__main_window (GapVexMainGlobalParams *gpp)
   p_align_widget_columns(wgt_array, wgt_idx);
 
 
+  /* copy widget pointers to global parameter
+   * (for use in callbacks outside of this procedure)
+   */
+  gpp->mw__checkbutton_disable_mmx             = mw__checkbutton_disable_mmx;
+  gpp->mw__entry_video                         = mw__entry_video;
+  gpp->mw__button_vrange_dialog                = mw__button_vrange_dialog;
+  gpp->mw__button_vrange_docked                = mw__button_vrange_docked;
+  gpp->mw__button_video                        = mw__button_video;
+  gpp->mw__label_active_decoder                = mw__label_active_decoder;
+  gpp->mw__label_aspect_ratio                  = mw__label_aspect_ratio;
+  gpp->mw__entry_preferred_decoder             = mw__entry_preferred_decoder;
+  gpp->mw__spinbutton_audiotrack_adj           = mw__spinbutton_audiotrack_adj;
+  gpp->mw__spinbutton_audiotrack               = mw__spinbutton_audiotrack;
+  gpp->mw__spinbutton_videotrack_adj           = mw__spinbutton_videotrack_adj;
+  gpp->mw__spinbutton_videotrack               = mw__spinbutton_videotrack;
+  gpp->mw__spinbutton_end_frame_adj            = mw__spinbutton_end_frame_adj;
+  gpp->mw__spinbutton_end_frame                = mw__spinbutton_end_frame;
+  gpp->mw__spinbutton_begin_frame_adj          = mw__spinbutton_begin_frame_adj;
+  gpp->mw__spinbutton_begin_frame              = mw__spinbutton_begin_frame;
+  gpp->mw__checkbutton_exact_seek              = mw__checkbutton_exact_seek;
+  gpp->mw__entry_extension                     = mw__entry_extension;
+  gpp->mw__entry_basename                      = mw__entry_basename;
+  gpp->mw__button_basename                     = mw__button_basename;
+  gpp->mw__spinbutton_basenum_adj              = mw__spinbutton_basenum_adj;
+  gpp->mw__spinbutton_basenum                  = mw__spinbutton_basenum;
+  gpp->mw__entry_audiofile                     = mw__entry_audiofile;
+  gpp->mw__button_audiofile                    = mw__button_audiofile;
+  gpp->mw__spinbutton_delace_threshold_adj     = mw__spinbutton_delace_threshold_adj;
+  gpp->mw__spinbutton_delace_threshold         = mw__spinbutton_delace_threshold;
+  gpp->mw__spinbutton_fn_digits_adj            = mw__spinbutton_fn_digits_adj;
+  gpp->mw__spinbutton_fn_digits                = mw__spinbutton_fn_digits;
+  gpp->mw__button_OK                           = mw__button_OK;
+  gpp->mw__player_frame                        = mw__player_frame;
+
+
   g_signal_connect (G_OBJECT (mw__checkbutton_disable_mmx), "toggled",
                       G_CALLBACK (on_mw__checkbutton_disable_mmx_toggled),
                       gpp);
@@ -2774,9 +2778,6 @@ gap_vex_dlg_create_mw__main_window (GapVexMainGlobalParams *gpp)
   g_signal_connect (G_OBJECT (mw__button_audiofile), "clicked",
                       G_CALLBACK (on_mw__button_audiofile_clicked),
                       gpp);
-  g_signal_connect (G_OBJECT (mw__checkbutton_multilayer), "toggled",
-                      G_CALLBACK (on_mw__checkbutton_multilayer_toggled),
-                      gpp);
   g_signal_connect (G_OBJECT (mw__spinbutton_delace_threshold), "value_changed",
                       G_CALLBACK (on_mw__spinbutton_delace_threshold_changed),
                       gpp);
@@ -2787,43 +2788,22 @@ gap_vex_dlg_create_mw__main_window (GapVexMainGlobalParams *gpp)
                       G_CALLBACK (on_mw__spinbutton_fn_digits_changed),
                       gpp);
 
+  gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (mw__combo_preferred_decoder),
+                             GAP_VEX_DECODER_NONE,   /* initial value */
+                             G_CALLBACK (on_mw__combo_preferred_decoder),
+                             gpp);
+
+  gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (mw__combo_deinterlace),
+                             GAP_VEX_DELACE_NONE,   /* initial value */
+                             G_CALLBACK (on_mw__combo_deinterlace),
+                             gpp);
+
+  gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (mw__combo_mode_multilayer),
+                               CLAMP(gpp->val.multilayer, 0, 2),   /* initial value */
+                               G_CALLBACK (on_mw__combo_mode_multilayer),
+                               gpp);
+
 
-  /* copy widget pointers to global parameter
-   * (for use in callbacks outside of this procedure)
-   */
-  gpp->mw__checkbutton_disable_mmx             = mw__checkbutton_disable_mmx;
-  gpp->mw__entry_video                         = mw__entry_video;
-  gpp->mw__button_vrange_dialog                = mw__button_vrange_dialog;
-  gpp->mw__button_vrange_docked                = mw__button_vrange_docked;
-  gpp->mw__button_video                        = mw__button_video;
-  gpp->mw__combo_preferred_decoder             = mw__combo_preferred_decoder;
-  gpp->mw__label_active_decoder                = mw__label_active_decoder;
-  gpp->mw__label_aspect_ratio                  = mw__label_aspect_ratio;
-  gpp->mw__entry_preferred_decoder             = mw__entry_preferred_decoder;
-  gpp->mw__spinbutton_audiotrack_adj           = mw__spinbutton_audiotrack_adj;
-  gpp->mw__spinbutton_audiotrack               = mw__spinbutton_audiotrack;
-  gpp->mw__spinbutton_videotrack_adj           = mw__spinbutton_videotrack_adj;
-  gpp->mw__spinbutton_videotrack               = mw__spinbutton_videotrack;
-  gpp->mw__spinbutton_end_frame_adj            = mw__spinbutton_end_frame_adj;
-  gpp->mw__spinbutton_end_frame                = mw__spinbutton_end_frame;
-  gpp->mw__spinbutton_begin_frame_adj          = mw__spinbutton_begin_frame_adj;
-  gpp->mw__spinbutton_begin_frame              = mw__spinbutton_begin_frame;
-  gpp->mw__checkbutton_exact_seek              = mw__checkbutton_exact_seek;
-  gpp->mw__entry_extension                     = mw__entry_extension;
-  gpp->mw__entry_basename                      = mw__entry_basename;
-  gpp->mw__button_basename                     = mw__button_basename;
-  gpp->mw__spinbutton_basenum_adj              = mw__spinbutton_basenum_adj;
-  gpp->mw__spinbutton_basenum                  = mw__spinbutton_basenum;
-  gpp->mw__entry_audiofile                     = mw__entry_audiofile;
-  gpp->mw__button_audiofile                    = mw__button_audiofile;
-  gpp->mw__checkbutton_multilayer              = mw__checkbutton_multilayer;
-  gpp->mw__combo_deinterlace                   = mw__combo_deinterlace;
-  gpp->mw__spinbutton_delace_threshold_adj     = mw__spinbutton_delace_threshold_adj;
-  gpp->mw__spinbutton_delace_threshold         = mw__spinbutton_delace_threshold;
-  gpp->mw__spinbutton_fn_digits_adj            = mw__spinbutton_fn_digits_adj;
-  gpp->mw__spinbutton_fn_digits                = mw__spinbutton_fn_digits;
-  gpp->mw__button_OK                           = mw__button_OK;
-  gpp->mw__player_frame                        = mw__player_frame;
   p_init_mw__main_window_widgets(gpp);
 
 /* endif GAP_ENABLE_VIDEOAPI_SUPPORT (2) */
diff --git a/gap/gap_vex_dialog.h b/gap/gap_vex_dialog.h
index 67489d4..0623cb9 100644
--- a/gap/gap_vex_dialog.h
+++ b/gap/gap_vex_dialog.h
@@ -31,7 +31,7 @@
 
 #include "config.h"
 
-/* SYTEM (UNIX) includes */ 
+/* SYTEM (UNIX) includes */
 #include <stdio.h>
 #include <stdlib.h>
 
diff --git a/gap/gap_vex_exec.c b/gap/gap_vex_exec.c
index b24436f..b5ebee6 100644
--- a/gap/gap_vex_exec.c
+++ b/gap/gap_vex_exec.c
@@ -36,6 +36,8 @@
 #include "gap_audio_extract.h"
 #include "gap_bluebox.h"
 
+#define GAP_STORY_PLUG_IN_PROC_CREATION   "plug_in_gap_storyboard_create_and_edit"
+
 /* -------------------
  * p_gap_set_framerate
  * -------------------
@@ -55,7 +57,7 @@ p_gap_set_framerate(gint32 image_id, gdouble framerate)
                           GIMP_PDB_FLOAT,    framerate,
                           GIMP_PDB_END);
 
-  g_free(l_params);                               
+  g_free(l_params);
 }  /* end p_gap_set_framerate */
 
 
@@ -100,7 +102,7 @@ p_frame_postprocessing(t_GVA_Handle   *gvahand
 {
   gint32 l_bbox_layer_id;
   gint32 l_layermask_id;
-  
+
   l_bbox_layer_id = gvahand->layer_id;
   if (gpp->val.generate_alpha_via_bluebox == TRUE)
   {
@@ -114,7 +116,7 @@ p_frame_postprocessing(t_GVA_Handle   *gvahand
       {
         printf("created bb_layer_id:%d\n", l_bbox_layer_id);
       }
-      
+
     }
     if (!gimp_drawable_has_alpha(l_bbox_layer_id))
     {
@@ -133,7 +135,7 @@ p_frame_postprocessing(t_GVA_Handle   *gvahand
         printf("GRAY created layermask_id:%d\n", l_layermask_id);
       }
       gap_layer_copy_paste_drawable(gvahand->image_id, gvahand->layer_id, l_layermask_id);
-    } 
+    }
     else if (gpp->val.extract_with_layermask == TRUE)
     {
       l_layermask_id = gimp_layer_create_mask(l_bbox_layer_id, GIMP_ADD_ALPHA_MASK);
@@ -156,11 +158,172 @@ p_frame_postprocessing(t_GVA_Handle   *gvahand
       //gimp_drawable_delete(l_bbox_layer_id);
     }
   }
-  
+
 
 }  /* end p_frame_postprocessing  */
 
 
+/* ---------------------------------------------
+ * p_vex_exe_create_storyboard_from_videorange
+ * ---------------------------------------------
+ * calls a plug-in that creates a storyboard from the selected videorange
+ * and opens it into the storyboard editor dialog.
+ */
+static void
+p_vex_exe_create_storyboard_from_videorange(GapVexMainGlobalParams *gpp)
+{
+#ifdef GAP_ENABLE_VIDEOAPI_SUPPORT
+  t_GVA_Handle   *gvahand;
+  GimpParam* l_params;
+  gint   l_retvals;
+  gint   l_rc;
+
+  char   *l_storyboard_filename;
+  gdouble l_framerate;
+  gdouble l_samplerate;
+  gdouble l_aspect_ratio;
+  gint32  l_aspect_width;
+  gint32  l_aspect_height;
+  gint32  l_vid_width;
+  gint32  l_vid_height;
+  gint32  l_image_id;
+  gint32  l_record_type_int;
+  gint32  l_nloop;
+  gint32  l_from_frame;
+  gint32  l_to_frame;
+
+  if (gpp->val.videotrack <= 0)
+  {
+     printf("No valid videotrack was selected video %s\n", gpp->val.videoname);
+     return;
+  }
+
+  /* --------- OPEN the videofile --------------- */
+  gvahand = GVA_open_read_pref(gpp->val.videoname
+                           ,gpp->val.videotrack
+                           ,gpp->val.audiotrack
+                           ,gpp->val.preferred_decoder
+                           , FALSE  /* use MMX if available (disable_mmx == FALSE) */
+                           );
+  if(gvahand == NULL)
+  {
+     printf("failed to open video %s\n", gpp->val.videoname);
+     return;
+  }
+  l_framerate = gvahand->framerate;
+  l_vid_width = gvahand->width;
+  l_vid_height = gvahand->height;
+  l_samplerate = 44100;
+  if ((gvahand->atracks > 0) && (gvahand->samplerate > 0))
+  {
+    l_samplerate = gvahand->samplerate;
+  }
+  l_aspect_ratio = 0.0;
+  l_aspect_width = 0;
+  l_aspect_height = 0;
+  if (gvahand->aspect_ratio > 0)
+  {
+    l_aspect_ratio = gvahand->aspect_ratio;
+
+    if(p_check_aspect(l_aspect_ratio, 3, 2))
+    {
+      l_aspect_width = 3;
+      l_aspect_height = 2;
+    }
+    if(p_check_aspect(l_aspect_ratio, 4, 3))
+    {
+      l_aspect_width = 4;
+      l_aspect_height = 3;
+    }
+    if(p_check_aspect(l_aspect_ratio, 16, 9))
+    {
+      l_aspect_width = 16;
+      l_aspect_height = 9;
+    }
+  }
+
+
+  /* extract the 1st frame as gimp image
+   * (for passing to the storyboard plug-in as active image
+   *  -- that will be displayed in the player widget of the stroyboard dialog at startup --)
+   */
+  l_image_id = -1;
+  l_rc = GVA_seek_frame(gvahand, gpp->val.begin_frame, GVA_UPOS_FRAMES);
+  l_rc = GVA_get_next_frame(gvahand);
+
+  if(l_rc == GVA_RET_OK)
+  {
+    /* convert fetched frame from buffer to gimp image gvahand->image_id */
+    l_rc = GVA_frame_to_gimp_layer(gvahand
+                                  ,TRUE   /* delete_mode */
+                                  ,gpp->val.begin_frame
+                                  ,0    /* delace */
+                                  ,0.0  /* delace_threshold */
+                                  );
+    if(l_rc == GVA_RET_OK)
+    {
+      l_image_id = gvahand->image_id;
+      if (l_image_id >= 0)
+      {
+        gimp_display_new(l_image_id);
+      }
+    }
+  }
+
+
+  GVA_close(gvahand);
+
+  if (l_image_id < 0)
+  {
+    g_message(_("failed to extract frame from video: %s"),  gpp->val.videoname);
+    return;
+  }
+
+  l_record_type_int = 0;     /* 0: video, 1:image, 2:frame images, 3:anim image */
+  l_nloop = 1;
+
+  l_storyboard_filename = g_strdup_printf("STORY_%s.txt", gpp->val.basename);
+  l_from_frame = gpp->val.begin_frame;
+  l_to_frame = gpp->val.end_frame;
+
+  /* call the stroryboard plug-in */
+  l_params = gimp_run_procedure (GAP_STORY_PLUG_IN_PROC_CREATION,
+                                 &l_retvals,
+                                 GIMP_PDB_INT32,    GIMP_RUN_NONINTERACTIVE,
+                                 GIMP_PDB_IMAGE,    l_image_id,
+                                 GIMP_PDB_STRING,   l_storyboard_filename,
+                                 GIMP_PDB_STRING,   gpp->val.videoname,
+                                 GIMP_PDB_STRING,   gpp->val.preferred_decoder,
+                                 GIMP_PDB_INT32,    l_vid_width,
+                                 GIMP_PDB_INT32,    l_vid_height,
+                                 GIMP_PDB_FLOAT,    l_framerate,
+                                 GIMP_PDB_FLOAT,    l_aspect_ratio,
+                                 GIMP_PDB_INT32,    l_aspect_width,
+                                 GIMP_PDB_INT32,    l_aspect_height,
+                                 GIMP_PDB_FLOAT,    l_samplerate,
+                                 GIMP_PDB_INT32,    l_record_type_int,
+                                 GIMP_PDB_INT32,    l_from_frame,
+                                 GIMP_PDB_INT32,    l_to_frame,
+                                 GIMP_PDB_INT32,    gpp->val.videotrack,
+                                 GIMP_PDB_INT32,    gpp->val.deinterlace,
+                                 GIMP_PDB_FLOAT,    gpp->val.delace_threshold,
+                                 GIMP_PDB_INT32,    gpp->val.exact_seek,
+                                 GIMP_PDB_INT32,    l_nloop,
+                                 GIMP_PDB_END);
+
+  g_free(l_storyboard_filename);
+
+  l_rc = -1;
+  if (l_params[0].data.d_status == GIMP_PDB_SUCCESS)
+  {
+    l_rc = 0;  /* OK */
+  }
+  gimp_destroy_params (l_params, l_retvals);
+
+#endif
+}  /* end p_vex_exe_create_storyboard_from_videorange */
+
+
 /* ------------------------------
  * gap_vex_exe_extract_videorange
  * ------------------------------
@@ -219,11 +382,17 @@ gap_vex_exe_extract_videorange(GapVexMainGlobalParams *gpp)
       printf("extract_with_layermask: %d\n", (int)gpp->val.extract_with_layermask);
   }
 
+  if (gpp->val.multilayer >= 2)
+  {
+    p_vex_exe_create_storyboard_from_videorange(gpp);
+    return;
+  }
+
   l_save_run_mode = GIMP_RUN_INTERACTIVE;  /* for the 1.st call of saving a non xcf frame */
   l_overwrite_mode = 0;
 
   gpp->val.image_ID = -1;
-  
+
   /* --------- OPEN the videofile --------------- */
   gvahand = GVA_open_read_pref(gpp->val.videoname
                            ,gpp->val.videotrack
@@ -297,7 +466,7 @@ gap_vex_exe_extract_videorange(GapVexMainGlobalParams *gpp)
        iid_max = 2;
        framenumber_fil = (framenumber * 2) -1;
 
-       if(gpp->val.deinterlace == GAP_VEX_DELACE_ODD_X2) 
+       if(gpp->val.deinterlace == GAP_VEX_DELACE_ODD_X2)
        {
          delace[0] = GAP_VEX_DELACE_ODD;
          delace[1] = GAP_VEX_DELACE_EVEN;
@@ -334,7 +503,7 @@ gap_vex_exe_extract_videorange(GapVexMainGlobalParams *gpp)
       l_empty_layer_id = gimp_layer_new(l_dummy_image_id, "background",
                           32, 32,
                           GIMP_RGB_IMAGE,
-                          100.0,     /* Opacity full opaque */     
+                          100.0,     /* Opacity full opaque */
                           GIMP_NORMAL_MODE);
       gimp_image_add_layer(l_dummy_image_id, l_empty_layer_id, 0);
       gap_layer_clear_to_color(l_empty_layer_id, 0.0, 0.0, 0.0, 1.0);
@@ -343,7 +512,7 @@ gap_vex_exe_extract_videorange(GapVexMainGlobalParams *gpp)
 
       /* must use same basename and extension for the dummyname
        * because setup of jpeg save params for further non interactive save operation
-       * depend on a key that includes the same basename and extension. 
+       * depend on a key that includes the same basename and extension.
        */
       l_dummyname = gap_lib_alloc_fname6(&gpp->val.basename[0]
                                         ,99999999
@@ -357,8 +526,8 @@ gap_vex_exe_extract_videorange(GapVexMainGlobalParams *gpp)
                            );
 
       gap_image_delete_immediate(l_dummy_image_id);
-      g_remove(l_dummyname);                       
-      g_free(l_dummyname);       
+      g_remove(l_dummyname);
+      g_free(l_dummyname);
       l_save_run_mode = GIMP_RUN_WITH_LAST_VALS;     /* for all further calls */
     }
 
@@ -376,7 +545,7 @@ gap_vex_exe_extract_videorange(GapVexMainGlobalParams *gpp)
     {
       gint32 l_seekstep;
       gint32 l_seek_framenumber;
- 
+
 
       if(1==1)
       {
@@ -386,7 +555,7 @@ gap_vex_exe_extract_videorange(GapVexMainGlobalParams *gpp)
       else
       {
         /* dead code (older and slower seek emulation
-         * implementation outside the API) 
+         * implementation outside the API)
          */
         l_seek_framenumber = l_pos;
         if(l_pos_unit == GVA_UPOS_PRECENTAGE)
@@ -397,7 +566,7 @@ gap_vex_exe_extract_videorange(GapVexMainGlobalParams *gpp)
         for(l_seekstep = 1; l_seekstep < l_seek_framenumber; l_seekstep++)
         {
           /* fetch one frame to buffer gvahand->frame_data
-           * (and proceed position to next frame) 
+           * (and proceed position to next frame)
            */
           l_rc = GVA_get_next_frame(gvahand);
           if(l_rc != GVA_RET_OK)
@@ -424,7 +593,7 @@ gap_vex_exe_extract_videorange(GapVexMainGlobalParams *gpp)
     while(1)
     {
        /* fetch one frame to buffer gvahand->frame_data
-        * (and proceed position to next frame) 
+        * (and proceed position to next frame)
         */
        l_rc = GVA_get_next_frame(gvahand);
        if(l_rc != GVA_RET_OK)
@@ -433,7 +602,7 @@ gap_vex_exe_extract_videorange(GapVexMainGlobalParams *gpp)
        }
        if(gpp->val.multilayer == 0)
        {
-         if((gpp->val.deinterlace == GAP_VEX_DELACE_ODD_X2) 
+         if((gpp->val.deinterlace == GAP_VEX_DELACE_ODD_X2)
          || (gpp->val.deinterlace == GAP_VEX_DELACE_EVEN_X2))
          {
            framenumber_fil = (framenumber * 2) -1;
@@ -472,16 +641,16 @@ gap_vex_exe_extract_videorange(GapVexMainGlobalParams *gpp)
                                      );
            if (l_overwrite_mode < 0)
            {
-               g_free(framename);       
+               g_free(framename);
                break;
            }
            else
            {
               gint32 l_sav_rc;
               gint32 l_sav_image_id;
-              
+
               l_sav_image_id = gvahand->image_id;
-              
+
               p_frame_postprocessing(gvahand, gpp);
               if (gpp->val.extract_alpha_as_gray_frames == TRUE)
               {
@@ -493,7 +662,7 @@ gap_vex_exe_extract_videorange(GapVexMainGlobalParams *gpp)
                            , framename
                            , l_save_run_mode
                            );
-                           
+
               if (l_sav_image_id != gvahand->image_id)
               {
                 /* delete temporary grayscale image */
@@ -505,7 +674,7 @@ gap_vex_exe_extract_videorange(GapVexMainGlobalParams *gpp)
                 break;
               }
            }
-           g_free(framename);       
+           g_free(framename);
          }
        }
        else
@@ -523,7 +692,7 @@ gap_vex_exe_extract_videorange(GapVexMainGlobalParams *gpp)
            break;
          }
          gpp->val.image_ID = gvahand->image_id;
-         
+
          if((gpp->val.deinterlace == GAP_VEX_DELACE_ODD_X2)
          || (gpp->val.deinterlace == GAP_VEX_DELACE_EVEN_X2))
          {
@@ -539,7 +708,7 @@ gap_vex_exe_extract_videorange(GapVexMainGlobalParams *gpp)
              break;
            }
          }
-         
+
        }
 
        framenumber++;
@@ -571,9 +740,9 @@ gap_vex_exe_extract_videorange(GapVexMainGlobalParams *gpp)
      {
        gdouble l_extracted_frames;
        gboolean do_progress;
-       
+
        l_extracted_frames = framenumber - framenumber1;
-       
+
        do_progress = TRUE;
        if(gpp->val.run_mode != GIMP_RUN_NONINTERACTIVE)
        {
@@ -612,7 +781,7 @@ gap_vex_exe_extract_videorange(GapVexMainGlobalParams *gpp)
     gimp_progress_update (l_progress);
   }
 
-  
+
   if(gpp->val.image_ID >= 0)
   {
     gimp_image_undo_enable(gpp->val.image_ID);
diff --git a/gap/gap_vex_exec.h b/gap/gap_vex_exec.h
index 33a5ecb..ae6bf66 100644
--- a/gap/gap_vex_exec.h
+++ b/gap/gap_vex_exec.h
@@ -32,7 +32,7 @@
 
 #include "config.h"
 
-/* SYTEM (UNIX) includes */ 
+/* SYTEM (UNIX) includes */
 #include <stdio.h>
 #include <stdlib.h>
 
diff --git a/gap/gap_vex_main.c b/gap/gap_vex_main.c
index 667ac00..7c59b12 100644
--- a/gap/gap_vex_main.c
+++ b/gap/gap_vex_main.c
@@ -63,7 +63,7 @@
 #include "gap_vex_exec.h"
 
 
-int gap_debug = 0;  /* 1 == print debug infos , 0 dont print debug infos */ 
+int gap_debug = 0;  /* 1 == print debug infos , 0 dont print debug infos */
 
 
 static void   query      (void);
@@ -104,7 +104,7 @@ query ()
     { GIMP_PDB_STRING, "basename", "The name for extracted ouput frames _0001.<extension> is added" },
     { GIMP_PDB_STRING, "extension", "select image save format by extension (.xcf, .ppm, .jpg, ...)" },
     { GIMP_PDB_INT32, "basenum", "number for the 1.st extracted output frame, 0: use original framenr" },
-    { GIMP_PDB_INT32, "multilayer", "0: save each frame to one file, 1: load all frames into one multilayer image" },
+    { GIMP_PDB_INT32, "multilayer", "0: save each frame to one file, 1: load all frames into one multilayer image, 2: create storyboard with selected clip" },
     { GIMP_PDB_INT32, "extract_videotrack", "0:ignore video frames, 1 upto n: extract frames from videotrack" },
     { GIMP_PDB_INT32, "extract_audiotrack", "0:ignore audio, 1 upto n: extract audiotrack to .wav file" },
     { GIMP_PDB_INT32, "overwrite_mode", "1: overwrite all existing files, other values: cancel if files already exists" },
@@ -281,7 +281,7 @@ run (const gchar *name,          /* name of plugin */
 
 
   /* init return status
-   * (if this plug-in is compiled without GAP_ENABLE_VIDEOAPI_SUPPORT 
+   * (if this plug-in is compiled without GAP_ENABLE_VIDEOAPI_SUPPORT
    *  it will always fail)
    */
   values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
@@ -390,9 +390,9 @@ run (const gchar *name,          /* name of plugin */
         values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
     }
   }
-  
+
   return;
-  
+
 /* endif GAP_ENABLE_VIDEOAPI_SUPPORT */
 #endif
   g_message(_("Videoextract is not available because "
diff --git a/gap/gap_vex_main.h b/gap/gap_vex_main.h
index 21b454f..8e3a15c 100644
--- a/gap/gap_vex_main.h
+++ b/gap/gap_vex_main.h
@@ -81,7 +81,7 @@ typedef struct {
   gdouble begin_frame;
   gdouble end_frame;
   gint    pos_unit;       /* 0 .. frames, 2 percent */
-  gint    multilayer;     /* 0 .. extract to single frames */
+  gint    multilayer;     /* 0 .. extract to single frames, 1 ..extract to multilayer image, 2.. create Stroyboard, 3 create + edit Storyboard */
   gint    disable_mmx;    /* 0 .. use MMX if available, 1 disable MMX  */
   gint    exact_seek;     /* 0 .. NO, 1 .. YES */
   gint    deinterlace;    /* 0 .. NO, 1 .. odd rows only, 2 even rows only, 3 .. odd first, 4 .. even first */
@@ -97,7 +97,7 @@ typedef struct {
 
   gchar preferred_decoder[100];
 
-  /* last checked videoname */ 
+  /* last checked videoname */
   gboolean chk_is_compatible_videofile;
   gint32  chk_total_frames;
   gint32  chk_vtracks;
@@ -110,7 +110,7 @@ typedef struct {
   /* current states of actual loaded (frame)image */
   gint32  image_ID;        /* -1 if there is no valid current image */
   GimpRunMode run_mode;
-  
+
   gboolean generate_alpha_via_bluebox;
   gboolean extract_alpha_as_gray_frames;
   gboolean extract_with_layermask;
@@ -119,18 +119,18 @@ typedef struct {
 
 typedef struct {  /* nick: gpp */
   GapVexMainVal   val;
-  
+
   GapPlayerMainGlobalParams *plp;      /* player widget parameters */
   gboolean   in_player_call;
   gint32     video_width;
   gint32     video_height;
   gdouble    video_speed;    /* original playback speed in frames per sec */
-  
+
   GtkWidget *mw__main_window;
   GtkWidget *fsv__fileselection;
   GtkWidget *fsb__fileselection;
   GtkWidget *fsa__fileselection;
-  
+
   GtkWidget *mw__player_frame;
   GtkWidget *mw__checkbutton_disable_mmx;
   GtkWidget *mw__entry_video;
@@ -157,7 +157,7 @@ typedef struct {  /* nick: gpp */
   GtkWidget *mw__spinbutton_basenum;
   GtkWidget *mw__entry_audiofile;
   GtkWidget *mw__button_audiofile;
-  GtkWidget *mw__checkbutton_multilayer;
+  GtkWidget *mw__combo_mode_multilayer;
   GtkWidget *mw__combo_deinterlace;
   GtkObject *mw__spinbutton_delace_threshold_adj;
   GtkWidget *mw__spinbutton_delace_threshold;
@@ -170,9 +170,32 @@ typedef struct {  /* nick: gpp */
   GtkWidget *mw__checkbutton_generate_alpha_via_bluebox;
   GtkWidget *mw__checkbutton_extract_alpha_as_gray_frames;
   GtkWidget *mw__checkbutton_extract_with_layermask;
-  
+
 } GapVexMainGlobalParams;
 
 extern int gap_debug;
 
+/* -------------------
+ * p_check_aspect
+ * -------------------
+ */
+static gboolean
+p_check_aspect(gdouble aspect_ratio, gint width, gint height)
+{
+  gdouble w_div_h;
+
+  if(height)
+  {
+    w_div_h = (gdouble)width / (gdouble)height;
+
+    if ((aspect_ratio <=  w_div_h + 0.001)
+    &&  (aspect_ratio >=  w_div_h - 0.001))
+    {
+      return(TRUE);
+    }
+  }
+
+  return (FALSE);
+}  /* end p_check_aspect */
+
 #endif
diff --git a/vid_common/gap_cme_gui.c b/vid_common/gap_cme_gui.c
index 23636c5..da9f9cb 100644
--- a/vid_common/gap_cme_gui.c
+++ b/vid_common/gap_cme_gui.c
@@ -1734,7 +1734,7 @@ p_thread_storyboard_file(gpointer data)
     l_create_audio_tmp_files = TRUE;
   }
 
-  vidhand = gap_gve_story_open_extended_video_handle
+  vidhand = gap_story_render_open_extended_video_handle
            ( FALSE   /* dont ignore video */
            , FALSE   /* dont ignore audio */
            , l_create_audio_tmp_files
@@ -1749,15 +1749,13 @@ p_thread_storyboard_file(gpointer data)
            , -1        /* frame_from */
            , 999999    /* frame_to */
            , &gpp->val.storyboard_total_frames
+           , gpp->val.util_sox
+           , gpp->val.util_sox_options
            );
 
   if(vidhand)
   {
     gstb->vidhand_open_ok = TRUE;
-    gap_gve_story_set_audio_resampling_program(vidhand
-                       , gpp->val.util_sox
-                       , gpp->val.util_sox_options
-                       );
 
     if(vidhand->master_framerate != 0.0)
     {



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