Merging r40615 through r40652 from trunk into soc-2011-tomato
[blender.git] / source / blender / blenkernel / intern / sequencer.c
index 009665f3a1fddb22f31e4aa96967887aaf2e510f..57a8afb99ffa3f7ccdf5386b57002bdc9ed7e633 100644 (file)
 
 #include "BKE_context.h"
 #include "BKE_sound.h"
-#include "AUD_C-API.h"
 
-#ifdef WIN32
-#define snprintf _snprintf
+#ifdef WITH_AUDASPACE
+#  include "AUD_C-API.h"
 #endif
 
-
 static ImBuf* seq_render_strip_stack( 
        SeqRenderData context, ListBase *seqbasep, float cfra, int chanshown);
 
@@ -215,6 +213,18 @@ void seq_free_sequence(Scene *scene, Sequence *seq)
        MEM_freeN(seq);
 }
 
+void seq_free_sequence_recurse(Scene *scene, Sequence *seq)
+{
+       Sequence *iseq;
+
+       for(iseq= seq->seqbase.first; iseq; iseq= iseq->next) {
+               seq_free_sequence_recurse(scene, iseq);
+       }
+
+       seq_free_sequence(scene, seq);
+}
+
+
 Editing *seq_give_editing(Scene *scene, int alloc)
 {
        if (scene->ed == NULL && alloc) {
@@ -530,7 +540,7 @@ void calc_sequence_disp(Scene *scene, Sequence *seq)
                seq->handsize= (float)((seq->enddisp-seq->startdisp)/25);
        }
 
-       seq_update_sound(scene, seq);
+       seq_update_sound_bounds(scene, seq);
 }
 
 static void seq_update_sound_bounds_recursive(Scene *scene, Sequence *metaseq)
@@ -587,8 +597,22 @@ void calc_sequence(Scene *scene, Sequence *seq)
                if (seq->seq1) {
                        seq->start= seq->startdisp= MAX3(seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp);
                        seq->enddisp= MIN3(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp);
+                       /* we cant help if strips don't overlap, it wont give useful results.
+                        * but at least ensure 'len' is never negative which causes bad bugs elsewhere. */
+                       if(seq->enddisp < seq->startdisp) {
+                               /* simple start/end swap */
+                               seq->start= seq->enddisp;
+                               seq->enddisp = seq->startdisp;
+                               seq->startdisp= seq->start;
+                               seq->flag |= SEQ_INVALID_EFFECT;
+                       }
+                       else {
+                               seq->flag &= ~SEQ_INVALID_EFFECT;
+                       }
+
                        seq->len= seq->enddisp - seq->startdisp;
-               } else {
+               }
+               else {
                        calc_sequence_disp(scene, seq);
                }
 
@@ -666,13 +690,16 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq, int lock_range)
        }
        case SEQ_MOVIE:
                if(seq->anim) IMB_free_anim(seq->anim);
-               seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0));
+               seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex);
 
                if (!seq->anim) {
                        return;
                }
        
-               seq->len = IMB_anim_get_duration(seq->anim);
+               seq->len = IMB_anim_get_duration(seq->anim,
+                                                seq->strip->proxy ?
+                                                seq->strip->proxy->tc :
+                                                IMB_TC_RECORD_RUN);
                
                seq->anim_preseek = IMB_anim_get_preseek(seq->anim);
 
@@ -682,7 +709,9 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq, int lock_range)
                        seq->len = 0;
                }
                seq->strip->len = seq->len;
+               break;
        case SEQ_SOUND:
+#ifdef WITH_AUDASPACE
                if(!seq->sound)
                        return;
                seq->len = ceil(AUD_getInfo(seq->sound->playback_handle).length * FPS);
@@ -692,6 +721,9 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq, int lock_range)
                        seq->len = 0;
                }
                seq->strip->len = seq->len;
+#else
+               return;
+#endif
                break;
        case SEQ_SCENE:
        {
@@ -1095,7 +1127,7 @@ static int get_shown_sequences(   ListBase * seqbasep, int cfra, int chanshown, Se
 
        return cnt;
 }
+
 
 /* **********************************************************************
    proxy management
@@ -1103,49 +1135,106 @@ static int get_shown_sequences(        ListBase * seqbasep, int cfra, int chanshown, Se
 
 #define PROXY_MAXFILE (2*FILE_MAXDIR+FILE_MAXFILE)
 
+static IMB_Proxy_Size seq_rendersize_to_proxysize(int size)
+{
+       if (size >= 100) {
+               return IMB_PROXY_NONE;
+       }
+       if (size >= 99) {
+               return IMB_PROXY_100;
+       }
+       if (size >= 75) {
+               return IMB_PROXY_75;
+       }
+       if (size >= 50) {
+               return IMB_PROXY_50;
+       }
+       return IMB_PROXY_25;
+}
+
+static void seq_open_anim_file(Sequence * seq)
+{
+       char name[FILE_MAXDIR+FILE_MAXFILE];
+       StripProxy * proxy;
+
+       if(seq->anim != NULL) {
+               return;
+       }
+
+       BLI_join_dirfile(name, sizeof(name), 
+                        seq->strip->dir, seq->strip->stripdata->name);
+       BLI_path_abs(name, G.main->name);
+       
+       seq->anim = openanim(name, IB_rect |
+                            ((seq->flag & SEQ_FILTERY) ? 
+                             IB_animdeinterlace : 0), seq->streamindex);
+
+       if (seq->anim == NULL) {
+               return;
+       }
+
+       proxy = seq->strip->proxy;
+
+       if (proxy == NULL) {
+               return;
+       }
+
+       if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) {
+               IMB_anim_set_index_dir(seq->anim, seq->strip->proxy->dir);
+       }
+}
+
+
 static int seq_proxy_get_fname(SeqRenderData context, Sequence * seq, int cfra, char * name)
 {
        int frameno;
-       char dir[FILE_MAXDIR];
+       char dir[PROXY_MAXFILE];
+       int render_size = context.preview_render_size;
 
        if (!seq->strip->proxy) {
                return FALSE;
        }
 
+       /* MOVIE tracks (only exception: custom files) are now handled 
+          internally by ImBuf module for various reasons: proper time code 
+          support, quicker index build, using one file instead 
+          of a full directory of jpeg files, etc. Trying to support old
+          and new method at once could lead to funny effects, if people
+          have both, a directory full of jpeg files and proxy avis, so
+          sorry folks, please rebuild your proxies... */
+
        if (seq->flag & (SEQ_USE_PROXY_CUSTOM_DIR|SEQ_USE_PROXY_CUSTOM_FILE)) {
                strcpy(dir, seq->strip->proxy->dir);
+       } else if (seq->type == SEQ_IMAGE) {
+               BLI_snprintf(dir, PROXY_MAXFILE, "%s/BL_proxy", seq->strip->dir);
        } else {
-               if (ELEM(seq->type, SEQ_IMAGE, SEQ_MOVIE)) {
-                       snprintf(dir, FILE_MAXDIR, "%s/BL_proxy", seq->strip->dir);
-               } else {
-                       return FALSE;
-               }
+               return FALSE;
        }
 
        if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
-               BLI_join_dirfile(name, FILE_MAX, dir, seq->strip->proxy->file); /* XXX, not real length */
+               BLI_join_dirfile(name, PROXY_MAXFILE, 
+                                dir, seq->strip->proxy->file);
                BLI_path_abs(name, G.main->name);
 
                return TRUE;
        }
 
+       /* dirty hack to distinguish 100% render size from PROXY_100 */
+       if (render_size == 99) {
+               render_size = 100;
+       }
+
        /* generate a separate proxy directory for each preview size */
 
-       switch(seq->type) {
-       case SEQ_IMAGE:
-               snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy", dir,
+       if (seq->type == SEQ_IMAGE) {
+               BLI_snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy", dir,
                         context.preview_render_size, 
                         give_stripelem(seq, cfra)->name);
                frameno = 1;
-               break;
-       case SEQ_MOVIE:
-               frameno = (int) give_stripelem_index(seq, cfra) + seq->anim_startofs;
-               snprintf(name, PROXY_MAXFILE, "%s/%s/%d/####", dir,
-                        seq->strip->stripdata->name, context.preview_render_size);
-               break;
-       default:
-               frameno = (int) give_stripelem_index(seq, cfra) + seq->anim_startofs;
-               snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir, 
+       } else {
+               frameno = (int) give_stripelem_index(seq, cfra) 
+                       + seq->anim_startofs;
+               BLI_snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir, 
                         context.preview_render_size);
        }
 
@@ -1160,13 +1249,18 @@ static int seq_proxy_get_fname(SeqRenderData context, Sequence * seq, int cfra,
 static struct ImBuf * seq_proxy_fetch(SeqRenderData context, Sequence * seq, int cfra)
 {
        char name[PROXY_MAXFILE];
+       IMB_Proxy_Size psize = seq_rendersize_to_proxysize(
+               context.preview_render_size);
+       int size_flags;
 
        if (!(seq->flag & SEQ_USE_PROXY)) {
                return NULL;
        }
 
-       /* rendering at 100% ? No real sense in proxy-ing, right? */
-       if (context.preview_render_size == 100) {
+       size_flags = seq->strip->proxy->build_size_flags;
+
+       /* only use proxies, if they are enabled (even if present!) */
+       if (psize == IMB_PROXY_NONE || ((size_flags & psize) != psize)) {
                return NULL;
        }
 
@@ -1177,13 +1271,19 @@ static struct ImBuf * seq_proxy_fetch(SeqRenderData context, Sequence * seq, int
                                return NULL;
                        }
  
-                       seq->strip->proxy->anim = openanim(name, IB_rect);
+                       seq->strip->proxy->anim = openanim(name, IB_rect, 0);
                }
                if (seq->strip->proxy->anim==NULL) {
                        return NULL;
                }
  
-               return IMB_anim_absolute(seq->strip->proxy->anim, frameno);
+               seq_open_anim_file(seq);
+
+               frameno = IMB_anim_index_get_frame_index(
+                       seq->anim, seq->strip->proxy->tc, frameno);
+
+               return IMB_anim_absolute(seq->strip->proxy->anim, frameno,
+                                        IMB_TC_NONE, IMB_PROXY_NONE);
        }
  
        if (seq_proxy_get_fname(context, seq, cfra, name) == 0) {
@@ -1197,71 +1297,38 @@ static struct ImBuf * seq_proxy_fetch(SeqRenderData context, Sequence * seq, int
        }
 }
 
-#if 0
-static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra,
-                                 int build_proxy_run, int preview_render_size);
-
-static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int preview_render_size, int seqrectx, int seqrecty)
+static void seq_proxy_build_frame(SeqRenderData context,
+                                 Sequence* seq, int cfra,
+                                 int proxy_render_size)
 {
        char name[PROXY_MAXFILE];
        int quality;
-       TStripElem * se;
-       int ok;
        int rectx, recty;
+       int ok;
        struct ImBuf * ibuf;
 
-       if (!(seq->flag & SEQ_USE_PROXY)) {
-               return;
-       }
-
-       /* rendering at 100% ? No real sense in proxy-ing, right? */
-       if (preview_render_size == 100) {
+       if (!seq_proxy_get_fname(context, seq, cfra, name)) {
                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, preview_render_size)) {
-               return;
-       }
+       ibuf = seq_render_strip(context, seq, cfra);
 
-       se = give_tstripelem(seq, cfra);
-       if (!se) {
-               return;
-       }
-
-       if(se->ibuf) {
-               IMB_freeImBuf(se->ibuf);
-               se->ibuf = 0;
-       }
-       
-       do_build_seq_ibuf(scene, seq, se, cfra, TRUE, preview_render_size,
-                         seqrectx, seqrecty);
-
-       if (!se->ibuf) {
-               return;
-       }
-
-       rectx= (preview_render_size*scene->r.xsch)/100;
-       recty= (preview_render_size*scene->r.ysch)/100;
-
-       ibuf = se->ibuf;
+       rectx = (proxy_render_size * context.scene->r.xsch) / 100;
+       recty = (proxy_render_size * context.scene->r.ysch) / 100;
 
        if (ibuf->x != rectx || ibuf->y != recty) {
                IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty);
        }
 
-       /* quality is fixed, otherwise one has to generate separate
-          directories for every quality...
-
-          depth = 32 is intentionally left in, otherwise ALPHA channels
+       /* depth = 32 is intentionally left in, otherwise ALPHA channels
           won't work... */
        quality = seq->strip->proxy->quality;
        ibuf->ftype= JPG | quality;
 
+       /* unsupported feature only confuses other s/w */
+       if(ibuf->depth==32)
+               ibuf->depth= 24;
+
        BLI_make_existing_file(name);
        
        ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat);
@@ -1270,69 +1337,80 @@ static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int pr
        }
 
        IMB_freeImBuf(ibuf);
-       se->ibuf = 0;
 }
 
-static void seq_proxy_rebuild(Scene *scene, Sequence * seq, int seqrectx,
-                             int seqrecty)
+void seq_proxy_rebuild(struct Main * bmain, Scene *scene, Sequence * seq,
+                      short *stop, short *do_update, float *progress)
 {
+       SeqRenderData context;
        int cfra;
-       float rsize = seq->strip->proxy->size;
+       int tc_flags;
+       int size_flags;
+       int quality;
 
-       waitcursor(1);
+       if (!seq->strip || !seq->strip->proxy) {
+               return;
+       }
 
-       G.afbreek = 0;
+       if (!(seq->flag & SEQ_USE_PROXY)) {
+               return;
+       }
 
-       /* 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.
-        */
+       tc_flags   = seq->strip->proxy->build_tc_flags;
+       size_flags = seq->strip->proxy->build_size_flags;
+       quality    = seq->strip->proxy->quality;
 
-       for (cfra = seq->startdisp; cfra < seq->enddisp; cfra++) {
-               TStripElem * tse = give_tstripelem(seq, cfra);
+       if (seq->type == SEQ_MOVIE) {
+               seq_open_anim_file(seq);
 
-               tse->flag &= ~STRIPELEM_PREVIEW_DONE;
+               if (seq->anim) {
+                       IMB_anim_index_rebuild(
+                               seq->anim, tc_flags, size_flags, quality,
+                               stop, do_update, progress);
+               }
+               return;
        }
 
-       
+       if (!(seq->flag & SEQ_USE_PROXY)) {
+               return;
+       }
 
-       /* a _lot_ faster for movie files, if we read frames in
-          sequential order */
-       if (seq->flag & SEQ_REVERSE_FRAMES) {
-               for (cfra = seq->enddisp-seq->endstill-1; 
-                        cfra >= seq->startdisp + seq->startstill; cfra--) {
-                       TStripElem * tse = give_tstripelem(seq, cfra);
-
-                       if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) {
-//XXX                          set_timecursor(cfra);
-                               seq_proxy_build_frame(scene, seq, cfra, rsize,
-                                                     seqrectx, seqrecty);
-                               tse->flag |= STRIPELEM_PREVIEW_DONE;
-                       }
-                       if (blender_test_break()) {
-                               break;
-                       }
+       /* that's why it is called custom... */
+       if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
+               return;
+       }
+
+       /* fail safe code */
+
+       context = seq_new_render_data(
+               bmain, scene, 
+               (scene->r.size * (float) scene->r.xsch) / 100.0f + 0.5f, 
+               (scene->r.size * (float) scene->r.ysch) / 100.0f + 0.5f, 
+               100);
+
+       for (cfra = seq->startdisp + seq->startstill; 
+            cfra < seq->enddisp - seq->endstill; cfra++) {
+               if (size_flags & IMB_PROXY_25) {
+                       seq_proxy_build_frame(context, seq, cfra, 25);
                }
-       } else {
-               for (cfra = seq->startdisp + seq->startstill; 
-                        cfra < seq->enddisp - seq->endstill; cfra++) {
-                       TStripElem * tse = give_tstripelem(seq, cfra);
-
-                       if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) {
-//XXX                          set_timecursor(cfra);
-                               seq_proxy_build_frame(scene, seq, cfra, rsize,
-                                                     seqrectx, seqrecty);
-                               tse->flag |= STRIPELEM_PREVIEW_DONE;
-                       }
-                       if (blender_test_break()) {
-                               break;
-                       }
+               if (size_flags & IMB_PROXY_50) {
+                       seq_proxy_build_frame(context, seq, cfra, 50);
                }
+               if (size_flags & IMB_PROXY_75) {
+                       seq_proxy_build_frame(context, seq, cfra, 75);
+               }
+               if (size_flags & IMB_PROXY_100) {
+                       seq_proxy_build_frame(context, seq, cfra, 100);
+               }
+
+               *progress= (float)cfra/(seq->enddisp - seq->endstill 
+                                       - seq->startdisp + seq->startstill);
+               *do_update= 1;
+
+               if(*stop || G.afbreek)
+                       break;
        }
-       waitcursor(0);
 }
-#endif
 
 
 /* **********************************************************************
@@ -1549,6 +1627,8 @@ static ImBuf * input_preprocess(
 {
        float mul;
 
+       ibuf = IMB_makeSingleUser(ibuf);
+
        if((seq->flag & SEQ_FILTERY) && seq->type != SEQ_MOVIE) {
                IMB_filtery(ibuf);
        }
@@ -1753,7 +1833,7 @@ static ImBuf* seq_render_effect_strip_impl(
                        facf= fac;
        }
        else {
-               fcu = id_data_find_fcurve(&context.scene->id, seq, &RNA_Sequence, "effect_fader", 0);
+               fcu = id_data_find_fcurve(&context.scene->id, seq, &RNA_Sequence, "effect_fader", 0, NULL);
                if (fcu) {
                        fac = facf = evaluate_fcurve(fcu, cfra);
                        if( context.scene->r.mode & R_FIELDS ) {
@@ -2074,17 +2154,20 @@ static ImBuf * seq_render_strip(SeqRenderData context, Sequence * seq, float cfr
                }
                case SEQ_MOVIE:
                {
-                       if(seq->anim==NULL) {
-                               BLI_join_dirfile(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name);
-                               BLI_path_abs(name, G.main->name);
-                                       
-                               seq->anim = openanim(name, IB_rect |
-                                                    ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0));
-                       }
+                       seq_open_anim_file(seq);
 
                        if(seq->anim) {
-                               IMB_anim_set_preseek(seq->anim, seq->anim_preseek);
-                               ibuf = IMB_anim_absolute(seq->anim, nr + seq->anim_startofs);
+                               IMB_anim_set_preseek(seq->anim,
+                                                    seq->anim_preseek);
+
+                               ibuf = IMB_anim_absolute(
+                                       seq->anim, nr + seq->anim_startofs, 
+                                       seq->strip->proxy ? 
+                                       seq->strip->proxy->tc
+                                       : IMB_TC_RECORD_RUN, 
+                                       seq_rendersize_to_proxysize(
+                                               context.preview_render_size));
+
                                /* we don't need both (speed reasons)! */
                                if (ibuf && ibuf->rect_float && ibuf->rect)
                                        imb_freerectImBuf(ibuf);
@@ -2101,7 +2184,7 @@ static ImBuf * seq_render_strip(SeqRenderData context, Sequence * seq, float cfr
                        ibuf = seq_render_scene_strip_impl(context, seq, nr);
 
                        /* Scene strips update all animation, so we need to restore original state.*/
-                       BKE_animsys_evaluate_all_animation(context.bmain, cfra);
+                       BKE_animsys_evaluate_all_animation(context.bmain, context.scene, cfra);
 
                        copy_to_ibuf_still(context, seq, nr, ibuf);
                        break;
@@ -2178,7 +2261,7 @@ static ImBuf* seq_render_strip_stack(
        if(scene->r.cfra != cfra) {
                // XXX for prefetch and overlay offset!..., very bad!!!
                AnimData *adt= BKE_animdata_from_id(&scene->id);
-               BKE_animsys_evaluate_animdata(&scene->id, adt, cfra, ADT_RECALC_ANIM);
+               BKE_animsys_evaluate_animdata(scene, &scene->id, adt, cfra, ADT_RECALC_ANIM);
        }
 #endif
 
@@ -2773,7 +2856,8 @@ void update_changed_seq_and_deps(Scene *scene, Sequence *changed_seq, int len_ch
  left and right are the bounds at which the sequence is rendered,
 start and end are from the start and fixed length of the sequence.
 */
-int seq_tx_get_start(Sequence *seq) {
+int seq_tx_get_start(Sequence *seq)
+{
        return seq->start;
 }
 int seq_tx_get_end(Sequence *seq)
@@ -3123,16 +3207,33 @@ int shuffle_seq_time(ListBase * seqbasep, Scene *evil_scene)
        return offset? 0:1;
 }
 
-void seq_update_sound(Scene* scene, Sequence *seq)
+void seq_update_sound_bounds_all(Scene *scene)
 {
-       if(seq->scene_sound)
-       {
+       Editing *ed = scene->ed;
+
+       if(ed) {
+               Sequence *seq;
+
+               for(seq = ed->seqbase.first; seq; seq = seq->next) {
+                       if(seq->type == SEQ_META) {
+                               seq_update_sound_bounds_recursive(scene, seq);
+                       }
+                       else if(ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) {
+                               seq_update_sound_bounds(scene, seq);
+                       }
+               }
+       }
+}
+
+void seq_update_sound_bounds(Scene* scene, Sequence *seq)
+{
+       if(seq->scene_sound) {
                sound_move_scene_sound(scene, seq->scene_sound, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
                /* mute is set in seq_update_muting_recursive */
        }
 }
 
-static void seq_update_muting_recursive(Scene *scene, ListBase *seqbasep, Sequence *metaseq, int mute)
+static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, int mute)
 {
        Sequence *seq;
        int seqmute;
@@ -3148,26 +3249,49 @@ static void seq_update_muting_recursive(Scene *scene, ListBase *seqbasep, Sequen
                        if(seq == metaseq)
                                seqmute= 0;
 
-                       seq_update_muting_recursive(scene, &seq->seqbase, metaseq, seqmute);
+                       seq_update_muting_recursive(&seq->seqbase, metaseq, seqmute);
                }
                else if(ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) {
                        if(seq->scene_sound) {
-                               sound_mute_scene_sound(scene, seq->scene_sound, seqmute);
+                               sound_mute_scene_sound(seq->scene_sound, seqmute);
                        }
                }
        }
 }
 
-void seq_update_muting(Scene *scene, Editing *ed)
+void seq_update_muting(Editing *ed)
 {
        if(ed) {
                /* mute all sounds up to current metastack list */
                MetaStack *ms= ed->metastack.last;
 
                if(ms)
-                       seq_update_muting_recursive(scene, &ed->seqbase, ms->parseq, 1);
+                       seq_update_muting_recursive(&ed->seqbase, ms->parseq, 1);
                else
-                       seq_update_muting_recursive(scene, &ed->seqbase, NULL, 0);
+                       seq_update_muting_recursive(&ed->seqbase, NULL, 0);
+       }
+}
+
+static void seq_update_sound_recursive(Scene *scene, ListBase *seqbasep, bSound *sound)
+{
+       Sequence *seq;
+
+       for(seq=seqbasep->first; seq; seq=seq->next) {
+               if(seq->type == SEQ_META) {
+                       seq_update_sound_recursive(scene, &seq->seqbase, sound);
+               }
+               else if(seq->type == SEQ_SOUND) {
+                       if(seq->scene_sound && sound == seq->sound) {
+                               sound_update_scene_sound(seq->scene_sound, sound);
+                       }
+               }
+       }
+}
+
+void seq_update_sound(struct Scene *scene, struct bSound *sound)
+{
+       if(scene->ed) {
+               seq_update_sound_recursive(scene, &scene->ed->seqbase, sound);
        }
 }
 
@@ -3211,9 +3335,10 @@ int seq_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str)
 {
        char name[sizeof(seq_a->name)];
 
-       if(seq_a->len != seq_b->len)
+       if(seq_a->len != seq_b->len) {
                *error_str= "Strips must be the same length";
                return 0;
+       }
 
        /* type checking, could be more advanced but disalow sound vs non-sound copy */
        if(seq_a->type != seq_b->type) {
@@ -3423,7 +3548,7 @@ void seq_load_apply(Scene *scene, Sequence *seq, SeqLoadInfo *seq_load)
 
                if(seq_load->flag & SEQ_LOAD_SOUND_CACHE) {
                        if(seq->sound)
-                               sound_cache(seq->sound, 0);
+                               sound_cache(seq->sound);
                }
 
                seq_load->tot_success++;
@@ -3450,6 +3575,7 @@ Sequence *alloc_sequence(ListBase *lb, int cfra, int machine)
        seq->mul= 1.0;
        seq->blend_opacity = 100.0;
        seq->volume = 1.0f;
+       seq->pitch = 1.0f;
        seq->scene_sound = NULL;
 
        return seq;
@@ -3479,8 +3605,10 @@ Sequence *sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
        return seq;
 }
 
+#ifdef WITH_AUDASPACE
 Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
 {
+       Main *bmain= CTX_data_main(C);
        Scene *scene= CTX_data_scene(C); /* only for sound */
        Editing *ed= seq_give_editing(scene, TRUE);
        bSound *sound;
@@ -3502,7 +3630,7 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
        info = AUD_getInfo(sound->playback_handle);
 
        if (info.specs.channels == AUD_CHANNELS_INVALID) {
-               sound_delete(C, sound);
+               sound_delete(bmain, sound);
                //if(op)
                //      BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
                return NULL;
@@ -3530,12 +3658,21 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
        calc_sequence_disp(scene, seq);
 
        /* last active name */
-       strncpy(ed->act_sounddir, strip->dir, FILE_MAXDIR-1);
+       BLI_strncpy(ed->act_sounddir, strip->dir, FILE_MAXDIR);
 
        seq_load_apply(scene, seq, seq_load);
 
        return seq;
 }
+#else // WITH_AUDASPACE
+Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
+{
+       (void)C;
+       (void)seqbasep;
+       (void)seq_load;
+       return NULL;
+}
+#endif // WITH_AUDASPACE
 
 Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
 {
@@ -3551,7 +3688,7 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
        BLI_strncpy(path, seq_load->path, sizeof(path));
        BLI_path_abs(path, G.main->name);
 
-       an = openanim(path, IB_rect);
+       an = openanim(path, IB_rect, 0);
 
        if(an==NULL)
                return NULL;
@@ -3567,7 +3704,7 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
 
        /* basic defaults */
        seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
-       strip->len = seq->len = IMB_anim_get_duration( an );
+       strip->len = seq->len = IMB_anim_get_duration( an, IMB_TC_RECORD_RUN );
        strip->us= 1;
 
        /* we only need 1 element for MOVIE strips */