4f19cfa86afa5cf9d31c3b33f215ec9bf66eb04a
[blender-staging.git] / source / blender / editors / space_sequencer / sequencer_edit.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation, 2003-2009
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <stdlib.h>
29 #include <math.h>
30 #include <string.h>
31
32 #ifndef WIN32
33 #include <unistd.h>
34 #else
35 #include <io.h>
36 #endif
37 #include <sys/types.h>
38
39 #include "MEM_guardedalloc.h"
40
41 #include "BLI_blenlib.h"
42 #include "BLI_math.h"
43 #include "BLI_storage_types.h"
44
45 #include "IMB_imbuf_types.h"
46 #include "IMB_imbuf.h"
47
48 #include "DNA_ipo_types.h"
49 #include "DNA_curve_types.h"
50 #include "DNA_scene_types.h"
51 #include "DNA_screen_types.h"
52 #include "DNA_space_types.h"
53 #include "DNA_sequence_types.h"
54 #include "DNA_view2d_types.h"
55 #include "DNA_userdef_types.h"
56 #include "DNA_sound_types.h"
57
58 #include "BKE_context.h"
59 #include "BKE_global.h"
60 #include "BKE_image.h"
61 #include "BKE_library.h"
62 #include "BKE_main.h"
63 #include "BKE_plugin_types.h"
64 #include "BKE_sequencer.h"
65 #include "BKE_scene.h"
66 #include "BKE_utildefines.h"
67 #include "BKE_report.h"
68 #include "BKE_sound.h"
69
70 #include "WM_api.h"
71 #include "WM_types.h"
72
73 #include "RNA_access.h"
74 #include "RNA_define.h"
75
76 /* for menu/popup icons etc etc*/
77 #include "UI_interface.h"
78 #include "UI_resources.h"
79
80 #include "ED_anim_api.h"
81 #include "ED_space_api.h"
82 #include "ED_types.h"
83 #include "ED_screen.h"
84 #include "ED_transform.h"
85 #include "ED_util.h"
86 #include "ED_sequencer.h"
87
88 #include "UI_interface.h"
89 #include "UI_resources.h"
90 #include "UI_view2d.h"
91
92 /* own include */
93 #include "sequencer_intern.h"
94
95 /* XXX */
96 //static Sequence *_last_seq=0;
97 //static int _last_seq_init=0;
98 /* XXX */
99 static void error() {}
100 static void waitcursor(int val) {}
101 static void activate_fileselect() {}
102 static int pupmenu() {return 0;}
103 static int okee() {return 0;}
104
105
106 /* XXX */
107 /* RNA Enums, used in multiple files */
108 EnumPropertyItem sequencer_prop_effect_types[] = {
109         {SEQ_CROSS, "CROSS", 0, "Crossfade", "Crossfade effect strip type"},
110         {SEQ_ADD, "ADD", 0, "Add", "Add effect strip type"},
111         {SEQ_SUB, "SUBTRACT", 0, "Subtract", "Subtract effect strip type"},
112         {SEQ_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", "Alpha Over effect strip type"},
113         {SEQ_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", "Alpha Under effect strip type"},
114         {SEQ_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", "Gamma Cross effect strip type"},
115         {SEQ_MUL, "MULTIPLY", 0, "Multiply", "Multiply effect strip type"},
116         {SEQ_OVERDROP, "OVER_DROP", 0, "Alpha Over Drop", "Alpha Over Drop effect strip type"},
117         {SEQ_PLUGIN, "PLUGIN", 0, "Plugin", "Plugin effect strip type"},
118         {SEQ_WIPE, "WIPE", 0, "Wipe", "Wipe effect strip type"},
119         {SEQ_GLOW, "GLOW", 0, "Glow", "Glow effect strip type"},
120         {SEQ_TRANSFORM, "TRANSFORM", 0, "Transform", "Transform effect strip type"},
121         {SEQ_COLOR, "COLOR", 0, "Color", "Color effect strip type"},
122         {SEQ_SPEED, "SPEED", 0, "Speed", "Color effect strip type"},
123         {0, NULL, 0, NULL, NULL}
124 };
125
126 /* mute operator */
127
128 EnumPropertyItem prop_side_types[] = {
129         {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""},
130         {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
131         {SEQ_SIDE_BOTH, "BOTH", 0, "Both", ""},
132         {0, NULL, 0, NULL, NULL}
133 };
134
135 EnumPropertyItem prop_side_lr_types[] = {
136         {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""},
137         {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
138         {0, NULL, 0, NULL, NULL}
139 };
140
141 typedef struct TransSeq {
142         int start, machine;
143         int startstill, endstill;
144         int startdisp, enddisp;
145         int startofs, endofs;
146         int final_left, final_right;
147         int len;
148 } TransSeq;
149
150 Sequence *get_foreground_frame_seq(Scene *scene, int frame)
151 {
152         Editing *ed= seq_give_editing(scene, FALSE);
153         Sequence *seq, *best_seq=NULL;
154         int best_machine = -1;
155         
156         if(!ed) return NULL;
157         
158         for (seq=ed->seqbasep->first; seq; seq= seq->next) {
159                 if(seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame)
160                         continue;
161                 /* only use elements you can see - not */
162                 if (ELEM5(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE, SEQ_COLOR)) {
163                         if (seq->machine > best_machine) {
164                                 best_seq = seq;
165                                 best_machine = seq->machine;
166                         }
167                 }
168         }
169         return best_seq;
170 }
171
172 void seq_rectf(Sequence *seq, rctf *rectf)
173 {
174         if(seq->startstill) rectf->xmin= seq->start;
175         else rectf->xmin= seq->startdisp;
176         rectf->ymin= seq->machine+SEQ_STRIP_OFSBOTTOM;
177         if(seq->endstill) rectf->xmax= seq->start+seq->len;
178         else rectf->xmax= seq->enddisp;
179         rectf->ymax= seq->machine+SEQ_STRIP_OFSTOP;
180 }
181
182 static void change_plugin_seq(Scene *scene, char *str)  /* called from fileselect */
183 {
184         Editing *ed= seq_give_editing(scene, FALSE);
185         struct SeqEffectHandle sh;
186         Sequence *last_seq= active_seq_get(scene);
187
188         if(last_seq && last_seq->type != SEQ_PLUGIN) return;
189
190         sh = get_sequence_effect(last_seq);
191         sh.free(last_seq);
192         sh.init_plugin(last_seq, str);
193
194         last_seq->machine = MAX3(last_seq->seq1->machine, 
195                                  last_seq->seq2->machine, 
196                                  last_seq->seq3->machine);
197
198         if( seq_test_overlap(ed->seqbasep, last_seq) ) shuffle_seq(ed->seqbasep, last_seq, scene);
199         
200 }
201
202
203 void boundbox_seq(Scene *scene, rctf *rect)
204 {
205         Sequence *seq;
206         Editing *ed= seq_give_editing(scene, FALSE);
207         float min[2], max[2];
208
209         
210         if(ed==NULL) return;
211
212         min[0]= 0.0;
213         max[0]= EFRA+1;
214         min[1]= 0.0;
215         max[1]= 8.0;
216
217         seq= ed->seqbasep->first;
218         while(seq) {
219
220                 if( min[0] > seq->startdisp-1) min[0]= seq->startdisp-1;
221                 if( max[0] < seq->enddisp+1) max[0]= seq->enddisp+1;
222                 if( max[1] < seq->machine+2.0) max[1]= seq->machine+2.0;
223
224                 seq= seq->next;
225         }
226
227         rect->xmin= min[0];
228         rect->xmax= max[0];
229         rect->ymin= min[1];
230         rect->ymax= max[1];
231
232 }
233
234 int mouse_frame_side(View2D *v2d, short mouse_x, int frame ) 
235 {
236         short mval[2];
237         float mouseloc[2];
238         
239         mval[0]= mouse_x;
240         mval[1]= 0;
241         
242         /* choose the side based on which side of the playhead the mouse is on */
243         UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouseloc[0], &mouseloc[1]);
244         
245         return mouseloc[0] > frame ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT;
246 }
247
248
249 Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int sel) 
250 {
251         /* sel - 0==unselected, 1==selected, -1==done care*/
252         Sequence *seq;
253         Editing *ed= seq_give_editing(scene, FALSE);
254
255         if(ed==NULL) return NULL;
256
257         if (sel>0) sel = SELECT;
258         
259         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
260                 if(     (seq!=test) &&
261                         (test->machine==seq->machine) &&
262                         ((sel == -1) || (sel && (seq->flag & SELECT)) || (sel==0 && (seq->flag & SELECT)==0)  ))
263                 {
264                         switch (lr) {
265                         case SEQ_SIDE_LEFT:
266                                 if (test->startdisp == (seq->enddisp)) {
267                                         return seq;
268                                 }
269                                 break;
270                         case SEQ_SIDE_RIGHT:
271                                 if (test->enddisp == (seq->startdisp)) {
272                                         return seq;
273                                 }
274                                 break;
275                         }
276                 }
277         }
278         return NULL;
279 }
280
281 Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, int sel) 
282 {
283         /* sel - 0==unselected, 1==selected, -1==done care*/
284         Sequence *seq,*best_seq = NULL;
285         Editing *ed= seq_give_editing(scene, FALSE);
286         
287         int dist, best_dist;
288         best_dist = MAXFRAME*2;
289
290         
291         if(ed==NULL) return NULL;
292
293         seq= ed->seqbasep->first;
294         while(seq) {
295                 if(             (seq!=test) &&
296                                 (test->machine==seq->machine) &&
297                                 (test->depth==seq->depth) &&
298                                 ((sel == -1) || (sel==(seq->flag & SELECT))))
299                 {
300                         dist = MAXFRAME*2;
301                         
302                         switch (lr) {
303                         case SEQ_SIDE_LEFT:
304                                 if (seq->enddisp <= test->startdisp) {
305                                         dist = test->enddisp - seq->startdisp;
306                                 }
307                                 break;
308                         case SEQ_SIDE_RIGHT:
309                                 if (seq->startdisp >= test->enddisp) {
310                                         dist = seq->startdisp - test->enddisp;
311                                 }
312                                 break;
313                         }
314                         
315                         if (dist==0) {
316                                 best_seq = seq;
317                                 break;
318                         } else if (dist < best_dist) {
319                                 best_dist = dist;
320                                 best_seq = seq;
321                         }
322                 }
323                 seq= seq->next;
324         }
325         return best_seq; /* can be null */
326 }
327
328
329 Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, short mval[2])
330 {
331         Sequence *seq;
332         Editing *ed= seq_give_editing(scene, FALSE);
333         float x, y;
334         float pixelx;
335         float handsize;
336         float displen;
337         *hand= SEQ_SIDE_NONE;
338
339         
340         if(ed==NULL) return NULL;
341         
342         pixelx = (v2d->cur.xmax - v2d->cur.xmin)/(v2d->mask.xmax - v2d->mask.xmin);
343
344         UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
345         
346         seq= ed->seqbasep->first;
347         
348         while(seq) {
349                 if(seq->machine == (int)y) {
350                         /* check for both normal strips, and strips that have been flipped horizontally */
351                         if( ((seq->startdisp < seq->enddisp) && (seq->startdisp<=x && seq->enddisp>=x)) ||
352                                 ((seq->startdisp > seq->enddisp) && (seq->startdisp>=x && seq->enddisp<=x)) )
353                         {
354                                 if(seq_tx_test(seq)) {
355                                         
356                                         /* clamp handles to defined size in pixel space */
357                                         
358                                         handsize = seq->handsize;
359                                         displen = (float)abs(seq->startdisp - seq->enddisp);
360                                         
361                                         if (displen / pixelx > 16) { /* dont even try to grab the handles of small strips */
362                                                 /* Set the max value to handle to 1/3 of the total len when its less then 28.
363                                                 * This is important because otherwise selecting handles happens even when you click in the middle */
364                                                 
365                                                 if ((displen/3) < 30*pixelx) {
366                                                         handsize = displen/3;
367                                                 } else {
368                                                         CLAMP(handsize, 7*pixelx, 30*pixelx);
369                                                 }
370                                                 
371                                                 if( handsize+seq->startdisp >=x )
372                                                         *hand= SEQ_SIDE_LEFT;
373                                                 else if( -handsize+seq->enddisp <=x )
374                                                         *hand= SEQ_SIDE_RIGHT;
375                                         }
376                                 }
377                                 return seq;
378                         }
379                 }
380                 seq= seq->next;
381         }
382         return 0;
383 }
384
385
386 static int seq_is_parent(Sequence *par, Sequence *seq)
387 {
388         return ((par->seq1 == seq) || (par->seq2 == seq) || (par->seq3 == seq));
389 }
390
391 static int seq_is_predecessor(Sequence *pred, Sequence *seq)
392 {
393         if (!pred) return 0;
394         if(pred == seq) return 0;
395         else if(seq_is_parent(pred, seq)) return 1;
396         else if(pred->seq1 && seq_is_predecessor(pred->seq1, seq)) return 1;
397         else if(pred->seq2 && seq_is_predecessor(pred->seq2, seq)) return 1;
398         else if(pred->seq3 && seq_is_predecessor(pred->seq3, seq)) return 1;
399
400         return 0;
401 }
402
403 void deselect_all_seq(Scene *scene)
404 {
405         Sequence *seq;
406         Editing *ed= seq_give_editing(scene, FALSE);
407
408         
409         if(ed==NULL) return;
410
411         SEQP_BEGIN(ed, seq) {
412                 seq->flag &= SEQ_DESEL;
413         }
414         SEQ_END
415                 
416 }
417
418 void recurs_sel_seq(Sequence *seqm)
419 {
420         Sequence *seq;
421
422         seq= seqm->seqbase.first;
423         while(seq) {
424
425                 if(seqm->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL)) seq->flag &= SEQ_DESEL;
426                 else if(seqm->flag & SELECT) seq->flag |= SELECT;
427                 else seq->flag &= SEQ_DESEL;
428
429                 if(seq->seqbase.first) recurs_sel_seq(seq);
430
431                 seq= seq->next;
432         }
433 }
434
435 int event_to_efftype(int event)
436 {
437         if(event==2) return SEQ_CROSS;
438         if(event==3) return SEQ_GAMCROSS;
439         if(event==4) return SEQ_ADD;
440         if(event==5) return SEQ_SUB;
441         if(event==6) return SEQ_MUL;
442         if(event==7) return SEQ_ALPHAOVER;
443         if(event==8) return SEQ_ALPHAUNDER;
444         if(event==9) return SEQ_OVERDROP;
445         if(event==10) return SEQ_PLUGIN;
446         if(event==13) return SEQ_WIPE;
447         if(event==14) return SEQ_GLOW;
448         if(event==15) return SEQ_TRANSFORM;
449         if(event==16) return SEQ_COLOR;
450         if(event==17) return SEQ_SPEED;
451         return 0;
452 }
453
454 #if 0
455 static void reload_sound_strip(Scene *scene, char *name)
456 {
457         Editing *ed;
458         Sequence *seq, *seqact;
459         SpaceFile *sfile;
460         Sequence *last_seq= active_seq_get(scene);
461
462         ed= scene->ed;
463
464         if(last_seq==0 || last_seq->type!=SEQ_SOUND) return;
465         seqact= last_seq;       /* last_seq changes in alloc_sequence */
466
467         /* search sfile */
468 //      sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
469         if(sfile==0) return;
470
471         waitcursor(1);
472
473         seq = sfile_to_snd_sequence(sfile, seqact->start, seqact->machine);
474         printf("seq->type: %i\n", seq->type);
475         if(seq && seq!=seqact) {
476                 /* i'm not sure about this one, seems to work without it -- sgefant */
477                 seq_free_strip(seqact->strip);
478
479                 seqact->strip= seq->strip;
480
481                 seqact->len= seq->len;
482                 calc_sequence(scene, seqact);
483
484                 seq->strip= 0;
485                 seq_free_sequence(scene, seq);
486                 BLI_remlink(ed->seqbasep, seq);
487
488                 seq= ed->seqbasep->first;
489
490         }
491
492         waitcursor(0);
493
494 }
495 #endif
496
497 static void reload_image_strip(Scene *scene, char *name)
498 {
499         Editing *ed= seq_give_editing(scene, FALSE);
500         Sequence *seq=NULL, *seqact;
501         SpaceFile *sfile=NULL;
502         Sequence *last_seq= active_seq_get(scene);
503
504
505
506         if(last_seq==0 || last_seq->type!=SEQ_IMAGE) return;
507         seqact= last_seq;       /* last_seq changes in alloc_sequence */
508
509         /* search sfile */
510 //      sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
511         if(sfile==0) return;
512
513         waitcursor(1);
514
515 //      seq= sfile_to_sequence(scene, sfile, seqact->start, seqact->machine, 1); // XXX ADD BACK
516         if(seq && seq!=seqact) {
517                 seq_free_strip(seqact->strip);
518
519                 seqact->strip= seq->strip;
520
521                 seqact->len= seq->len;
522                 calc_sequence(scene, seqact);
523
524                 seq->strip= 0;
525                 seq_free_sequence(scene, seq);
526                 BLI_remlink(ed->seqbasep, seq);
527
528                 update_changed_seq_and_deps(scene, seqact, 1, 1);
529         }
530         waitcursor(0);
531
532 }
533
534
535 void change_sequence(Scene *scene)
536 {
537         Editing *ed= seq_give_editing(scene, FALSE);
538         Sequence *last_seq= active_seq_get(scene);
539         Scene *sce;
540         short event;
541
542         if(last_seq==0) return;
543
544         if(last_seq->type & SEQ_EFFECT) {
545                 event = pupmenu("Change Effect%t"
546                                 "|Switch A <-> B %x1"
547                                 "|Switch B <-> C %x10"
548                                 "|Plugin%x11"
549                                 "|Recalculate%x12"
550                                 "|Cross%x2"
551                                 "|Gamma Cross%x3"
552                                 "|Add%x4"
553                                 "|Sub%x5"
554                                 "|Mul%x6"
555                                 "|Alpha Over%x7"
556                                 "|Alpha Under%x8"
557                                 "|Alpha Over Drop%x9"
558                                 "|Wipe%x13"
559                                 "|Glow%x14"
560                                 "|Transform%x15"
561                                 "|Color Generator%x16"
562                                 "|Speed Control%x17");
563                 if(event > 0) {
564                         if(event==1) {
565                                 SWAP(Sequence *,last_seq->seq1,last_seq->seq2);
566                         }
567                         else if(event==10) {
568                                 SWAP(Sequence *,last_seq->seq2,last_seq->seq3);
569                         }
570                         else if(event==11) {
571                                 activate_fileselect(
572                                         FILE_SPECIAL, "Select Plugin", 
573                                         U.plugseqdir, change_plugin_seq);
574                         }
575                         else if(event==12);     
576                                 /* recalculate: only new_stripdata */
577                         else {
578                                 /* free previous effect and init new effect */
579                                 struct SeqEffectHandle sh;
580
581                                 if (get_sequence_effect_num_inputs(
582                                             last_seq->type)
583                                     < get_sequence_effect_num_inputs(
584                                             event_to_efftype(event))) {
585                                         error("New effect needs more "
586                                               "input strips!");
587                                 } else {
588                                         sh = get_sequence_effect(last_seq);
589                                         sh.free(last_seq);
590                                         
591                                         last_seq->type 
592                                                 = event_to_efftype(event);
593                                         
594                                         sh = get_sequence_effect(last_seq);
595                                         sh.init(last_seq);
596                                 }
597                         }
598
599                         update_changed_seq_and_deps(scene, last_seq, 0, 1);
600                 }
601         }
602         else if(last_seq->type == SEQ_IMAGE) {
603                 if(okee("Change images")) {
604                         activate_fileselect(FILE_SPECIAL, 
605                                             "Select Images", 
606                                             ed->act_imagedir, 
607                                             reload_image_strip);
608                 }
609         }
610         else if(last_seq->type == SEQ_MOVIE) {
611                 ;
612         }
613         else if(last_seq->type == SEQ_SCENE) {
614                 event= pupmenu("Change Scene%t|Update Start and End");
615
616                 if(event==1) {
617                         sce= last_seq->scene;
618
619                         last_seq->len= sce->r.efra - sce->r.sfra + 1;
620                         last_seq->sfra= sce->r.sfra;
621                         
622                         /* bad code to change seq->len? update_changed_seq_and_deps() expects the strip->len to be OK */
623                         new_tstripdata(last_seq);
624                         
625                         update_changed_seq_and_deps(scene, last_seq, 1, 1);
626
627                 }
628         }
629
630 }
631
632 int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequence **selseq1, Sequence **selseq2, Sequence **selseq3, char **error_str)
633 {
634         Editing *ed = seq_give_editing(scene, FALSE);
635         Sequence *seq1= 0, *seq2= 0, *seq3= 0, *seq;
636         
637         *error_str= NULL;
638
639         if (!activeseq)
640                 seq2= active_seq_get(scene);
641
642         for(seq=ed->seqbasep->first; seq; seq=seq->next) {
643                 if(seq->flag & SELECT) {
644                         if (seq->type == SEQ_SOUND) {
645                                 *error_str= "Can't apply effects to audio sequence strips";
646                                 return 0;
647                         }
648                         if((seq != activeseq) && (seq != seq2)) {
649                                 if(seq2==0) seq2= seq;
650                                 else if(seq1==0) seq1= seq;
651                                 else if(seq3==0) seq3= seq;
652                                 else {
653                                                                         *error_str= "Can't apply effect to more than 3 sequence strips";
654                                                                         return 0;
655                                 }
656                         }
657                 }
658         }
659        
660         /* make sequence selection a little bit more intuitive
661            for 3 strips: the last-strip should be sequence3 */
662         if (seq3 != 0 && seq2 != 0) {
663                 Sequence *tmp = seq2;
664                 seq2 = seq3;
665                 seq3 = tmp;
666         }
667         
668
669         switch(get_sequence_effect_num_inputs(type)) {
670         case 0:
671                 *selseq1 = *selseq2 = *selseq3 = 0;
672                 return 1; /* succsess */
673         case 1:
674                 if(seq2==0)  {
675                         *error_str= "Need at least one selected sequence strip";
676                         return 0;
677                 }
678                 if(seq1==0) seq1= seq2;
679                 if(seq3==0) seq3= seq2;
680         case 2:
681                 if(seq1==0 || seq2==0) {
682                         *error_str= "Need 2 selected sequence strips";
683                         return 0;
684                 }
685                 if(seq3==0) seq3= seq2;
686         }
687         
688         if (seq1==NULL && seq2==NULL && seq3==NULL) {
689                 *error_str= "TODO: in what cases does this happen?";
690                 return 0;
691         }
692         
693         *selseq1= seq1;
694         *selseq2= seq2;
695         *selseq3= seq3;
696
697         return 1;
698 }
699
700 void reassign_inputs_seq_effect(Scene *scene)
701 {
702         Editing *ed= seq_give_editing(scene, FALSE);
703         Sequence *seq1, *seq2, *seq3, *last_seq = active_seq_get(scene);
704         char *error_msg;
705
706         if(last_seq==0 || !(last_seq->type & SEQ_EFFECT)) return;
707         if(ed==NULL) return;
708
709         if(!seq_effect_find_selected(scene, last_seq, last_seq->type, &seq1, &seq2, &seq3, &error_msg)) {
710                 //BKE_report(op->reports, RPT_ERROR, error_msg); // XXX operatorify
711                 return;
712         }
713         /* see reassigning would create a cycle */
714         if(     seq_is_predecessor(seq1, last_seq) ||
715                 seq_is_predecessor(seq2, last_seq) ||
716                 seq_is_predecessor(seq3, last_seq)
717         ) {
718                 //BKE_report(op->reports, RPT_ERROR, "Can't reassign inputs: no cycles allowed"); // XXX operatorify
719                 return;
720         }
721         
722         last_seq->seq1 = seq1;
723         last_seq->seq2 = seq2;
724         last_seq->seq3 = seq3;
725
726         update_changed_seq_and_deps(scene, last_seq, 1, 1);
727
728 }
729
730 static Sequence *del_seq_find_replace_recurs(Scene *scene, Sequence *seq)
731 {
732         Sequence *seq1, *seq2, *seq3;
733
734         /* try to find a replacement input sequence, and flag for later deletion if
735            no replacement can be found */
736
737         if(!seq)
738                 return NULL;
739         else if(!(seq->type & SEQ_EFFECT))
740                 return ((seq->flag & SELECT)? NULL: seq);
741         else if(!(seq->flag & SELECT)) {
742                 /* try to find replacement for effect inputs */
743                 seq1= del_seq_find_replace_recurs(scene, seq->seq1);
744                 seq2= del_seq_find_replace_recurs(scene, seq->seq2);
745                 seq3= del_seq_find_replace_recurs(scene, seq->seq3);
746
747                 if(seq1==seq->seq1 && seq2==seq->seq2 && seq3==seq->seq3);
748                 else if(seq1 || seq2 || seq3) {
749                         seq->seq1= (seq1)? seq1: (seq2)? seq2: seq3;
750                         seq->seq2= (seq2)? seq2: (seq1)? seq1: seq3;
751                         seq->seq3= (seq3)? seq3: (seq1)? seq1: seq2;
752
753                         update_changed_seq_and_deps(scene, seq, 1, 1);
754                 }
755                 else
756                         seq->flag |= SELECT; /* mark for delete */
757         }
758
759         if (seq->flag & SELECT) {
760                 if((seq1 = del_seq_find_replace_recurs(scene, seq->seq1))) return seq1;
761                 if((seq2 = del_seq_find_replace_recurs(scene, seq->seq2))) return seq2;
762                 if((seq3 = del_seq_find_replace_recurs(scene, seq->seq3))) return seq3;
763                 else return NULL;
764         }
765         else
766                 return seq;
767 }
768
769 static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short deleteall)
770 {
771         Sequence *seq, *seqn;
772         Sequence *last_seq = active_seq_get(scene);
773
774         seq= lb->first;
775         while(seq) {
776                 seqn= seq->next;
777                 if((seq->flag & flag) || deleteall) {
778                         if(seq->type==SEQ_SOUND && seq->sound)
779                                 seq->sound->id.us--;
780
781                         BLI_remlink(lb, seq);
782                         if(seq==last_seq) active_seq_set(scene, NULL);
783                         if(seq->type==SEQ_META) recurs_del_seq_flag(scene, &seq->seqbase, flag, 1);
784                         if(seq->ipo) seq->ipo->id.us--;
785                         seq_free_sequence(scene, seq);
786                 }
787                 seq= seqn;
788         }
789 }
790
791 static Sequence *dupli_seq(struct Scene *scene, Sequence *seq)
792 {
793         Sequence *seqn = MEM_dupallocN(seq);
794         // XXX animato: ID *id;
795
796         seq->tmp = seqn;
797                 
798         seqn->strip= MEM_dupallocN(seq->strip);
799
800         // XXX animato
801 #if 0
802         if (seqn->ipo) {
803                 if (U.dupflag & USER_DUP_IPO) {
804                         id= (ID *)seqn->ipo;
805                         seqn->ipo= copy_ipo(seqn->ipo);
806                         /* we don't need to decrease the number
807                          * of the ipo because we never increase it,
808                          * for example, adduplicate need decrease
809                          * the number but only because copy_object
810                          * call id_us_plus for the ipo block and
811                          * single_ipo_users only work if id->us > 1.
812                          *
813                          * need call ipo_idnew here, for drivers ??
814                          * - Diego
815                          */
816                 }
817                 else
818                         seqn->ipo->id.us++;
819         }
820 #endif
821
822         seqn->strip->tstripdata = 0;
823         seqn->strip->tstripdata_startstill = 0;
824         seqn->strip->tstripdata_endstill = 0;
825         seqn->strip->ibuf_startstill = 0;
826         seqn->strip->ibuf_endstill = 0;
827
828         if (seq->strip->crop) {
829                 seqn->strip->crop = MEM_dupallocN(seq->strip->crop);
830         }
831
832         if (seq->strip->transform) {
833                 seqn->strip->transform = MEM_dupallocN(seq->strip->transform);
834         }
835
836         if (seq->strip->proxy) {
837                 seqn->strip->proxy = MEM_dupallocN(seq->strip->proxy);
838         }
839
840         if (seq->strip->color_balance) {
841                 seqn->strip->color_balance 
842                         = MEM_dupallocN(seq->strip->color_balance);
843         }
844         
845         if(seq->type==SEQ_META) {
846                 seqn->strip->stripdata = 0;
847
848                 seqn->seqbase.first= seqn->seqbase.last= 0;
849                 /* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */
850                 /* - recurs_dupli_seq(&seq->seqbase,&seqn->seqbase);*/
851         } else if(seq->type == SEQ_SCENE) {
852                 seqn->strip->stripdata = 0;
853         } else if(seq->type == SEQ_MOVIE) {
854                 seqn->strip->stripdata = 
855                                 MEM_dupallocN(seq->strip->stripdata);
856                 seqn->anim= 0;
857         } else if(seq->type == SEQ_SOUND) {
858                 seqn->strip->stripdata =
859                                 MEM_dupallocN(seq->strip->stripdata);
860                 if(seq->scene_sound)
861                         seqn->scene_sound = sound_add_scene_sound(scene, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
862
863                 seqn->sound->id.us++;
864         } else if(seq->type == SEQ_IMAGE) {
865                 seqn->strip->stripdata = 
866                                 MEM_dupallocN(seq->strip->stripdata);
867         } else if(seq->type >= SEQ_EFFECT) {
868                 if(seq->seq1 && seq->seq1->tmp) seqn->seq1= seq->seq1->tmp;
869                 if(seq->seq2 && seq->seq2->tmp) seqn->seq2= seq->seq2->tmp;
870                 if(seq->seq3 && seq->seq3->tmp) seqn->seq3= seq->seq3->tmp;
871
872                 if (seq->type & SEQ_EFFECT) {
873                         struct SeqEffectHandle sh;
874                         sh = get_sequence_effect(seq);
875                         if(sh.copy)
876                                 sh.copy(seq, seqn);
877                 }
878
879                 seqn->strip->stripdata = 0;
880                 
881         } else {
882                 fprintf(stderr, "Aiiiiekkk! sequence type not "
883                                 "handled in duplicate!\nExpect a crash"
884                                                 " now...\n");
885         }
886
887         seqUniqueName(scene->ed->seqbasep, seqn);
888
889         return seqn;
890 }
891
892 static Sequence * deep_dupli_seq(struct Scene *scene, Sequence * seq)
893 {
894         Sequence * seqn = dupli_seq(scene, seq);
895         if (seq->type == SEQ_META) {
896                 Sequence * s;
897                 for(s= seq->seqbase.first; s; s = s->next) {
898                         Sequence * n = deep_dupli_seq(scene, s);
899                         if (n) { 
900                                 BLI_addtail(&seqn->seqbase, n);
901                         }
902                 }
903         }
904         return seqn;
905 }
906
907
908 static void recurs_dupli_seq(Scene *scene, ListBase *old, ListBase *new, int do_context)
909 {
910         Sequence *seq;
911         Sequence *seqn = 0;
912         Sequence *last_seq = active_seq_get(scene);
913
914         for(seq= old->first; seq; seq= seq->next) {
915                 seq->tmp= NULL;
916                 if(seq->flag & SELECT) {
917                         seqn = dupli_seq(scene, seq);
918                         if (seqn) { /*should never fail */
919                                 if(do_context) {
920                                         seq->flag &= SEQ_DESEL;
921                                         seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL+SEQ_LOCK);
922                                 }
923
924                                 BLI_addtail(new, seqn);
925                                 if(seq->type==SEQ_META)
926                                         recurs_dupli_seq(scene, &seq->seqbase,&seqn->seqbase, do_context);
927                                 
928                                 if(do_context) {
929                                         if (seq == last_seq) {
930                                                 active_seq_set(scene, seqn);
931                                         }
932                                 }
933                         }
934                 }
935         }
936 }
937
938 static Sequence *cut_seq_hard(Scene *scene, Sequence * seq, int cutframe)
939 {
940         TransSeq ts;
941         Sequence *seqn = 0;
942         int skip_dup = FALSE;
943
944         /* backup values */
945         ts.start= seq->start;
946         ts.machine= seq->machine;
947         ts.startstill= seq->startstill;
948         ts.endstill= seq->endstill;
949         ts.startdisp= seq->startdisp;
950         ts.enddisp= seq->enddisp;
951         ts.startofs= seq->anim_startofs;
952         ts.endofs= seq->anim_endofs;
953         ts.len= seq->len;
954         
955         /* First Strip! */
956         /* strips with extended stillfames before */
957         
958         if ((seq->startstill) && (cutframe <seq->start)) {
959                 /* don't do funny things with METAs ... */
960                 if (seq->type == SEQ_META) {
961                         skip_dup = TRUE;
962                         seq->startstill = seq->start - cutframe;
963                 } else {
964                         seq->start= cutframe -1;
965                         seq->startstill= cutframe -seq->startdisp -1;
966                         seq->anim_endofs += seq->len - 1;
967                         seq->endstill= 0;
968                 }
969         }
970         /* normal strip */
971         else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) {
972                 seq->endofs = 0;
973                 seq->endstill = 0;
974                 seq->anim_endofs += (seq->start+seq->len) - cutframe;
975         }
976         /* strips with extended stillframes after */
977         else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
978                 seq->endstill -= seq->enddisp - cutframe;
979                 /* don't do funny things with METAs ... */
980                 if (seq->type == SEQ_META) {
981                         skip_dup = TRUE;
982                 }
983         }
984         
985         reload_sequence_new_file(scene, seq);
986         calc_sequence(scene, seq);
987
988         if (!skip_dup) {
989                 /* Duplicate AFTER the first change */
990                 seqn = deep_dupli_seq(scene, seq);
991         }
992         
993         if (seqn) { 
994                 seqn->flag |= SELECT;
995                         
996                 /* Second Strip! */
997                 /* strips with extended stillframes before */
998                 if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
999                         seqn->start = ts.start;
1000                         seqn->startstill= ts.start- cutframe;
1001                         seqn->anim_endofs = ts.endofs;
1002                         seqn->endstill = ts.endstill;
1003                 }
1004                 
1005                 /* normal strip */
1006                 else if ((cutframe>=seqn->start)&&(cutframe<=(seqn->start+seqn->len))) {
1007                         seqn->start = cutframe;
1008                         seqn->startstill = 0;
1009                         seqn->startofs = 0;
1010                         seqn->anim_startofs += cutframe - ts.start;
1011                         seqn->anim_endofs = ts.endofs;
1012                         seqn->endstill = ts.endstill;
1013                 }                               
1014                 
1015                 /* strips with extended stillframes after */
1016                 else if (((seqn->start+seqn->len) < cutframe) && (seqn->endstill)) {
1017                         seqn->start = cutframe;
1018                         seqn->startofs = 0;
1019                         seqn->anim_startofs += ts.len-1;
1020                         seqn->endstill = ts.enddisp - cutframe -1;
1021                         seqn->startstill = 0;
1022                 }
1023                 
1024                 reload_sequence_new_file(scene, seqn);
1025                 calc_sequence(scene, seqn);
1026         }
1027         return seqn;
1028 }
1029
1030 static Sequence *cut_seq_soft(Scene *scene, Sequence * seq, int cutframe)
1031 {
1032         TransSeq ts;
1033         Sequence *seqn = 0;
1034         int skip_dup = FALSE;
1035
1036         /* backup values */
1037         ts.start= seq->start;
1038         ts.machine= seq->machine;
1039         ts.startstill= seq->startstill;
1040         ts.endstill= seq->endstill;
1041         ts.startdisp= seq->startdisp;
1042         ts.enddisp= seq->enddisp;
1043         ts.startofs= seq->startofs;
1044         ts.endofs= seq->endofs;
1045         ts.len= seq->len;
1046         
1047         /* First Strip! */
1048         /* strips with extended stillfames before */
1049         
1050         if ((seq->startstill) && (cutframe <seq->start)) {
1051                 /* don't do funny things with METAs ... */
1052                 if (seq->type == SEQ_META) {
1053                         skip_dup = TRUE;
1054                         seq->startstill = seq->start - cutframe;
1055                 } else {
1056                         seq->start= cutframe -1;
1057                         seq->startstill= cutframe -seq->startdisp -1;
1058                         seq->endofs = seq->len - 1;
1059                         seq->endstill= 0;
1060                 }
1061         }
1062         /* normal strip */
1063         else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) {
1064                 seq->endofs = (seq->start+seq->len) - cutframe;
1065         }
1066         /* strips with extended stillframes after */
1067         else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
1068                 seq->endstill -= seq->enddisp - cutframe;
1069                 /* don't do funny things with METAs ... */
1070                 if (seq->type == SEQ_META) {
1071                         skip_dup = TRUE;
1072                 }
1073         }
1074         
1075         calc_sequence(scene, seq);
1076
1077         if (!skip_dup) {
1078                 /* Duplicate AFTER the first change */
1079                 seqn = deep_dupli_seq(scene, seq);
1080         }
1081         
1082         if (seqn) { 
1083                 seqn->flag |= SELECT;
1084                         
1085                 /* Second Strip! */
1086                 /* strips with extended stillframes before */
1087                 if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
1088                         seqn->start = ts.start;
1089                         seqn->startstill= ts.start- cutframe;
1090                         seqn->endofs = ts.endofs;
1091                         seqn->endstill = ts.endstill;
1092                 }
1093                 
1094                 /* normal strip */
1095                 else if ((cutframe>=seqn->start)&&(cutframe<=(seqn->start+seqn->len))) {
1096                         seqn->startstill = 0;
1097                         seqn->startofs = cutframe - ts.start;
1098                         seqn->endofs = ts.endofs;
1099                         seqn->endstill = ts.endstill;
1100                 }                               
1101                 
1102                 /* strips with extended stillframes after */
1103                 else if (((seqn->start+seqn->len) < cutframe) && (seqn->endstill)) {
1104                         seqn->start = cutframe - ts.len +1;
1105                         seqn->startofs = ts.len-1;
1106                         seqn->endstill = ts.enddisp - cutframe -1;
1107                         seqn->startstill = 0;
1108                 }
1109                 
1110                 calc_sequence(scene, seqn);
1111         }
1112         return seqn;
1113 }
1114
1115
1116 /* like duplicate, but only duplicate and cut overlapping strips,
1117  * strips to the left of the cutframe are ignored and strips to the right are moved into the new list */
1118 static int cut_seq_list(Scene *scene, ListBase *old, ListBase *new, int cutframe,
1119                         Sequence * (*cut_seq)(Scene *, Sequence *, int))
1120 {
1121         int did_something = FALSE;
1122         Sequence *seq, *seq_next;
1123         
1124         seq= old->first;
1125         
1126         while(seq) {
1127                 seq_next = seq->next; /* we need this because we may remove seq */
1128                 
1129                 seq->tmp= NULL;
1130                 if(seq->flag & SELECT) {
1131                         if(cutframe > seq->startdisp && 
1132                            cutframe < seq->enddisp) {
1133                                 Sequence * seqn = cut_seq(scene, seq, cutframe);
1134                                 if (seqn) {
1135                                         BLI_addtail(new, seqn);
1136                                 }
1137                                 did_something = TRUE;
1138                         } else if (seq->enddisp <= cutframe) {
1139                                 /* do nothing */
1140                         } else if (seq->startdisp >= cutframe) {
1141                                 /* move into new list */
1142                                 BLI_remlink(old, seq);
1143                                 BLI_addtail(new, seq);
1144                         }
1145                 }
1146                 seq = seq_next;
1147         }
1148         return did_something;
1149 }
1150
1151 int insert_gap(Scene *scene, int gap, int cfra)
1152 {
1153         Sequence *seq;
1154         Editing *ed= seq_give_editing(scene, FALSE);
1155         int done=0;
1156
1157         /* all strips >= cfra are shifted */
1158         
1159         if(ed==NULL) return 0;
1160
1161         SEQP_BEGIN(ed, seq) {
1162                 if(seq->startdisp >= cfra) {
1163                         seq->start+= gap;
1164                         calc_sequence(scene, seq);
1165                         done= 1;
1166                 }
1167         }
1168         SEQ_END
1169
1170         return done;
1171 }
1172
1173 void touch_seq_files(Scene *scene)
1174 {
1175         Sequence *seq;
1176         Editing *ed= seq_give_editing(scene, FALSE);
1177         char str[256];
1178
1179         /* touch all strips with movies */
1180         
1181         if(ed==NULL) return;
1182
1183         if(okee("Touch and print selected movies")==0) return;
1184
1185         waitcursor(1);
1186
1187         SEQP_BEGIN(ed, seq) {
1188                 if(seq->flag & SELECT) {
1189                         if(seq->type==SEQ_MOVIE) {
1190                                 if(seq->strip && seq->strip->stripdata) {
1191                                         BLI_make_file_string(G.sce, str, seq->strip->dir, seq->strip->stripdata->name);
1192                                         BLI_touch(seq->name);
1193                                 }
1194                         }
1195
1196                 }
1197         }
1198         SEQ_END
1199
1200         waitcursor(0);
1201 }
1202
1203 void set_filter_seq(Scene *scene)
1204 {
1205         Sequence *seq;
1206         Editing *ed= seq_give_editing(scene, FALSE);
1207
1208         
1209         if(ed==NULL) return;
1210
1211         if(okee("Set Deinterlace")==0) return;
1212
1213         SEQP_BEGIN(ed, seq) {
1214                 if(seq->flag & SELECT) {
1215                         if(seq->type==SEQ_MOVIE) {
1216                                 seq->flag |= SEQ_FILTERY;
1217                                 reload_sequence_new_file(scene, seq);
1218                         }
1219
1220                 }
1221         }
1222         SEQ_END
1223
1224 }
1225
1226 void seq_remap_paths(Scene *scene)
1227 {
1228         Sequence *seq, *last_seq = active_seq_get(scene);
1229         Editing *ed= seq_give_editing(scene, FALSE);
1230         char from[FILE_MAX], to[FILE_MAX], stripped[FILE_MAX];
1231         
1232         
1233         if(last_seq==NULL) 
1234                 return;
1235         
1236         BLI_strncpy(from, last_seq->strip->dir, FILE_MAX);
1237 // XXX  if (0==sbutton(from, 0, sizeof(from)-1, "From: "))
1238 //              return;
1239         
1240         strcpy(to, from);
1241 // XXX  if (0==sbutton(to, 0, sizeof(to)-1, "To: "))
1242 //              return;
1243         
1244         if (strcmp(to, from)==0)
1245                 return;
1246         
1247         SEQP_BEGIN(ed, seq) {
1248                 if(seq->flag & SELECT) {
1249                         if(strncmp(seq->strip->dir, from, strlen(from))==0) {
1250                                 printf("found %s\n", seq->strip->dir);
1251                                 
1252                                 /* strip off the beginning */
1253                                 stripped[0]= 0;
1254                                 BLI_strncpy(stripped, seq->strip->dir + strlen(from), FILE_MAX);
1255                                 
1256                                 /* new path */
1257                                 BLI_strncpy(seq->strip->dir, to, FILE_MAX);
1258                                 strcat(seq->strip->dir, stripped);
1259                                 printf("new %s\n", seq->strip->dir);
1260                         }
1261                 }
1262         }
1263         SEQ_END
1264                 
1265 }
1266
1267
1268 void no_gaps(Scene *scene)
1269 {
1270         Editing *ed= seq_give_editing(scene, FALSE);
1271         int cfra, first= 0, done;
1272
1273         
1274         if(ed==NULL) return;
1275
1276         for(cfra= CFRA; cfra<=EFRA; cfra++) {
1277                 if(first==0) {
1278                         if( evaluate_seq_frame(scene, cfra) ) first= 1;
1279                 }
1280                 else {
1281                         done= 1;
1282                         while( evaluate_seq_frame(scene, cfra) == 0) {
1283                                 done= insert_gap(scene, -1, cfra);
1284                                 if(done==0) break;
1285                         }
1286                         if(done==0) break;
1287                 }
1288         }
1289
1290 }
1291
1292 #if 0
1293 static int seq_get_snaplimit(View2D *v2d)
1294 {
1295         /* fake mouse coords to get the snap value
1296         a bit lazy but its only done once pre transform */
1297         float xmouse, ymouse, x;
1298         short mval[2] = {24, 0}; /* 24 screen px snap */
1299         
1300         UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
1301         x = xmouse;
1302         mval[0] = 0;
1303         UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
1304         return (int)(x - xmouse);
1305 }
1306 #endif
1307
1308 /* Operator functions */
1309
1310 /* snap operator*/
1311 static int sequencer_snap_exec(bContext *C, wmOperator *op)
1312 {
1313         Scene *scene= CTX_data_scene(C);
1314         
1315         Editing *ed= seq_give_editing(scene, FALSE);
1316         Sequence *seq;
1317         int snap_frame;
1318         
1319         if(ed==NULL) return OPERATOR_CANCELLED;
1320
1321         snap_frame= RNA_int_get(op->ptr, "frame");
1322
1323         /* problem: contents of meta's are all shifted to the same position... */
1324
1325         /* also check metas */
1326         SEQP_BEGIN(ed, seq) {
1327                 if (seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK) &&
1328                     seq_tx_test(seq)) {
1329                         if((seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))==0) {
1330                                 seq->start= snap_frame-seq->startofs+seq->startstill;
1331                         } else { 
1332                                 if(seq->flag & SEQ_LEFTSEL) {
1333                                         seq_tx_set_final_left(seq, snap_frame);
1334                                 } else { /* SEQ_RIGHTSEL */
1335                                         seq_tx_set_final_right(seq, snap_frame);
1336                                 }
1337                                 seq_tx_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
1338                         }
1339                         calc_sequence(scene, seq);
1340                 }
1341         }
1342         SEQ_END
1343
1344         /* test for effects and overlap */
1345         SEQP_BEGIN(ed, seq) {
1346                 if(seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK)) {
1347                         seq->flag &= ~SEQ_OVERLAP;
1348                         if( seq_test_overlap(ed->seqbasep, seq) ) {
1349                                 shuffle_seq(ed->seqbasep, seq, scene);
1350                         }
1351                 }
1352                 else if(seq->type & SEQ_EFFECT) {
1353                         if(seq->seq1 && (seq->seq1->flag & SELECT)) 
1354                                 calc_sequence(scene, seq);
1355                         else if(seq->seq2 && (seq->seq2->flag & SELECT)) 
1356                                 calc_sequence(scene, seq);
1357                         else if(seq->seq3 && (seq->seq3->flag & SELECT)) 
1358                                 calc_sequence(scene, seq);
1359                 }
1360         }
1361         SEQ_END;
1362
1363         /* as last: */
1364         sort_seq(scene);
1365         
1366         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1367         
1368         return OPERATOR_FINISHED;
1369 }
1370
1371 static int sequencer_snap_invoke(bContext *C, wmOperator *op, wmEvent *event)
1372 {
1373         Scene *scene = CTX_data_scene(C);
1374         
1375         int snap_frame;
1376         
1377         snap_frame= CFRA;
1378         
1379         RNA_int_set(op->ptr, "frame", snap_frame);
1380         return sequencer_snap_exec(C, op);
1381 }
1382
1383 void SEQUENCER_OT_snap(struct wmOperatorType *ot)
1384 {
1385         /* identifiers */
1386         ot->name= "Snap strips";
1387         ot->idname= "SEQUENCER_OT_snap";
1388         ot->description="Frame where selected strips will be snapped.";
1389         
1390         /* api callbacks */
1391         ot->invoke= sequencer_snap_invoke;
1392         ot->exec= sequencer_snap_exec;
1393
1394         ot->poll= ED_operator_sequencer_active;
1395         
1396         /* flags */
1397         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1398         
1399         RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be snapped", INT_MIN, INT_MAX);
1400 }
1401
1402 /* mute operator */
1403 static int sequencer_mute_exec(bContext *C, wmOperator *op)
1404 {
1405         Scene *scene= CTX_data_scene(C);
1406         Editing *ed= seq_give_editing(scene, FALSE);
1407         Sequence *seq;
1408         int selected;
1409
1410         if(ed==NULL)
1411                 return OPERATOR_CANCELLED;
1412
1413         selected= !RNA_boolean_get(op->ptr, "unselected");
1414         
1415         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1416                 if ((seq->flag & SEQ_LOCK)==0) {
1417                         if(selected){ /* mute unselected */
1418                                 if(seq->flag & SELECT)
1419                                         seq->flag |= SEQ_MUTE;
1420                         }
1421                         else {
1422                                 if((seq->flag & SELECT)==0)
1423                                         seq->flag |= SEQ_MUTE;
1424                         }
1425                 }
1426         }
1427         
1428         seq_update_muting(scene, ed);
1429         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1430         
1431         return OPERATOR_FINISHED;
1432 }
1433
1434 void SEQUENCER_OT_mute(struct wmOperatorType *ot)
1435 {
1436         /* identifiers */
1437         ot->name= "Mute Strips";
1438         ot->idname= "SEQUENCER_OT_mute";
1439         ot->description="Mute selected strips.";
1440         
1441         /* api callbacks */
1442         ot->exec= sequencer_mute_exec;
1443
1444         ot->poll= ED_operator_sequencer_active;
1445         
1446         /* flags */
1447         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1448         
1449         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Mute unselected rather than selected strips.");
1450 }
1451
1452
1453 /* unmute operator */
1454 static int sequencer_unmute_exec(bContext *C, wmOperator *op)
1455 {
1456         Scene *scene= CTX_data_scene(C);
1457         Editing *ed= seq_give_editing(scene, FALSE);
1458         Sequence *seq;
1459         int selected;
1460
1461         if(ed==NULL)
1462                 return OPERATOR_CANCELLED;
1463
1464         selected= !RNA_boolean_get(op->ptr, "unselected");
1465         
1466         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1467                 if ((seq->flag & SEQ_LOCK)==0) {
1468                         if(selected){ /* unmute unselected */
1469                                 if(seq->flag & SELECT)
1470                                         seq->flag &= ~SEQ_MUTE;
1471                         }
1472                         else {
1473                                 if((seq->flag & SELECT)==0)
1474                                         seq->flag &= ~SEQ_MUTE;
1475                         }
1476                 }
1477         }
1478         
1479         seq_update_muting(scene, ed);
1480         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1481         
1482         return OPERATOR_FINISHED;
1483 }
1484
1485 void SEQUENCER_OT_unmute(struct wmOperatorType *ot)
1486 {
1487         /* identifiers */
1488         ot->name= "UnMute Strips";
1489         ot->idname= "SEQUENCER_OT_unmute";
1490         ot->description="UnMute unselected rather than selected strips.";
1491         
1492         /* api callbacks */
1493         ot->exec= sequencer_unmute_exec;
1494
1495         ot->poll= ED_operator_sequencer_active;
1496         
1497         /* flags */
1498         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1499         
1500         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "UnMute unselected rather than selected strips.");
1501 }
1502
1503
1504 /* lock operator */
1505 static int sequencer_lock_exec(bContext *C, wmOperator *op)
1506 {
1507         Scene *scene= CTX_data_scene(C);
1508         Editing *ed= seq_give_editing(scene, FALSE);
1509         Sequence *seq;
1510
1511         if(ed==NULL)
1512                 return OPERATOR_CANCELLED;
1513
1514         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1515                 if (seq->flag & SELECT) {
1516                         seq->flag |= SEQ_LOCK;
1517                 }
1518         }
1519
1520         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1521
1522         return OPERATOR_FINISHED;
1523 }
1524
1525 void SEQUENCER_OT_lock(struct wmOperatorType *ot)
1526 {
1527         /* identifiers */
1528         ot->name= "Lock Strips";
1529         ot->idname= "SEQUENCER_OT_lock";
1530         ot->description="Lock the active strip so that it can't be transformed.";
1531         
1532         /* api callbacks */
1533         ot->exec= sequencer_lock_exec;
1534
1535         ot->poll= ED_operator_sequencer_active;
1536         
1537         /* flags */
1538         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1539 }
1540
1541 /* unlock operator */
1542 static int sequencer_unlock_exec(bContext *C, wmOperator *op)
1543 {
1544         Scene *scene= CTX_data_scene(C);
1545         Editing *ed= seq_give_editing(scene, FALSE);
1546         Sequence *seq;
1547
1548         if(ed==NULL)
1549                 return OPERATOR_CANCELLED;
1550
1551         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1552                 if (seq->flag & SELECT) {
1553                         seq->flag &= ~SEQ_LOCK;
1554                 }
1555         }
1556
1557         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1558
1559         return OPERATOR_FINISHED;
1560 }
1561
1562 void SEQUENCER_OT_unlock(struct wmOperatorType *ot)
1563 {
1564         /* identifiers */
1565         ot->name= "UnLock Strips";
1566         ot->idname= "SEQUENCER_OT_unlock";
1567         ot->description="Unlock the active strip so that it can't be transformed.";
1568         
1569         /* api callbacks */
1570         ot->exec= sequencer_unlock_exec;
1571
1572         ot->poll= ED_operator_sequencer_active;
1573         
1574         /* flags */
1575         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1576 }
1577
1578 /* reload operator */
1579 static int sequencer_reload_exec(bContext *C, wmOperator *op)
1580 {
1581         Scene *scene= CTX_data_scene(C);
1582         Editing *ed= seq_give_editing(scene, FALSE);
1583         Sequence *seq;
1584
1585         if(ed==NULL)
1586                 return OPERATOR_CANCELLED;
1587
1588         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1589                 if(seq->flag & SELECT) {
1590                         update_changed_seq_and_deps(scene, seq, 0, 1);
1591                 }
1592         }
1593
1594         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1595
1596         return OPERATOR_FINISHED;
1597 }
1598
1599 void SEQUENCER_OT_reload(struct wmOperatorType *ot)
1600 {
1601         /* identifiers */
1602         ot->name= "Reload Strips";
1603         ot->idname= "SEQUENCER_OT_reload";
1604         ot->description="Reload strips in the sequencer.";
1605         
1606         /* api callbacks */
1607         ot->exec= sequencer_reload_exec;
1608
1609         ot->poll= ED_operator_sequencer_active;
1610         
1611         /* flags */
1612         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1613 }
1614
1615 /* reload operator */
1616 static int sequencer_refresh_all_exec(bContext *C, wmOperator *op)
1617 {
1618         Scene *scene= CTX_data_scene(C);
1619         Editing *ed= seq_give_editing(scene, FALSE);
1620         
1621         if(ed==NULL)
1622                 return OPERATOR_CANCELLED;
1623
1624         free_imbuf_seq(scene, &ed->seqbase, FALSE);
1625
1626         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1627
1628         return OPERATOR_FINISHED;
1629 }
1630
1631 void SEQUENCER_OT_refresh_all(struct wmOperatorType *ot)
1632 {
1633         /* identifiers */
1634         ot->name= "Refresh Sequencer";
1635         ot->idname= "SEQUENCER_OT_refresh_all";
1636         ot->description="Refresh the sequencer editor.";
1637         
1638         /* api callbacks */
1639         ot->exec= sequencer_refresh_all_exec;
1640
1641         ot->poll= ED_operator_sequencer_active;
1642         
1643         /* flags */
1644         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1645 }
1646
1647 /* cut operator */
1648 static EnumPropertyItem prop_cut_types[] = {
1649         {SEQ_CUT_SOFT, "SOFT", 0, "Soft", ""},
1650         {SEQ_CUT_HARD, "HARD", 0, "Hard", ""},
1651         {0, NULL, 0, NULL, NULL}
1652 };
1653
1654 static int sequencer_cut_exec(bContext *C, wmOperator *op)
1655 {
1656         Scene *scene= CTX_data_scene(C);
1657         Editing *ed= seq_give_editing(scene, FALSE);
1658         int cut_side, cut_hard, cut_frame;
1659
1660         ListBase newlist;
1661         int changed;
1662         
1663         if(ed==NULL)
1664                 return OPERATOR_CANCELLED;
1665
1666         cut_frame= RNA_int_get(op->ptr, "frame");
1667         cut_hard= RNA_enum_get(op->ptr, "type");
1668         cut_side= RNA_enum_get(op->ptr, "side");
1669         
1670         newlist.first= newlist.last= NULL;
1671
1672         if (cut_hard==SEQ_CUT_HARD) {
1673                 changed = cut_seq_list(scene,
1674                         ed->seqbasep, &newlist, cut_frame, cut_seq_hard);
1675         } else {
1676                 changed = cut_seq_list(scene,
1677                         ed->seqbasep, &newlist, cut_frame, cut_seq_soft);
1678         }
1679         
1680         if (newlist.first) { /* got new strips ? */
1681                 Sequence *seq;
1682                 addlisttolist(ed->seqbasep, &newlist);
1683
1684                 if (cut_side != SEQ_SIDE_BOTH) {
1685                         SEQP_BEGIN(ed, seq) {
1686                                 if (cut_side==SEQ_SIDE_LEFT) {
1687                                         if ( seq->startdisp >= cut_frame ) {
1688                                                 seq->flag &= SEQ_DESEL;
1689                                         }
1690                                 } else {
1691                                         if ( seq->enddisp <= cut_frame ) {
1692                                                 seq->flag &= SEQ_DESEL;
1693                                         }
1694                                 }
1695                         }
1696                         SEQ_END;
1697                 }
1698                 /* as last: */
1699                 sort_seq(scene);
1700         }
1701
1702         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1703         
1704         return OPERATOR_FINISHED;
1705 }
1706
1707
1708 static int sequencer_cut_invoke(bContext *C, wmOperator *op, wmEvent *event)
1709 {
1710         Scene *scene = CTX_data_scene(C);
1711         ARegion *ar= CTX_wm_region(C);
1712         View2D *v2d= UI_view2d_fromcontext(C);
1713         
1714         int cut_side, cut_frame;
1715         
1716         cut_frame= CFRA;
1717         cut_side= mouse_frame_side(v2d, event->x - ar->winrct.xmin, cut_frame);
1718         
1719         RNA_int_set(op->ptr, "frame", cut_frame);
1720         RNA_enum_set(op->ptr, "side", cut_side);
1721         /*RNA_enum_set(op->ptr, "type", cut_hard); */ /*This type is set from the key shortcut */
1722
1723         return sequencer_cut_exec(C, op);
1724 }
1725
1726
1727 void SEQUENCER_OT_cut(struct wmOperatorType *ot)
1728 {
1729         /* identifiers */
1730         ot->name= "Cut Strips";
1731         ot->idname= "SEQUENCER_OT_cut";
1732         ot->description="Cut the selected strips.";
1733         
1734         /* api callbacks */
1735         ot->invoke= sequencer_cut_invoke;
1736         ot->exec= sequencer_cut_exec;
1737
1738         ot->poll= ED_operator_sequencer_active;
1739         
1740         /* flags */
1741         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1742         
1743         RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be cut", INT_MIN, INT_MAX);
1744         RNA_def_enum(ot->srna, "type", prop_cut_types, SEQ_CUT_SOFT, "Type", "The type of cut operation to perform on strips");
1745         RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side that remains selected after cutting");
1746 }
1747
1748 /* duplicate operator */
1749 static int sequencer_add_duplicate_exec(bContext *C, wmOperator *op)
1750 {
1751         Scene *scene= CTX_data_scene(C);
1752         Editing *ed= seq_give_editing(scene, FALSE);
1753
1754         ListBase new= {NULL, NULL};
1755
1756         if(ed==NULL)
1757                 return OPERATOR_CANCELLED;
1758
1759         recurs_dupli_seq(scene, ed->seqbasep, &new, TRUE);
1760         addlisttolist(ed->seqbasep, &new);
1761
1762         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1763
1764         return OPERATOR_FINISHED;
1765 }
1766
1767 static int sequencer_add_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event)
1768 {
1769         sequencer_add_duplicate_exec(C, op);
1770
1771         RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
1772         WM_operator_name_call(C, "TRANSFORM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
1773
1774         return OPERATOR_FINISHED;
1775 }
1776
1777 void SEQUENCER_OT_duplicate(wmOperatorType *ot)
1778 {
1779
1780         /* identifiers */
1781         ot->name= "Duplicate";
1782         ot->idname= "SEQUENCER_OT_duplicate";
1783         ot->description="Duplicate the selected strips.";
1784         
1785         /* api callbacks */
1786         ot->invoke= sequencer_add_duplicate_invoke;
1787         ot->exec= sequencer_add_duplicate_exec;
1788
1789         ot->poll= ED_operator_sequencer_active;
1790         
1791         /* flags */
1792         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1793         
1794         /* to give to transform */
1795         RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
1796 }
1797
1798 /* delete operator */
1799 static int sequencer_delete_exec(bContext *C, wmOperator *op)
1800 {
1801         Scene *scene= CTX_data_scene(C);
1802         Editing *ed= seq_give_editing(scene, FALSE);
1803         Sequence *seq;
1804         MetaStack *ms;
1805         int nothingSelected = TRUE;
1806
1807         if(ed==NULL)
1808                 return OPERATOR_CANCELLED;
1809
1810         seq=active_seq_get(scene);
1811         if (seq && seq->flag & SELECT) { /* avoid a loop since this is likely to be selected */
1812                 nothingSelected = FALSE;
1813         } else {
1814                 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1815                         if (seq->flag & SELECT) {
1816                                 nothingSelected = FALSE;
1817                                 break;
1818                         }
1819                 }
1820         }
1821
1822         if (nothingSelected)
1823                 return OPERATOR_FINISHED;
1824
1825         /* free imbufs of all dependent strips */
1826         for(seq=ed->seqbasep->first; seq; seq=seq->next)
1827                 if(seq->flag & SELECT)
1828                         update_changed_seq_and_deps(scene, seq, 1, 0);
1829
1830         /* for effects, try to find a replacement input */
1831         for(seq=ed->seqbasep->first; seq; seq=seq->next)
1832                 if((seq->type & SEQ_EFFECT) && !(seq->flag & SELECT))
1833                         del_seq_find_replace_recurs(scene, seq);
1834
1835         /* delete all selected strips */
1836         recurs_del_seq_flag(scene, ed->seqbasep, SELECT, 0);
1837
1838         /* updates lengths etc */
1839         seq= ed->seqbasep->first;
1840         while(seq) {
1841                 calc_sequence(scene, seq);
1842                 seq= seq->next;
1843         }
1844
1845         /* free parent metas */
1846         ms= ed->metastack.last;
1847         while(ms) {
1848                 ms->parseq->strip->len= 0;              /* force new alloc */
1849                 calc_sequence(scene, ms->parseq);
1850                 ms= ms->prev;
1851         }
1852
1853         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1854         
1855         return OPERATOR_FINISHED;
1856 }
1857
1858
1859 void SEQUENCER_OT_delete(wmOperatorType *ot)
1860 {
1861
1862         /* identifiers */
1863         ot->name= "Erase Strips";
1864         ot->idname= "SEQUENCER_OT_delete";
1865         ot->description="Erase selected strips from the sequencer.";
1866         
1867         /* api callbacks */
1868         ot->invoke= WM_operator_confirm;
1869         ot->exec= sequencer_delete_exec;
1870
1871         ot->poll= ED_operator_sequencer_active;
1872         
1873         /* flags */
1874         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1875 }
1876
1877
1878 /* separate_images operator */
1879 static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
1880 {
1881         Scene *scene= CTX_data_scene(C);
1882         Editing *ed= seq_give_editing(scene, FALSE);
1883         
1884         Sequence *seq, *seq_new, *seq_next;
1885         Strip *strip_new;
1886         StripElem *se, *se_new;
1887         int start_ofs, cfra, frame_end;
1888         int step= RNA_int_get(op->ptr, "length");
1889
1890         if(ed==NULL)
1891                 return OPERATOR_CANCELLED;
1892
1893         seq= ed->seqbasep->first;
1894
1895         while (seq) {
1896                 if((seq->flag & SELECT) && (seq->type == SEQ_IMAGE) && (seq->len > 1)) {
1897                         /* remove seq so overlap tests dont conflict,
1898                         see seq_free_sequence below for the real free'ing */
1899                         seq_next = seq->next;
1900                         BLI_remlink(ed->seqbasep, seq);
1901                         if(seq->ipo) seq->ipo->id.us--;
1902
1903                         start_ofs = cfra = seq_tx_get_final_left(seq, 0);
1904                         frame_end = seq_tx_get_final_right(seq, 0);
1905
1906                         while (cfra < frame_end) {
1907                                 /* new seq */
1908                                 se = give_stripelem(seq, cfra);
1909
1910                                 seq_new= alloc_sequence(ed->seqbasep, start_ofs, seq->machine);
1911                                 seq_new->type= SEQ_IMAGE;
1912                                 seq_new->len = 1;
1913                                 seq_new->endstill = step-1;
1914
1915                                 /* new strip */
1916                                 seq_new->strip= strip_new= MEM_callocN(sizeof(Strip)*1, "strip");
1917                                 strip_new->len= 1;
1918                                 strip_new->us= 1;
1919                                 strncpy(strip_new->dir, seq->strip->dir, FILE_MAXDIR-1);
1920
1921                                 /* new stripdata */
1922                                 strip_new->stripdata= se_new= MEM_callocN(sizeof(StripElem)*1, "stripelem");
1923                                 strncpy(se_new->name, se->name, FILE_MAXFILE-1);
1924                                 calc_sequence(scene, seq_new);
1925                                 seq_new->flag &= ~SEQ_OVERLAP;
1926                                 if (seq_test_overlap(ed->seqbasep, seq_new)) {
1927                                         shuffle_seq(ed->seqbasep, seq_new, scene);
1928                                 }
1929
1930                                 seqUniqueName(scene->ed->seqbasep, seq_new);
1931
1932                                 cfra++;
1933                                 start_ofs += step;
1934                         }
1935
1936                         seq_free_sequence(scene, seq);
1937                         seq = seq->next;
1938                 } else {
1939                         seq = seq->next;
1940                 }
1941         }
1942
1943         /* as last: */
1944         sort_seq(scene);
1945         
1946         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1947
1948         return OPERATOR_FINISHED;
1949 }
1950
1951
1952 void SEQUENCER_OT_images_separate(wmOperatorType *ot)
1953 {
1954         /* identifiers */
1955         ot->name= "Separate Images";
1956         ot->idname= "SEQUENCER_OT_images_separate";
1957         ot->description="On image sequences strips, it return a strip for each image.";
1958         
1959         /* api callbacks */
1960         ot->invoke= WM_operator_props_popup;
1961         ot->exec= sequencer_separate_images_exec;
1962
1963         ot->poll= ED_operator_sequencer_active;
1964         
1965         /* flags */
1966         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1967
1968         RNA_def_int(ot->srna, "length", 1, 1, 1000, "Length", "Length of each frame", 1, INT_MAX);
1969 }
1970
1971
1972 /* META Operators */
1973
1974 /* separate_meta_toggle operator */
1975 static int sequencer_meta_toggle_exec(bContext *C, wmOperator *op)
1976 {
1977         Scene *scene= CTX_data_scene(C);
1978         Editing *ed= seq_give_editing(scene, FALSE);
1979         Sequence *last_seq= active_seq_get(scene);
1980         MetaStack *ms;
1981
1982         if(ed==NULL)
1983                 return OPERATOR_CANCELLED;
1984
1985         if(last_seq && last_seq->type==SEQ_META && last_seq->flag & SELECT) {
1986                 /* Enter Metastrip */
1987                 ms= MEM_mallocN(sizeof(MetaStack), "metastack");
1988                 BLI_addtail(&ed->metastack, ms);
1989                 ms->parseq= last_seq;
1990                 ms->oldbasep= ed->seqbasep;
1991
1992                 ed->seqbasep= &last_seq->seqbase;
1993
1994                 active_seq_set(scene, NULL);
1995
1996         }
1997         else {
1998                 /* Exit Metastrip (if possible) */
1999
2000                 Sequence *seq;
2001
2002                 if(ed->metastack.first==NULL)
2003                         return OPERATOR_CANCELLED;
2004
2005                 ms= ed->metastack.last;
2006                 BLI_remlink(&ed->metastack, ms);
2007
2008                 ed->seqbasep= ms->oldbasep;
2009
2010                 /* recalc all: the meta can have effects connected to it */
2011                 for(seq= ed->seqbasep->first; seq; seq= seq->next)
2012                         calc_sequence(scene, seq);
2013
2014                 active_seq_set(scene, ms->parseq);
2015
2016                 ms->parseq->flag |= SELECT;
2017                 recurs_sel_seq(ms->parseq);
2018
2019                 MEM_freeN(ms);
2020
2021         }
2022
2023         seq_update_muting(scene, ed);
2024         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2025
2026         return OPERATOR_FINISHED;
2027 }
2028
2029 void SEQUENCER_OT_meta_toggle(wmOperatorType *ot)
2030 {
2031         /* identifiers */
2032         ot->name= "Toggle Meta Strip";
2033         ot->idname= "SEQUENCER_OT_meta_toggle";
2034         ot->description="Toggle a metastrip (to edit enclosed strips).";
2035         
2036         /* api callbacks */
2037         ot->exec= sequencer_meta_toggle_exec;
2038
2039         ot->poll= ED_operator_sequencer_active;
2040         
2041         /* flags */
2042         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2043 }
2044
2045
2046 /* separate_meta_make operator */
2047 static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
2048 {
2049         Scene *scene= CTX_data_scene(C);
2050         Editing *ed= seq_give_editing(scene, FALSE);
2051         
2052         Sequence *seq, *seqm, *next;
2053         
2054         int channel_max= 1;
2055
2056         if(ed==NULL)
2057                 return OPERATOR_CANCELLED;
2058
2059         if(seqbase_isolated_sel_check(ed->seqbasep)==FALSE) {
2060                 BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
2061                 return OPERATOR_CANCELLED;
2062         }
2063
2064         /* remove all selected from main list, and put in meta */
2065
2066         seqm= alloc_sequence(ed->seqbasep, 1, 1); /* channel number set later */
2067         strcpy(seqm->name+2, "MetaStrip");
2068         seqm->type= SEQ_META;
2069         seqm->flag= SELECT;
2070
2071         seq= ed->seqbasep->first;
2072         while(seq) {
2073                 next= seq->next;
2074                 if(seq!=seqm && (seq->flag & SELECT)) {
2075                         channel_max= MAX2(seq->machine, channel_max);
2076                         BLI_remlink(ed->seqbasep, seq);
2077                         BLI_addtail(&seqm->seqbase, seq);
2078                 }
2079                 seq= next;
2080         }
2081         seqm->machine= channel_max;
2082         calc_sequence(scene, seqm);
2083
2084         seqm->strip= MEM_callocN(sizeof(Strip), "metastrip");
2085         seqm->strip->len= seqm->len;
2086         seqm->strip->us= 1;
2087         
2088         active_seq_set(scene, seqm);
2089
2090         if( seq_test_overlap(ed->seqbasep, seqm) ) shuffle_seq(ed->seqbasep, seqm, scene);
2091
2092         seq_update_muting(scene, ed);
2093
2094         seqUniqueName(scene->ed->seqbasep, seqm);
2095
2096         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2097
2098         return OPERATOR_FINISHED;
2099 }
2100
2101 void SEQUENCER_OT_meta_make(wmOperatorType *ot)
2102 {
2103         /* identifiers */
2104         ot->name= "Make Meta Strip";
2105         ot->idname= "SEQUENCER_OT_meta_make";
2106         ot->description="Group selected strips into a metastrip.";
2107         
2108         /* api callbacks */
2109         ot->invoke= WM_operator_confirm;
2110         ot->exec= sequencer_meta_make_exec;
2111
2112         ot->poll= ED_operator_sequencer_active;
2113         
2114         /* flags */
2115         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2116 }
2117
2118
2119 static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
2120 {
2121         if (seq == seqm) return 1;
2122         else if (seq->seq1 && seq_depends_on_meta(seq->seq1, seqm)) return 1;
2123         else if (seq->seq2 && seq_depends_on_meta(seq->seq2, seqm)) return 1;
2124         else if (seq->seq3 && seq_depends_on_meta(seq->seq3, seqm)) return 1;
2125         else return 0;
2126 }
2127
2128 /* separate_meta_make operator */
2129 static int sequencer_meta_separate_exec(bContext *C, wmOperator *op)
2130 {
2131         Scene *scene= CTX_data_scene(C);
2132         Editing *ed= seq_give_editing(scene, FALSE);
2133
2134         Sequence *seq, *last_seq = active_seq_get(scene); /* last_seq checks ed==NULL */
2135
2136         if(last_seq==NULL || last_seq->type!=SEQ_META)
2137                 return OPERATOR_CANCELLED;
2138
2139         addlisttolist(ed->seqbasep, &last_seq->seqbase);
2140
2141         last_seq->seqbase.first= 0;
2142         last_seq->seqbase.last= 0;
2143
2144         BLI_remlink(ed->seqbasep, last_seq);
2145         seq_free_sequence(scene, last_seq);
2146
2147         /* emtpy meta strip, delete all effects depending on it */
2148         for(seq=ed->seqbasep->first; seq; seq=seq->next)
2149                 if((seq->type & SEQ_EFFECT) && seq_depends_on_meta(seq, last_seq))
2150                         seq->flag |= SEQ_FLAG_DELETE;
2151
2152         recurs_del_seq_flag(scene, ed->seqbasep, SEQ_FLAG_DELETE, 0);
2153
2154         /* test for effects and overlap */
2155         SEQP_BEGIN(ed, seq) {
2156                 if(seq->flag & SELECT) {
2157                         seq->flag &= ~SEQ_OVERLAP;
2158                         if( seq_test_overlap(ed->seqbasep, seq) ) {
2159                                 shuffle_seq(ed->seqbasep, seq, scene);
2160                         }
2161                 }
2162         }
2163         SEQ_END;
2164
2165         sort_seq(scene);
2166         seq_update_muting(scene, ed);
2167
2168         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2169
2170         return OPERATOR_FINISHED;
2171 }
2172
2173 void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
2174 {
2175         /* identifiers */
2176         ot->name= "UnMeta Strip";
2177         ot->idname= "SEQUENCER_OT_meta_separate";
2178         ot->description="Put the contents of a metastrip back in the sequencer.";
2179         
2180         /* api callbacks */
2181         ot->invoke= WM_operator_confirm;
2182         ot->exec= sequencer_meta_separate_exec;
2183
2184         ot->poll= ED_operator_sequencer_active;
2185         
2186         /* flags */
2187         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2188 }
2189
2190 /* view_all operator */
2191 static int sequencer_view_all_exec(bContext *C, wmOperator *op)
2192 {
2193         //Scene *scene= CTX_data_scene(C);
2194         bScreen *sc= CTX_wm_screen(C);
2195         ScrArea *area= CTX_wm_area(C);
2196         //ARegion *ar= CTX_wm_region(C);
2197         View2D *v2d= UI_view2d_fromcontext(C);
2198
2199         v2d->cur= v2d->tot;
2200         UI_view2d_curRect_validate(v2d);
2201         UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
2202         
2203         ED_area_tag_redraw(CTX_wm_area(C));
2204         return OPERATOR_FINISHED;
2205 }
2206
2207 void SEQUENCER_OT_view_all(wmOperatorType *ot)
2208 {
2209         /* identifiers */
2210         ot->name= "View All";
2211         ot->idname= "SEQUENCER_OT_view_all";
2212         ot->description="View all the strips in the sequencer.";
2213         
2214         /* api callbacks */
2215         ot->exec= sequencer_view_all_exec;
2216
2217         ot->poll= ED_operator_sequencer_active;
2218         
2219         /* flags */
2220         ot->flag= OPTYPE_REGISTER;
2221 }
2222
2223 /* view_all operator */
2224 static int sequencer_view_all_preview_exec(bContext *C, wmOperator *op)
2225 {
2226         Scene *scene= CTX_data_scene(C);
2227         bScreen *sc= CTX_wm_screen(C);
2228         ScrArea *area= CTX_wm_area(C);
2229         ARegion *ar= CTX_wm_region(C);
2230         SpaceSeq *sseq= area->spacedata.first;
2231         View2D *v2d= UI_view2d_fromcontext(C);
2232
2233         v2d->cur= v2d->tot;
2234         UI_view2d_curRect_validate(v2d);
2235         UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
2236         
2237 #if 0
2238         /* Like zooming on an image view */
2239         float zoomX, zoomY;
2240         int width, height, imgwidth, imgheight;
2241
2242         width = ar->winx;
2243         height = ar->winy;
2244
2245         seq_reset_imageofs(sseq);
2246
2247         imgwidth= (scene->r.size*scene->r.xsch)/100;
2248         imgheight= (scene->r.size*scene->r.ysch)/100;
2249
2250         /* Apply aspect, dosnt need to be that accurate */
2251         imgwidth= (int)(imgwidth * ((float)scene->r.xasp / (float)scene->r.yasp));
2252
2253         if (((imgwidth >= width) || (imgheight >= height)) &&
2254                 ((width > 0) && (height > 0))) {
2255
2256                 /* Find the zoom value that will fit the image in the image space */
2257                 zoomX = ((float)width) / ((float)imgwidth);
2258                 zoomY = ((float)height) / ((float)imgheight);
2259                 sseq->zoom= (zoomX < zoomY) ? zoomX : zoomY;
2260
2261                 sseq->zoom = 1.0f / power_of_2(1/ MIN2(zoomX, zoomY) );
2262         }
2263         else {
2264                 sseq->zoom= 1.0f;
2265         }
2266 #endif
2267
2268         ED_area_tag_redraw(CTX_wm_area(C));
2269         return OPERATOR_FINISHED;
2270 }
2271
2272 void SEQUENCER_OT_view_all_preview(wmOperatorType *ot)
2273 {
2274         /* identifiers */
2275         ot->name= "View All";
2276         ot->idname= "SEQUENCER_OT_view_all_preview";
2277         ot->description="Zoom preview to fit in the area.";
2278         
2279         /* api callbacks */
2280         ot->exec= sequencer_view_all_preview_exec;
2281
2282         ot->poll= ED_operator_sequencer_active;
2283         
2284         /* flags */
2285         ot->flag= OPTYPE_REGISTER;
2286 }
2287
2288 #if 0
2289 static EnumPropertyItem view_type_items[] = {
2290                 {SEQ_VIEW_SEQUENCE, "SEQUENCER", ICON_SEQ_SEQUENCER, "Sequencer", ""},
2291                 {SEQ_VIEW_PREVIEW,  "PREVIEW", ICON_SEQ_PREVIEW, "Image Preview", ""},
2292                 {SEQ_VIEW_SEQUENCE_PREVIEW,  "SEQUENCER_PREVIEW", ICON_SEQ_SEQUENCER, "Sequencer and Image Preview", ""},
2293                 {0, NULL, 0, NULL, NULL}};
2294 #endif
2295
2296 /* view_all operator */
2297 static int sequencer_view_toggle_exec(bContext *C, wmOperator *op)
2298 {
2299         SpaceSeq *sseq= (SpaceSeq *)CTX_wm_space_data(C);
2300
2301         sseq->view++;
2302         if (sseq->view > SEQ_VIEW_SEQUENCE_PREVIEW) sseq->view = SEQ_VIEW_SEQUENCE;
2303
2304         ED_sequencer_update_view(C, sseq->view);
2305
2306         return OPERATOR_FINISHED;
2307 }
2308
2309 void SEQUENCER_OT_view_toggle(wmOperatorType *ot)
2310 {
2311         /* identifiers */
2312         ot->name= "View Toggle";
2313         ot->idname= "SEQUENCER_OT_view_toggle";
2314         ot->description="Toggle between sequencer views (sequence, preview, both).";
2315         
2316         /* api callbacks */
2317         ot->exec= sequencer_view_toggle_exec;
2318         ot->poll= ED_operator_sequencer_active;
2319         
2320         /* flags */
2321         ot->flag= OPTYPE_REGISTER;
2322 }
2323
2324
2325 /* view_selected operator */
2326 static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
2327 {
2328         Scene *scene= CTX_data_scene(C);
2329         View2D *v2d= UI_view2d_fromcontext(C);
2330         ScrArea *area= CTX_wm_area(C);
2331         bScreen *sc= CTX_wm_screen(C);
2332         Editing *ed= seq_give_editing(scene, FALSE);
2333         Sequence *seq;
2334
2335         int xmin=  MAXFRAME*2;
2336         int xmax= -MAXFRAME*2;
2337         int ymin=  MAXSEQ+1;
2338         int ymax= 0;
2339         int orig_height;
2340         int ymid;
2341         int ymargin= 1;
2342         int xmargin= FPS;
2343
2344         if(ed==NULL)
2345                 return OPERATOR_CANCELLED;
2346
2347         for(seq=ed->seqbasep->first; seq; seq=seq->next) {
2348                 if(seq->flag & SELECT) {
2349                         xmin= MIN2(xmin, seq->startdisp);
2350                         xmax= MAX2(xmax, seq->enddisp);
2351
2352                         ymin= MIN2(ymin, seq->machine);
2353                         ymax= MAX2(ymax, seq->machine);
2354                 }
2355         }
2356
2357         if (ymax != 0) {
2358                 
2359                 xmax += xmargin;
2360                 xmin -= xmargin;
2361                 ymax += ymargin;
2362                 ymin -= ymargin;
2363
2364                 orig_height= v2d->cur.ymax - v2d->cur.ymin;
2365
2366                 v2d->cur.xmin= xmin;
2367                 v2d->cur.xmax= xmax;
2368
2369                 v2d->cur.ymin= ymin;
2370                 v2d->cur.ymax= ymax;
2371
2372                 /* only zoom out vertically */
2373                 if (orig_height > v2d->cur.ymax - v2d->cur.ymin) {
2374                         ymid= (v2d->cur.ymax + v2d->cur.ymin) / 2;
2375
2376                         v2d->cur.ymin= ymid - (orig_height/2);
2377                         v2d->cur.ymax= ymid + (orig_height/2);
2378                 }
2379
2380                 UI_view2d_curRect_validate(v2d);
2381                 UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
2382
2383                 ED_area_tag_redraw(CTX_wm_area(C));
2384         }
2385         
2386         return OPERATOR_FINISHED;
2387 }
2388
2389 void SEQUENCER_OT_view_selected(wmOperatorType *ot)
2390 {
2391         /* identifiers */
2392         ot->name= "View Selected";
2393         ot->idname= "SEQUENCER_OT_view_selected";
2394         ot->description="Zoom the sequencer on the selected strips.";
2395         
2396         /* api callbacks */
2397         ot->exec= sequencer_view_selected_exec;
2398
2399         ot->poll= ED_operator_sequencer_active;
2400         
2401         /* flags */
2402         ot->flag= OPTYPE_REGISTER;
2403 }
2404
2405
2406 static int find_next_prev_edit(Scene *scene, int cfra, int side)
2407 {
2408         Editing *ed= seq_give_editing(scene, FALSE);
2409         Sequence *seq,*best_seq = NULL,*frame_seq = NULL;
2410         
2411         int dist, best_dist;
2412         best_dist = MAXFRAME*2;
2413
2414         if(ed==NULL) return cfra;
2415         
2416         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
2417                 dist = MAXFRAME*2;
2418                         
2419                 switch (side) {
2420                         case SEQ_SIDE_LEFT:
2421                                 if (seq->startdisp < cfra) {
2422                                         dist = cfra - seq->startdisp;
2423                                 }
2424                                 break;
2425                         case SEQ_SIDE_RIGHT:
2426                                 if (seq->startdisp > cfra) {
2427                                         dist = seq->startdisp - cfra;
2428                                 } else if (seq->startdisp == cfra) {
2429                                         frame_seq=seq;
2430                                 }
2431                                 break;
2432                 }
2433
2434                 if (dist < best_dist) {
2435                         best_dist = dist;
2436                         best_seq = seq;
2437                 }
2438         }
2439
2440         /* if no sequence to the right is found and the
2441            frame is on the start of the last sequence,
2442            move to the end of the last sequence */
2443         if (frame_seq) cfra = frame_seq->enddisp;
2444
2445         return best_seq ? best_seq->startdisp : cfra;
2446 }
2447
2448 static int next_prev_edit_internal(Scene *scene, int side)
2449 {
2450         int change=0;
2451         int cfra = CFRA;
2452         int nfra= find_next_prev_edit(scene, cfra, side);
2453         
2454         if (nfra != cfra) {
2455                 CFRA = nfra;
2456                 change= 1;
2457         }
2458
2459         return change;
2460 }
2461
2462 /* move frame to next edit point operator */
2463 static int sequencer_next_edit_exec(bContext *C, wmOperator *op)
2464 {
2465         Scene *scene= CTX_data_scene(C);
2466         
2467         if(!next_prev_edit_internal(scene, SEQ_SIDE_RIGHT))
2468                 return OPERATOR_CANCELLED;
2469
2470         WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
2471
2472         return OPERATOR_FINISHED;
2473 }
2474
2475 void SEQUENCER_OT_next_edit(wmOperatorType *ot)
2476 {
2477         /* identifiers */
2478         ot->name= "Next Edit";
2479         ot->idname= "SEQUENCER_OT_next_edit";
2480         ot->description="Move frame to next edit point.";
2481         
2482         /* api callbacks */
2483         ot->exec= sequencer_next_edit_exec;
2484         ot->poll= ED_operator_sequencer_active;
2485         
2486         /* flags */
2487         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2488         
2489         /* properties */
2490 }
2491
2492 /* move frame to previous edit point operator */
2493 static int sequencer_previous_edit_exec(bContext *C, wmOperator *op)
2494 {
2495         Scene *scene= CTX_data_scene(C);
2496         
2497         if(!next_prev_edit_internal(scene, SEQ_SIDE_LEFT))
2498                 return OPERATOR_CANCELLED;
2499
2500         WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
2501         
2502         return OPERATOR_FINISHED;
2503 }
2504
2505 void SEQUENCER_OT_previous_edit(wmOperatorType *ot)
2506 {
2507         /* identifiers */
2508         ot->name= "Previous Edit";
2509         ot->idname= "SEQUENCER_OT_previous_edit";
2510         ot->description="Move frame to previous edit point.";
2511         
2512         /* api callbacks */
2513         ot->exec= sequencer_previous_edit_exec;
2514         ot->poll= ED_operator_sequencer_active;
2515         
2516         /* flags */
2517         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2518         
2519         /* properties */
2520 }
2521
2522 static void swap_sequence(Scene* scene, Sequence* seqa, Sequence* seqb)
2523 {
2524         int gap = seqb->startdisp - seqa->enddisp;
2525         seqb->start = seqa->start;
2526         calc_sequence(scene, seqb);
2527         seqa->start = seqb->enddisp + gap;
2528         calc_sequence(scene, seqa);
2529 }
2530
2531 static Sequence* sequence_find_parent(Scene* scene, Sequence* child)
2532 {
2533         Editing *ed= seq_give_editing(scene, FALSE);
2534         Sequence *parent= NULL;
2535         Sequence *seq;
2536
2537         if(ed==NULL) return NULL;
2538
2539         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
2540                 if ( (seq != child) && seq_is_parent(seq, child) ) {
2541                         parent = seq;
2542                         break;
2543                 }
2544         }
2545         return parent;
2546
2547 }
2548
2549 static int sequencer_swap_exec(bContext *C, wmOperator *op)
2550 {
2551         Scene *scene= CTX_data_scene(C);
2552         Editing *ed= seq_give_editing(scene, FALSE);
2553         Sequence *active_seq = active_seq_get(scene);
2554         Sequence *seq, *iseq;
2555         int side= RNA_enum_get(op->ptr, "side");
2556
2557         if(ed==NULL) return OPERATOR_CANCELLED;
2558         if(active_seq==NULL) return OPERATOR_CANCELLED;
2559
2560         seq = find_next_prev_sequence(scene, active_seq, side, -1);
2561         
2562         if(seq) {
2563                 
2564                 /* disallow effect strips */
2565                 if ((seq->type!=SEQ_COLOR) && (seq->effectdata || seq->seq1 || seq->seq2 || seq->seq3))
2566                         return OPERATOR_CANCELLED;
2567                 if ((active_seq->type!=SEQ_COLOR) && (active_seq->effectdata || active_seq->seq1 || active_seq->seq2 || active_seq->seq3))
2568                         return OPERATOR_CANCELLED;
2569
2570                 switch (side) {
2571                         case SEQ_SIDE_LEFT: 
2572                                 swap_sequence(scene, seq, active_seq);
2573                                 break;
2574                         case SEQ_SIDE_RIGHT: 
2575                                 swap_sequence(scene, active_seq, seq);
2576                                 break;
2577                 }
2578
2579                 // XXX - should be a generic function
2580                 for(iseq= scene->ed->seqbasep->first; iseq; iseq= iseq->next) {
2581                         if((iseq->type & SEQ_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
2582                                 calc_sequence(scene, iseq);
2583                         }
2584                 }
2585
2586                 /* do this in a new loop since both effects need to be calculated first */
2587                 for(iseq= scene->ed->seqbasep->first; iseq; iseq= iseq->next) {
2588                         if((iseq->type & SEQ_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
2589                                 /* this may now overlap */
2590                                 if( seq_test_overlap(ed->seqbasep, iseq) ) {
2591                                         shuffle_seq(ed->seqbasep, iseq, scene);
2592                                 }
2593                         }
2594                 }
2595
2596
2597
2598                 sort_seq(scene);
2599
2600                 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2601
2602                 return OPERATOR_FINISHED;
2603         }
2604
2605         return OPERATOR_CANCELLED;
2606 }
2607
2608 void SEQUENCER_OT_swap(wmOperatorType *ot)
2609 {
2610         /* identifiers */
2611         ot->name= "Swap Strip";
2612         ot->idname= "SEQUENCER_OT_swap";
2613         ot->description="Swap active strip with strip to the left.";
2614         
2615         /* api callbacks */
2616         ot->exec= sequencer_swap_exec;
2617         ot->poll= ED_operator_sequencer_active;
2618         
2619         /* flags */
2620         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2621         
2622         /* properties */
2623         RNA_def_enum(ot->srna, "side", prop_side_lr_types, SEQ_SIDE_RIGHT, "Side", "Side of the strip to swap");
2624 }
2625
2626 static int sequencer_rendersize_exec(bContext *C, wmOperator *op)
2627 {
2628         int retval = OPERATOR_CANCELLED;
2629         Scene *scene= CTX_data_scene(C);
2630         Sequence *active_seq = active_seq_get(scene);
2631
2632         if(active_seq==NULL)
2633                 return OPERATOR_CANCELLED;
2634
2635         switch (active_seq->type) {
2636                 case SEQ_IMAGE:
2637                 case SEQ_MOVIE:
2638                         if (active_seq->strip) {
2639                                 // prevent setting the render size if sequence values aren't initialized
2640                                 if ( (active_seq->strip->orx>0) && (active_seq->strip->ory>0) ) {
2641                                         scene->r.xsch= active_seq->strip->orx;
2642                                         scene->r.ysch= active_seq->strip->ory;
2643                                         WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
2644                                         retval = OPERATOR_FINISHED;
2645                                 }
2646                         }
2647                         break;
2648                 case SEQ_SCENE:
2649                 case SEQ_META:
2650                 case SEQ_RAM_SOUND:
2651                 case SEQ_HD_SOUND:
2652                 default:
2653                         break;
2654         }
2655         return retval;
2656 }
2657
2658 void SEQUENCER_OT_rendersize(wmOperatorType *ot)
2659 {
2660         /* identifiers */
2661         ot->name= "Set Render Size";
2662         ot->idname= "SEQUENCER_OT_rendersize";
2663         ot->description="Set render size and aspect from active sequence.";
2664         
2665         /* api callbacks */
2666         ot->exec= sequencer_rendersize_exec;
2667         ot->poll= ED_operator_sequencer_active;
2668         
2669         /* flags */
2670         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2671         
2672         /* properties */
2673 }
2674
2675 static void seq_del_sound(Scene *scene, Sequence *seq)
2676 {
2677         if(seq->type == SEQ_META) {
2678                 Sequence *iseq;
2679                 for(iseq= seq->seqbase.first; iseq; iseq= iseq->next) {
2680                         seq_del_sound(scene, iseq);
2681                 }
2682         }
2683         else if(seq->scene_sound) {
2684                 sound_remove_scene_sound(scene, seq->scene_sound);
2685                 seq->scene_sound = NULL;
2686         }
2687 }
2688
2689 /* TODO, validate scenes */
2690 static int sequencer_copy_exec(bContext *C, wmOperator *op)
2691 {
2692         Scene *scene= CTX_data_scene(C);
2693         Editing *ed= seq_give_editing(scene, FALSE);
2694         Sequence *seq;
2695
2696         if(ed==NULL)
2697                 return OPERATOR_CANCELLED;
2698
2699         seq_free_clipboard();
2700
2701         if(seqbase_isolated_sel_check(ed->seqbasep)==FALSE) {
2702                 BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
2703                 return OPERATOR_CANCELLED;
2704         }
2705
2706         recurs_dupli_seq(scene, ed->seqbasep, &seqbase_clipboard, FALSE);
2707         seqbase_clipboard_frame= scene->r.cfra;
2708
2709         /* Need to remove anything that references the current scene */
2710         for(seq= seqbase_clipboard.first; seq; seq= seq->next) {
2711                 seq_del_sound(scene, seq);
2712         }
2713
2714         return OPERATOR_FINISHED;
2715 }
2716
2717 void SEQUENCER_OT_copy(wmOperatorType *ot)
2718 {
2719         /* identifiers */
2720         ot->name= "Copy";
2721         ot->idname= "SEQUENCER_OT_copy";
2722         ot->description="";
2723
2724         /* api callbacks */
2725         ot->exec= sequencer_copy_exec;
2726         ot->poll= ED_operator_sequencer_active;
2727
2728         /* flags */
2729         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2730
2731         /* properties */
2732 }
2733
2734 static void seq_offset(Scene *scene, Sequence *seq, int ofs)
2735 {
2736         if(seq->type == SEQ_META) {
2737                 Sequence *iseq;
2738                 for(iseq= seq->seqbase.first; iseq; iseq= iseq->next) {
2739                         seq_offset(scene, iseq, ofs);
2740                 }
2741         }
2742         else {
2743                 seq->start += ofs;
2744         }
2745
2746         calc_sequence_disp(scene, seq);
2747 }
2748
2749 static int sequencer_paste_exec(bContext *C, wmOperator *op)
2750 {
2751         Scene *scene= CTX_data_scene(C);
2752         Editing *ed= seq_give_editing(scene, TRUE); /* create if needed */
2753         ListBase new = {NULL, NULL};
2754         int ofs;
2755         Sequence *iseq;
2756
2757         deselect_all_seq(scene);
2758         ofs = scene->r.cfra - seqbase_clipboard_frame;
2759
2760         recurs_dupli_seq(scene, &seqbase_clipboard, &new, FALSE);
2761
2762         /* transform pasted strips before adding */
2763         if(ofs) {
2764                 for(iseq= new.first; iseq; iseq= iseq->next) {
2765                         seq_offset(scene, iseq, ofs);
2766                 }
2767         }
2768
2769         addlisttolist(ed->seqbasep, &new);
2770
2771         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2772
2773         return OPERATOR_FINISHED;
2774 }
2775
2776 void SEQUENCER_OT_paste(wmOperatorType *ot)
2777 {
2778         /* identifiers */
2779         ot->name= "Paste";
2780         ot->idname= "SEQUENCER_OT_paste";
2781         ot->description="";
2782
2783         /* api callbacks */
2784         ot->exec= sequencer_paste_exec;
2785         ot->poll= ED_operator_sequencer_active;
2786
2787         /* flags */
2788         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2789
2790         /* properties */
2791 }