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