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