2.5
authorTon Roosendaal <ton@blender.org>
Mon, 12 Jan 2009 19:02:08 +0000 (19:02 +0000)
committerTon Roosendaal <ton@blender.org>
Mon, 12 Jan 2009 19:02:08 +0000 (19:02 +0000)
12k lines of sequencer back! Only seqaudio.c skipped for now.
Notes:

- it only draws now, nothing refreshes or edits.
- fixed bug in view2d.c with vertical grid step being 0.0f
- render code and fileselect code is #ifdeffed out
- sequence evaluation code moved to blenkernel, so it can
  be used for render without bad level calls

General note; sequencer code is very untidy, mixing styles too
much. Tried to clean it some, but it would be nice if formatting
is kept consistant from now on.

12 files changed:
source/blender/blenkernel/BKE_sequence.h
source/blender/blenkernel/intern/seqeffects.c [new file with mode: 0644]
source/blender/blenkernel/intern/sequence.c
source/blender/blenlib/intern/bpath.c
source/blender/editors/interface/view2d.c
source/blender/editors/space_sequencer/Makefile
source/blender/editors/space_sequencer/SConscript
source/blender/editors/space_sequencer/editseq.c [new file with mode: 0644]
source/blender/editors/space_sequencer/sequencer_draw.c [new file with mode: 0644]
source/blender/editors/space_sequencer/sequencer_intern.h
source/blender/editors/space_sequencer/sequencer_scopes.c [new file with mode: 0644]
source/blender/editors/space_sequencer/space_sequencer.c

index 2c4daf7fce5c7bf073e056da165042e7699f6ad3..bd56b100fc04ec421b38d8f215d1941975b7238b 100644 (file)
 
 struct Editing;
 struct Sequence;
+struct Strip;
+struct StripElem;
+struct ImBuf;
+struct Scene;
 
-/* free */
+#define MAXSEQ          32
+
+#define BUILD_SEQAR_COUNT_NOTHING  0
+#define BUILD_SEQAR_COUNT_CURRENT  1
+#define BUILD_SEQAR_COUNT_CHILDREN 2
 
-void seq_free_sequence(struct Sequence *seq);
-void seq_free_editing(struct Editing *ed);
 
 /* sequence iterator */
 
@@ -49,16 +55,21 @@ typedef struct SeqIterator {
        int valid;
 } SeqIterator;
 
-void seq_begin(struct Editing *ed, SeqIterator *iter);
+void seq_begin(struct Editing *ed, SeqIterator *iter, int use_pointer);
 void seq_next(SeqIterator *iter);
 void seq_end(SeqIterator *iter);
+void seq_array(struct Editing *ed, struct Sequence ***seqarray, int *tot, int use_pointer);
 
-void seq_array(struct Editing *ed, struct Sequence ***array, int *tot);
-
+#define SEQP_BEGIN(ed, seq) \
+{ \
+       SeqIterator iter;\
+               for(seq_begin(ed, &iter, 1); iter.valid; seq_next(&iter)) { \
+                       seq= iter.seq;
+                       
 #define SEQ_BEGIN(ed, seq) \
        { \
                SeqIterator iter;\
-               for(seq_begin(ed, &iter); iter.valid; seq_next(&iter)) { \
+               for(seq_begin(ed, &iter, 0); iter.valid; seq_next(&iter)) { \
                        seq= iter.seq;
 
 #define SEQ_END \
@@ -68,3 +79,89 @@ void seq_array(struct Editing *ed, struct Sequence ***array, int *tot);
 
 #endif
 
+
+/* Wipe effect */
+enum {DO_SINGLE_WIPE, DO_DOUBLE_WIPE, DO_BOX_WIPE, DO_CROSS_WIPE,
+       DO_IRIS_WIPE,DO_CLOCK_WIPE};
+
+
+struct SeqEffectHandle {
+       /* constructors & destructor */
+       /* init & init_plugin are _only_ called on first creation */
+       void (*init)(struct Sequence *seq);
+       void (*init_plugin)(struct Sequence *seq, const char *fname);
+       
+       /* number of input strips needed 
+               (called directly after construction) */
+       int (*num_inputs)();
+       
+       /* load is called first time after readblenfile in
+               get_sequence_effect automatically */
+       void (*load)(struct Sequence *seq);
+       
+       /* duplicate */
+       void (*copy)(struct Sequence *dst, struct Sequence *src);
+       
+       /* destruct */
+       void (*free)(struct Sequence *seq);
+       
+       /* returns: -1: no input needed,
+       0: no early out, 
+       1: out = ibuf1, 
+       2: out = ibuf2 */
+       int (*early_out)(struct Sequence *seq,
+                                        float facf0, float facf1); 
+       
+       /* stores the y-range of the effect IPO */
+       void (*store_icu_yrange)(struct Sequence * seq,
+                                                        short adrcode, float *ymin, float *ymax);
+       
+       /* stores the default facf0 and facf1 if no IPO is present */
+       void (*get_default_fac)(struct Sequence *seq, int cfra,
+                                                       float * facf0, float * facf1);
+       
+       /* execute the effect
+               sequence effects are only required to either support
+               float-rects or byte-rects 
+               (mixed cases are handled one layer up...) */
+       
+       void (*execute)(struct Sequence *seq, int cfra,
+                                       float facf0, float facf1,
+                                       int x, int y,
+                                       struct ImBuf *ibuf1, struct ImBuf *ibuf2,
+                                       struct ImBuf *ibuf3, struct ImBuf *out);
+};
+
+/* ********************* prototypes *************** */
+
+/* sequence.c */
+
+// extern
+void seq_free_sequence(struct Sequence *seq);
+void seq_free_strip(struct Strip *strip);
+void seq_free_editing(struct Editing *ed);
+char *give_seqname(struct Sequence *seq);
+struct ImBuf *give_ibuf_seq(struct Scene *scene, int rectx, int recty, int cfra, int chanshown);
+struct ImBuf *give_ibuf_seq_threaded(struct Scene *scene, int rectx, int recty, int cfra, int chanshown);
+struct ImBuf *give_ibuf_seq_direct(struct Scene *scene, int rectx, int recty, int cfra, struct Sequence *seq);
+void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown);
+void calc_sequence(struct Sequence *seq);
+void new_tstripdata(struct Sequence *seq);
+void reload_sequence_new_file(struct Scene *scene, struct Sequence * seq);
+void sort_seq(struct Scene *scene);
+void build_seqar_cb(struct ListBase *seqbase, struct Sequence  ***seqar, int *totseq,
+                                       int (*test_func)(struct Sequence * seq));
+int evaluate_seq_frame(struct Scene *scene, int cfra);
+struct StripElem *give_stripelem(struct Sequence *seq, int cfra);
+
+// intern?
+void update_changed_seq_and_deps(struct Scene *scene, struct Sequence *changed_seq, int len_change, int ibuf_change);
+
+/* seqeffects.c */
+// intern?
+struct SeqEffectHandle get_sequence_blend(struct Sequence *seq);
+void sequence_effect_speed_rebuild_map(struct Scene *scene, struct Sequence *seq, int force);
+
+// extern
+struct SeqEffectHandle get_sequence_effect(struct Sequence *seq);
+int get_sequence_effect_num_inputs(int seq_type);
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
new file mode 100644 (file)
index 0000000..9036156
--- /dev/null
@@ -0,0 +1,3145 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): 
+ * - Blender Foundation, 2003-2009
+ * - Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+#include "PIL_dynlib.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_sequence_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BKE_global.h"
+#include "BKE_ipo.h"
+#include "BKE_plugin_types.h"
+#include "BKE_sequence.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+/* **** XXX **** */
+static void error() {}
+
+#define INT    96
+#define FLO    128
+
+/* **** XXX **** */
+
+/* Glow effect */
+enum {
+       GlowR=0,
+       GlowG=1,
+       GlowB=2,
+       GlowA=3
+};
+
+
+/* **********************************************************************
+   PLUGINS
+   ********************************************************************** */
+
+static void open_plugin_seq(PluginSeq *pis, const char *seqname)
+{
+       int (*version)();
+       void* (*alloc_private)();
+       char *cp;
+
+       /* to be sure: (is tested for) */
+       pis->doit= 0;
+       pis->pname= 0;
+       pis->varstr= 0;
+       pis->cfra= 0;
+       pis->version= 0;
+       pis->instance_private_data = 0;
+
+       /* clear the error list */
+       PIL_dynlib_get_error_as_string(NULL);
+
+       /* if(pis->handle) PIL_dynlib_close(pis->handle); */
+       /* pis->handle= 0; */
+
+       /* open the needed object */
+       pis->handle= PIL_dynlib_open(pis->name);
+       if(test_dlerr(pis->name, pis->name)) return;
+
+       if (pis->handle != 0) {
+               /* find the address of the version function */
+               version= (int (*)())PIL_dynlib_find_symbol(pis->handle, "plugin_seq_getversion");
+               if (test_dlerr(pis->name, "plugin_seq_getversion")) return;
+
+               if (version != 0) {
+                       pis->version= version();
+                       if (pis->version >= 2 && pis->version <= 6) {
+                               int (*info_func)(PluginInfo *);
+                               PluginInfo *info= (PluginInfo*) MEM_mallocN(sizeof(PluginInfo), "plugin_info");
+
+                               info_func= (int (*)(PluginInfo *))PIL_dynlib_find_symbol(pis->handle, "plugin_getinfo");
+
+                               if(info_func == NULL) error("No info func");
+                               else {
+                                       info_func(info);
+
+                                       pis->pname= info->name;
+                                       pis->vars= info->nvars;
+                                       pis->cfra= info->cfra;
+
+                                       pis->varstr= info->varstr;
+
+                                       pis->doit= (void(*)(void))info->seq_doit;
+                                       if (info->init)
+                                               info->init();
+                               }
+                               MEM_freeN(info);
+
+                               cp= PIL_dynlib_find_symbol(pis->handle, "seqname");
+                               if(cp) strncpy(cp, seqname, 21);
+                       } else {
+                               printf ("Plugin returned unrecognized version number\n");
+                               return;
+                       }
+               }
+               alloc_private = (void* (*)())PIL_dynlib_find_symbol(
+                       pis->handle, "plugin_seq_alloc_private_data");
+               if (alloc_private) {
+                       pis->instance_private_data = alloc_private();
+               }
+               
+               pis->current_private_data = (void**) 
+                       PIL_dynlib_find_symbol(
+                               pis->handle, "plugin_private_data");
+       }
+}
+
+static PluginSeq *add_plugin_seq(const char *str, const char *seqname)
+{
+       PluginSeq *pis;
+       VarStruct *varstr;
+       int a;
+
+       pis= MEM_callocN(sizeof(PluginSeq), "PluginSeq");
+
+       strncpy(pis->name, str, FILE_MAXDIR+FILE_MAXFILE);
+       open_plugin_seq(pis, seqname);
+
+       if(pis->doit==0) {
+               if(pis->handle==0) error("no plugin: %s", str);
+               else error("in plugin: %s", str);
+               MEM_freeN(pis);
+               return 0;
+       }
+
+       /* default values */
+       varstr= pis->varstr;
+       for(a=0; a<pis->vars; a++, varstr++) {
+               if( (varstr->type & FLO)==FLO)
+                       pis->data[a]= varstr->def;
+               else if( (varstr->type & INT)==INT)
+                       *((int *)(pis->data+a))= (int) varstr->def;
+       }
+
+       return pis;
+}
+
+static void free_plugin_seq(PluginSeq *pis)
+{
+       if(pis==0) return;
+
+       /* no PIL_dynlib_close: same plugin can be opened multiple times with 1 handle */
+
+       if (pis->instance_private_data) {
+               void (*free_private)(void *);
+
+               free_private = (void (*)(void *))PIL_dynlib_find_symbol(
+                       pis->handle, "plugin_seq_free_private_data");
+               if (free_private) {
+                       free_private(pis->instance_private_data);
+               }
+       }
+
+       MEM_freeN(pis);
+}
+
+static void init_plugin(Sequence * seq, const char * fname)
+{
+       seq->plugin= (PluginSeq *)add_plugin_seq(fname, seq->name+2);
+}
+
+/* 
+ * FIXME: should query plugin! Could be generator, that needs zero inputs...
+ */
+static int num_inputs_plugin()
+{
+       return 1;
+}
+
+static void load_plugin(Sequence * seq)
+{
+       if (seq) {
+               open_plugin_seq(seq->plugin, seq->name+2);
+       }
+}
+
+static void copy_plugin(Sequence * dst, Sequence * src)
+{
+       if(src->plugin) {
+               dst->plugin= MEM_dupallocN(src->plugin);
+               open_plugin_seq(dst->plugin, dst->name+2);
+       }
+}
+
+static ImBuf * IMB_cast_away_list(ImBuf * i)
+{
+       if (!i) {
+               return 0;
+       }
+       return (ImBuf*) (((void**) i) + 2);
+}
+
+static void do_plugin_effect(Sequence * seq,int cfra,
+                            float facf0, float facf1, int x, int y, 
+                            struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
+                            struct ImBuf *ibuf3, struct ImBuf *out)
+{
+       char *cp;
+       int float_rendering;
+       int use_temp_bufs = 0; /* Are needed since blur.c (and maybe some other
+                                 old plugins) do very bad stuff
+                                 with imbuf-internals */
+
+       if(seq->plugin && seq->plugin->doit) {
+               
+               if(seq->plugin->cfra) 
+                       *(seq->plugin->cfra)= cfra;
+// XXX                 *(seq->plugin->cfra)= frame_to_float(scene, cfra);
+               
+               cp = PIL_dynlib_find_symbol(
+                       seq->plugin->handle, "seqname");
+
+               if(cp) strncpy(cp, seq->name+2, 22);
+
+               if (seq->plugin->current_private_data) {
+                       *seq->plugin->current_private_data 
+                               = seq->plugin->instance_private_data;
+               }
+
+               float_rendering = (out->rect_float != NULL);
+
+               if (seq->plugin->version<=3 && float_rendering) {
+                       use_temp_bufs = 1;
+
+                       if (ibuf1) {
+                               ibuf1 = IMB_dupImBuf(ibuf1);
+                               IMB_rect_from_float(ibuf1);
+                               imb_freerectfloatImBuf(ibuf1);
+                               ibuf1->flags &= ~IB_rectfloat;
+                       }
+                       if (ibuf2) {
+                               ibuf2 = IMB_dupImBuf(ibuf2);
+                               IMB_rect_from_float(ibuf2);
+                               imb_freerectfloatImBuf(ibuf2);
+                               ibuf2->flags &= ~IB_rectfloat;
+                       } 
+                       if (ibuf3) {
+                               ibuf3 = IMB_dupImBuf(ibuf3);
+                               IMB_rect_from_float(ibuf3);
+                               imb_freerectfloatImBuf(ibuf3);
+                               ibuf3->flags &= ~IB_rectfloat;
+                       } 
+                       if (!out->rect) imb_addrectImBuf(out);
+                       imb_freerectfloatImBuf(out);
+                       out->flags &= ~IB_rectfloat;
+               }
+
+               if (seq->plugin->version<=2) {
+                       if(ibuf1) IMB_convert_rgba_to_abgr(ibuf1);
+                       if(ibuf2) IMB_convert_rgba_to_abgr(ibuf2);
+                       if(ibuf3) IMB_convert_rgba_to_abgr(ibuf3);
+               }
+
+               if (seq->plugin->version<=4) {
+                       ((SeqDoit)seq->plugin->doit)(
+                               seq->plugin->data, facf0, facf1, x, y,
+                               IMB_cast_away_list(ibuf1), 
+                               IMB_cast_away_list(ibuf2), 
+                               IMB_cast_away_list(out), 
+                               IMB_cast_away_list(ibuf3));
+               } else {
+                       ((SeqDoit)seq->plugin->doit)(
+                               seq->plugin->data, facf0, facf1, x, y,
+                               ibuf1, ibuf2, out, ibuf3);
+               }
+
+               if (seq->plugin->version<=2) {
+                       if (!use_temp_bufs) {
+                               if(ibuf1) IMB_convert_rgba_to_abgr(ibuf1);
+                               if(ibuf2) IMB_convert_rgba_to_abgr(ibuf2);
+                               if(ibuf3) IMB_convert_rgba_to_abgr(ibuf3);
+                       }
+                       IMB_convert_rgba_to_abgr(out);
+               }
+               if (seq->plugin->version<=3 && float_rendering) {
+                       IMB_float_from_rect(out);
+               }
+
+               if (use_temp_bufs) {
+                       if (ibuf1) IMB_freeImBuf(ibuf1);
+                       if (ibuf2) IMB_freeImBuf(ibuf2);
+                       if (ibuf3) IMB_freeImBuf(ibuf3);
+               }
+       }
+}
+
+static int do_plugin_early_out(struct Sequence *seq,
+                              float facf0, float facf1)
+{
+       return 0;
+}
+
+static void free_plugin(struct Sequence * seq)
+{
+       free_plugin_seq(seq->plugin);
+       seq->plugin = 0;
+}
+
+/* **********************************************************************
+   ALPHA OVER
+   ********************************************************************** */
+
+static void init_alpha_over_or_under(Sequence * seq)
+{
+       Sequence * seq1 = seq->seq1;
+       Sequence * seq2 = seq->seq2;
+
+       seq->seq2= seq1;
+       seq->seq1= seq2;
+}
+
+static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y, 
+                                    char * rect1, char *rect2, char *out)
+{
+       int fac2, mfac, fac, fac4;
+       int xo, tempc;
+       char *rt1, *rt2, *rt;
+
+       xo= x;
+       rt1= (char *)rect1;
+       rt2= (char *)rect2;
+       rt= (char *)out;
+
+       fac2= (int)(256.0*facf0);
+       fac4= (int)(256.0*facf1);
+
+       while(y--) {
+
+               x= xo;
+               while(x--) {
+
+                       /* rt = rt1 over rt2  (alpha from rt1) */
+
+                       fac= fac2;
+                       mfac= 256 - ( (fac2*rt1[3])>>8 );
+
+                       if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+                       else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+                       else {
+                               tempc= ( fac*rt1[0] + mfac*rt2[0])>>8;
+                               if(tempc>255) rt[0]= 255; else rt[0]= tempc;
+                               tempc= ( fac*rt1[1] + mfac*rt2[1])>>8;
+                               if(tempc>255) rt[1]= 255; else rt[1]= tempc;
+                               tempc= ( fac*rt1[2] + mfac*rt2[2])>>8;
+                               if(tempc>255) rt[2]= 255; else rt[2]= tempc;
+                               tempc= ( fac*rt1[3] + mfac*rt2[3])>>8;
+                               if(tempc>255) rt[3]= 255; else rt[3]= tempc;
+                       }
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+
+               if(y==0) break;
+               y--;
+
+               x= xo;
+               while(x--) {
+
+                       fac= fac4;
+                       mfac= 256 - ( (fac4*rt1[3])>>8 );
+
+                       if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+                       else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+                       else {
+                               tempc= ( fac*rt1[0] + mfac*rt2[0])>>8;
+                               if(tempc>255) rt[0]= 255; else rt[0]= tempc;
+                               tempc= ( fac*rt1[1] + mfac*rt2[1])>>8;
+                               if(tempc>255) rt[1]= 255; else rt[1]= tempc;
+                               tempc= ( fac*rt1[2] + mfac*rt2[2])>>8;
+                               if(tempc>255) rt[2]= 255; else rt[2]= tempc;
+                               tempc= ( fac*rt1[3] + mfac*rt2[3])>>8;
+                               if(tempc>255) rt[3]= 255; else rt[3]= tempc;
+                       }
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+       }
+}
+
+static void do_alphaover_effect_float(float facf0, float facf1, int x, int y, 
+                                     float * rect1, float *rect2, float *out)
+{
+       float fac2, mfac, fac, fac4;
+       int xo;
+       float *rt1, *rt2, *rt;
+
+       xo= x;
+       rt1= rect1;
+       rt2= rect2;
+       rt= out;
+
+       fac2= facf0;
+       fac4= facf1;
+
+       while(y--) {
+
+               x= xo;
+               while(x--) {
+
+                       /* rt = rt1 over rt2  (alpha from rt1) */
+
+                       fac= fac2;
+                       mfac= 1.0 - (fac2*rt1[3]) ;
+
+                       if(fac <= 0.0) {
+                               memcpy(rt, rt2, 4 * sizeof(float));
+                       } else if(mfac <=0) {
+                               memcpy(rt, rt1, 4 * sizeof(float));
+                       } else {
+                               rt[0] = fac*rt1[0] + mfac*rt2[0];
+                               rt[1] = fac*rt1[1] + mfac*rt2[1];
+                               rt[2] = fac*rt1[2] + mfac*rt2[2];
+                               rt[3] = fac*rt1[3] + mfac*rt2[3];
+                       }
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+
+               if(y==0) break;
+               y--;
+
+               x= xo;
+               while(x--) {
+
+                       fac= fac4;
+                       mfac= 1.0 - (fac4*rt1[3]);
+
+                       if(fac <= 0.0) {
+                               memcpy(rt, rt2, 4 * sizeof(float));
+                       } else if(mfac <= 0.0) {
+                               memcpy(rt, rt1, 4 * sizeof(float));
+                       } else {
+                               rt[0] = fac*rt1[0] + mfac*rt2[0];
+                               rt[1] = fac*rt1[1] + mfac*rt2[1];
+                               rt[2] = fac*rt1[2] + mfac*rt2[2];
+                               rt[3] = fac*rt1[3] + mfac*rt2[3];
+                       }
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+       }
+}
+
+static void do_alphaover_effect(Sequence * seq,int cfra,
+                               float facf0, float facf1, int x, int y, 
+                               struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
+                               struct ImBuf *ibuf3, struct ImBuf *out)
+{
+       if (out->rect_float) {
+               do_alphaover_effect_float(
+                       facf0, facf1, x, y,
+                       ibuf1->rect_float, ibuf2->rect_float,
+                       out->rect_float);
+       } else {
+               do_alphaover_effect_byte(
+                       facf0, facf1, x, y,
+                       (char*) ibuf1->rect, (char*) ibuf2->rect,
+                       (char*) out->rect);
+       }
+}
+
+
+/* **********************************************************************
+   ALPHA UNDER
+   ********************************************************************** */
+
+void do_alphaunder_effect_byte(
+       float facf0, float facf1, int x, int y, char *rect1, 
+       char *rect2, char *out)
+{
+       int fac2, mfac, fac, fac4;
+       int xo;
+       char *rt1, *rt2, *rt;
+
+       xo= x;
+       rt1= rect1;
+       rt2= rect2;
+       rt= out;
+
+       fac2= (int)(256.0*facf0);
+       fac4= (int)(256.0*facf1);
+
+       while(y--) {
+
+               x= xo;
+               while(x--) {
+
+                       /* rt = rt1 under rt2  (alpha from rt2) */
+
+                       /* this complex optimalisation is because the
+                        * 'skybuf' can be crossed in
+                        */
+                       if(rt2[3]==0 && fac2==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+                       else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+                       else {
+                               mfac= rt2[3];
+                               fac= (fac2*(256-mfac))>>8;
+
+                               if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+                               else {
+                                       rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8;
+                                       rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8;
+                                       rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8;
+                                       rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8;
+                               }
+                       }
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+
+               if(y==0) break;
+               y--;
+
+               x= xo;
+               while(x--) {
+
+                       if(rt2[3]==0 && fac4==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+                       else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+                       else {
+                               mfac= rt2[3];
+                               fac= (fac4*(256-mfac))>>8;
+
+                               if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+                               else {
+                                       rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8;
+                                       rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8;
+                                       rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8;
+                                       rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8;
+                               }
+                       }
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+       }
+}
+
+
+static void do_alphaunder_effect_float(float facf0, float facf1, int x, int y, 
+                                      float *rect1, float *rect2, 
+                                      float *out)
+{
+       float fac2, mfac, fac, fac4;
+       int xo;
+       float *rt1, *rt2, *rt;
+
+       xo= x;
+       rt1= rect1;
+       rt2= rect2;
+       rt= out;
+
+       fac2= facf0;
+       fac4= facf1;
+
+       while(y--) {
+
+               x= xo;
+               while(x--) {
+
+                       /* rt = rt1 under rt2  (alpha from rt2) */
+
+                       /* this complex optimalisation is because the
+                        * 'skybuf' can be crossed in
+                        */
+                       if( rt2[3]<=0 && fac2>=1.0) {
+                               memcpy(rt, rt1, 4 * sizeof(float));
+                       } else if(rt2[3]>=1.0) {
+                               memcpy(rt, rt2, 4 * sizeof(float));
+                       } else {
+                               mfac = rt2[3];
+                               fac = fac2 * (1.0 - mfac);
+
+                               if(fac == 0) {
+                                       memcpy(rt, rt2, 4 * sizeof(float));
+                               } else {
+                                       rt[0]= fac*rt1[0] + mfac*rt2[0];
+                                       rt[1]= fac*rt1[1] + mfac*rt2[1];
+                                       rt[2]= fac*rt1[2] + mfac*rt2[2];
+                                       rt[3]= fac*rt1[3] + mfac*rt2[3];
+                               }
+                       }
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+
+               if(y==0) break;
+               y--;
+
+               x= xo;
+               while(x--) {
+
+                       if(rt2[3]<=0 && fac4 >= 1.0) {
+                               memcpy(rt, rt1, 4 * sizeof(float));
+                       } else if(rt2[3]>=1.0) {
+                               memcpy(rt, rt2, 4 * sizeof(float));
+                       } else {
+                               mfac= rt2[3];
+                               fac= fac4*(1.0-mfac);
+
+                               if(fac == 0) {
+                                       memcpy(rt, rt2, 4 * sizeof(float));
+                               } else {
+                                       rt[0]= fac * rt1[0] + mfac * rt2[0];
+                                       rt[1]= fac * rt1[1] + mfac * rt2[1];
+                                       rt[2]= fac * rt1[2] + mfac * rt2[2];
+                                       rt[3]= fac * rt1[3] + mfac * rt2[3];
+                               }
+                       }
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+       }
+}
+
+static void do_alphaunder_effect(Sequence * seq,int cfra,
+                               float facf0, float facf1, int x, int y, 
+                               struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
+                               struct ImBuf *ibuf3, struct ImBuf *out)
+{
+       if (out->rect_float) {
+               do_alphaunder_effect_float(
+                       facf0, facf1, x, y,
+                       ibuf1->rect_float, ibuf2->rect_float,
+                       out->rect_float);
+       } else {
+               do_alphaunder_effect_byte(
+                       facf0, facf1, x, y,
+                       (char*) ibuf1->rect, (char*) ibuf2->rect,
+                       (char*) out->rect);
+       }
+}
+
+
+/* **********************************************************************
+   CROSS
+   ********************************************************************** */
+
+void do_cross_effect_byte(float facf0, float facf1, int x, int y, 
+                         char *rect1, char *rect2, 
+                         char *out)
+{
+       int fac1, fac2, fac3, fac4;
+       int xo;
+       char *rt1, *rt2, *rt;
+
+       xo= x;
+       rt1= rect1;
+       rt2= rect2;
+       rt= out;
+
+       fac2= (int)(256.0*facf0);
+       fac1= 256-fac2;
+       fac4= (int)(256.0*facf1);
+       fac3= 256-fac4;
+
+       while(y--) {
+
+               x= xo;
+               while(x--) {
+
+                       rt[0]= (fac1*rt1[0] + fac2*rt2[0])>>8;
+                       rt[1]= (fac1*rt1[1] + fac2*rt2[1])>>8;
+                       rt[2]= (fac1*rt1[2] + fac2*rt2[2])>>8;
+                       rt[3]= (fac1*rt1[3] + fac2*rt2[3])>>8;
+
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+
+               if(y==0) break;
+               y--;
+
+               x= xo;
+               while(x--) {
+
+                       rt[0]= (fac3*rt1[0] + fac4*rt2[0])>>8;
+                       rt[1]= (fac3*rt1[1] + fac4*rt2[1])>>8;
+                       rt[2]= (fac3*rt1[2] + fac4*rt2[2])>>8;
+                       rt[3]= (fac3*rt1[3] + fac4*rt2[3])>>8;
+
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+
+       }
+}
+
+void do_cross_effect_float(float facf0, float facf1, int x, int y, 
+                          float *rect1, float *rect2, float *out)
+{
+       float fac1, fac2, fac3, fac4;
+       int xo;
+       float *rt1, *rt2, *rt;
+
+       xo= x;
+       rt1= rect1;
+       rt2= rect2;
+       rt= out;
+
+       fac2= facf0;
+       fac1= 1.0 - fac2;
+       fac4= facf1;
+       fac3= 1.0 - fac4;
+
+       while(y--) {
+
+               x= xo;
+               while(x--) {
+
+                       rt[0]= fac1*rt1[0] + fac2*rt2[0];
+                       rt[1]= fac1*rt1[1] + fac2*rt2[1];
+                       rt[2]= fac1*rt1[2] + fac2*rt2[2];
+                       rt[3]= fac1*rt1[3] + fac2*rt2[3];
+
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+
+               if(y==0) break;
+               y--;
+
+               x= xo;
+               while(x--) {
+
+                       rt[0]= fac3*rt1[0] + fac4*rt2[0];
+                       rt[1]= fac3*rt1[1] + fac4*rt2[1];
+                       rt[2]= fac3*rt1[2] + fac4*rt2[2];
+                       rt[3]= fac3*rt1[3] + fac4*rt2[3];
+
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+
+       }
+}
+
+/* carefull: also used by speed effect! */
+
+static void do_cross_effect(Sequence * seq,int cfra,
+                           float facf0, float facf1, int x, int y, 
+                           struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
+                           struct ImBuf *ibuf3, struct ImBuf *out)
+{
+       if (out->rect_float) {
+               do_cross_effect_float(
+                       facf0, facf1, x, y,
+                       ibuf1->rect_float, ibuf2->rect_float,
+                       out->rect_float);
+       } else {
+               do_cross_effect_byte(
+                       facf0, facf1, x, y,
+                       (char*) ibuf1->rect, (char*) ibuf2->rect,
+                       (char*) out->rect);
+       }
+}
+
+
+/* **********************************************************************
+   GAMMA CROSS
+   ********************************************************************** */
+
+/* copied code from initrender.c */
+static unsigned short gamtab[65536];
+static unsigned short igamtab1[256];
+static int gamma_tabs_init = FALSE;
+
+#define RE_GAMMA_TABLE_SIZE 400
+
+static float gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
+static float gamfactor_table[RE_GAMMA_TABLE_SIZE];
+static float inv_gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
+static float inv_gamfactor_table[RE_GAMMA_TABLE_SIZE];
+static float color_domain_table[RE_GAMMA_TABLE_SIZE + 1]; 
+static float color_step;
+static float inv_color_step;
+static float valid_gamma;
+static float valid_inv_gamma;
+
+static void makeGammaTables(float gamma)
+{
+       /* we need two tables: one forward, one backward */
+       int i;
+
+       valid_gamma        = gamma;
+       valid_inv_gamma    = 1.0 / gamma;
+       color_step        = 1.0 / RE_GAMMA_TABLE_SIZE;
+       inv_color_step    = (float) RE_GAMMA_TABLE_SIZE; 
+
+       /* We could squeeze out the two range tables to gain some memory.        */     
+       for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) {
+               color_domain_table[i]   = i * color_step;
+               gamma_range_table[i]     = pow(color_domain_table[i],
+                                                                               valid_gamma);
+               inv_gamma_range_table[i] = pow(color_domain_table[i],
+                                                                               valid_inv_gamma);
+       }
+
+       /* The end of the table should match 1.0 carefully. In order to avoid    */
+       /* rounding errors, we just set this explicitly. The last segment may    */
+       /* have a different lenght than the other segments, but our              */
+       /* interpolation is insensitive to that.                                 */
+       color_domain_table[RE_GAMMA_TABLE_SIZE]   = 1.0;
+       gamma_range_table[RE_GAMMA_TABLE_SIZE]     = 1.0;
+       inv_gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0;
+
+       /* To speed up calculations, we make these calc factor tables. They are  */
+       /* multiplication factors used in scaling the interpolation.             */
+       for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++ ) {
+               gamfactor_table[i] = inv_color_step
+                       * (gamma_range_table[i + 1] - gamma_range_table[i]) ;
+               inv_gamfactor_table[i] = inv_color_step
+                       * (inv_gamma_range_table[i + 1] - inv_gamma_range_table[i]) ;
+       }
+
+} /* end of void makeGammaTables(float gamma) */
+
+
+static float gammaCorrect(float c)
+{
+       int i;
+       float res = 0.0;
+       
+       i = floor(c * inv_color_step);
+       /* Clip to range [0,1]: outside, just do the complete calculation.       */
+       /* We may have some performance problems here. Stretching up the LUT     */
+       /* may help solve that, by exchanging LUT size for the interpolation.    */
+       /* Negative colors are explicitly handled.                              */
+       if (i < 0) res = -pow(abs(c), valid_gamma);
+       else if (i >= RE_GAMMA_TABLE_SIZE ) res = pow(c, valid_gamma);
+       else res = gamma_range_table[i] + 
+                        ( (c - color_domain_table[i]) * gamfactor_table[i]); 
+       
+       return res;
+} /* end of float gammaCorrect(float col) */
+
+/* ------------------------------------------------------------------------- */
+
+static float invGammaCorrect(float col)
+{
+       int i;
+       float res = 0.0;
+
+       i = floor(col*inv_color_step);
+       /* Negative colors are explicitly handled.                              */
+       if (i < 0) res = -pow(abs(col), valid_inv_gamma);
+       else if (i >= RE_GAMMA_TABLE_SIZE) res = pow(col, valid_inv_gamma);
+       else res = inv_gamma_range_table[i] + 
+                        ( (col - color_domain_table[i]) * inv_gamfactor_table[i]);
+       return res;
+} /* end of float invGammaCorrect(float col) */
+
+
+static void gamtabs(float gamma)
+{
+       float val, igamma= 1.0f/gamma;
+       int a;
+       
+       /* gamtab: in short, out short */
+       for(a=0; a<65536; a++) {
+               val= a;
+               val/= 65535.0;
+               
+               if(gamma==2.0) val= sqrt(val);
+               else if(gamma!=1.0) val= pow(val, igamma);
+               
+               gamtab[a]= (65535.99*val);
+       }
+       /* inverse gamtab1 : in byte, out short */
+       for(a=1; a<=256; a++) {
+               if(gamma==2.0) igamtab1[a-1]= a*a-1;
+               else if(gamma==1.0) igamtab1[a-1]= 256*a-1;
+               else {
+                       val= a/256.0;
+                       igamtab1[a-1]= (65535.0*pow(val, gamma)) -1 ;
+               }
+       }
+
+}
+
+static void build_gammatabs()
+{
+       if (gamma_tabs_init == FALSE) {
+               gamtabs(2.0f);
+               makeGammaTables(2.0f);
+               gamma_tabs_init = TRUE;
+       }
+}
+
+static void init_gammacross(Sequence * seq)
+{
+}
+
+static void load_gammacross(Sequence * seq)
+{
+}
+
+static void free_gammacross(Sequence * seq)
+{
+}
+
+static void do_gammacross_effect_byte(float facf0, float facf1, 
+                                     int x, int y, 
+                                     char *rect1, 
+                                     char *rect2, 
+                                     char *out)
+{
+       int fac1, fac2, col;
+       int xo;
+       char *rt1, *rt2, *rt;
+       
+       xo= x;
+       rt1= (char *)rect1;
+       rt2= (char *)rect2;
+       rt= (char *)out;
+
+       fac2= (int)(256.0*facf0);
+       fac1= 256-fac2;
+
+       while(y--) {
+
+               x= xo;
+               while(x--) {
+
+                       col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8;
+                       if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+                       col=(fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8;
+                       if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+                       col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8;
+                       if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+                       col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8;
+                       if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+
+               if(y==0) break;
+               y--;
+
+               x= xo;
+               while(x--) {
+
+                       col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8;
+                       if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+                       col= (fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8;
+                       if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+                       col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8;
+                       if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+                       col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8;
+                       if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+       }
+
+}
+
+static void do_gammacross_effect_float(float facf0, float facf1, 
+                                      int x, int y, 
+                                      float *rect1, float *rect2, 
+                                      float *out)
+{
+       float fac1, fac2;
+       int xo;
+       float *rt1, *rt2, *rt;
+
+       xo= x;
+       rt1= rect1;
+       rt2= rect2;
+       rt= out;
+
+       fac2= facf0;
+       fac1= 1.0 - fac2;
+
+       while(y--) {
+
+               x= xo * 4;
+               while(x--) {
+
+                       *rt= gammaCorrect(
+                               fac1 * invGammaCorrect(*rt1) 
+                               + fac2 * invGammaCorrect(*rt2));
+                       rt1++; rt2++; rt++;
+               }
+
+               if(y==0) break;
+               y--;
+
+               x= xo * 4;
+               while(x--) {
+
+                       *rt= gammaCorrect(
+                               fac1*invGammaCorrect(*rt1) 
+                               + fac2*invGammaCorrect(*rt2));
+
+                       rt1++; rt2++; rt++;
+               }
+       }
+}
+
+static void do_gammacross_effect(Sequence * seq,int cfra,
+                                float facf0, float facf1, int x, int y, 
+                                struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
+                                struct ImBuf *ibuf3, struct ImBuf *out)
+{
+       build_gammatabs();
+
+       if (out->rect_float) {
+               do_gammacross_effect_float(
+                       facf0, facf1, x, y,
+                       ibuf1->rect_float, ibuf2->rect_float,
+                       out->rect_float);
+       } else {
+               do_gammacross_effect_byte(
+                       facf0, facf1, x, y,
+                       (char*) ibuf1->rect, (char*) ibuf2->rect,
+                       (char*) out->rect);
+       }
+}
+
+
+/* **********************************************************************
+   ADD
+   ********************************************************************** */
+
+static void do_add_effect_byte(float facf0, float facf1, int x, int y, 
+                              unsigned char *rect1, unsigned char *rect2, 
+                              unsigned char *out)
+{
+       int col, xo, fac1, fac3;
+       char *rt1, *rt2, *rt;
+
+       xo= x;
+       rt1= (char *)rect1;
+       rt2= (char *)rect2;
+       rt= (char *)out;
+
+       fac1= (int)(256.0*facf0);
+       fac3= (int)(256.0*facf1);
+
+       while(y--) {
+
+               x= xo;
+               while(x--) {
+
+                       col= rt1[0]+ ((fac1*rt2[0])>>8);
+                       if(col>255) rt[0]= 255; else rt[0]= col;
+                       col= rt1[1]+ ((fac1*rt2[1])>>8);
+                       if(col>255) rt[1]= 255; else rt[1]= col;
+                       col= rt1[2]+ ((fac1*rt2[2])>>8);
+                       if(col>255) rt[2]= 255; else rt[2]= col;
+                       col= rt1[3]+ ((fac1*rt2[3])>>8);
+                       if(col>255) rt[3]= 255; else rt[3]= col;
+
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+
+               if(y==0) break;
+               y--;
+
+               x= xo;
+               while(x--) {
+
+                       col= rt1[0]+ ((fac3*rt2[0])>>8);
+                       if(col>255) rt[0]= 255; else rt[0]= col;
+                       col= rt1[1]+ ((fac3*rt2[1])>>8);
+                       if(col>255) rt[1]= 255; else rt[1]= col;
+                       col= rt1[2]+ ((fac3*rt2[2])>>8);
+                       if(col>255) rt[2]= 255; else rt[2]= col;
+                       col= rt1[3]+ ((fac3*rt2[3])>>8);
+                       if(col>255) rt[3]= 255; else rt[3]= col;
+
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+       }
+}
+
+static void do_add_effect_float(float facf0, float facf1, int x, int y, 
+                               float *rect1, float *rect2, 
+                               float *out)
+{
+       int xo;
+       float fac1, fac3;
+       float *rt1, *rt2, *rt;
+
+       xo= x;
+       rt1= rect1;
+       rt2= rect2;
+       rt= out;
+
+       fac1= facf0;
+       fac3= facf1;
+
+       while(y--) {
+
+               x= xo * 4;
+               while(x--) {
+                       *rt = *rt1 + fac1 * (*rt2);
+
+                       rt1++; rt2++; rt++;
+               }
+
+               if(y==0) break;
+               y--;
+
+               x= xo * 4;
+               while(x--) {
+                       *rt = *rt1 + fac3 * (*rt2);
+
+                       rt1++; rt2++; rt++;
+               }
+       }
+}
+
+static void do_add_effect(Sequence * seq,int cfra,
+                         float facf0, float facf1, int x, int y, 
+                         struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
+                         struct ImBuf *ibuf3, struct ImBuf *out)
+{
+       if (out->rect_float) {
+               do_add_effect_float(
+                       facf0, facf1, x, y,
+                       ibuf1->rect_float, ibuf2->rect_float,
+                       out->rect_float);
+       } else {
+               do_add_effect_byte(
+                       facf0, facf1, x, y,
+                       (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect,
+                       (unsigned char*) out->rect);
+       }
+}
+
+
+/* **********************************************************************
+   SUB
+   ********************************************************************** */
+
+static void do_sub_effect_byte(float facf0, float facf1, 
+                              int x, int y, 
+                              char *rect1, char *rect2, char *out)
+{
+       int col, xo, fac1, fac3;
+       char *rt1, *rt2, *rt;
+
+       xo= x;
+       rt1= (char *)rect1;
+       rt2= (char *)rect2;
+       rt= (char *)out;
+
+       fac1= (int)(256.0*facf0);
+       fac3= (int)(256.0*facf1);
+
+       while(y--) {
+
+               x= xo;
+               while(x--) {
+
+                       col= rt1[0]- ((fac1*rt2[0])>>8);
+                       if(col<0) rt[0]= 0; else rt[0]= col;
+                       col= rt1[1]- ((fac1*rt2[1])>>8);
+                       if(col<0) rt[1]= 0; else rt[1]= col;
+                       col= rt1[2]- ((fac1*rt2[2])>>8);
+                       if(col<0) rt[2]= 0; else rt[2]= col;
+                       col= rt1[3]- ((fac1*rt2[3])>>8);
+                       if(col<0) rt[3]= 0; else rt[3]= col;
+
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+
+               if(y==0) break;
+               y--;
+
+               x= xo;
+               while(x--) {
+
+                       col= rt1[0]- ((fac3*rt2[0])>>8);
+                       if(col<0) rt[0]= 0; else rt[0]= col;
+                       col= rt1[1]- ((fac3*rt2[1])>>8);
+                       if(col<0) rt[1]= 0; else rt[1]= col;
+                       col= rt1[2]- ((fac3*rt2[2])>>8);
+                       if(col<0) rt[2]= 0; else rt[2]= col;
+                       col= rt1[3]- ((fac3*rt2[3])>>8);
+                       if(col<0) rt[3]= 0; else rt[3]= col;
+
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+       }
+}
+
+static void do_sub_effect_float(float facf0, float facf1, int x, int y, 
+                               float *rect1, float *rect2, 
+                               float *out)
+{
+       int xo;
+       float fac1, fac3;
+       float *rt1, *rt2, *rt;
+
+       xo= x;
+       rt1= rect1;
+       rt2= rect2;
+       rt= out;
+
+       fac1= facf0;
+       fac3= facf1;
+
+       while(y--) {
+
+               x= xo * 4;
+               while(x--) {
+                       *rt = *rt1 - fac1 * (*rt2);
+
+                       rt1++; rt2++; rt++;
+               }
+
+               if(y==0) break;
+               y--;
+
+               x= xo * 4;
+               while(x--) {
+                       *rt = *rt1 - fac3 * (*rt2);
+
+                       rt1++; rt2++; rt++;
+               }
+       }
+}
+
+static void do_sub_effect(Sequence * seq,int cfra,
+                         float facf0, float facf1, int x, int y, 
+                         struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
+                         struct ImBuf *ibuf3, struct ImBuf *out)
+{
+       if (out->rect_float) {
+               do_sub_effect_float(
+                       facf0, facf1, x, y,
+                       ibuf1->rect_float, ibuf2->rect_float,
+                       out->rect_float);
+       } else {
+               do_sub_effect_byte(
+                       facf0, facf1, x, y,
+                       (char*) ibuf1->rect, (char*) ibuf2->rect,
+                       (char*) out->rect);
+       }
+}
+
+/* **********************************************************************
+   DROP
+   ********************************************************************** */
+
+/* Must be > 0 or add precopy, etc to the function */
+#define XOFF   8
+#define YOFF   8
+
+static void do_drop_effect_byte(float facf0, float facf1, int x, int y, 
+                               unsigned char *rect2i, unsigned char *rect1i, 
+                               unsigned char *outi)
+{
+       int height, width, temp, fac, fac1, fac2;
+       char *rt1, *rt2, *out;
+       int field= 1;
+
+       width= x;
+       height= y;
+
+       fac1= (int)(70.0*facf0);
+       fac2= (int)(70.0*facf1);
+
+       rt2= (char*) (rect2i + YOFF*width);
+       rt1= (char*) rect1i;
+       out= (char*) outi;
+       for (y=0; y<height-YOFF; y++) {
+               if(field) fac= fac1;
+               else fac= fac2;
+               field= !field;
+
+               memcpy(out, rt1, sizeof(int)*XOFF);
+               rt1+= XOFF*4;
+               out+= XOFF*4;
+
+               for (x=XOFF; x<width; x++) {
+                       temp= ((fac*rt2[3])>>8);
+
+                       *(out++)= MAX2(0, *rt1 - temp); rt1++;
+                       *(out++)= MAX2(0, *rt1 - temp); rt1++;
+                       *(out++)= MAX2(0, *rt1 - temp); rt1++;
+                       *(out++)= MAX2(0, *rt1 - temp); rt1++;
+                       rt2+=4;
+               }
+               rt2+=XOFF*4;
+       }
+       memcpy(out, rt1, sizeof(int)*YOFF*width);
+}
+
+static void do_drop_effect_float(float facf0, float facf1, int x, int y, 
+                                float *rect2i, float *rect1i, 
+                                float *outi)
+{
+       int height, width;
+       float temp, fac, fac1, fac2;
+       float *rt1, *rt2, *out;
+       int field= 1;
+
+       width= x;
+       height= y;
+
+       fac1= 70.0*facf0;
+       fac2= 70.0*facf1;
+
+       rt2=  (rect2i + YOFF*width);
+       rt1=  rect1i;
+       out=  outi;
+       for (y=0; y<height-YOFF; y++) {
+               if(field) fac= fac1;
+               else fac= fac2;
+               field= !field;
+
+               memcpy(out, rt1, 4 * sizeof(float)*XOFF);
+               rt1+= XOFF*4;
+               out+= XOFF*4;
+
+               for (x=XOFF; x<width; x++) {
+                       temp= fac * rt2[3];
+
+                       *(out++)= MAX2(0.0, *rt1 - temp); rt1++;
+                       *(out++)= MAX2(0.0, *rt1 - temp); rt1++;
+                       *(out++)= MAX2(0.0, *rt1 - temp); rt1++;
+                       *(out++)= MAX2(0.0, *rt1 - temp); rt1++;
+                       rt2+=4;
+               }
+               rt2+=XOFF*4;
+       }
+       memcpy(out, rt1, 4 * sizeof(float)*YOFF*width);
+}
+
+
+static void do_drop_effect(Sequence * seq,int cfra,
+                          float facf0, float facf1, int x, int y, 
+                          struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
+                          struct ImBuf * ibuf3,
+                          struct ImBuf *out)
+{
+       if (out->rect_float) {
+               do_drop_effect_float(
+                       facf0, facf1, x, y,
+                       ibuf1->rect_float, ibuf2->rect_float,
+                       out->rect_float);
+       } else {
+               do_drop_effect_byte(
+                       facf0, facf1, x, y,
+                       (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect,
+                       (unsigned char*) out->rect);
+       }
+}
+
+/* **********************************************************************
+   MUL
+   ********************************************************************** */
+
+static void do_mul_effect_byte(float facf0, float facf1, int x, int y, 
+                              unsigned char *rect1, unsigned char *rect2, 
+                              unsigned char *out)
+{
+       int xo, fac1, fac3;
+       char *rt1, *rt2, *rt;
+
+       xo= x;
+       rt1= (char *)rect1;
+       rt2= (char *)rect2;
+       rt= (char *)out;
+
+       fac1= (int)(256.0*facf0);
+       fac3= (int)(256.0*facf1);
+
+       /* formula:
+        *              fac*(a*b) + (1-fac)*a  => fac*a*(b-1)+axaux= c*px + py*s ;//+centx
+                       yaux= -s*px + c*py;//+centy
+        */
+
+       while(y--) {
+
+               x= xo;
+               while(x--) {
+
+                       rt[0]= rt1[0] + ((fac1*rt1[0]*(rt2[0]-256))>>16);
+                       rt[1]= rt1[1] + ((fac1*rt1[1]*(rt2[1]-256))>>16);
+                       rt[2]= rt1[2] + ((fac1*rt1[2]*(rt2[2]-256))>>16);
+                       rt[3]= rt1[3] + ((fac1*rt1[3]*(rt2[3]-256))>>16);
+
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+
+               if(y==0) break;
+               y--;
+
+               x= xo;
+               while(x--) {
+
+                       rt[0]= rt1[0] + ((fac3*rt1[0]*(rt2[0]-256))>>16);
+                       rt[1]= rt1[1] + ((fac3*rt1[1]*(rt2[1]-256))>>16);
+                       rt[2]= rt1[2] + ((fac3*rt1[2]*(rt2[2]-256))>>16);
+                       rt[3]= rt1[3] + ((fac3*rt1[3]*(rt2[3]-256))>>16);
+
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+       }
+}
+
+static void do_mul_effect_float(float facf0, float facf1, int x, int y, 
+                               float *rect1, float *rect2, 
+                               float *out)
+{
+       int xo;
+       float fac1, fac3;
+       float *rt1, *rt2, *rt;
+
+       xo= x;
+       rt1= rect1;
+       rt2= rect2;
+       rt= out;
+
+       fac1= facf0;
+       fac3= facf1;
+
+       /* formula:
+        *              fac*(a*b) + (1-fac)*a  => fac*a*(b-1)+a
+        */
+
+       while(y--) {
+
+               x= xo;
+               while(x--) {
+
+                       rt[0]= rt1[0] + fac1*rt1[0]*(rt2[0]-1.0);
+                       rt[1]= rt1[1] + fac1*rt1[1]*(rt2[1]-1.0);
+                       rt[2]= rt1[2] + fac1*rt1[2]*(rt2[2]-1.0);
+                       rt[3]= rt1[3] + fac1*rt1[3]*(rt2[3]-1.0);
+
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+
+               if(y==0) break;
+               y--;
+
+               x= xo;
+               while(x--) {
+
+                       rt[0]= rt1[0] + fac3*rt1[0]*(rt2[0]-1.0);
+                       rt[1]= rt1[1] + fac3*rt1[1]*(rt2[1]-1.0);
+                       rt[2]= rt1[2] + fac3*rt1[2]*(rt2[2]-1.0);
+                       rt[3]= rt1[3] + fac3*rt1[3]*(rt2[3]-1.0);
+
+                       rt1+= 4; rt2+= 4; rt+= 4;
+               }
+       }
+}
+
+static void do_mul_effect(Sequence * seq,int cfra,
+                         float facf0, float facf1, int x, int y, 
+                         struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
+                         struct ImBuf *ibuf3, struct ImBuf *out)
+{
+       if (out->rect_float) {
+               do_mul_effect_float(
+                       facf0, facf1, x, y,
+                       ibuf1->rect_float, ibuf2->rect_float,
+                       out->rect_float);
+       } else {
+               do_mul_effect_byte(
+                       facf0, facf1, x, y,
+                       (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect,
+                       (unsigned char*) out->rect);
+       }
+}
+
+/* **********************************************************************
+   WIPE
+   ********************************************************************** */
+
+typedef struct WipeZone {
+       float angle;
+       int flip;
+       int xo, yo;
+       int width;
+       float invwidth;
+       float pythangle;
+} WipeZone;
+
+static void precalc_wipe_zone(WipeZone *wipezone, WipeVars *wipe, int xo, int yo)
+{
+       wipezone->flip = (wipe->angle < 0);
+       wipezone->angle = pow(fabs(wipe->angle)/45.0f, log(xo)/log(2.0f));
+       wipezone->xo = xo;
+       wipezone->yo = yo;
+       wipezone->width = (int)(wipe->edgeWidth*((xo+yo)/2.0f));
+       wipezone->pythangle = 1.0f/sqrt(wipe->angle*wipe->angle + 1.0f);
+
+       if(wipe->wipetype == DO_SINGLE_WIPE)
+               wipezone->invwidth = 1.0f/wipezone->width;
+       else
+               wipezone->invwidth = 1.0f/(0.5f*wipezone->width);
+}
+
+// This function calculates the blur band for the wipe effects
+static float in_band(WipeZone *wipezone,float width,float dist,float perc,int side,int dir)
+{
+       float t1,t2,alpha,percwidth;
+
+       if(width == 0)
+               return (float)side;
+
+       if(side == 1)
+               percwidth = width * perc;
+       else
+               percwidth = width * (1 - perc);
+       
+       if(width < dist)
+               return side;
+       
+       t1 = dist * wipezone->invwidth;  //percentange of width that is
+       t2 = wipezone->invwidth;  //amount of alpha per % point
+       
+       if(side == 1)
+               alpha = (t1*t2*100) + (1-perc); // add point's alpha contrib to current position in wipe
+       else
+               alpha = (1-perc) - (t1*t2*100);
+       
+       if(dir == 0)
+               alpha = 1-alpha;
+
+       return alpha;
+}
+
+static float check_zone(WipeZone *wipezone, int x, int y,
+       Sequence *seq, float facf0) 
+{
+       float posx, posy,hyp,hyp2,angle,hwidth,b1,b2,b3,pointdist;
+/*some future stuff
+float hyp3,hyp4,b4,b5     
+*/
+       float temp1,temp2,temp3,temp4; //some placeholder variables
+       int xo = wipezone->xo;
+       int yo = wipezone->yo;
+       float halfx = xo*0.5f;
+       float halfy = yo*0.5f;
+       float widthf,output=0;
+       WipeVars *wipe = (WipeVars *)seq->effectdata;
+       int width;
+
+       if(wipezone->flip) x = xo - x;
+       angle = wipezone->angle;
+
+       posy = facf0 * yo;
+
+       if(wipe->forward){
+               posx = facf0 * xo;
+               posy = facf0 * yo;
+       } else{
+               posx = xo - facf0 * xo;
+               posy = yo - facf0 * yo;
+       }
+
+       switch (wipe->wipetype) {
+               case DO_SINGLE_WIPE:
+                       width = wipezone->width;
+                       hwidth = width*0.5f;
+
+                       if(angle == 0.0f) {
+                               b1 = posy;
+                               b2 = y;
+                               hyp = fabs(y - posy);
+                       }
+                       else {
+                               b1 = posy - (-angle)*posx;
+                               b2 = y - (-angle)*x;
+                               hyp = fabs(angle*x+y+(-posy-angle*posx))*wipezone->pythangle;
+                       }
+
+                       if(angle < 0) {
+                               temp1 = b1;
+                               b1 = b2;
+                               b2 = temp1;
+                       }
+
+                       if(wipe->forward) {
+                               if(b1 < b2)
+                                       output = in_band(wipezone,width,hyp,facf0,1,1);
+                               else
+                                       output = in_band(wipezone,width,hyp,facf0,0,1);
+                       }
+                       else {
+                               if(b1 < b2)
+                                       output = in_band(wipezone,width,hyp,facf0,0,1);
+                               else
+                                       output = in_band(wipezone,width,hyp,facf0,1,1);
+                       }
+               break;
+        
+               case DO_DOUBLE_WIPE:
+                       if(!wipe->forward)
+                               facf0 = 1.0f-facf0;   // Go the other direction
+
+                       width = wipezone->width;  // calculate the blur width
+                       hwidth = width*0.5f;
+                       if (angle == 0) {
+                               b1 = posy*0.5f;
+                               b3 = yo-posy*0.5f;
+                               b2 = y;
+
+                               hyp = abs(y - posy*0.5f);
+                               hyp2 = abs(y - (yo-posy*0.5f));
+                       }
+                       else {
+                               b1 = posy*0.5f - (-angle)*posx*0.5f;
+                               b3 = (yo-posy*0.5f) - (-angle)*(xo-posx*0.5f);
+                               b2 = y - (-angle)*x;
+
+                               hyp = abs(angle*x+y+(-posy*0.5f-angle*posx*0.5f))*wipezone->pythangle;
+                               hyp2 = abs(angle*x+y+(-(yo-posy*0.5f)-angle*(xo-posx*0.5f)))*wipezone->pythangle;
+                       }
+
+                       temp1 = xo*(1-facf0*0.5f)-xo*facf0*0.5f;
+                       temp2 = yo*(1-facf0*0.5f)-yo*facf0*0.5f;
+                       pointdist = sqrt(temp1*temp1 + temp2*temp2);
+
+                       if(b2 < b1 && b2 < b3 ){
+                               if(hwidth < pointdist)
+                                       output = in_band(wipezone,hwidth,hyp,facf0,0,1);
+                       } else if(b2 > b1 && b2 > b3 ){
+                               if(hwidth < pointdist)
+                                       output = in_band(wipezone,hwidth,hyp2,facf0,0,1);       
+                       } else {
+                               if(  hyp < hwidth && hyp2 > hwidth )
+                                       output = in_band(wipezone,hwidth,hyp,facf0,1,1);
+                               else if( hyp > hwidth && hyp2 < hwidth )
+                                        output = in_band(wipezone,hwidth,hyp2,facf0,1,1);
+                               else
+                                        output = in_band(wipezone,hwidth,hyp2,facf0,1,1) * in_band(wipezone,hwidth,hyp,facf0,1,1);
+                       }
+                       if(!wipe->forward)output = 1-output;
+               break;
+               case DO_CLOCK_WIPE:
+                       /*
+                               temp1: angle of effect center in rads
+                               temp2: angle of line through (halfx,halfy) and (x,y) in rads
+                               temp3: angle of low side of blur
+                               temp4: angle of high side of blur
+                       */
+                       output = 1.0f - facf0;
+                       widthf = wipe->edgeWidth*2.0f*(float)M_PI;
+                       temp1 = 2.0f * (float)M_PI * facf0;
+                       
+                       if(wipe->forward){
+                               temp1 = 2.0f*(float)M_PI - temp1;
+                       }
+                       
+                       x = x - halfx;
+                       y = y - halfy;
+
+                       temp2 = asin(abs(y)/sqrt(x*x + y*y));
+                       if(x <= 0 && y >= 0) temp2 = (float)M_PI - temp2;
+                       else if(x<=0 && y <= 0) temp2 += (float)M_PI;
+                       else if(x >= 0 && y <= 0) temp2 = 2.0f*(float)M_PI - temp2;
+
+                       if(wipe->forward){
+                               temp3 = temp1-(widthf*0.5f)*facf0;
+                               temp4 = temp1+(widthf*0.5f)*(1-facf0);
+                       } else{
+                               temp3 = temp1-(widthf*0.5f)*(1-facf0);
+                               temp4 = temp1+(widthf*0.5f)*facf0;
+                       }
+                       if (temp3 < 0) temp3 = 0;
+                       if (temp4 > 2.0f*(float)M_PI) temp4 = 2.0f*(float)M_PI;
+                       
+                       
+                       if(temp2 < temp3) output = 0;
+                       else if (temp2 > temp4) output = 1;
+                       else output = (temp2-temp3)/(temp4-temp3);
+                       if(x == 0 && y == 0) output = 1;
+                       if(output != output) output = 1;
+                       if(wipe->forward) output = 1 - output;
+               break;
+       /* BOX WIPE IS NOT WORKING YET */
+       /* case DO_CROSS_WIPE: */
+       /* BOX WIPE IS NOT WORKING YET */
+       /* 
+               case DO_BOX_WIPE: 
+                       if(invert)facf0 = 1-facf0;
+
+                       width = (int)(wipe->edgeWidth*((xo+yo)/2.0));
+                       hwidth = (float)width/2.0;
+                       if (angle == 0)angle = 0.000001;
+                       b1 = posy/2 - (-angle)*posx/2;
+                       b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
+                       b2 = y - (-angle)*x;
+
+                       hyp = abs(angle*x+y+(-posy/2-angle*posx/2))*wipezone->pythangle;
+                       hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))*wipezone->pythangle;
+
+                       temp1 = xo*(1-facf0/2)-xo*facf0/2;
+                       temp2 = yo*(1-facf0/2)-yo*facf0/2;
+                       pointdist = sqrt(temp1*temp1 + temp2*temp2);
+
+                       if(b2 < b1 && b2 < b3 ){
+                               if(hwidth < pointdist)
+                                       output = in_band(wipezone,hwidth,hyp,facf0,0,1);
+                       } else if(b2 > b1 && b2 > b3 ){
+                               if(hwidth < pointdist)
+                                       output = in_band(wipezone,hwidth,hyp2,facf0,0,1);       
+                       } else {
+                               if( hyp < hwidth && hyp2 > hwidth )
+                                       output = in_band(wipezone,hwidth,hyp,facf0,1,1);
+                               else if( hyp > hwidth && hyp2 < hwidth )
+                                       output = in_band(wipezone,hwidth,hyp2,facf0,1,1);
+                               else
+                                       output = in_band(wipezone,hwidth,hyp2,facf0,1,1) * in_band(wipezone,hwidth,hyp,facf0,1,1);
+                       }
+
+                       if(invert)facf0 = 1-facf0;
+                       angle = -1/angle;
+                       b1 = posy/2 - (-angle)*posx/2;
+                       b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
+                       b2 = y - (-angle)*x;
+
+                       hyp = abs(angle*x+y+(-posy/2-angle*posx/2))*wipezone->pythangle;
+                       hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))*wipezone->pythangle;
+
+                       if(b2 < b1 && b2 < b3 ){
+                               if(hwidth < pointdist)
+                                       output *= in_band(wipezone,hwidth,hyp,facf0,0,1);
+                       } else if(b2 > b1 && b2 > b3 ){
+                               if(hwidth < pointdist)
+                                       output *= in_band(wipezone,hwidth,hyp2,facf0,0,1);      
+                       } else {
+                               if( hyp < hwidth && hyp2 > hwidth )
+                                       output *= in_band(wipezone,hwidth,hyp,facf0,1,1);
+                               else if( hyp > hwidth && hyp2 < hwidth )
+                                       output *= in_band(wipezone,hwidth,hyp2,facf0,1,1);
+                               else
+                                       output *= in_band(wipezone,hwidth,hyp2,facf0,1,1) * in_band(wipezone,hwidth,hyp,facf0,1,1);
+                       }
+
+               break;
+*/
+               case DO_IRIS_WIPE:
+                       if(xo > yo) yo = xo;
+                       else xo = yo;
+
+                       if(!wipe->forward) facf0 = 1-facf0;
+
+                       width = wipezone->width;
+                       hwidth = width*0.5f;
+
+                       temp1 = (halfx-(halfx)*facf0);
+                       pointdist = sqrt(temp1*temp1 + temp1*temp1);
+                
+                       temp2 = sqrt((halfx-x)*(halfx-x) + (halfy-y)*(halfy-y));
+                       if(temp2 > pointdist) output = in_band(wipezone,hwidth,fabs(temp2-pointdist),facf0,0,1);
+                       else output = in_band(wipezone,hwidth,fabs(temp2-pointdist),facf0,1,1);
+                
+                       if(!wipe->forward) output = 1-output;
+                       
+               break;
+       }
+       if (output < 0) output = 0;
+       else if(output > 1) output = 1;
+       return output;
+}
+
+static void init_wipe_effect(Sequence *seq)
+{
+       if(seq->effectdata)MEM_freeN(seq->effectdata);
+       seq->effectdata = MEM_callocN(sizeof(struct WipeVars), "wipevars");
+}
+
+static int num_inputs_wipe()
+{
+       return 1;
+}
+
+static void free_wipe_effect(Sequence *seq)
+{
+       if(seq->effectdata)MEM_freeN(seq->effectdata);
+       seq->effectdata = 0;
+}
+
+static void copy_wipe_effect(Sequence *dst, Sequence *src)
+{
+       dst->effectdata = MEM_dupallocN(src->effectdata);
+}
+
+static void do_wipe_effect_byte(Sequence *seq, float facf0, float facf1, 
+                               int x, int y, 
+                               unsigned char *rect1, 
+                               unsigned char *rect2, unsigned char *out)
+{
+       WipeZone wipezone;
+       WipeVars *wipe = (WipeVars *)seq->effectdata;
+       int xo, yo;
+       char *rt1, *rt2, *rt;
+
+       precalc_wipe_zone(&wipezone, wipe, x, y);
+
+       rt1 = (char *)rect1;
+       rt2 = (char *)rect2;
+       rt = (char *)out;
+
+       xo = x;
+       yo = y;
+       for(y=0;y<yo;y++) {
+               for(x=0;x<xo;x++) {
+                       float check = check_zone(&wipezone,x,y,seq,facf0);
+                       if (check) {
+                               if (rt1) {
+                                       rt[0] = (int)(rt1[0]*check)+ (int)(rt2[0]*(1-check));
+                                       rt[1] = (int)(rt1[1]*check)+ (int)(rt2[1]*(1-check));
+                                       rt[2] = (int)(rt1[2]*check)+ (int)(rt2[2]*(1-check));
+                                       rt[3] = (int)(rt1[3]*check)+ (int)(rt2[3]*(1-check));
+                               } else {
+                                       rt[0] = 0;
+                                       rt[1] = 0;
+                                       rt[2] = 0;
+                                       rt[3] = 255;
+                               }
+                       } else {
+                               if (rt2) {
+                                       rt[0] = rt2[0];
+                                       rt[1] = rt2[1];
+                                       rt[2] = rt2[2];
+                                       rt[3] = rt2[3];
+                               } else {
+                                       rt[0] = 0;
+                                       rt[1] = 0;
+                                       rt[2] = 0;
+                                       rt[3] = 255;
+                               }
+                       }
+
+                       rt+=4;
+                       if(rt1 !=NULL){
+                               rt1+=4;
+                       }
+                       if(rt2 !=NULL){
+                               rt2+=4;
+                       }
+               }
+       }
+}
+
+static void do_wipe_effect_float(Sequence *seq, float facf0, float facf1, 
+                                int x, int y, 
+                                float *rect1, 
+                                float *rect2, float *out)
+{
+       WipeZone wipezone;
+       WipeVars *wipe = (WipeVars *)seq->effectdata;
+       int xo, yo;
+       float *rt1, *rt2, *rt;
+
+       precalc_wipe_zone(&wipezone, wipe, x, y);
+
+       rt1 = rect1;
+       rt2 = rect2;
+       rt = out;
+
+       xo = x;
+       yo = y;
+       for(y=0;y<yo;y++) {
+               for(x=0;x<xo;x++) {
+                       float check = check_zone(&wipezone,x,y,seq,facf0);
+                       if (check) {
+                               if (rt1) {
+                                       rt[0] = rt1[0]*check+ rt2[0]*(1-check);
+                                       rt[1] = rt1[1]*check+ rt2[1]*(1-check);
+                                       rt[2] = rt1[2]*check+ rt2[2]*(1-check);
+                                       rt[3] = rt1[3]*check+ rt2[3]*(1-check);
+                               } else {
+                                       rt[0] = 0;
+                                       rt[1] = 0;
+                                       rt[2] = 0;
+                                       rt[3] = 1.0;
+                               }
+                       } else {
+                               if (rt2) {
+                                       rt[0] = rt2[0];
+                                       rt[1] = rt2[1];
+                                       rt[2] = rt2[2];
+                                       rt[3] = rt2[3];
+                               } else {
+                                       rt[0] = 0;
+                                       rt[1] = 0;
+                                       rt[2] = 0;
+                                       rt[3] = 1.0;
+                               }
+                       }
+
+                       rt+=4;
+                       if(rt1 !=NULL){
+                               rt1+=4;
+                       }
+                       if(rt2 !=NULL){
+                               rt2+=4;
+                       }
+               }
+       }
+}
+
+static void do_wipe_effect(Sequence * seq,int cfra,
+                          float facf0, float facf1, int x, int y, 
+                          struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
+                          struct ImBuf *ibuf3, struct ImBuf *out)
+{
+       if (out->rect_float) {
+               do_wipe_effect_float(seq,
+                                    facf0, facf1, x, y,
+                                    ibuf1->rect_float, ibuf2->rect_float,
+                                    out->rect_float);
+       } else {
+               do_wipe_effect_byte(seq,
+                                   facf0, facf1, x, y,
+                                   (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect,
+                                   (unsigned char*) out->rect);
+       }
+}
+/* **********************************************************************
+   TRANSFORM
+   ********************************************************************** */
+static void init_transform_effect(Sequence *seq)
+{
+       TransformVars *scale;
+
+       if(seq->effectdata)MEM_freeN(seq->effectdata);
+       seq->effectdata = MEM_callocN(sizeof(struct TransformVars), "transformvars");
+
+       scale = (TransformVars *)seq->effectdata;
+       scale->ScalexIni = 1;
+       scale->ScaleyIni = 1;
+       scale->ScalexFin = 1;
+       scale->ScaleyFin = 1;
+       
+       scale->xIni=0;
+       scale->xFin=0;
+       scale->yIni=0;
+       scale->yFin=0;
+       
+       scale->rotIni=0;
+       scale->rotFin=0;
+       
+       scale->interpolation=1;
+       scale->percent=1;
+}
+
+static int num_inputs_transform()
+{
+       return 1;
+}
+
+static void free_transform_effect(Sequence *seq)
+{
+       if(seq->effectdata)MEM_freeN(seq->effectdata);
+       seq->effectdata = 0;
+}
+
+static void copy_transform_effect(Sequence *dst, Sequence *src)
+{
+       dst->effectdata = MEM_dupallocN(src->effectdata);
+}
+
+static void do_transform(Sequence * seq,float facf0, int x, int y, 
+                         struct ImBuf *ibuf1,struct ImBuf *out)
+{
+       int xo, yo, xi, yi;
+       float xs,ys,factxScale,factyScale,tx,ty,rad,s,c,xaux,yaux,factRot,px,py;
+       TransformVars *scale;
+       
+       scale = (TransformVars *)seq->effectdata;
+       xo = x;
+       yo = y;
+
+       //factor scale
+       factxScale = scale->ScalexIni + (scale->ScalexFin - scale->ScalexIni) * facf0;
+       factyScale = scale->ScaleyIni + (scale->ScaleyFin - scale->ScaleyIni) * facf0;
+
+       //Factor translate
+       if(!scale->percent){
+               tx = scale->xIni+(xo / 2.0f) + (scale->xFin-(xo / 2.0f) - scale->xIni+(xo / 2.0f)) * facf0;
+               ty = scale->yIni+(yo / 2.0f) + (scale->yFin-(yo / 2.0f) - scale->yIni+(yo / 2.0f)) * facf0;
+       }else{
+               tx = xo*(scale->xIni/100.0f)+(xo / 2.0f) + (xo*(scale->xFin/100.0f)-(xo / 2.0f) - xo*(scale->xIni/100.0f)+(xo / 2.0f)) * facf0;
+               ty = yo*(scale->yIni/100.0f)+(yo / 2.0f) + (yo*(scale->yFin/100.0f)-(yo / 2.0f) - yo*(scale->yIni/100.0f)+(yo / 2.0f)) * facf0;
+       }
+
+       //factor Rotate
+       factRot = scale->rotIni + (scale->rotFin - scale->rotIni) * facf0;
+       rad = (M_PI * factRot) / 180.0f;
+       s= sin(rad);
+       c= cos(rad);
+
+       for (yi = 0; yi < yo; yi++) {
+               for (xi = 0; xi < xo; xi++) {
+                       //tranlate point
+                       px = xi-tx;
+                       py = yi-ty;
+
+                       //rotate point with center ref
+                       xaux = c*px + py*s ;
+                       yaux = -s*px + c*py;
+
+                       //scale point with center ref
+                       xs = xaux / factxScale;
+                       ys = yaux / factyScale;
+
+                       //undo reference center point 
+                       xs += (xo / 2.0f);
+                       ys += (yo / 2.0f);
+
+                       //interpolate
+                       switch(scale->interpolation) {
+                       case 0:
+                               neareast_interpolation(ibuf1,out, xs,ys,xi,yi);
+                               break;
+                       case 1:
+                               bilinear_interpolation(ibuf1,out, xs,ys,xi,yi);
+                               break;
+                       case 2:
+                               bicubic_interpolation(ibuf1,out, xs,ys,xi,yi);
+                               break;
+                       }
+               }
+       }       
+
+}
+static void do_transform_effect(Sequence * seq,int cfra,
+                          float facf0, float facf1, int x, int y, 
+                          struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
+                          struct ImBuf *ibuf3, struct ImBuf *out)
+{
+       do_transform(seq, facf0, x, y, ibuf1, out);
+}
+
+
+/* **********************************************************************
+   GLOW
+   ********************************************************************** */
+
+static void RVBlurBitmap2_byte ( unsigned char* map, int width,int height,
+                                float blur,
+                                int quality)
+/*     MUUUCCH better than the previous blur. */
+/*     We do the blurring in two passes which is a whole lot faster. */
+/*     I changed the math arount to implement an actual Gaussian */
+/*     distribution. */
+/* */
+/*     Watch out though, it tends to misbehaven with large blur values on */
+/*     a small bitmap.  Avoid avoid avoid. */
+/*=============================== */
+{
+       unsigned char*  temp=NULL,*swap;
+       float   *filter=NULL;
+       int     x,y,i,fx,fy;
+       int     index, ix, halfWidth;
+       float   fval, k, curColor[3], curColor2[3], weight=0;
+
+       /*      If we're not really blurring, bail out */
+       if (blur<=0)
+               return;
+
+       /*      Allocate memory for the tempmap and the blur filter matrix */
+       temp= MEM_mallocN( (width*height*4), "blurbitmaptemp");
+       if (!temp)
+               return;
+
+       /*      Allocate memory for the filter elements */
+       halfWidth = ((quality+1)*blur);
+       filter = (float *)MEM_mallocN(sizeof(float)*halfWidth*2, "blurbitmapfilter");
+       if (!filter){
+               MEM_freeN (temp);
+               return;
+       }
+
+       /*      Apparently we're calculating a bell curve */
+       /*      based on the standard deviation (or radius) */
+       /*      This code is based on an example */
+       /*      posted to comp.graphics.algorithms by */
+       /*      Blancmange (bmange@airdmhor.gen.nz) */
+
+       k = -1.0/(2.0*3.14159*blur*blur);
+       fval=0;
+       for (ix = 0;ix< halfWidth;ix++){
+               weight = (float)exp(k*(ix*ix));
+               filter[halfWidth - ix] = weight;
+               filter[halfWidth + ix] = weight;
+       }
+       filter[0] = weight;
+
+       /*      Normalize the array */
+       fval=0;
+       for (ix = 0;ix< halfWidth*2;ix++)
+               fval+=filter[ix];
+
+       for (ix = 0;ix< halfWidth*2;ix++)
+               filter[ix]/=fval;
+
+       /*      Blur the rows */
+       for (y=0;y<height;y++){
+               /*      Do the left & right strips */
+               for (x=0;x<halfWidth;x++){
+                       index=(x+y*width)*4;
+                       fx=0;
+                       curColor[0]=curColor[1]=curColor[2]=0;
+                       curColor2[0]=curColor2[1]=curColor2[2]=0;
+
+                       for (i=x-halfWidth;i<x+halfWidth;i++){
+                               if ((i>=0)&&(i<width)){
+                                       curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
+                                       curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
+                                       curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
+
+                                       curColor2[0]+=map[(width-1-i+y*width)*4+GlowR] *
+                                               filter[fx];
+                                       curColor2[1]+=map[(width-1-i+y*width)*4+GlowG] *
+                                               filter[fx];
+                                       curColor2[2]+=map[(width-1-i+y*width)*4+GlowB] *
+                                               filter[fx];
+                               }
+                               fx++;
+                       }
+                       temp[index+GlowR]=curColor[0];
+                       temp[index+GlowG]=curColor[1];
+                       temp[index+GlowB]=curColor[2];
+
+                       temp[((width-1-x+y*width)*4)+GlowR]=curColor2[0];
+                       temp[((width-1-x+y*width)*4)+GlowG]=curColor2[1];
+                       temp[((width-1-x+y*width)*4)+GlowB]=curColor2[2];
+
+               }
+               /*      Do the main body */
+               for (x=halfWidth;x<width-halfWidth;x++){
+                       index=(x+y*width)*4;
+                       fx=0;
+                       curColor[0]=curColor[1]=curColor[2]=0;
+                       for (i=x-halfWidth;i<x+halfWidth;i++){
+                               curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
+                               curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
+                               curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
+                               fx++;
+                       }
+                       temp[index+GlowR]=curColor[0];
+                       temp[index+GlowG]=curColor[1];
+                       temp[index+GlowB]=curColor[2];
+               }
+       }
+
+       /*      Swap buffers */
+       swap=temp;temp=map;map=swap;
+
+
+       /*      Blur the columns */
+       for (x=0;x<width;x++){
+               /*      Do the top & bottom strips */
+               for (y=0;y<halfWidth;y++){
+                       index=(x+y*width)*4;
+                       fy=0;
+                       curColor[0]=curColor[1]=curColor[2]=0;
+                       curColor2[0]=curColor2[1]=curColor2[2]=0;
+                       for (i=y-halfWidth;i<y+halfWidth;i++){
+                               if ((i>=0)&&(i<height)){
+                                       /*      Bottom */
+                                       curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
+                                       curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
+                                       curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
+
+                                       /*      Top */
+                                       curColor2[0]+=map[(x+(height-1-i)*width) *
+                                               4+GlowR]*filter[fy];
+                                       curColor2[1]+=map[(x+(height-1-i)*width) *
+                                               4+GlowG]*filter[fy];
+                                       curColor2[2]+=map[(x+(height-1-i)*width) *
+                                               4+GlowB]*filter[fy];
+                               }
+                               fy++;
+                       }
+                       temp[index+GlowR]=curColor[0];
+                       temp[index+GlowG]=curColor[1];
+                       temp[index+GlowB]=curColor[2];
+                       temp[((x+(height-1-y)*width)*4)+GlowR]=curColor2[0];
+                       temp[((x+(height-1-y)*width)*4)+GlowG]=curColor2[1];
+                       temp[((x+(height-1-y)*width)*4)+GlowB]=curColor2[2];
+               }
+               /*      Do the main body */
+               for (y=halfWidth;y<height-halfWidth;y++){
+                       index=(x+y*width)*4;
+                       fy=0;
+                       curColor[0]=curColor[1]=curColor[2]=0;
+                       for (i=y-halfWidth;i<y+halfWidth;i++){
+                               curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
+                               curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
+                               curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
+                               fy++;
+                       }
+                       temp[index+GlowR]=curColor[0];
+                       temp[index+GlowG]=curColor[1];
+                       temp[index+GlowB]=curColor[2];
+               }
+       }
+
+
+       /*      Swap buffers */
+       swap=temp;temp=map;map=swap;
+
+       /*      Tidy up  */
+       MEM_freeN (filter);
+       MEM_freeN (temp);
+}
+
+static void RVBlurBitmap2_float ( float* map, int width,int height,
+                                 float blur,
+                                 int quality)
+/*     MUUUCCH better than the previous blur. */
+/*     We do the blurring in two passes which is a whole lot faster. */
+/*     I changed the math arount to implement an actual Gaussian */
+/*     distribution. */
+/* */
+/*     Watch out though, it tends to misbehaven with large blur values on */
+/*     a small bitmap.  Avoid avoid avoid. */
+/*=============================== */
+{
+       float*  temp=NULL,*swap;
+       float   *filter=NULL;
+       int     x,y,i,fx,fy;
+       int     index, ix, halfWidth;
+       float   fval, k, curColor[3], curColor2[3], weight=0;
+
+       /*      If we're not really blurring, bail out */
+       if (blur<=0)
+               return;
+
+       /*      Allocate memory for the tempmap and the blur filter matrix */
+       temp= MEM_mallocN( (width*height*4*sizeof(float)), "blurbitmaptemp");
+       if (!temp)
+               return;
+
+       /*      Allocate memory for the filter elements */
+       halfWidth = ((quality+1)*blur);
+       filter = (float *)MEM_mallocN(sizeof(float)*halfWidth*2, "blurbitmapfilter");
+       if (!filter){
+               MEM_freeN (temp);
+               return;
+       }
+
+       /*      Apparently we're calculating a bell curve */
+       /*      based on the standard deviation (or radius) */
+       /*      This code is based on an example */
+       /*      posted to comp.graphics.algorithms by */
+       /*      Blancmange (bmange@airdmhor.gen.nz) */
+
+       k = -1.0/(2.0*3.14159*blur*blur);
+       fval=0;
+       for (ix = 0;ix< halfWidth;ix++){
+               weight = (float)exp(k*(ix*ix));
+               filter[halfWidth - ix] = weight;
+               filter[halfWidth + ix] = weight;
+       }
+       filter[0] = weight;
+
+       /*      Normalize the array */
+       fval=0;
+       for (ix = 0;ix< halfWidth*2;ix++)
+               fval+=filter[ix];
+
+       for (ix = 0;ix< halfWidth*2;ix++)
+               filter[ix]/=fval;
+
+       /*      Blur the rows */
+       for (y=0;y<height;y++){
+               /*      Do the left & right strips */
+               for (x=0;x<halfWidth;x++){
+                       index=(x+y*width)*4;
+                       fx=0;
+                       curColor[0]=curColor[1]=curColor[2]=0.0f;
+                       curColor2[0]=curColor2[1]=curColor2[2]=0.0f;
+
+                       for (i=x-halfWidth;i<x+halfWidth;i++){
+                               if ((i>=0)&&(i<width)){
+                                       curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
+                                       curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
+                                       curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
+
+                                       curColor2[0]+=map[(width-1-i+y*width)*4+GlowR] *
+                                               filter[fx];
+                                       curColor2[1]+=map[(width-1-i+y*width)*4+GlowG] *
+                                               filter[fx];
+                                       curColor2[2]+=map[(width-1-i+y*width)*4+GlowB] *
+                                               filter[fx];
+                               }
+                               fx++;
+                       }
+                       temp[index+GlowR]=curColor[0];
+                       temp[index+GlowG]=curColor[1];
+                       temp[index+GlowB]=curColor[2];
+
+                       temp[((width-1-x+y*width)*4)+GlowR]=curColor2[0];
+                       temp[((width-1-x+y*width)*4)+GlowG]=curColor2[1];
+                       temp[((width-1-x+y*width)*4)+GlowB]=curColor2[2];
+
+               }
+               /*      Do the main body */
+               for (x=halfWidth;x<width-halfWidth;x++){
+                       index=(x+y*width)*4;
+                       fx=0;
+                       curColor[0]=curColor[1]=curColor[2]=0;
+                       for (i=x-halfWidth;i<x+halfWidth;i++){
+                               curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
+                               curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
+                               curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
+                               fx++;
+                       }
+                       temp[index+GlowR]=curColor[0];
+                       temp[index+GlowG]=curColor[1];
+                       temp[index+GlowB]=curColor[2];
+               }
+       }
+
+       /*      Swap buffers */
+       swap=temp;temp=map;map=swap;
+
+
+       /*      Blur the columns */
+       for (x=0;x<width;x++){
+               /*      Do the top & bottom strips */
+               for (y=0;y<halfWidth;y++){
+                       index=(x+y*width)*4;
+                       fy=0;
+                       curColor[0]=curColor[1]=curColor[2]=0;
+                       curColor2[0]=curColor2[1]=curColor2[2]=0;
+                       for (i=y-halfWidth;i<y+halfWidth;i++){
+                               if ((i>=0)&&(i<height)){
+                                       /*      Bottom */
+                                       curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
+                                       curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
+                                       curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
+
+                                       /*      Top */
+                                       curColor2[0]+=map[(x+(height-1-i)*width) *
+                                               4+GlowR]*filter[fy];
+                                       curColor2[1]+=map[(x+(height-1-i)*width) *
+                                               4+GlowG]*filter[fy];
+                                       curColor2[2]+=map[(x+(height-1-i)*width) *
+                                               4+GlowB]*filter[fy];
+                               }
+                               fy++;
+                       }
+                       temp[index+GlowR]=curColor[0];
+                       temp[index+GlowG]=curColor[1];
+                       temp[index+GlowB]=curColor[2];
+                       temp[((x+(height-1-y)*width)*4)+GlowR]=curColor2[0];
+                       temp[((x+(height-1-y)*width)*4)+GlowG]=curColor2[1];
+                       temp[((x+(height-1-y)*width)*4)+GlowB]=curColor2[2];
+               }
+               /*      Do the main body */
+               for (y=halfWidth;y<height-halfWidth;y++){
+                       index=(x+y*width)*4;
+                       fy=0;
+                       curColor[0]=curColor[1]=curColor[2]=0;
+                       for (i=y-halfWidth;i<y+halfWidth;i++){
+                               curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
+                               curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
+                               curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
+                               fy++;
+                       }
+                       temp[index+GlowR]=curColor[0];
+                       temp[index+GlowG]=curColor[1];
+                       temp[index+GlowB]=curColor[2];
+               }
+       }
+
+
+       /*      Swap buffers */
+       swap=temp;temp=map;map=swap;
+
+       /*      Tidy up  */
+       MEM_freeN (filter);
+       MEM_freeN (temp);
+}
+
+
+/*     Adds two bitmaps and puts the results into a third map. */
+/*     C must have been previously allocated but it may be A or B. */
+/*     We clamp values to 255 to prevent weirdness */
+/*=============================== */
+static void RVAddBitmaps_byte (unsigned char* a, unsigned char* b, unsigned char* c, int width, int height)
+{
+       int     x,y,index;
+
+       for (y=0;y<height;y++){
+               for (x=0;x<width;x++){
+                       index=(x+y*width)*4;
+                       c[index+GlowR]=MIN2(255,a[index+GlowR]+b[index+GlowR]);
+                       c[index+GlowG]=MIN2(255,a[index+GlowG]+b[index+GlowG]);
+                       c[index+GlowB]=MIN2(255,a[index+GlowB]+b[index+GlowB]);
+                       c[index+GlowA]=MIN2(255,a[index+GlowA]+b[index+GlowA]);
+               }
+       }
+}
+
+static void RVAddBitmaps_float (float* a, float* b, float* c, 
+                               int width, int height)
+{
+       int     x,y,index;
+
+       for (y=0;y<height;y++){
+               for (x=0;x<width;x++){
+                       index=(x+y*width)*4;
+                       c[index+GlowR]=MIN2(1.0,a[index+GlowR]+b[index+GlowR]);
+                       c[index+GlowG]=MIN2(1.0,a[index+GlowG]+b[index+GlowG]);
+                       c[index+GlowB]=MIN2(1.0,a[index+GlowB]+b[index+GlowB]);
+                       c[index+GlowA]=MIN2(1.0,a[index+GlowA]+b[index+GlowA]);
+               }
+       }
+}
+
+/*     For each pixel whose total luminance exceeds the threshold, */
+/*     Multiply it's value by BOOST and add it to the output map */
+static void RVIsolateHighlights_byte (unsigned char* in, unsigned char* out, 
+                                     int width, int height, int threshold, 
+                                     float boost, float clamp)
+{
+       int x,y,index;
+       int     intensity;
+
+
+       for(y=0;y< height;y++) {
+               for (x=0;x< width;x++) {
+                       index= (x+y*width)*4;
+
+                       /*      Isolate the intensity */
+                       intensity=(in[index+GlowR]+in[index+GlowG]+in[index+GlowB]-threshold);
+                       if (intensity>0){
+                               out[index+GlowR]=MIN2(255*clamp, (in[index+GlowR]*boost*intensity)/255);
+                               out[index+GlowG]=MIN2(255*clamp, (in[index+GlowG]*boost*intensity)/255);
+                               out[index+GlowB]=MIN2(255*clamp, (in[index+GlowB]*boost*intensity)/255);
+                               out[index+GlowA]=MIN2(255*clamp, (in[index+GlowA]*boost*intensity)/255);
+                       } else{
+                               out[index+GlowR]=0;
+                               out[index+GlowG]=0;
+                               out[index+GlowB]=0;
+                               out[index+GlowA]=0;
+                       }
+               }
+       }
+}
+
+static void RVIsolateHighlights_float (float* in, float* out, 
+                                     int width, int height, float threshold, 
+                                     float boost, float clamp)
+{
+       int x,y,index;
+       float   intensity;
+
+
+       for(y=0;y< height;y++) {
+               for (x=0;x< width;x++) {
+                       index= (x+y*width)*4;
+
+                       /*      Isolate the intensity */
+                       intensity=(in[index+GlowR]+in[index+GlowG]+in[index+GlowB]-threshold);
+                       if (intensity>0){
+                               out[index+GlowR]=MIN2(clamp, (in[index+GlowR]*boost*intensity));
+                               out[index+GlowG]=MIN2(clamp, (in[index+GlowG]*boost*intensity));
+                               out[index+GlowB]=MIN2(clamp, (in[index+GlowB]*boost*intensity));
+                               out[index+GlowA]=MIN2(clamp, (in[index+GlowA]*boost*intensity));
+                       } else{
+                               out[index+GlowR]=0;
+                               out[index+GlowG]=0;
+                               out[index+GlowB]=0;
+                               out[index+GlowA]=0;
+                       }
+               }
+       }
+}
+
+static void init_glow_effect(Sequence *seq)
+{
+       GlowVars *glow;
+
+       if(seq->effectdata)MEM_freeN(seq->effectdata);
+       seq->effectdata = MEM_callocN(sizeof(struct GlowVars), "glowvars");
+
+       glow = (GlowVars *)seq->effectdata;
+       glow->fMini = 0.25;
+       glow->fClamp = 1.0;
+       glow->fBoost = 0.5;
+       glow->dDist = 3.0;
+       glow->dQuality = 3;
+       glow->bNoComp = 0;
+}
+
+static int num_inputs_glow()
+{
+       return 1;
+}
+
+static void free_glow_effect(Sequence *seq)
+{
+       if(seq->effectdata)MEM_freeN(seq->effectdata);
+       seq->effectdata = 0;
+}
+
+static void copy_glow_effect(Sequence *dst, Sequence *src)
+{
+       dst->effectdata = MEM_dupallocN(src->effectdata);
+}
+
+//void do_glow_effect(Cast *cast, float facf0, float facf1, int xo, int yo, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *outbuf, ImBuf *use)
+static void do_glow_effect_byte(Sequence *seq, float facf0, float facf1, 
+                               int x, int y, char *rect1, 
+                               char *rect2, char *out)
+{
+       unsigned char *outbuf=(unsigned char *)out;
+       unsigned char *inbuf=(unsigned char *)rect1;
+       GlowVars *glow = (GlowVars *)seq->effectdata;
+       int size= 100; // renderdata XXX
+       
+       RVIsolateHighlights_byte(inbuf, outbuf , x, y, glow->fMini*765, glow->fBoost * facf0, glow->fClamp);
+       RVBlurBitmap2_byte (outbuf, x, y, glow->dDist * (size / 100.0f),glow->dQuality);
+       if (!glow->bNoComp)
+               RVAddBitmaps_byte (inbuf , outbuf, outbuf, x, y);
+}
+
+static void do_glow_effect_float(Sequence *seq, float facf0, float facf1, 
+                                int x, int y, 
+                                float *rect1, float *rect2, float *out)
+{
+       float *outbuf = out;
+       float *inbuf = rect1;
+       GlowVars *glow = (GlowVars *)seq->effectdata;
+       int size= 100; // renderdata XXX
+
+       RVIsolateHighlights_float(inbuf, outbuf , x, y, glow->fMini*3.0f, glow->fBoost * facf0, glow->fClamp);
+       RVBlurBitmap2_float (outbuf, x, y, glow->dDist * (size / 100.0f),glow->dQuality);
+       if (!glow->bNoComp)
+               RVAddBitmaps_float (inbuf , outbuf, outbuf, x, y);
+}
+
+static void do_glow_effect(Sequence * seq,int cfra,
+                          float facf0, float facf1, int x, int y, 
+                          struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
+                          struct ImBuf *ibuf3, struct ImBuf *out)
+{
+       if (out->rect_float) {
+               do_glow_effect_float(seq,
+                                    facf0, facf1, x, y,
+                                    ibuf1->rect_float, ibuf2->rect_float,
+                                    out->rect_float);
+       } else {
+               do_glow_effect_byte(seq,
+                                   facf0, facf1, x, y,
+                                   (char*) ibuf1->rect, (char*) ibuf2->rect,
+                                   (char*) out->rect);
+       }
+}
+
+/* **********************************************************************
+   SOLID COLOR
+   ********************************************************************** */
+
+static void init_solid_color(Sequence *seq)
+{
+       SolidColorVars *cv;
+       
+       if(seq->effectdata)MEM_freeN(seq->effectdata);
+       seq->effectdata = MEM_callocN(sizeof(struct SolidColorVars), "solidcolor");
+       
+       cv = (SolidColorVars *)seq->effectdata;
+       cv->col[0] = cv->col[1] = cv->col[2] = 0.5;
+}
+
+static int num_inputs_color()
+{
+       return 0;
+}
+
+static void free_solid_color(Sequence *seq)
+{
+       if(seq->effectdata)MEM_freeN(seq->effectdata);
+       seq->effectdata = 0;
+}
+
+static void copy_solid_color(Sequence *dst, Sequence *src)
+{
+       dst->effectdata = MEM_dupallocN(src->effectdata);
+}
+
+static int early_out_color(struct Sequence *seq,
+                          float facf0, float facf1)
+{
+       return -1;
+}
+
+static void do_solid_color(Sequence * seq,int cfra,
+                          float facf0, float facf1, int x, int y, 
+                          struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
+                          struct ImBuf *ibuf3, struct ImBuf *out)
+{
+       SolidColorVars *cv = (SolidColorVars *)seq->effectdata;
+
+       unsigned char *rect;
+       float *rect_float;
+
+       if (out->rect) {
+               unsigned char col0[3];
+               unsigned char col1[3];
+
+               col0[0] = facf0 * cv->col[0] * 255;
+               col0[1] = facf0 * cv->col[1] * 255;
+               col0[2] = facf0 * cv->col[2] * 255;
+
+               col1[0] = facf1 * cv->col[0] * 255;
+               col1[1] = facf1 * cv->col[1] * 255;
+               col1[2] = facf1 * cv->col[2] * 255;
+
+               rect = (unsigned char *)out->rect;
+               
+               for(y=0; y<out->y; y++) {       
+                       for(x=0; x<out->x; x++, rect+=4) {
+                               rect[0]= col0[0];
+                               rect[1]= col0[1];
+                               rect[2]= col0[2];
+                               rect[3]= 255;
+                       }
+                       y++;
+                       if (y<out->y) {
+                               for(x=0; x<out->x; x++, rect+=4) {
+                                       rect[0]= col1[0];
+                                       rect[1]= col1[1];
+                                       rect[2]= col1[2];
+                                       rect[3]= 255;
+                               }       
+                       }
+               }
+
+       } else if (out->rect_float) {
+               float col0[3];
+               float col1[3];
+
+               col0[0] = facf0 * cv->col[0];
+               col0[1] = facf0 * cv->col[1];
+               col0[2] = facf0 * cv->col[2];
+
+               col1[0] = facf1 * cv->col[0];
+               col1[1] = facf1 * cv->col[1];
+               col1[2] = facf1 * cv->col[2];
+
+               rect_float = out->rect_float;
+               
+               for(y=0; y<out->y; y++) {       
+                       for(x=0; x<out->x; x++, rect_float+=4) {
+                               rect_float[0]= col0[0];
+                               rect_float[1]= col0[1];
+                               rect_float[2]= col0[2];
+                               rect_float[3]= 1.0;
+                       }
+                       y++;
+                       if (y<out->y) {
+                               for(x=0; x<out->x; x++, rect_float+=4) {
+                                       rect_float[0]= col1[0];
+                                       rect_float[1]= col1[1];
+                                       rect_float[2]= col1[2];
+                                       rect_float[3]= 1.0;
+                               }
+                       }
+               }
+       }
+}
+
+/* **********************************************************************
+   SPEED
+   ********************************************************************** */
+static void init_speed_effect(Sequence *seq)
+{
+       SpeedControlVars * v;
+
+       if(seq->effectdata) MEM_freeN(seq->effectdata);
+       seq->effectdata = MEM_callocN(sizeof(struct SpeedControlVars), 
+                                     "speedcontrolvars");
+
+       v = (SpeedControlVars *)seq->effectdata;
+       v->globalSpeed = 1.0;
+       v->frameMap = 0;
+       v->flags = SEQ_SPEED_COMPRESS_IPO_Y;
+       v->length = 0;
+}
+
+static void load_speed_effect(Sequence * seq)
+{
+       SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
+
+       v->frameMap = 0;
+       v->length = 0;
+}
+
+static int num_inputs_speed()
+{
+       return 1;
+}
+
+static void free_speed_effect(Sequence *seq)
+{
+       SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
+       if(v->frameMap) MEM_freeN(v->frameMap);
+       if(seq->effectdata) MEM_freeN(seq->effectdata);
+       seq->effectdata = 0;
+}
+
+static void copy_speed_effect(Sequence *dst, Sequence *src)
+{
+       SpeedControlVars * v;
+       dst->effectdata = MEM_dupallocN(src->effectdata);
+       v = (SpeedControlVars *)dst->effectdata;
+       v->frameMap = 0;
+       v->length = 0;
+}
+
+static int early_out_speed(struct Sequence *seq,
+                         float facf0, float facf1)
+{
+       return 1;
+}
+
+static void store_icu_yrange_speed(struct Sequence * seq,
+                                  short adrcode, float * ymin, float * ymax)
+{
+       SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
+
+       /* if not already done, load / initialize data */
+       get_sequence_effect(seq);
+
+       if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) {
+               *ymin = -100.0;
+               *ymax = 100.0;
+       } else {
+               if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) {
+                       *ymin = 0.0;
+                       *ymax = 1.0;
+               } else {
+                       *ymin = 0.0;
+                       *ymax = seq->len;
+               }
+       }       
+}
+
+void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force)
+{
+       float facf0 = seq->facf0;
+       float ctime, div;
+       int cfra;
+       float fallback_fac;
+       SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
+
+       /* if not already done, load / initialize data */
+       get_sequence_effect(seq);
+
+       if (!(force || seq->len != v->length || !v->frameMap)) {
+               return;
+       }
+
+       if (!v->frameMap || v->length != seq->len) {
+               if (v->frameMap) MEM_freeN(v->frameMap);
+
+               v->length = seq->len;
+
+               v->frameMap = MEM_callocN(sizeof(float) * v->length, 
+                                         "speedcontrol frameMap");
+       }
+
+       fallback_fac = 1.0;
+       
+       /* if there is no IPO, try to make retiming easy by stretching the
+          strip */
+
+       if (!seq->ipo && seq->seq1 && seq->seq1->enddisp != seq->seq1->start
+           && seq->seq1->len != 0) {
+               fallback_fac = (float) seq->seq1->len / 
+                       (float) (seq->seq1->enddisp - seq->seq1->start);
+               /* FIXME: this strip stretching gets screwed by stripdata
+                  handling one layer up.
+                  
+                  So it currently works by enlarging, never by shrinking!
+
+                  (IPOs still work, if used correctly)
+               */
+               if (fallback_fac > 1.0) {
+                       fallback_fac = 1.0;
+               }
+       }
+
+       if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) {
+               float cursor = 0;
+
+               v->frameMap[0] = 0;
+               v->lastValidFrame = 0;
+
+               for (cfra = 1; cfra < v->length; cfra++) {
+                       if(seq->ipo) {
+                               if((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
+                                       ctime = frame_to_float(scene, seq->startdisp + cfra);
+                                       div = 1.0;
+                               } else {
+                                       ctime= frame_to_float(scene, cfra);
+                                       div= v->length / 100.0f;
+                                       if(div==0.0) return;
+                               }
+               
+                               calc_ipo(seq->ipo, ctime/div);
+                               execute_ipo((ID *)seq, seq->ipo);
+                       } else {
+                               seq->facf0 = fallback_fac;
+                       }
+                       seq->facf0 *= v->globalSpeed;
+
+                       cursor += seq->facf0;
+
+                       if (cursor >= v->length) {
+                               v->frameMap[cfra] = v->length - 1;
+                       } else {
+                               v->frameMap[cfra] = cursor;
+                               v->lastValidFrame = cfra;
+                       }
+               }
+       } else {
+               v->lastValidFrame = 0;
+               for (cfra = 0; cfra < v->length; cfra++) {
+                       if(seq->ipo) {
+                               if((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
+                                       ctime = frame_to_float(scene, seq->startdisp + cfra);
+                                       div = 1.0;
+                               } else {
+                                       ctime= frame_to_float(scene, cfra);
+                                       div= v->length / 100.0f;
+                                       if(div==0.0) return;
+                               }
+               
+                               calc_ipo(seq->ipo, ctime/div);
+                               execute_ipo((ID *)seq, seq->ipo);
+                       }
+                       
+                       if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) {
+                               seq->facf0 *= v->length;
+                       }
+                       if (!seq->ipo) {
+                               seq->facf0 = (float) cfra * fallback_fac;
+                       }
+                       seq->facf0 *= v->globalSpeed;
+                       if (seq->facf0 >= v->length) {
+                               seq->facf0 = v->length - 1;
+                       } else {
+                               v->lastValidFrame = cfra;
+                       }
+                       v->frameMap[cfra] = seq->facf0;
+               }
+       }
+       seq->facf0 = facf0;
+}
+
+/*
+  simply reuse do_cross_effect for blending...
+
+static void do_speed_effect(Sequence * seq,int cfra,
+                          float facf0, float facf1, int x, int y, 
+                          struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
+                          struct ImBuf *ibuf3, struct ImBuf *out)
+{
+
+}
+*/
+
+
+/* **********************************************************************
+   sequence effect factory
+   ********************************************************************** */
+
+
+static void init_noop(struct Sequence *seq)
+{
+
+}
+
+static void load_noop(struct Sequence *seq)
+{
+
+}
+
+static void init_plugin_noop(struct Sequence *seq, const char * fname)
+{
+
+}
+
+static void free_noop(struct Sequence *seq)
+{
+
+}
+
+static int num_inputs_default()
+{
+       return 2;
+}
+
+static int early_out_noop(struct Sequence *seq,
+                         float facf0, float facf1)
+{
+       return 0;
+}
+
+static int early_out_fade(struct Sequence *seq,
+                         float facf0, float facf1)
+{
+       if (facf0 == 0.0 && facf1 == 0.0) {
+               return 1;
+       } else if (facf0 == 1.0 && facf1 == 1.0) {
+               return 2;
+       }
+       return 0;
+}
+
+static int early_out_mul_input2(struct Sequence *seq,
+                               float facf0, float facf1)
+{
+       if (facf0 == 0.0 && facf1 == 0.0) {
+               return 1;
+       }
+       return 0;
+}
+
+static void store_icu_yrange_noop(struct Sequence * seq,
+                                 short adrcode, float * ymin, float * ymax)
+{
+       /* defaults are fine */
+}
+
+static void get_default_fac_noop(struct Sequence *seq, int cfra,
+                                float * facf0, float * facf1)
+{
+       *facf0 = *facf1 = 1.0;
+}
+
+static void get_default_fac_fade(struct Sequence *seq, int cfra,
+                                float * facf0, float * facf1)
+{
+       *facf0 = (float)(cfra - seq->startdisp);
+       *facf1 = (float)(*facf0 + 0.5);
+       *facf0 /= seq->len;
+       *facf1 /= seq->len;
+}
+
+static void do_overdrop_effect(struct Sequence * seq, int cfra,
+                              float fac, float facf, 
+                              int x, int y, struct ImBuf * ibuf1, 
+                              struct ImBuf * ibuf2, 
+                              struct ImBuf * ibuf3, 
+                              struct ImBuf * out)
+{
+       do_drop_effect(seq, cfra, fac, facf, x, y, 
+                      ibuf1, ibuf2, ibuf3, out);
+       do_alphaover_effect(seq, cfra, fac, facf, x, y, 
+                           ibuf1, ibuf2, ibuf3, out);
+}
+
+static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
+{
+       struct SeqEffectHandle rval;
+       int sequence_type = seq_type;
+
+       rval.init = init_noop;
+       rval.init_plugin = init_plugin_noop;
+       rval.num_inputs = num_inputs_default;
+       rval.load = load_noop;
+       rval.free = free_noop;
+       rval.early_out = early_out_noop;
+       rval.get_default_fac = get_default_fac_noop;
+       rval.store_icu_yrange = store_icu_yrange_noop;
+       rval.execute = NULL;
+       rval.copy = NULL;
+
+       switch (sequence_type) {
+       case SEQ_CROSS:
+               rval.execute = do_cross_effect;
+               rval.early_out = early_out_fade;
+               rval.get_default_fac = get_default_fac_fade;
+               break;
+       case SEQ_GAMCROSS:
+               rval.init = init_gammacross;
+               rval.load = load_gammacross;
+               rval.free = free_gammacross;
+               rval.early_out = early_out_fade;
+               rval.get_default_fac = get_default_fac_fade;
+               rval.execute = do_gammacross_effect;
+               break;
+       case SEQ_ADD:
+               rval.execute = do_add_effect;
+               rval.early_out = early_out_mul_input2;
+               break;
+       case SEQ_SUB:
+               rval.execute = do_sub_effect;
+               rval.early_out = early_out_mul_input2;
+               break;
+       case SEQ_MUL:
+               rval.execute = do_mul_effect;
+               rval.early_out = early_out_mul_input2;
+               break;
+       case SEQ_ALPHAOVER:
+               rval.init = init_alpha_over_or_under;
+               rval.execute = do_alphaover_effect;
+               break;
+       case SEQ_OVERDROP:
+               rval.execute = do_overdrop_effect;
+               break;
+       case SEQ_ALPHAUNDER:
+               rval.init = init_alpha_over_or_under;
+               rval.execute = do_alphaunder_effect;
+               break;
+       case SEQ_WIPE:
+               rval.init = init_wipe_effect;
+               rval.num_inputs = num_inputs_wipe;
+               rval.free = free_wipe_effect;
+               rval.copy = copy_wipe_effect;
+               rval.early_out = early_out_fade;
+               rval.get_default_fac = get_default_fac_fade;
+               rval.execute = do_wipe_effect;
+               break;
+       case SEQ_GLOW:
+               rval.init = init_glow_effect;
+               rval.num_inputs = num_inputs_glow;
+               rval.free = free_glow_effect;
+               rval.copy = copy_glow_effect;
+               rval.execute = do_glow_effect;
+               break;
+       case SEQ_TRANSFORM:
+               rval.init = init_transform_effect;
+               rval.num_inputs = num_inputs_transform;
+               rval.free = free_transform_effect;
+               rval.copy = copy_transform_effect;
+               rval.execute = do_transform_effect;
+               break;
+       case SEQ_SPEED:
+               rval.init = init_speed_effect;
+               rval.num_inputs = num_inputs_speed;
+               rval.load = load_speed_effect;
+               rval.free = free_speed_effect;
+               rval.copy = copy_speed_effect;
+               rval.execute = do_cross_effect;
+               rval.early_out = early_out_speed;
+               rval.store_icu_yrange = store_icu_yrange_speed;
+               break;
+       case SEQ_COLOR:
+               rval.init = init_solid_color;
+               rval.num_inputs = num_inputs_color;
+               rval.early_out = early_out_color;
+               rval.free = free_solid_color;
+               rval.copy = copy_solid_color;
+               rval.execute = do_solid_color;
+               break;
+       case SEQ_PLUGIN:
+               rval.init_plugin = init_plugin;
+               rval.num_inputs = num_inputs_plugin;
+               rval.load = load_plugin;
+               rval.free = free_plugin;
+               rval.copy = copy_plugin;
+               rval.execute = do_plugin_effect;
+               rval.early_out = do_plugin_early_out;
+               rval.get_default_fac = get_default_fac_fade;
+               break;
+       }
+
+       return rval;
+}
+
+
+struct SeqEffectHandle get_sequence_effect(Sequence * seq)
+{
+       struct SeqEffectHandle rval;
+
+       memset(&rval, 0, sizeof(struct SeqEffectHandle));
+
+       if (seq->type & SEQ_EFFECT) {
+               rval = get_sequence_effect_impl(seq->type);
+               if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) {
+                       rval.load(seq);
+                       seq->flag &= ~SEQ_EFFECT_NOT_LOADED;
+               }
+       }
+
+       return rval;
+}
+
+struct SeqEffectHandle get_sequence_blend(Sequence * seq)
+{
+       struct SeqEffectHandle rval;
+
+       memset(&rval, 0, sizeof(struct SeqEffectHandle));
+
+       if (seq->blend_mode != 0) {
+               rval = get_sequence_effect_impl(seq->blend_mode);
+               if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) {
+                       rval.load(seq);
+                       seq->flag &= ~SEQ_EFFECT_NOT_LOADED;
+               }
+       }
+
+       return rval;
+}
+
+int get_sequence_effect_num_inputs(int seq_type)
+{
+       struct SeqEffectHandle rval = get_sequence_effect_impl(seq_type);
+
+       int cnt = rval.num_inputs();
+       if (rval.execute) {
+               return cnt;
+       }
+       return 0;
+}
index e203c1bcb8e3da0ffdb37c60b325d15cca137a49..5cc087e857e8db98e4f04b77a81615bb61578efe 100644 (file)
@@ -1,19 +1,74 @@
+/**
+* $Id: sequence.c 17508 2008-11-20 00:34:24Z campbellbarton $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): 
+ * - Blender Foundation, 2003-2009
+ * - Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
 
 #include <stdlib.h>
 #include <string.h>
+#include <math.h>
 
 #include "MEM_guardedalloc.h"
 
+#include "DNA_ipo_types.h"
 #include "DNA_listBase.h"
 #include "DNA_sequence_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_ipo.h"
+#include "BKE_main.h"
+#include "BKE_sequence.h"
+#include "BKE_utildefines.h"
 
 #include "BLI_blenlib.h"
 
 #include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
 
-#include "BKE_sequence.h"
+#include "BLI_threads.h"
+#include <pthread.h>
+
+#ifdef WIN32
+#define snprintf _snprintf
+#endif
 
-/* strip data */
+/* **** XXX ******** */
+static int seqrectx= 0;        /* bad bad global! */
+static int seqrecty= 0;
+static void waitcursor() {}
+static int blender_test_break() {return 0;}
+
+/* **** XXX ******** */
+
+
+/* **********************************************************************
+   alloc / free functions
+   ********************************************************************** */
 
 static void free_tstripdata(int len, TStripElem *se)
 {
@@ -38,8 +93,8 @@ static void free_tstripdata(int len, TStripElem *se)
        MEM_freeN(seo);
 }
 
-/*
-static void new_tstripdata(Sequence *seq)
+
+void new_tstripdata(Sequence *seq)
 {
        if(seq->strip) {
                free_tstripdata(seq->strip->len, seq->strip->tstripdata);
@@ -65,11 +120,11 @@ static void new_tstripdata(Sequence *seq)
                seq->strip->len= seq->len;
        }
 }
-*/
+
 
 /* free */
 
-static void seq_free_strip(Strip *strip)
+void seq_free_strip(Strip *strip)
 {
        strip->us--;
        if(strip->us>0) return;
@@ -155,6 +210,10 @@ void seq_free_editing(Editing *ed)
        MEM_freeN(ed);
 }
 
+/* ************************* itterator ************************** */
+/* *************** (replaces old WHILE_SEQ) ********************* */
+/* **************** use now SEQ_BEGIN() SEQ_END ***************** */
+
 /* sequence strip iterator:
  * - builds a full array, recursively into meta strips */
 
@@ -185,7 +244,7 @@ static void seq_build_array(ListBase *seqbase, Sequence ***array, int depth)
        }
 }
 
-void seq_array(Editing *ed, Sequence ***seqarray, int *tot)
+void seq_array(Editing *ed, Sequence ***seqarray, int *tot, int use_pointer)
 {
        Sequence **array;
 
@@ -195,19 +254,25 @@ void seq_array(Editing *ed, Sequence ***seqarray, int *tot)
        if(ed == NULL)
                return;
 
-       seq_count(&ed->seqbase, tot);
+       if(use_pointer)
+               seq_count(ed->seqbasep, tot);
+       else
+               seq_count(&ed->seqbase, tot);
 
        if(*tot == 0)
                return;
 
        *seqarray= array= MEM_mallocN(sizeof(Sequence *)*(*tot), "SeqArray");
-       seq_build_array(&ed->seqbase, &array, 0);
+       if(use_pointer)
+               seq_build_array(ed->seqbasep, &array, 0);
+       else
+               seq_build_array(&ed->seqbase, &array, 0);
 }
 
-void seq_begin(Editing *ed, SeqIterator *iter)
+void seq_begin(Editing *ed, SeqIterator *iter, int use_pointer)
 {
        memset(iter, 0, sizeof(*iter));
-       seq_array(ed, &iter->array, &iter->tot);
+       seq_array(ed, &iter->array, &iter->tot, use_pointer);
 
        if(iter->tot) {
                iter->cur= 0;
@@ -232,4 +297,2762 @@ void seq_end(SeqIterator *iter)
        iter->valid= 0;
 }
 
+/*
+  **********************************************************************
+  * build_seqar
+  **********************************************************************
+  * Build a complete array of _all_ sequencies (including those
+  * in metastrips!)
+  **********************************************************************
+*/
+
+static void do_seq_count(ListBase *seqbase, int *totseq)
+{
+       Sequence *seq;
+
+       seq= seqbase->first;
+       while(seq) {
+               (*totseq)++;
+               if(seq->seqbase.first) do_seq_count(&seq->seqbase, totseq);
+               seq= seq->next;
+       }
+}
+
+static void do_build_seqar(ListBase *seqbase, Sequence ***seqar, int depth)
+{
+       Sequence *seq;
+
+       seq= seqbase->first;
+       while(seq) {
+               seq->depth= depth;
+               if(seq->seqbase.first) do_build_seqar(&seq->seqbase, seqar, depth+1);
+               **seqar= seq;
+               (*seqar)++;
+               seq= seq->next;
+       }
+}
+
+void build_seqar(ListBase *seqbase, Sequence  ***seqar, int *totseq)
+{
+       Sequence **tseqar;
+
+       *totseq= 0;
+       do_seq_count(seqbase, totseq);
+
+       if(*totseq==0) {
+               *seqar= 0;
+               return;
+       }
+       *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar");
+       tseqar= *seqar;
+
+       do_build_seqar(seqbase, seqar, 0);
+       *seqar= tseqar;
+}
+
+static void do_seq_count_cb(ListBase *seqbase, int *totseq,
+                           int (*test_func)(Sequence * seq))
+{
+       Sequence *seq;
+
+       seq= seqbase->first;
+       while(seq) {
+               int test = test_func(seq);
+               if (test & BUILD_SEQAR_COUNT_CURRENT) {
+                       (*totseq)++;
+               }
+               if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) {
+                       do_seq_count_cb(&seq->seqbase, totseq, test_func);
+               }
+               seq= seq->next;
+       }
+}
+
+static void do_build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int depth,
+                             int (*test_func)(Sequence * seq))
+{
+       Sequence *seq;
+
+       seq= seqbase->first;
+       while(seq) {
+               int test = test_func(seq);
+               seq->depth= depth;
+
+               if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) {
+                       do_build_seqar_cb(&seq->seqbase, seqar, depth+1, 
+                                         test_func);
+               }
+               if (test & BUILD_SEQAR_COUNT_CURRENT) {
+                       **seqar= seq;
+                       (*seqar)++;
+               }
+               seq= seq->next;
+       }
+}
+
+void build_seqar_cb(ListBase *seqbase, Sequence  ***seqar, int *totseq,
+                   int (*test_func)(Sequence * seq))
+{
+       Sequence **tseqar;
+
+       *totseq= 0;
+       do_seq_count_cb(seqbase, totseq, test_func);
+
+       if(*totseq==0) {
+               *seqar= 0;
+               return;
+       }
+       *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar");
+       tseqar= *seqar;
+
+       do_build_seqar_cb(seqbase, seqar, 0, test_func);
+       *seqar= tseqar;
+}
+
+
+void calc_sequence_disp(Sequence *seq)
+{
+       if(seq->startofs && seq->startstill) seq->startstill= 0;
+       if(seq->endofs && seq->endstill) seq->endstill= 0;
+       
+       seq->startdisp= seq->start + seq->startofs - seq->startstill;
+       seq->enddisp= seq->start+seq->len - seq->endofs + seq->endstill;
+       
+       seq->handsize= 10.0;    /* 10 frames */
+       if( seq->enddisp-seq->startdisp < 10 ) {
+               seq->handsize= (float)(0.5*(seq->enddisp-seq->startdisp));
+       }
+       else if(seq->enddisp-seq->startdisp > 250) {
+               seq->handsize= (float)((seq->enddisp-seq->startdisp)/25);
+       }
+}
+
+void calc_sequence(Sequence *seq)
+{
+       Sequence *seqm;
+       int min, max;
+
+       /* check all metas recursively */
+       seqm= seq->seqbase.first;
+       while(seqm) {
+               if(seqm->seqbase.first) calc_sequence(seqm);
+               seqm= seqm->next;
+       }
+
+       /* effects and meta: automatic start and end */
+
+       if(seq->type & SEQ_EFFECT) {
+               /* pointers */
+               if(seq->seq2==0) seq->seq2= seq->seq1;
+               if(seq->seq3==0) seq->seq3= seq->seq1;
+
+               /* effecten go from seq1 -> seq2: test */
+
+               /* we take the largest start and smallest end */
+
+               // seq->start= seq->startdisp= MAX2(seq->seq1->startdisp, seq->seq2->startdisp);
+               // seq->enddisp= MIN2(seq->seq1->enddisp, seq->seq2->enddisp);
+
+               if (seq->seq1) {
+                       seq->start= seq->startdisp= MAX3(seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp);
+                       seq->enddisp= MIN3(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp);
+                       seq->len= seq->enddisp - seq->startdisp;
+               } else {
+                       calc_sequence_disp(seq);
+               }
+
+               if(seq->strip && seq->len!=seq->strip->len) {
+                       new_tstripdata(seq);
+               }
+
+       }
+       else {
+               if(seq->type==SEQ_META) {
+                       seqm= seq->seqbase.first;
+                       if(seqm) {
+                               min= 1000000;
+                               max= -1000000;
+                               while(seqm) {
+                                       if(seqm->startdisp < min) min= seqm->startdisp;
+                                       if(seqm->enddisp > max) max= seqm->enddisp;
+                                       seqm= seqm->next;
+                               }
+                               seq->start= min + seq->anim_startofs;
+                               seq->len = max-min;
+                               seq->len -= seq->anim_startofs;
+                               seq->len -= seq->anim_endofs;
+
+                               if(seq->strip && seq->len!=seq->strip->len) {
+                                       new_tstripdata(seq);
+                               }
+                       }
+               }
+               calc_sequence_disp(seq);
+       }
+}
+
+void reload_sequence_new_file(Scene *scene, Sequence * seq)
+{
+       char str[FILE_MAXDIR+FILE_MAXFILE];
+
+       if (!(seq->type == SEQ_MOVIE || seq->type == SEQ_IMAGE ||
+             seq->type == SEQ_HD_SOUND || seq->type == SEQ_RAM_SOUND ||
+             seq->type == SEQ_SCENE || seq->type == SEQ_META)) {
+               return;
+       }
+
+       new_tstripdata(seq);
+
+       if (seq->type != SEQ_SCENE && seq->type != SEQ_META &&
+           seq->type != SEQ_IMAGE) {
+               BLI_join_dirfile(str, seq->strip->dir, seq->strip->stripdata->name);
+               BLI_convertstringcode(str, G.sce);
+               BLI_convertstringframe(str, scene->r.cfra);
+               
+       }
+
+       if (seq->type == SEQ_IMAGE) {
+               /* Hack? */
+               int olen = MEM_allocN_len(seq->strip->stripdata)/sizeof(struct StripElem);
+               seq->len = olen;
+               seq->len -= seq->anim_startofs;
+               seq->len -= seq->anim_endofs;
+               if (seq->len < 0) {
+                       seq->len = 0;
+               }
+               seq->strip->len = seq->len;
+       } else if (seq->type == SEQ_MOVIE) {
+               if(seq->anim) IMB_free_anim(seq->anim);
+               seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0));
+
+               if (!seq->anim) {
+                       return;
+               }
+       
+               seq->len = IMB_anim_get_duration(seq->anim);
+               
+               seq->anim_preseek = IMB_anim_get_preseek(seq->anim);
+
+               seq->len -= seq->anim_startofs;
+               seq->len -= seq->anim_endofs;
+               if (seq->len < 0) {
+                       seq->len = 0;
+               }
+               seq->strip->len = seq->len;
+       } else if (seq->type == SEQ_HD_SOUND) {
+// XXX         if(seq->hdaudio) sound_close_hdaudio(seq->hdaudio);
+//             seq->hdaudio = sound_open_hdaudio(str);
+
+               if (!seq->hdaudio) {
+                       return;
+               }
+
+// XXX         seq->len = sound_hdaudio_get_duration(seq->hdaudio, FPS) - seq->anim_startofs - seq->anim_endofs;
+               if (seq->len < 0) {
+                       seq->len = 0;
+               }
+               seq->strip->len = seq->len;
+       } else if (seq->type == SEQ_RAM_SOUND) {
+               seq->len = (int) ( ((float)(seq->sound->streamlen-1)/
+                                   ((float)scene->audio.mixrate*4.0 ))
+                                  * FPS);
+               seq->len -= seq->anim_startofs;
+               seq->len -= seq->anim_endofs;
+               if (seq->len < 0) {
+                       seq->len = 0;
+               }
+               seq->strip->len = seq->len;
+       } else if (seq->type == SEQ_SCENE) {
+               Scene * sce = G.main->scene.first;
+               int nr = 1;
+               
+               while(sce) {
+                       if(nr == seq->scenenr) {
+                               break;
+                       }
+                       nr++;
+                       sce= sce->id.next;
+               }
+
+               if (sce) {
+                       seq->scene = sce;
+               } else {
+                       sce = seq->scene;
+               }
+
+               strncpy(seq->name + 2, sce->id.name + 2, 
+                       sizeof(seq->name) - 2);
+
+               seq->len= seq->scene->r.efra - seq->scene->r.sfra + 1;
+               seq->len -= seq->anim_startofs;
+               seq->len -= seq->anim_endofs;
+               if (seq->len < 0) {
+                       seq->len = 0;
+               }
+               seq->strip->len = seq->len;
+       }
+
+       calc_sequence(seq);
+}
+
+void sort_seq(Scene *scene)
+{
+       /* all strips together per kind, and in order of y location ("machine") */
+       ListBase seqbase, effbase;
+       Editing *ed;
+       Sequence *seq, *seqt;
+
+       ed= scene->ed;
+       if(ed==NULL) return;
+
+       seqbase.first= seqbase.last= 0;
+       effbase.first= effbase.last= 0;
+
+       while( (seq= ed->seqbasep->first) ) {
+               BLI_remlink(ed->seqbasep, seq);
+
+               if(seq->type & SEQ_EFFECT) {
+                       seqt= effbase.first;
+                       while(seqt) {
+                               if(seqt->machine>=seq->machine) {
+                                       BLI_insertlinkbefore(&effbase, seqt, seq);
+                                       break;
+                               }
+                               seqt= seqt->next;
+                       }
+                       if(seqt==0) BLI_addtail(&effbase, seq);
+               }
+               else {
+                       seqt= seqbase.first;
+                       while(seqt) {
+                               if(seqt->machine>=seq->machine) {
+                                       BLI_insertlinkbefore(&seqbase, seqt, seq);
+                                       break;
+                               }
+                               seqt= seqt->next;
+                       }
+                       if(seqt==0) BLI_addtail(&seqbase, seq);
+               }
+       }
+
+       addlisttolist(&seqbase, &effbase);
+       *(ed->seqbasep)= seqbase;
+}
+
+
+void clear_scene_in_allseqs(Scene *sce)
+{
+       Scene *sce1;
+       Editing *ed;
+       Sequence *seq;
+
+       /* when a scene is deleted: test all seqs */
+
+       sce1= G.main->scene.first;
+       while(sce1) {
+               if(sce1!=sce && sce1->ed) {
+                       ed= sce1->ed;
+
+                       SEQ_BEGIN(ed, seq) {
+
+                               if(seq->scene==sce) seq->scene= 0;
+
+                       }
+                       SEQ_END
+               }
+
+               sce1= sce1->id.next;
+       }
+}
+
+char *give_seqname_by_type(int type)
+{
+       switch(type) {
+       case SEQ_META:       return "Meta";
+       case SEQ_IMAGE:      return "Image";
+       case SEQ_SCENE:      return "Scene";
+       case SEQ_MOVIE:      return "Movie";
+       case SEQ_RAM_SOUND:  return "Audio (RAM)";
+       case SEQ_HD_SOUND:   return "Audio (HD)";
+       case SEQ_CROSS:      return "Cross";
+       case SEQ_GAMCROSS:   return "Gamma Cross";
+       case SEQ_ADD:        return "Add";
+       case SEQ_SUB:        return "Sub";
+       case SEQ_MUL:        return "Mul";
+       case SEQ_ALPHAOVER:  return "Alpha Over";
+       case SEQ_ALPHAUNDER: return "Alpha Under";
+       case SEQ_OVERDROP:   return "Over Drop";
+       case SEQ_WIPE:       return "Wipe";
+       case SEQ_GLOW:       return "Glow";
+       case SEQ_TRANSFORM:  return "Transform";
+       case SEQ_COLOR:      return "Color";
+       case SEQ_SPEED:      return "Speed";
+       default:
+               return 0;
+       }
+}
+
+char *give_seqname(Sequence *seq)
+{
+       char * name = give_seqname_by_type(seq->type);
+
+       if (!name) {
+               if(seq->type<SEQ_EFFECT) {
+                       return seq->strip->dir;
+               } else if(seq->type==SEQ_PLUGIN) {
+                       if(!(seq->flag & SEQ_EFFECT_NOT_LOADED) &&
+                          seq->plugin && seq->plugin->doit) {
+                               return seq->plugin->pname;
+                       } else {
+                               return "Plugin";
+                       }
+               } else {
+                       return "Effect";
+               }
+       }
+       return name;
+}
+
+/* ***************** DO THE SEQUENCE ***************** */
+
+static void make_black_ibuf(ImBuf *ibuf)
+{
+       unsigned int *rect;
+       float *rect_float;
+       int tot;
+
+       if(ibuf==0 || (ibuf->rect==0 && ibuf->rect_float==0)) return;
+
+       tot= ibuf->x*ibuf->y;
+
+       rect= ibuf->rect;
+       rect_float = ibuf->rect_float;
+
+       if (rect) {
+               memset(rect,       0, tot * sizeof(char) * 4);
+       }
+
+       if (rect_float) {
+               memset(rect_float, 0, tot * sizeof(float) * 4);
+       }
+}
+
+static void multibuf(ImBuf *ibuf, float fmul)
+{
+       char *rt;
+       float *rt_float;
+
+       int a, mul, icol;
+
+       mul= (int)(256.0*fmul);
+       rt= (char *)ibuf->rect;
+       rt_float = ibuf->rect_float;
+
+       if (rt) {
+               a= ibuf->x*ibuf->y;
+               while(a--) {
+
+                       icol= (mul*rt[0])>>8;
+                       if(icol>254) rt[0]= 255; else rt[0]= icol;
+                       icol= (mul*rt[1])>>8;
+                       if(icol>254) rt[1]= 255; else rt[1]= icol;
+                       icol= (mul*rt[2])>>8;
+                       if(icol>254) rt[2]= 255; else rt[2]= icol;
+                       icol= (mul*rt[3])>>8;
+                       if(icol>254) rt[3]= 255; else rt[3]= icol;
+                       
+                       rt+= 4;
+               }
+       }
+       if (rt_float) {
+               a= ibuf->x*ibuf->y;
+               while(a--) {
+                       rt_float[0] *= fmul;
+                       rt_float[1] *= fmul;
+                       rt_float[2] *= fmul;
+                       rt_float[3] *= fmul;
+                       
+                       rt_float += 4;
+               }
+       }
+}
+
+static void do_effect(Scene *scene, int cfra, Sequence *seq, TStripElem * se)
+{
+       TStripElem *se1, *se2, *se3;
+       float fac, facf;
+       int x, y;
+       int early_out;
+       struct SeqEffectHandle sh = get_sequence_effect(seq);
+
+       if (!sh.execute) { /* effect not supported in this version... */
+               make_black_ibuf(se->ibuf);
+               return;
+       }
+
+       if(seq->ipo && seq->ipo->curve.first) {
+               do_seq_ipo(scene, seq, cfra);
+               fac= seq->facf0;
+               facf= seq->facf1;
+       } else {
+               sh.get_default_fac(seq, cfra, &fac, &facf);
+       }
+
+       if( !(scene->r.mode & R_FIELDS) ) facf = fac;
+
+       early_out = sh.early_out(seq, fac, facf);
+
+       if (early_out == -1) { /* no input needed */
+               sh.execute(seq, cfra, fac, facf, 
+                          se->ibuf->x, se->ibuf->y, 
+                          0, 0, 0, se->ibuf);
+               return;
+       }
+
+       switch (early_out) {
+       case 0:
+               if (se->se1==0 || se->se2==0 || se->se3==0) {
+                       make_black_ibuf(se->ibuf);
+                       return;
+               }
+
+               se1= se->se1;
+               se2= se->se2;
+               se3= se->se3;
+
+               if (   (se1==0 || se2==0 || se3==0)
+                   || (se1->ibuf==0 || se2->ibuf==0 || se3->ibuf==0)) {
+                       make_black_ibuf(se->ibuf);
+                       return;
+               }
+
+               break;
+       case 1:
+               if (se->se1 == 0) {
+                       make_black_ibuf(se->ibuf);
+                       return;
+               }
+
+               se1= se->se1;
+
+               if (se1 == 0 || se1->ibuf == 0) {
+                       make_black_ibuf(se->ibuf);
+                       return;
+               }
+
+               if (se->ibuf != se1->ibuf) {
+                       IMB_freeImBuf(se->ibuf);
+                       se->ibuf = se1->ibuf;
+                       IMB_refImBuf(se->ibuf);
+               }
+               return;
+       case 2:
+               if (se->se2 == 0) {
+                       make_black_ibuf(se->ibuf);
+                       return;
+               }
+
+               se2= se->se2;
+
+               if (se2 == 0 || se2->ibuf == 0) {
+                       make_black_ibuf(se->ibuf);
+                       return;
+               }
+               if (se->ibuf != se2->ibuf) {
+                       IMB_freeImBuf(se->ibuf);
+                       se->ibuf = se2->ibuf;
+                       IMB_refImBuf(se->ibuf);
+               }
+               return;
+       default:
+               make_black_ibuf(se->ibuf);
+               return;
+       }
+
+       x= se2->ibuf->x;
+       y= se2->ibuf->y;
+
+       if (!se1->ibuf->rect_float && se->ibuf->rect_float) {
+               IMB_float_from_rect(se1->ibuf);
+       }
+       if (!se2->ibuf->rect_float && se->ibuf->rect_float) {
+               IMB_float_from_rect(se2->ibuf);
+       }
+       if (!se3->ibuf->rect_float && se->ibuf->rect_float) {
+               IMB_float_from_rect(se3->ibuf);
+       }
+       
+       if (!se1->ibuf->rect && !se->ibuf->rect_float) {
+               IMB_rect_from_float(se1->ibuf);
+       }
+       if (!se2->ibuf->rect && !se->ibuf->rect_float) {
+               IMB_rect_from_float(se2->ibuf);
+       }
+       if (!se3->ibuf->rect && !se->ibuf->rect_float) {
+               IMB_rect_from_float(se3->ibuf);
+       }
+
+       sh.execute(seq, cfra, fac, facf, x, y, se1->ibuf, se2->ibuf, se3->ibuf,
+                  se->ibuf);
+}
+
+static int give_stripelem_index(Sequence *seq, int cfra)
+{
+       int nr;
+
+       if(seq->startdisp >cfra || seq->enddisp <= cfra) return -1;
+       if(seq->len == 0) return -1;
+       if(seq->flag&SEQ_REVERSE_FRAMES) {      
+               /*reverse frame in this sequence */
+               if(cfra <= seq->start) nr= seq->len-1;
+               else if(cfra >= seq->start+seq->len-1) nr= 0;
+               else nr= (seq->start + seq->len) - cfra;
+       } else {
+               if(cfra <= seq->start) nr= 0;
+               else if(cfra >= seq->start+seq->len-1) nr= seq->len-1;
+               else nr= cfra-seq->start;
+       }
+       if (seq->strobe < 1.0) seq->strobe = 1.0;
+       if (seq->strobe > 1.0) {
+               nr -= (int)fmod((double)nr, (double)seq->strobe);
+       }
+
+       return nr;
+}
+
+static TStripElem* alloc_tstripdata(int len, const char * name)
+{
+       int i;
+       TStripElem *se = MEM_callocN(len * sizeof(TStripElem), name);
+       for (i = 0; i < len; i++) {
+               se[i].ok = STRIPELEM_OK;
+       }
+       return se;
+}
+
+TStripElem *give_tstripelem(Sequence *seq, int cfra)
+{
+       TStripElem *se;
+       int nr;
+
+       se = seq->strip->tstripdata;
+       if (se == 0 && seq->len > 0) {
+               se = seq->strip->tstripdata = alloc_tstripdata(seq->len,
+                                                              "tstripelems");
+       }
+       nr = give_stripelem_index(seq, cfra);
+
+       if (nr == -1) return 0;
+       if (se == 0) return 0;
+
+       se += nr; 
+
+       /* if there are IPOs with blend modes active, one has to watch out
+          for startstill + endstill area: we can't use the same tstripelem
+          here for all ibufs, since then, blending with IPOs won't work!
+          
+          Rather common case, if you use a single image and try to fade
+          it in and out... or want to use your strip as a watermark in
+          alpha over mode...
+       */
+       if (seq->blend_mode != SEQ_BLEND_REPLACE ||
+           (seq->ipo && seq->ipo->curve.first && (
+                   !(seq->type & SEQ_EFFECT) || !seq->seq1))) {
+               Strip * s = seq->strip;
+               if (cfra < seq->start) {
+                       se = s->tstripdata_startstill;
+                       if (seq->startstill > s->startstill) {
+                               free_tstripdata(s->startstill, 
+                                               s->tstripdata_startstill);
+                               se = 0;
+                       }
+
+                       if (se == 0) {
+                               s->startstill = seq->startstill;
+                               se = seq->strip->tstripdata_startstill
+                                       = alloc_tstripdata(
+                                               s->startstill,
+                                               "tstripelems_startstill");
+                       }
+                       se += seq->start - cfra - 1;
+
+               } else if (cfra > seq->start + seq->len-1) {
+                       se = s->tstripdata_endstill;
+                       if (seq->endstill > s->endstill) {
+                               free_tstripdata(s->endstill, 
+                                               s->tstripdata_endstill);
+                               se = 0;
+                       }
+
+                       if (se == 0) {
+                               s->endstill = seq->endstill;
+                               se = seq->strip->tstripdata_endstill
+                                       = alloc_tstripdata(
+                                               s->endstill,
+                                               "tstripelems_endstill");
+                       }
+                       se += cfra - (seq->start + seq->len-1) - 1;
+               }
+       }
+
+       
+       se->nr= nr;
+
+       return se;
+}
+
+StripElem *give_stripelem(Sequence *seq, int cfra)
+{
+       StripElem *se;
+       int nr;
+
+       se = seq->strip->stripdata;
+       nr = give_stripelem_index(seq, cfra);
+
+       if (nr == -1) return 0;
+       if (se == 0) return 0;
+
+       se += nr + seq->anim_startofs; 
+       
+       return se;
+}
+
+static int evaluate_seq_frame_gen(Sequence ** seq_arr, ListBase *seqbase, int cfra)
+{
+       Sequence *seq;
+       int totseq=0;
+
+       memset(seq_arr, 0, sizeof(Sequence*) * (MAXSEQ+1));
+
+       seq= seqbase->first;
+       while(seq) {
+               if(seq->startdisp <=cfra && seq->enddisp > cfra) {
+                       seq_arr[seq->machine]= seq;
+                       totseq++;
+               }
+               seq= seq->next;
+       }
+
+       return totseq;
+}
+
+int evaluate_seq_frame(Scene *scene, int cfra)
+{
+       Editing *ed;
+       Sequence *seq_arr[MAXSEQ+1];
+
+       ed= scene->ed;
+       if(ed==NULL) return 0;
+       
+       return evaluate_seq_frame_gen(seq_arr, ed->seqbasep, cfra);
+
+}
+
+static int video_seq_is_rendered(Sequence * seq)
+{
+       return (seq 
+               && !(seq->flag & SEQ_MUTE) 
+               && seq->type != SEQ_RAM_SOUND 
+               && seq->type != SEQ_HD_SOUND);
+}
+
+static int get_shown_sequences(        ListBase * seqbasep, int cfra, int chanshown, Sequence ** seq_arr_out)
+{
+       Sequence *seq_arr[MAXSEQ+1];
+       int b = chanshown;
+       int cnt = 0;
+
+       if (b > MAXSEQ) {
+               return 0;
+       }
+
+       if(evaluate_seq_frame_gen(seq_arr, seqbasep, cfra)) {
+               if (b > 0) {
+                       if (seq_arr[b] == 0) {
+                               return 0;
+                       }
+               } else {
+                       for (b = MAXSEQ; b > 0; b--) {
+                               if (video_seq_is_rendered(seq_arr[b])) {
+                                       break;
+                               }
+                       }
+               }
+       }
+       
+       chanshown = b;
+
+       for (;b > 0; b--) {
+               if (video_seq_is_rendered(seq_arr[b])) {
+                       if (seq_arr[b]->blend_mode == SEQ_BLEND_REPLACE) {
+                               break;
+                       }
+               }
+       }
+
+       for (;b <= chanshown; b++) {
+               if (video_seq_is_rendered(seq_arr[b])) {
+                       seq_arr_out[cnt++] = seq_arr[b];
+               }
+       }
+
+       return cnt;
+}
+
+/* **********************************************************************
+   proxy management
+   ********************************************************************** */
+
+#define PROXY_MAXFILE (2*FILE_MAXDIR+FILE_MAXFILE)
+
+static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * name)
+{
+       int frameno;
+       char dir[FILE_MAXDIR];
+
+       if (!seq->strip->proxy) {
+               return FALSE;
+       }
+
+       if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) {
+               strcpy(dir, seq->strip->proxy->dir);
+       } else {
+               if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) {
+                       snprintf(dir, FILE_MAXDIR, "%s/BL_proxy", 
+                                seq->strip->dir);
+               } else {
+                       return FALSE;
+               }
+       }
+
+       /* generate a seperate proxy directory for each preview size */
+
+       if (seq->type == SEQ_IMAGE) {
+               StripElem * se = give_stripelem(seq, cfra);
+               snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy",
+                        dir, scene->r.size, se->name);
+               frameno = 1;
+       } else if (seq->type == SEQ_MOVIE) {
+               TStripElem * tse = give_tstripelem(seq, cfra);
+
+               frameno = tse->nr + seq->anim_startofs;
+
+               snprintf(name, PROXY_MAXFILE, "%s/%s/%d/####", dir,
+                        seq->strip->stripdata->name,
+                        scene->r.size);
+       } else {
+               TStripElem * tse = give_tstripelem(seq, cfra);
+
+               frameno = tse->nr + seq->anim_startofs;
+
+               snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir,
+                        scene->r.size);
+       }
+
+       BLI_convertstringcode(name, G.sce);
+       BLI_convertstringframe(name, frameno);
+       
+
+       strcat(name, ".jpg");
+
+       return TRUE;
+}
+
+static struct ImBuf * seq_proxy_fetch(Scene *scene, Sequence * seq, int cfra)
+{
+       char name[PROXY_MAXFILE];
+
+       if (!(seq->flag & SEQ_USE_PROXY)) {
+               return 0;
+       }
+
+       /* rendering at 100% ? No real sense in proxy-ing, right? */
+       if (scene->r.size == 100.0) {
+               return 0;
+       }
+
+       if (!seq_proxy_get_fname(scene, seq, cfra, name)) {
+               return 0;
+       }
+
+       if (BLI_exists(name)) {
+               return IMB_loadiffname(name, IB_rect);
+       } else {
+               return 0;
+       }
+}
+
+static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra,
+                             int build_proxy_run);
+
+static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra)
+{
+       char name[PROXY_MAXFILE];
+       int quality;
+       TStripElem * se;
+       int ok;
+       int rectx, recty;
+       struct ImBuf * ibuf;
+
+       if (!(seq->flag & SEQ_USE_PROXY)) {
+               return;
+       }
+
+       /* rendering at 100% ? No real sense in proxy-ing, right? */
+       if (scene->r.size == 100.0) {
+               return;
+       }
+
+       if (!seq_proxy_get_fname(scene, seq, cfra, name)) {
+               return;
+       }
+
+       se = give_tstripelem(seq, cfra);
+       if (!se) {
+               return;
+       }
+
+       if(se->ibuf) {
+               IMB_freeImBuf(se->ibuf);
+               se->ibuf = 0;
+       }
+       
+       do_build_seq_ibuf(scene, seq, se, cfra, TRUE);
+
+       if (!se->ibuf) {
+               return;
+       }
+
+       rectx= (scene->r.size*scene->r.xsch)/100;
+       recty= (scene->r.size*scene->r.ysch)/100;
+
+       ibuf = se->ibuf;
+
+       if (ibuf->x != rectx || ibuf->y != recty) {
+               IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty);
+       }
+
+       /* quality is fixed, otherwise one has to generate seperate
+          directories for every quality...
+
+          depth = 32 is intentionally left in, otherwise ALPHA channels
+          won't work... */
+       quality = 90;
+       ibuf->ftype= JPG | quality;
+
+       BLI_make_existing_file(name);
+       
+       ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat);
+       if (ok == 0) {
+               perror(name);
+       }
+
+       IMB_freeImBuf(ibuf);
+       se->ibuf = 0;
+}
+
+void seq_proxy_rebuild(Scene *scene, Sequence * seq)
+{
+       int cfra;
+
+       waitcursor(1);
+
+       G.afbreek = 0;
+
+       /* flag management tries to account for strobe and 
+          other "non-linearities", that might come in the future...
+          better way would be to "touch" the files, so that _really_
+          no one is rebuild twice.
+        */
+
+       for (cfra = seq->startdisp; cfra < seq->enddisp; cfra++) {
+               TStripElem * tse = give_tstripelem(seq, cfra);
+
+               tse->flag &= ~STRIPELEM_PREVIEW_DONE;
+       }
+
+       /* a _lot_ faster for movie files, if we read frames in
+          sequential order */
+       if (seq->flag & SEQ_REVERSE_FRAMES) {
+               for (cfra = seq->enddisp-seq->endstill-1; 
+                    cfra >= seq->startdisp + seq->startstill; cfra--) {
+                       TStripElem * tse = give_tstripelem(seq, cfra);
+
+                       if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) {
+                               seq_proxy_build_frame(scene, seq, cfra);
+                               tse->flag |= STRIPELEM_PREVIEW_DONE;
+                       }
+                       if (blender_test_break()) {
+                               break;
+                       }
+               }
+       } else {
+               for (cfra = seq->startdisp + seq->startstill; 
+                    cfra < seq->enddisp - seq->endstill; cfra++) {
+                       TStripElem * tse = give_tstripelem(seq, cfra);
+
+                       if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) {
+                               seq_proxy_build_frame(scene, seq, cfra);
+                               tse->flag |= STRIPELEM_PREVIEW_DONE;
+                       }
+                       if (blender_test_break()) {
+                               break;
+                       }
+               }
+       }
+       waitcursor(0);
+}
+
+
+/* **********************************************************************
+   color balance 
+   ********************************************************************** */
+
+static StripColorBalance calc_cb(StripColorBalance * cb_)
+{
+       StripColorBalance cb = *cb_;
+       int c;
+
+       if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_LIFT) {
+               for (c = 0; c < 3; c++) {
+                       cb.lift[c] = 1.0 - cb.lift[c];
+               }
+       } else {
+               for (c = 0; c < 3; c++) {
+                       cb.lift[c] = -(1.0 - cb.lift[c]);
+               }
+       }
+       if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAIN) {
+               for (c = 0; c < 3; c++) {
+                       if (cb.gain[c] != 0.0) {
+                               cb.gain[c] = 1.0/cb.gain[c];
+                       } else {
+                               cb.gain[c] = 1000000; /* should be enough :) */
+                       }
+               }
+       }
+
+       if (!(cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAMMA)) {
+               for (c = 0; c < 3; c++) {
+                       if (cb.gamma[c] != 0.0) {
+                               cb.gamma[c] = 1.0/cb.gamma[c];
+                       } else {
+                               cb.gamma[c] = 1000000; /* should be enough :) */
+                       }
+               }
+       }
+
+       return cb;
+}
+
+static void make_cb_table_byte(float lift, float gain, float gamma,
+                              unsigned char * table, float mul)
+{
+       int y;
+
+       for (y = 0; y < 256; y++) {
+               float v = 1.0 * y / 255;
+               v *= gain;
+               v += lift; 
+               v = pow(v, gamma);
+               v *= mul;
+               if ( v > 1.0) {
+                       v = 1.0;
+               } else if (v < 0.0) {
+                       v = 0.0;
+               }
+               table[y] = v * 255;
+       }
+
+}
+
+static void make_cb_table_float(float lift, float gain, float gamma,
+                               float * table, float mul)
+{
+       int y;
+
+       for (y = 0; y < 256; y++) {
+               float v = (float) y * 1.0 / 255.0;
+               v *= gain;
+               v += lift;
+               v = pow(v, gamma);
+               v *= mul;
+               table[y] = v;
+       }
+}
+
+static void color_balance_byte_byte(Sequence * seq, TStripElem* se, float mul)
+{
+       unsigned char cb_tab[3][256];
+       int c;
+       unsigned char * p = (unsigned char*) se->ibuf->rect;
+       unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y;
+
+       StripColorBalance cb = calc_cb(seq->strip->color_balance);
+
+       for (c = 0; c < 3; c++) {
+               make_cb_table_byte(cb.lift[c], cb.gain[c], cb.gamma[c],
+                                  cb_tab[c], mul);
+       }
+
+       while (p < e) {
+               p[0] = cb_tab[0][p[0]];
+               p[1] = cb_tab[1][p[1]];
+               p[2] = cb_tab[2][p[2]];
+               
+               p += 4;
+       }
+}
+
+static void color_balance_byte_float(Sequence * seq, TStripElem* se, float mul)
+{
+       float cb_tab[4][256];
+       int c,i;
+       unsigned char * p = (unsigned char*) se->ibuf->rect;
+       unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y;
+       float * o;
+       StripColorBalance cb;
+
+       imb_addrectfloatImBuf(se->ibuf);
+
+       o = se->ibuf->rect_float;
+
+       cb = calc_cb(seq->strip->color_balance);
+
+       for (c = 0; c < 3; c++) {
+               make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c],
+                                   cb_tab[c], mul);
+       }
+
+       for (i = 0; i < 256; i++) {
+               cb_tab[3][i] = ((float)i)*(1.0f/255.0f);
+       }
+
+       while (p < e) {
+               o[0] = cb_tab[0][p[0]];
+               o[1] = cb_tab[1][p[1]];
+               o[2] = cb_tab[2][p[2]];
+               o[3] = cb_tab[3][p[3]];
+
+               p += 4; o += 4;
+       }
+}
+
+static void color_balance_float_float(Sequence * seq, TStripElem* se, float mul)
+{
+       float * p = se->ibuf->rect_float;
+       float * e = se->ibuf->rect_float + se->ibuf->x * 4* se->ibuf->y;
+       StripColorBalance cb = calc_cb(seq->strip->color_balance);
+
+       while (p < e) {
+               int c;
+               for (c = 0; c < 3; c++) {
+                       p[c] = pow(p[c] * cb.gain[c] + cb.lift[c], 
+                                  cb.gamma[c]) * mul;
+               }
+               p += 4;
+       }
+}
+
+static void color_balance(Sequence * seq, TStripElem* se, float mul)
+{
+       if (se->ibuf->rect_float) {
+               color_balance_float_float(seq, se, mul);
+       } else if(seq->flag & SEQ_MAKE_FLOAT) {
+               color_balance_byte_float(seq, se, mul);
+       } else {
+               color_balance_byte_byte(seq, se, mul);
+       }
+}
+
+/*
+  input preprocessing for SEQ_IMAGE, SEQ_MOVIE and SEQ_SCENE
+
+  Do all the things you can't really do afterwards using sequence effects
+  (read: before rescaling to render resolution has been done)
+
+  Order is important!
+
+  - Deinterlace
+  - Crop and transform in image source coordinate space
+  - Flip X + Flip Y (could be done afterwards, backward compatibility)
+  - Promote image to float data (affects pipeline operations afterwards)
+  - Color balance (is most efficient in the byte -> float 
+    (future: half -> float should also work fine!)
+    case, if done on load, since we can use lookup tables)
+  - Premultiply
+
+*/
+
+static int input_have_to_preprocess(Scene *scene, Sequence * seq, TStripElem* se, int cfra)
+{
+       float mul;
+
+       if ((seq->flag & SEQ_FILTERY) || 
+           (seq->flag & SEQ_USE_CROP) ||
+           (seq->flag & SEQ_USE_TRANSFORM) ||
+           (seq->flag & SEQ_FLIPX) ||
+           (seq->flag & SEQ_FLIPY) ||
+           (seq->flag & SEQ_USE_COLOR_BALANCE) ||
+           (seq->flag & SEQ_MAKE_PREMUL) ||
+           (se->ibuf->x != seqrectx || se->ibuf->y != seqrecty)) {
+               return TRUE;
+       }
+
+       mul = seq->mul;
+
+       if(seq->blend_mode == SEQ_BLEND_REPLACE) {
+               if (seq->ipo && seq->ipo->curve.first) {
+                       do_seq_ipo(scene, seq, cfra);
+                       mul *= seq->facf0;
+               }
+               mul *= seq->blend_opacity / 100.0;
+       }
+
+       if (mul != 1.0) {
+               return TRUE;
+       }
+               
+       return FALSE;
+}
+
+static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cfra)
+{
+       float mul;
+
+       seq->strip->orx= se->ibuf->x;
+       seq->strip->ory= se->ibuf->y;
+
+       if((seq->flag & SEQ_FILTERY) && seq->type != SEQ_MOVIE) {
+               IMB_filtery(se->ibuf);
+       }
+
+       if(seq->flag & SEQ_USE_CROP || seq->flag & SEQ_USE_TRANSFORM) {
+               StripCrop c;
+               StripTransform t;
+               int sx,sy,dx,dy;
+
+               memset(&c, 0, sizeof(StripCrop));
+               memset(&t, 0, sizeof(StripTransform));
+
+               if(seq->flag & SEQ_USE_CROP && seq->strip->crop) {
+                       c = *seq->strip->crop;
+               }
+               if(seq->flag & SEQ_USE_TRANSFORM && seq->strip->transform) {
+                       t = *seq->strip->transform;
+               }
+
+               sx = se->ibuf->x - c.left - c.right;
+               sy = se->ibuf->y - c.top - c.bottom;
+               dx = sx;
+               dy = sy;
+
+               if (seq->flag & SEQ_USE_TRANSFORM) {
+                       dx = scene->r.xsch;
+                       dy = scene->r.ysch;
+               }
+
+               if (c.top + c.bottom >= se->ibuf->y ||
+                   c.left + c.right >= se->ibuf->x ||
+                   t.xofs >= dx || t.yofs >= dy) {
+                       make_black_ibuf(se->ibuf);
+               } else {
+                       ImBuf * i;
+
+                       if (se->ibuf->rect_float) {
+                               i = IMB_allocImBuf(dx, dy,32, IB_rectfloat, 0);
+                       } else {
+                               i = IMB_allocImBuf(dx, dy,32, IB_rect, 0);
+                       }
+
+                       IMB_rectcpy(i, se->ibuf, 
+                                   t.xofs, t.yofs, 
+                                   c.left, c.bottom, 
+                                   sx, sy);
+
+                       IMB_freeImBuf(se->ibuf);
+
+                       se->ibuf = i;
+               }
+       } 
+
+       if(seq->flag & SEQ_FLIPX) {
+               IMB_flipx(se->ibuf);
+       }
+       if(seq->flag & SEQ_FLIPY) {
+               IMB_flipy(se->ibuf);
+       }
+
+       if(seq->mul == 0.0) {
+               seq->mul = 1.0;
+       }
+
+       mul = seq->mul;
+
+       if(seq->blend_mode == SEQ_BLEND_REPLACE) {
+               if (seq->ipo && seq->ipo->curve.first) {
+                       do_seq_ipo(scene, seq, cfra);
+                       mul *= seq->facf0;
+               }
+               mul *= seq->blend_opacity / 100.0;
+       }
+
+       if(seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) {
+               color_balance(seq, se, mul);
+               mul = 1.0;
+       }
+
+       if(seq->flag & SEQ_MAKE_FLOAT) {
+               if (!se->ibuf->rect_float) {
+                       IMB_float_from_rect(se->ibuf);
+               }
+               if (se->ibuf->rect) {
+                       imb_freerectImBuf(se->ibuf);
+               }
+       }
+
+       if(mul != 1.0) {
+               multibuf(se->ibuf, mul);
+       }
+
+       if(seq->flag & SEQ_MAKE_PREMUL) {
+               if(se->ibuf->depth == 32 && se->ibuf->zbuf == 0) {
+                       converttopremul(se->ibuf);
+               }
+       }
+
+
+       if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) {
+               if(scene->r.mode & R_OSA) {
+                       IMB_scaleImBuf(se->ibuf, 
+                                      (short)seqrectx, (short)seqrecty);
+               } else {
+                       IMB_scalefastImBuf(se->ibuf, 
+                                          (short)seqrectx, (short)seqrecty);
+               }
+       }
+}
+
+/* test if image too small or discarded from cache: reload */
+
+static void test_and_auto_discard_ibuf(TStripElem * se)
+{
+       if (se->ibuf) {
+               if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty 
+                  || !(se->ibuf->rect || se->ibuf->rect_float)) {
+                       IMB_freeImBuf(se->ibuf);
+
+                       se->ibuf= 0;
+                       se->ok= STRIPELEM_OK;
+               }
+       }
+       if (se->ibuf_comp) {
+               if(se->ibuf_comp->x != seqrectx || se->ibuf_comp->y != seqrecty 
+                  || !(se->ibuf_comp->rect || se->ibuf_comp->rect_float)) {
+                       IMB_freeImBuf(se->ibuf_comp);
+
+                       se->ibuf_comp = 0;
+               }
+       }
+}
+
+static void test_and_auto_discard_ibuf_stills(Strip * strip)
+{
+       if (strip->ibuf_startstill) {
+               if (!strip->ibuf_startstill->rect &&
+                   !strip->ibuf_startstill->rect_float) {
+                       IMB_freeImBuf(strip->ibuf_startstill);
+                       strip->ibuf_startstill = 0;
+               }
+       }
+       if (strip->ibuf_endstill) {
+               if (!strip->ibuf_endstill->rect &&
+                   !strip->ibuf_endstill->rect_float) {
+                       IMB_freeImBuf(strip->ibuf_endstill);
+                       strip->ibuf_endstill = 0;
+               }
+       }
+}
+
+static void copy_from_ibuf_still(Sequence * seq, TStripElem * se)
+{
+       if (!se->ibuf) {
+               if (se->nr == 0 && seq->strip->ibuf_startstill) {
+                       IMB_cache_limiter_touch(seq->strip->ibuf_startstill);
+
+                       se->ibuf = IMB_dupImBuf(seq->strip->ibuf_startstill);
+               }
+               if (se->nr == seq->len - 1 
+                   && (seq->len != 1)
+                   && seq->strip->ibuf_endstill) {
+                       IMB_cache_limiter_touch(seq->strip->ibuf_endstill);
+
+                       se->ibuf = IMB_dupImBuf(seq->strip->ibuf_endstill);
+               }
+       }
+}
+
+static void copy_to_ibuf_still(Sequence * seq, TStripElem * se)
+{
+       if (se->ibuf) {
+               if (se->nr == 0) {
+                       seq->strip->ibuf_startstill = IMB_dupImBuf(se->ibuf);
+
+                       IMB_cache_limiter_insert(seq->strip->ibuf_startstill);
+                       IMB_cache_limiter_touch(seq->strip->ibuf_startstill);
+               }
+               if (se->nr == seq->len - 1 && seq->len != 1) {
+                       seq->strip->ibuf_endstill = IMB_dupImBuf(se->ibuf);
+
+                       IMB_cache_limiter_insert(seq->strip->ibuf_endstill);
+                       IMB_cache_limiter_touch(seq->strip->ibuf_endstill);
+               }
+       }
+}
+
+static void free_metastrip_imbufs(ListBase *seqbasep, int cfra, int chanshown)
+{
+       Sequence* seq_arr[MAXSEQ+1];
+       int i;
+       TStripElem* se = 0;
+
+       evaluate_seq_frame_gen(seq_arr, seqbasep, cfra);
+
+       for (i = 0; i < MAXSEQ; i++) {
+               if (!video_seq_is_rendered(seq_arr[i])) {
+                       continue;
+               }
+               se = give_tstripelem(seq_arr[i], cfra);
+               if (se) {
+                       if (se->ibuf) {
+                               IMB_freeImBuf(se->ibuf);
+
+                               se->ibuf= 0;
+                               se->ok= STRIPELEM_OK;
+                       }
+
+                       if (se->ibuf_comp) {
+                               IMB_freeImBuf(se->ibuf_comp);
+
+                               se->ibuf_comp = 0;
+                       }
+               }
+       }
+       
+}
+
+static TStripElem* do_build_seq_array_recursively(Scene *scene,
+                               ListBase *seqbasep, int cfra, int chanshown);
+
+static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra,
+                             int build_proxy_run)
+{
+       char name[FILE_MAXDIR+FILE_MAXFILE];
+       int use_limiter = TRUE;
+
+       test_and_auto_discard_ibuf(se);
+       test_and_auto_discard_ibuf_stills(seq->strip);
+
+       if(seq->type == SEQ_META) {
+               TStripElem * meta_se = 0;
+               use_limiter = FALSE;
+
+               if (!build_proxy_run && se->ibuf == 0) {
+                       se->ibuf = seq_proxy_fetch(scene, seq, cfra);
+                       if (se->ibuf) {
+                               use_limiter = TRUE;
+                       }
+               }
+
+               if(!se->ibuf && seq->seqbase.first) {
+                       meta_se = do_build_seq_array_recursively(scene,
+                               &seq->seqbase, seq->start + se->nr, 0);
+               }
+
+               se->ok = STRIPELEM_OK;
+
+               if(!se->ibuf && meta_se) {
+                       se->ibuf = meta_se->ibuf_comp;
+                       if(se->ibuf &&
+                          (!input_have_to_preprocess(scene, seq, se, cfra) ||
+                           build_proxy_run)) {
+                               IMB_refImBuf(se->ibuf);
+                               if (build_proxy_run) {
+                                       IMB_cache_limiter_unref(se->ibuf);
+                               }
+                       } else if (se->ibuf) {
+                               struct ImBuf * i = IMB_dupImBuf(se->ibuf);
+
+                               IMB_cache_limiter_unref(se->ibuf);
+
+                               se->ibuf = i;
+
+                               use_limiter = TRUE;
+                       }
+               }
+               if (meta_se) {
+                       free_metastrip_imbufs(
+                               &seq->seqbase, seq->start + se->nr, 0);
+               }
+
+               if (use_limiter) {
+                       input_preprocess(scene, seq, se, cfra);
+               }
+       } else if(seq->type & SEQ_EFFECT) {
+               /* should the effect be recalculated? */
+               
+               if (!build_proxy_run && se->ibuf == 0) {
+                       se->ibuf = seq_proxy_fetch(scene, seq, cfra);
+               }
+
+               if(se->ibuf == 0) {
+                       /* if any inputs are rectfloat, output is float too */
+                       if((se->se1 && se->se1->ibuf && se->se1->ibuf->rect_float) ||
+                          (se->se2 && se->se2->ibuf && se->se2->ibuf->rect_float) ||
+                          (se->se3 && se->se3->ibuf && se->se3->ibuf->rect_float))
+                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
+                       else
+                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
+                       
+                       do_effect(scene, cfra, seq, se);
+               }
+       } else if(seq->type == SEQ_IMAGE) {
+               if(se->ok == STRIPELEM_OK && se->ibuf == 0) {
+                       StripElem * s_elem = give_stripelem(seq, cfra);
+                       BLI_join_dirfile(name, seq->strip->dir, s_elem->name);
+                       BLI_convertstringcode(name, G.sce);
+                       BLI_convertstringframe(name, scene->r.cfra);
+                       if (!build_proxy_run) {
+                               se->ibuf = seq_proxy_fetch(scene, seq, cfra);
+                       }
+                       copy_from_ibuf_still(seq, se);
+
+                       if (!se->ibuf) {
+                               se->ibuf= IMB_loadiffname(
+                                       name, IB_rect);
+                               copy_to_ibuf_still(seq, se);
+                       }
+                       
+                       if(se->ibuf == 0) {
+                               se->ok = STRIPELEM_FAILED;
+                       } else if (!build_proxy_run) {
+                               input_preprocess(scene, seq, se, cfra);
+                       }
+               }
+       } else if(seq->type == SEQ_MOVIE) {
+               if(se->ok == STRIPELEM_OK && se->ibuf==0) {
+                       if(!build_proxy_run) {
+                               se->ibuf = seq_proxy_fetch(scene, seq, cfra);
+                       }
+                       copy_from_ibuf_still(seq, se);
+
+                       if (se->ibuf == 0) {
+                               if(seq->anim==0) {
+                                       BLI_join_dirfile(name, seq->strip->dir, seq->strip->stripdata->name);
+                                       BLI_convertstringcode(name, G.sce);
+                                       BLI_convertstringframe(name, scene->r.cfra);
+                                       
+                                       seq->anim = openanim(
+                                               name, IB_rect | 
+                                               ((seq->flag & SEQ_FILTERY) 
+                                                ? IB_animdeinterlace : 0));
+                               }
+                               if(seq->anim) {
+                                       IMB_anim_set_preseek(seq->anim, seq->anim_preseek);
+                                       se->ibuf = IMB_anim_absolute(seq->anim, se->nr + seq->anim_startofs);
+                               }
+                               copy_to_ibuf_still(seq, se);
+                       }
+                       
+                       if(se->ibuf == 0) {
+                               se->ok = STRIPELEM_FAILED;
+                       } else if (!build_proxy_run) {
+                               input_preprocess(scene, seq, se, cfra);
+                       }
+               }
+       } else if(seq->type == SEQ_SCENE) {     // scene can be NULL after deletions
+#if 0
+               /* XXX move entirely to render? */
+               int oldcfra = CFRA;
+               Sequence * oldseq = get_last_seq();
+               Scene *sce= seq->scene, *oldsce= scene;
+               Render *re;
+               RenderResult rres;
+               int doseq, rendering= G.rendering;
+               char scenename[64];
+               int sce_valid =sce&& (sce->camera || sce->r.scemode & R_DOSEQ);
+                       
+               if (se->ibuf == NULL && sce_valid && !build_proxy_run) {
+                       se->ibuf = seq_proxy_fetch(scene, seq, cfra);
+                       if (se->ibuf) {
+                               input_preprocess(scene, seq, se, cfra);
+                       }
+               }
+
+               if (se->ibuf == NULL && sce_valid) {
+                       copy_from_ibuf_still(seq, se);
+                       if (se->ibuf) {
+                               input_preprocess(scene, seq, se, cfra);
+                       }
+               }
+               
+               if (!sce_valid) {
+                       se->ok = STRIPELEM_FAILED;
+               } else if (se->ibuf==NULL && sce_valid) {
+                       waitcursor(1);
+                       
+                       /* Hack! This function can be called from do_render_seq(), in that case
+                          the seq->scene can already have a Render initialized with same name, 
+                          so we have to use a default name. (compositor uses scene name to
+                          find render).
+                          However, when called from within the UI (image preview in sequencer)
+                          we do want to use scene Render, that way the render result is defined
+                          for display in render/imagewindow */
+                       if(rendering) {
+                               BLI_strncpy(scenename, sce->id.name+2, 64);
+                               strcpy(sce->id.name+2, " do_build_seq_ibuf");
+                       }
+                       re= RE_NewRender(sce->id.name);
+                       
+                       /* prevent eternal loop */
+                       doseq= scene->r.scemode & R_DOSEQ;
+                       scene->r.scemode &= ~R_DOSEQ;
+                       
+                       BIF_init_render_callbacks(re, 0);       /* 0= no display callbacks */
+                       
+                       /* XXX hrms, set_scene still needed? work on that... */
+                       if(sce!=oldsce) set_scene_bg(sce);
+                       RE_BlenderFrame(re, sce,
+                                       seq->sfra+se->nr+seq->anim_startofs);
+                       if(sce!=oldsce) set_scene_bg(oldsce);
+                       
+                       /* UGLY WARNING, it is set to zero in  RE_BlenderFrame */
+                       G.rendering= rendering;
+                       if(rendering)
+                               BLI_strncpy(sce->id.name+2, scenename, 64);
+                       
+                       RE_GetResultImage(re, &rres);
+                       
+                       if(rres.rectf) {
+                               se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0);
+                               memcpy(se->ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty);
+                               if(rres.rectz) {
+                                       addzbuffloatImBuf(se->ibuf);
+                                       memcpy(se->ibuf->zbuf_float, rres.rectz, sizeof(float)*rres.rectx*rres.recty);
+                               }
+                       } else if (rres.rect32) {
+                               se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect, 0);
+                               memcpy(se->ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty);
+                       }
+                       
+                       BIF_end_render_callbacks();
+                       
+                       /* restore */
+                       scene->r.scemode |= doseq;
+                       
+                       CFRA = oldcfra;
+                       set_last_seq(oldseq);
+
+                       copy_to_ibuf_still(seq, se);
+
+                       if (!build_proxy_run) {
+                               if(se->ibuf == NULL) {
+                                       se->ok = STRIPELEM_FAILED;
+                               } else {
+                                       input_preprocess(scene, seq, se, cfra);
+                               }
+                       }
+
+               }
+#endif
+       }
+       if (!build_proxy_run) {
+               if (se->ibuf && use_limiter) {
+                       IMB_cache_limiter_insert(se->ibuf);
+                       IMB_cache_limiter_ref(se->ibuf);
+                       IMB_cache_limiter_touch(se->ibuf);
+               }
+       }
+}
+
+static TStripElem* do_build_seq_recursively(Scene *scene, Sequence *seq, int cfra);
+
+static void do_effect_seq_recursively(Scene *scene, Sequence *seq, TStripElem *se, int cfra)
+{
+       float fac, facf;
+       struct SeqEffectHandle sh = get_sequence_effect(seq);
+       int early_out;
+
+       se->se1 = 0;
+       se->se2 = 0;
+       se->se3 = 0;
+
+       if(seq->ipo && seq->ipo->curve.first) {
+               do_seq_ipo(scene, seq, cfra);
+               fac= seq->facf0;
+               facf= seq->facf1;
+       } else {
+               sh.get_default_fac(seq, cfra, &fac, &facf);
+       } 
+
+       if( scene->r.mode & R_FIELDS ); else facf= fac;
+       
+       early_out = sh.early_out(seq, fac, facf);
+       switch (early_out) {
+       case -1:
+               /* no input needed */
+               break;
+       case 0:
+               se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra);
+               se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra);
+               if (seq->seq3) {
+                       se->se3 = do_build_seq_recursively(scene, seq->seq3, cfra);
+               }
+               break;
+       case 1:
+               se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra);
+               break;
+       case 2:
+               se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra);
+               break;
+       }
+
+
+       do_build_seq_ibuf(scene, seq, se, cfra, FALSE);
+
+       /* children are not needed anymore ... */
+
+       if (se->se1 && se->se1->ibuf) {
+               IMB_cache_limiter_unref(se->se1->ibuf);
+       }
+       if (se->se2 && se->se2->ibuf) {
+               IMB_cache_limiter_unref(se->se2->ibuf);
+       }
+       if (se->se3 && se->se3->ibuf) {
+               IMB_cache_limiter_unref(se->se3->ibuf);
+       }
+}
+
+static TStripElem* do_build_seq_recursively_impl(Scene *scene, Sequence * seq, int cfra)
+{
+       TStripElem *se;
+
+       se = give_tstripelem(seq, cfra);
+
+       if(se) {
+               if (seq->type & SEQ_EFFECT) {
+                       do_effect_seq_recursively(scene, seq, se, cfra);
+               } else {
+                       do_build_seq_ibuf(scene, seq, se, cfra, FALSE);
+               }
+       }
+       return se;
+}
+
+/* FIXME:
+   
+If cfra was float throughout blender (especially in the render
+pipeline) one could even _render_ with subframe precision
+instead of faking using the blend code below...
+
+*/
+
+static TStripElem* do_handle_speed_effect(Scene *scene, Sequence * seq, int cfra)
+{
+       SpeedControlVars * s = (SpeedControlVars *)seq->effectdata;
+       int nr = cfra - seq->start;
+       float f_cfra;
+       int cfra_left;
+       int cfra_right;
+       TStripElem * se = 0;
+       TStripElem * se1 = 0;
+       TStripElem * se2 = 0;
+       
+       sequence_effect_speed_rebuild_map(scene, seq, 0);
+       
+       f_cfra = seq->start + s->frameMap[nr];
+       
+       cfra_left = (int) floor(f_cfra);
+       cfra_right = (int) ceil(f_cfra);
+
+       se = give_tstripelem(seq, cfra);
+
+       if (!se) {
+               return se;
+       }
+
+       if (cfra_left == cfra_right || 
+           (s->flags & SEQ_SPEED_BLEND) == 0) {
+               test_and_auto_discard_ibuf(se);
+
+               if (se->ibuf == NULL) {
+                       se1 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_left);
+
+                       if((se1 && se1->ibuf && se1->ibuf->rect_float))
+                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
+                       else
+                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
+
+                       if (se1 == 0 || se1->ibuf == 0) {
+                               make_black_ibuf(se->ibuf);
+                       } else {
+                               if (se->ibuf != se1->ibuf) {
+                                       if (se->ibuf) {
+                                               IMB_freeImBuf(se->ibuf);
+                                       }
+
+                                       se->ibuf = se1->ibuf;
+                                       IMB_refImBuf(se->ibuf);
+                               }
+                       }
+               }
+       } else {
+               struct SeqEffectHandle sh;
+
+               if(se->ibuf) {
+                       if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty 
+                          || !(se->ibuf->rect || se->ibuf->rect_float)) {
+                               IMB_freeImBuf(se->ibuf);
+                               se->ibuf= 0;
+                       }
+               }
+
+               if (se->ibuf == NULL) {
+                       se1 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_left);
+                       se2 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_right);
+
+                       if((se1 && se1->ibuf && se1->ibuf->rect_float))
+                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
+                       else
+                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
+                       
+                       if (!se1 || !se2) {
+                               make_black_ibuf(se->ibuf);
+                       } else {
+                               sh = get_sequence_effect(seq);
+
+                               sh.execute(seq, cfra, 
+                                          f_cfra - (float) cfra_left, 
+                                          f_cfra - (float) cfra_left, 
+                                          se->ibuf->x, se->ibuf->y, 
+                                          se1->ibuf, se2->ibuf, 0, se->ibuf);
+                       }
+               }
+
+       }
+
+       /* caller expects this to be referenced, so do it! */
+       if (se->ibuf) {
+               IMB_cache_limiter_insert(se->ibuf);
+               IMB_cache_limiter_ref(se->ibuf);
+               IMB_cache_limiter_touch(se->ibuf);
+       }
+
+       /* children are no longer needed */
+       if (se1 && se1->ibuf)
+               IMB_cache_limiter_unref(se1->ibuf);
+       if (se2 && se2->ibuf)
+               IMB_cache_limiter_unref(se2->ibuf);
+
+       return se;
+}
+
+/* 
+ * build all ibufs recursively
+ * 
+ * if successfull, the returned TStripElem contains the (referenced!) imbuf
+ * that means: you _must_ call 
+ *
+ * IMB_cache_limiter_unref(rval);
+ * 
+ * if rval != 0
+ * 
+ */
+
+static TStripElem* do_build_seq_recursively(Scene *scene, Sequence * seq, int cfra)
+{
+       if (seq->type == SEQ_SPEED) {
+               return do_handle_speed_effect(scene, seq, cfra);
+       } else {
+               return do_build_seq_recursively_impl(scene, seq, cfra);
+       }
+}
+
+static TStripElem* do_build_seq_array_recursively(Scene *scene,
+       ListBase *seqbasep, int cfra, int chanshown)
+{
+       Sequence* seq_arr[MAXSEQ+1];
+       int count;
+       int i;
+       TStripElem* se = 0;
+
+       count = get_shown_sequences(seqbasep, cfra, chanshown, (Sequence **)&seq_arr);
+
+       if (!count) {
+               return 0;
+       }
+
+       se = give_tstripelem(seq_arr[count - 1], cfra);
+
+       if (!se) {
+               return 0;
+       }
+
+       test_and_auto_discard_ibuf(se);
+
+       if (se->ibuf_comp != 0) {
+               IMB_cache_limiter_insert(se->ibuf_comp);
+               IMB_cache_limiter_ref(se->ibuf_comp);
+               IMB_cache_limiter_touch(se->ibuf_comp);
+               return se;
+       }
+
+       
+       if(count == 1) {
+               se = do_build_seq_recursively(scene, seq_arr[0], cfra);
+               if (se->ibuf) {
+                       se->ibuf_comp = se->ibuf;
+                       IMB_refImBuf(se->ibuf_comp);
+               }
+               return se;
+       }
+
+
+       for (i = count - 1; i >= 0; i--) {
+               int early_out;
+               Sequence * seq = seq_arr[i];
+               struct SeqEffectHandle sh;
+
+               se = give_tstripelem(seq, cfra);
+
+               test_and_auto_discard_ibuf(se);
+
+               if (se->ibuf_comp != 0) {
+                       break;
+               }
+               if (seq->blend_mode == SEQ_BLEND_REPLACE) {
+                       do_build_seq_recursively(scene, seq, cfra);
+                       if (se->ibuf) {
+                               se->ibuf_comp = se->ibuf;
+                               IMB_refImBuf(se->ibuf);
+                       } else {
+                               se->ibuf_comp = IMB_allocImBuf(
+                                       (short)seqrectx, (short)seqrecty, 
+                                       32, IB_rect, 0);
+                       }
+                       break;
+               }
+
+               sh = get_sequence_blend(seq);
+
+               seq->facf0 = seq->facf1 = 1.0;
+
+               if(seq->ipo && seq->ipo->curve.first) {
+                       do_seq_ipo(scene, seq, cfra);
+               } 
+
+               if( scene->r.mode & R_FIELDS ); else seq->facf0 = seq->facf1;
+
+               seq->facf0 *= seq->blend_opacity / 100.0;
+               seq->facf1 *= seq->blend_opacity / 100.0;
+
+               early_out = sh.early_out(seq, seq->facf0, seq->facf1);
+
+               switch (early_out) {
+               case -1:
+               case 2:
+                       do_build_seq_recursively(scene, seq, cfra);
+                       if (se->ibuf) {
+                               se->ibuf_comp = se->ibuf;
+                               IMB_refImBuf(se->ibuf_comp);
+                       } else {
+                               se->ibuf_comp = IMB_allocImBuf(
+                                       (short)seqrectx, (short)seqrecty, 
+                                       32, IB_rect, 0);
+                       }
+                       break;
+               case 1:
+                       if (i == 0) {
+                               se->ibuf_comp = IMB_allocImBuf(
+                                       (short)seqrectx, (short)seqrecty, 
+                                       32, IB_rect, 0);
+                               IMB_cache_limiter_insert(se->ibuf_comp);
+                               IMB_cache_limiter_ref(se->ibuf_comp);
+                               IMB_cache_limiter_touch(se->ibuf_comp);
+                       }
+                       break;
+               case 0:
+                       do_build_seq_recursively(scene, seq, cfra);
+                       if (!se->ibuf) {
+                               se->ibuf = IMB_allocImBuf(
+                                       (short)seqrectx, (short)seqrecty, 
+                                       32, IB_rect, 0);
+                       }
+                       if (i == 0) {
+                               se->ibuf_comp = se->ibuf;
+                               IMB_refImBuf(se->ibuf_comp);
+                       }
+                       break;
+               }
+       
+               if (se->ibuf_comp) {
+                       break;
+               }
+       }
+
+       i++;
+
+       for (; i < count; i++) {
+               Sequence * seq = seq_arr[i];
+               struct SeqEffectHandle sh = get_sequence_blend(seq);
+               TStripElem* se1 = give_tstripelem(seq_arr[i-1], cfra);
+               TStripElem* se2 = give_tstripelem(seq_arr[i], cfra);
+       
+               int early_out = sh.early_out(seq, seq->facf0, seq->facf1);
+               switch (early_out) {
+               case 0: {
+                       int x= se2->ibuf->x;
+                       int y= se2->ibuf->y;
+                       int swap_input = FALSE;
+
+                       if (se1->ibuf_comp->rect_float ||
+                           se2->ibuf->rect_float) {
+                               se2->ibuf_comp = IMB_allocImBuf(
+                                       (short)seqrectx, (short)seqrecty, 
+                                       32, IB_rectfloat, 0);
+                       } else {
+                               se2->ibuf_comp = IMB_allocImBuf(
+                                       (short)seqrectx, (short)seqrecty, 
+                                       32, IB_rect, 0);
+                       }
+
+
+                       if (!se1->ibuf_comp->rect_float && 
+                           se2->ibuf_comp->rect_float) {
+                               IMB_float_from_rect(se1->ibuf_comp);
+                       }
+                       if (!se2->ibuf->rect_float && 
+                           se2->ibuf_comp->rect_float) {
+                               IMB_float_from_rect(se2->ibuf);
+                       }
+
+                       if (!se1->ibuf_comp->rect && 
+                           !se2->ibuf_comp->rect_float) {
+                               IMB_rect_from_float(se1->ibuf_comp);
+                       }
+                       if (!se2->ibuf->rect && 
+                           !se2->ibuf_comp->rect_float) {
+                               IMB_rect_from_float(se2->ibuf);
+                       }
+
+                       /* bad hack, to fix crazy input ordering of 
+                          those two effects */
+
+                       if (seq->blend_mode == SEQ_ALPHAOVER ||
+                           seq->blend_mode == SEQ_ALPHAUNDER ||
+                           seq->blend_mode == SEQ_OVERDROP) {
+                               swap_input = TRUE;
+                       }
+
+                       if (swap_input) {
+                               sh.execute(seq, cfra, 
+                                          seq->facf0, seq->facf1, x, y, 
+                                          se2->ibuf, se1->ibuf_comp, 0,
+                                          se2->ibuf_comp);
+                       } else {
+                               sh.execute(seq, cfra, 
+                                          seq->facf0, seq->facf1, x, y, 
+                                          se1->ibuf_comp, se2->ibuf, 0,
+                                          se2->ibuf_comp);
+                       }
+                       
+                       IMB_cache_limiter_insert(se2->ibuf_comp);
+                       IMB_cache_limiter_ref(se2->ibuf_comp);
+                       IMB_cache_limiter_touch(se2->ibuf_comp);
+
+                       IMB_cache_limiter_unref(se1->ibuf_comp);
+                       IMB_cache_limiter_unref(se2->ibuf);
+
+                       break;
+               }
+               case 1: {
+                       se2->ibuf_comp = se1->ibuf;
+                       IMB_refImBuf(se2->ibuf_comp);
+
+                       break;
+               }
+               }
+               se = se2;
+       }
+
+       return se;
+}
+
+/*
+ * returned ImBuf is refed!
+ * you have to unref after usage!
+ */
+
+static ImBuf *give_ibuf_seq_impl(Scene *scene, int rectx, int recty, int cfra, int chanshown)
+{
+       Editing *ed;
+       int count;
+       ListBase *seqbasep;
+       TStripElem *se;
+
+       ed= scene->ed;
+       if(ed==NULL) return NULL;
+
+       count = BLI_countlist(&ed->metastack);
+       if((chanshown < 0) && (count > 0)) {
+               count = MAX2(count + chanshown, 0);
+               seqbasep= ((MetaStack*)BLI_findlink(&ed->metastack, count))->oldbasep;
+       } else {
+               seqbasep= ed->seqbasep;
+       }
+
+       seqrectx= rectx;        /* bad bad global! */
+       seqrecty= recty;
+
+       se = do_build_seq_array_recursively(scene, seqbasep, cfra, chanshown);
+
+       if(!se) { 
+               return 0;
+       }
+
+       return se->ibuf_comp;
+}
+
+ImBuf *give_ibuf_seq_direct(Scene *scene, int rectx, int recty, int cfra, Sequence *seq)
+{
+       TStripElem* se;
+
+       seqrectx= rectx;        /* bad bad global! */
+       seqrecty= recty;
+
+       se = do_build_seq_recursively(scene, seq, cfra);
+
+       if(!se) { 
+               return 0;
+       }
+
+       if (se->ibuf) {
+               IMB_cache_limiter_unref(se->ibuf);
+       }
+
+       return se->ibuf;
+}
+
+ImBuf *give_ibuf_seq(Scene *scene, int rectx, int recty, int cfra, int chanshown)
+{
+       ImBuf* i = give_ibuf_seq_impl(scene, rectx, recty, cfra, chanshown);
+
+       if (i) {
+               IMB_cache_limiter_unref(i);
+       }
+       return i;
+}
+
+/* check used when we need to change seq->blend_mode but not to effect or audio strips */
+int seq_can_blend(Sequence *seq)
+{
+       if (ELEM4(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE)) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+/* *********************** threading api ******************* */
+
+static ListBase running_threads;
+static ListBase prefetch_wait;
+static ListBase prefetch_done;
+
+static pthread_mutex_t queue_lock          = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t wakeup_lock         = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t  wakeup_cond         = PTHREAD_COND_INITIALIZER;
+
+static pthread_mutex_t prefetch_ready_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t  prefetch_ready_cond = PTHREAD_COND_INITIALIZER;
+
+static pthread_mutex_t frame_done_lock     = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t  frame_done_cond     = PTHREAD_COND_INITIALIZER;
+
+static volatile int seq_thread_shutdown = FALSE;
+static volatile int seq_last_given_monoton_cfra = 0;
+static int monoton_cfra = 0;
+
+typedef struct PrefetchThread {
+       struct PrefetchThread *next, *prev;
+       
+       Scene *scene;
+       struct PrefetchQueueElem *current;
+       pthread_t pthread;
+       int running;
+       
+} PrefetchThread;
+
+typedef struct PrefetchQueueElem {
+       struct PrefetchQueueElem *next, *prev;
+       
+       int rectx;
+       int recty;
+       int cfra;
+       int chanshown;
+
+       int monoton_cfra;
+
+       struct ImBuf * ibuf;
+} PrefetchQueueElem;
+
+static void *seq_prefetch_thread(void * This_)
+{
+       PrefetchThread * This = This_;
+
+       while (!seq_thread_shutdown) {
+               PrefetchQueueElem *e;
+               int s_last;
+
+               pthread_mutex_lock(&queue_lock);
+               e = prefetch_wait.first;
+               if (e) {
+                       BLI_remlink(&prefetch_wait, e);
+               }
+               s_last = seq_last_given_monoton_cfra;
+
+               This->current = e;
+
+               pthread_mutex_unlock(&queue_lock);
+
+               if (!e) {
+                       pthread_mutex_lock(&prefetch_ready_lock);
+
+                       This->running = FALSE;
+
+                       pthread_cond_signal(&prefetch_ready_cond);
+                       pthread_mutex_unlock(&prefetch_ready_lock);
+
+                       pthread_mutex_lock(&wakeup_lock);
+                       if (!seq_thread_shutdown) {
+                               pthread_cond_wait(&wakeup_cond, &wakeup_lock);
+                       }
+                       pthread_mutex_unlock(&wakeup_lock);
+                       continue;
+               }
+
+               This->running = TRUE;
+               
+               if (e->cfra >= s_last) { 
+                       e->ibuf = give_ibuf_seq_impl(This->scene, 
+                               e->rectx, e->recty, e->cfra, e->chanshown);
+               }
+
+               pthread_mutex_lock(&queue_lock);
+
+               BLI_addtail(&prefetch_done, e);
+
+               for (e = prefetch_wait.first; e; e = e->next) {
+                       if (s_last > e->monoton_cfra) {
+                               BLI_remlink(&prefetch_wait, e);
+                               MEM_freeN(e);
+                       }
+               }
+
+               for (e = prefetch_done.first; e; e = e->next) {
+                       if (s_last > e->monoton_cfra) {
+                               if (e->ibuf) {
+                                       IMB_cache_limiter_unref(e->ibuf);
+                               }
+                               BLI_remlink(&prefetch_done, e);
+                               MEM_freeN(e);
+                       }
+               }
+
+               pthread_mutex_unlock(&queue_lock);
+
+               pthread_mutex_lock(&frame_done_lock);
+               pthread_cond_signal(&frame_done_cond);
+               pthread_mutex_unlock(&frame_done_lock);
+       }
+       return 0;
+}
+
+void seq_start_threads(Scene *scene)
+{
+       int i;
+
+       running_threads.first = running_threads.last = NULL;
+       prefetch_wait.first = prefetch_wait.last = NULL;
+       prefetch_done.first = prefetch_done.last = NULL;
+
+       seq_thread_shutdown = FALSE;
+       seq_last_given_monoton_cfra = monoton_cfra = 0;
+
+       /* since global structures are modified during the processing
+          of one frame, only one render thread is currently possible... 
+
+          (but we code, in the hope, that we can remove this restriction
+          soon...)
+       */
+
+       fprintf(stderr, "SEQ-THREAD: seq_start_threads\n");
+
+       for (i = 0; i < 1; i++) {
+               PrefetchThread *t = MEM_callocN(sizeof(PrefetchThread), "prefetch_thread");
+               t->scene= scene;
+               t->running = TRUE;
+               BLI_addtail(&running_threads, t);
+
+               pthread_create(&t->pthread, NULL, seq_prefetch_thread, t);
+       }
+
+       /* init malloc mutex */
+       BLI_init_threads(0, 0, 0);
+}
+
+void seq_stop_threads()
+{
+       PrefetchThread *tslot;
+       PrefetchQueueElem *e;
+
+       fprintf(stderr, "SEQ-THREAD: seq_stop_threads()\n");
+
+       if (seq_thread_shutdown) {
+               fprintf(stderr, "SEQ-THREAD: ... already stopped\n");
+               return;
+       }
+       
+       pthread_mutex_lock(&wakeup_lock);
+
+       seq_thread_shutdown = TRUE;
+
+        pthread_cond_broadcast(&wakeup_cond);
+        pthread_mutex_unlock(&wakeup_lock);
+
+       for(tslot = running_threads.first; tslot; tslot= tslot->next) {
+               pthread_join(tslot->pthread, NULL);
+       }
+
+
+       for (e = prefetch_wait.first; e; e = e->next) {
+               BLI_remlink(&prefetch_wait, e);
+               MEM_freeN(e);
+       }
+
+       for (e = prefetch_done.first; e; e = e->next) {
+               if (e->ibuf) {
+                       IMB_cache_limiter_unref(e->ibuf);
+               }
+               BLI_remlink(&prefetch_done, e);
+               MEM_freeN(e);
+       }
+
+       BLI_freelistN(&running_threads);
+
+       /* deinit malloc mutex */
+       BLI_end_threads(0);
+}
+
+void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown)
+{
+       PrefetchQueueElem *e;
+       if (seq_thread_shutdown) {
+               return;
+       }
+
+       e = MEM_callocN(sizeof(PrefetchQueueElem), "prefetch_queue_elem");
+       e->rectx = rectx;
+       e->recty = recty;
+       e->cfra = cfra;
+       e->chanshown = chanshown;
+       e->monoton_cfra = monoton_cfra++;
+
+       pthread_mutex_lock(&queue_lock);
+       BLI_addtail(&prefetch_wait, e);
+       pthread_mutex_unlock(&queue_lock);
+       
+       pthread_mutex_lock(&wakeup_lock);
+       pthread_cond_signal(&wakeup_cond);
+       pthread_mutex_unlock(&wakeup_lock);
+}
+
+void seq_wait_for_prefetch_ready()
+{
+       PrefetchThread *tslot;
+
+       if (seq_thread_shutdown) {
+               return;
+       }
+
+       fprintf(stderr, "SEQ-THREAD: rendering prefetch frames...\n");
+
+       pthread_mutex_lock(&prefetch_ready_lock);
+
+       for(;;) {
+               for(tslot = running_threads.first; tslot; tslot= tslot->next) {
+                       if (tslot->running) {
+                               break;
+                       }
+               }
+               if (!tslot) {
+                       break;
+               }
+               pthread_cond_wait(&prefetch_ready_cond, &prefetch_ready_lock);
+       }
+
+       pthread_mutex_unlock(&prefetch_ready_lock);
+
+       fprintf(stderr, "SEQ-THREAD: prefetch done\n");
+}
+
+ImBuf *give_ibuf_seq_threaded(Scene *scene, int rectx, int recty, int cfra, int chanshown)
+{
+       PrefetchQueueElem *e = NULL;
+       int found_something = FALSE;
+
+       if (seq_thread_shutdown) {
+               return give_ibuf_seq(scene, rectx, recty, cfra, chanshown);
+       }
+
+       while (!e) {
+               int success = FALSE;
+               pthread_mutex_lock(&queue_lock);
+
+               for (e = prefetch_done.first; e; e = e->next) {
+                       if (cfra == e->cfra &&
+                           chanshown == e->chanshown &&
+                           rectx == e->rectx && 
+                           recty == e->recty) {
+                               success = TRUE;
+                               found_something = TRUE;
+                               break;
+                       }
+               }
+
+               if (!e) {
+                       for (e = prefetch_wait.first; e; e = e->next) {
+                               if (cfra == e->cfra &&
+                                   chanshown == e->chanshown &&
+                                   rectx == e->rectx && 
+                                   recty == e->recty) {
+                                       found_something = TRUE;
+                                       break;
+                               }
+                       }
+               }
+
+               if (!e) {
+                       PrefetchThread *tslot;
+
+                       for(tslot = running_threads.first; 
+                           tslot; tslot= tslot->next) {
+                               if (tslot->current &&
+                                   cfra == tslot->current->cfra &&
+                                   chanshown == tslot->current->chanshown &&
+                                   rectx == tslot->current->rectx && 
+                                   recty == tslot->current->recty) {
+                                       found_something = TRUE;
+                                       break;
+                               }
+                       }
+               }
+
+               /* e->ibuf is unrefed by render thread on next round. */
+
+               if (e) {
+                       seq_last_given_monoton_cfra = e->monoton_cfra;
+               }
+
+               pthread_mutex_unlock(&queue_lock);
+
+               if (!success) {
+                       e = NULL;
+
+                       if (!found_something) {
+                               fprintf(stderr, 
+                                       "SEQ-THREAD: Requested frame "
+                                       "not in queue ???\n");
+                               break;
+                       }
+                       pthread_mutex_lock(&frame_done_lock);
+                       pthread_cond_wait(&frame_done_cond, &frame_done_lock);
+                       pthread_mutex_unlock(&frame_done_lock);
+               }
+       }
+       
+       return e ? e->ibuf : 0;
+}
+
+/* Functions to free imbuf and anim data on changes */
+
+static void free_imbuf_strip_elem(TStripElem *se)
+{
+       if(se->ibuf) {
+               IMB_freeImBuf(se->ibuf);
+       }
+       if(se->ibuf_comp) {
+               IMB_freeImBuf(se->ibuf_comp);
+       }
+       se->ibuf_comp = 0;
+       se->ibuf= 0;
+       se->ok= STRIPELEM_OK;
+       se->se1= se->se2= se->se3= 0;
+}
+
+static void free_anim_seq(Sequence *seq)
+{
+       if(seq->anim) {
+               IMB_free_anim(seq->anim);
+               seq->anim = 0;
+       }
+}
+
+void free_imbuf_seq_except(Scene *scene, int cfra)
+{
+       Editing *ed= scene->ed;
+       Sequence *seq;
+       TStripElem *se;
+       int a;
+
+       if(ed==NULL) return;
+
+       SEQ_BEGIN(ed, seq) {
+               if(seq->strip) {
+                       TStripElem * curelem = give_tstripelem(seq, cfra);
+
+                       for(a = 0, se = seq->strip->tstripdata; 
+                           a < seq->strip->len && se; a++, se++) {
+                               if(se != curelem) {
+                                       free_imbuf_strip_elem(se);
+                               }
+                       }
+                       for(a = 0, se = seq->strip->tstripdata_startstill;
+                           a < seq->strip->startstill && se; a++, se++) {
+                               if(se != curelem) {
+                                       free_imbuf_strip_elem(se);
+                               }
+                       }
+                       for(a = 0, se = seq->strip->tstripdata_endstill;
+                           a < seq->strip->endstill && se; a++, se++) {
+                               if(se != curelem) {
+                                       free_imbuf_strip_elem(se);
+                               }
+                       }
+                       if(seq->strip->ibuf_startstill) {
+                               IMB_freeImBuf(seq->strip->ibuf_startstill);
+                               seq->strip->ibuf_startstill = 0;
+                       }
+
+                       if(seq->strip->ibuf_endstill) {
+                               IMB_freeImBuf(seq->strip->ibuf_endstill);
+                               seq->strip->ibuf_endstill = 0;
+                       }
+
+                       if(seq->type==SEQ_MOVIE)
+                               if(seq->startdisp > cfra || seq->enddisp < cfra)
+                                       free_anim_seq(seq);
+               }
+       }
+       SEQ_END
+}
+
+void free_imbuf_seq(Scene *scene)
+{
+       Editing *ed= scene->ed;
+       Sequence *seq;
+       TStripElem *se;
+       int a;
+
+       if(ed==NULL) return;
+
+       SEQ_BEGIN(ed, seq) {
+               if(seq->strip) {
+                       for(a = 0, se = seq->strip->tstripdata; 
+                           a < seq->strip->len && se; a++, se++) {
+                               free_imbuf_strip_elem(se);
+                       }
+                       for(a = 0, se = seq->strip->tstripdata_startstill; 
+                           a < seq->strip->startstill && se; a++, se++) {
+                               free_imbuf_strip_elem(se);
+                       }
+                       for(a = 0, se = seq->strip->tstripdata_endstill; 
+                           a < seq->strip->endstill && se; a++, se++) {
+                               free_imbuf_strip_elem(se);
+                       }
+                       if(seq->strip->ibuf_startstill) {
+                               IMB_freeImBuf(seq->strip->ibuf_startstill);
+                               seq->strip->ibuf_startstill = 0;
+                       }
+
+                       if(seq->strip->ibuf_endstill) {
+                               IMB_freeImBuf(seq->strip->ibuf_endstill);
+                               seq->strip->ibuf_endstill = 0;
+                       }
+
+                       if(seq->type==SEQ_MOVIE)
+                               free_anim_seq(seq);
+                       if(seq->type==SEQ_SPEED) {
+                               sequence_effect_speed_rebuild_map(scene, seq, 1);
+                       }
+               }
+       }
+       SEQ_END
+}
+
+static int update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *changed_seq, int len_change, int ibuf_change)
+{
+       Sequence *subseq;
+       int a, free_imbuf = 0;
+       TStripElem *se;
+       
+       /* recurs downwards to see if this seq depends on the changed seq */
+       
+       if(seq == NULL)
+               return 0;
+       
+       if(seq == changed_seq)
+               free_imbuf = 1;
+       
+       for(subseq=seq->seqbase.first; subseq; subseq=subseq->next)
+               if(update_changed_seq_recurs(scene, subseq, changed_seq, len_change, ibuf_change))
+                       free_imbuf = TRUE;
+       
+       if(seq->seq1)
+               if(update_changed_seq_recurs(scene, seq->seq1, changed_seq, len_change, ibuf_change))
+                       free_imbuf = TRUE;
+       if(seq->seq2 && (seq->seq2 != seq->seq1))
+               if(update_changed_seq_recurs(scene, seq->seq2, changed_seq, len_change, ibuf_change))
+                       free_imbuf = TRUE;
+       if(seq->seq3 && (seq->seq3 != seq->seq1) && (seq->seq3 != seq->seq2))
+               if(update_changed_seq_recurs(scene, seq->seq3, changed_seq, len_change, ibuf_change))
+                       free_imbuf = TRUE;
+       
+       if(free_imbuf) {
+               if(ibuf_change) {
+                       se= seq->strip->tstripdata;
+                       if (se) {
+                               for(a=0; a<seq->len; a++, se++)
+                                       free_imbuf_strip_elem(se);
+                       }
+                       
+                       if(seq->type == SEQ_MOVIE)
+                               free_anim_seq(seq);
+                       if(seq->type == SEQ_SPEED) {
+                               sequence_effect_speed_rebuild_map(scene, seq, 1);
+                       }
+               }
+               
+               if(len_change)
+                       calc_sequence(seq);
+       }
+       
+       return free_imbuf;
+}
+
+void update_changed_seq_and_deps(Scene *scene, Sequence *changed_seq, int len_change, int ibuf_change)
+{
+       Editing *ed= scene->ed;
+       Sequence *seq;
+       
+       if (!ed) return;
+       
+       for (seq=ed->seqbase.first; seq; seq=seq->next)
+               update_changed_seq_recurs(scene, seq, changed_seq, len_change, ibuf_change);
+}
+
+void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo)
+{
+       /* force update of all sequences with this ipo, on ipo changes */
+       Editing *ed= scene->ed;
+       Sequence *seq;
+
+       if(ed==NULL) return;
+
+       SEQ_BEGIN(ed, seq) {
+               if(seq->ipo == ipo) {
+                       update_changed_seq_and_deps(scene, seq, 0, 1);
+                       if(seq->type == SEQ_SPEED) {
+                               sequence_effect_speed_rebuild_map(scene, seq, 1);
+                       }
+               }
+       }
+       SEQ_END
+}
+
+#if 0
+/* bad levell call... */
+void do_render_seq(RenderResult *rr, int cfra)
+{
+       ImBuf *ibuf;
+
+       ibuf= give_ibuf_seq(scene, rr->rectx, rr->recty, cfra, 0);
+       
+       if(ibuf) {
+               if(ibuf->rect_float) {
+                       if (!rr->rectf)
+                               rr->rectf= MEM_mallocN(4*sizeof(float)*rr->rectx*rr->recty, "render_seq rectf");
+                       
+                       memcpy(rr->rectf, ibuf->rect_float, 4*sizeof(float)*rr->rectx*rr->recty);
+                       
+                       /* TSK! Since sequence render doesn't free the *rr render result, the old rect32
+                          can hang around when sequence render has rendered a 32 bits one before */
+                       if(rr->rect32) {
+                               MEM_freeN(rr->rect32);
+                               rr->rect32= NULL;
+                       }
+               }
+               else if(ibuf->rect) {
+                       if (!rr->rect32)
+                               rr->rect32= MEM_mallocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect");
+
+                       memcpy(rr->rect32, ibuf->rect, 4*rr->rectx*rr->recty);
+
+                       /* if (ibuf->zbuf) { */
+                       /*      if (R.rectz) freeN(R.rectz); */
+                       /*      R.rectz = BLI_dupallocN(ibuf->zbuf); */
+                       /* } */
+               }
+               
+               /* Let the cache limitor take care of this (schlaile) */
+               /* While render let's keep all memory available for render 
+                  (ton)
+                  At least if free memory is tight...
+                  This can make a big difference in encoding speed
+                  (it is around 4 times(!) faster, if we do not waste time
+                  on freeing _all_ buffers every time on long timelines...)
+                  (schlaile)
+               */
+               {
+                       uintptr_t mem_in_use;
+                       uintptr_t mmap_in_use;
+                       uintptr_t max;
+
+                       mem_in_use= MEM_get_memory_in_use();
+                       mmap_in_use= MEM_get_mapped_memory_in_use();
+                       max = MEM_CacheLimiter_get_maximum();
+
+                       if (max != 0 && mem_in_use + mmap_in_use > max) {
+                               fprintf(stderr, "Memory in use > maximum memory\n");
+                               fprintf(stderr, "Cleaning up, please wait...\n"
+                                       "If this happens very often,\n"
+                                       "consider "
+                                       "raising the memcache limit in the "
+                                       "user preferences.\n");
+                               free_imbuf_seq();
+                       }
+               }
+       }
+       else {
+               /* render result is delivered empty in most cases, nevertheless we handle all cases */
+               if (rr->rectf)
+                       memset(rr->rectf, 0, 4*sizeof(float)*rr->rectx*rr->recty);
+               else if (rr->rect32)
+                       memset(rr->rect32, 0, 4*rr->rectx*rr->recty);
+               else
+                       rr->rect32= MEM_callocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect");
+       }
+}
 
+#endif
index a18efb09515bc30a6f75ffdde388f590a3da2344..5c8eb5d2aa0ccf8ebc77fbf3a9477a0cc0e8a69a 100644 (file)
@@ -218,7 +218,7 @@ static struct Sequence *seq_stepdata__internal(struct BPathIterator *bpi, int st
                if (bpi->seqdata.scene->ed) {
                        if (bpi->seqdata.seqar == NULL) {
                                /* allocate the sequencer array */
-                               seq_array(bpi->seqdata.scene->ed, &bpi->seqdata.seqar, &bpi->seqdata.totseq);           
+                               seq_array(bpi->seqdata.scene->ed, &bpi->seqdata.seqar, &bpi->seqdata.totseq, 0);                
                                bpi->seqdata.seq = 0;
                        }
                        
index b412641284db6a6a3e96083efab7100608b65298..daca401ab50aea85302e2ae596a2bda24f603ca7 100644 (file)
@@ -1522,9 +1522,11 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
                                fac += 0.5f * dfac;
                                
                        /* draw vertical steps */
-                       for (; fac < vert.ymax; fac+= dfac, val += grid->dy) {
-                               scroll_printstr(vs, scene, (float)(vert.xmax)-14.0f, fac, val, grid->powery, vs->yunits, 'v');
-                       }                       
+                       if (dfac != 0.0f) {
+                               for (; fac < vert.ymax; fac+= dfac, val += grid->dy) {
+                                       scroll_printstr(vs, scene, (float)(vert.xmax)-14.0f, fac, val, grid->powery, vs->yunits, 'v');
+                               }
+                       }
                }       
                
                /* decoration outer bevel line */
index f6f837a107aafe25862f8638c735dcb02ba3257c..052e191cb7d35d7b26343a214e73c4bb838dc33f 100644 (file)
@@ -38,6 +38,8 @@ CFLAGS += $(LEVEL_1_C_WARNINGS)
 CPPFLAGS += -I$(NAN_GLEW)/include
 CPPFLAGS += -I$(OPENGL_HEADERS)
 
+CPPFLAGS += -I$(NAN_BMFONT)/include
+
 # not very neat....
 CPPFLAGS += -I../../windowmanager
 CPPFLAGS += -I../../blenloader
index e6c40474d25d75f6c7299a5cd5882496b1008d54..29781202e054e20502e504622f820c02e5d48680 100644 (file)
@@ -5,5 +5,6 @@ sources = env.Glob('*.c')
 
 incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
 incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' #intern/bmfont'
 
 env.BlenderLib ( 'bf_editors_space_sequencer', sources, Split(incs), [], libtype=['core'], priority=[100] )
diff --git a/source/blender/editors/space_sequencer/editseq.c b/source/blender/editors/space_sequencer/editseq.c
new file mode 100644 (file)
index 0000000..d9a0f48
--- /dev/null
@@ -0,0 +1,3985 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2003-2009
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+#include <sys/types.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_storage_types.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_ipo_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_view2d_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_sound_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_plugin_types.h"
+#include "BKE_sequence.h"
+#include "BKE_scene.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "WM_types.h"
+
+#include "ED_anim_api.h"
+#include "ED_space_api.h"
+#include "ED_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+/* own include */
+#include "sequencer_intern.h"
+
+/* XXX */
+static Sequence *_last_seq=0;
+static int _last_seq_init=0;
+/* XXX */
+static void BIF_undo_push() {}
+static void error() {}
+static void waitcursor() {}
+static void activate_fileselect() {}
+static void std_rmouse_transform() {}
+static int get_mbut() {return 0;}
+static int pupmenu() {return 0;}
+static int pupmenu_col() {return 0;}
+static int okee() {return 0;}
+static void *find_nearest_marker() {return NULL;}
+static void deselect_markers() {}
+static void transform_markers() {}
+static void transform_seq_nomarker() {}
+#define SCE_MARKERS 0
+/* XXX */
+
+
+#ifdef WIN32
+char last_imagename[FILE_MAXDIR+FILE_MAXFILE]= "c:\\";
+#else
+char last_imagename[FILE_MAXDIR+FILE_MAXFILE]= "/";
+#endif
+
+char last_sounddir[FILE_MAXDIR+FILE_MAXFILE]= "";
+
+#define SEQ_DESEL      ~(SELECT+SEQ_LEFTSEL+SEQ_RIGHTSEL)
+
+typedef struct TransSeq {
+       int start, machine;
+       int startstill, endstill;
+       int startdisp, enddisp;
+       int startofs, endofs;
+       int final_left, final_right;
+       int len;
+} TransSeq;
+
+Sequence *get_last_seq(Scene *scene)
+{
+       if(!_last_seq_init) {
+               Editing *ed;
+               Sequence *seq;
+               Sequence *l_sel = NULL;
+               Sequence *l_act = NULL;
+
+               ed= scene->ed;
+               if(!ed) return NULL;
+
+               for(seq= ed->seqbasep->first; seq; seq=seq->next) {
+                       if(seq->flag & SEQ_ACTIVE)
+                               l_act = seq;
+                       if(seq->flag & SELECT)
+                               l_sel = seq;
+               }
+
+               if (l_act) {
+                       _last_seq = l_act;
+               } else {
+                       _last_seq = l_sel;
+               }
+
+               if (_last_seq) {
+                       _last_seq->flag |= SEQ_ACTIVE;
+               }
+
+               _last_seq_init = 1;
+       }
+
+       return _last_seq;
+}
+
+void set_last_seq(Sequence *seq)
+{
+       if (_last_seq_init && _last_seq) {
+               _last_seq->flag &= ~SEQ_ACTIVE;
+       }
+
+       _last_seq = seq;
+       _last_seq_init = 1;
+
+       if (_last_seq) {
+               _last_seq->flag |= SEQ_ACTIVE;
+       }
+}
+
+void clear_last_seq()
+{
+       if (_last_seq_init && _last_seq) {
+               _last_seq->flag &= ~SEQ_ACTIVE;
+       }
+       _last_seq = NULL;
+       _last_seq_init = 0;
+}
+
+Sequence *get_forground_frame_seq(Scene *scene, int frame)
+{
+       Editing *ed;
+       Sequence *seq, *best_seq=NULL;
+       int best_machine = -1;
+       ed= scene->ed;
+       if(!ed) return NULL;
+       
+       for (seq=ed->seqbasep->first; seq; seq= seq->next) {
+               if(seq->startdisp > frame || seq->enddisp <= frame)
+                       continue;
+               /* only use elements you can see - not */
+               if (ELEM6(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE, SEQ_MOVIE_AND_HD_SOUND, SEQ_COLOR)) {
+                       if (seq->machine > best_machine) {
+                               best_seq = seq;
+                               best_machine = seq->machine;
+                       }
+               }
+       }
+       return best_seq;
+}
+
+/* seq funcs's for transforming internally
+ notice the difference between start/end and left/right.
+ left and right are the bounds at which the sequence is rendered,
+start and end are from the start and fixed length of the sequence.
+*/
+int seq_tx_get_start(Sequence *seq) {
+       return seq->start;
+}
+int seq_tx_get_end(Sequence *seq)
+{
+       return seq->start+seq->len;
+}
+
+int seq_tx_get_final_left(Sequence *seq, int metaclip)
+{
+       if (metaclip && seq->tmp) {
+               /* return the range clipped by the parents range */
+               return MAX2( seq_tx_get_final_left(seq, 0), seq_tx_get_final_left((Sequence *)seq->tmp, 1) );
+       } else {
+               return (seq->start - seq->startstill) + seq->startofs;
+       }
+       
+}
+int seq_tx_get_final_right(Sequence *seq, int metaclip)
+{
+       if (metaclip && seq->tmp) {
+               /* return the range clipped by the parents range */
+               return MIN2( seq_tx_get_final_right(seq, 0), seq_tx_get_final_right((Sequence *)seq->tmp, 1) );
+       } else {
+               return ((seq->start+seq->len) + seq->endstill) - seq->endofs;   
+       }
+}
+
+void seq_tx_set_final_left(Sequence *seq, int val)
+{
+       if (val < (seq)->start) {
+               seq->startstill = abs(val - (seq)->start);
+                               (seq)->startofs = 0;
+       } else {
+               seq->startofs = abs(val - (seq)->start);
+               seq->startstill = 0;
+       }
+}
+
+void seq_tx_set_final_right(Sequence *seq, int val)
+{
+       if (val > (seq)->start + (seq)->len) {
+               seq->endstill = abs(val - (seq->start + (seq)->len));
+               (seq)->endofs = 0;
+       } else {
+               seq->endofs = abs(val - ((seq)->start + (seq)->len));
+               seq->endstill = 0;
+       }
+}
+
+/* check if one side can be transformed */
+int seq_tx_check_left(Sequence *seq)
+{
+       if (seq->flag & SELECT) {
+               if (seq->flag & SEQ_LEFTSEL)
+                       return 1;
+               else if (seq->flag & SEQ_RIGHTSEL)
+                       return 0;
+               
+               return 1; /* selected and neither left or right handles are, so let us move both */
+       }
+       return 0;
+}
+
+int seq_tx_check_right(Sequence *seq)
+{
+       if (seq->flag & SELECT) {
+               if (seq->flag & SEQ_RIGHTSEL)
+                       return 1;
+               else if (seq->flag & SEQ_LEFTSEL)
+                       return 0;
+               
+               return 1; /* selected and neither left or right handles are, so let us move both */
+       }
+       return 0;
+}
+
+/* used so we can do a quick check for single image seq
+   since they work a bit differently to normal image seq's (during transform) */
+int check_single_seq(Sequence *seq)
+{
+       if ( seq->len==1 && (seq->type == SEQ_IMAGE || seq->type == SEQ_COLOR))
+               return 1;
+       else
+               return 0;
+}
+
+static void fix_single_image_seq(Sequence *seq)
+{
+       int left, start, offset;
+       if (!check_single_seq(seq))
+               return;
+       
+       /* make sure the image is always at the start since there is only one,
+          adjusting its start should be ok */
+       left = seq_tx_get_final_left(seq, 0);
+       start = seq->start;
+       if (start != left) {
+               offset = left - start;
+               seq_tx_set_final_left( seq, seq_tx_get_final_left(seq, 0) - offset );
+               seq_tx_set_final_right( seq, seq_tx_get_final_right(seq, 0) - offset );
+               seq->start += offset;
+       }
+}
+
+int test_overlap_seq(Scene *scene, Sequence *test)
+{
+       Sequence *seq;
+       Editing *ed;
+       
+       ed= scene->ed;
+       if(ed==NULL) return 0;
+       
+       seq= ed->seqbasep->first;
+       while(seq) {
+               if(seq!=test) {
+                       if(test->machine==seq->machine) {
+                               if(test->depth==seq->depth) {
+                                       if( (test->enddisp <= seq->startdisp) || (test->startdisp >= seq->enddisp) );
+                                       else return 1;
+                               }
+                       }
+               }
+               seq= seq->next;
+       }
+       return 0;
+}
+
+void shuffle_seq(Scene *scene, Sequence *test)
+{
+       Editing *ed;
+       Sequence *seq;
+       int a, start;
+       
+       ed= scene->ed;
+       if(ed==NULL) return;
+       
+       /* is there more than 1 select: only shuffle y */
+       a=0;
+       seq= ed->seqbasep->first;
+       while(seq) {
+               if(seq->flag & SELECT) a++;
+               seq= seq->next;
+       }
+       
+       if(a<2 && test->type==SEQ_IMAGE) {
+               start= test->start;
+               
+               for(a= 1; a<50; a++) {
+                       test->start= start+a;
+                       calc_sequence(test);
+                       if( test_overlap_seq(scene, test)==0) return;
+                       test->start= start-a;
+                       calc_sequence(test);
+                       if( test_overlap_seq(scene, test)==0) return;
+               }
+               test->start= start;
+       }
+       
+       test->machine++;
+       calc_sequence(test);
+       while( test_overlap_seq(scene, test) ) {
+               if(test->machine >= MAXSEQ) {
+                       error("There is no more space to add a sequence strip");
+                       
+                       BLI_remlink(ed->seqbasep, test);
+                       seq_free_sequence(test);
+                       return;
+               }
+               test->machine++;
+               calc_sequence(test);
+       }
+}
+
+static void change_plugin_seq(Scene *scene, char *str) /* called from fileselect */
+{
+       struct SeqEffectHandle sh;
+       Sequence *last_seq= get_last_seq(scene);
+
+       if(last_seq && last_seq->type != SEQ_PLUGIN) return;
+
+       sh = get_sequence_effect(last_seq);
+       sh.free(last_seq);
+       sh.init_plugin(last_seq, str);
+
+       last_seq->machine = MAX3(last_seq->seq1->machine, 
+                                last_seq->seq2->machine, 
+                                last_seq->seq3->machine);
+
+       if( test_overlap_seq(scene, last_seq) ) shuffle_seq(scene, last_seq);
+       
+       BIF_undo_push("Load/Change Plugin, Sequencer");
+}
+
+
+void boundbox_seq(Scene *scene, rctf *rect)
+{
+       Sequence *seq;
+       Editing *ed;
+       float min[2], max[2];
+
+       ed= scene->ed;
+       if(ed==NULL) return;
+
+       min[0]= 0.0;
+       max[0]= EFRA+1;
+       min[1]= 0.0;
+       max[1]= 8.0;
+
+       seq= ed->seqbasep->first;
+       while(seq) {
+
+               if( min[0] > seq->startdisp-1) min[0]= seq->startdisp-1;
+               if( max[0] < seq->enddisp+1) max[0]= seq->enddisp+1;
+               if( max[1] < seq->machine+2.0) max[1]= seq->machine+2.0;
+
+               seq= seq->next;
+       }
+
+       rect->xmin= min[0];
+       rect->xmax= max[0];
+       rect->ymin= min[1];
+       rect->ymax= max[1];
+
+}
+
+int sequence_is_free_transformable(Sequence * seq)
+{
+       return seq->type < SEQ_EFFECT
+               || (get_sequence_effect_num_inputs(seq->type) == 0);
+}
+
+char mouse_cfra_side(View2D *v2d, int frame ) 
+{
+       short mval[2];
+       float xmouse, ymouse;
+//     getmouseco_areawin(mval);
+       
+       /* choose the side based on which side of the playhead the mouse is on */
+       UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
+       return (xmouse > frame) ? 'R' : 'L';
+}
+
+Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int sel) 
+{
+/*     looks to the left on lr==1, to the right on lr==2
+       sel - 0==unselected, 1==selected, -1==done care*/
+       Sequence *seq;
+       Editing *ed;
+
+       ed= scene->ed;
+       if(ed==NULL) return 0;
+
+       if (sel>0) sel = SELECT;
+       
+       seq= ed->seqbasep->first;
+       while(seq) {
+               if(     (seq!=test) &&
+                       (test->machine==seq->machine) &&
+                       (test->depth==seq->depth) && 
+                       ((sel == -1) || (sel && (seq->flag & SELECT)) || (sel==0 && (seq->flag & SELECT)==0)  ))
+               {
+                       switch (lr) {
+                       case 1:
+                               if (test->startdisp == (seq->enddisp)) {
+                                       return seq;
+                               }
+                               break;
+                       case 2:
+                               if (test->enddisp == (seq->startdisp)) {
+                                       return seq;
+                               }
+                               break;
+                       }
+               }
+               seq= seq->next;
+       }
+       return NULL;
+}
+
+Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, int sel) 
+{
+/*     looks to the left on lr==1, to the right on lr==2
+       sel - 0==unselected, 1==selected, -1==done care*/
+       Sequence *seq,*best_seq = NULL;
+       Editing *ed;
+       
+       int dist, best_dist;
+       best_dist = MAXFRAME*2;
+
+       ed= scene->ed;
+       if(ed==NULL) return 0;
+
+       if (sel) sel = SELECT;
+       
+       seq= ed->seqbasep->first;
+       while(seq) {
+               if(             (seq!=test) &&
+                               (test->machine==seq->machine) &&
+                               (test->depth==seq->depth) &&
+                               ((sel == -1) || (sel==(seq->flag & SELECT))))
+               {
+                       dist = MAXFRAME*2;
+                       
+                       switch (lr) {
+                       case 1:
+                               if (seq->enddisp <= test->startdisp) {
+                                       dist = test->enddisp - seq->startdisp;
+                               }
+                               break;
+                       case 2:
+                               if (seq->startdisp >= test->enddisp) {
+                                       dist = seq->startdisp - test->enddisp;
+                               }
+                               break;
+                       }
+                       
+                       if (dist==0) {
+                               best_seq = seq;
+                               break;
+                       } else if (dist < best_dist) {
+                               best_dist = dist;
+                               best_seq = seq;
+                       }
+               }
+               seq= seq->next;
+       }
+       return best_seq; /* can be null */
+}
+
+
+Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand)
+{
+       Sequence *seq;
+       Editing *ed;
+       float x, y;
+       short mval[2];
+       float pixelx;
+       float handsize;
+       float displen;
+       *hand= 0;
+
+       ed= scene->ed;
+       if(ed==NULL) return 0;
+       
+       pixelx = (v2d->cur.xmax - v2d->cur.xmin)/(v2d->mask.xmax - v2d->mask.xmin);
+
+//     getmouseco_areawin(mval);
+       UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
+       
+       seq= ed->seqbasep->first;
+       
+       while(seq) {
+               if(seq->machine == (int)y) {
+                       /* check for both normal strips, and strips that have been flipped horizontally */
+                       if( ((seq->startdisp < seq->enddisp) && (seq->startdisp<=x && seq->enddisp>=x)) ||
+                               ((seq->startdisp > seq->enddisp) && (seq->startdisp>=x && seq->enddisp<=x)) )
+                       {
+                               if(sequence_is_free_transformable(seq)) {
+                                       
+                                       /* clamp handles to defined size in pixel space */
+                                       
+                                       handsize = seq->handsize;
+                                       displen = (float)abs(seq->startdisp - seq->enddisp);
+                                       
+                                       if (displen / pixelx > 16) { /* dont even try to grab the handles of small strips */
+                                               /* Set the max value to handle to 1/3 of the total len when its less then 28.
+                                               * This is important because otherwise selecting handles happens even when you click in the middle */
+                                               
+                                               if ((displen/3) < 30*pixelx) {
+                                                       handsize = displen/3;
+                                               } else {
+                                                       CLAMP(handsize, 7*pixelx, 30*pixelx);
+                                               }
+                                               
+                                               if( handsize+seq->startdisp >=x )
+                                                       *hand= 1;
+                                               else if( -handsize+seq->enddisp <=x )
+                                                       *hand= 2;
+                                       }
+                               }
+                               return seq;
+                       }
+               }
+               seq= seq->next;
+       }
+       return 0;
+}
+
+void update_seq_ipo_rect(Scene *scene, View2D *v2d, Sequence *seq)
+{
+       float start;
+       float end;
+
+       if (!seq || !seq->ipo) {
+               return;
+       }
+       start =  -5.0;
+       end   =  105.0;
+
+       
+       /* Adjust IPO window to sequence and 
+          avoid annoying snap-back to startframe 
+          when Lock Time is on */
+       if (0) { // XXX v2d->flag & V2D_VIEWLOCK) {
+               if ((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
+                       start = -5.0 + seq->startdisp;
+                       end = 5.0 + seq->enddisp;
+               } else {
+                       start = (float)scene->r.sfra - 0.1;
+                       end = scene->r.efra;
+               }
+       }
+
+       seq->ipo->cur.xmin= start;
+       seq->ipo->cur.xmax= end;
+}
+
+void update_seq_icu_rects(Sequence * seq)
+{
+       IpoCurve *icu= NULL;
+       struct SeqEffectHandle sh;
+
+       if (!seq || !seq->ipo) {
+               return;
+       }
+
+       if(!(seq->type & SEQ_EFFECT)) {
+               return;
+       }
+
+       sh = get_sequence_effect(seq);
+
+       for(icu= seq->ipo->curve.first; icu; icu= icu->next) {
+               sh.store_icu_yrange(seq, icu->adrcode, &icu->ymin, &icu->ymax);
+       }
+}
+
+
+static int seq_is_parent(Sequence *par, Sequence *seq)
+{
+       return ((par->seq1 == seq) || (par->seq2 == seq) || (par->seq3 == seq));
+}
+
+static int seq_is_predecessor(Sequence *pred, Sequence *seq)
+{
+       if (!pred) return 0;
+       if(pred == seq) return 0;
+       else if(seq_is_parent(pred, seq)) return 1;
+       else if(pred->seq1 && seq_is_predecessor(pred->seq1, seq)) return 1;
+       else if(pred->seq2 && seq_is_predecessor(pred->seq2, seq)) return 1;
+       else if(pred->seq3 && seq_is_predecessor(pred->seq3, seq)) return 1;
+
+       return 0;
+}
+
+static void deselect_all_seq(Scene *scene)
+{
+       Sequence *seq;
+       Editing *ed;
+
+       ed= scene->ed;
+       if(ed==NULL) return;
+
+       SEQP_BEGIN(ed, seq) {
+               seq->flag &= SEQ_DESEL;
+       }
+       SEQ_END
+               
+       BIF_undo_push("(De)select all Strips, Sequencer");
+}
+
+static void recurs_sel_seq(Sequence *seqm)
+{
+       Sequence *seq;
+
+       seq= seqm->seqbase.first;
+       while(seq) {
+
+               if(seqm->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL)) seq->flag &= SEQ_DESEL;
+               else if(seqm->flag & SELECT) seq->flag |= SELECT;
+               else seq->flag &= SEQ_DESEL;
+
+               if(seq->seqbase.first) recurs_sel_seq(seq);
+
+               seq= seq->next;
+       }
+}
+
+void select_single_seq(Scene *scene, Sequence *seq, int deselect_all)
+{
+       if(deselect_all)
+               deselect_all_seq(scene);
+       set_last_seq(seq);
+
+       if((seq->type==SEQ_IMAGE) || (seq->type==SEQ_MOVIE)) {
+               if(seq->strip)
+                       strncpy(last_imagename, seq->strip->dir, FILE_MAXDIR-1);
+       }
+       else if((seq->type==SEQ_HD_SOUND) || (seq->type==SEQ_RAM_SOUND)) {
+               if(seq->strip)
+                       strncpy(last_sounddir, seq->strip->dir, FILE_MAXDIR-1);
+       }
+       seq->flag|= SELECT;
+       recurs_sel_seq(seq);
+}
+
+void swap_select_seq(Scene *scene)
+{
+       Sequence *seq;
+       Editing *ed;
+       int sel=0;
+
+       ed= scene->ed;
+       if(ed==NULL) return;
+
+       SEQP_BEGIN(ed, seq) {
+               if(seq->flag & SELECT) sel= 1;
+       }
+       SEQ_END
+
+       SEQP_BEGIN(ed, seq) {
+               /* always deselect all to be sure */
+               seq->flag &= SEQ_DESEL;
+               if(sel==0) seq->flag |= SELECT;
+       }
+       SEQ_END
+
+       BIF_undo_push("Swap Selected Strips, Sequencer");
+
+}
+
+void select_channel_direction(Scene *scene, Sequence *test,int lr) {
+/* selects all strips in a channel to one direction of the passed strip */
+       Sequence *seq;
+       Editing *ed;
+
+       ed= scene->ed;
+       if(ed==NULL) return;
+
+       seq= ed->seqbasep->first;
+       while(seq) {
+               if(seq!=test) {
+                       if (test->machine==seq->machine) {
+                               if(test->depth==seq->depth) {
+                                       if (((lr==1)&&(test->startdisp > (seq->startdisp)))||((lr==2)&&(test->startdisp < (seq->startdisp)))) {
+                                               seq->flag |= SELECT;
+                                               recurs_sel_seq(seq);
+                                       }
+                               }
+                       }
+               }
+               seq= seq->next;
+       }
+       test->flag |= SELECT;
+       recurs_sel_seq(test);
+}
+
+void select_dir_from_last(Scene *scene, int lr)
+{
+       Sequence *seq=get_last_seq(scene);
+       if (seq==NULL)
+               return;
+       
+       select_channel_direction(scene, seq,lr);
+       
+       if (lr==1)      BIF_undo_push("Select Strips to the Left, Sequencer");
+       else            BIF_undo_push("Select Strips to the Right, Sequencer");
+}
+
+void select_surrounding_handles(Scene *scene, Sequence *test) 
+{
+       Sequence *neighbor;
+       
+       neighbor=find_neighboring_sequence(scene, test, 1, -1);
+       if (neighbor) {
+               neighbor->flag |= SELECT;
+               recurs_sel_seq(neighbor);
+               neighbor->flag |= SEQ_RIGHTSEL;
+       }
+       neighbor=find_neighboring_sequence(scene, test, 2, -1);
+       if (neighbor) {
+               neighbor->flag |= SELECT;
+               recurs_sel_seq(neighbor);
+               neighbor->flag |= SEQ_LEFTSEL;
+       }
+       test->flag |= SELECT;
+}
+
+void select_surround_from_last(Scene *scene)
+{
+       Sequence *seq=get_last_seq(scene);
+       
+       if (seq==NULL)
+               return;
+       
+       select_surrounding_handles(scene, seq);
+       BIF_undo_push("Select Surrounding Handles, Sequencer");
+}
+
+void select_neighbor_from_last(Scene *scene, int lr)
+{
+       Sequence *seq=get_last_seq(scene);
+       Sequence *neighbor;
+       int change = 0;
+       if (seq) {
+               neighbor=find_neighboring_sequence(scene, seq, lr, -1);
+               if (neighbor) {
+                       switch (lr) {
+                       case 1:
+                               neighbor->flag |= SELECT;
+                               recurs_sel_seq(neighbor);
+                               neighbor->flag |= SEQ_RIGHTSEL;
+                               seq->flag |= SEQ_LEFTSEL;
+                               break;
+                       case 2:
+                               neighbor->flag |= SELECT;
+                               recurs_sel_seq(neighbor);
+                               neighbor->flag |= SEQ_LEFTSEL;
+                               seq->flag |= SEQ_RIGHTSEL;
+                               break;
+                       }
+               seq->flag |= SELECT;
+               change = 1;
+               }
+       }
+       if (change) {
+               
+               if (lr==1)      BIF_undo_push("Select Left Handles, Sequencer");
+               else            BIF_undo_push("Select Right Handles, Sequencer");
+       }
+}
+
+void mouse_select_seq(Scene *scene, View2D *v2d)
+{
+       Sequence *seq,*neighbor;
+       int hand,seldir, shift= 0; // XXX
+       TimeMarker *marker;
+       
+       marker=find_nearest_marker(SCE_MARKERS, 1);
+       
+       if (marker) {
+               int oldflag;
+               /* select timeline marker */
+               if (shift) {
+                       oldflag= marker->flag;
+                       if (oldflag & SELECT)
+                               marker->flag &= ~SELECT;
+                       else
+                               marker->flag |= SELECT;
+               }
+               else {
+                       deselect_markers(0, 0);
+                       marker->flag |= SELECT;                         
+               }
+
+               BIF_undo_push("Select Strips, Sequencer");
+               
+       } else {
+       
+               seq= find_nearest_seq(scene, v2d, &hand);
+               if(0)  // !(G.qual & LR_SHIFTKEY)&&!(G.qual & LR_ALTKEY)&&!(G.qual & LR_CTRLKEY)) 
+                       deselect_all_seq(scene);
+       
+               if(seq) {
+                       set_last_seq(seq);
+       
+                       if ((seq->type == SEQ_IMAGE) || (seq->type == SEQ_MOVIE)) {
+                               if(seq->strip) {
+                                       strncpy(last_imagename, seq->strip->dir, FILE_MAXDIR-1);
+                               }
+                       } else
+                       if (seq->type == SEQ_HD_SOUND || seq->type == SEQ_RAM_SOUND) {
+                               if(seq->strip) {
+                                       strncpy(last_sounddir, seq->strip->dir, FILE_MAXDIR-1);
+                               }
+                       }
+       
+                       if(0) { // XXX (G.qual & LR_SHIFTKEY) && (seq->flag & SELECT)) {
+                               if(hand==0) seq->flag &= SEQ_DESEL;
+                               else if(hand==1) {
+                                       if(seq->flag & SEQ_LEFTSEL) 
+                                               seq->flag &= ~SEQ_LEFTSEL;
+                                       else seq->flag |= SEQ_LEFTSEL;
+                               }
+                               else if(hand==2) {
+                                       if(seq->flag & SEQ_RIGHTSEL) 
+                                               seq->flag &= ~SEQ_RIGHTSEL;
+                                       else seq->flag |= SEQ_RIGHTSEL;
+                               }
+                       }
+                       else {
+                               seq->flag |= SELECT;
+                               if(hand==1) seq->flag |= SEQ_LEFTSEL;
+                               if(hand==2) seq->flag |= SEQ_RIGHTSEL;
+                       }
+                       
+                       /* On Ctrl-Alt selection, select the strip and bordering handles */
+                       if (0) { // XXX (G.qual & LR_CTRLKEY) && (G.qual & LR_ALTKEY)) {
+                               // XXX if (!(G.qual & LR_SHIFTKEY)) deselect_all_seq(scene);
+                               seq->flag |= SELECT;
+                               select_surrounding_handles(scene, seq);
+                               
+                       /* Ctrl signals Left, Alt signals Right
+                       First click selects adjacent handles on that side.
+                       Second click selects all strips in that direction.
+                       If there are no adjacent strips, it just selects all in that direction. */
+                       } else if (0) { // XXX ((G.qual & LR_CTRLKEY) || (G.qual & LR_ALTKEY)) && (seq->flag & SELECT)) {
+               
+                               if (0); // G.qual & LR_CTRLKEY) seldir=1;
+                                       else seldir=2;
+                               neighbor=find_neighboring_sequence(scene, seq, seldir, -1);
+                               if (neighbor) {
+                                       switch (seldir) {
+                                       case 1:
+                                               if ((seq->flag & SEQ_LEFTSEL)&&(neighbor->flag & SEQ_RIGHTSEL)) {
+// XXX                                                 if (!(G.qual & LR_SHIFTKEY)) deselect_all_seq(scene);
+                                                       select_channel_direction(scene, seq,1);
+                                               } else {
+                                                       neighbor->flag |= SELECT;
+                                                       recurs_sel_seq(neighbor);
+                                                       neighbor->flag |= SEQ_RIGHTSEL;
+                                                       seq->flag |= SEQ_LEFTSEL;
+                                               }
+                                               break;
+                                       case 2:
+                                               if ((seq->flag & SEQ_RIGHTSEL)&&(neighbor->flag & SEQ_LEFTSEL)) {
+// XXX                                                 if (!(G.qual & LR_SHIFTKEY)) deselect_all_seq(scene);
+                                                       select_channel_direction(scene, seq,2);
+                                               } else {
+                                                       neighbor->flag |= SELECT;
+                                                       recurs_sel_seq(neighbor);
+                                                       neighbor->flag |= SEQ_LEFTSEL;
+                                                       seq->flag |= SEQ_RIGHTSEL;
+                                               }
+                                               break;
+                                       }
+                               } else {
+// XXX                                 if (!(G.qual & LR_SHIFTKEY)) deselect_all_seq(scene);
+                                       select_channel_direction(scene, seq,seldir);
+                               }
+                       }
+
+                       recurs_sel_seq(seq);
+               }
+
+
+               BIF_undo_push("Select Strips, Sequencer");
+
+               std_rmouse_transform(transform_seq_nomarker);
+       }
+       
+       /* marker transform */
+       if (marker) {
+               short mval[2], xo, yo;
+//             getmouseco_areawin(mval);
+               xo= mval[0]; 
+               yo= mval[1];
+               
+               while(get_mbut()) {             
+//                     getmouseco_areawin(mval);
+                       if(abs(mval[0]-xo)+abs(mval[1]-yo) > 4) {
+                               transform_markers('g', 0);
+                               return;
+                       }
+               }
+       }
+}
+
+
+Sequence *alloc_sequence(ListBase *lb, int cfra, int machine)
+{
+       Sequence *seq;
+
+       /*ed= scene->ed;*/
+
+       seq= MEM_callocN( sizeof(Sequence), "addseq");
+       BLI_addtail(lb, seq);
+
+       set_last_seq(seq);
+
+       *( (short *)seq->name )= ID_SEQ;
+       seq->name[2]= 0;
+
+       seq->flag= SELECT;
+       seq->start= cfra;
+       seq->machine= machine;
+       seq->mul= 1.0;
+       seq->blend_opacity = 100.0;
+       
+       return seq;
+}
+
+static Sequence *sfile_to_sequence(Scene *scene, SpaceFile *sfile, int cfra, int machine, int last)
+{
+#if 0
+       /* XXX sfile recoded... */
+       Sequence *seq;
+       Strip *strip;
+       StripElem *se;
+       int totsel, a;
+       char name[160];
+
+       /* are there selected files? */
+       totsel= 0;
+       for(a=0; a<sfile->totfile; a++) {
+               if(sfile->filelist[a].flags & ACTIVE) {
+                       if( (sfile->filelist[a].type & S_IFDIR)==0 ) {
+                               totsel++;
+                       }
+               }
+       }
+
+       if(last) {
+               /* if not, a file handed to us? */
+               if(totsel==0 && sfile->file[0]) totsel= 1;
+       }
+
+       if(totsel==0) return 0;
+
+       /* make seq */
+       seq= alloc_sequence(((Editing *)scene->ed)->seqbasep, cfra, machine);
+       seq->len= totsel;
+
+       if(totsel==1) {
+               seq->startstill= 25;
+               seq->endstill= 24;
+       }
+
+       calc_sequence(seq);
+       
+       if(sfile->flag & FILE_STRINGCODE) {
+               strcpy(name, sfile->dir);
+               BLI_makestringcode(G.sce, name);
+       } else {
+               strcpy(name, sfile->dir);
+       }
+
+       /* strip and stripdata */
+       seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+       strip->len= totsel;
+       strip->us= 1;
+       strncpy(strip->dir, name, FILE_MAXDIR-1);
+       strip->stripdata= se= MEM_callocN(totsel*sizeof(StripElem), "stripelem");
+
+       for(a=0; a<sfile->totfile; a++) {
+               if(sfile->filelist[a].flags & ACTIVE) {
+                       if( (sfile->filelist[a].type & S_IFDIR)==0 ) {
+                               strncpy(se->name, sfile->filelist[a].relname, FILE_MAXFILE-1);
+                               se++;
+                       }
+               }
+       }
+       /* no selected file: */
+       if(totsel==1 && se==strip->stripdata) {
+               strncpy(se->name, sfile->file, FILE_MAXFILE-1);
+       }
+
+       /* last active name */
+       strncpy(last_imagename, seq->strip->dir, FILE_MAXDIR-1);
+
+       return seq;
+#endif
+       return NULL;
+}
+
+
+#if 0
+static int sfile_to_mv_sequence_load(Scene *scene, SpaceFile *sfile, int cfra, 
+                                    int machine, int index )
+{
+       /* XXX sfile recoded... */
+       Sequence *seq;
+       struct anim *anim;
+       Strip *strip;
+       StripElem *se;
+       int totframe;
+       char name[160];
+       char str[FILE_MAXDIR+FILE_MAXFILE];
+
+       totframe= 0;
+
+       strncpy(str, sfile->dir, FILE_MAXDIR-1);
+       if(index<0)
+               strncat(str, sfile->file, FILE_MAXDIR-1);
+       else
+               strncat(str, sfile->filelist[index].relname, FILE_MAXDIR-1);
+
+       /* is it a movie? */
+       anim = openanim(str, IB_rect);
+       if(anim==0) {
+               error("The selected file is not a movie or "
+                     "FFMPEG-support not compiled in!");
+               return(cfra);
+       }
+       
+       totframe= IMB_anim_get_duration(anim);
+
+       /* make seq */
+       seq= alloc_sequence(((Editing *)scene->ed)->seqbasep, cfra, machine);
+       seq->len= totframe;
+       seq->type= SEQ_MOVIE;
+       seq->anim= anim;
+       seq->anim_preseek = IMB_anim_get_preseek(anim);
+
+       calc_sequence(seq);
+       
+       if(sfile->flag & FILE_STRINGCODE) {
+               strcpy(name, sfile->dir);
+               BLI_makestringcode(G.sce, name);
+       } else {
+               strcpy(name, sfile->dir);
+       }
+
+       /* strip and stripdata */
+       seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+       strip->len= totframe;
+       strip->us= 1;
+       strncpy(strip->dir, name, FILE_MAXDIR-1);
+       strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem");
+
+       /* name movie in first strip */
+       if(index<0)
+               strncpy(se->name, sfile->file, FILE_MAXFILE-1);
+       else
+               strncpy(se->name, sfile->filelist[index].relname, FILE_MAXFILE-1);
+
+       /* last active name */
+       strncpy(last_imagename, seq->strip->dir, FILE_MAXDIR-1);
+       return(cfra+totframe);
+}
+#endif
+
+static void sfile_to_mv_sequence(SpaceFile *sfile, int cfra, int machine)
+{
+#if 0
+       /* XXX sfile recoded... */
+       int a, totsel;
+
+       totsel= 0;
+       for(a= 0; a<sfile->totfile; a++) {
+               if(sfile->filelist[a].flags & ACTIVE) {
+                       if ((sfile->filelist[a].type & S_IFDIR)==0) {
+                               totsel++;
+                       }
+               }
+       }
+
+       if((totsel==0) && (sfile->file[0])) {
+               cfra= sfile_to_mv_sequence_load(sfile, cfra, machine, -1);
+               return;
+       }
+
+       if(totsel==0) return;
+
+       /* ok. check all the select file, and load it. */
+       for(a= 0; a<sfile->totfile; a++) {
+               if(sfile->filelist[a].flags & ACTIVE) {
+                       if ((sfile->filelist[a].type & S_IFDIR)==0) {
+                               /* load and update current frame. */
+                               cfra= sfile_to_mv_sequence_load(sfile, cfra, machine, a);
+                       }
+               }
+       }
+#endif
+}
+
+static Sequence *sfile_to_ramsnd_sequence(Scene *scene, SpaceFile *sfile,  int cfra, int machine)
+{
+#if 0
+       /* XXX sfile recoded... */
+       Sequence *seq;
+       bSound *sound;
+       Strip *strip;
+       StripElem *se;
+       double totframe;
+       char name[160];
+       char str[256];
+
+       totframe= 0.0;
+
+       strncpy(str, sfile->dir, FILE_MAXDIR-1);
+       strncat(str, sfile->file, FILE_MAXFILE-1);
+
+       sound= sound_new_sound(str);
+       if (!sound || sound->sample->type == SAMPLE_INVALID) {
+               error("Unsupported audio format");
+               return 0;
+       }
+       if (sound->sample->bits != 16) {
+               error("Only 16 bit audio is supported");
+               return 0;
+       }
+       sound->id.us=1;
+       sound->flags |= SOUND_FLAGS_SEQUENCE;
+       audio_makestream(sound);
+
+       totframe= (int) ( ((float)(sound->streamlen-1)/
+                          ( (float)scene->r.audio.mixrate*4.0 ))* FPS);
+
+       /* make seq */
+       seq= alloc_sequence(((Editing *)scene->ed)->seqbasep, cfra, machine);
+       seq->len= totframe;
+       seq->type= SEQ_RAM_SOUND;
+       seq->sound = sound;
+
+       calc_sequence(seq);
+       
+       if(sfile->flag & FILE_STRINGCODE) {
+               strcpy(name, sfile->dir);
+               BLI_makestringcode(G.sce, name);
+       } else {
+               strcpy(name, sfile->dir);
+       }
+
+       /* strip and stripdata */
+       seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+       strip->len= totframe;
+       strip->us= 1;
+       strncpy(strip->dir, name, FILE_MAXDIR-1);
+       strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem");
+
+       /* name sound in first strip */
+       strncpy(se->name, sfile->file, FILE_MAXFILE-1);
+
+       /* last active name */
+       strncpy(last_sounddir, seq->strip->dir, FILE_MAXDIR-1);
+
+       return seq;
+#endif
+       return NULL;
+}
+
+#if 0
+static int sfile_to_hdsnd_sequence_load(SpaceFile *sfile, int cfra, 
+                                       int machine, int index)
+{
+       /* XXX sfile recoded... */
+       Sequence *seq;
+       struct hdaudio *hdaudio;
+       Strip *strip;
+       StripElem *se;
+       int totframe;
+       char name[160];
+       char str[FILE_MAXDIR+FILE_MAXFILE];
+
+       totframe= 0;
+
+       strncpy(str, sfile->dir, FILE_MAXDIR-1);
+       if(index<0)
+               strncat(str, sfile->file, FILE_MAXDIR-1);
+       else
+               strncat(str, sfile->filelist[index].relname, FILE_MAXDIR-1);
+
+       /* is it a sound file? */
+       hdaudio = sound_open_hdaudio(str);
+       if(hdaudio==0) {
+               error("The selected file is not a sound file or "
+                     "FFMPEG-support not compiled in!");
+               return(cfra);
+       }
+
+       totframe= sound_hdaudio_get_duration(hdaudio, FPS);
+
+       /* make seq */
+       seq= alloc_sequence(((Editing *)scene->ed)->seqbasep, cfra, machine);
+       seq->len= totframe;
+       seq->type= SEQ_HD_SOUND;
+       seq->hdaudio= hdaudio;
+
+       calc_sequence(seq);
+       
+       if(sfile->flag & FILE_STRINGCODE) {
+               strcpy(name, sfile->dir);
+               BLI_makestringcode(G.sce, name);
+       } else {
+               strcpy(name, sfile->dir);
+       }
+
+       /* strip and stripdata */
+       seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+       strip->len= totframe;
+       strip->us= 1;
+       strncpy(strip->dir, name, FILE_MAXDIR-1);
+       strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem");
+
+       /* name movie in first strip */
+       if(index<0)
+               strncpy(se->name, sfile->file, FILE_MAXFILE-1);
+       else
+               strncpy(se->name, sfile->filelist[index].relname, FILE_MAXFILE-1);
+
+       /* last active name */
+       strncpy(last_sounddir, seq->strip->dir, FILE_MAXDIR-1);
+       return(cfra+totframe);
+}
+#endif
+
+static void sfile_to_hdsnd_sequence(SpaceFile *sfile, int cfra, int machine)
+{
+#if 0
+       /* XXX sfile recoded... */
+       int totsel, a;
+
+       totsel= 0;
+       for(a= 0; a<sfile->totfile; a++) {
+               if(sfile->filelist[a].flags & ACTIVE) {
+                       if((sfile->filelist[a].type & S_IFDIR)==0) {
+                               totsel++;
+                       }
+               }
+       }
+
+       if((totsel==0) && (sfile->file[0])) {
+               cfra= sfile_to_hdsnd_sequence_load(sfile, cfra, machine, -1);
+               return;
+       }
+
+       if(totsel==0) return;
+
+       /* ok, check all the select file, and load it. */
+       for(a= 0; a<sfile->totfile; a++) {
+               if(sfile->filelist[a].flags & ACTIVE) {
+                       if((sfile->filelist[a].type & S_IFDIR)==0) {
+                       &