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