changes to the sequencer in trunk between 20855:20928, (excluding UI changes)
authorCampbell Barton <ideasman42@gmail.com>
Tue, 16 Jun 2009 15:04:29 +0000 (15:04 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 16 Jun 2009 15:04:29 +0000 (15:04 +0000)
had to //XXX comment some funcs.

1  2 
source/blender/blenkernel/intern/sequence.c
source/blender/editors/space_sequencer/sequencer_draw.c

index 3365af3,0000000..bb0665a
mode 100644,000000..100644
--- /dev/null
@@@ -1,3417 -1,0 +1,3459 @@@
-       quality = 90;
 +/**
 +* $Id: sequence.c 17508 2008-11-20 00:34:24Z campbellbarton $
 + *
 + * ***** BEGIN GPL LICENSE BLOCK *****
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 + *
 + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
 + * All rights reserved.
 + *
 + * Contributor(s): 
 + * - Blender Foundation, 2003-2009
 + * - Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +#include <stdlib.h>
 +#include <string.h>
 +#include <math.h>
 +
 +#include "MEM_guardedalloc.h"
 +
 +#include "DNA_listBase.h"
 +#include "DNA_sequence_types.h"
 +#include "DNA_scene_types.h"
 +
 +#include "BKE_global.h"
 +#include "BKE_image.h"
 +#include "BKE_main.h"
 +#include "BKE_sequence.h"
 +#include "BKE_utildefines.h"
 +
 +#include "BLI_blenlib.h"
 +
 +#include "IMB_imbuf.h"
 +#include "IMB_imbuf_types.h"
 +
 +#include "BLI_threads.h"
 +#include <pthread.h>
 +
 +#ifdef WIN32
 +#define snprintf _snprintf
 +#endif
 +
 +/* **** XXX ******** */
 +static int seqrectx= 0;       /* bad bad global! */
 +static int seqrecty= 0;
 +static void waitcursor() {}
 +static int blender_test_break() {return 0;}
 +
 +/* **** XXX ******** */
 +
 +
 +/* **********************************************************************
 +   alloc / free functions
 +   ********************************************************************** */
 +
 +static void free_tstripdata(int len, TStripElem *se)
 +{
 +      TStripElem *seo;
 +      int a;
 +
 +      seo= se;
 +      if (!se)
 +              return;
 +
 +      for(a=0; a<len; a++, se++) {
 +              if(se->ibuf) {
 +                      IMB_freeImBuf(se->ibuf);
 +                      se->ibuf = 0;
 +              }
 +              if(se->ibuf_comp) {
 +                      IMB_freeImBuf(se->ibuf_comp);
 +                      se->ibuf_comp = 0;
 +              }
 +      }
 +
 +      MEM_freeN(seo);
 +}
 +
 +
 +void new_tstripdata(Sequence *seq)
 +{
 +      if(seq->strip) {
 +              free_tstripdata(seq->strip->len, seq->strip->tstripdata);
 +              free_tstripdata(seq->strip->endstill, 
 +                              seq->strip->tstripdata_endstill);
 +              free_tstripdata(seq->strip->startstill, 
 +                              seq->strip->tstripdata_startstill);
 +
 +              seq->strip->tstripdata= 0;
 +              seq->strip->tstripdata_endstill= 0;
 +              seq->strip->tstripdata_startstill= 0;
 +
 +              if(seq->strip->ibuf_startstill) {
 +                      IMB_freeImBuf(seq->strip->ibuf_startstill);
 +                      seq->strip->ibuf_startstill = 0;
 +              }
 +
 +              if(seq->strip->ibuf_endstill) {
 +                      IMB_freeImBuf(seq->strip->ibuf_endstill);
 +                      seq->strip->ibuf_endstill = 0;
 +              }
 +
 +              seq->strip->len= seq->len;
 +      }
 +}
 +
 +
 +/* free */
 +
 +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;
 +      }
 +}
 +
 +void seq_free_strip(Strip *strip)
 +{
 +      strip->us--;
 +      if(strip->us>0) return;
 +      if(strip->us<0) {
 +              printf("error: negative users in strip\n");
 +              return;
 +      }
 +
 +      if (strip->stripdata) {
 +              MEM_freeN(strip->stripdata);
 +      }
 +
 +      if (strip->proxy) {
 +              if (strip->proxy->anim) {
 +                      IMB_free_anim(strip->proxy->anim);
 +              }
 +
 +              MEM_freeN(strip->proxy);
 +      }
 +      if (strip->crop) {
 +              MEM_freeN(strip->crop);
 +      }
 +      if (strip->transform) {
 +              MEM_freeN(strip->transform);
 +      }
 +      if (strip->color_balance) {
 +              MEM_freeN(strip->color_balance);
 +      }
 +
 +      free_tstripdata(strip->len, strip->tstripdata);
 +      free_tstripdata(strip->endstill, strip->tstripdata_endstill);
 +      free_tstripdata(strip->startstill, strip->tstripdata_startstill);
 +
 +      if(strip->ibuf_startstill) {
 +              IMB_freeImBuf(strip->ibuf_startstill);
 +              strip->ibuf_startstill = 0;
 +      }
 +
 +      if(strip->ibuf_endstill) {
 +              IMB_freeImBuf(strip->ibuf_endstill);
 +              strip->ibuf_endstill = 0;
 +      }
 +
 +      MEM_freeN(strip);
 +}
 +
 +void seq_free_sequence(Editing *ed, Sequence *seq)
 +{
 +      if(seq->strip) seq_free_strip(seq->strip);
 +
 +      if(seq->anim) IMB_free_anim(seq->anim);
 +      //XXX if(seq->hdaudio) sound_close_hdaudio(seq->hdaudio);
 +
 +      /* XXX if (seq->type & SEQ_EFFECT) {
 +              struct SeqEffectHandle sh = get_sequence_effect(seq);
 +
 +              sh.free(seq);
 +      }*/
 +
 +      if (ed->act_seq==seq)
 +              ed->act_seq= NULL;
 +
 +      MEM_freeN(seq);
 +}
 +
 +Editing *seq_give_editing(Scene *scene, int alloc)
 +{
 +      if (scene->ed == NULL && alloc) {
 +              Editing *ed;
 +
 +              ed= scene->ed= MEM_callocN( sizeof(Editing), "addseq");
 +              ed->seqbasep= &ed->seqbase;
 +      }
 +      return scene->ed;
 +}
 +
 +void seq_free_editing(Editing *ed)
 +{
 +      MetaStack *ms;
 +      Sequence *seq;
 +
 +      if(ed==NULL)
 +              return;
 +
 +      SEQ_BEGIN(ed, seq) {
 +              seq_free_sequence(ed, seq);
 +      }
 +      SEQ_END
 +
 +      while((ms= ed->metastack.first)) {
 +              BLI_remlink(&ed->metastack, ms);
 +              MEM_freeN(ms);
 +      }
 +
 +      MEM_freeN(ed);
 +}
 +
 +/* ************************* itterator ************************** */
 +/* *************** (replaces old WHILE_SEQ) ********************* */
 +/* **************** use now SEQ_BEGIN() SEQ_END ***************** */
 +
 +/* sequence strip iterator:
 + * - builds a full array, recursively into meta strips */
 +
 +static void seq_count(ListBase *seqbase, int *tot)
 +{
 +      Sequence *seq;
 +
 +      for(seq=seqbase->first; seq; seq=seq->next) {
 +              (*tot)++;
 +
 +              if(seq->seqbase.first)
 +                      seq_count(&seq->seqbase, tot);
 +      }
 +}
 +
 +static void seq_build_array(ListBase *seqbase, Sequence ***array, int depth)
 +{
 +      Sequence *seq;
 +
 +      for(seq=seqbase->first; seq; seq=seq->next) {
 +              seq->depth= depth;
 +
 +              if(seq->seqbase.first)
 +                      seq_build_array(&seq->seqbase, array, depth+1);
 +
 +              **array= seq;
 +              (*array)++;
 +      }
 +}
 +
 +void seq_array(Editing *ed, Sequence ***seqarray, int *tot, int use_pointer)
 +{
 +      Sequence **array;
 +
 +      *seqarray= NULL;
 +      *tot= 0;
 +
 +      if(ed == NULL)
 +              return;
 +
 +      if(use_pointer)
 +              seq_count(ed->seqbasep, tot);
 +      else
 +              seq_count(&ed->seqbase, tot);
 +
 +      if(*tot == 0)
 +              return;
 +
 +      *seqarray= array= MEM_mallocN(sizeof(Sequence *)*(*tot), "SeqArray");
 +      if(use_pointer)
 +              seq_build_array(ed->seqbasep, &array, 0);
 +      else
 +              seq_build_array(&ed->seqbase, &array, 0);
 +}
 +
 +void seq_begin(Editing *ed, SeqIterator *iter, int use_pointer)
 +{
 +      memset(iter, 0, sizeof(*iter));
 +      seq_array(ed, &iter->array, &iter->tot, use_pointer);
 +
 +      if(iter->tot) {
 +              iter->cur= 0;
 +              iter->seq= iter->array[iter->cur];
 +              iter->valid= 1;
 +      }
 +}
 +
 +void seq_next(SeqIterator *iter)
 +{
 +      if(++iter->cur < iter->tot)
 +              iter->seq= iter->array[iter->cur];
 +      else
 +              iter->valid= 0;
 +}
 +
 +void seq_end(SeqIterator *iter)
 +{
 +      if(iter->array)
 +              MEM_freeN(iter->array);
 +
 +      iter->valid= 0;
 +}
 +
 +/*
 +  **********************************************************************
 +  * build_seqar
 +  **********************************************************************
 +  * Build a complete array of _all_ sequencies (including those
 +  * in metastrips!)
 +  **********************************************************************
 +*/
 +
 +static void do_seq_count(ListBase *seqbase, int *totseq)
 +{
 +      Sequence *seq;
 +
 +      seq= seqbase->first;
 +      while(seq) {
 +              (*totseq)++;
 +              if(seq->seqbase.first) do_seq_count(&seq->seqbase, totseq);
 +              seq= seq->next;
 +      }
 +}
 +
 +static void do_build_seqar(ListBase *seqbase, Sequence ***seqar, int depth)
 +{
 +      Sequence *seq;
 +
 +      seq= seqbase->first;
 +      while(seq) {
 +              seq->depth= depth;
 +              if(seq->seqbase.first) do_build_seqar(&seq->seqbase, seqar, depth+1);
 +              **seqar= seq;
 +              (*seqar)++;
 +              seq= seq->next;
 +      }
 +}
 +
 +void build_seqar(ListBase *seqbase, Sequence  ***seqar, int *totseq)
 +{
 +      Sequence **tseqar;
 +
 +      *totseq= 0;
 +      do_seq_count(seqbase, totseq);
 +
 +      if(*totseq==0) {
 +              *seqar= 0;
 +              return;
 +      }
 +      *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar");
 +      tseqar= *seqar;
 +
 +      do_build_seqar(seqbase, seqar, 0);
 +      *seqar= tseqar;
 +}
 +
 +static void do_seq_count_cb(ListBase *seqbase, int *totseq,
 +                          int (*test_func)(Sequence * seq))
 +{
 +      Sequence *seq;
 +
 +      seq= seqbase->first;
 +      while(seq) {
 +              int test = test_func(seq);
 +              if (test & BUILD_SEQAR_COUNT_CURRENT) {
 +                      (*totseq)++;
 +              }
 +              if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) {
 +                      do_seq_count_cb(&seq->seqbase, totseq, test_func);
 +              }
 +              seq= seq->next;
 +      }
 +}
 +
 +static void do_build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int depth,
 +                            int (*test_func)(Sequence * seq))
 +{
 +      Sequence *seq;
 +
 +      seq= seqbase->first;
 +      while(seq) {
 +              int test = test_func(seq);
 +              seq->depth= depth;
 +
 +              if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) {
 +                      do_build_seqar_cb(&seq->seqbase, seqar, depth+1, 
 +                                        test_func);
 +              }
 +              if (test & BUILD_SEQAR_COUNT_CURRENT) {
 +                      **seqar= seq;
 +                      (*seqar)++;
 +              }
 +              seq= seq->next;
 +      }
 +}
 +
 +void build_seqar_cb(ListBase *seqbase, Sequence  ***seqar, int *totseq,
 +                  int (*test_func)(Sequence * seq))
 +{
 +      Sequence **tseqar;
 +
 +      *totseq= 0;
 +      do_seq_count_cb(seqbase, totseq, test_func);
 +
 +      if(*totseq==0) {
 +              *seqar= 0;
 +              return;
 +      }
 +      *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar");
 +      tseqar= *seqar;
 +
 +      do_build_seqar_cb(seqbase, seqar, 0, test_func);
 +      *seqar= tseqar;
 +}
 +
 +
 +void calc_sequence_disp(Sequence *seq)
 +{
 +      if(seq->startofs && seq->startstill) seq->startstill= 0;
 +      if(seq->endofs && seq->endstill) seq->endstill= 0;
 +      
 +      seq->startdisp= seq->start + seq->startofs - seq->startstill;
 +      seq->enddisp= seq->start+seq->len - seq->endofs + seq->endstill;
 +      
 +      seq->handsize= 10.0;    /* 10 frames */
 +      if( seq->enddisp-seq->startdisp < 10 ) {
 +              seq->handsize= (float)(0.5*(seq->enddisp-seq->startdisp));
 +      }
 +      else if(seq->enddisp-seq->startdisp > 250) {
 +              seq->handsize= (float)((seq->enddisp-seq->startdisp)/25);
 +      }
 +}
 +
 +void calc_sequence(Sequence *seq)
 +{
 +      Sequence *seqm;
 +      int min, max;
 +
 +      /* check all metas recursively */
 +      seqm= seq->seqbase.first;
 +      while(seqm) {
 +              if(seqm->seqbase.first) calc_sequence(seqm);
 +              seqm= seqm->next;
 +      }
 +
 +      /* effects and meta: automatic start and end */
 +
 +      if(seq->type & SEQ_EFFECT) {
 +              /* pointers */
 +              if(seq->seq2==0) seq->seq2= seq->seq1;
 +              if(seq->seq3==0) seq->seq3= seq->seq1;
 +
 +              /* effecten go from seq1 -> seq2: test */
 +
 +              /* we take the largest start and smallest end */
 +
 +              // seq->start= seq->startdisp= MAX2(seq->seq1->startdisp, seq->seq2->startdisp);
 +              // seq->enddisp= MIN2(seq->seq1->enddisp, seq->seq2->enddisp);
 +
 +              if (seq->seq1) {
 +                      seq->start= seq->startdisp= MAX3(seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp);
 +                      seq->enddisp= MIN3(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp);
 +                      seq->len= seq->enddisp - seq->startdisp;
 +              } else {
 +                      calc_sequence_disp(seq);
 +              }
 +
 +              if(seq->strip && seq->len!=seq->strip->len) {
 +                      new_tstripdata(seq);
 +              }
 +
 +      }
 +      else {
 +              if(seq->type==SEQ_META) {
 +                      seqm= seq->seqbase.first;
 +                      if(seqm) {
 +                              min= 1000000;
 +                              max= -1000000;
 +                              while(seqm) {
 +                                      if(seqm->startdisp < min) min= seqm->startdisp;
 +                                      if(seqm->enddisp > max) max= seqm->enddisp;
 +                                      seqm= seqm->next;
 +                              }
 +                              seq->start= min + seq->anim_startofs;
 +                              seq->len = max-min;
 +                              seq->len -= seq->anim_startofs;
 +                              seq->len -= seq->anim_endofs;
 +
 +                              if(seq->strip && seq->len!=seq->strip->len) {
 +                                      new_tstripdata(seq);
 +                              }
 +                      }
 +              }
 +              calc_sequence_disp(seq);
 +      }
 +}
 +
 +void reload_sequence_new_file(Scene *scene, Sequence * seq)
 +{
 +      char str[FILE_MAXDIR+FILE_MAXFILE];
 +
 +      if (!(seq->type == SEQ_MOVIE || seq->type == SEQ_IMAGE ||
 +            seq->type == SEQ_HD_SOUND || seq->type == SEQ_RAM_SOUND ||
 +            seq->type == SEQ_SCENE || seq->type == SEQ_META)) {
 +              return;
 +      }
 +
 +      new_tstripdata(seq);
 +
 +      if (seq->type != SEQ_SCENE && seq->type != SEQ_META &&
 +          seq->type != SEQ_IMAGE) {
 +              BLI_join_dirfile(str, seq->strip->dir, seq->strip->stripdata->name);
 +              BLI_convertstringcode(str, G.sce);
 +              BLI_convertstringframe(str, scene->r.cfra);
 +              
 +      }
 +
 +      if (seq->type == SEQ_IMAGE) {
 +              /* Hack? */
 +              int olen = MEM_allocN_len(seq->strip->stripdata)/sizeof(struct StripElem);
 +              seq->len = olen;
 +              seq->len -= seq->anim_startofs;
 +              seq->len -= seq->anim_endofs;
 +              if (seq->len < 0) {
 +                      seq->len = 0;
 +              }
 +              seq->strip->len = seq->len;
 +      } else if (seq->type == SEQ_MOVIE) {
 +              if(seq->anim) IMB_free_anim(seq->anim);
 +              seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0));
 +
 +              if (!seq->anim) {
 +                      return;
 +              }
 +      
 +              seq->len = IMB_anim_get_duration(seq->anim);
 +              
 +              seq->anim_preseek = IMB_anim_get_preseek(seq->anim);
 +
 +              seq->len -= seq->anim_startofs;
 +              seq->len -= seq->anim_endofs;
 +              if (seq->len < 0) {
 +                      seq->len = 0;
 +              }
 +              seq->strip->len = seq->len;
 +      } else if (seq->type == SEQ_HD_SOUND) {
 +// XXX                if(seq->hdaudio) sound_close_hdaudio(seq->hdaudio);
 +//            seq->hdaudio = sound_open_hdaudio(str);
 +
 +              if (!seq->hdaudio) {
 +                      return;
 +              }
 +
 +// XXX                seq->len = sound_hdaudio_get_duration(seq->hdaudio, FPS) - seq->anim_startofs - seq->anim_endofs;
 +              if (seq->len < 0) {
 +                      seq->len = 0;
 +              }
 +              seq->strip->len = seq->len;
 +      } else if (seq->type == SEQ_RAM_SOUND) {
 +              seq->len = (int) ( ((float)(seq->sound->streamlen-1)/
 +                                  ((float)scene->audio.mixrate*4.0 ))
 +                                 * FPS);
 +              seq->len -= seq->anim_startofs;
 +              seq->len -= seq->anim_endofs;
 +              if (seq->len < 0) {
 +                      seq->len = 0;
 +              }
 +              seq->strip->len = seq->len;
 +      } else if (seq->type == SEQ_SCENE) {
 +              Scene * sce = G.main->scene.first;
 +              int nr = 1;
 +              
 +              while(sce) {
 +                      if(nr == seq->scenenr) {
 +                              break;
 +                      }
 +                      nr++;
 +                      sce= sce->id.next;
 +              }
 +
 +              if (sce) {
 +                      seq->scene = sce;
 +              } else {
 +                      sce = seq->scene;
 +              }
 +
 +              strncpy(seq->name + 2, sce->id.name + 2, 
 +                      sizeof(seq->name) - 2);
 +
 +              seq->len= seq->scene->r.efra - seq->scene->r.sfra + 1;
 +              seq->len -= seq->anim_startofs;
 +              seq->len -= seq->anim_endofs;
 +              if (seq->len < 0) {
 +                      seq->len = 0;
 +              }
 +              seq->strip->len = seq->len;
 +      }
 +
 +      free_proxy_seq(seq);
 +
 +      calc_sequence(seq);
 +}
 +
 +void sort_seq(Scene *scene)
 +{
 +      /* all strips together per kind, and in order of y location ("machine") */
 +      ListBase seqbase, effbase;
 +      Editing *ed= seq_give_editing(scene, FALSE);
 +      Sequence *seq, *seqt;
 +
 +      
 +      if(ed==NULL) return;
 +
 +      seqbase.first= seqbase.last= 0;
 +      effbase.first= effbase.last= 0;
 +
 +      while( (seq= ed->seqbasep->first) ) {
 +              BLI_remlink(ed->seqbasep, seq);
 +
 +              if(seq->type & SEQ_EFFECT) {
 +                      seqt= effbase.first;
 +                      while(seqt) {
 +                              if(seqt->machine>=seq->machine) {
 +                                      BLI_insertlinkbefore(&effbase, seqt, seq);
 +                                      break;
 +                              }
 +                              seqt= seqt->next;
 +                      }
 +                      if(seqt==0) BLI_addtail(&effbase, seq);
 +              }
 +              else {
 +                      seqt= seqbase.first;
 +                      while(seqt) {
 +                              if(seqt->machine>=seq->machine) {
 +                                      BLI_insertlinkbefore(&seqbase, seqt, seq);
 +                                      break;
 +                              }
 +                              seqt= seqt->next;
 +                      }
 +                      if(seqt==0) BLI_addtail(&seqbase, seq);
 +              }
 +      }
 +
 +      addlisttolist(&seqbase, &effbase);
 +      *(ed->seqbasep)= seqbase;
 +}
 +
 +
 +void clear_scene_in_allseqs(Scene *sce)
 +{
 +      Scene *sce1;
 +      Editing *ed;
 +      Sequence *seq;
 +
 +      /* when a scene is deleted: test all seqs */
 +
 +      sce1= G.main->scene.first;
 +      while(sce1) {
 +              if(sce1!=sce && sce1->ed) {
 +                      ed= sce1->ed;
 +
 +                      SEQ_BEGIN(ed, seq) {
 +
 +                              if(seq->scene==sce) seq->scene= 0;
 +
 +                      }
 +                      SEQ_END
 +              }
 +
 +              sce1= sce1->id.next;
 +      }
 +}
 +
 +char *give_seqname_by_type(int type)
 +{
 +      switch(type) {
 +      case SEQ_META:       return "Meta";
 +      case SEQ_IMAGE:      return "Image";
 +      case SEQ_SCENE:      return "Scene";
 +      case SEQ_MOVIE:      return "Movie";
 +      case SEQ_RAM_SOUND:  return "Audio (RAM)";
 +      case SEQ_HD_SOUND:   return "Audio (HD)";
 +      case SEQ_CROSS:      return "Cross";
 +      case SEQ_GAMCROSS:   return "Gamma Cross";
 +      case SEQ_ADD:        return "Add";
 +      case SEQ_SUB:        return "Sub";
 +      case SEQ_MUL:        return "Mul";
 +      case SEQ_ALPHAOVER:  return "Alpha Over";
 +      case SEQ_ALPHAUNDER: return "Alpha Under";
 +      case SEQ_OVERDROP:   return "Over Drop";
 +      case SEQ_WIPE:       return "Wipe";
 +      case SEQ_GLOW:       return "Glow";
 +      case SEQ_TRANSFORM:  return "Transform";
 +      case SEQ_COLOR:      return "Color";
 +      case SEQ_SPEED:      return "Speed";
 +      default:
 +              return 0;
 +      }
 +}
 +
 +char *give_seqname(Sequence *seq)
 +{
 +      char * name = give_seqname_by_type(seq->type);
 +
 +      if (!name) {
 +              if(seq->type<SEQ_EFFECT) {
 +                      return seq->strip->dir;
 +              } else if(seq->type==SEQ_PLUGIN) {
 +                      if(!(seq->flag & SEQ_EFFECT_NOT_LOADED) &&
 +                         seq->plugin && seq->plugin->doit) {
 +                              return seq->plugin->pname;
 +                      } else {
 +                              return "Plugin";
 +                      }
 +              } else {
 +                      return "Effect";
 +              }
 +      }
 +      return name;
 +}
 +
 +/* ***************** DO THE SEQUENCE ***************** */
 +
 +static void make_black_ibuf(ImBuf *ibuf)
 +{
 +      unsigned int *rect;
 +      float *rect_float;
 +      int tot;
 +
 +      if(ibuf==0 || (ibuf->rect==0 && ibuf->rect_float==0)) return;
 +
 +      tot= ibuf->x*ibuf->y;
 +
 +      rect= ibuf->rect;
 +      rect_float = ibuf->rect_float;
 +
 +      if (rect) {
 +              memset(rect,       0, tot * sizeof(char) * 4);
 +      }
 +
 +      if (rect_float) {
 +              memset(rect_float, 0, tot * sizeof(float) * 4);
 +      }
 +}
 +
 +static void multibuf(ImBuf *ibuf, float fmul)
 +{
 +      char *rt;
 +      float *rt_float;
 +
 +      int a, mul, icol;
 +
 +      mul= (int)(256.0*fmul);
 +      rt= (char *)ibuf->rect;
 +      rt_float = ibuf->rect_float;
 +
 +      if (rt) {
 +              a= ibuf->x*ibuf->y;
 +              while(a--) {
 +
 +                      icol= (mul*rt[0])>>8;
 +                      if(icol>254) rt[0]= 255; else rt[0]= icol;
 +                      icol= (mul*rt[1])>>8;
 +                      if(icol>254) rt[1]= 255; else rt[1]= icol;
 +                      icol= (mul*rt[2])>>8;
 +                      if(icol>254) rt[2]= 255; else rt[2]= icol;
 +                      icol= (mul*rt[3])>>8;
 +                      if(icol>254) rt[3]= 255; else rt[3]= icol;
 +                      
 +                      rt+= 4;
 +              }
 +      }
 +      if (rt_float) {
 +              a= ibuf->x*ibuf->y;
 +              while(a--) {
 +                      rt_float[0] *= fmul;
 +                      rt_float[1] *= fmul;
 +                      rt_float[2] *= fmul;
 +                      rt_float[3] *= fmul;
 +                      
 +                      rt_float += 4;
 +              }
 +      }
 +}
 +
 +static void do_effect(Scene *scene, int cfra, Sequence *seq, TStripElem * se)
 +{
 +      TStripElem *se1, *se2, *se3;
 +      float fac, facf;
 +      int x, y;
 +      int early_out;
 +      struct SeqEffectHandle sh = get_sequence_effect(seq);
 +
 +      if (!sh.execute) { /* effect not supported in this version... */
 +              make_black_ibuf(se->ibuf);
 +              return;
 +      }
 +
 +#if 0 // XXX old animation system
 +      if(seq->ipo && seq->ipo->curve.first) {
 +              do_seq_ipo(scene, seq, cfra);
 +              fac= seq->facf0;
 +              facf= seq->facf1;
 +      } else
 +#endif // XXX old animation system    
 +      {
 +              sh.get_default_fac(seq, cfra, &fac, &facf);
 +      }
 +
 +      if( !(scene->r.mode & R_FIELDS) ) facf = fac;
 +
 +      early_out = sh.early_out(seq, fac, facf);
 +
 +      if (early_out == -1) { /* no input needed */
 +              sh.execute(seq, cfra, fac, facf, 
 +                         se->ibuf->x, se->ibuf->y, 
 +                         0, 0, 0, se->ibuf);
 +              return;
 +      }
 +
 +      switch (early_out) {
 +      case 0:
 +              if (se->se1==0 || se->se2==0 || se->se3==0) {
 +                      make_black_ibuf(se->ibuf);
 +                      return;
 +              }
 +
 +              se1= se->se1;
 +              se2= se->se2;
 +              se3= se->se3;
 +
 +              if (   (se1==0 || se2==0 || se3==0)
 +                  || (se1->ibuf==0 || se2->ibuf==0 || se3->ibuf==0)) {
 +                      make_black_ibuf(se->ibuf);
 +                      return;
 +              }
 +
 +              break;
 +      case 1:
 +              if (se->se1 == 0) {
 +                      make_black_ibuf(se->ibuf);
 +                      return;
 +              }
 +
 +              se1= se->se1;
 +
 +              if (se1 == 0 || se1->ibuf == 0) {
 +                      make_black_ibuf(se->ibuf);
 +                      return;
 +              }
 +
 +              if (se->ibuf != se1->ibuf) {
 +                      IMB_freeImBuf(se->ibuf);
 +                      se->ibuf = se1->ibuf;
 +                      IMB_refImBuf(se->ibuf);
 +              }
 +              return;
 +      case 2:
 +              if (se->se2 == 0) {
 +                      make_black_ibuf(se->ibuf);
 +                      return;
 +              }
 +
 +              se2= se->se2;
 +
 +              if (se2 == 0 || se2->ibuf == 0) {
 +                      make_black_ibuf(se->ibuf);
 +                      return;
 +              }
 +              if (se->ibuf != se2->ibuf) {
 +                      IMB_freeImBuf(se->ibuf);
 +                      se->ibuf = se2->ibuf;
 +                      IMB_refImBuf(se->ibuf);
 +              }
 +              return;
 +      default:
 +              make_black_ibuf(se->ibuf);
 +              return;
 +      }
 +
 +      x= se2->ibuf->x;
 +      y= se2->ibuf->y;
 +
 +      if (!se1->ibuf->rect_float && se->ibuf->rect_float) {
 +              IMB_float_from_rect(se1->ibuf);
 +      }
 +      if (!se2->ibuf->rect_float && se->ibuf->rect_float) {
 +              IMB_float_from_rect(se2->ibuf);
 +      }
 +      if (!se3->ibuf->rect_float && se->ibuf->rect_float) {
 +              IMB_float_from_rect(se3->ibuf);
 +      }
 +      
 +      if (!se1->ibuf->rect && !se->ibuf->rect_float) {
 +              IMB_rect_from_float(se1->ibuf);
 +      }
 +      if (!se2->ibuf->rect && !se->ibuf->rect_float) {
 +              IMB_rect_from_float(se2->ibuf);
 +      }
 +      if (!se3->ibuf->rect && !se->ibuf->rect_float) {
 +              IMB_rect_from_float(se3->ibuf);
 +      }
 +
 +      sh.execute(seq, cfra, fac, facf, x, y, se1->ibuf, se2->ibuf, se3->ibuf,
 +                 se->ibuf);
 +}
 +
 +static int give_stripelem_index(Sequence *seq, int cfra)
 +{
 +      int nr;
 +
 +      if(seq->startdisp >cfra || seq->enddisp <= cfra) return -1;
 +      if(seq->len == 0) return -1;
 +      if(seq->flag&SEQ_REVERSE_FRAMES) {      
 +              /*reverse frame in this sequence */
 +              if(cfra <= seq->start) nr= seq->len-1;
 +              else if(cfra >= seq->start+seq->len-1) nr= 0;
 +              else nr= (seq->start + seq->len) - cfra;
 +      } else {
 +              if(cfra <= seq->start) nr= 0;
 +              else if(cfra >= seq->start+seq->len-1) nr= seq->len-1;
 +              else nr= cfra-seq->start;
 +      }
 +      if (seq->strobe < 1.0) seq->strobe = 1.0;
 +      if (seq->strobe > 1.0) {
 +              nr -= (int)fmod((double)nr, (double)seq->strobe);
 +      }
 +
 +      return nr;
 +}
 +
 +static TStripElem* alloc_tstripdata(int len, const char * name)
 +{
 +      int i;
 +      TStripElem *se = MEM_callocN(len * sizeof(TStripElem), name);
 +      for (i = 0; i < len; i++) {
 +              se[i].ok = STRIPELEM_OK;
 +      }
 +      return se;
 +}
 +
 +TStripElem *give_tstripelem(Sequence *seq, int cfra)
 +{
 +      TStripElem *se;
 +      int nr;
 +
 +      se = seq->strip->tstripdata;
 +      if (se == 0 && seq->len > 0) {
 +              se = seq->strip->tstripdata = alloc_tstripdata(seq->len,
 +                                                             "tstripelems");
 +      }
 +      nr = give_stripelem_index(seq, cfra);
 +
 +      if (nr == -1) return 0;
 +      if (se == 0) return 0;
 +
 +      se += nr; 
 +
 +      /* if there are IPOs with blend modes active, one has to watch out
 +         for startstill + endstill area: we can't use the same tstripelem
 +         here for all ibufs, since then, blending with IPOs won't work!
 +         
 +         Rather common case, if you use a single image and try to fade
 +         it in and out... or want to use your strip as a watermark in
 +         alpha over mode...
 +      */
 +      if (seq->blend_mode != SEQ_BLEND_REPLACE ||
 +          (/*seq->ipo && seq->ipo->curve.first &&*/ 
 +                 (!(seq->type & SEQ_EFFECT) || !seq->seq1))) {
 +              Strip * s = seq->strip;
 +              if (cfra < seq->start) {
 +                      se = s->tstripdata_startstill;
 +                      if (seq->startstill > s->startstill) {
 +                              free_tstripdata(s->startstill, 
 +                                              s->tstripdata_startstill);
 +                              se = 0;
 +                      }
 +
 +                      if (se == 0) {
 +                              s->startstill = seq->startstill;
 +                              se = seq->strip->tstripdata_startstill
 +                                      = alloc_tstripdata(
 +                                              s->startstill,
 +                                              "tstripelems_startstill");
 +                      }
 +                      se += seq->start - cfra - 1;
 +
 +              } else if (cfra > seq->start + seq->len-1) {
 +                      se = s->tstripdata_endstill;
 +                      if (seq->endstill > s->endstill) {
 +                              free_tstripdata(s->endstill, 
 +                                              s->tstripdata_endstill);
 +                              se = 0;
 +                      }
 +
 +                      if (se == 0) {
 +                              s->endstill = seq->endstill;
 +                              se = seq->strip->tstripdata_endstill
 +                                      = alloc_tstripdata(
 +                                              s->endstill,
 +                                              "tstripelems_endstill");
 +                      }
 +                      se += cfra - (seq->start + seq->len-1) - 1;
 +              }
 +      }
 +
 +      
 +      se->nr= nr;
 +
 +      return se;
 +}
 +
 +StripElem *give_stripelem(Sequence *seq, int cfra)
 +{
 +      StripElem *se;
 +      int nr;
 +
 +      se = seq->strip->stripdata;
 +      nr = give_stripelem_index(seq, cfra);
 +
 +      if (nr == -1) return 0;
 +      if (se == 0) return 0;
 +
 +      se += nr + seq->anim_startofs; 
 +      
 +      return se;
 +}
 +
 +static int evaluate_seq_frame_gen(Sequence ** seq_arr, ListBase *seqbase, int cfra)
 +{
 +      Sequence *seq;
 +      int totseq=0;
 +
 +      memset(seq_arr, 0, sizeof(Sequence*) * (MAXSEQ+1));
 +
 +      seq= seqbase->first;
 +      while(seq) {
 +              if(seq->startdisp <=cfra && seq->enddisp > cfra) {
 +                      seq_arr[seq->machine]= seq;
 +                      totseq++;
 +              }
 +              seq= seq->next;
 +      }
 +
 +      return totseq;
 +}
 +
 +int evaluate_seq_frame(Scene *scene, int cfra)
 +{
 +      Editing *ed= seq_give_editing(scene, FALSE);
 +      Sequence *seq_arr[MAXSEQ+1];
 +
 +      if(ed==NULL) return 0;
 +      return evaluate_seq_frame_gen(seq_arr, ed->seqbasep, cfra);
 +}
 +
 +static int video_seq_is_rendered(Sequence * seq)
 +{
 +      return (seq 
 +              && !(seq->flag & SEQ_MUTE) 
 +              && seq->type != SEQ_RAM_SOUND 
 +              && seq->type != SEQ_HD_SOUND);
 +}
 +
 +static int get_shown_sequences(       ListBase * seqbasep, int cfra, int chanshown, Sequence ** seq_arr_out)
 +{
 +      Sequence *seq_arr[MAXSEQ+1];
 +      int b = chanshown;
 +      int cnt = 0;
 +
 +      if (b > MAXSEQ) {
 +              return 0;
 +      }
 +
 +      if(evaluate_seq_frame_gen(seq_arr, seqbasep, cfra)) {
 +              if (b > 0) {
 +                      if (seq_arr[b] == 0) {
 +                              return 0;
 +                      }
 +              } else {
 +                      for (b = MAXSEQ; b > 0; b--) {
 +                              if (video_seq_is_rendered(seq_arr[b])) {
 +                                      break;
 +                              }
 +                      }
 +              }
 +      }
 +      
 +      chanshown = b;
 +
 +      for (;b > 0; b--) {
 +              if (video_seq_is_rendered(seq_arr[b])) {
 +                      if (seq_arr[b]->blend_mode == SEQ_BLEND_REPLACE) {
 +                              break;
 +                      }
 +              }
 +      }
 +
 +      for (;b <= chanshown; b++) {
 +              if (video_seq_is_rendered(seq_arr[b])) {
 +                      seq_arr_out[cnt++] = seq_arr[b];
 +              }
 +      }
 +
 +      return cnt;
 +}
 + 
 +
 +/* **********************************************************************
 +   proxy management
 +   ********************************************************************** */
 +
 +#define PROXY_MAXFILE (2*FILE_MAXDIR+FILE_MAXFILE)
 +
 +static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * name, int render_size)
 +{
 +      int frameno;
 +      char dir[FILE_MAXDIR];
 +
 +      if (!seq->strip->proxy) {
 +              return FALSE;
 +      }
 +
 +      if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) {
 +              strcpy(dir, seq->strip->proxy->dir);
 +      } else {
 +              if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) {
 +                      snprintf(dir, FILE_MAXDIR, "%s/BL_proxy", 
 +                               seq->strip->dir);
 +              } else {
 +                      return FALSE;
 +              }
 +      }
 +
 +      if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
 +              BLI_join_dirfile(name, dir, seq->strip->proxy->file);
 +              BLI_convertstringcode(name, G.sce);
 +              BLI_convertstringframe(name, cfra);
 +
 +              return TRUE;
 +      }
 +
 +      /* generate a seperate proxy directory for each preview size */
 +
 +      if (seq->type == SEQ_IMAGE) {
 +              StripElem * se = give_stripelem(seq, cfra);
 +              snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy",
 +                       dir, render_size, se->name);
 +              frameno = 1;
 +      } else if (seq->type == SEQ_MOVIE) {
 +              TStripElem * tse = give_tstripelem(seq, cfra);
 +
 +              frameno = tse->nr + seq->anim_startofs;
 +
 +              snprintf(name, PROXY_MAXFILE, "%s/%s/%d/####", dir,
 +                       seq->strip->stripdata->name,
 +                       render_size);
 +      } else {
 +              TStripElem * tse = give_tstripelem(seq, cfra);
 +
 +              frameno = tse->nr + seq->anim_startofs;
 +
 +              snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir,
 +                       render_size);
 +      }
 +
 +      BLI_convertstringcode(name, G.sce);
 +      BLI_convertstringframe(name, frameno);
 +      
 +
 +      strcat(name, ".jpg");
 +
 +      return TRUE;
 +}
 +
 +static struct ImBuf * seq_proxy_fetch(Scene *scene, Sequence * seq, int cfra, int render_size)
 +{
 +      char name[PROXY_MAXFILE];
 +
 +      if (!(seq->flag & SEQ_USE_PROXY)) {
 +              return 0;
 +      }
 +
 +      /* rendering at 100% ? No real sense in proxy-ing, right? */
 +      if (render_size == 100) {
 +              return 0;
 +      }
 +
 +      if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
 +              TStripElem * tse = give_tstripelem(seq, cfra);
 +              int frameno = tse->nr + seq->anim_startofs;
 +              if (!seq->strip->proxy->anim) {
 +                      if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) {
 +                              return 0;
 +                      }
 + 
 +                      seq->strip->proxy->anim = openanim(name, IB_rect);
 +              }
 +              if (!seq->strip->proxy->anim) {
 +                      return 0;
 +              }
 + 
 +              return IMB_anim_absolute(seq->strip->proxy->anim, frameno);
 +      }
 + 
 +      if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) {
 +              return 0;
 +      }
 +
 +      if (BLI_exists(name)) {
 +              return IMB_loadiffname(name, IB_rect);
 +      } else {
 +              return 0;
 +      }
 +}
 +
 +static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra,
 +                            int build_proxy_run, int render_size);
 +
 +static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int render_size)
 +{
 +      char name[PROXY_MAXFILE];
 +      int quality;
 +      TStripElem * se;
 +      int ok;
 +      int rectx, recty;
 +      struct ImBuf * ibuf;
 +
 +      if (!(seq->flag & SEQ_USE_PROXY)) {
 +              return;
 +      }
 +
 +      /* rendering at 100% ? No real sense in proxy-ing, right? */
 +      if (render_size == 100) {
 +              return;
 +      }
 +
 +      /* that's why it is called custom... */
 +      if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
 +              return;
 +    }
 +
 +      if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) {
 +              return;
 +      }
 +
 +      se = give_tstripelem(seq, cfra);
 +      if (!se) {
 +              return;
 +      }
 +
 +      if(se->ibuf) {
 +              IMB_freeImBuf(se->ibuf);
 +              se->ibuf = 0;
 +      }
 +      
 +      do_build_seq_ibuf(scene, seq, se, cfra, TRUE, render_size);
 +
 +      if (!se->ibuf) {
 +              return;
 +      }
 +
 +      rectx= (render_size*scene->r.xsch)/100;
 +      recty= (render_size*scene->r.ysch)/100;
 +
 +      ibuf = se->ibuf;
 +
 +      if (ibuf->x != rectx || ibuf->y != recty) {
 +              IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty);
 +      }
 +
 +      /* quality is fixed, otherwise one has to generate seperate
 +         directories for every quality...
 +
 +         depth = 32 is intentionally left in, otherwise ALPHA channels
 +         won't work... */
-                               seq_proxy_build_frame(scene, seq, cfra, scene->r.size);
++      quality = seq->strip->proxy->quality;
 +      ibuf->ftype= JPG | quality;
 +
 +      BLI_make_existing_file(name);
 +      
 +      ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat);
 +      if (ok == 0) {
 +              perror(name);
 +      }
 +
 +      IMB_freeImBuf(ibuf);
 +      se->ibuf = 0;
 +}
 +
 +void seq_proxy_rebuild(Scene *scene, Sequence * seq)
 +{
 +      int cfra;
++      float rsize = seq->strip->proxy->size;
 +
 +      waitcursor(1);
 +
 +      G.afbreek = 0;
 +
 +      /* flag management tries to account for strobe and 
 +         other "non-linearities", that might come in the future...
 +         better way would be to "touch" the files, so that _really_
 +         no one is rebuild twice.
 +       */
 +
 +      for (cfra = seq->startdisp; cfra < seq->enddisp; cfra++) {
 +              TStripElem * tse = give_tstripelem(seq, cfra);
 +
 +              tse->flag &= ~STRIPELEM_PREVIEW_DONE;
 +      }
 +
++      
++
 +      /* a _lot_ faster for movie files, if we read frames in
 +         sequential order */
 +      if (seq->flag & SEQ_REVERSE_FRAMES) {
 +              for (cfra = seq->enddisp-seq->endstill-1; 
 +                   cfra >= seq->startdisp + seq->startstill; cfra--) {
 +                      TStripElem * tse = give_tstripelem(seq, cfra);
 +
 +                      if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) {
-                               seq_proxy_build_frame(scene, seq, cfra, scene->r.size);
++//XXX                         set_timecursor(cfra);
++                              seq_proxy_build_frame(scene, seq, cfra, rsize);
 +                              tse->flag |= STRIPELEM_PREVIEW_DONE;
 +                      }
 +                      if (blender_test_break()) {
 +                              break;
 +                      }
 +              }
 +      } else {
 +              for (cfra = seq->startdisp + seq->startstill; 
 +                   cfra < seq->enddisp - seq->endstill; cfra++) {
 +                      TStripElem * tse = give_tstripelem(seq, cfra);
 +
 +                      if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) {
-       if(seq->blend_mode == SEQ_BLEND_REPLACE) {
++//XXX                         set_timecursor(cfra);
++                              seq_proxy_build_frame(scene, seq, cfra, rsize);
 +                              tse->flag |= STRIPELEM_PREVIEW_DONE;
 +                      }
 +                      if (blender_test_break()) {
 +                              break;
 +                      }
 +              }
 +      }
 +      waitcursor(0);
 +}
 +
 +
 +/* **********************************************************************
 +   color balance 
 +   ********************************************************************** */
 +
 +static StripColorBalance calc_cb(StripColorBalance * cb_)
 +{
 +      StripColorBalance cb = *cb_;
 +      int c;
 +
 +      if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_LIFT) {
 +              for (c = 0; c < 3; c++) {
 +                      cb.lift[c] = 1.0 - cb.lift[c];
 +              }
 +      } else {
 +              for (c = 0; c < 3; c++) {
 +                      cb.lift[c] = -(1.0 - cb.lift[c]);
 +              }
 +      }
 +      if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAIN) {
 +              for (c = 0; c < 3; c++) {
 +                      if (cb.gain[c] != 0.0) {
 +                              cb.gain[c] = 1.0/cb.gain[c];
 +                      } else {
 +                              cb.gain[c] = 1000000; /* should be enough :) */
 +                      }
 +              }
 +      }
 +
 +      if (!(cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAMMA)) {
 +              for (c = 0; c < 3; c++) {
 +                      if (cb.gamma[c] != 0.0) {
 +                              cb.gamma[c] = 1.0/cb.gamma[c];
 +                      } else {
 +                              cb.gamma[c] = 1000000; /* should be enough :) */
 +                      }
 +              }
 +      }
 +
 +      return cb;
 +}
 +
 +static void make_cb_table_byte(float lift, float gain, float gamma,
 +                             unsigned char * table, float mul)
 +{
 +      int y;
 +
 +      for (y = 0; y < 256; y++) {
 +              float v = 1.0 * y / 255;
 +              v *= gain;
 +              v += lift; 
 +              v = pow(v, gamma);
 +              v *= mul;
 +              if ( v > 1.0) {
 +                      v = 1.0;
 +              } else if (v < 0.0) {
 +                      v = 0.0;
 +              }
 +              table[y] = v * 255;
 +      }
 +
 +}
 +
 +static void make_cb_table_float(float lift, float gain, float gamma,
 +                              float * table, float mul)
 +{
 +      int y;
 +
 +      for (y = 0; y < 256; y++) {
 +              float v = (float) y * 1.0 / 255.0;
 +              v *= gain;
 +              v += lift;
 +              v = pow(v, gamma);
 +              v *= mul;
 +              table[y] = v;
 +      }
 +}
 +
 +static void color_balance_byte_byte(Sequence * seq, TStripElem* se, float mul)
 +{
 +      unsigned char cb_tab[3][256];
 +      int c;
 +      unsigned char * p = (unsigned char*) se->ibuf->rect;
 +      unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y;
 +
 +      StripColorBalance cb = calc_cb(seq->strip->color_balance);
 +
 +      for (c = 0; c < 3; c++) {
 +              make_cb_table_byte(cb.lift[c], cb.gain[c], cb.gamma[c],
 +                                 cb_tab[c], mul);
 +      }
 +
 +      while (p < e) {
 +              p[0] = cb_tab[0][p[0]];
 +              p[1] = cb_tab[1][p[1]];
 +              p[2] = cb_tab[2][p[2]];
 +              
 +              p += 4;
 +      }
 +}
 +
 +static void color_balance_byte_float(Sequence * seq, TStripElem* se, float mul)
 +{
 +      float cb_tab[4][256];
 +      int c,i;
 +      unsigned char * p = (unsigned char*) se->ibuf->rect;
 +      unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y;
 +      float * o;
 +      StripColorBalance cb;
 +
 +      imb_addrectfloatImBuf(se->ibuf);
 +
 +      o = se->ibuf->rect_float;
 +
 +      cb = calc_cb(seq->strip->color_balance);
 +
 +      for (c = 0; c < 3; c++) {
 +              make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c],
 +                                  cb_tab[c], mul);
 +      }
 +
 +      for (i = 0; i < 256; i++) {
 +              cb_tab[3][i] = ((float)i)*(1.0f/255.0f);
 +      }
 +
 +      while (p < e) {
 +              o[0] = cb_tab[0][p[0]];
 +              o[1] = cb_tab[1][p[1]];
 +              o[2] = cb_tab[2][p[2]];
 +              o[3] = cb_tab[3][p[3]];
 +
 +              p += 4; o += 4;
 +      }
 +}
 +
 +static void color_balance_float_float(Sequence * seq, TStripElem* se, float mul)
 +{
 +      float * p = se->ibuf->rect_float;
 +      float * e = se->ibuf->rect_float + se->ibuf->x * 4* se->ibuf->y;
 +      StripColorBalance cb = calc_cb(seq->strip->color_balance);
 +
 +      while (p < e) {
 +              int c;
 +              for (c = 0; c < 3; c++) {
 +                      p[c] = pow(p[c] * cb.gain[c] + cb.lift[c], 
 +                                 cb.gamma[c]) * mul;
 +              }
 +              p += 4;
 +      }
 +}
 +
 +static void color_balance(Sequence * seq, TStripElem* se, float mul)
 +{
 +      if (se->ibuf->rect_float) {
 +              color_balance_float_float(seq, se, mul);
 +      } else if(seq->flag & SEQ_MAKE_FLOAT) {
 +              color_balance_byte_float(seq, se, mul);
 +      } else {
 +              color_balance_byte_byte(seq, se, mul);
 +      }
 +}
 +
 +/*
 +  input preprocessing for SEQ_IMAGE, SEQ_MOVIE and SEQ_SCENE
 +
 +  Do all the things you can't really do afterwards using sequence effects
 +  (read: before rescaling to render resolution has been done)
 +
 +  Order is important!
 +
 +  - Deinterlace
 +  - Crop and transform in image source coordinate space
 +  - Flip X + Flip Y (could be done afterwards, backward compatibility)
 +  - Promote image to float data (affects pipeline operations afterwards)
 +  - Color balance (is most efficient in the byte -> float 
 +    (future: half -> float should also work fine!)
 +    case, if done on load, since we can use lookup tables)
 +  - Premultiply
 +
 +*/
 +
 +static int input_have_to_preprocess(Scene *scene, Sequence * seq, TStripElem* se, int cfra)
 +{
 +      float mul;
 +
 +      if ((seq->flag & SEQ_FILTERY) || 
 +          (seq->flag & SEQ_USE_CROP) ||
 +          (seq->flag & SEQ_USE_TRANSFORM) ||
 +          (seq->flag & SEQ_FLIPX) ||
 +          (seq->flag & SEQ_FLIPY) ||
 +          (seq->flag & SEQ_USE_COLOR_BALANCE) ||
 +          (seq->flag & SEQ_MAKE_PREMUL) ||
 +          (se->ibuf->x != seqrectx || se->ibuf->y != seqrecty)) {
 +              return TRUE;
 +      }
 +
 +      mul = seq->mul;
 +
-                               && !(sce->r.scemode & R_DOSEQ)) 
-                               waitcursor(0);
++      if(seq->blend_mode == SEQ_BLEND_REPLACE &&
++         !(seq->type & SEQ_EFFECT)) {
 +#if 0 // XXX old animation system
 +              if (seq->ipo && seq->ipo->curve.first) {
 +                      do_seq_ipo(scene, seq, cfra);
 +                      mul *= seq->facf0;
 +              }
 +#endif // XXX old animation system
 +              mul *= seq->blend_opacity / 100.0;
 +      }
 +
 +      if (mul != 1.0) {
 +              return TRUE;
 +      }
 +              
 +      return FALSE;
 +}
 +
 +static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cfra)
 +{
 +      float mul;
 +
 +      seq->strip->orx= se->ibuf->x;
 +      seq->strip->ory= se->ibuf->y;
 +
 +      if((seq->flag & SEQ_FILTERY) && seq->type != SEQ_MOVIE) {
 +              IMB_filtery(se->ibuf);
 +      }
 +
 +      if(seq->flag & SEQ_USE_CROP || seq->flag & SEQ_USE_TRANSFORM) {
 +              StripCrop c;
 +              StripTransform t;
 +              int sx,sy,dx,dy;
 +
 +              memset(&c, 0, sizeof(StripCrop));
 +              memset(&t, 0, sizeof(StripTransform));
 +
 +              if(seq->flag & SEQ_USE_CROP && seq->strip->crop) {
 +                      c = *seq->strip->crop;
 +              }
 +              if(seq->flag & SEQ_USE_TRANSFORM && seq->strip->transform) {
 +                      t = *seq->strip->transform;
 +              }
 +
 +              sx = se->ibuf->x - c.left - c.right;
 +              sy = se->ibuf->y - c.top - c.bottom;
 +              dx = sx;
 +              dy = sy;
 +
 +              if (seq->flag & SEQ_USE_TRANSFORM) {
 +                      dx = scene->r.xsch;
 +                      dy = scene->r.ysch;
 +              }
 +
 +              if (c.top + c.bottom >= se->ibuf->y ||
 +                  c.left + c.right >= se->ibuf->x ||
 +                  t.xofs >= dx || t.yofs >= dy) {
 +                      make_black_ibuf(se->ibuf);
 +              } else {
 +                      ImBuf * i;
 +
 +                      if (se->ibuf->rect_float) {
 +                              i = IMB_allocImBuf(dx, dy,32, IB_rectfloat, 0);
 +                      } else {
 +                              i = IMB_allocImBuf(dx, dy,32, IB_rect, 0);
 +                      }
 +
 +                      IMB_rectcpy(i, se->ibuf, 
 +                                  t.xofs, t.yofs, 
 +                                  c.left, c.bottom, 
 +                                  sx, sy);
 +
 +                      IMB_freeImBuf(se->ibuf);
 +
 +                      se->ibuf = i;
 +              }
 +      } 
 +
 +      if(seq->flag & SEQ_FLIPX) {
 +              IMB_flipx(se->ibuf);
 +      }
 +      if(seq->flag & SEQ_FLIPY) {
 +              IMB_flipy(se->ibuf);
 +      }
 +
 +      if(seq->mul == 0.0) {
 +              seq->mul = 1.0;
 +      }
 +
 +      mul = seq->mul;
 +
 +      if(seq->blend_mode == SEQ_BLEND_REPLACE) {
 +#if 0 // XXX old animation system
 +              if (seq->ipo && seq->ipo->curve.first) {
 +                      do_seq_ipo(scene, seq, cfra);
 +                      mul *= seq->facf0;
 +              }
 +#endif // XXX old animation system
 +              mul *= seq->blend_opacity / 100.0;
 +      }
 +
 +      if(seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) {
 +              color_balance(seq, se, mul);
 +              mul = 1.0;
 +      }
 +
 +      if(seq->flag & SEQ_MAKE_FLOAT) {
 +              if (!se->ibuf->rect_float) {
 +                      IMB_float_from_rect(se->ibuf);
 +              }
 +              if (se->ibuf->rect) {
 +                      imb_freerectImBuf(se->ibuf);
 +              }
 +      }
 +
 +      if(mul != 1.0) {
 +              multibuf(se->ibuf, mul);
 +      }
 +
 +      if(seq->flag & SEQ_MAKE_PREMUL) {
 +              if(se->ibuf->depth == 32 && se->ibuf->zbuf == 0) {
 +                      converttopremul(se->ibuf);
 +              }
 +      }
 +
 +
 +      if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) {
 +              if(scene->r.mode & R_OSA) {
 +                      IMB_scaleImBuf(se->ibuf, 
 +                                     (short)seqrectx, (short)seqrecty);
 +              } else {
 +                      IMB_scalefastImBuf(se->ibuf, 
 +                                         (short)seqrectx, (short)seqrecty);
 +              }
 +      }
 +}
 +
 +/* test if image too small or discarded from cache: reload */
 +
 +static void test_and_auto_discard_ibuf(TStripElem * se)
 +{
 +      if (se->ibuf) {
 +              if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty 
 +                 || !(se->ibuf->rect || se->ibuf->rect_float)) {
 +                      IMB_freeImBuf(se->ibuf);
 +
 +                      se->ibuf= 0;
 +                      se->ok= STRIPELEM_OK;
 +              }
 +      }
 +      if (se->ibuf_comp) {
 +              if(se->ibuf_comp->x != seqrectx || se->ibuf_comp->y != seqrecty 
 +                 || !(se->ibuf_comp->rect || se->ibuf_comp->rect_float)) {
 +                      IMB_freeImBuf(se->ibuf_comp);
 +
 +                      se->ibuf_comp = 0;
 +              }
 +      }
 +}
 +
 +static void test_and_auto_discard_ibuf_stills(Strip * strip)
 +{
 +      if (strip->ibuf_startstill) {
 +              if (!strip->ibuf_startstill->rect &&
 +                  !strip->ibuf_startstill->rect_float) {
 +                      IMB_freeImBuf(strip->ibuf_startstill);
 +                      strip->ibuf_startstill = 0;
 +              }
 +      }
 +      if (strip->ibuf_endstill) {
 +              if (!strip->ibuf_endstill->rect &&
 +                  !strip->ibuf_endstill->rect_float) {
 +                      IMB_freeImBuf(strip->ibuf_endstill);
 +                      strip->ibuf_endstill = 0;
 +              }
 +      }
 +}
 +
 +static void copy_from_ibuf_still(Sequence * seq, TStripElem * se)
 +{
 +      if (!se->ibuf) {
 +              if (se->nr == 0 && seq->strip->ibuf_startstill) {
 +                      IMB_cache_limiter_touch(seq->strip->ibuf_startstill);
 +
 +                      se->ibuf = IMB_dupImBuf(seq->strip->ibuf_startstill);
 +              }
 +              if (se->nr == seq->len - 1 
 +                  && (seq->len != 1)
 +                  && seq->strip->ibuf_endstill) {
 +                      IMB_cache_limiter_touch(seq->strip->ibuf_endstill);
 +
 +                      se->ibuf = IMB_dupImBuf(seq->strip->ibuf_endstill);
 +              }
 +      }
 +}
 +
 +static void copy_to_ibuf_still(Sequence * seq, TStripElem * se)
 +{
 +      if (se->ibuf) {
 +              if (se->nr == 0) {
 +                      seq->strip->ibuf_startstill = IMB_dupImBuf(se->ibuf);
 +
 +                      IMB_cache_limiter_insert(seq->strip->ibuf_startstill);
 +                      IMB_cache_limiter_touch(seq->strip->ibuf_startstill);
 +              }
 +              if (se->nr == seq->len - 1 && seq->len != 1) {
 +                      seq->strip->ibuf_endstill = IMB_dupImBuf(se->ibuf);
 +
 +                      IMB_cache_limiter_insert(seq->strip->ibuf_endstill);
 +                      IMB_cache_limiter_touch(seq->strip->ibuf_endstill);
 +              }
 +      }
 +}
 +
 +static void free_metastrip_imbufs(ListBase *seqbasep, int cfra, int chanshown)
 +{
 +      Sequence* seq_arr[MAXSEQ+1];
 +      int i;
 +      TStripElem* se = 0;
 +
 +      evaluate_seq_frame_gen(seq_arr, seqbasep, cfra);
 +
 +      for (i = 0; i < MAXSEQ; i++) {
 +              if (!video_seq_is_rendered(seq_arr[i])) {
 +                      continue;
 +              }
 +              se = give_tstripelem(seq_arr[i], cfra);
 +              if (se) {
 +                      if (se->ibuf) {
 +                              IMB_freeImBuf(se->ibuf);
 +
 +                              se->ibuf= 0;
 +                              se->ok= STRIPELEM_OK;
 +                      }
 +
 +                      if (se->ibuf_comp) {
 +                              IMB_freeImBuf(se->ibuf_comp);
 +
 +                              se->ibuf_comp = 0;
 +                      }
 +              }
 +      }
 +      
 +}
 +
 +static void check_limiter_refcount(const char * func, TStripElem *se)
 +{
 +      if (se && se->ibuf) {
 +              int refcount = IMB_cache_limiter_get_refcount(se->ibuf);
 +              if (refcount != 1) {
 +                      /* can happen on complex pipelines */
 +                      if (refcount > 1 && (G.f & G_DEBUG) == 0) {
 +                              return;
 +                      }
 + 
 +                      fprintf(stderr, 
 +                              "sequencer: (ibuf) %s: "
 +                              "suspicious memcache "
 +                              "limiter refcount: %d\n", func, refcount);
 +              }
 +      }
 +}
 + 
 +static void check_limiter_refcount_comp(const char * func, TStripElem *se)
 +{
 +      if (se && se->ibuf_comp) {
 +              int refcount = IMB_cache_limiter_get_refcount(se->ibuf_comp);
 +              if (refcount != 1) {
 +                      /* can happen on complex pipelines */
 +                      if (refcount > 1 && (G.f & G_DEBUG) == 0) {
 +                              return;
 +                      }
 +                      fprintf(stderr, 
 +                              "sequencer: (ibuf comp) %s: "
 +                              "suspicious memcache "
 +                              "limiter refcount: %d\n", func, refcount);
 +              }
 +      }
 +}
 +
 +static TStripElem* do_build_seq_array_recursively(Scene *scene,
 +                              ListBase *seqbasep, int cfra, int chanshown, int render_size);
 +
 +static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra,
 +                            int build_proxy_run, int render_size)
 +{
 +      char name[FILE_MAXDIR+FILE_MAXFILE];
 +      int use_limiter = TRUE;
 +
 +      test_and_auto_discard_ibuf(se);
 +      test_and_auto_discard_ibuf_stills(seq->strip);
 +
 +      if(seq->type == SEQ_META) {
 +              TStripElem * meta_se = 0;
 +              int use_preprocess = FALSE;
 +              use_limiter = FALSE;
 +
 +              if (!build_proxy_run && se->ibuf == 0) {
 +                      se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
 +                      if (se->ibuf) {
 +                              use_limiter = TRUE;
 +                              use_preprocess = TRUE;
 +                      }
 +              }
 +
 +              if(!se->ibuf && seq->seqbase.first) {
 +                      meta_se = do_build_seq_array_recursively(scene,
 +                              &seq->seqbase, seq->start + se->nr, 0,
 +                              render_size);
 +
 +                      check_limiter_refcount("do_build_seq_ibuf: for META", meta_se);
 +              }
 +
 +              se->ok = STRIPELEM_OK;
 +
 +              if(!se->ibuf && meta_se) {
 +                      se->ibuf = meta_se->ibuf_comp;
 +                      if(se->ibuf &&
 +                         (!input_have_to_preprocess(scene, seq, se, cfra) ||
 +                          build_proxy_run)) {
 +                              IMB_refImBuf(se->ibuf);
 +                              if (build_proxy_run) {
 +                                      IMB_cache_limiter_unref(se->ibuf);
 +                              }
 +                      } else if (se->ibuf) {
 +                              struct ImBuf * i = IMB_dupImBuf(se->ibuf);
 +
 +                              IMB_cache_limiter_unref(se->ibuf);
 +
 +                              se->ibuf = i;
 +
 +                              use_limiter = TRUE;
 +                              use_preprocess = TRUE;
 +                      }
 +              } else if (se->ibuf) {
 +                      use_limiter = TRUE;
 +              }
 +              if (meta_se) {
 +                      free_metastrip_imbufs(
 +                              &seq->seqbase, seq->start + se->nr, 0);
 +              }
 +
 +              if (use_preprocess) {
 +                      input_preprocess(scene, seq, se, cfra);
 +              }
 +      } else if(seq->type & SEQ_EFFECT) {
++              int use_preprocess = FALSE;
 +              /* should the effect be recalculated? */
 +              
 +              if (!build_proxy_run && se->ibuf == 0) {
 +                      se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
++                      if (se->ibuf) {
++                              use_preprocess = TRUE;
++                      }
 +              }
 +
 +              if(se->ibuf == 0) {
 +                      /* if any inputs are rectfloat, output is float too */
 +                      if((se->se1 && se->se1->ibuf && se->se1->ibuf->rect_float) ||
 +                         (se->se2 && se->se2->ibuf && se->se2->ibuf->rect_float) ||
 +                         (se->se3 && se->se3->ibuf && se->se3->ibuf->rect_float))
 +                              se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
 +                      else
 +                              se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
 +                      
 +                      do_effect(scene, cfra, seq, se);
++                      if (input_have_to_preprocess(scene, seq, se, cfra) &&
++                          !build_proxy_run) {
++                              if ((se->se1 && (se->ibuf == se->se1->ibuf)) ||
++                                  (se->se2 && (se->ibuf == se->se2->ibuf))) {
++                                      struct ImBuf * i
++                                              = IMB_dupImBuf(se->ibuf);
++
++                                      IMB_freeImBuf(se->ibuf);
++
++                                      se->ibuf = i;
++                              }
++                              use_preprocess = TRUE;
++                      }
++              }
++              if (use_preprocess) {
++                      input_preprocess(scene, seq, se, cfra);
 +              }
 +      } else if(seq->type == SEQ_IMAGE) {
 +              if(se->ok == STRIPELEM_OK && se->ibuf == 0) {
 +                      StripElem * s_elem = give_stripelem(seq, cfra);
 +                      BLI_join_dirfile(name, seq->strip->dir, s_elem->name);
 +                      BLI_convertstringcode(name, G.sce);
 +                      BLI_convertstringframe(name, scene->r.cfra);
 +                      if (!build_proxy_run) {
 +                              se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
 +                      }
 +                      copy_from_ibuf_still(seq, se);
 +
 +                      if (!se->ibuf) {
 +                              se->ibuf= IMB_loadiffname(
 +                                      name, IB_rect);
 +                              /* we don't need both (speed reasons)! */
 +                              if (se->ibuf &&
 +                                      se->ibuf->rect_float && se->ibuf->rect) {
 +                                      imb_freerectImBuf(se->ibuf);
 +                              }
 +
 +                              copy_to_ibuf_still(seq, se);
 +                      }
 +                      
 +                      if(se->ibuf == 0) {
 +                              se->ok = STRIPELEM_FAILED;
 +                      } else if (!build_proxy_run) {
 +                              input_preprocess(scene, seq, se, cfra);
 +                      }
 +              }
 +      } else if(seq->type == SEQ_MOVIE) {
 +              if(se->ok == STRIPELEM_OK && se->ibuf==0) {
 +                      if(!build_proxy_run) {
 +                              se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
 +                      }
 +                      copy_from_ibuf_still(seq, se);
 +
 +                      if (se->ibuf == 0) {
 +                              if(seq->anim==0) {
 +                                      BLI_join_dirfile(name, seq->strip->dir, seq->strip->stripdata->name);
 +                                      BLI_convertstringcode(name, G.sce);
 +                                      BLI_convertstringframe(name, scene->r.cfra);
 +                                      
 +                                      seq->anim = openanim(
 +                                              name, IB_rect | 
 +                                              ((seq->flag & SEQ_FILTERY) 
 +                                               ? IB_animdeinterlace : 0));
 +                              }
 +                              if(seq->anim) {
 +                                      IMB_anim_set_preseek(seq->anim, seq->anim_preseek);
 +                                      se->ibuf = IMB_anim_absolute(seq->anim, se->nr + seq->anim_startofs);
 +                                      /* we don't need both (speed reasons)! */
 +                                      if (se->ibuf 
 +                                          && se->ibuf->rect_float 
 +                                          && se->ibuf->rect) {
 +                                              imb_freerectImBuf(se->ibuf);
 +                                      }
 +
 +                              }
 +                              copy_to_ibuf_still(seq, se);
 +                      }
 +                      
 +                      if(se->ibuf == 0) {
 +                              se->ok = STRIPELEM_FAILED;
 +                      } else if (!build_proxy_run) {
 +                              input_preprocess(scene, seq, se, cfra);
 +                      }
 +              }
 +      } else if(seq->type == SEQ_SCENE) {     // scene can be NULL after deletions
 +#if 0
 +              /* XXX move entirely to render? */
 +              int oldcfra = CFRA;
 +              Sequence * oldseq = get_last_seq();
 +              Scene *sce= seq->scene, *oldsce= scene;
 +              Render *re;
 +              RenderResult rres;
 +              int doseq, rendering= G.rendering;
 +              char scenename[64];
 +              int sce_valid =sce&& (sce->camera || sce->r.scemode & R_DOSEQ);
 +                      
 +              if (se->ibuf == NULL && sce_valid && !build_proxy_run) {
 +                      se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
 +                      if (se->ibuf) {
 +                              input_preprocess(scene, seq, se, cfra);
 +                      }
 +              }
 +
 +              if (se->ibuf == NULL && sce_valid) {
 +                      copy_from_ibuf_still(seq, se);
 +                      if (se->ibuf) {
 +                              input_preprocess(scene, seq, se, cfra);
 +                      }
 +              }
 +              
 +              if (!sce_valid) {
 +                      se->ok = STRIPELEM_FAILED;
 +              } else if (se->ibuf==NULL && sce_valid) {
 +                      /* no need to display a waitcursor on sequencer
 +                         scene strips */
 +                      if (!(sce->r.scemode & R_DOSEQ)) 
 +                              waitcursor(1);
 +                      
 +                      /* Hack! This function can be called from do_render_seq(), in that case
 +                         the seq->scene can already have a Render initialized with same name, 
 +                         so we have to use a default name. (compositor uses scene name to
 +                         find render).
 +                         However, when called from within the UI (image preview in sequencer)
 +                         we do want to use scene Render, that way the render result is defined
 +                         for display in render/imagewindow */
 +                      if(rendering) {
 +                              BLI_strncpy(scenename, sce->id.name+2, 64);
 +                              strcpy(sce->id.name+2, " do_build_seq_ibuf");
 +                      }
 +                      re= RE_NewRender(sce->id.name);
 +                      
 +                      /* prevent eternal loop */
 +                      doseq= scene->r.scemode & R_DOSEQ;
 +                      scene->r.scemode &= ~R_DOSEQ;
 +                      
 +                      BIF_init_render_callbacks(re, 0);       /* 0= no display callbacks */
 +                      
 +                      /* XXX hrms, set_scene still needed? work on that... */
 +                      if(sce!=oldsce) set_scene_bg(sce);
 +                      RE_BlenderFrame(re, sce,
 +                                      seq->sfra+se->nr+seq->anim_startofs);
 +                      if(sce!=oldsce) set_scene_bg(oldsce);
 +                      
 +                      /* UGLY WARNING, it is set to zero in  RE_BlenderFrame */
 +                      G.rendering= rendering;
 +                      if(rendering)
 +                              BLI_strncpy(sce->id.name+2, scenename, 64);
 +                      
 +                      RE_GetResultImage(re, &rres);
 +                      
 +                      if(rres.rectf) {
 +                              se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0);
 +                              memcpy(se->ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty);
 +                              if(rres.rectz) {
 +                                      addzbuffloatImBuf(se->ibuf);
 +                                      memcpy(se->ibuf->zbuf_float, rres.rectz, sizeof(float)*rres.rectx*rres.recty);
 +                              }
 +                      } else if (rres.rect32) {
 +                              se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect, 0);
 +                              memcpy(se->ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty);
 +                      }
 +                      
 +                      BIF_end_render_callbacks();
 +                      
 +                      /* restore */
 +                      scene->r.scemode |= doseq;
 +
 +                      // XXX
 +#if 0
 +                      if((G.f & G_PLAYANIM)==0 /* bad, is set on do_render_seq */
-       ibuf= give_ibuf_seq(scene, rr->rectx, rr->recty, cfra, 0, scene->r.size);
++                         && !(sce->r.scemode & R_DOSEQ)
++                         && !build_proxy_run) 
 +#endif
 +                      
 +                      CFRA = oldcfra;
 +                      set_last_seq(oldseq);
 +
 +                      copy_to_ibuf_still(seq, se);
 +
 +                      if (!build_proxy_run) {
 +                              if(se->ibuf == NULL) {
 +                                      se->ok = STRIPELEM_FAILED;
 +                              } else {
 +                                      input_preprocess(scene, seq, se, cfra);
 +                              }
 +                      }
 +
 +              }
 +#endif
 +      }
 +      if (!build_proxy_run) {
 +              if (se->ibuf && use_limiter) {
 +                      IMB_cache_limiter_insert(se->ibuf);
 +                      IMB_cache_limiter_ref(se->ibuf);
 +                      IMB_cache_limiter_touch(se->ibuf);
 +              }
 +      }
 +}
 +
 +static TStripElem* do_build_seq_recursively(Scene *scene, Sequence *seq, int cfra, int render_size);
 +
 +static void do_effect_seq_recursively(Scene *scene, Sequence *seq, TStripElem *se, int cfra, int render_size)
 +{
 +      float fac, facf;
 +      struct SeqEffectHandle sh = get_sequence_effect(seq);
 +      int early_out;
 +
 +      se->se1 = 0;
 +      se->se2 = 0;
 +      se->se3 = 0;
 +
 +#if 0 // XXX old animation system
 +      if(seq->ipo && seq->ipo->curve.first) {
 +              do_seq_ipo(scene, seq, cfra);
 +              fac= seq->facf0;
 +              facf= seq->facf1;
 +      } else 
 +#endif // XXX old animation system
 +      {
 +              sh.get_default_fac(seq, cfra, &fac, &facf);
 +      } 
 +
 +      if( scene->r.mode & R_FIELDS ); else facf= fac;
 +      
 +      early_out = sh.early_out(seq, fac, facf);
 +      switch (early_out) {
 +      case -1:
 +              /* no input needed */
 +              break;
 +      case 0:
 +              se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra, render_size);
 +              se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra, render_size);
 +              if (seq->seq3) {
 +                      se->se3 = do_build_seq_recursively(scene, seq->seq3, cfra, render_size);
 +              }
 +              break;
 +      case 1:
 +              se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra, render_size);
 +              break;
 +      case 2:
 +              se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra, render_size);
 +              break;
 +      }
 +
 +
 +      do_build_seq_ibuf(scene, seq, se, cfra, FALSE, render_size);
 +
 +      /* children are not needed anymore ... */
 +
 +      if (se->se1 && se->se1->ibuf) {
 +              IMB_cache_limiter_unref(se->se1->ibuf);
 +      }
 +      if (se->se2 && se->se2->ibuf) {
 +              IMB_cache_limiter_unref(se->se2->ibuf);
 +      }
 +      if (se->se3 && se->se3->ibuf) {
 +              IMB_cache_limiter_unref(se->se3->ibuf);
 +      }
 +      check_limiter_refcount("do_effect_seq_recursively", se);
 +}
 +
 +static TStripElem* do_build_seq_recursively_impl(Scene *scene, Sequence * seq, int cfra, int render_size)
 +{
 +      TStripElem *se;
 +
 +      se = give_tstripelem(seq, cfra);
 +
 +      if(se) {
 +              if (seq->type & SEQ_EFFECT) {
 +                      do_effect_seq_recursively(scene, seq, se, cfra, render_size);
 +              } else {
 +                      do_build_seq_ibuf(scene, seq, se, cfra, FALSE, render_size);
 +              }
 +      }
 +      return se;
 +}
 +
 +/* FIXME:
 +   
 +If cfra was float throughout blender (especially in the render
 +pipeline) one could even _render_ with subframe precision
 +instead of faking using the blend code below...
 +
 +*/
 +
 +static TStripElem* do_handle_speed_effect(Scene *scene, Sequence * seq, int cfra, int render_size)
 +{
 +      SpeedControlVars * s = (SpeedControlVars *)seq->effectdata;
 +      int nr = cfra - seq->start;
 +      float f_cfra;
 +      int cfra_left;
 +      int cfra_right;
 +      TStripElem * se = 0;
 +      TStripElem * se1 = 0;
 +      TStripElem * se2 = 0;
 +      
 +      sequence_effect_speed_rebuild_map(seq, 0);
 +      
 +      f_cfra = seq->start + s->frameMap[nr];
 +      
 +      cfra_left = (int) floor(f_cfra);
 +      cfra_right = (int) ceil(f_cfra);
 +
 +      se = give_tstripelem(seq, cfra);
 +
 +      if (!se) {
 +              return se;
 +      }
 +
 +      if (cfra_left == cfra_right || 
 +          (s->flags & SEQ_SPEED_BLEND) == 0) {
 +              test_and_auto_discard_ibuf(se);
 +
 +              if (se->ibuf == NULL) {
 +                      se1 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_left, render_size);
 +
 +                      if((se1 && se1->ibuf && se1->ibuf->rect_float))
 +                              se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
 +                      else
 +                              se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
 +
 +                      if (se1 == 0 || se1->ibuf == 0) {
 +                              make_black_ibuf(se->ibuf);
 +                      } else {
 +                              if (se->ibuf != se1->ibuf) {
 +                                      if (se->ibuf) {
 +                                              IMB_freeImBuf(se->ibuf);
 +                                      }
 +
 +                                      se->ibuf = se1->ibuf;
 +                                      IMB_refImBuf(se->ibuf);
 +                              }
 +                      }
 +              }
 +      } else {
 +              struct SeqEffectHandle sh;
 +
 +              if(se->ibuf) {
 +                      if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty 
 +                         || !(se->ibuf->rect || se->ibuf->rect_float)) {
 +                              IMB_freeImBuf(se->ibuf);
 +                              se->ibuf= 0;
 +                      }
 +              }
 +
 +              if (se->ibuf == NULL) {
 +                      se1 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_left, render_size);
 +                      se2 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_right, render_size);
 +
 +                      if((se1 && se1->ibuf && se1->ibuf->rect_float))
 +                              se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
 +                      else
 +                              se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
 +                      
 +                      if (!se1 || !se2) {
 +                              make_black_ibuf(se->ibuf);
 +                      } else {
 +                              sh = get_sequence_effect(seq);
 +
 +                              sh.execute(seq, cfra, 
 +                                         f_cfra - (float) cfra_left, 
 +                                         f_cfra - (float) cfra_left, 
 +                                         se->ibuf->x, se->ibuf->y, 
 +                                         se1->ibuf, se2->ibuf, 0, se->ibuf);
 +                      }
 +              }
 +
 +      }
 +
 +      /* caller expects this to be referenced, so do it! */
 +      if (se->ibuf) {
 +              IMB_cache_limiter_insert(se->ibuf);
 +              IMB_cache_limiter_ref(se->ibuf);
 +              IMB_cache_limiter_touch(se->ibuf);
 +      }
 +
 +      /* children are no longer needed */
 +      if (se1 && se1->ibuf)
 +              IMB_cache_limiter_unref(se1->ibuf);
 +      if (se2 && se2->ibuf)
 +              IMB_cache_limiter_unref(se2->ibuf);
 +
 +      check_limiter_refcount("do_handle_speed_effect", se);
 +
 +      return se;
 +}
 +
 +/* 
 + * build all ibufs recursively
 + * 
 + * if successfull, the returned TStripElem contains the (referenced!) imbuf
 + * that means: you _must_ call 
 + *
 + * IMB_cache_limiter_unref(rval);
 + * 
 + * if rval != 0
 + * 
 + */
 +
 +static TStripElem* do_build_seq_recursively(Scene *scene, Sequence * seq, int cfra, int render_size)
 +{
 +      TStripElem *se;
 +      if (seq->type == SEQ_SPEED) {
 +              se = do_handle_speed_effect(scene, seq, cfra, render_size);
 +      } else {
 +              se = do_build_seq_recursively_impl(scene, seq, cfra, render_size);
 +      }
 +
 +      check_limiter_refcount("do_build_seq_recursively", se);
 +
 +      return se;
 +}
 +
 +static TStripElem* do_build_seq_array_recursively(Scene *scene,
 +      ListBase *seqbasep, int cfra, int chanshown, int render_size)
 +{
 +      Sequence* seq_arr[MAXSEQ+1];
 +      int count;
 +      int i;
 +      TStripElem* se = 0;
 +
 +      count = get_shown_sequences(seqbasep, cfra, chanshown, (Sequence **)&seq_arr);
 +
 +      if (!count) {
 +              return 0;
 +      }
 +
 +      se = give_tstripelem(seq_arr[count - 1], cfra);
 +
 +      if (!se) {
 +              return 0;
 +      }
 +
 +      test_and_auto_discard_ibuf(se);
 +
 +      if (se->ibuf_comp != 0) {
 +              IMB_cache_limiter_insert(se->ibuf_comp);
 +              IMB_cache_limiter_ref(se->ibuf_comp);
 +              IMB_cache_limiter_touch(se->ibuf_comp);
 +              return se;
 +      }
 +
 +      
 +      if(count == 1) {
 +              se = do_build_seq_recursively(scene, seq_arr[0], cfra, render_size);
 +              if (se->ibuf) {
 +                      se->ibuf_comp = se->ibuf;
 +                      IMB_refImBuf(se->ibuf_comp);
 +              }
 +              return se;
 +      }
 +
 +
 +      for (i = count - 1; i >= 0; i--) {
 +              int early_out;
 +              Sequence * seq = seq_arr[i];
 +              struct SeqEffectHandle sh;
 +
 +              se = give_tstripelem(seq, cfra);
 +
 +              test_and_auto_discard_ibuf(se);
 +
 +              if (se->ibuf_comp != 0) {
 +                      break;
 +              }
 +              if (seq->blend_mode == SEQ_BLEND_REPLACE) {
 +                      do_build_seq_recursively(scene, seq, cfra, render_size);
 +                      if (se->ibuf) {
 +                              se->ibuf_comp = se->ibuf;
 +                              IMB_refImBuf(se->ibuf);
 +                      } else {
 +                              se->ibuf_comp = IMB_allocImBuf(
 +                                      (short)seqrectx, (short)seqrecty, 
 +                                      32, IB_rect, 0);
 +                              IMB_cache_limiter_insert(se->ibuf_comp);
 +                              IMB_cache_limiter_ref(se->ibuf_comp);
 +                              IMB_cache_limiter_touch(se->ibuf_comp);
 +                      }
 +                      break;
 +              }
 +
 +              sh = get_sequence_blend(seq);
 +
 +              seq->facf0 = seq->facf1 = 1.0;
 +
 +#if 0 // XXX old animation system
 +              if(seq->ipo && seq->ipo->curve.first) {
 +                      do_seq_ipo(scene, seq, cfra);
 +              } 
 +#endif
 +
 +              if( scene->r.mode & R_FIELDS ); else seq->facf0 = seq->facf1;
 +
 +              seq->facf0 *= seq->blend_opacity / 100.0;
 +              seq->facf1 *= seq->blend_opacity / 100.0;
 +
 +              early_out = sh.early_out(seq, seq->facf0, seq->facf1);
 +
 +              switch (early_out) {
 +              case -1:
 +              case 2:
 +                      do_build_seq_recursively(scene, seq, cfra, render_size);
 +                      if (se->ibuf) {
 +                              se->ibuf_comp = se->ibuf;
 +                              IMB_refImBuf(se->ibuf_comp);
 +                      } else {
 +                              se->ibuf_comp = IMB_allocImBuf(
 +                                      (short)seqrectx, (short)seqrecty, 
 +                                      32, IB_rect, 0);
 +                              IMB_cache_limiter_insert(se->ibuf_comp);
 +                              IMB_cache_limiter_ref(se->ibuf_comp);
 +                              IMB_cache_limiter_touch(se->ibuf_comp);
 +                      }
 +                      break;
 +              case 1:
 +                      if (i == 0) {
 +                              se->ibuf_comp = IMB_allocImBuf(
 +                                      (short)seqrectx, (short)seqrecty, 
 +                                      32, IB_rect, 0);
 +                              IMB_cache_limiter_insert(se->ibuf_comp);
 +                              IMB_cache_limiter_ref(se->ibuf_comp);
 +                              IMB_cache_limiter_touch(se->ibuf_comp);
 +                      }
 +                      break;
 +              case 0:
 +                      do_build_seq_recursively(scene, seq, cfra, render_size);
 +                      if (!se->ibuf) {
 +                              se->ibuf = IMB_allocImBuf(
 +                                      (short)seqrectx, (short)seqrecty, 
 +                                      32, IB_rect, 0);
 +                              IMB_cache_limiter_insert(se->ibuf);
 +                              IMB_cache_limiter_ref(se->ibuf);
 +                              IMB_cache_limiter_touch(se->ibuf);
 +                      }
 +                      if (i == 0) {
 +                              se->ibuf_comp = se->ibuf;
 +                              IMB_refImBuf(se->ibuf_comp);
 +                      }
 +                      break;
 +              }
 +      
 +              if (se->ibuf_comp) {
 +                      break;
 +              }
 +      }
 +
 +      i++;
 +
 +      for (; i < count; i++) {
 +              Sequence * seq = seq_arr[i];
 +              struct SeqEffectHandle sh = get_sequence_blend(seq);
 +              TStripElem* se1 = give_tstripelem(seq_arr[i-1], cfra);
 +              TStripElem* se2 = give_tstripelem(seq_arr[i], cfra);
 +      
 +              int early_out = sh.early_out(seq, seq->facf0, seq->facf1);
 +              switch (early_out) {
 +              case 0: {
 +                      int x= se2->ibuf->x;
 +                      int y= se2->ibuf->y;
 +                      int swap_input = FALSE;
 +
 +                      if (se1->ibuf_comp->rect_float ||
 +                          se2->ibuf->rect_float) {
 +                              se2->ibuf_comp = IMB_allocImBuf(
 +                                      (short)seqrectx, (short)seqrecty, 
 +                                      32, IB_rectfloat, 0);
 +                      } else {
 +                              se2->ibuf_comp = IMB_allocImBuf(
 +                                      (short)seqrectx, (short)seqrecty, 
 +                                      32, IB_rect, 0);
 +                      }
 +
 +
 +                      if (!se1->ibuf_comp->rect_float && 
 +                          se2->ibuf_comp->rect_float) {
 +                              IMB_float_from_rect(se1->ibuf_comp);
 +                      }
 +                      if (!se2->ibuf->rect_float && 
 +                          se2->ibuf_comp->rect_float) {
 +                              IMB_float_from_rect(se2->ibuf);
 +                      }
 +
 +                      if (!se1->ibuf_comp->rect && 
 +                          !se2->ibuf_comp->rect_float) {
 +                              IMB_rect_from_float(se1->ibuf_comp);
 +                      }
 +                      if (!se2->ibuf->rect && 
 +                          !se2->ibuf_comp->rect_float) {
 +                              IMB_rect_from_float(se2->ibuf);
 +                      }
 +                      
 +                      /* bad hack, to fix crazy input ordering of 
 +                         those two effects */
 +
 +                      if (seq->blend_mode == SEQ_ALPHAOVER ||
 +                          seq->blend_mode == SEQ_ALPHAUNDER ||
 +                          seq->blend_mode == SEQ_OVERDROP) {
 +                              swap_input = TRUE;
 +                      }
 +
 +                      if (swap_input) {
 +                              sh.execute(seq, cfra, 
 +                                         seq->facf0, seq->facf1, x, y, 
 +                                         se2->ibuf, se1->ibuf_comp, 0,
 +                                         se2->ibuf_comp);
 +                      } else {
 +                              sh.execute(seq, cfra, 
 +                                         seq->facf0, seq->facf1, x, y, 
 +                                         se1->ibuf_comp, se2->ibuf, 0,
 +                                         se2->ibuf_comp);
 +                      }
 +                      
 +                      IMB_cache_limiter_insert(se2->ibuf_comp);
 +                      IMB_cache_limiter_ref(se2->ibuf_comp);
 +                      IMB_cache_limiter_touch(se2->ibuf_comp);
 +
 +                      IMB_cache_limiter_unref(se1->ibuf_comp);
 +                      IMB_cache_limiter_unref(se2->ibuf);
 +
 +                      break;
 +              }
 +              case 1: {
 +                      se2->ibuf_comp = se1->ibuf;
 +                      IMB_refImBuf(se2->ibuf_comp);
 +
 +                      break;
 +              }
 +              }
 +              se = se2;
 +      }
 +
 +      return se;
 +}
 +
 +/*
 + * returned ImBuf is refed!
 + * you have to unref after usage!
 + */
 +
 +static ImBuf *give_ibuf_seq_impl(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size)
 +{
 +      Editing *ed= seq_give_editing(scene, FALSE);
 +      int count;
 +      ListBase *seqbasep;
 +      TStripElem *se;
 +
 +      
 +      if(ed==NULL) return NULL;
 +
 +      count = BLI_countlist(&ed->metastack);
 +      if((chanshown < 0) && (count > 0)) {
 +              count = MAX2(count + chanshown, 0);
 +              seqbasep= ((MetaStack*)BLI_findlink(&ed->metastack, count))->oldbasep;
 +      } else {
 +              seqbasep= ed->seqbasep;
 +      }
 +
 +      seqrectx= rectx;        /* bad bad global! */
 +      seqrecty= recty;
 +
 +      se = do_build_seq_array_recursively(scene, seqbasep, cfra, chanshown, render_size);
 +
 +      if(!se) { 
 +              return 0;
 +      }
 +
 +      check_limiter_refcount_comp("give_ibuf_seq_impl", se);
 +
 +      return se->ibuf_comp;
 +}
 +
 +ImBuf *give_ibuf_seq_direct(Scene *scene, int rectx, int recty, int cfra, int render_size, Sequence *seq)
 +{
 +      TStripElem* se;
 +
 +      seqrectx= rectx;        /* bad bad global! */
 +      seqrecty= recty;
 +
 +      se = do_build_seq_recursively(scene, seq, cfra, render_size);
 +
 +      if(!se) { 
 +              return 0;
 +      }
 +
 +      check_limiter_refcount("give_ibuf_seq_direct", se);
 +
 +      if (se->ibuf) {
 +              IMB_cache_limiter_unref(se->ibuf);
 +      }
 +
 +      return se->ibuf;
 +}
 +
 +ImBuf *give_ibuf_seq(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size)
 +{
 +      ImBuf* i = give_ibuf_seq_impl(scene, rectx, recty, cfra, chanshown, render_size);
 +
 +      if (i) {
 +              IMB_cache_limiter_unref(i);
 +      }
 +      return i;
 +}
 +
 +/* check used when we need to change seq->blend_mode but not to effect or audio strips */
 +int seq_can_blend(Sequence *seq)
 +{
 +      if (ELEM4(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE)) {
 +              return 1;
 +      } else {
 +              return 0;
 +      }
 +}
 +
 +/* *********************** threading api ******************* */
 +
 +static ListBase running_threads;
 +static ListBase prefetch_wait;
 +static ListBase prefetch_done;
 +
 +static pthread_mutex_t queue_lock          = PTHREAD_MUTEX_INITIALIZER;
 +static pthread_mutex_t wakeup_lock         = PTHREAD_MUTEX_INITIALIZER;
 +static pthread_cond_t  wakeup_cond         = PTHREAD_COND_INITIALIZER;
 +
 +static pthread_mutex_t prefetch_ready_lock = PTHREAD_MUTEX_INITIALIZER;
 +static pthread_cond_t  prefetch_ready_cond = PTHREAD_COND_INITIALIZER;
 +
 +static pthread_mutex_t frame_done_lock     = PTHREAD_MUTEX_INITIALIZER;
 +static pthread_cond_t  frame_done_cond     = PTHREAD_COND_INITIALIZER;
 +
 +static volatile int seq_thread_shutdown = FALSE;
 +static volatile int seq_last_given_monoton_cfra = 0;
 +static int monoton_cfra = 0;
 +
 +typedef struct PrefetchThread {
 +      struct PrefetchThread *next, *prev;
 +      
 +      Scene *scene;
 +      struct PrefetchQueueElem *current;
 +      pthread_t pthread;
 +      int running;
 +      
 +} PrefetchThread;
 +
 +typedef struct PrefetchQueueElem {
 +      struct PrefetchQueueElem *next, *prev;
 +      
 +      int rectx;
 +      int recty;
 +      int cfra;
 +      int chanshown;
 +      int render_size;
 +
 +      int monoton_cfra;
 +
 +      struct ImBuf * ibuf;
 +} PrefetchQueueElem;
 +
 +static void *seq_prefetch_thread(void * This_)
 +{
 +      PrefetchThread * This = This_;
 +
 +      while (!seq_thread_shutdown) {
 +              PrefetchQueueElem *e;
 +              int s_last;
 +
 +              pthread_mutex_lock(&queue_lock);
 +              e = prefetch_wait.first;
 +              if (e) {
 +                      BLI_remlink(&prefetch_wait, e);
 +              }
 +              s_last = seq_last_given_monoton_cfra;
 +
 +              This->current = e;
 +
 +              pthread_mutex_unlock(&queue_lock);
 +
 +              if (!e) {
 +                      pthread_mutex_lock(&prefetch_ready_lock);
 +
 +                      This->running = FALSE;
 +
 +                      pthread_cond_signal(&prefetch_ready_cond);
 +                      pthread_mutex_unlock(&prefetch_ready_lock);
 +
 +                      pthread_mutex_lock(&wakeup_lock);
 +                      if (!seq_thread_shutdown) {
 +                              pthread_cond_wait(&wakeup_cond, &wakeup_lock);
 +                      }
 +                      pthread_mutex_unlock(&wakeup_lock);
 +                      continue;
 +              }
 +
 +              This->running = TRUE;
 +              
 +              if (e->cfra >= s_last) { 
 +                      e->ibuf = give_ibuf_seq_impl(This->scene, 
 +                              e->rectx, e->recty, e->cfra, e->chanshown,
 +                              e->render_size);
 +              }
 +
 +              pthread_mutex_lock(&queue_lock);
 +
 +              BLI_addtail(&prefetch_done, e);
 +
 +              for (e = prefetch_wait.first; e; e = e->next) {
 +                      if (s_last > e->monoton_cfra) {
 +                              BLI_remlink(&prefetch_wait, e);
 +                              MEM_freeN(e);
 +                      }
 +              }
 +
 +              for (e = prefetch_done.first; e; e = e->next) {
 +                      if (s_last > e->monoton_cfra) {
 +                              if (e->ibuf) {
 +                                      IMB_cache_limiter_unref(e->ibuf);
 +                              }
 +                              BLI_remlink(&prefetch_done, e);
 +                              MEM_freeN(e);
 +                      }
 +              }
 +
 +              pthread_mutex_unlock(&queue_lock);
 +
 +              pthread_mutex_lock(&frame_done_lock);
 +              pthread_cond_signal(&frame_done_cond);
 +              pthread_mutex_unlock(&frame_done_lock);
 +      }
 +      return 0;
 +}
 +
 +void seq_start_threads(Scene *scene)
 +{
 +      int i;
 +
 +      running_threads.first = running_threads.last = NULL;
 +      prefetch_wait.first = prefetch_wait.last = NULL;
 +      prefetch_done.first = prefetch_done.last = NULL;
 +
 +      seq_thread_shutdown = FALSE;
 +      seq_last_given_monoton_cfra = monoton_cfra = 0;
 +
 +      /* since global structures are modified during the processing
 +         of one frame, only one render thread is currently possible... 
 +
 +         (but we code, in the hope, that we can remove this restriction
 +         soon...)
 +      */
 +
 +      fprintf(stderr, "SEQ-THREAD: seq_start_threads\n");
 +
 +      for (i = 0; i < 1; i++) {
 +              PrefetchThread *t = MEM_callocN(sizeof(PrefetchThread), "prefetch_thread");
 +              t->scene= scene;
 +              t->running = TRUE;
 +              BLI_addtail(&running_threads, t);
 +
 +              pthread_create(&t->pthread, NULL, seq_prefetch_thread, t);
 +      }
 +
 +      /* init malloc mutex */
 +      BLI_init_threads(0, 0, 0);
 +}
 +
 +void seq_stop_threads()
 +{
 +      PrefetchThread *tslot;
 +      PrefetchQueueElem *e;
 +
 +      fprintf(stderr, "SEQ-THREAD: seq_stop_threads()\n");
 +
 +      if (seq_thread_shutdown) {
 +              fprintf(stderr, "SEQ-THREAD: ... already stopped\n");
 +              return;
 +      }
 +      
 +      pthread_mutex_lock(&wakeup_lock);
 +
 +      seq_thread_shutdown = TRUE;
 +
 +        pthread_cond_broadcast(&wakeup_cond);
 +        pthread_mutex_unlock(&wakeup_lock);
 +
 +      for(tslot = running_threads.first; tslot; tslot= tslot->next) {
 +              pthread_join(tslot->pthread, NULL);
 +      }
 +
 +
 +      for (e = prefetch_wait.first; e; e = e->next) {
 +              BLI_remlink(&prefetch_wait, e);
 +              MEM_freeN(e);
 +      }
 +
 +      for (e = prefetch_done.first; e; e = e->next) {
 +              if (e->ibuf) {
 +                      IMB_cache_limiter_unref(e->ibuf);
 +              }
 +              BLI_remlink(&prefetch_done, e);
 +              MEM_freeN(e);
 +      }
 +
 +      BLI_freelistN(&running_threads);
 +
 +      /* deinit malloc mutex */
 +      BLI_end_threads(0);
 +}
 +
 +void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown,
 +                              int render_size)
 +{
 +      PrefetchQueueElem *e;
 +      if (seq_thread_shutdown) {
 +              return;
 +      }
 +
 +      e = MEM_callocN(sizeof(PrefetchQueueElem), "prefetch_queue_elem");
 +      e->rectx = rectx;
 +      e->recty = recty;
 +      e->cfra = cfra;
 +      e->chanshown = chanshown;
 +      e->render_size = render_size;
 +      e->monoton_cfra = monoton_cfra++;
 +
 +      pthread_mutex_lock(&queue_lock);
 +      BLI_addtail(&prefetch_wait, e);
 +      pthread_mutex_unlock(&queue_lock);
 +      
 +      pthread_mutex_lock(&wakeup_lock);
 +      pthread_cond_signal(&wakeup_cond);
 +      pthread_mutex_unlock(&wakeup_lock);
 +}
 +
 +void seq_wait_for_prefetch_ready()
 +{
 +      PrefetchThread *tslot;
 +
 +      if (seq_thread_shutdown) {
 +              return;
 +      }
 +
 +      fprintf(stderr, "SEQ-THREAD: rendering prefetch frames...\n");
 +
 +      pthread_mutex_lock(&prefetch_ready_lock);
 +
 +      for(;;) {
 +              for(tslot = running_threads.first; tslot; tslot= tslot->next) {
 +                      if (tslot->running) {
 +                              break;
 +                      }
 +              }
 +              if (!tslot) {
 +                      break;
 +              }
 +              pthread_cond_wait(&prefetch_ready_cond, &prefetch_ready_lock);
 +      }
 +
 +      pthread_mutex_unlock(&prefetch_ready_lock);
 +
 +      fprintf(stderr, "SEQ-THREAD: prefetch done\n");
 +}
 +
 +ImBuf *give_ibuf_seq_threaded(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size)
 +{
 +      PrefetchQueueElem *e = NULL;
 +      int found_something = FALSE;
 +
 +      if (seq_thread_shutdown) {
 +              return give_ibuf_seq(scene, rectx, recty, cfra, chanshown, render_size);
 +      }
 +
 +      while (!e) {
 +              int success = FALSE;
 +              pthread_mutex_lock(&queue_lock);
 +
 +              for (e = prefetch_done.first; e; e = e->next) {
 +                      if (cfra == e->cfra &&
 +                          chanshown == e->chanshown &&
 +                          rectx == e->rectx && 
 +                          recty == e->recty &&
 +                          render_size == e->render_size) {
 +                              success = TRUE;
 +                              found_something = TRUE;
 +                              break;
 +                      }
 +              }
 +
 +              if (!e) {
 +                      for (e = prefetch_wait.first; e; e = e->next) {
 +                              if (cfra == e->cfra &&
 +                                  chanshown == e->chanshown &&
 +                                  rectx == e->rectx && 
 +                                  recty == e->recty &&
 +                                  render_size == e->render_size) {
 +                                      found_something = TRUE;
 +                                      break;
 +                              }
 +                      }
 +              }
 +
 +              if (!e) {
 +                      PrefetchThread *tslot;
 +
 +                      for(tslot = running_threads.first; 
 +                          tslot; tslot= tslot->next) {
 +                              if (tslot->current &&
 +                                  cfra == tslot->current->cfra &&
 +                                  chanshown == tslot->current->chanshown &&
 +                                  rectx == tslot->current->rectx && 
 +                                  recty == tslot->current->recty &&
 +                                  render_size== tslot->current->render_size){
 +                                      found_something = TRUE;
 +                                      break;
 +                              }
 +                      }
 +              }
 +
 +              /* e->ibuf is unrefed by render thread on next round. */
 +
 +              if (e) {
 +                      seq_last_given_monoton_cfra = e->monoton_cfra;
 +              }
 +
 +              pthread_mutex_unlock(&queue_lock);
 +
 +              if (!success) {
 +                      e = NULL;
 +
 +                      if (!found_something) {
 +                              fprintf(stderr, 
 +                                      "SEQ-THREAD: Requested frame "
 +                                      "not in queue ???\n");
 +                              break;
 +                      }
 +                      pthread_mutex_lock(&frame_done_lock);
 +                      pthread_cond_wait(&frame_done_cond, &frame_done_lock);
 +                      pthread_mutex_unlock(&frame_done_lock);
 +              }
 +      }
 +      
 +      return e ? e->ibuf : 0;
 +}
 +
 +/* Functions to free imbuf and anim data on changes */
 +
 +static void free_imbuf_strip_elem(TStripElem *se)
 +{
 +      if(se->ibuf) {
 +              IMB_freeImBuf(se->ibuf);
 +      }
 +      if(se->ibuf_comp) {
 +              IMB_freeImBuf(se->ibuf_comp);
 +      }
 +      se->ibuf_comp = 0;
 +      se->ibuf= 0;
 +      se->ok= STRIPELEM_OK;
 +      se->se1= se->se2= se->se3= 0;
 +}
 +
 +static void free_anim_seq(Sequence *seq)
 +{
 +      if(seq->anim) {
 +              IMB_free_anim(seq->anim);
 +              seq->anim = 0;
 +      }
 +}
 +
 +void free_imbuf_seq_except(Scene *scene, int cfra)
 +{
 +      Editing *ed= seq_give_editing(scene, FALSE);
 +      Sequence *seq;
 +      TStripElem *se;
 +      int a;
 +
 +      if(ed==NULL) return;
 +
 +      SEQ_BEGIN(ed, seq) {
 +              if(seq->strip) {
 +                      TStripElem * curelem = give_tstripelem(seq, cfra);
 +
 +                      for(a = 0, se = seq->strip->tstripdata; 
 +                          a < seq->strip->len && se; a++, se++) {
 +                              if(se != curelem) {
 +                                      free_imbuf_strip_elem(se);
 +                              }
 +                      }
 +                      for(a = 0, se = seq->strip->tstripdata_startstill;
 +                          a < seq->strip->startstill && se; a++, se++) {
 +                              if(se != curelem) {
 +                                      free_imbuf_strip_elem(se);
 +                              }
 +                      }
 +                      for(a = 0, se = seq->strip->tstripdata_endstill;
 +                          a < seq->strip->endstill && se; a++, se++) {
 +                              if(se != curelem) {
 +                                      free_imbuf_strip_elem(se);
 +                              }
 +                      }
 +                      if(seq->strip->ibuf_startstill) {
 +                              IMB_freeImBuf(seq->strip->ibuf_startstill);
 +                              seq->strip->ibuf_startstill = 0;
 +                      }
 +
 +                      if(seq->strip->ibuf_endstill) {
 +                              IMB_freeImBuf(seq->strip->ibuf_endstill);
 +                              seq->strip->ibuf_endstill = 0;
 +                      }
 +
 +                      if(seq->type==SEQ_MOVIE)
 +                              if(seq->startdisp > cfra || seq->enddisp < cfra)
 +                                      free_anim_seq(seq);
 +                      free_proxy_seq(seq);
 +              }
 +      }
 +      SEQ_END
 +}
 +
 +void free_imbuf_seq(ListBase * seqbase)
 +{
 +      Sequence *seq;
 +      TStripElem *se;
 +      int a;
 +      
 +      for(seq= seqbase->first; seq; seq= seq->next) {
 +              if(seq->strip) {
 +                      for(a = 0, se = seq->strip->tstripdata; 
 +                          a < seq->strip->len && se; a++, se++) {
 +                              free_imbuf_strip_elem(se);
 +                      }
 +                      for(a = 0, se = seq->strip->tstripdata_startstill; 
 +                          a < seq->strip->startstill && se; a++, se++) {
 +                              free_imbuf_strip_elem(se);
 +                      }
 +                      for(a = 0, se = seq->strip->tstripdata_endstill; 
 +                          a < seq->strip->endstill && se; a++, se++) {
 +                              free_imbuf_strip_elem(se);
 +                      }
 +                      if(seq->strip->ibuf_startstill) {
 +                              IMB_freeImBuf(seq->strip->ibuf_startstill);
 +                              seq->strip->ibuf_startstill = 0;
 +                      }
 +
 +                      if(seq->strip->ibuf_endstill) {
 +                              IMB_freeImBuf(seq->strip->ibuf_endstill);
 +                              seq->strip->ibuf_endstill = 0;
 +                      }
 +
 +                      if(seq->type==SEQ_MOVIE)
 +                              free_anim_seq(seq);
 +                      if(seq->type==SEQ_SPEED) {
 +                              sequence_effect_speed_rebuild_map(seq, 1);
 +                      }
 +              }
 +              if(seq->type==SEQ_META) {
 +                      free_imbuf_seq(&seq->seqbase);
 +              }
 +      }
 +      
 +}
 +
 +static int update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *changed_seq, int len_change, int ibuf_change)
 +{
 +      Sequence *subseq;
 +      int a, free_imbuf = 0;
 +      TStripElem *se;
 +      
 +      /* recurs downwards to see if this seq depends on the changed seq */
 +      
 +      if(seq == NULL)
 +              return 0;
 +      
 +      if(seq == changed_seq)
 +              free_imbuf = 1;
 +      
 +      for(subseq=seq->seqbase.first; subseq; subseq=subseq->next)
 +              if(update_changed_seq_recurs(scene, subseq, changed_seq, len_change, ibuf_change))
 +                      free_imbuf = TRUE;
 +      
 +      if(seq->seq1)
 +              if(update_changed_seq_recurs(scene, seq->seq1, changed_seq, len_change, ibuf_change))
 +                      free_imbuf = TRUE;
 +      if(seq->seq2 && (seq->seq2 != seq->seq1))
 +              if(update_changed_seq_recurs(scene, seq->seq2, changed_seq, len_change, ibuf_change))
 +                      free_imbuf = TRUE;
 +      if(seq->seq3 && (seq->seq3 != seq->seq1) && (seq->seq3 != seq->seq2))
 +              if(update_changed_seq_recurs(scene, seq->seq3, changed_seq, len_change, ibuf_change))
 +                      free_imbuf = TRUE;
 +      
 +      if(free_imbuf) {
 +              if(ibuf_change) {
 +                      se= seq->strip->tstripdata;
 +                      if (se) {
 +                              for(a=0; a<seq->len; a++, se++)
 +                                      free_imbuf_strip_elem(se);
 +                      }
 +                      
 +                      if(seq->type == SEQ_MOVIE)
 +                              free_anim_seq(seq);
 +                      if(seq->type == SEQ_SPEED) {
 +                              sequence_effect_speed_rebuild_map(seq, 1);
 +                      }
 +              }
 +              
 +              if(len_change)
 +                      calc_sequence(seq);
 +      }
 +      
 +      return free_imbuf;
 +}
 +
 +void update_changed_seq_and_deps(Scene *scene, Sequence *changed_seq, int len_change, int ibuf_change)
 +{
 +      Editing *ed= seq_give_editing(scene, FALSE);
 +      Sequence *seq;
 +      
 +      if (ed==NULL) return;
 +      
 +      for (seq=ed->seqbase.first; seq; seq=seq->next)
 +              update_changed_seq_recurs(scene, seq, changed_seq, len_change, ibuf_change);
 +}
 +
++#if 0 // XXX from 2.4x, needs updating
++void free_imbuf_seq()
++{
++      Scene * sce = G.main->scene.first;
++      while(sce) {
++              free_imbuf_seq_editing(sce->ed);
++              sce= sce->id.next;
++      }
++}
++#endif 
++
 +void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo)
 +{
 +      /* force update of all sequences with this ipo, on ipo changes */
 +      Editing *ed= seq_give_editing(scene, FALSE);
 +      Sequence *seq;
 +
 +      if(ed==NULL) return;
 +
 +      SEQ_BEGIN(ed, seq) {
 +              if(seq->ipo == ipo) {
 +                      update_changed_seq_and_deps(scene, seq, 0, 1);
 +                      if(seq->type == SEQ_SPEED) {
 +                              sequence_effect_speed_rebuild_map(seq, 1);
 +                      }
 +                      free_proxy_seq(seq);
 +              }
 +      }
 +      SEQ_END
 +}
 +
 +#if 0
 +/* bad levell call... */
 +void do_render_seq(RenderResult *rr, int cfra)
 +{
++      static int recurs_depth = 0
 +      ImBuf *ibuf;
 +
-               {
++      recurs_depth++;
++
++      ibuf= give_ibuf_seq(rr->rectx, rr->recty, cfra, 0, 100.0);
++
++      recurs_depth--;
 +      
 +      if(ibuf) {
 +              if(ibuf->rect_float) {
 +                      if (!rr->rectf)
 +                              rr->rectf= MEM_mallocN(4*sizeof(float)*rr->rectx*rr->recty, "render_seq rectf");
 +                      
 +                      memcpy(rr->rectf, ibuf->rect_float, 4*sizeof(float)*rr->rectx*rr->recty);
 +                      
 +                      /* TSK! Since sequence render doesn't free the *rr render result, the old rect32
 +                         can hang around when sequence render has rendered a 32 bits one before */
 +                      if(rr->rect32) {
 +                              MEM_freeN(rr->rect32);
 +                              rr->rect32= NULL;
 +                      }
 +              }
 +              else if(ibuf->rect) {
 +                      if (!rr->rect32)
 +                              rr->rect32= MEM_mallocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect");
 +
 +                      memcpy(rr->rect32, ibuf->rect, 4*rr->rectx*rr->recty);
 +
 +                      /* if (ibuf->zbuf) { */
 +                      /*      if (R.rectz) freeN(R.rectz); */
 +                      /*      R.rectz = BLI_dupallocN(ibuf->zbuf); */
 +                      /* } */
 +              }
 +              
 +              /* Let the cache limitor take care of this (schlaile) */
 +              /* While render let's keep all memory available for render 
 +                 (ton)
 +                 At least if free memory is tight...
 +                 This can make a big difference in encoding speed
 +                 (it is around 4 times(!) faster, if we do not waste time
 +                 on freeing _all_ buffers every time on long timelines...)
 +                 (schlaile)
 +              */
++              if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */
 +                      uintptr_t mem_in_use;
 +                      uintptr_t mmap_in_use;
 +                      uintptr_t max;
 +
 +                      mem_in_use= MEM_get_memory_in_use();
 +                      mmap_in_use= MEM_get_mapped_memory_in_use();
 +                      max = MEM_CacheLimiter_get_maximum();
 +
 +                      if (max != 0 && mem_in_use + mmap_in_use > max) {
 +                              fprintf(stderr, "Memory in use > maximum memory\n");
 +                              fprintf(stderr, "Cleaning up, please wait...\n"
 +                                      "If this happens very often,\n"
 +                                      "consider "
 +                                      "raising the memcache limit in the "
 +                                      "user preferences.\n");
 +                              free_imbuf_seq();
 +                      }
 +                      free_proxy_seq(seq);
 +              }
 +      }
 +      else {
 +              /* render result is delivered empty in most cases, nevertheless we handle all cases */
 +              if (rr->rectf)
 +                      memset(rr->rectf, 0, 4*sizeof(float)*rr->rectx*rr->recty);
 +              else if (rr->rect32)
 +                      memset(rr->rect32, 0, 4*rr->rectx*rr->recty);
 +              else
 +                      rr->rect32= MEM_callocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect");
 +      }
 +}
 +
 +#endif
 +
 +/* seq funcs's for transforming internally
 + notice the difference between start/end and left/right.
 +
 + left and right are the bounds at which the sequence is rendered,
 +start and end are from the start and fixed length of the sequence.
 +*/
 +int seq_tx_get_start(Sequence *seq) {
 +      return seq->start;
 +}
 +int seq_tx_get_end(Sequence *seq)
 +{
 +      return seq->start+seq->len;
 +}
 +
 +int seq_tx_get_final_left(Sequence *seq, int metaclip)
 +{
 +      if (metaclip && seq->tmp) {
 +              /* return the range clipped by the parents range */
 +              return MAX2( seq_tx_get_final_left(seq, 0), seq_tx_get_final_left((Sequence *)seq->tmp, 1) );
 +      } else {
 +              return (seq->start - seq->startstill) + seq->startofs;
 +      }
 +
 +}
 +int seq_tx_get_final_right(Sequence *seq, int metaclip)
 +{
 +      if (metaclip && seq->tmp) {
 +              /* return the range clipped by the parents range */
 +              return MIN2( seq_tx_get_final_right(seq, 0), seq_tx_get_final_right((Sequence *)seq->tmp, 1) );
 +      } else {
 +              return ((seq->start+seq->len) + seq->endstill) - seq->endofs;
 +      }
 +}
 +
 +void seq_tx_set_final_left(Sequence *seq, int val)
 +{
 +      if (val < (seq)->start) {
 +              seq->startstill = abs(val - (seq)->start);
 +                              (seq)->startofs = 0;
 +      } else {
 +              seq->startofs = abs(val - (seq)->start);
 +              seq->startstill = 0;
 +      }
 +}
 +
 +void seq_tx_set_final_right(Sequence *seq, int val)
 +{
 +      if (val > (seq)->start + (seq)->len) {
 +              seq->endstill = abs(val - (seq->start + (seq)->len));
 +              (seq)->endofs = 0;
 +      } else {
 +              seq->endofs = abs(val - ((seq)->start + (seq)->len));
 +              seq->endstill = 0;
 +      }
 +}
 +
 +/* used so we can do a quick check for single image seq
 +   since they work a bit differently to normal image seq's (during transform) */
 +int check_single_seq(Sequence *seq)
 +{
 +      if ( seq->len==1 && (seq->type == SEQ_IMAGE || seq->type == SEQ_COLOR))
 +              return 1;
 +      else
 +              return 0;
 +}
 +
 +/* use to impose limits when dragging/extending - so impossible situations dont happen
 + * Cant use the SEQ_LEFTSEL and SEQ_LEFTSEL directly because the strip may be in a metastrip */
 +void seq_tx_handle_xlimits(Sequence *seq, int leftflag, int rightflag)
 +{
 +      if(leftflag) {
 +              if (seq_tx_get_final_left(seq, 0) >= seq_tx_get_final_right(seq, 0)) {
 +                      seq_tx_set_final_left(seq, seq_tx_get_final_right(seq, 0)-1);
 +              }
 +
 +              if (check_single_seq(seq)==0) {
 +                      if (seq_tx_get_final_left(seq, 0) >= seq_tx_get_end(seq)) {
 +                              seq_tx_set_final_left(seq, seq_tx_get_end(seq)-1);
 +                      }
 +
 +                      /* dosnt work now - TODO */
 +                      /*
 +                      if (seq_tx_get_start(seq) >= seq_tx_get_final_right(seq, 0)) {
 +                              int ofs;
 +                              ofs = seq_tx_get_start(seq) - seq_tx_get_final_right(seq, 0);
 +                              seq->start -= ofs;
 +                              seq_tx_set_final_left(seq, seq_tx_get_final_left(seq, 0) + ofs );
 +                      }*/
 +
 +              }
 +      }
 +
 +      if(rightflag) {
 +              if (seq_tx_get_final_right(seq, 0) <=  seq_tx_get_final_left(seq, 0)) {
 +                      seq_tx_set_final_right(seq, seq_tx_get_final_left(seq, 0)+1);
 +              }
 +
 +              if (check_single_seq(seq)==0) {
 +                      if (seq_tx_get_final_right(seq, 0) <= seq_tx_get_start(seq)) {
 +                              seq_tx_set_final_right(seq, seq_tx_get_start(seq)+1);
 +                      }
 +              }
 +      }
 +
 +      /* sounds cannot be extended past their endpoints */
 +      if (seq->type == SEQ_RAM_SOUND || seq->type == SEQ_HD_SOUND) {
 +              seq->startstill= 0;
 +              seq->endstill= 0;
 +      }
 +}
 +
 +void fix_single_seq(Sequence *seq)
 +{
 +      int left, start, offset;
 +      if (!check_single_seq(seq))
 +              return;
 +
 +      /* make sure the image is always at the start since there is only one,
 +         adjusting its start should be ok */
 +      left = seq_tx_get_final_left(seq, 0);
 +      start = seq->start;
 +      if (start != left) {
 +              offset = left - start;
 +              seq_tx_set_final_left( seq, seq_tx_get_final_left(seq, 0) - offset );
 +              seq_tx_set_final_right( seq, seq_tx_get_final_right(seq, 0) - offset );
 +              seq->start += offset;
 +      }
 +}
 +
 +int seq_tx_test(Sequence * seq)
 +{
 +      return (seq->type < SEQ_EFFECT) || (get_sequence_effect_num_inputs(seq->type) == 0);
 +}
 +
 +int seq_test_overlap(ListBase * seqbasep, Sequence *test)
 +{
 +      Sequence *seq;
 +
 +      seq= seqbasep->first;
 +      while(seq) {
 +              if(seq!=test) {
 +                      if(test->machine==seq->machine) {
 +                              if( (test->enddisp <= seq->startdisp) || (test->startdisp >= seq->enddisp) );
 +                              else return 1;
 +                      }
 +              }
 +              seq= seq->next;
 +      }
 +      return 0;
 +}
 +
 +
 +static void seq_translate(Sequence *seq, int delta)
 +{
 +      seq->start += delta;
 +      if(seq->type==SEQ_META) {
 +              Sequence *seq_child;
 +              for(seq_child= seq->seqbase.first; seq_child; seq_child= seq_child->next) {
 +                      seq_translate(seq_child, delta);
 +              }
 +      }
 +
 +      calc_sequence_disp(seq);
 +}
 +
 +/* return 0 if there werent enough space */
 +int shuffle_seq(ListBase * seqbasep, Sequence *test)
 +{
 +      int orig_machine= test->machine;
 +      test->machine++;
 +      calc_sequence(test);
 +      while( seq_test_overlap(seqbasep, test) ) {
 +              if(test->machine >= MAXSEQ) {
 +                      break;
 +              }
 +              test->machine++;
 +              calc_sequence(test); // XXX - I dont think this is needed since were only moving vertically, Campbell.
 +      }
 +
 +      
 +      if(test->machine >= MAXSEQ) {
 +              /* Blender 2.4x would remove the strip.
 +               * nicer to move it to the end */
 +
 +              Sequence *seq;
 +              int new_frame= test->enddisp;
 +
 +              for(seq= seqbasep->first; seq; seq= seq->next) {
 +                      if (seq->machine == orig_machine)
 +                              new_frame = MAX2(new_frame, seq->enddisp);
 +              }
 +
 +              test->machine= orig_machine;
 +              new_frame = new_frame + (test->start-test->startdisp); /* adjust by the startdisp */
 +              seq_translate(test, new_frame - test->start);
 +
 +              calc_sequence(test);
 +              return 0;
 +      } else {
 +              return 1;
 +      }
 +}
index 2450765,0000000..3b90039
mode 100644,000000..100644
--- /dev/null
@@@ -1,1093 -1,0 +1,1099 @@@
-       int render_size = 0;
 +/**
 + * $Id$
 + *
 + * ***** BEGIN GPL LICENSE BLOCK *****
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 + *
 + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
 + * All rights reserved.
 + *
 + * Contributor(s): Blender Foundation, 2003-2009
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +#include <string.h>
 +#include <math.h>
 +
 +#include "MEM_guardedalloc.h"
 +
 +#include "BLI_blenlib.h"
 +#include "BLI_arithb.h"
 +
 +#include "IMB_imbuf_types.h"
 +
 +#include "DNA_gpencil_types.h"
 +#include "DNA_sequence_types.h"
 +#include "DNA_scene_types.h"
 +#include "DNA_screen_types.h"
 +#include "DNA_space_types.h"
 +#include "DNA_view2d_types.h"
 +#include "DNA_userdef_types.h"
 +
 +#include "BKE_context.h"
 +#include "BKE_global.h"
 +#include "BKE_plugin_types.h"
 +#include "BKE_sequence.h"
 +#include "BKE_scene.h"
 +#include "BKE_utildefines.h"
 + 
 +#include "IMB_imbuf_types.h"
 +#include "IMB_imbuf.h"
 +
 +#include "BIF_gl.h"
 +#include "BIF_glutil.h"
 +
 +#include "ED_anim_api.h"
 +#include "ED_space_api.h"
 +#include "ED_sequencer.h"
 +#include "ED_types.h"
 +
 +#include "UI_interface.h"
 +#include "UI_resources.h"
 +#include "UI_view2d.h"
 +
 +/* own include */
 +#include "sequencer_intern.h"
 +
 +#define SEQ_LEFTHANDLE                1
 +#define SEQ_RIGHTHANDLE       2
 +
 +
 +/* Note, Dont use WHILE_SEQ while drawing! - it messes up transform, - Campbell */
 +
 +int no_rightbox=0, no_leftbox= 0;
 +static void draw_shadedstrip(Sequence *seq, char *col, float x1, float y1, float x2, float y2);
 +
 +
 +static void draw_cfra_seq(View2D *v2d, int cfra)
 +{
 +      glColor3ub(0x30, 0x90, 0x50);
 +      glLineWidth(2.0);
 +      glBegin(GL_LINES);
 +      glVertex2f(cfra, v2d->cur.ymin);
 +      glVertex2f(cfra, v2d->cur.ymax);
 +      glEnd();
 +      glLineWidth(1.0);
 +}
 +
 +static void get_seq_color3ubv(Scene *curscene, Sequence *seq, char *col)
 +{
 +      char blendcol[3];
 +      float hsv[3], rgb[3];
 +      SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
 +
 +      switch(seq->type) {
 +      case SEQ_IMAGE:
 +              UI_GetThemeColor3ubv(TH_SEQ_IMAGE, col);
 +              break;
 +      case SEQ_META:
 +              UI_GetThemeColor3ubv(TH_SEQ_META, col);
 +              break;
 +      case SEQ_MOVIE:
 +              UI_GetThemeColor3ubv(TH_SEQ_MOVIE, col);
 +              break;
 +      case SEQ_SCENE:
 +              UI_GetThemeColor3ubv(TH_SEQ_SCENE, col);
 +              
 +              if(seq->scene==curscene) {
 +                      UI_GetColorPtrBlendShade3ubv(col, col, col, 1.0, 20);
 +              }
 +              break;
 +
 +      /* transitions */
 +      case SEQ_CROSS:
 +      case SEQ_GAMCROSS:
 +      case SEQ_WIPE:
 +              /* slightly offset hue to distinguish different effects */
 +              UI_GetThemeColor3ubv(TH_SEQ_TRANSITION, col);
 +              
 +              rgb[0] = col[0]/255.0; rgb[1] = col[1]/255.0; rgb[2] = col[2]/255.0; 
 +              rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
 +              
 +              if (seq->type == SEQ_CROSS)             hsv[0]+= 0.04;
 +              if (seq->type == SEQ_GAMCROSS)  hsv[0]+= 0.08;
 +              if (seq->type == SEQ_WIPE)              hsv[0]+= 0.12;
 +              
 +              if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
 +              hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
 +              col[0] = (char)(rgb[0]*255); col[1] = (char)(rgb[1]*255); col[2] = (char)(rgb[2]*255); 
 +              break;
 +              
 +      /* effects */
 +      case SEQ_TRANSFORM:
 +      case SEQ_SPEED:
 +      case SEQ_ADD:
 +      case SEQ_SUB:
 +      case SEQ_MUL:
 +      case SEQ_ALPHAOVER:
 +      case SEQ_ALPHAUNDER:
 +      case SEQ_OVERDROP:
 +      case SEQ_GLOW:
 +              /* slightly offset hue to distinguish different effects */
 +              UI_GetThemeColor3ubv(TH_SEQ_EFFECT, col);
 +              
 +              rgb[0] = col[0]/255.0; rgb[1] = col[1]/255.0; rgb[2] = col[2]/255.0; 
 +              rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
 +              
 +              if (seq->type == SEQ_ADD)               hsv[0]+= 0.04;
 +              if (seq->type == SEQ_SUB)               hsv[0]+= 0.08;
 +              if (seq->type == SEQ_MUL)               hsv[0]+= 0.12;
 +              if (seq->type == SEQ_ALPHAOVER) hsv[0]+= 0.16;
 +              if (seq->type == SEQ_ALPHAUNDER)        hsv[0]+= 0.20;
 +              if (seq->type == SEQ_OVERDROP)  hsv[0]+= 0.24;
 +              if (seq->type == SEQ_GLOW)              hsv[0]+= 0.28;
 +              if (seq->type == SEQ_TRANSFORM)         hsv[0]+= 0.36;
 +
 +              if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
 +              hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
 +              col[0] = (char)(rgb[0]*255); col[1] = (char)(rgb[1]*255); col[2] = (char)(rgb[2]*255); 
 +              break;
 +      case SEQ_COLOR:
 +              if (colvars->col) {
 +                      col[0]= (char)(colvars->col[0]*255);
 +                      col[1]= (char)(colvars->col[1]*255);
 +                      col[2]= (char)(colvars->col[2]*255);
 +              } else {
 +                      col[0] = col[1] = col[2] = 128;
 +              }
 +              break;
 +      case SEQ_PLUGIN:
 +              UI_GetThemeColor3ubv(TH_SEQ_PLUGIN, col);
 +              break;
 +      case SEQ_HD_SOUND:
 +      case SEQ_RAM_SOUND:
 +              UI_GetThemeColor3ubv(TH_SEQ_AUDIO, col);
 +              blendcol[0] = blendcol[1] = blendcol[2] = 128;
 +              if(seq->flag & SEQ_MUTE) UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.5, 20);
 +              break;
 +      default:
 +              col[0] = 10; col[1] = 255; col[2] = 40;
 +      }
 +}
 +
 +static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, float x2, float y2)
 +{
 +      /* Note, this used to use WHILE_SEQ, but it messes up the seq->depth value, (needed by transform when doing overlap checks)
 +       * so for now, just use the meta's immediate children, could be fixed but its only drawing - Campbell */
 +      Sequence *seq;
 +      float dx;
 +      int nr;
 +      char col[3];
 +      
 +      nr= BLI_countlist(&seqm->seqbase);
 +
 +      dx= (x2-x1)/nr;
 +
 +      if (seqm->flag & SEQ_MUTE) {
 +              glEnable(GL_POLYGON_STIPPLE);
 +              glPolygonStipple(stipple_halftone);
 +              
 +              glEnable(GL_LINE_STIPPLE);
 +              glLineStipple(1, 0x8888);
 +      }
 +      
 +      for (seq= seqm->seqbase.first; seq; seq= seq->next) {
 +              get_seq_color3ubv(scene, seq, col);
 +              
 +              glColor3ubv((GLubyte *)col);
 +
 +              glRectf(x1,  y1,  x1+0.9*dx,  y2);
 +              
 +              UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -30);
 +              glColor3ubv((GLubyte *)col);
 +
 +              fdrawbox(x1,  y1,  x1+0.9*dx,  y2);
 +              
 +              x1+= dx;
 +      }
 +      
 +      if (seqm->flag & SEQ_MUTE) {
 +              glDisable(GL_POLYGON_STIPPLE);
 +              glDisable(GL_LINE_STIPPLE);
 +      }
 +}
 +
 +static void drawseqwave(Scene *scene, View2D *v2d, Sequence *seq, float x1, float y1, float x2, float y2, int winx)
 +{
 +      /*
 +      x1 is the starting x value to draw the wave,
 +      x2 the end x value, same for y1 and y2
 +      winx is the zoom level.
 +      */
 +      
 +      float
 +      f, /* floating point value used to store the X draw location for the wave lines when openGL drawing*/
 +      midy, /* fast access to the middle location (y1+y2)/2 */
 +      clipxmin, /* the minimum X value, clip this with the window */
 +      clipxmax, /* the maximum X value, clip this with the window */
 +      sample_step, /* steps to move per sample, floating value must later translate into an int */
 +      fsofs, /* steps to move per sample, floating value must later translate into an int */
 +      feofs_sofs, /*  */
 +      sound_width, /* convenience: x2-x1 */
 +      wavemulti; /* scale the samples by this value when GL_LINE drawing so it renders the right height */
 +      
 +      int
 +      offset, /* initial offset value for the wave drawing */
 +      offset_next, /* when in the wave drawing loop this value is the samples intil the next vert */
 +      sofs, /* Constrained offset value (~3) for the wave, start */
 +      eofs, /* ditto, end */
 +      wavesample, /* inner loop storage if the current wave sample value, used to make the 2 values below */
 +      wavesamplemin, /* used for finding the min and max wave peaks */
 +      wavesamplemax, /* ditto */
 +      subsample_step=4; /* when the sample step is 4 every sample of
 +      the wave is evaluated for min and max values used to draw the wave,
 +      however this is slow ehrn zoomed out so when the sample step is above
 +      1 (the larger the further out the zoom is) so not evaluate all samples, only some. */
 +      
 +      signed short* s;
 +      bSound *sound;
 +      uint8_t *stream;
 +      
 +// XXX        audio_makestream(seq->sound);
 +      if(seq->sound==NULL || seq->sound->stream==NULL) return;
 +      
 +      if (seq->flag & SEQ_MUTE) glColor3ub(0x70, 0x80, 0x80); else glColor3ub(0x70, 0xc0, 0xc0);
 +      
 +      sofs = ((int)( FRA2TIME(seq->startdisp-seq->start+seq->anim_startofs)*(float)scene->r.audio.mixrate*4.0 )) & (~3);
 +      eofs = ((int)( FRA2TIME(seq->enddisp-seq->start+seq->anim_startofs)*(float)scene->r.audio.mixrate*4.0 )) & (~3);
 +      
 +      /* clip the drawing area to the screen bounds to save time */
 +      sample_step= (v2d->cur.xmax - v2d->cur.xmin)/winx;
 +      clipxmin= MAX2(x1, v2d->cur.xmin);
 +      clipxmax= MIN2(x2, v2d->cur.xmax);
 +      
 +      if (sample_step > 1)
 +              subsample_step= ((int)(subsample_step*sample_step*8)) & (~3);
 +      
 +      /* for speedy access */
 +      midy = (y1+y2)/2;
 +      fsofs= (float)sofs;
 +      feofs_sofs= (float)(eofs-sofs);
 +      sound_width= x2-x1;
 +      sound = seq->sound;
 +      stream = sound->stream;
 +      wavemulti = (y2-y1)/196605; /*y2-y1 is the height*/
 +      wavesample=0;
 +      
 +      /* we need to get the starting offset value, excuse the duplicate code */
 +      f=clipxmin;
 +      offset= (int) (fsofs + ((f-x1)/sound_width) * feofs_sofs) & (~3);
 +      
 +      /* start the loop, draw a line per sample_step -sample_step is about 1 line drawn per pixel */
 +      glBegin(GL_LINES);
 +      for (f=x1+sample_step; f<=clipxmax; f+=sample_step) {
 +              
 +              offset_next = (int) (fsofs + ((f-x1)/sound_width) * feofs_sofs) & (~3);
 +              if (f > v2d->cur.xmin) {
 +                      /* if this is close to the last sample just exit */
 +                      if (offset_next >= sound->streamlen) break;
 +                      
 +                      wavesamplemin = 131070;
 +                      wavesamplemax = -131070;
 +                      
 +                      /*find with high and low of the waveform for this draw,
 +                      evaluate small samples to find this range */
 +                      while (offset < offset_next) {
 +                              s = (signed short*)(stream+offset);
 +                              
 +                              wavesample = s[0]*2 + s[1];
 +                              if (wavesamplemin>wavesample)
 +                                      wavesamplemin=wavesample;
 +                              if (wavesamplemax<wavesample)
 +                                      wavesamplemax=wavesample;
 +                              offset+=subsample_step;
 +                      }
 +                      /* draw the wave line, looks good up close and zoomed out */
 +                      glVertex2f(f,  midy-(wavemulti*wavesamplemin) );
 +                      glVertex2f(f,  midy-(wavemulti*wavesamplemax) );
 +              } else {
 +                      while (offset < offset_next) offset+=subsample_step;
 +              }
 +              
 +              offset=offset_next;
 +      }
 +      glEnd();
 +}
 +
 +/* draw a handle, for each end of a sequence strip */
 +static void draw_seq_handle(View2D *v2d, Sequence *seq, float pixelx, short direction)
 +{
 +      float v1[2], v2[2], v3[2], rx1=0, rx2=0; //for triangles and rect
 +      float x1, x2, y1, y2;
 +      float handsize;
 +      float minhandle, maxhandle;
 +      char str[32];
 +      unsigned int whichsel=0;
 +      
 +      x1= seq->startdisp;
 +      x2= seq->enddisp;
 +      
 +      y1= seq->machine+SEQ_STRIP_OFSBOTTOM;
 +      y2= seq->machine+SEQ_STRIP_OFSTOP;
 +      
 +      /* clamp handles to defined size in pixel space */
 +      handsize = seq->handsize;
 +      minhandle = 7;
 +      maxhandle = 40;
 +      CLAMP(handsize, minhandle*pixelx, maxhandle*pixelx);
 +      
 +      /* set up co-ordinates/dimensions for either left or right handle */
 +      if (direction == SEQ_LEFTHANDLE) {      
 +              rx1 = x1;
 +              rx2 = x1+handsize*0.75;
 +              
 +              v1[0]= x1+handsize/4; v1[1]= y1+( ((y1+y2)/2.0 - y1)/2);
 +              v2[0]= x1+handsize/4; v2[1]= y2-( ((y1+y2)/2.0 - y1)/2);
 +              v3[0]= v2[0] + handsize/4; v3[1]= (y1+y2)/2.0;
 +              
 +              whichsel = SEQ_LEFTSEL;
 +      } else if (direction == SEQ_RIGHTHANDLE) {      
 +              rx1 = x2-handsize*0.75;
 +              rx2 = x2;
 +              
 +              v1[0]= x2-handsize/4; v1[1]= y1+( ((y1+y2)/2.0 - y1)/2);
 +              v2[0]= x2-handsize/4; v2[1]= y2-( ((y1+y2)/2.0 - y1)/2);
 +              v3[0]= v2[0] - handsize/4; v3[1]= (y1+y2)/2.0;
 +              
 +              whichsel = SEQ_RIGHTSEL;
 +      }
 +      
 +      /* draw! */
 +      if(seq->type < SEQ_EFFECT || 
 +         get_sequence_effect_num_inputs(seq->type) == 0) {
 +              glEnable( GL_BLEND );
 +              
 +              glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 +              
 +              if(seq->flag & whichsel) glColor4ub(0, 0, 0, 80);
 +              else if (seq->flag & SELECT) glColor4ub(255, 255, 255, 30);
 +              else glColor4ub(0, 0, 0, 22);
 +              
 +              glRectf(rx1, y1, rx2, y2);
 +              
 +              if(seq->flag & whichsel) glColor4ub(255, 255, 255, 200);
 +              else glColor4ub(0, 0, 0, 50);
 +              
 +              glEnable( GL_POLYGON_SMOOTH );
 +              glBegin(GL_TRIANGLES);
 +              glVertex2fv(v1); glVertex2fv(v2); glVertex2fv(v3);
 +              glEnd();
 +              
 +              glDisable( GL_POLYGON_SMOOTH );
 +              glDisable( GL_BLEND );
 +      }
 +      
 +      if(G.moving || (seq->flag & whichsel)) {
 +              cpack(0xFFFFFF);
 +              if (direction == SEQ_LEFTHANDLE) {
 +                      sprintf(str, "%d", seq->startdisp);
 +                      x1= rx1;
 +                      y1 -= 0.45;
 +              } else {
 +                      sprintf(str, "%d", seq->enddisp - 1);
 +                      x1= x2 - handsize*0.75;
 +                      y1= y2 + 0.05;
 +              }
 +              UI_view2d_text_cache_add(v2d, x1, y1, str);
 +      }       
 +}
 +
 +static void draw_seq_extensions(Scene *scene, SpaceSeq *sseq, Sequence *seq)
 +{
 +      float x1, x2, y1, y2, pixely, a;
 +      char col[3], blendcol[3];
 +      View2D *v2d;
 +      
 +      if(seq->type >= SEQ_EFFECT) return;
 +
 +      x1= seq->startdisp;
 +      x2= seq->enddisp;
 +      
 +      y1= seq->machine+SEQ_STRIP_OFSBOTTOM;
 +      y2= seq->machine+SEQ_STRIP_OFSTOP;
 +      
 +      v2d = &sseq->v2d;
 +      pixely = (v2d->cur.ymax - v2d->cur.ymin)/(v2d->mask.ymax - v2d->mask.ymin);
 +      
 +      blendcol[0] = blendcol[1] = blendcol[2] = 120;
 +
 +      if(seq->startofs) {
 +              glEnable( GL_BLEND );
 +              glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 +              
 +              get_seq_color3ubv(scene, seq, col);
 +              
 +              if (seq->flag & SELECT) {
 +                      UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
 +                      glColor4ub(col[0], col[1], col[2], 170);
 +              } else {
 +                      UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
 +                      glColor4ub(col[0], col[1], col[2], 110);
 +              }
 +              
 +              glRectf((float)(seq->start), y1-SEQ_STRIP_OFSBOTTOM, x1, y1);
 +              
 +              if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
 +              else glColor4ub(col[0], col[1], col[2], 160);
 +
 +              fdrawbox((float)(seq->start), y1-SEQ_STRIP_OFSBOTTOM, x1, y1);  //outline
 +              
 +              glDisable( GL_BLEND );
 +      }
 +      if(seq->endofs) {
 +              glEnable( GL_BLEND );
 +              glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 +              
 +              get_seq_color3ubv(scene, seq, col);
 +              
 +              if (seq->flag & SELECT) {
 +                      UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
 +                      glColor4ub(col[0], col[1], col[2], 170);
 +              } else {
 +                      UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
 +                      glColor4ub(col[0], col[1], col[2], 110);
 +              }
 +              
 +              glRectf(x2, y2, (float)(seq->start+seq->len), y2+SEQ_STRIP_OFSBOTTOM);
 +              
 +              if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
 +              else glColor4ub(col[0], col[1], col[2], 160);
 +
 +              fdrawbox(x2, y2, (float)(seq->start+seq->len), y2+SEQ_STRIP_OFSBOTTOM); //outline
 +              
 +              glDisable( GL_BLEND );
 +      }
 +      if(seq->startstill) {
 +              get_seq_color3ubv(scene, seq, col);
 +              UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
 +              glColor3ubv((GLubyte *)col);
 +              
 +              draw_shadedstrip(seq, col, x1, y1, (float)(seq->start), y2);
 +              
 +              /* feint pinstripes, helps see exactly which is extended and which isn't,
 +              * especially when the extension is very small */ 
 +              if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
 +              else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -16);
 +              
 +              glColor3ubv((GLubyte *)col);
 +              
 +              for(a=y1; a< y2; a+= pixely*2.0 ) {
 +                      fdrawline(x1,  a,  (float)(seq->start),  a);
 +              }
 +      }
 +      if(seq->endstill) {
 +              get_seq_color3ubv(scene, seq, col);
 +              UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
 +              glColor3ubv((GLubyte *)col);
 +              
 +              draw_shadedstrip(seq, col, (float)(seq->start+seq->len), y1, x2, y2);
 +              
 +              /* feint pinstripes, helps see exactly which is extended and which isn't,
 +              * especially when the extension is very small */ 
 +              if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
 +              else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -16);
 +              
 +              glColor3ubv((GLubyte *)col);
 +              
 +              for(a=y1; a< y2; a+= pixely*2.0 ) {
 +                      fdrawline((float)(seq->start+seq->len),  a,  x2,  a);
 +              }
 +      }
 +}
 +
 +/* draw info text on a sequence strip */
 +static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float y1, float y2, char *background_col)
 +{
 +      rctf rect;
 +      char str[32 + FILE_MAXDIR+FILE_MAXFILE];
 +      
 +      if(seq->name[2]) {
 +              sprintf(str, "%d | %s: %s", seq->len, give_seqname(seq), seq->name+2);
 +      }
 +      else{
 +              if(seq->type == SEQ_META) {
 +                      sprintf(str, "%d | %s", seq->len, give_seqname(seq));
 +              }
 +              else if(seq->type == SEQ_SCENE) {
 +                      if(seq->scene) sprintf(str, "%d | %s: %s", seq->len, give_seqname(seq), seq->scene->id.name+2);
 +                      else sprintf(str, "%d | %s", seq->len, give_seqname(seq));
 +                      
 +              }
 +              else if(seq->type == SEQ_IMAGE) {
 +                      sprintf(str, "%d | %s%s", seq->len, seq->strip->dir, seq->strip->stripdata->name);
 +              }
 +              else if(seq->type & SEQ_EFFECT) {
 +                      int can_float = (seq->type != SEQ_PLUGIN)
 +                              || (seq->plugin && seq->plugin->version >= 4);
 +
 +                      if(seq->seq3!=seq->seq2 && seq->seq1!=seq->seq3)
 +                              sprintf(str, "%d | %s: %d>%d (use %d)%s", seq->len, give_seqname(seq), seq->seq1->machine, seq->seq2->machine, seq->seq3->machine, can_float ? "" : " No float, upgrade plugin!");
 +                      else if (seq->seq1 && seq->seq2)
 +                              sprintf(str, "%d | %s: %d>%d%s", seq->len, give_seqname(seq), seq->seq1->machine, seq->seq2->machine, can_float ? "" : " No float, upgrade plugin!");
 +                      else 
 +                              sprintf(str, "%d | %s", seq->len, give_seqname(seq));
 +              }
 +              else if (seq->type == SEQ_RAM_SOUND) {
 +                      sprintf(str, "%d | %s", seq->len, seq->strip->stripdata->name);
 +              }
 +              else if (seq->type == SEQ_HD_SOUND) {
 +                      sprintf(str, "%d | %s", seq->len, seq->strip->stripdata->name);
 +              }
 +              else if (seq->type == SEQ_MOVIE) {
 +                      sprintf(str, "%d | %s%s", seq->len, seq->strip->dir, seq->strip->stripdata->name);
 +              }
 +      }
 +      
 +      if(seq->flag & SELECT){
 +              cpack(0xFFFFFF);
 +      }else if ((((int)background_col[0] + (int)background_col[1] + (int)background_col[2]) / 3) < 50){
 +              cpack(0x505050); /* use lighter text colour for dark background */
 +      }else{
 +              cpack(0);
 +      }
 +      
 +      rect.xmin= x1;
 +      rect.ymin= y1;
 +      rect.xmax= x2;
 +      rect.ymax= y2;
 +      UI_view2d_text_cache_rectf(v2d, &rect, str);
 +}
 +
 +/* draws a shaded strip, made from gradient + flat color + gradient */
 +static void draw_shadedstrip(Sequence *seq, char *col, float x1, float y1, float x2, float y2)
 +{
 +      float ymid1, ymid2;
 +      
 +      if (seq->flag & SEQ_MUTE) {
 +              glEnable(GL_POLYGON_STIPPLE);
 +              glPolygonStipple(stipple_halftone);
 +      }
 +      
 +      ymid1 = (y2-y1)*0.25 + y1;
 +      ymid2 = (y2-y1)*0.65 + y1;
 +      
 +      glShadeModel(GL_SMOOTH);
 +      glBegin(GL_QUADS);
 +      
 +      if(seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -50);
 +      else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 0);
 +      
 +      glColor3ubv((GLubyte *)col);
 +      
 +      glVertex2f(x1,y1);
 +      glVertex2f(x2,y1);
 +      
 +      if(seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 5);
 +      else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -5);
 +
 +      glColor3ubv((GLubyte *)col);
 +      
 +      glVertex2f(x2,ymid1);
 +      glVertex2f(x1,ymid1);
 +      
 +      glEnd();
 +      
 +      glRectf(x1,  ymid1,  x2,  ymid2);
 +      
 +      glBegin(GL_QUADS);
 +      
 +      glVertex2f(x1,ymid2);
 +      glVertex2f(x2,ymid2);
 +      
 +      if(seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -15);
 +      else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 25);
 +      
 +      glColor3ubv((GLubyte *)col);
 +      
 +      glVertex2f(x2,y2);
 +      glVertex2f(x1,y2);
 +      
 +      glEnd();
 +      
 +      if (seq->flag & SEQ_MUTE) {
 +              glDisable(GL_POLYGON_STIPPLE);
 +      }
 +}
 +
 +/*
 +Draw a sequence strip, bounds check alredy made
 +ARegion is currently only used to get the windows width in pixels
 +so wave file sample drawing precission is zoom adjusted
 +*/
 +static void draw_seq_strip(Scene *scene, ARegion *ar, SpaceSeq *sseq, Sequence *seq, int outline_tint, float pixelx)
 +{
 +      // XXX
 +      extern void gl_round_box_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown);
 +      View2D *v2d= &ar->v2d;
 +      float x1, x2, y1, y2;
 +      char col[3], background_col[3], is_single_image;
 +
 +      /* we need to know if this is a single image/color or not for drawing */
 +      is_single_image = (char)check_single_seq(seq);
 +      
 +      /* body */
 +      if(seq->startstill) x1= seq->start;
 +      else x1= seq->startdisp;
 +      y1= seq->machine+SEQ_STRIP_OFSBOTTOM;
 +      if(seq->endstill) x2= seq->start+seq->len;
 +      else x2= seq->enddisp;
 +      y2= seq->machine+SEQ_STRIP_OFSTOP;
 +      
 +      
 +      /* get the correct color per strip type*/
 +      //get_seq_color3ubv(scene, seq, col);
 +      get_seq_color3ubv(scene, seq, background_col);
 +      
 +      /* draw the main strip body */
 +      if (is_single_image) /* single image */
 +              draw_shadedstrip(seq, background_col, seq_tx_get_final_left(seq, 0), y1, seq_tx_get_final_right(seq, 0), y2);
 +      else /* normal operation */
 +              draw_shadedstrip(seq, background_col, x1, y1, x2, y2);
 +      
 +      /* draw additional info and controls */
 +      if (seq->type == SEQ_RAM_SOUND)
 +              drawseqwave(scene, v2d, seq, x1, y1, x2, y2, ar->winx);
 +      
 +      if (!is_single_image)
 +              draw_seq_extensions(scene, sseq, seq);
 +      
 +      draw_seq_handle(v2d, seq, pixelx, SEQ_LEFTHANDLE);
 +      draw_seq_handle(v2d, seq, pixelx, SEQ_RIGHTHANDLE);
 +      
 +      /* draw the strip outline */
 +      x1= seq->startdisp;
 +      x2= seq->enddisp;
 +      
 +      get_seq_color3ubv(scene, seq, col);
 +      if (G.moving && (seq->flag & SELECT)) {
 +              if(seq->flag & SEQ_OVERLAP) {
 +                      col[0]= 255; col[1]= col[2]= 40;
 +              } else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 120);
 +      }
 +
 +      UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, outline_tint);
 +      
 +      glColor3ubv((GLubyte *)col);
 +      
 +      if (seq->flag & SEQ_MUTE) {
 +              glEnable(GL_LINE_STIPPLE);
 +              glLineStipple(1, 0x8888);
 +      }
 +      
 +      gl_round_box_shade(GL_LINE_LOOP, x1, y1, x2, y2, 0.0, 0.1, 0.0);
 +      
 +      if (seq->flag & SEQ_MUTE) {
 +              glDisable(GL_LINE_STIPPLE);
 +      }
 +      
 +      /* calculate if seq is long enough to print a name */
 +      x1= seq->startdisp+seq->handsize;
 +      x2= seq->enddisp-seq->handsize;
 +
 +      /* but first the contents of a meta */
 +      if(seq->type==SEQ_META) drawmeta_contents(scene, seq, x1, y1+0.15, x2, y2-0.15);
 +
 +      /* info text on the strip */
 +      if(x1<v2d->cur.xmin) x1= v2d->cur.xmin;
 +      else if(x1>v2d->cur.xmax) x1= v2d->cur.xmax;
 +      if(x2<v2d->cur.xmin) x2= v2d->cur.xmin;
 +      else if(x2>v2d->cur.xmax) x2= v2d->cur.xmax;
 +
 +      /* nice text here would require changing the view matrix for texture text */
 +      if( (x2-x1) / pixelx > 32) {
 +              draw_seq_text(v2d, seq, x1, x2, y1, y2, background_col);
 +      }
 +}
 +
 +static Sequence *special_seq_update= 0;
 +
 +void set_special_seq_update(int val)
 +{
 +//    int x;
 +
 +      /* if mouse over a sequence && LEFTMOUSE */
 +      if(val) {
 +// XXX                special_seq_update= find_nearest_seq(&x);
 +      }
 +      else special_seq_update= 0;
 +}
 +
 +
 +static void draw_image_seq(Scene *scene, ARegion *ar, SpaceSeq *sseq)
 +{
 +      extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad);
 +      struct ImBuf *ibuf;
 +      int x1, y1, rectx, recty;
 +      int free_ibuf = 0;
 +      static int recursive= 0;
 +      float zoom;
 +      float zoomx, zoomy;
-                       ibuf= give_ibuf_seq_direct(scene, rectx, recty, (scene->r.cfra), render_size, special_seq_update);
++      float render_size = 0.0;
++      float proxy_size = 100.0;
 +
 +      glClearColor(0.0, 0.0, 0.0, 0.0);
 +      glClear(GL_COLOR_BUFFER_BIT);
 +
 +      render_size = sseq->render_size;
 +      if (render_size == 0) {
 +              render_size = scene->r.size;
++      } else {
++              proxy_size = render_size;
 +      }
 +      if (render_size < 0) {
 +              return;
 +      }
 +
 +      rectx= (render_size*scene->r.xsch)/100;
 +      recty= (render_size*scene->r.ysch)/100;
 +
 +      /* BIG PROBLEM: the give_ibuf_seq() can call a rendering, which in turn calls redraws...
 +         this shouldn't belong in a window drawing....
 +         So: solve this once event based. 
 +         Now we check for recursion, space type and active area again (ton) */
 +      
 +      if(recursive)
 +              return;
 +      else {
 +              recursive= 1;
 +              if (special_seq_update) {
-                       ibuf= (ImBuf *)give_ibuf_seq(scene, rectx, recty, (scene->r.cfra), sseq->chanshown, render_size);
++                      ibuf= give_ibuf_seq_direct(scene, rectx, recty, (scene->r.cfra), proxy_size, special_seq_update);
 +              } 
 +              else if (!U.prefetchframes) { // XXX || (G.f & G_PLAYANIM) == 0) {
-                       ibuf= (ImBuf *)give_ibuf_seq_threaded(scene, rectx, recty, (scene->r.cfra), sseq->chanshown, render_size);
++                      ibuf= (ImBuf *)give_ibuf_seq(scene, rectx, recty, (scene->r.cfra), sseq->chanshown, proxy_size);
 +              } 
 +              else {
-               zoom /= render_size / 100.0;
++                      ibuf= (ImBuf *)give_ibuf_seq_threaded(scene, rectx, recty, (scene->r.cfra), sseq->chanshown, proxy_size);
 +              }
 +              recursive= 0;
 +              
 +              /* XXX HURMF! the give_ibuf_seq can call image display in this window */
 +//            if(sa->spacetype!=SPACE_SEQ)
 +//                    return;
 +//            if(sa!=curarea) {
 +//                    areawinset(sa->win);
 +//            }
 +      }
 +      
 +      if(ibuf==NULL) 
 +              return;
 +
 +      if(ibuf->rect==NULL && ibuf->rect_float == NULL) 
 +              return;
 +      
 +      switch(sseq->mainb) {
 +      case SEQ_DRAW_IMG_IMBUF:
 +              if (sseq->zebra != 0) {
 +                      ibuf = make_zebra_view_from_ibuf(ibuf, sseq->zebra);
 +                      free_ibuf = 1;
 +              }
 +              break;
 +      case SEQ_DRAW_IMG_WAVEFORM:
 +              if ((sseq->flag & SEQ_DRAW_COLOR_SEPERATED) != 0) {
 +                      ibuf = make_sep_waveform_view_from_ibuf(ibuf);
 +              } else {
 +                      ibuf = make_waveform_view_from_ibuf(ibuf);
 +              }
 +              free_ibuf = 1;
 +              break;
 +      case SEQ_DRAW_IMG_VECTORSCOPE:
 +              ibuf = make_vectorscope_view_from_ibuf(ibuf);
 +              free_ibuf = 1;
 +              break;
 +      case SEQ_DRAW_IMG_HISTOGRAM:
 +              ibuf = make_histogram_view_from_ibuf(ibuf);
 +              free_ibuf = 1;
 +              break;
 +      }
 +
 +      if(ibuf->rect_float && ibuf->rect==NULL)
 +              IMB_rect_from_float(ibuf);
 +      
 +      /* needed for gla draw */
 +      glaDefine2DArea(&ar->winrct);
 +      
 +      zoom= SEQ_ZOOM_FAC(sseq->zoom);
 +      if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
-                       render_size);
++              zoom /= proxy_size / 100.0;
 +              zoomx = zoom * ((float)scene->r.xasp / (float)scene->r.yasp);
 +              zoomy = zoom;
 +      } else {
 +              zoomx = zoomy = zoom;
 +      }
 +
 +      /* calc location */
 +      x1= (ar->winx-zoomx*ibuf->x)/2 + sseq->xof;
 +      y1= (ar->winy-zoomy*ibuf->y)/2 + sseq->yof;
 +      
 +      glPixelZoom(zoomx, zoomy);
 +      
 +      glaDrawPixelsSafe(x1, y1, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
 +      
 +      glPixelZoom(1.0, 1.0);
 +
 +      /* safety border */
 +      if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && 
 +          (sseq->flag & SEQ_DRAW_SAFE_MARGINS) != 0) {
 +              float fac= 0.1;
 +              float x2 = x1 + ibuf->x * zoomx;
 +              float y2 = y1 + ibuf->y * zoomy;
 +              
 +              float a= fac*(x2-x1);
 +              x1+= a; 
 +              x2-= a;
 +      
 +              a= fac*(y2-y1);
 +              y1+= a;
 +              y2-= a;
 +      
 +              glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
 +              setlinestyle(3);
 +
 +              UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0);
 +              
 +              uiSetRoundBox(15);
 +              gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 12.0);
 +
 +              setlinestyle(0);
 +              glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 +      }
 +      
 +      /* draw grease-pencil (image aligned) */
 +//    if (sseq->flag & SEQ_DRAW_GPENCIL)
 +// XXX                draw_gpencil_2dimage(sa, ibuf);
 +
 +      if (free_ibuf) {
 +              IMB_freeImBuf(ibuf);
 +      } 
 +      
 +      /* draw grease-pencil (screen aligned) */
 +//    if (sseq->flag & SEQ_DRAW_GPENCIL)
 +// XXX                draw_gpencil_2dview(sa, 0);
 +      
 +      /* ortho at pixel level sa */
 +// XXX        myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
 +      
 +}
 +
 +void seq_reset_imageofs(SpaceSeq *sseq)
 +{
 +      sseq->xof = sseq->yof = sseq->zoom = 0;
 +}
 +
 +
 +#if 0
 +/* XXX - these should really be made to use View2D instead of so wacko private system - Aligorith */
 +
 +void seq_viewzoom(SpaceSeq *sseq, unsigned short event, int invert)
 +{
 +
 +      if(event==PAD1)
 +              sseq->zoom= 1.0;
 +      else if(event==PAD2)
 +              sseq->zoom= (invert)? 2.0: 0.5;
 +      else if(event==PAD4)
 +              sseq->zoom= (invert)? 4.0: 0.25;
 +      else if(event==PAD8)
 +              sseq->zoom= (invert)? 8.0: 0.125;
 +      
 +      /* ensure pixel exact locations for draw */
 +      sseq->xof= (int)sseq->xof;
 +      sseq->yof= (int)sseq->yof;
 +}
 +
 +void seq_viewmove(Scene *scene, ARegion *ar, SpaceSeq *sseq)
 +{     
 +      short mval[2], mvalo[2];
 +      short rectx, recty, xmin, xmax, ymin, ymax, pad;
 +      int oldcursor;
 +      Window *win;
 +      
 +      sa = sseq->area;
 +      rectx= (scene->r.size*scene->r.xsch)/100;
 +      recty= (scene->r.size*scene->r.ysch)/100;
 +      
 +      pad = 10;
 +      xmin = -(ar->winx/2) - rectx/2 + pad;
 +      xmax = ar->winx/2 + rectx/2 - pad;
 +      ymin = -(ar->winy/2) - recty/2 + pad;
 +      ymax = ar->winy/2 + recty/2 - pad;
 +      
 +      getmouseco_sc(mvalo);
 +
 +      oldcursor=get_cursor();
 +      win=winlay_get_active_window();
 +      
 +      SetBlenderCursor(BC_NSEW_SCROLLCURSOR);
 +      
 +      while(get_mbut()&(L_MOUSE|M_MOUSE)) {
 +              
 +              getmouseco_sc(mval);
 +              
 +              if(mvalo[0]!=mval[0] || mvalo[1]!=mval[1]) {
 +
 +                      sseq->xof -= (mvalo[0]-mval[0]);
 +                      sseq->yof -= (mvalo[1]-mval[1]);
 +                      
 +                      /* prevent dragging image outside of the window and losing it! */
 +                      CLAMP(sseq->xof, xmin, xmax);
 +                      CLAMP(sseq->yof, ymin, ymax);
 +                      
 +                      mvalo[0]= mval[0];
 +                      mvalo[1]= mval[1];
 +                      
 +              }
 +      }
 +}
 +#endif
 +
 +void drawprefetchseqspace(Scene *scene, ARegion *ar, SpaceSeq *sseq)
 +{
 +      int rectx, recty;
 +      int render_size = sseq->render_size;
++      int proxy_size = 100.0; 
 +      if (render_size == 0) {
 +              render_size = scene->r.size;
++      } else {
++              proxy_size = render_size;
 +      }
 +      if (render_size < 0) {
 +              return;
 +      }
 +
 +      rectx= (render_size*scene->r.xsch)/100;
 +      recty= (render_size*scene->r.ysch)/100;
 +
 +      if(sseq->mainb != SEQ_DRAW_SEQUENCE) {
 +              give_ibuf_prefetch_request(
 +                      rectx, recty, (scene->r.cfra), sseq->chanshown,
++                      proxy_size);
 +      }
 +}
 +
 +void drawseqspace(const bContext *C, ARegion *ar)
 +{
 +      ScrArea *sa= CTX_wm_area(C);
 +      SpaceSeq *sseq= sa->spacedata.first;
 +      Scene *scene= CTX_data_scene(C);
 +      View2D *v2d= &ar->v2d;
 +      View2DScrollers *scrollers;
 +      Editing *ed= seq_give_editing(scene, FALSE);
 +      Sequence *seq;
 +      float col[3];
 +      int i;
 +
 +      if(sseq->mainb != SEQ_DRAW_SEQUENCE) {
 +              draw_image_seq(scene, ar, sseq);
 +              return;
 +      }
 +
 +      UI_GetThemeColor3fv(TH_BACK, col);
 +      if(ed && ed->metastack.first) glClearColor(col[0], col[1], col[2]-0.1, 0.0);
 +      else glClearColor(col[0], col[1], col[2], 0.0);
 +
 +      glClear(GL_COLOR_BUFFER_BIT);
 +
 +      UI_view2d_view_ortho(C, v2d);
 +      
 +      UI_ThemeColorShade(TH_BACK, -20);
 +      glRectf(v2d->cur.xmin,  0.0,  v2d->cur.xmax,  1.0);
 +
 +      boundbox_seq(scene, &v2d->tot);
 +      
 +      /* Alternating horizontal stripes */
 +      i= MAX2(1, ((int)v2d->cur.ymin)-1);
 +
 +      glBegin(GL_QUADS);
 +      while (i<v2d->cur.ymax) {
 +              if (((int)i) & 1)
 +                      UI_ThemeColorShade(TH_BACK, -15);
 +              else
 +                      UI_ThemeColorShade(TH_BACK, -25);
 +              
 +              glVertex2f(v2d->cur.xmax, i);
 +              glVertex2f(v2d->cur.xmin, i);
 +              glVertex2f(v2d->cur.xmin, i+1);
 +              glVertex2f(v2d->cur.xmax, i+1);
 +              i+=1.0;
 +      }
 +      glEnd();
 +      
 +      /* Force grid lines */
 +      i= MAX2(1, ((int)v2d->cur.ymin)-1);
 +      glBegin(GL_LINES);
 +
 +      while (i<v2d->cur.ymax) {
 +              UI_ThemeColor(TH_GRID);
 +              glVertex2f(v2d->cur.xmax, i);
 +              glVertex2f(v2d->cur.xmin, i);
 +              i+=1.0;
 +      }
 +      glEnd();
 +      
 +      UI_view2d_constant_grid_draw(C, v2d);
 +
 +      draw_cfra_seq(v2d, scene->r.cfra);
 +
 +      /* sequences: first deselect */
 +      if(ed) {
 +              Sequence *last_seq = get_last_seq(scene);
 +              int sel = 0, j;
 +              int outline_tint;
 +              float pixelx = (v2d->cur.xmax - v2d->cur.xmin)/(v2d->mask.xmax - v2d->mask.xmin);
 +              /* loop through twice, first unselected, then selected */
 +              for (j=0; j<2; j++) {
 +                      seq= ed->seqbasep->first;
 +                      if (j==0)       outline_tint = -150;
 +                      else            outline_tint = -60;
 +                      
 +                      while(seq) { /* bound box test, dont draw outside the view */
 +                              if (  ((seq->flag & SELECT) == sel) ||
 +                                              seq == last_seq ||
 +                                              MIN2(seq->startdisp, seq->start) > v2d->cur.xmax ||
 +                                              MAX2(seq->enddisp, seq->start+seq->len) < v2d->cur.xmin ||
 +                                              seq->machine+1.0 < v2d->cur.ymin ||
 +                                              seq->machine > v2d->cur.ymax)
 +                              {
 +                                      /* dont draw */
 +                              } else {
 +                                      draw_seq_strip(scene, ar, sseq, seq, outline_tint, pixelx);
 +                              }
 +                              seq= seq->next;
 +                      }
 +                      sel= SELECT; /* draw selected next time round */
 +              }
 +              /* draw the last selected last, removes some overlapping error */
 +              if (last_seq) {
 +                      draw_seq_strip(scene, ar, sseq, last_seq, 120, pixelx);
 +              }
 +      }
 +
 +      /* text draw cached, in pixelspace now */
 +      UI_view2d_text_cache_draw(ar);
 +
 +      /* Draw markers */
 +//    draw_markers_timespace(SCE_MARKERS, DRAW_MARKERS_LINES);
 +      
 +      /* reset view matrix */
 +      UI_view2d_view_restore(C);
 +
 +      /* scrollers */
 +      scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_UNIT_SECONDSSEQ, V2D_GRID_CLAMP, V2D_UNIT_VALUES, V2D_GRID_CLAMP);
 +      UI_view2d_scrollers_draw(C, v2d, scrollers);
 +      UI_view2d_scrollers_free(scrollers);
 +}
 +
 +