Some small fixes and changes:
[blender.git] / source / blender / blenkernel / intern / sequencer.c
index b6bb5c3..3dcbe03 100644 (file)
@@ -1,6 +1,4 @@
-/**
-* $Id$
- *
+/*
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/blenkernel/intern/sequencer.c
+ *  \ingroup bke
+ */
+
+
 #include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
 #include "DNA_object_types.h"
 #include "DNA_sound_types.h"
 
+#include "BLI_math.h"
+#include "BLI_fileops.h"
+#include "BLI_listbase.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_threads.h"
+#include "BLI_utildefines.h"
+
 #include "BKE_animsys.h"
 #include "BKE_global.h"
 #include "BKE_image.h"
 #include "BKE_sequencer.h"
 #include "BKE_fcurve.h"
 #include "BKE_scene.h"
+#include "BKE_utildefines.h"
+
 #include "RNA_access.h"
+
 #include "RE_pipeline.h"
 
-#include "BLI_math.h"
-#include "BLI_fileops.h"
-#include "BLI_listbase.h"
-#include "BLI_path_util.h"
-#include "BLI_string.h"
-#include "BLI_threads.h"
 #include <pthread.h>
 
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
 
-
-
 #include "BKE_context.h"
 #include "BKE_sound.h"
-#include "AUD_C-API.h"
 
-#ifdef WIN32
-#define snprintf _snprintf
+#ifdef WITH_AUDASPACE
+#  include "AUD_C-API.h"
 #endif
 
-/* **** XXX ******** */
-//static void waitcursor(int val) {}
-//static int blender_test_break() {return 0;}
+static ImBuf* seq_render_strip_stack( 
+       SeqRenderData context, ListBase *seqbasep, float cfra, int chanshown);
+
+static ImBuf * seq_render_strip(
+       SeqRenderData context, Sequence * seq, float cfra);
+
+static void seq_free_animdata(Scene *scene, Sequence *seq);
+
 
 /* **** XXX ******** */
 #define SELECT 1
@@ -133,7 +143,7 @@ static void free_proxy_seq(Sequence *seq)
 {
        if (seq->strip && seq->strip->proxy && seq->strip->proxy->anim) {
                IMB_free_anim(seq->strip->proxy->anim);
-               seq->strip->proxy->anim = 0;
+               seq->strip->proxy->anim = NULL;
        }
 }
 
@@ -170,8 +180,6 @@ void seq_free_strip(Strip *strip)
        MEM_freeN(strip);
 }
 
-static void seq_free_animdata(Scene *scene, Sequence *seq);
-
 void seq_free_sequence(Scene *scene, Sequence *seq)
 {
        if(seq->strip) seq_free_strip(seq->strip);
@@ -184,6 +192,10 @@ void seq_free_sequence(Scene *scene, Sequence *seq)
                sh.free(seq);
        }
 
+       if(seq->sound) {
+               ((ID *)seq->sound)->us--; 
+       }
+
        /* clipboard has no scene and will never have a sound handle or be active */
        if(scene) {
                Editing *ed = scene->ed;
@@ -191,7 +203,7 @@ void seq_free_sequence(Scene *scene, Sequence *seq)
                if (ed->act_seq==seq)
                        ed->act_seq= NULL;
 
-               if(seq->scene_sound)
+               if(seq->scene_sound && ELEM(seq->type, SEQ_SOUND, SEQ_SCENE))
                        sound_remove_scene_sound(scene, seq->scene_sound);
 
                seq_free_animdata(scene, seq);
@@ -200,6 +212,18 @@ void seq_free_sequence(Scene *scene, Sequence *seq)
        MEM_freeN(seq);
 }
 
+void seq_free_sequence_recurse(Scene *scene, Sequence *seq)
+{
+       Sequence *iseq;
+
+       for(iseq= seq->seqbase.first; iseq; iseq= iseq->next) {
+               seq_free_sequence_recurse(scene, iseq);
+       }
+
+       seq_free_sequence(scene, seq);
+}
+
+
 Editing *seq_give_editing(Scene *scene, int alloc)
 {
        if (scene->ed == NULL && alloc) {
@@ -211,13 +235,25 @@ Editing *seq_give_editing(Scene *scene, int alloc)
        return scene->ed;
 }
 
+static void seq_free_clipboard_recursive(Sequence *seq_parent)
+{
+       Sequence *seq, *nseq;
+
+       for(seq= seq_parent->seqbase.first; seq; seq= nseq) {
+               nseq= seq->next;
+               seq_free_clipboard_recursive(seq);
+       }
+
+       seq_free_sequence(NULL, seq_parent);
+}
+
 void seq_free_clipboard(void)
 {
        Sequence *seq, *nseq;
 
        for(seq= seqbase_clipboard.first; seq; seq= nseq) {
                nseq= seq->next;
-               seq_free_sequence(NULL, seq);
+               seq_free_clipboard_recursive(seq);
        }
        seqbase_clipboard.first= seqbase_clipboard.last= NULL;
 }
@@ -244,7 +280,95 @@ void seq_free_editing(Scene *scene)
        MEM_freeN(ed);
 }
 
-/* ************************* itterator ************************** */
+/* **********************************************************************
+   * sequencer pipeline functions
+   ********************************************************************** */
+
+SeqRenderData seq_new_render_data(
+       struct Main * bmain, struct Scene * scene,
+       int rectx, int recty, int preview_render_size)
+{
+       SeqRenderData rval;
+
+       rval.bmain = bmain;
+       rval.scene = scene;
+       rval.rectx = rectx;
+       rval.recty = recty;
+       rval.preview_render_size = preview_render_size;
+       rval.motion_blur_samples = 0;
+       rval.motion_blur_shutter = 0;
+
+       return rval;
+}
+
+int seq_cmp_render_data(const SeqRenderData * a, const SeqRenderData * b)
+{
+       if (a->preview_render_size < b->preview_render_size) {
+               return -1;
+       }
+       if (a->preview_render_size > b->preview_render_size) {
+               return 1;
+       }
+       
+       if (a->rectx < b->rectx) {
+               return -1;
+       }
+       if (a->rectx > b->rectx) {
+               return 1;
+       }
+
+       if (a->recty < b->recty) {
+               return -1;
+       }
+       if (a->recty > b->recty) {
+               return 1;
+       }
+
+       if (a->bmain < b->bmain) {
+               return -1;
+       }
+       if (a->bmain > b->bmain) {
+               return 1;
+       }
+
+       if (a->scene < b->scene) {
+               return -1;
+       }
+       if (a->scene > b->scene) {
+               return 1;
+       }
+
+       if (a->motion_blur_shutter < b->motion_blur_shutter) {
+               return -1;
+       }
+       if (a->motion_blur_shutter > b->motion_blur_shutter) {
+               return 1;
+       }
+
+       if (a->motion_blur_samples < b->motion_blur_samples) {
+               return -1;
+       }
+       if (a->motion_blur_samples > b->motion_blur_samples) {
+               return 1;
+       }
+
+       return 0;
+}
+
+unsigned int seq_hash_render_data(const SeqRenderData * a)
+{
+       unsigned int rval = a->rectx + a->recty;
+
+       rval ^= a->preview_render_size;
+       rval ^= ((intptr_t) a->bmain) << 6;
+       rval ^= ((intptr_t) a->scene) << 6;
+       rval ^= (int) (a->motion_blur_shutter * 100.0f) << 10;
+       rval ^= a->motion_blur_samples << 24;
+       
+       return rval;
+}
+
+/* ************************* iterator ************************** */
 /* *************** (replaces old WHILE_SEQ) ********************* */
 /* **************** use now SEQ_BEGIN() SEQ_END ***************** */
 
@@ -340,50 +464,6 @@ void seq_end(SeqIterator *iter)
   **********************************************************************
 */
 
-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))
 {
@@ -413,8 +493,7 @@ static void do_build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int depth,
                seq->depth= depth;
 
                if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) {
-                       do_build_seqar_cb(&seq->seqbase, seqar, depth+1, 
-                                         test_func);
+                       do_build_seqar_cb(&seq->seqbase, seqar, depth+1, test_func);
                }
                if (test & BUILD_SEQAR_COUNT_CURRENT) {
                        **seqar= seq;
@@ -433,7 +512,7 @@ void build_seqar_cb(ListBase *seqbase, Sequence  ***seqar, int *totseq,
        do_seq_count_cb(seqbase, totseq, test_func);
 
        if(*totseq==0) {
-               *seqar= 0;
+               *seqar= NULL;
                return;
        }
        *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar");
@@ -460,7 +539,7 @@ void calc_sequence_disp(Scene *scene, Sequence *seq)
                seq->handsize= (float)((seq->enddisp-seq->startdisp)/25);
        }
 
-       seq_update_sound(scene, seq);
+       seq_update_sound_bounds(scene, seq);
 }
 
 static void seq_update_sound_bounds_recursive(Scene *scene, Sequence *metaseq)
@@ -473,7 +552,7 @@ static void seq_update_sound_bounds_recursive(Scene *scene, Sequence *metaseq)
                if(seq->type == SEQ_META) {
                        seq_update_sound_bounds_recursive(scene, seq);
                }
-               else if((seq->type == SEQ_SOUND) || (seq->type == SEQ_SCENE)) {
+               else if(ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) {
                        if(seq->scene_sound) {
                                int startofs = seq->startofs;
                                int endofs = seq->endofs;
@@ -504,8 +583,8 @@ void calc_sequence(Scene *scene, Sequence *seq)
 
        if(seq->type & SEQ_EFFECT) {
                /* pointers */
-               if(seq->seq2==0) seq->seq2= seq->seq1;
-               if(seq->seq3==0) seq->seq3= seq->seq1;
+               if(seq->seq2==NULL) seq->seq2= seq->seq1;
+               if(seq->seq3==NULL) seq->seq3= seq->seq1;
 
                /* effecten go from seq1 -> seq2: test */
 
@@ -517,8 +596,22 @@ void calc_sequence(Scene *scene, Sequence *seq)
                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);
+                       /* we cant help if strips don't overlap, it wont give useful results.
+                        * but at least ensure 'len' is never negative which causes bad bugs elsewhere. */
+                       if(seq->enddisp < seq->startdisp) {
+                               /* simple start/end swap */
+                               seq->start= seq->enddisp;
+                               seq->enddisp = seq->startdisp;
+                               seq->startdisp= seq->start;
+                               seq->flag |= SEQ_INVALID_EFFECT;
+                       }
+                       else {
+                               seq->flag &= ~SEQ_INVALID_EFFECT;
+                       }
+
                        seq->len= seq->enddisp - seq->startdisp;
-               } else {
+               }
+               else {
                        calc_sequence_disp(scene, seq);
                }
 
@@ -554,15 +647,13 @@ void calc_sequence(Scene *scene, Sequence *seq)
 }
 
 /* note: caller should run calc_sequence(scene, seq) after */
-void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int lock_range)
+void reload_sequence_new_file(Scene *scene, Sequence * seq, int lock_range)
 {
        char str[FILE_MAXDIR+FILE_MAXFILE];
-       int prev_startdisp, prev_enddisp;
+       int prev_startdisp=0, prev_enddisp=0;
        /* note: dont rename the strip, will break animation curves */
 
-       if (!(seq->type == SEQ_MOVIE || seq->type == SEQ_IMAGE ||
-                 seq->type == SEQ_SOUND ||
-                 seq->type == SEQ_SCENE || seq->type == SEQ_META)) {
+       if (ELEM5(seq->type, SEQ_MOVIE, SEQ_IMAGE, SEQ_SOUND, SEQ_SCENE, SEQ_META)==0) {
                return;
        }
 
@@ -576,13 +667,14 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc
 
        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_path_abs(str, G.sce);
+       if (ELEM3(seq->type, SEQ_SCENE, SEQ_META, SEQ_IMAGE)==0) {
+               BLI_join_dirfile(str, sizeof(str), seq->strip->dir, seq->strip->stripdata->name);
+               BLI_path_abs(str, G.main->name);
        }
 
-       if (seq->type == SEQ_IMAGE) {
+       switch(seq->type) {
+       case SEQ_IMAGE:
+       {
                /* Hack? */
                size_t olen = MEM_allocN_len(seq->strip->stripdata)/sizeof(struct StripElem);
 
@@ -593,15 +685,20 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc
                        seq->len = 0;
                }
                seq->strip->len = seq->len;
-       } else if (seq->type == SEQ_MOVIE) {
+               break;
+       }
+       case SEQ_MOVIE:
                if(seq->anim) IMB_free_anim(seq->anim);
-               seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0));
+               seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex);
 
                if (!seq->anim) {
                        return;
                }
        
-               seq->len = IMB_anim_get_duration(seq->anim);
+               seq->len = IMB_anim_get_duration(seq->anim,
+                                                seq->strip->proxy ?
+                                                seq->strip->proxy->tc :
+                                                IMB_TC_RECORD_RUN);
                
                seq->anim_preseek = IMB_anim_get_preseek(seq->anim);
 
@@ -611,7 +708,11 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc
                        seq->len = 0;
                }
                seq->strip->len = seq->len;
-       } else if (seq->type == SEQ_SOUND) {
+               break;
+       case SEQ_SOUND:
+#ifdef WITH_AUDASPACE
+               if(!seq->sound)
+                       return;
                seq->len = ceil(AUD_getInfo(seq->sound->playback_handle).length * FPS);
                seq->len -= seq->anim_startofs;
                seq->len -= seq->anim_endofs;
@@ -619,9 +720,14 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc
                        seq->len = 0;
                }
                seq->strip->len = seq->len;
-       } else if (seq->type == SEQ_SCENE) {
+#else
+               return;
+#endif
+               break;
+       case SEQ_SCENE:
+       {
                /* 'seq->scenenr' should be replaced with something more reliable */
-               Scene * sce = bmain->scene.first;
+               Scene * sce = G.main->scene.first;
                int nr = 1;
                
                while(sce) {
@@ -634,10 +740,8 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc
 
                if (sce) {
                        seq->scene = sce;
-               } else {
-                       sce = seq->scene;
                }
-               
+
                seq->len= seq->scene->r.efra - seq->scene->r.sfra + 1;
                seq->len -= seq->anim_startofs;
                seq->len -= seq->anim_endofs;
@@ -645,6 +749,8 @@ void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int loc
                        seq->len = 0;
                }
                seq->strip->len = seq->len;
+               break;
+       }
        }
 
        free_proxy_seq(seq);
@@ -668,8 +774,8 @@ void sort_seq(Scene *scene)
        
        if(ed==NULL) return;
 
-       seqbase.first= seqbase.last= 0;
-       effbase.first= effbase.last= 0;
+       seqbase.first= seqbase.last= NULL;
+       effbase.first= effbase.last= NULL;
 
        while( (seq= ed->seqbasep->first) ) {
                BLI_remlink(ed->seqbasep, seq);
@@ -683,7 +789,7 @@ void sort_seq(Scene *scene)
                                }
                                seqt= seqt->next;
                        }
-                       if(seqt==0) BLI_addtail(&effbase, seq);
+                       if(seqt==NULL) BLI_addtail(&effbase, seq);
                }
                else {
                        seqt= seqbase.first;
@@ -694,11 +800,11 @@ void sort_seq(Scene *scene)
                                }
                                seqt= seqt->next;
                        }
-                       if(seqt==0) BLI_addtail(&seqbase, seq);
+                       if(seqt==NULL) BLI_addtail(&seqbase, seq);
                }
        }
 
-       addlisttolist(&seqbase, &effbase);
+       BLI_movelisttolist(&seqbase, &effbase);
        *(ed->seqbasep)= seqbase;
 }
 
@@ -733,7 +839,7 @@ typedef struct SeqUniqueInfo {
 /*
 static void seqbase_unique_name(ListBase *seqbasep, Sequence *seq)
 {
-        BLI_uniquename(seqbasep, seq, "Sequence", '.', offsetof(Sequence, name), SEQ_NAME_MAXSTR);
+       BLI_uniquename(seqbasep, seq, "Sequence", '.', offsetof(Sequence, name), SEQ_NAME_MAXSTR);
 }*/
 
 static void seqbase_unique_name(ListBase *seqbasep, SeqUniqueInfo *sui)
@@ -759,8 +865,8 @@ void seqbase_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq)
        SeqUniqueInfo sui;
        char *dot;
        sui.seq= seq;
-       strcpy(sui.name_src, seq->name+2);
-       strcpy(sui.name_dest, seq->name+2);
+       BLI_strncpy(sui.name_src, seq->name+2, sizeof(sui.name_src));
+       BLI_strncpy(sui.name_dest, seq->name+2, sizeof(sui.name_dest));
 
        sui.count= 1;
        sui.match= 1; /* assume the worst to start the loop */
@@ -780,10 +886,10 @@ void seqbase_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq)
                seqbase_recursive_apply(seqbasep, seqbase_unique_name_recursive_cb, &sui);
        }
 
-       strcpy(seq->name+2, sui.name_dest);
+       BLI_strncpy(seq->name+2, sui.name_dest, sizeof(seq->name)-2);
 }
 
-static char *give_seqname_by_type(int type)
+static const char *give_seqname_by_type(int type)
 {
        switch(type) {
        case SEQ_META:       return "Meta";
@@ -804,15 +910,16 @@ static char *give_seqname_by_type(int type)
        case SEQ_TRANSFORM:  return "Transform";
        case SEQ_COLOR:      return "Color";
        case SEQ_MULTICAM:   return "Multicam";
+       case SEQ_ADJUSTMENT: return "Adjustment";
        case SEQ_SPEED:      return "Speed";
        default:
-               return 0;
+               return NULL;
        }
 }
 
-char *give_seqname(Sequence *seq)
+const char *give_seqname(Sequence *seq)
 {
-       char * name = give_seqname_by_type(seq->type);
+       const char *name = give_seqname_by_type(seq->type);
 
        if (!name) {
                if(seq->type<SEQ_EFFECT) {
@@ -839,7 +946,7 @@ static void make_black_ibuf(ImBuf *ibuf)
        float *rect_float;
        int tot;
 
-       if(ibuf==0 || (ibuf->rect==0 && ibuf->rect_float==0)) return;
+       if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) return;
 
        tot= ibuf->x*ibuf->y;
 
@@ -862,7 +969,7 @@ static void multibuf(ImBuf *ibuf, float fmul)
 
        int a, mul, icol;
 
-       mul= (int)(256.0*fmul);
+       mul= (int)(256.0f * fmul);
        rt= (char *)ibuf->rect;
        rt_float = ibuf->rect_float;
 
@@ -898,21 +1005,32 @@ static void multibuf(ImBuf *ibuf, float fmul)
 static float give_stripelem_index(Sequence *seq, float cfra)
 {
        float nr;
+       int sta = seq->start;
+       int end = seq->start+seq->len-1;
+
+       if (seq->type & SEQ_EFFECT) {
+               end = seq->enddisp;
+       } 
+
+       if(end < sta) {
+               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 - 1) - cfra;
+               if(cfra <= sta) nr= end - sta;
+               else if(cfra >= end) nr= 0;
+               else nr= end - 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(cfra <= sta) nr= 0;
+               else if(cfra >= end) nr= end - sta;
+               else nr= cfra - sta;
        }
-       if (seq->strobe < 1.0) seq->strobe = 1.0;
-       if (seq->strobe > 1.0) {
-               nr -= fmod((double)nr, (double)seq->strobe);
+       
+       if (seq->strobe < 1.0f) seq->strobe = 1.0f;
+       
+       if (seq->strobe > 1.0f) {
+               nr -= fmodf((double)nr, (double)seq->strobe);
        }
 
        return nr;
@@ -922,14 +1040,14 @@ StripElem *give_stripelem(Sequence *seq, int cfra)
 {
        StripElem *se= seq->strip->stripdata;
 
-       if(seq->type == SEQ_MOVIE) {
-               /* use the first */
-       }
-       else {
+       if(seq->type == SEQ_IMAGE) { /* only 
+                                       IMAGE strips use the whole array,
+                                       MOVIE strips use only 
+                                       the first element, all other strips
+                                       don't use this... */
                int nr = (int) give_stripelem_index(seq, cfra);
 
-               if (nr == -1) return 0;
-               if (se == 0) return 0;
+               if (nr == -1 || se == NULL) return NULL;
        
                se += nr + seq->anim_startofs;
        }
@@ -966,9 +1084,7 @@ int evaluate_seq_frame(Scene *scene, int cfra)
 
 static int video_seq_is_rendered(Sequence * seq)
 {
-       return (seq
-               && !(seq->flag & SEQ_MUTE)
-               && seq->type != SEQ_SOUND);
+       return (seq && !(seq->flag & SEQ_MUTE) && seq->type != SEQ_SOUND);
 }
 
 static int get_shown_sequences(        ListBase * seqbasep, int cfra, int chanshown, Sequence ** seq_arr_out)
@@ -982,15 +1098,12 @@ static int get_shown_sequences(  ListBase * seqbasep, int cfra, int chanshown, Se
        }
 
        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;
-                               }
+               if (b == 0) {
+                       b = MAXSEQ;
+               }
+               for (; b > 0; b--) {
+                       if (video_seq_is_rendered(seq_arr[b])) {
+                               break;
                        }
                }
        }
@@ -1005,7 +1118,7 @@ static int get_shown_sequences(   ListBase * seqbasep, int cfra, int chanshown, Se
                }
        }
 
-       for (;b <= chanshown; b++) {
+       for (;b <= chanshown && b >= 0; b++) {
                if (video_seq_is_rendered(seq_arr[b])) {
                        seq_arr_out[cnt++] = seq_arr[b];
                }
@@ -1013,7 +1126,7 @@ static int get_shown_sequences(   ListBase * seqbasep, int cfra, int chanshown, Se
 
        return cnt;
 }
+
 
 /* **********************************************************************
    proxy management
@@ -1021,172 +1134,200 @@ static int get_shown_sequences(       ListBase * seqbasep, int cfra, int chanshown, Se
 
 #define PROXY_MAXFILE (2*FILE_MAXDIR+FILE_MAXFILE)
 
-static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * name, int render_size)
+static IMB_Proxy_Size seq_rendersize_to_proxysize(int size)
+{
+       if (size >= 100) {
+               return IMB_PROXY_NONE;
+       }
+       if (size >= 99) {
+               return IMB_PROXY_100;
+       }
+       if (size >= 75) {
+               return IMB_PROXY_75;
+       }
+       if (size >= 50) {
+               return IMB_PROXY_50;
+       }
+       return IMB_PROXY_25;
+}
+
+static void seq_open_anim_file(Sequence * seq)
+{
+       char name[FILE_MAXDIR+FILE_MAXFILE];
+       StripProxy * proxy;
+
+       if(seq->anim != NULL) {
+               return;
+       }
+
+       BLI_join_dirfile(name, sizeof(name), 
+                        seq->strip->dir, seq->strip->stripdata->name);
+       BLI_path_abs(name, G.main->name);
+       
+       seq->anim = openanim(name, IB_rect |
+                            ((seq->flag & SEQ_FILTERY) ? 
+                             IB_animdeinterlace : 0), seq->streamindex);
+
+       if (seq->anim == NULL) {
+               return;
+       }
+
+       proxy = seq->strip->proxy;
+
+       if (proxy == NULL) {
+               return;
+       }
+
+       if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) {
+               IMB_anim_set_index_dir(seq->anim, seq->strip->proxy->dir);
+       }
+}
+
+
+static int seq_proxy_get_fname(SeqRenderData context, Sequence * seq, int cfra, char * name)
 {
        int frameno;
-       char dir[FILE_MAXDIR];
+       char dir[PROXY_MAXFILE];
+       int render_size = context.preview_render_size;
 
        if (!seq->strip->proxy) {
                return FALSE;
        }
 
-       if ((seq->flag & SEQ_USE_PROXY_CUSTOM_DIR)
-           || (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE)) {
-               strcpy(dir, seq->strip->proxy->dir);
+       /* MOVIE tracks (only exception: custom files) are now handled 
+          internally by ImBuf module for various reasons: proper time code 
+          support, quicker index build, using one file instead 
+          of a full directory of jpeg files, etc. Trying to support old
+          and new method at once could lead to funny effects, if people
+          have both, a directory full of jpeg files and proxy avis, so
+          sorry folks, please rebuild your proxies... */
+
+       if (seq->flag & (SEQ_USE_PROXY_CUSTOM_DIR|SEQ_USE_PROXY_CUSTOM_FILE)) {
+               BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir));
+       } else if (seq->type == SEQ_IMAGE) {
+               BLI_snprintf(dir, PROXY_MAXFILE, "%s/BL_proxy", seq->strip->dir);
        } else {
-               if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) {
-                       snprintf(dir, FILE_MAXDIR, "%s/BL_proxy", 
-                                seq->strip->dir);
-               } else {
-                       return FALSE;
-               }
+               return FALSE;
        }
 
        if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
-               BLI_join_dirfile(name, dir, seq->strip->proxy->file);
-               BLI_path_abs(name, G.sce);
+               BLI_join_dirfile(name, PROXY_MAXFILE, 
+                                dir, seq->strip->proxy->file);
+               BLI_path_abs(name, G.main->name);
 
                return TRUE;
        }
 
+       /* dirty hack to distinguish 100% render size from PROXY_100 */
+       if (render_size == 99) {
+               render_size = 100;
+       }
+
        /* generate a separate 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, render_size, se->name);
+               BLI_snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy", dir,
+                        context.preview_render_size, 
+                        give_stripelem(seq, cfra)->name);
                frameno = 1;
-       } else if (seq->type == SEQ_MOVIE) {
-               frameno = (int) give_stripelem_index(seq, cfra) 
-                       + seq->anim_startofs;
-
-               snprintf(name, PROXY_MAXFILE, "%s/%s/%d/####", dir,
-                        seq->strip->stripdata->name,
-                        render_size);
        } else {
                frameno = (int) give_stripelem_index(seq, cfra) 
                        + seq->anim_startofs;
-
-               snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir,
-                        render_size);
+               BLI_snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir, 
+                        context.preview_render_size);
        }
 
-       BLI_path_abs(name, G.sce);
+       BLI_path_abs(name, G.main->name);
        BLI_path_frame(name, frameno, 0);
 
-
        strcat(name, ".jpg");
 
        return TRUE;
 }
 
-static struct ImBuf * seq_proxy_fetch(Scene *scene, Sequence * seq, int cfra, int render_size)
+static struct ImBuf * seq_proxy_fetch(SeqRenderData context, Sequence * seq, int cfra)
 {
        char name[PROXY_MAXFILE];
+       IMB_Proxy_Size psize = seq_rendersize_to_proxysize(
+               context.preview_render_size);
+       int size_flags;
 
        if (!(seq->flag & SEQ_USE_PROXY)) {
-               return 0;
+               return NULL;
        }
 
-       /* rendering at 100% ? No real sense in proxy-ing, right? */
-       if (render_size == 100) {
-               return 0;
+       size_flags = seq->strip->proxy->build_size_flags;
+
+       /* only use proxies, if they are enabled (even if present!) */
+       if (psize == IMB_PROXY_NONE || ((size_flags & psize) != psize)) {
+               return NULL;
        }
 
        if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
-               int frameno = (int) give_stripelem_index(seq, cfra) 
-                       + seq->anim_startofs;
-               if (!seq->strip->proxy->anim) {
-                       if (!seq_proxy_get_fname(
-                                   scene, seq, cfra, name, render_size)) {
-                               return 0;
+               int frameno = (int) give_stripelem_index(seq, cfra) + seq->anim_startofs;
+               if (seq->strip->proxy->anim == NULL) {
+                       if (seq_proxy_get_fname(context, seq, cfra, name)==0) {
+                               return NULL;
                        }
  
-                       seq->strip->proxy->anim = openanim(name, IB_rect);
+                       seq->strip->proxy->anim = openanim(name, IB_rect, 0);
                }
-               if (!seq->strip->proxy->anim) {
-                       return 0;
+               if (seq->strip->proxy->anim==NULL) {
+                       return NULL;
                }
  
-               return IMB_anim_absolute(seq->strip->proxy->anim, frameno);
+               seq_open_anim_file(seq);
+
+               frameno = IMB_anim_index_get_frame_index(
+                       seq->anim, seq->strip->proxy->tc, frameno);
+
+               return IMB_anim_absolute(seq->strip->proxy->anim, frameno,
+                                        IMB_TC_NONE, IMB_PROXY_NONE);
        }
  
-       if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) {
-               return 0;
+       if (seq_proxy_get_fname(context, seq, cfra, name) == 0) {
+               return NULL;
        }
 
        if (BLI_exists(name)) {
                return IMB_loadiffname(name, IB_rect);
        } else {
-               return 0;
+               return NULL;
        }
 }
 
-#if 0
-static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra,
-                                 int build_proxy_run, int render_size);
-
-static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int render_size, int seqrectx, int seqrecty)
+static void seq_proxy_build_frame(SeqRenderData context,
+                                 Sequence* seq, int cfra,
+                                 int proxy_render_size)
 {
        char name[PROXY_MAXFILE];
        int quality;
-       TStripElem * se;
-       int ok;
        int rectx, recty;
+       int ok;
        struct ImBuf * ibuf;
 
-       if (!(seq->flag & SEQ_USE_PROXY)) {
-               return;
-       }
-
-       /* rendering at 100% ? No real sense in proxy-ing, right? */
-       if (render_size == 100) {
-               return;
-       }
-
-       /* that's why it is called custom... */
-       if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
+       if (!seq_proxy_get_fname(context, seq, cfra, name)) {
                return;
        }
 
-       if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) {
-               return;
-       }
+       ibuf = seq_render_strip(context, seq, cfra);
 
-       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, render_size,
-                         seqrectx, seqrecty);
-
-       if (!se->ibuf) {
-               return;
-       }
-
-       rectx= (render_size*scene->r.xsch)/100;
-       recty= (render_size*scene->r.ysch)/100;
-
-       ibuf = se->ibuf;
+       rectx = (proxy_render_size * context.scene->r.xsch) / 100;
+       recty = (proxy_render_size * context.scene->r.ysch) / 100;
 
        if (ibuf->x != rectx || ibuf->y != recty) {
                IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty);
        }
 
-       /* quality is fixed, otherwise one has to generate separate
-          directories for every quality...
-
-          depth = 32 is intentionally left in, otherwise ALPHA channels
+       /* depth = 32 is intentionally left in, otherwise ALPHA channels
           won't work... */
        quality = seq->strip->proxy->quality;
        ibuf->ftype= JPG | quality;
 
+       /* unsupported feature only confuses other s/w */
+       if(ibuf->depth==32)
+               ibuf->depth= 24;
+
        BLI_make_existing_file(name);
        
        ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat);
@@ -1195,69 +1336,80 @@ static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int re
        }
 
        IMB_freeImBuf(ibuf);
-       se->ibuf = 0;
 }
 
-static void seq_proxy_rebuild(Scene *scene, Sequence * seq, int seqrectx,
-                             int seqrecty)
+void seq_proxy_rebuild(struct Main * bmain, Scene *scene, Sequence * seq,
+                      short *stop, short *do_update, float *progress)
 {
+       SeqRenderData context;
        int cfra;
-       float rsize = seq->strip->proxy->size;
+       int tc_flags;
+       int size_flags;
+       int quality;
 
-       waitcursor(1);
+       if (!seq->strip || !seq->strip->proxy) {
+               return;
+       }
+
+       if (!(seq->flag & SEQ_USE_PROXY)) {
+               return;
+       }
 
-       G.afbreek = 0;
+       tc_flags   = seq->strip->proxy->build_tc_flags;
+       size_flags = seq->strip->proxy->build_size_flags;
+       quality    = seq->strip->proxy->quality;
 
-       /* 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.
-        */
+       if (seq->type == SEQ_MOVIE) {
+               seq_open_anim_file(seq);
 
-       for (cfra = seq->startdisp; cfra < seq->enddisp; cfra++) {
-               TStripElem * tse = give_tstripelem(seq, cfra);
+               if (seq->anim) {
+                       IMB_anim_index_rebuild(
+                               seq->anim, tc_flags, size_flags, quality,
+                               stop, do_update, progress);
+               }
+               return;
+       }
 
-               tse->flag &= ~STRIPELEM_PREVIEW_DONE;
+       if (!(seq->flag & SEQ_USE_PROXY)) {
+               return;
        }
 
-       
+       /* that's why it is called custom... */
+       if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
+               return;
+       }
 
-       /* 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)) {
-//XXX                          set_timecursor(cfra);
-                               seq_proxy_build_frame(scene, seq, cfra, rsize,
-                                                     seqrectx, seqrecty);
-                               tse->flag |= STRIPELEM_PREVIEW_DONE;
-                       }
-                       if (blender_test_break()) {
-                               break;
-                       }
+       /* fail safe code */
+
+       context = seq_new_render_data(
+               bmain, scene, 
+               (scene->r.size * (float) scene->r.xsch) / 100.0f + 0.5f, 
+               (scene->r.size * (float) scene->r.ysch) / 100.0f + 0.5f, 
+               100);
+
+       for (cfra = seq->startdisp + seq->startstill; 
+            cfra < seq->enddisp - seq->endstill; cfra++) {
+               if (size_flags & IMB_PROXY_25) {
+                       seq_proxy_build_frame(context, seq, cfra, 25);
                }
-       } 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)) {
-//XXX                          set_timecursor(cfra);
-                               seq_proxy_build_frame(scene, seq, cfra, rsize,
-                                                     seqrectx, seqrecty);
-                               tse->flag |= STRIPELEM_PREVIEW_DONE;
-                       }
-                       if (blender_test_break()) {
-                               break;
-                       }
+               if (size_flags & IMB_PROXY_50) {
+                       seq_proxy_build_frame(context, seq, cfra, 50);
+               }
+               if (size_flags & IMB_PROXY_75) {
+                       seq_proxy_build_frame(context, seq, cfra, 75);
+               }
+               if (size_flags & IMB_PROXY_100) {
+                       seq_proxy_build_frame(context, seq, cfra, 100);
                }
+
+               *progress= (float)cfra/(seq->enddisp - seq->endstill 
+                                       - seq->startdisp + seq->startstill);
+               *do_update= 1;
+
+               if(*stop || G.afbreek)
+                       break;
        }
-       waitcursor(0);
 }
-#endif
 
 
 /* **********************************************************************
@@ -1278,7 +1430,7 @@ static StripColorBalance calc_cb(StripColorBalance * cb_)
                        /* tweak to give more subtle results
                         * values above 1.0 are scaled */
                        if(cb.lift[c] > 1.0f)
-                               cb.lift[c] = pow(cb.lift[c] - 1.0f, 2.0f) + 1.0f;
+                               cb.lift[c] = pow(cb.lift[c] - 1.0f, 2.0) + 1.0;
 
                        cb.lift[c] = 2.0f - cb.lift[c];
                }
@@ -1286,8 +1438,8 @@ static StripColorBalance calc_cb(StripColorBalance * cb_)
 
        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];
+                       if (cb.gain[c] != 0.0f) {
+                               cb.gain[c] = 1.0f / cb.gain[c];
                        } else {
                                cb.gain[c] = 1000000; /* should be enough :) */
                        }
@@ -1296,8 +1448,8 @@ static StripColorBalance calc_cb(StripColorBalance * cb_)
 
        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];
+                       if (cb.gamma[c] != 0.0f) {
+                               cb.gamma[c] = 1.0f/cb.gamma[c];
                        } else {
                                cb.gamma[c] = 1000000; /* should be enough :) */
                        }
@@ -1324,7 +1476,7 @@ static void make_cb_table_byte(float lift, float gain, float gamma,
        int y;
 
        for (y = 0; y < 256; y++) {
-               float v= color_balance_fl((float)y * (1.0 / 255.0f), lift, gain, gamma, mul);
+               float v= color_balance_fl((float)y * (1.0f / 255.0f), lift, gain, gamma, mul);
                CLAMP(v, 0.0f, 1.0f);
                table[y] = v * 255;
        }
@@ -1336,7 +1488,7 @@ static void make_cb_table_float(float lift, float gain, float gamma,
        int y;
 
        for (y = 0; y < 256; y++) {
-               float v= color_balance_fl((float)y * (1.0 / 255.0f), lift, gain, gamma, mul);
+               float v= color_balance_fl((float)y * (1.0f / 255.0f), lift, gain, gamma, mul);
                table[y] = v;
        }
 }
@@ -1380,8 +1532,7 @@ static void color_balance_byte_float(Sequence * seq, ImBuf* ibuf, float mul)
        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);
+               make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul);
        }
 
        for (i = 0; i < 256; i++) {
@@ -1444,31 +1595,26 @@ static void color_balance(Sequence * seq, ImBuf* ibuf, float mul)
 */
 
 int input_have_to_preprocess(
-       Scene *scene, Sequence * seq, float cfra, int seqrectx, int seqrecty)
+       SeqRenderData UNUSED(context), Sequence * seq, float UNUSED(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)) {
+       if (seq->flag & (SEQ_FILTERY|SEQ_USE_CROP|SEQ_USE_TRANSFORM|SEQ_FLIPX|
+                        SEQ_FLIPY|SEQ_USE_COLOR_BALANCE|SEQ_MAKE_PREMUL)) {
                return TRUE;
        }
 
        mul = seq->mul;
 
        if(seq->blend_mode == SEQ_BLEND_REPLACE) {
-               mul *= seq->blend_opacity / 100.0;
+               mul *= seq->blend_opacity / 100.0f;
        }
 
-       if (mul != 1.0) {
+       if (mul != 1.0f) {
                return TRUE;
        }
 
-       if (seq->sat != 1.0) {
+       if (seq->sat != 1.0f) {
                return TRUE;
        }
                
@@ -1476,26 +1622,21 @@ int input_have_to_preprocess(
 }
 
 static ImBuf * input_preprocess(
-       Scene *scene, Sequence *seq, float cfra, int seqrectx, int seqrecty,
-       ImBuf * ibuf)
+       SeqRenderData context, Sequence *seq, float UNUSED(cfra), ImBuf * ibuf)
 {
        float mul;
 
-       seq->strip->orx= ibuf->x;
-       seq->strip->ory= ibuf->y;
+       ibuf = IMB_makeSingleUser(ibuf);
 
        if((seq->flag & SEQ_FILTERY) && seq->type != SEQ_MOVIE) {
                IMB_filtery(ibuf);
        }
 
-       if(seq->flag & SEQ_USE_CROP || seq->flag & SEQ_USE_TRANSFORM) {
-               StripCrop c;
-               StripTransform t;
+       if(seq->flag & (SEQ_USE_CROP|SEQ_USE_TRANSFORM)) {
+               StripCrop c= {0};
+               StripTransform t= {0};
                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;
                }
@@ -1509,27 +1650,17 @@ static ImBuf * input_preprocess(
                dy = sy;
 
                if (seq->flag & SEQ_USE_TRANSFORM) {
-                       dx = scene->r.xsch;
-                       dy = scene->r.ysch;
+                       dx = context.scene->r.xsch;
+                       dy = context.scene->r.ysch;
                }
 
-               if (c.top + c.bottom >= ibuf->y ||
-                       c.left + c.right >= ibuf->x ||
-                       t.xofs >= dx || t.yofs >= dy) {
+               if (c.top + c.bottom >= ibuf->y || c.left + c.right >= ibuf->x ||
+                               t.xofs >= dx || t.yofs >= dy) {
                        make_black_ibuf(ibuf);
                } else {
-                       ImBuf * i;
+                       ImBuf * i = IMB_allocImBuf(dx, dy,32, ibuf->rect_float ? IB_rectfloat : IB_rect);
 
-                       if (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, ibuf, 
-                                   t.xofs, t.yofs, 
-                                   c.left, c.bottom, 
-                                   sx, sy);
+                       IMB_rectcpy(i, ibuf, t.xofs, t.yofs, c.left, c.bottom, sx, sy);
                        
                        IMB_freeImBuf(ibuf);
 
@@ -1548,7 +1679,7 @@ static ImBuf * input_preprocess(
        if(seq->sat != 1.0f) {
                /* inline for now, could become an imbuf function */
                int i;
-               char *rct= (char *)ibuf->rect;
+               unsigned char *rct= (unsigned char *)ibuf->rect;
                float *rctf= ibuf->rect_float;
                const float sat= seq->sat;
                float hsv[3];
@@ -1574,7 +1705,7 @@ static ImBuf * input_preprocess(
        mul = seq->mul;
 
        if(seq->blend_mode == SEQ_BLEND_REPLACE) {
-               mul *= seq->blend_opacity / 100.0;
+               mul *= seq->blend_opacity / 100.0f;
        }
 
        if(seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) {
@@ -1591,43 +1722,40 @@ static ImBuf * input_preprocess(
                }
        }
 
-       if(mul != 1.0) {
+       if(mul != 1.0f) {
                multibuf(ibuf, mul);
        }
 
        if(seq->flag & SEQ_MAKE_PREMUL) {
-               if(ibuf->depth == 32 && ibuf->zbuf == 0) {
+               if(ibuf->depth == 32 && ibuf->zbuf == NULL) {
                        IMB_premultiply_alpha(ibuf);
                }
        }
 
 
-       if(ibuf->x != seqrectx || ibuf->y != seqrecty ) {
-               if(scene->r.mode & R_OSA) {
-                       IMB_scaleImBuf(ibuf, 
-                                      (short)seqrectx, (short)seqrecty);
+       if(ibuf->x != context.rectx || ibuf->y != context.recty ) {
+               if(context.scene->r.mode & R_OSA) {
+                       IMB_scaleImBuf(ibuf, (short)context.rectx, (short)context.recty);
                } else {
-                       IMB_scalefastImBuf(ibuf, 
-                                          (short)seqrectx, (short)seqrecty);
+                       IMB_scalefastImBuf(ibuf, (short)context.rectx, (short)context.recty);
                }
        }
        return ibuf;
 }
 
-static ImBuf * copy_from_ibuf_still(Sequence * seq, float nr,
-                                   int seqrectx, int seqrecty)
+static ImBuf * copy_from_ibuf_still(SeqRenderData context, Sequence * seq, 
+                                   float nr)
 {
-       ImBuf * rval = 0;
-       ImBuf * ibuf = 0;
+       ImBuf * rval = NULL;
+       ImBuf * ibuf = NULL;
 
        if (nr == 0) {
                ibuf = seq_stripelem_cache_get(
-                       seq, seqrectx, seqrecty, seq->start, 
+                       context, seq, seq->start, 
                        SEQ_STRIPELEM_IBUF_STARTSTILL);
-       }
-       if (nr == seq->len - 1) {
+       } else if (nr == seq->len - 1) {
                ibuf = seq_stripelem_cache_get(
-                       seq, seqrectx, seqrecty, seq->start, 
+                       context, seq, seq->start, 
                        SEQ_STRIPELEM_IBUF_ENDSTILL);
        }
 
@@ -1639,18 +1767,28 @@ static ImBuf * copy_from_ibuf_still(Sequence * seq, float nr,
        return rval;
 }
 
-static void copy_to_ibuf_still(Sequence * seq, float nr,
+static void copy_to_ibuf_still(SeqRenderData context, Sequence * seq, float nr,
                               ImBuf * ibuf)
 {
-       if (nr == 0) {
-               seq_stripelem_cache_put(
-                       seq, 0, 0, seq->start, 
-                       SEQ_STRIPELEM_IBUF_STARTSTILL, ibuf);
-       }
-       if (nr == seq->len - 1) {
-               seq_stripelem_cache_put(
-                       seq, 0, 0, seq->start, 
-                       SEQ_STRIPELEM_IBUF_ENDSTILL, ibuf);
+       if (nr == 0 || nr == seq->len - 1) {
+               /* we have to store a copy, since the passed ibuf
+                  could be preprocessed afterwards (thereby silently
+                  changing the cached image... */
+               ibuf = IMB_dupImBuf(ibuf);
+
+               if (nr == 0) {
+                       seq_stripelem_cache_put(
+                               context, seq, seq->start, 
+                               SEQ_STRIPELEM_IBUF_STARTSTILL, ibuf);
+               } 
+
+               if (nr == seq->len - 1) {
+                       seq_stripelem_cache_put(
+                               context, seq, seq->start, 
+                               SEQ_STRIPELEM_IBUF_ENDSTILL, ibuf);
+               }
+
+               IMB_freeImBuf(ibuf);
        }
 }
 
@@ -1658,46 +1796,47 @@ static void copy_to_ibuf_still(Sequence * seq, float nr,
    strip rendering functions
    ********************************************************************** */
 
-static ImBuf* seq_render_strip_stack(
-       Main *bmain, Scene *scene,
-       ListBase *seqbasep, float cfra, int chanshown, int render_size,
-       int seqrectx, int seqrecty);
+static ImBuf* seq_render_strip_stack( 
+       SeqRenderData context, ListBase *seqbasep, float cfra, int chanshown);
 
-static ImBuf * seq_render_strip(Main *bmain, Scene *scene, Sequence * seq, float cfra,
-                               int render_size, 
-                               int seqrectx, int seqrecty);
+static ImBuf * seq_render_strip(
+       SeqRenderData context, Sequence * seq, float cfra);
 
 
 static ImBuf* seq_render_effect_strip_impl(
-       Main *bmain, Scene *scene, float cfra, Sequence *seq, int render_size,
-       int seqrectx, int seqrecty)
+       SeqRenderData context, Sequence *seq, float cfra)
 {
        float fac, facf;
        int early_out;
        int i;
-       int must_preprocess = FALSE;
-
        struct SeqEffectHandle sh = get_sequence_effect(seq);
        FCurve *fcu= NULL;
        ImBuf * ibuf[3];
-       ImBuf * out = 0;
+       Sequence *input[3];
+       ImBuf * out = NULL;
 
-       ibuf[0] = ibuf[1] = ibuf[2] = 0;
+       ibuf[0] = ibuf[1] = ibuf[2] = NULL;
+
+       input[0] = seq->seq1; input[1] = seq->seq2; input[2] = seq->seq3;
 
        if (!sh.execute) { /* effect not supported in this version... */
-               goto finish;
+               out = IMB_allocImBuf((short)context.rectx, 
+                                    (short)context.recty, 32, IB_rect);
+               return out;
        }
 
-       if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) {
+       if (seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) {
                sh.get_default_fac(seq, cfra, &fac, &facf);
-               if( scene->r.mode & R_FIELDS ); else facf= fac;
-       } else {
-               fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, 
-                                         "effect_fader", 0);
+               
+               if ((context.scene->r.mode & R_FIELDS)==0)
+                       facf= fac;
+       }
+       else {
+               fcu = id_data_find_fcurve(&context.scene->id, seq, &RNA_Sequence, "effect_fader", 0, NULL);
                if (fcu) {
                        fac = facf = evaluate_fcurve(fcu, cfra);
-                       if( scene->r.mode & R_FIELDS ) {
-                               facf = evaluate_fcurve(fcu, cfra + 0.5);
+                       if( context.scene->r.mode & R_FIELDS ) {
+                               facf = evaluate_fcurve(fcu, cfra + 0.5f);
                        }
                } else {
                        fac = facf = seq->effect_fader;
@@ -1706,88 +1845,57 @@ static ImBuf* seq_render_effect_strip_impl(
 
        early_out = sh.early_out(seq, fac, facf);
 
-       if (early_out == -1) { /* no input needed */
-               out = sh.execute(bmain, scene, seq, cfra, fac, facf, 
-                                seqrectx, seqrecty, render_size,
-                                0, 0, 0);
-               goto finish;
-       }
-
-
-       must_preprocess = input_have_to_preprocess(
-               scene, seq, cfra, seqrectx, seqrecty);
-
        switch (early_out) {
-       case 0:
+       case EARLY_NO_INPUT:
+               out = sh.execute(context, seq, cfra, fac, facf, 
+                                NULL, NULL, NULL);
                break;
-       case 1:
-               if (seq->seq1) {
-                       ibuf[0] = seq_render_strip(bmain, scene, seq->seq1, cfra,
-                                                  render_size, 
-                                                  seqrectx, seqrecty);
+       case EARLY_DO_EFFECT:
+               for(i=0; i<3; i++) {
+                       if(input[i])
+                               ibuf[i] = seq_render_strip(
+                                       context, input[i], cfra);
+               }
+
+               if (ibuf[0] && ibuf[1]) {
+                       out = sh.execute(context, seq, cfra, fac, facf,  
+                                        ibuf[0], ibuf[1], ibuf[2]);
+               }
+               break;
+       case EARLY_USE_INPUT_1:
+               if (input[0]) {
+                       ibuf[0] = seq_render_strip(context, input[0], cfra);
                }
                if (ibuf[0]) {
-                       if (must_preprocess) {
+                       if (input_have_to_preprocess(context, seq, cfra)) {
                                out = IMB_dupImBuf(ibuf[0]);
                        } else {
                                out = ibuf[0];
                                IMB_refImBuf(out);
                        }
                }
-               goto finish;
-       case 2:
-               if (seq->seq2) {
-                       ibuf[1] = seq_render_strip(bmain, scene, seq->seq2, cfra,
-                                                  render_size, 
-                                                  seqrectx, seqrecty);
+               break;
+       case EARLY_USE_INPUT_2:
+               if (input[1]) {
+                       ibuf[1] = seq_render_strip(context, input[1], cfra);
                }
                if (ibuf[1]) {
-                       if (must_preprocess) {
+                       if (input_have_to_preprocess(context, seq, cfra)) {
                                out = IMB_dupImBuf(ibuf[1]);
                        } else {
                                out = ibuf[1];
                                IMB_refImBuf(out);
                        }
                }
-               goto finish;
-       default:
-               goto finish;
-       }
-
-       if (seq->seq1) {
-               ibuf[0] = seq_render_strip(bmain, scene, seq->seq1, cfra,
-                                          render_size, 
-                                          seqrectx, seqrecty);
-       } 
-
-       if (seq->seq2) {
-               ibuf[1] = seq_render_strip(bmain, scene, seq->seq2, cfra,
-                                          render_size, 
-                                          seqrectx, seqrecty);
-       }
-
-       if (seq->seq3) {
-               ibuf[2] = seq_render_strip(bmain, scene, seq->seq3, cfra,
-                                          render_size, 
-                                          seqrectx, seqrecty);
-       }
-
-       if (!ibuf[0] || !ibuf[1]) {
-               goto finish;
+               break;
        }
 
-       out = sh.execute(bmain, scene, seq, cfra, fac, facf, seqrectx, seqrecty, 
-                        render_size,
-                        ibuf[0], ibuf[1], ibuf[2]);
-
-finish:
        for (i = 0; i < 3; i++) {
                IMB_freeImBuf(ibuf[i]);
        }
 
-       if (!out) {
-               out = IMB_allocImBuf(
-                       (short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
+       if (out == NULL) {
+               out = IMB_allocImBuf((short)context.rectx, (short)context.recty, 32, IB_rect);
        }
 
        return out;
@@ -1795,15 +1903,16 @@ finish:
 
 
 static ImBuf * seq_render_scene_strip_impl(
-       Main *bmain, Scene * scene, Sequence * seq, float nr, int seqrectx, int seqrecty)
+       SeqRenderData context, Sequence * seq, float nr)
 {
-       ImBuf * ibuf = 0;
+       ImBuf * ibuf = NULL;
        float frame= seq->sfra + nr + seq->anim_startofs;
        float oldcfra;
-       Object *oldcamera;
+       Object *camera;
        ListBase oldmarkers;
        
-       /* Hack! This function can be called from do_render_seq(), in that case
+       /* Old info:
+          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).
@@ -1815,61 +1924,96 @@ static ImBuf * seq_render_scene_strip_impl(
           and since G.rendering is uhm, gone... (Peter)
        */
 
+       /* New info:
+          Using the same name for the renders works just fine as the do_render_seq()
+          render is not used while the scene strips are rendered.
+          
+          However rendering from UI (through sequencer_preview_area_draw) can crash in
+          very many cases since other renders (material preview, an actual render etc.)
+          can be started while this sequence preview render is running. The only proper
+          solution is to make the sequencer preview render a proper job, which can be
+          stopped when needed. This would also give a nice progress bar for the preview
+          space so that users know there's something happening.
+
+          As a result the active scene now only uses OpenGL rendering for the sequencer
+          preview. This is far from nice, but is the only way to prevent crashes at this
+          time. 
+
+          -jahka
+       */
+
        int rendering = G.rendering;
        int doseq;
-       int doseq_gl= G.rendering ? /*(scene->r.seq_flag & R_SEQ_GL_REND)*/ 0 : (scene->r.seq_flag & R_SEQ_GL_PREV);
+       int doseq_gl= G.rendering ? /*(scene->r.seq_flag & R_SEQ_GL_REND)*/ 0 : /*(scene->r.seq_flag & R_SEQ_GL_PREV)*/ 1;
        int have_seq= FALSE;
-       Scene *sce= seq->scene; /* dont refer to seq->scene above this point!, it can be NULL */
-       int sce_valid= FALSE;
+       Scene *scene;
 
-       if(sce) {
-               have_seq= (sce->r.scemode & R_DOSEQ) && sce->ed && sce->ed->seqbase.first;
-               sce_valid= (sce->camera || have_seq);
+       /* dont refer to seq->scene above this point!, it can be NULL */
+       if(seq->scene == NULL) {
+               return NULL;
        }
 
-       if (!sce_valid)
-               return NULL;
+       scene= seq->scene;
 
-       oldcfra= seq->scene->r.cfra;
-       oldcamera= seq->scene->camera;
+       have_seq= (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first;
+
+       oldcfra= scene->r.cfra; 
+       scene->r.cfra= frame;
 
-       /* prevent eternal loop */
-       doseq= scene->r.scemode & R_DOSEQ;
-       scene->r.scemode &= ~R_DOSEQ;
-       
-       seq->scene->r.cfra= frame;
        if(seq->scene_camera)   
-               seq->scene->camera= seq->scene_camera;
-       else    
-               scene_camera_switch_update(seq->scene);
+               camera= seq->scene_camera;
+       else {  
+               scene_camera_switch_update(scene);
+               camera= scene->camera;
+       }
+
+       if(have_seq==FALSE && camera==NULL) {
+               scene->r.cfra= oldcfra;
+               return NULL;
+       }
+
+       /* prevent eternal loop */
+       doseq= context.scene->r.scemode & R_DOSEQ;
+       context.scene->r.scemode &= ~R_DOSEQ;
        
 #ifdef DURIAN_CAMERA_SWITCH
        /* stooping to new low's in hackyness :( */
-       oldmarkers= seq->scene->markers;
-       seq->scene->markers.first= seq->scene->markers.last= NULL;
+       oldmarkers= scene->markers;
+       scene->markers.first= scene->markers.last= NULL;
 #endif
        
-       if(sequencer_view3d_cb && BLI_thread_is_main() && doseq_gl && (seq->scene == scene || have_seq==0) && seq->scene->camera) {
+       if(sequencer_view3d_cb && BLI_thread_is_main() && doseq_gl && (scene == context.scene || have_seq==0) && camera) {
+               char err_out[256]= "unknown";
+               /* for old scened this can be uninitialized, should probably be added to do_versions at some point if the functionality stays */
+               if(context.scene->r.seq_prev_type==0)
+                       context.scene->r.seq_prev_type = 3 /* ==OB_SOLID */; 
+
                /* opengl offscreen render */
-               scene_update_for_newframe(bmain, seq->scene, seq->scene->lay);
-               ibuf= sequencer_view3d_cb(seq->scene, seqrectx, seqrecty, IB_rect,
-                                         scene->r.seq_prev_type);
+               scene_update_for_newframe(context.bmain, scene, scene->lay);
+               ibuf= sequencer_view3d_cb(scene, camera, context.rectx, context.recty, IB_rect, context.scene->r.seq_prev_type, err_out);
+               if(ibuf == NULL) {
+                       fprintf(stderr, "seq_render_scene_strip_impl failed to get opengl buffer: %s\n", err_out);
+               }
        }
        else {
-               Render *re;
+               Render *re = RE_GetRender(scene->id.name);
                RenderResult rres;
-               
-               if(rendering)
-                       re= RE_NewRender(" do_build_seq_ibuf");
-               else
-                       re= RE_NewRender(sce->id.name);
-               
-               RE_BlenderFrame(re, bmain, sce, NULL, sce->lay, frame);
+
+               /* XXX: this if can be removed when sequence preview rendering uses the job system */
+               if(rendering || context.scene != scene) {
+                       if(re==NULL)
+                               re= RE_NewRender(scene->id.name);
+                       
+                       RE_BlenderFrame(re, context.bmain, scene, NULL, camera, scene->lay, frame, FALSE);
+
+                       /* restore previous state after it was toggled on & off by RE_BlenderFrame */
+                       G.rendering = rendering;
+               }
                
                RE_AcquireResultImage(re, &rres);
                
                if(rres.rectf) {
-                       ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0);
+                       ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat);
                        memcpy(ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty);
                        if(rres.rectz) {
                                addzbuffloatImBuf(ibuf);
@@ -1881,7 +2025,7 @@ static ImBuf * seq_render_scene_strip_impl(
                        IMB_convert_profile(ibuf, IB_PROFILE_SRGB);                     
                }
                else if (rres.rect32) {
-                       ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect, 0);
+                       ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect);
                        memcpy(ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty);
                }
                
@@ -1891,199 +2035,171 @@ static ImBuf * seq_render_scene_strip_impl(
        }
        
        /* restore */
-       scene->r.scemode |= doseq;
+       context.scene->r.scemode |= doseq;
        
-       seq->scene->r.cfra = oldcfra;
-       seq->scene->camera= oldcamera;
+       scene->r.cfra = oldcfra;
+
+       if(frame != oldcfra)
+               scene_update_for_newframe(context.bmain, scene, scene->lay);
        
 #ifdef DURIAN_CAMERA_SWITCH
        /* stooping to new low's in hackyness :( */
-       seq->scene->markers= oldmarkers;
+       scene->markers= oldmarkers;
 #endif
 
        return ibuf;
 }
 
-static ImBuf * seq_render_strip(Main *bmain, Scene *scene, Sequence * seq, float cfra,
-                               int render_size, 
-                               int seqrectx, int seqrecty)
+static ImBuf * seq_render_strip(SeqRenderData context, Sequence * seq, float cfra)
 {
+       ImBuf * ibuf = NULL;
        char name[FILE_MAXDIR+FILE_MAXFILE];
-       int use_preprocess = input_have_to_preprocess(
-               scene, seq, cfra, seqrectx, seqrecty);
-       ImBuf * ibuf = seq_stripelem_cache_get(
-               seq, seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF);
+       int use_preprocess = input_have_to_preprocess(context, seq, cfra);
        float nr = give_stripelem_index(seq, cfra);
+       /* all effects are handled similarly with the exception of speed effect */
+       int type = (seq->type & SEQ_EFFECT && seq->type != SEQ_SPEED) ? SEQ_EFFECT : seq->type;
 
-       /* currently, we cache preprocessed images */
-       if (ibuf) {
+       ibuf = seq_stripelem_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
+
+       /* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF,
+          but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL */
+       if (ibuf)
                use_preprocess = FALSE;
-       }
 
-       if(seq->type == SEQ_META) {
-               ImBuf * meta_ibuf = 0;
+       if (ibuf == NULL)
+               ibuf = copy_from_ibuf_still(context, seq, nr);
+       
+       if (ibuf == NULL)
+               ibuf = seq_proxy_fetch(context, seq, cfra);
 
-               if (ibuf == 0) {
-                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
-               }
+       if(ibuf == NULL) switch(type) {
+               case SEQ_META:
+               {
+                       ImBuf * meta_ibuf = NULL;
 
-               if(!ibuf && seq->seqbase.first) {
-                       meta_ibuf = seq_render_strip_stack(
-                               bmain, scene,
-                               &seq->seqbase, seq->start + nr, 0,
-                               render_size, seqrectx, seqrecty);
-               }
+                       if(seq->seqbase.first)
+                               meta_ibuf = seq_render_strip_stack(
+                                       context, &seq->seqbase,
+                                       seq->start + nr, 0);
 
-               if(!ibuf && meta_ibuf) {
-                       ibuf = meta_ibuf;
-                       if(ibuf && use_preprocess) {
-                               struct ImBuf * i = IMB_dupImBuf(ibuf);
+                       if(meta_ibuf) {
+                               ibuf = meta_ibuf;
+                               if(ibuf && use_preprocess) {
+                                       struct ImBuf * i = IMB_dupImBuf(ibuf);
 
-                               IMB_freeImBuf(ibuf);
+                                       IMB_freeImBuf(ibuf);
 
-                               ibuf = i;
+                                       ibuf = i;
+                               }
                        }
+                       break;
                }
-       } else if(seq->type == SEQ_SPEED) {
-               ImBuf * child_ibuf = 0;
-
-               if (ibuf == 0) {
-                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
-               }
+               case SEQ_SPEED:
+               {
+                       ImBuf * child_ibuf = NULL;
 
-               if (ibuf == 0) {
                        float f_cfra;
-                       SpeedControlVars * s 
-                               = (SpeedControlVars *)seq->effectdata;
+                       SpeedControlVars * s = (SpeedControlVars *)seq->effectdata;
 
-                       sequence_effect_speed_rebuild_map(scene, seq, 0);
+                       sequence_effect_speed_rebuild_map(context.scene,seq, 0);
 
                        /* weeek! */
                        f_cfra = seq->start + s->frameMap[(int) nr];
 
-                       child_ibuf = seq_render_strip(bmain, scene, seq->seq1, f_cfra,
-                                                     render_size, 
-                                                     seqrectx, seqrecty);
-               }
+                       child_ibuf = seq_render_strip(context,seq->seq1,f_cfra);
 
-               if (!ibuf && child_ibuf) {
-                       ibuf = child_ibuf;
-                       if(ibuf && use_preprocess) {
-                               struct ImBuf * i = IMB_dupImBuf(ibuf);
+                       if (child_ibuf) {
+                               ibuf = child_ibuf;
+                               if(ibuf && use_preprocess) {
+                                       struct ImBuf * i = IMB_dupImBuf(ibuf);
 
-                               IMB_freeImBuf(ibuf);
+                                       IMB_freeImBuf(ibuf);
 
-                               ibuf = i;
+                                       ibuf = i;
+                               }
                        }
+                       break;
                }
-       } else if(seq->type & SEQ_EFFECT) {
-               /* should the effect be recalculated? */
-               
-               if (ibuf == 0) {
-                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
-               }
-
-               if(ibuf == 0) {         
+               case SEQ_EFFECT:
+               {
                        ibuf = seq_render_effect_strip_impl(
-                               bmain, scene, cfra, seq, render_size, 
-                               seqrectx, seqrecty);
+                               context, seq, seq->start + nr);
+                       break;
                }
-       } else if(seq->type == SEQ_IMAGE) {
-               StripElem * s_elem = give_stripelem(seq, cfra);
+               case SEQ_IMAGE:
+               {
+                       StripElem * s_elem = give_stripelem(seq, cfra);
 
-               if(ibuf == 0 && s_elem) {
-                       BLI_join_dirfile(name, seq->strip->dir, s_elem->name);
-                       BLI_path_abs(name, G.sce);
-
-                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
-               }
+                       if (s_elem) {
+                               BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name);
+                               BLI_path_abs(name, G.main->name);
+                       }
 
-               if (ibuf == 0) {
-                       ibuf = copy_from_ibuf_still(seq,nr,seqrectx,seqrecty);
-               }
+                       if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect))) {
+                               /* we don't need both (speed reasons)! */
+                               if (ibuf->rect_float && ibuf->rect)
+                                       imb_freerectImBuf(ibuf);
 
-               if (ibuf == 0 && s_elem && 
-                   (ibuf = IMB_loadiffname(name, IB_rect))) {
-                       /* we don't need both (speed reasons)! */
-                       if (ibuf->rect_float && ibuf->rect)
-                               imb_freerectImBuf(ibuf);
+                               /* all sequencer color is done in SRGB space, linear gives odd crossfades */
+                               if(ibuf->profile == IB_PROFILE_LINEAR_RGB)
+                                       IMB_convert_profile(ibuf, IB_PROFILE_NONE);
 
-                       /* all sequencer color is done in SRGB space, linear gives odd crossfades */
-                       if(ibuf->profile == IB_PROFILE_LINEAR_RGB)
-                               IMB_convert_profile(ibuf, IB_PROFILE_NONE);
+                               copy_to_ibuf_still(context, seq, nr, ibuf);
 
-                       copy_to_ibuf_still(seq, nr, ibuf);
-               }
-       } else if(seq->type == SEQ_MOVIE) {
-               if(ibuf == 0) {
-                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
-                       
-               }
-               
-               if (ibuf == 0) {
-                       ibuf = copy_from_ibuf_still(seq, nr,seqrectx,seqrecty);
-               }
-
-               if (ibuf == 0) {
-                       if(seq->anim==0) {
-                               BLI_join_dirfile(name, 
-                                                seq->strip->dir, 
-                                                seq->strip->stripdata->name);
-                               BLI_path_abs(name, G.sce);
-                                       
-                               seq->anim = openanim(
-                                       name, IB_rect | 
-                                       ((seq->flag & SEQ_FILTERY) 
-                                        ? IB_animdeinterlace : 0));
+                               s_elem->orig_width  = ibuf->x;
+                               s_elem->orig_height = ibuf->y;
                        }
+                       break;
+               }
+               case SEQ_MOVIE:
+               {
+                       seq_open_anim_file(seq);
+
                        if(seq->anim) {
-                               IMB_anim_set_preseek(seq->anim, 
+                               IMB_anim_set_preseek(seq->anim,
                                                     seq->anim_preseek);
-                               ibuf = IMB_anim_absolute(seq->anim, 
-                                                        nr 
-                                                        + seq->anim_startofs);
+
+                               ibuf = IMB_anim_absolute(
+                                       seq->anim, nr + seq->anim_startofs, 
+                                       seq->strip->proxy ? 
+                                       seq->strip->proxy->tc
+                                       : IMB_TC_RECORD_RUN, 
+                                       seq_rendersize_to_proxysize(
+                                               context.preview_render_size));
+
                                /* we don't need both (speed reasons)! */
-                               if (ibuf && ibuf->rect_float 
-                                   && ibuf->rect) {
+                               if (ibuf && ibuf->rect_float && ibuf->rect)
                                        imb_freerectImBuf(ibuf);
+                               if (ibuf) {
+                                       seq->strip->stripdata->orig_width = ibuf->x;
+                                       seq->strip->stripdata->orig_height = ibuf->y;
                                }
-
                        }
-                       copy_to_ibuf_still(seq, nr, ibuf);
-               }
-                       
-       } else if(seq->type == SEQ_SCENE) {     // scene can be NULL after deletions
-               if (ibuf == 0) {
-                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
-               }
-               if (ibuf == 0) {
-                       ibuf = copy_from_ibuf_still(seq, nr,seqrectx,seqrecty);
+                       copy_to_ibuf_still(context, seq, nr, ibuf);
+                       break;
                }
-               
-               if (ibuf == 0) {
-                       ibuf = seq_render_scene_strip_impl(bmain, scene, seq, nr,
-                                                          seqrectx, seqrecty);
+               case SEQ_SCENE:
+               {       // scene can be NULL after deletions
+                       ibuf = seq_render_scene_strip_impl(context, seq, nr);
 
-                       copy_to_ibuf_still(seq, nr, ibuf);
+                       /* Scene strips update all animation, so we need to restore original state.*/
+                       BKE_animsys_evaluate_all_animation(context.bmain, context.scene, cfra);
+
+                       copy_to_ibuf_still(context, seq, nr, ibuf);
+                       break;
                }
        }
 
-       if (!ibuf) {
-               ibuf = IMB_allocImBuf(
-                       (short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
-       }
+       if (ibuf == NULL)
+               ibuf = IMB_allocImBuf((short)context.rectx, (short)context.recty, 32, IB_rect);
 
-       if (ibuf->x != seqrectx || ibuf->y != seqrecty) {
+       if (ibuf->x != context.rectx || ibuf->y != context.recty)
                use_preprocess = TRUE;
-       }
 
-       if (use_preprocess) {
-               ibuf = input_preprocess(scene, seq, cfra, seqrectx,
-                                       seqrecty, ibuf);
-       }
+       if (use_preprocess)
+               ibuf = input_preprocess(context, seq, cfra, ibuf);
 
-       seq_stripelem_cache_put(
-               seq, seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF, ibuf);
+       seq_stripelem_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf);
 
        return ibuf;
 }
@@ -2099,9 +2215,7 @@ static int seq_must_swap_input_in_blend_mode(Sequence * seq)
        /* 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) {
+       if (ELEM3(seq->blend_mode, SEQ_ALPHAOVER, SEQ_ALPHAUNDER, SEQ_OVERDROP)) {
                swap_input = TRUE;
        }
        
@@ -2111,63 +2225,56 @@ static int seq_must_swap_input_in_blend_mode(Sequence * seq)
 static int seq_get_early_out_for_blend_mode(Sequence * seq)
 {
        struct SeqEffectHandle sh = get_sequence_blend(seq);
-       float facf = seq->blend_opacity / 100.0;
+       float facf = seq->blend_opacity / 100.0f;
        int early_out = sh.early_out(seq, facf, facf);
        
-       if (early_out < 1) {
+       if (ELEM(early_out, EARLY_DO_EFFECT, EARLY_NO_INPUT)) {
                return early_out;
        }
 
        if (seq_must_swap_input_in_blend_mode(seq)) {
-               if (early_out == 2) {
-                       return 1;
-               } else if (early_out == 1) {
-                       return 2;
+               if (early_out == EARLY_USE_INPUT_2) {
+                       return EARLY_USE_INPUT_1;
+               } else if (early_out == EARLY_USE_INPUT_1) {
+                       return EARLY_USE_INPUT_2;
                }
        }
        return early_out;
 }
 
 static ImBuf* seq_render_strip_stack(
-       Main *bmain, Scene *scene, ListBase *seqbasep, float cfra, int chanshown, 
-       int render_size, int seqrectx, int seqrecty)
+       SeqRenderData context, ListBase *seqbasep, float cfra, int chanshown)
 {
        Sequence* seq_arr[MAXSEQ+1];
        int count;
        int i;
-       ImBuf* out = 0;
+       ImBuf* out = NULL;
 
-       count = get_shown_sequences(seqbasep, cfra, chanshown, 
-                                   (Sequence **)&seq_arr);
+       count = get_shown_sequences(seqbasep, cfra, chanshown, (Sequence **)&seq_arr);
 
-       if (!count) {
-               return 0;
+       if (count == 0) {
+               return NULL;
        }
 
 #if 0 /* commentind since this breaks keyframing, since it resets the value on draw */
        if(scene->r.cfra != cfra) {
                // XXX for prefetch and overlay offset!..., very bad!!!
                AnimData *adt= BKE_animdata_from_id(&scene->id);
-               BKE_animsys_evaluate_animdata(&scene->id, adt, cfra, ADT_RECALC_ANIM);
+               BKE_animsys_evaluate_animdata(scene, &scene->id, adt, cfra, ADT_RECALC_ANIM);
        }
 #endif
 
-       out = seq_stripelem_cache_get(
-               seq_arr[count - 1], 
-               seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF_COMP);
+       out = seq_stripelem_cache_get(context, seq_arr[count - 1], 
+                                     cfra, SEQ_STRIPELEM_IBUF_COMP);
 
        if (out) {
                return out;
        }
        
        if(count == 1) {
-               out = seq_render_strip(bmain, scene, seq_arr[0],
-                                       cfra, render_size,
-                                       seqrectx, seqrecty);
-               seq_stripelem_cache_put(
-                       seq_arr[0], 
-                       seqrectx, seqrecty, cfra, 
-                       SEQ_STRIPELEM_IBUF_COMP, out);
+               out = seq_render_strip(context, seq_arr[0], cfra);
+               seq_stripelem_cache_put(context, seq_arr[0], cfra, 
+                                       SEQ_STRIPELEM_IBUF_COMP, out);
 
                return out;
        }
@@ -2175,43 +2282,34 @@ static ImBuf* seq_render_strip_stack(
 
        for (i = count - 1; i >= 0; i--) {
                int early_out;
-               Sequence * seq = seq_arr[i];
+               Sequence *seq = seq_arr[i];
 
                out = seq_stripelem_cache_get(
-                       seq, 
-                       seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF_COMP);
+                       context, seq, cfra, SEQ_STRIPELEM_IBUF_COMP);
 
                if (out) {
                        break;
                }
                if (seq->blend_mode == SEQ_BLEND_REPLACE) {
-                       out = seq_render_strip(bmain, scene, seq, cfra,
-                                              render_size,
-                                              seqrectx, seqrecty);
+                       out = seq_render_strip(context, seq, cfra);
                        break;
                }
 
                early_out = seq_get_early_out_for_blend_mode(seq);
 
                switch (early_out) {
-               case -1:
-               case 2:
-                       out = seq_render_strip(bmain, scene, seq, cfra,
-                                              render_size,
-                                              seqrectx, seqrecty);
+               case EARLY_NO_INPUT:
+               case EARLY_USE_INPUT_2:
+                       out = seq_render_strip(context, seq, cfra);
                        break;
-               case 1:
+               case EARLY_USE_INPUT_1:
                        if (i == 0) {
-                               out = IMB_allocImBuf(
-                                       (short)seqrectx, (short)seqrecty, 
-                                       32, IB_rect, 0);
+                               out = IMB_allocImBuf((short)context.rectx, (short)context.recty, 32, IB_rect);
                        }
                        break;
-               case 0:
+               case EARLY_DO_EFFECT:
                        if (i == 0) {
-                               out = seq_render_strip(bmain, scene, seq, cfra,
-                                                      render_size,
-                                                      seqrectx, seqrecty);
+                               out = seq_render_strip(context, seq, cfra);
                        }
 
                        break;
@@ -2221,9 +2319,8 @@ static ImBuf* seq_render_strip_stack(
                }
        }
 
-       seq_stripelem_cache_put(
-               seq_arr[i], seqrectx, seqrecty, cfra, 
-               SEQ_STRIPELEM_IBUF_COMP, out);
+       seq_stripelem_cache_put(context, seq_arr[i], cfra, 
+                               SEQ_STRIPELEM_IBUF_COMP, out);
 
 
        i++;
@@ -2231,37 +2328,30 @@ static ImBuf* seq_render_strip_stack(
        for (; i < count; i++) {
                Sequence * seq = seq_arr[i];
 
-               if (seq_get_early_out_for_blend_mode(seq) == 0) {
+               if (seq_get_early_out_for_blend_mode(seq) == EARLY_DO_EFFECT) {
                        struct SeqEffectHandle sh = get_sequence_blend(seq);
                        ImBuf * ibuf1 = out;
-                       ImBuf * ibuf2 = seq_render_strip(bmain, scene, seq, cfra,
-                                                        render_size,
-                                                        seqrectx, seqrecty);
-
-                       float facf = seq->blend_opacity / 100.0;
-                       int swap_input 
-                               = seq_must_swap_input_in_blend_mode(seq);
+                       ImBuf * ibuf2 = seq_render_strip(context, seq, cfra);
 
-                       int x= seqrectx;
-                       int y= seqrecty;
+                       float facf = seq->blend_opacity / 100.0f;
+                       int swap_input = seq_must_swap_input_in_blend_mode(seq);
 
                        if (swap_input) {
-                               out = sh.execute(bmain, scene, seq, cfra, 
-                                                facf, facf, x, y, render_size,
-                                                ibuf2, ibuf1, 0);
+                               out = sh.execute(context, seq, cfra, 
+                                                facf, facf, 
+                                                ibuf2, ibuf1, NULL);
                        } else {
-                               out = sh.execute(bmain, scene, seq, cfra, 
-                                                facf, facf, x, y, render_size,
-                                                ibuf1, ibuf2, 0);
+                               out = sh.execute(context, seq, cfra, 
+                                                facf, facf, 
+                                                ibuf1, ibuf2, NULL);
                        }
                
                        IMB_freeImBuf(ibuf1);
                        IMB_freeImBuf(ibuf2);
                }
 
-               seq_stripelem_cache_put(
-                       seq_arr[i], seqrectx, seqrecty, cfra, 
-                       SEQ_STRIPELEM_IBUF_COMP, out);
+               seq_stripelem_cache_put(context, seq_arr[i], cfra,
+                                       SEQ_STRIPELEM_IBUF_COMP, out);
        }
 
        return out;
@@ -2272,9 +2362,9 @@ static ImBuf* seq_render_strip_stack(
  * you have to free after usage!
  */
 
-ImBuf *give_ibuf_seq(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size)
+ImBuf *give_ibuf_seq(SeqRenderData context, float cfra, int chanshown)
 {
-       Editing *ed= seq_give_editing(scene, FALSE);
+       Editing *ed= seq_give_editing(context.scene, FALSE);
        int count;
        ListBase *seqbasep;
        
@@ -2288,19 +2378,18 @@ ImBuf *give_ibuf_seq(Main *bmain, Scene *scene, int rectx, int recty, int cfra,
                seqbasep= ed->seqbasep;
        }
 
-       return seq_render_strip_stack(
-               bmain, scene, seqbasep, cfra, chanshown, render_size, rectx, recty);
+       return seq_render_strip_stack(context, seqbasep, cfra, chanshown);
 }
 
-ImBuf *give_ibuf_seqbase(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size, ListBase *seqbasep)
+ImBuf *give_ibuf_seqbase(SeqRenderData context, float cfra, int chanshown, ListBase *seqbasep)
 {
-       return seq_render_strip_stack(bmain, scene, seqbasep, cfra, chanshown, render_size, rectx, recty);
+       return seq_render_strip_stack(context, seqbasep, cfra, chanshown);
 }
 
 
-ImBuf *give_ibuf_seq_direct(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int render_size, Sequence *seq)
+ImBuf *give_ibuf_seq_direct(SeqRenderData context, float cfra, Sequence *seq)
 {
-       return seq_render_strip(bmain, scene, seq, cfra, render_size, rectx, recty);
+       return seq_render_strip(context, seq, cfra);
 }
 
 #if 0
@@ -2350,9 +2439,9 @@ typedef struct PrefetchQueueElem {
        
        int rectx;
        int recty;
-       int cfra;
+       float cfra;
        int chanshown;
-       int render_size;
+       int preview_render_size;
 
        int monoton_cfra;
 
@@ -2400,7 +2489,7 @@ static void *seq_prefetch_thread(void * This_)
                if (e->cfra >= s_last) { 
                        e->ibuf = give_ibuf_seq_impl(This->scene, 
                                e->rectx, e->recty, e->cfra, e->chanshown,
-                               e->render_size);
+                               e->preview_render_size);
                }
 
                pthread_mutex_lock(&queue_lock);
@@ -2510,8 +2599,7 @@ static void seq_stop_threads()
 }
 #endif
 
-void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown,
-                               int render_size)
+void give_ibuf_prefetch_request(SeqRenderData context, float cfra, int chanshown)
 {
        PrefetchQueueElem *e;
        if (seq_thread_shutdown) {
@@ -2519,11 +2607,11 @@ void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown,
        }
 
        e = MEM_callocN(sizeof(PrefetchQueueElem), "prefetch_queue_elem");
-       e->rectx = rectx;
-       e->recty = recty;
+       e->rectx = context.rectx;
+       e->recty = context.recty;
        e->cfra = cfra;
        e->chanshown = chanshown;
-       e->render_size = render_size;
+       e->preview_render_size = context.preview_render_size;
        e->monoton_cfra = monoton_cfra++;
 
        pthread_mutex_lock(&queue_lock);
@@ -2566,13 +2654,13 @@ static void seq_wait_for_prefetch_ready()
 }
 #endif
 
-ImBuf *give_ibuf_seq_threaded(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size)
+ImBuf *give_ibuf_seq_threaded(SeqRenderData context, float cfra, int chanshown)
 {
        PrefetchQueueElem *e = NULL;
        int found_something = FALSE;
 
        if (seq_thread_shutdown) {
-               return give_ibuf_seq(bmain, scene, rectx, recty, cfra, chanshown, render_size);
+               return give_ibuf_seq(context, cfra, chanshown);
        }
 
        while (!e) {
@@ -2582,9 +2670,9 @@ ImBuf *give_ibuf_seq_threaded(Main *bmain, Scene *scene, int rectx, int recty, i
                for (e = prefetch_done.first; e; e = e->next) {
                        if (cfra == e->cfra &&
                                chanshown == e->chanshown &&
-                               rectx == e->rectx && 
-                               recty == e->recty &&
-                               render_size == e->render_size) {
+                               context.rectx == e->rectx && 
+                               context.recty == e->recty &&
+                               context.preview_render_size == e->preview_render_size) {
                                success = TRUE;
                                found_something = TRUE;
                                break;
@@ -2595,9 +2683,9 @@ ImBuf *give_ibuf_seq_threaded(Main *bmain, Scene *scene, int rectx, int recty, i
                        for (e = prefetch_wait.first; e; e = e->next) {
                                if (cfra == e->cfra &&
                                        chanshown == e->chanshown &&
-                                       rectx == e->rectx && 
-                                       recty == e->recty &&
-                                       render_size == e->render_size) {
+                                       context.rectx == e->rectx && 
+                                       context.recty == e->recty &&
+                                       context.preview_render_size == e->preview_render_size) {
                                        found_something = TRUE;
                                        break;
                                }
@@ -2612,9 +2700,9 @@ ImBuf *give_ibuf_seq_threaded(Main *bmain, Scene *scene, int rectx, int recty, i
                                if (tslot->current &&
                                        cfra == tslot->current->cfra &&
                                        chanshown == tslot->current->chanshown &&
-                                       rectx == tslot->current->rectx && 
-                                       recty == tslot->current->recty &&
-                                       render_size== tslot->current->render_size){
+                                       context.rectx == tslot->current->rectx && 
+                                       context.recty == tslot->current->recty &&
+                                       context.preview_render_size== tslot->current->preview_render_size){
                                        found_something = TRUE;
                                        break;
                                }
@@ -2644,7 +2732,7 @@ ImBuf *give_ibuf_seq_threaded(Main *bmain, Scene *scene, int rectx, int recty, i
                }
        }
        
-       return e ? e->ibuf : 0;
+       return e ? e->ibuf : NULL;
 }
 
 /* Functions to free imbuf and anim data on changes */
@@ -2653,7 +2741,7 @@ static void free_anim_seq(Sequence *seq)
 {
        if(seq->anim) {
                IMB_free_anim(seq->anim);
-               seq->anim = 0;
+               seq->anim = NULL;
        }
 }
 
@@ -2697,8 +2785,7 @@ void free_imbuf_seq(Scene *scene, ListBase * seqbase, int check_mem_usage,
                        }
                }
                if(seq->type==SEQ_META) {
-                       free_imbuf_seq(scene, &seq->seqbase, FALSE,
-                                      keep_file_handles);
+                       free_imbuf_seq(scene, &seq->seqbase, FALSE, keep_file_handles);
                }
                if(seq->type==SEQ_SCENE) {
                        /* FIXME: recurs downwards, 
@@ -2768,7 +2855,8 @@ void update_changed_seq_and_deps(Scene *scene, Sequence *changed_seq, int len_ch
  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) {
+int seq_tx_get_start(Sequence *seq)
+{
        return seq->start;
 }
 int seq_tx_get_end(Sequence *seq)
@@ -2822,11 +2910,10 @@ void seq_tx_set_final_right(Sequence *seq, int val)
    since they work a bit differently to normal image seq's (during transform) */
 int seq_single_check(Sequence *seq)
 {
-       if ( seq->len==1 && (seq->type == SEQ_IMAGE || seq->type == SEQ_COLOR
-                            || seq->type == SEQ_MULTICAM))
-               return 1;
-       else
-               return 0;
+       return (seq->len==1 && (
+                       seq->type == SEQ_IMAGE 
+                       || ((seq->type & SEQ_EFFECT) && 
+                           get_sequence_effect_num_inputs(seq->type) == 0)));
 }
 
 /* check if the selected seq's reference unselected seq's */
@@ -2848,17 +2935,20 @@ int seqbase_isolated_sel_check(ListBase *seqbase)
 
        /* test relationships */
        for(seq= seqbase->first; seq; seq= seq->next) {
+               if((seq->type & SEQ_EFFECT)==0)
+                       continue;
+
                if(seq->flag & SELECT) {
-                       if(seq->type & SEQ_EFFECT) {
-                               if(seq->seq1 && (seq->seq1->flag & SELECT)==0) return FALSE;
-                               if(seq->seq2 && (seq->seq2->flag & SELECT)==0) return FALSE;
-                               if(seq->seq3 && (seq->seq3->flag & SELECT)==0) return FALSE;
-                       }
+                       if( (seq->seq1 && (seq->seq1->flag & SELECT)==0) ||
+                               (seq->seq2 && (seq->seq2->flag & SELECT)==0) ||
+                               (seq->seq3 && (seq->seq3->flag & SELECT)==0) )
+                               return FALSE;
                }
-               else if(seq->type & SEQ_EFFECT) {
-                       if(seq->seq1 && (seq->seq1->flag & SELECT)) return FALSE;
-                       if(seq->seq2 && (seq->seq2->flag & SELECT)) return FALSE;
-                       if(seq->seq3 && (seq->seq3->flag & SELECT)) return FALSE;
+               else {
+                       if( (seq->seq1 && (seq->seq1->flag & SELECT)) ||
+                               (seq->seq2 && (seq->seq2->flag & SELECT)) ||
+                               (seq->seq3 && (seq->seq3->flag & SELECT)) )
+                               return FALSE;
                }
        }
 
@@ -2935,12 +3025,8 @@ int seq_tx_test(Sequence * seq)
 
 static int seq_overlap(Sequence *seq1, Sequence *seq2)
 {
-       if(seq1 != seq2)
-               if(seq1->machine==seq2->machine)
-                       if(((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp))==0)
-                               return 1;
-
-       return 0;
+       return (seq1 != seq2 && seq1->machine == seq2->machine &&
+                       ((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp))==0);
 }
 
 int seq_test_overlap(ListBase * seqbasep, Sequence *test)
@@ -2958,7 +3044,7 @@ int seq_test_overlap(ListBase * seqbasep, Sequence *test)
 }
 
 
-static void seq_translate(Scene *evil_scene, Sequence *seq, int delta)
+void seq_translate(Scene *evil_scene, Sequence *seq, int delta)
 {
        seq_offset_animdata(evil_scene, seq, delta);
        seq->start += delta;
@@ -2973,6 +3059,46 @@ static void seq_translate(Scene *evil_scene, Sequence *seq, int delta)
        calc_sequence_disp(evil_scene, seq);
 }
 
+void seq_sound_init(Scene *scene, Sequence *seq)
+{
+       if(seq->type==SEQ_META) {
+               Sequence *seq_child;
+               for(seq_child= seq->seqbase.first; seq_child; seq_child= seq_child->next) {
+                       seq_sound_init(scene, seq_child);
+               }
+       }
+       else {
+               if(seq->sound) {
+                       seq->scene_sound = sound_add_scene_sound(scene, seq, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
+               }
+               if(seq->scene) {
+                       sound_scene_add_scene_sound(scene, seq, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
+               }
+       }
+}
+
+Sequence *seq_foreground_frame_get(Scene *scene, int frame)
+{
+       Editing *ed= seq_give_editing(scene, FALSE);
+       Sequence *seq, *best_seq=NULL;
+       int best_machine = -1;
+       
+       if(!ed) return NULL;
+       
+       for (seq=ed->seqbasep->first; seq; seq= seq->next) {
+               if(seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame)
+                       continue;
+               /* only use elements you can see - not */
+               if (ELEM5(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE, SEQ_COLOR)) {
+                       if (seq->machine > best_machine) {
+                               best_seq = seq;
+                               best_machine = seq->machine;
+                       }
+               }
+       }
+       return best_seq;
+}
+
 /* return 0 if there werent enough space */
 int shuffle_seq(ListBase * seqbasep, Sequence *test, Scene *evil_scene)
 {
@@ -3080,16 +3206,33 @@ int shuffle_seq_time(ListBase * seqbasep, Scene *evil_scene)
        return offset? 0:1;
 }
 
-void seq_update_sound(Scene* scene, Sequence *seq)
+void seq_update_sound_bounds_all(Scene *scene)
 {
-       if(seq->scene_sound)
-       {
+       Editing *ed = scene->ed;
+
+       if(ed) {
+               Sequence *seq;
+
+               for(seq = ed->seqbase.first; seq; seq = seq->next) {
+                       if(seq->type == SEQ_META) {
+                               seq_update_sound_bounds_recursive(scene, seq);
+                       }
+                       else if(ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) {
+                               seq_update_sound_bounds(scene, seq);
+                       }
+               }
+       }
+}
+
+void seq_update_sound_bounds(Scene* scene, Sequence *seq)
+{
+       if(seq->scene_sound) {
                sound_move_scene_sound(scene, seq->scene_sound, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
                /* mute is set in seq_update_muting_recursive */
        }
 }
 
-static void seq_update_muting_recursive(Scene *scene, ListBase *seqbasep, Sequence *metaseq, int mute)
+static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, int mute)
 {
        Sequence *seq;
        int seqmute;
@@ -3105,26 +3248,49 @@ static void seq_update_muting_recursive(Scene *scene, ListBase *seqbasep, Sequen
                        if(seq == metaseq)
                                seqmute= 0;
 
-                       seq_update_muting_recursive(scene, &seq->seqbase, metaseq, seqmute);
+                       seq_update_muting_recursive(&seq->seqbase, metaseq, seqmute);
                }
-               else if((seq->type == SEQ_SOUND) || (seq->type == SEQ_SCENE)) {
+               else if(ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) {
                        if(seq->scene_sound) {
-                               sound_mute_scene_sound(scene, seq->scene_sound, seqmute);
+                               sound_mute_scene_sound(seq->scene_sound, seqmute);
                        }
                }
        }
 }
 
-void seq_update_muting(Scene *scene, Editing *ed)
+void seq_update_muting(Editing *ed)
 {
        if(ed) {
                /* mute all sounds up to current metastack list */
                MetaStack *ms= ed->metastack.last;
 
                if(ms)
-                       seq_update_muting_recursive(scene, &ed->seqbase, ms->parseq, 1);
+                       seq_update_muting_recursive(&ed->seqbase, ms->parseq, 1);
                else
-                       seq_update_muting_recursive(scene, &ed->seqbase, NULL, 0);
+                       seq_update_muting_recursive(&ed->seqbase, NULL, 0);
+       }
+}
+
+static void seq_update_sound_recursive(Scene *scene, ListBase *seqbasep, bSound *sound)
+{
+       Sequence *seq;
+
+       for(seq=seqbasep->first; seq; seq=seq->next) {
+               if(seq->type == SEQ_META) {
+                       seq_update_sound_recursive(scene, &seq->seqbase, sound);
+               }
+               else if(seq->type == SEQ_SOUND) {
+                       if(seq->scene_sound && sound == seq->sound) {
+                               sound_update_scene_sound(seq->scene_sound, sound);
+                       }
+               }
+       }
+}
+
+void seq_update_sound(struct Scene *scene, struct bSound *sound)
+{
+       if(scene->ed) {
+               seq_update_sound_recursive(scene, &scene->ed->seqbase, sound);
        }
 }
 
@@ -3146,26 +3312,49 @@ ListBase *seq_seqbase(ListBase *seqbase, Sequence *seq)
        return NULL;
 }
 
-int seq_swap(Sequence *seq_a, Sequence *seq_b)
+Sequence *seq_metastrip(ListBase * seqbase, Sequence * meta, Sequence *seq)
+{
+       Sequence * iseq;
+
+       for(iseq = seqbase->first; iseq; iseq = iseq->next) {
+               Sequence * rval;
+
+               if (seq == iseq) {
+                       return meta;
+               } else if(iseq->seqbase.first && 
+                       (rval = seq_metastrip(&iseq->seqbase, iseq, seq))) {
+                       return rval;
+               }
+       }
+
+       return NULL;
+}
+
+int seq_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str)
 {
        char name[sizeof(seq_a->name)];
 
-       if(seq_a->len != seq_b->len)
+       if(seq_a->len != seq_b->len) {
+               *error_str= "Strips must be the same length";
                return 0;
+       }
 
        /* type checking, could be more advanced but disalow sound vs non-sound copy */
        if(seq_a->type != seq_b->type) {
                if(seq_a->type == SEQ_SOUND || seq_b->type == SEQ_SOUND) {
+                       *error_str= "Strips were not compatible";
                        return 0;
                }
 
                /* disallow effects to swap with non-effects strips */
                if((seq_a->type & SEQ_EFFECT) != (seq_b->type & SEQ_EFFECT)) {
+                       *error_str= "Strips were not compatible";
                        return 0;
                }
 
                if((seq_a->type & SEQ_EFFECT) && (seq_b->type & SEQ_EFFECT)) {
                        if(get_sequence_effect_num_inputs(seq_a->type) != get_sequence_effect_num_inputs(seq_b->type)) {
+                               *error_str= "Strips must have the same number of inputs";
                                return 0;
                        }
                }
@@ -3174,9 +3363,9 @@ int seq_swap(Sequence *seq_a, Sequence *seq_b)
        SWAP(Sequence, *seq_a, *seq_b);
 
        /* swap back names so animation fcurves dont get swapped */
-       strcpy(name, seq_a->name+2);
-       strcpy(seq_a->name+2, seq_b->name+2);
-       strcpy(seq_b->name+2, name);
+       BLI_strncpy(name, seq_a->name+2, sizeof(name));
+       BLI_strncpy(seq_a->name+2, seq_b->name+2, sizeof(seq_b->name)-2);
+       BLI_strncpy(seq_b->name+2, name, sizeof(seq_b->name)-2);
 
        /* swap back opacity, and overlay mode */
        SWAP(int, seq_a->blend_mode, seq_b->blend_mode);
@@ -3210,7 +3399,7 @@ void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs)
 
        for (fcu= scene->adt->action->curves.first; fcu; fcu= fcu->next) {
                if(strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str)) {
-                       int i;
+                       unsigned int i;
                        for (i = 0; i < fcu->totvert; i++) {
                                BezTriple *bezt= &fcu->bezt[i];
                                bezt->vec[0][0] += ofs;
@@ -3247,7 +3436,7 @@ void seq_dupe_animdata(Scene *scene, char *name_from, char *name_to)
        BKE_animdata_fix_paths_rename(&scene->id, scene->adt, "sequence_editor.sequences_all", name_from, name_to, 0, 0, 0);
 
        /* add the original fcurves back */
-       addlisttolist(&scene->adt->action->curves, &lb);
+       BLI_movelisttolist(&scene->adt->action->curves, &lb);
 }
 
 /* XXX - hackish function needed to remove all fcurves belonging to a sequencer strip */
@@ -3358,7 +3547,7 @@ void seq_load_apply(Scene *scene, Sequence *seq, SeqLoadInfo *seq_load)
 
                if(seq_load->flag & SEQ_LOAD_SOUND_CACHE) {
                        if(seq->sound)
-                               sound_cache(seq->sound, 0);
+                               sound_cache(seq->sound);
                }
 
                seq_load->tot_success++;
@@ -3385,6 +3574,8 @@ Sequence *alloc_sequence(ListBase *lb, int cfra, int machine)
        seq->mul= 1.0;
        seq->blend_opacity = 100.0;
        seq->volume = 1.0f;
+       seq->pitch = 1.0f;
+       seq->scene_sound = NULL;
 
        return seq;
 }
@@ -3395,7 +3586,6 @@ Sequence *sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
        Scene *scene= CTX_data_scene(C); /* only for active seq */
        Sequence *seq;
        Strip *strip;
-       StripElem *se;
 
        seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel);
        seq->type= SEQ_IMAGE;
@@ -3406,7 +3596,7 @@ Sequence *sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
 
        strip->len = seq->len = seq_load->len ? seq_load->len : 1;
        strip->us= 1;
-       strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+       strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
        BLI_strncpy(strip->dir, seq_load->path, sizeof(strip->dir));
 
        seq_load_apply(scene, seq, seq_load);
@@ -3414,8 +3604,10 @@ Sequence *sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
        return seq;
 }
 
+#ifdef WITH_AUDASPACE
 Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
 {
+       Main *bmain= CTX_data_main(C);
        Scene *scene= CTX_data_scene(C); /* only for sound */
        Editing *ed= seq_give_editing(scene, TRUE);
        bSound *sound;
@@ -3437,7 +3629,7 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
        info = AUD_getInfo(sound->playback_handle);
 
        if (info.specs.channels == AUD_CHANNELS_INVALID) {
-               sound_delete(C, sound);
+               sound_delete(bmain, sound);
                //if(op)
                //      BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
                return NULL;
@@ -3455,37 +3647,47 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
        strip->len = seq->len = ceil(info.length * FPS);
        strip->us= 1;
 
-       strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+       /* we only need 1 element to store the filename */
+       strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem");
 
-       BLI_split_dirfile(seq_load->path, strip->dir, se->name);
+       BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name));
 
        seq->scene_sound = sound_add_scene_sound(scene, seq, seq_load->start_frame, seq_load->start_frame + strip->len, 0);
 
        calc_sequence_disp(scene, seq);
 
        /* last active name */
-       strncpy(ed->act_sounddir, strip->dir, FILE_MAXDIR-1);
+       BLI_strncpy(ed->act_sounddir, strip->dir, FILE_MAXDIR);
 
        seq_load_apply(scene, seq, seq_load);
 
        return seq;
 }
+#else // WITH_AUDASPACE
+Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
+{
+       (void)C;
+       (void)seqbasep;
+       (void)seq_load;
+       return NULL;
+}
+#endif // WITH_AUDASPACE
 
 Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
 {
        Scene *scene= CTX_data_scene(C); /* only for sound */
        char path[sizeof(seq_load->path)];
 
-       Sequence *seq, *soundseq;       /* generic strip vars */
+       Sequence *seq;  /* generic strip vars */
        Strip *strip;
        StripElem *se;
 
        struct anim *an;
 
        BLI_strncpy(path, seq_load->path, sizeof(path));
-       BLI_path_abs(path, G.sce);
+       BLI_path_abs(path, G.main->name);
 
-       an = openanim(path, IB_rect);
+       an = openanim(path, IB_rect, 0);
 
        if(an==NULL)
                return NULL;
@@ -3501,12 +3703,13 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
 
        /* basic defaults */
        seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
-       strip->len = seq->len = IMB_anim_get_duration( an );
+       strip->len = seq->len = IMB_anim_get_duration( an, IMB_TC_RECORD_RUN );
        strip->us= 1;
 
-       strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+       /* we only need 1 element for MOVIE strips */
+       strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem");
 
-       BLI_split_dirfile(seq_load->path, strip->dir, se->name);
+       BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name));
 
        calc_sequence_disp(scene, seq);
 
@@ -3515,7 +3718,7 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
                int start_frame_back= seq_load->start_frame;
                seq_load->channel++;
 
-               soundseq = sequencer_add_sound_strip(C, seqbasep, seq_load);
+               sequencer_add_sound_strip(C, seqbasep, seq_load);
 
                seq_load->start_frame= start_frame_back;
                seq_load->channel--;
@@ -3531,8 +3734,9 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
 }
 
 
-static Sequence *seq_dupli(struct Scene *scene, Sequence *seq, int dupe_flag)
+static Sequence *seq_dupli(struct Scene *scene, struct Scene *scene_to, Sequence *seq, int dupe_flag)
 {
+       Scene *sce_audio= scene_to ? scene_to : scene;
        Sequence *seqn = MEM_dupallocN(seq);
 
        seq->tmp = seqn;
@@ -3550,6 +3754,7 @@ static Sequence *seq_dupli(struct Scene *scene, Sequence *seq, int dupe_flag)
 
        if (seq->strip->proxy) {
                seqn->strip->proxy = MEM_dupallocN(seq->strip->proxy);
+               seqn->strip->proxy->anim = NULL;
        }
 
        if (seq->strip->color_balance) {
@@ -3558,24 +3763,24 @@ static Sequence *seq_dupli(struct Scene *scene, Sequence *seq, int dupe_flag)
        }
 
        if(seq->type==SEQ_META) {
-               seqn->strip->stripdata = 0;
+               seqn->strip->stripdata = NULL;
 
-               seqn->seqbase.first= seqn->seqbase.last= 0;
+               seqn->seqbase.first= seqn->seqbase.last= NULL;
                /* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */
                /* - seq_dupli_recursive(&seq->seqbase,&seqn->seqbase);*/
        } else if(seq->type == SEQ_SCENE) {
-               seqn->strip->stripdata = 0;
+               seqn->strip->stripdata = NULL;
                if(seq->scene_sound)
-                       seqn->scene_sound = sound_scene_add_scene_sound(scene, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
+                       seqn->scene_sound = sound_scene_add_scene_sound(sce_audio, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
        } else if(seq->type == SEQ_MOVIE) {
                seqn->strip->stripdata =
                                MEM_dupallocN(seq->strip->stripdata);
-               seqn->anim= 0;
+               seqn->anim= NULL;
        } else if(seq->type == SEQ_SOUND) {
                seqn->strip->stripdata =
                                MEM_dupallocN(seq->strip->stripdata);
                if(seq->scene_sound)
-                       seqn->scene_sound = sound_add_scene_sound(scene, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
+                       seqn->scene_sound = sound_add_scene_sound(sce_audio, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
 
                seqn->sound->id.us++;
        } else if(seq->type == SEQ_IMAGE) {
@@ -3593,7 +3798,7 @@ static Sequence *seq_dupli(struct Scene *scene, Sequence *seq, int dupe_flag)
                                sh.copy(seq, seqn);
                }
 
-               seqn->strip->stripdata = 0;
+               seqn->strip->stripdata = NULL;
 
        } else {
                fprintf(stderr, "Aiiiiekkk! sequence type not "
@@ -3610,13 +3815,13 @@ static Sequence *seq_dupli(struct Scene *scene, Sequence *seq, int dupe_flag)
        return seqn;
 }
 
-Sequence * seq_dupli_recursive(struct Scene *scene, Sequence * seq, int dupe_flag)
+Sequence * seq_dupli_recursive(struct Scene *scene, struct Scene *scene_to, Sequence * seq, int dupe_flag)
 {
-       Sequence * seqn = seq_dupli(scene, seq, dupe_flag);
+       Sequence * seqn = seq_dupli(scene, scene_to, seq, dupe_flag);
        if (seq->type == SEQ_META) {
                Sequence *s;
                for(s= seq->seqbase.first; s; s = s->next) {
-                       Sequence *n = seq_dupli_recursive(scene, s, dupe_flag);
+                       Sequence *n = seq_dupli_recursive(scene, scene_to, s, dupe_flag);
                        if (n) {
                                BLI_addtail(&seqn->seqbase, n);
                        }
@@ -3625,16 +3830,16 @@ Sequence * seq_dupli_recursive(struct Scene *scene, Sequence * seq, int dupe_fla
        return seqn;
 }
 
-void seqbase_dupli_recursive(Scene *scene, ListBase *nseqbase, ListBase *seqbase, int dupe_flag)
+void seqbase_dupli_recursive(Scene *scene, Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, int dupe_flag)
 {
        Sequence *seq;
-       Sequence *seqn = 0;
+       Sequence *seqn = NULL;
        Sequence *last_seq = seq_active_get(scene);
 
        for(seq= seqbase->first; seq; seq= seq->next) {
                seq->tmp= NULL;
                if((seq->flag & SELECT) || (dupe_flag & SEQ_DUPE_ALL)) {
-                       seqn = seq_dupli(scene, seq, dupe_flag);
+                       seqn = seq_dupli(scene, scene_to, seq, dupe_flag);
                        if (seqn) { /*should never fail */
                                if(dupe_flag & SEQ_DUPE_CONTEXT) {
                                        seq->flag &= ~SEQ_ALLSEL;
@@ -3643,7 +3848,7 @@ void seqbase_dupli_recursive(Scene *scene, ListBase *nseqbase, ListBase *seqbase
 
                                BLI_addtail(nseqbase, seqn);
                                if(seq->type==SEQ_META)
-                                       seqbase_dupli_recursive(scene, &seqn->seqbase, &seq->seqbase, dupe_flag);
+                                       seqbase_dupli_recursive(scene, scene_to, &seqn->seqbase, &seq->seqbase, dupe_flag);
 
                                if(dupe_flag & SEQ_DUPE_CONTEXT) {
                                        if (seq == last_seq) {