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