== Sequencer ==
[blender.git] / source / blender / src / editseq.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <stdlib.h>
34 #include <math.h>
35 #include <string.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #ifndef WIN32
42 #include <unistd.h>
43 #else
44 #include <io.h>
45 #endif
46 #include <sys/types.h>
47
48 #include "MEM_guardedalloc.h"
49
50 #include "BLI_blenlib.h"
51 #include "BLI_arithb.h"
52 #include "BLI_storage_types.h"
53
54 #include "IMB_imbuf_types.h"
55 #include "IMB_imbuf.h"
56
57 #include "DNA_ipo_types.h"
58 #include "DNA_scene_types.h"
59 #include "DNA_screen_types.h"
60 #include "DNA_space_types.h"
61 #include "DNA_sequence_types.h"
62 #include "DNA_view2d_types.h"
63 #include "DNA_userdef_types.h"
64 #include "DNA_sound_types.h"
65
66 #include "BKE_utildefines.h"
67 #include "BKE_plugin_types.h"
68 #include "BKE_global.h"
69 #include "BKE_image.h"
70 #include "BKE_library.h"
71 #include "BKE_main.h"
72 #include "BKE_scene.h"
73
74 #include "BIF_space.h"
75 #include "BIF_interface.h"
76 #include "BIF_screen.h"
77 #include "BIF_drawseq.h"
78 #include "BIF_editseq.h"
79 #include "BIF_mywindow.h"
80 #include "BIF_toolbox.h"
81 #include "BIF_writemovie.h"
82 #include "BIF_editview.h"
83 #include "BIF_scrarea.h"
84 #include "BIF_editsound.h"
85
86 #include "BSE_edit.h"
87 #include "BSE_sequence.h"
88 #include "BSE_seqeffects.h"
89 #include "BSE_filesel.h"
90 #include "BSE_drawipo.h"
91 #include "BSE_seqaudio.h"
92
93 #include "BDR_editobject.h"
94
95 #include "blendef.h"
96 #include "mydevice.h"
97
98 static Sequence *_last_seq=0;
99 static int _last_seq_init=0;
100
101 #ifdef WIN32
102 char last_imagename[FILE_MAXDIR+FILE_MAXFILE]= "c:\\";
103 #else
104 char last_imagename[FILE_MAXDIR+FILE_MAXFILE]= "/";
105 #endif
106
107 char last_sounddir[FILE_MAXDIR+FILE_MAXFILE]= "";
108
109 #define SEQ_DESEL       ~(SELECT+SEQ_LEFTSEL+SEQ_RIGHTSEL)
110
111 static int test_overlap_seq(Sequence *);
112 static void shuffle_seq(Sequence *);
113
114 Sequence *get_last_seq()
115 {
116         if(!_last_seq_init) {
117                 Editing *ed;
118                 Sequence *seq;
119
120                 ed= G.scene->ed;
121                 if(!ed) return NULL;
122
123                 for(seq= ed->seqbasep->first; seq; seq=seq->next)
124                         if(seq->flag & SELECT)
125                                 _last_seq= seq;
126
127                 _last_seq_init = 1;
128         }
129
130         return _last_seq;
131 }
132
133 void set_last_seq(Sequence *seq)
134 {
135         _last_seq = seq;
136         _last_seq_init = 1;
137 }
138
139 void clear_last_seq()
140 {
141         _last_seq = NULL;
142         _last_seq_init = 0;
143 }
144
145 static void change_plugin_seq(char *str)        /* called from fileselect */
146 {
147         struct SeqEffectHandle sh;
148         Sequence *last_seq= get_last_seq();
149
150         if(last_seq && last_seq->type != SEQ_PLUGIN) return;
151
152         sh = get_sequence_effect(last_seq);
153         sh.free(last_seq);
154         sh.init_plugin(last_seq, str);
155
156         last_seq->machine = MAX3(last_seq->seq1->machine, 
157                                  last_seq->seq2->machine, 
158                                  last_seq->seq3->machine);
159
160         if( test_overlap_seq(last_seq) ) shuffle_seq(last_seq);
161         
162         BIF_undo_push("Load/change Sequencer plugin");
163 }
164
165
166 void boundbox_seq(void)
167 {
168         Sequence *seq;
169         Editing *ed;
170         float min[2], max[2];
171
172         ed= G.scene->ed;
173         if(ed==0) return;
174
175         min[0]= 0.0;
176         max[0]= EFRA+1;
177         min[1]= 0.0;
178         max[1]= 8.0;
179
180         seq= ed->seqbasep->first;
181         while(seq) {
182
183                 if( min[0] > seq->startdisp-1) min[0]= seq->startdisp-1;
184                 if( max[0] < seq->enddisp+1) max[0]= seq->enddisp+1;
185                 if( max[1] < seq->machine+2.0) max[1]= seq->machine+2.0;
186
187                 seq= seq->next;
188         }
189
190         G.v2d->tot.xmin= min[0];
191         G.v2d->tot.xmax= max[0];
192         G.v2d->tot.ymin= min[1];
193         G.v2d->tot.ymax= max[1];
194
195 }
196
197 int sequence_is_free_transformable(Sequence * seq)
198 {
199         return seq->type < SEQ_EFFECT
200                 || (get_sequence_effect_num_inputs(seq->type) == 0);
201 }
202
203 Sequence *find_nearest_seq(int *hand)
204 {
205         Sequence *seq;
206         Editing *ed;
207         float x, y;
208         short mval[2];
209         float pixelx;
210         float handsize;
211         float minhandle, maxhandle;
212         View2D *v2d = G.v2d;
213         *hand= 0;
214
215         ed= G.scene->ed;
216         if(ed==0) return 0;
217         
218         pixelx = (v2d->cur.xmax - v2d->cur.xmin)/(v2d->mask.xmax - v2d->mask.xmin);
219
220         getmouseco_areawin(mval);
221         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
222         
223         seq= ed->seqbasep->first;
224         
225         while(seq) {
226                 /* clamp handles to defined size in pixel space */
227                 handsize = seq->handsize;
228                 minhandle = 7;
229                 maxhandle = 28;
230                 CLAMP(handsize, minhandle*pixelx, maxhandle*pixelx);
231                 
232                 if(seq->machine == (int)y) {
233                         /* check for both normal strips, and strips that have been flipped horizontally */
234                         if( ((seq->startdisp < seq->enddisp) && (seq->startdisp<=x && seq->enddisp>=x)) ||
235                                 ((seq->startdisp > seq->enddisp) && (seq->startdisp>=x && seq->enddisp<=x)) )
236                         {
237                                 if(sequence_is_free_transformable(seq)) {
238                                         if( handsize+seq->startdisp >=x )
239                                                 *hand= 1;
240                                         else if( -handsize+seq->enddisp <=x )
241                                                 *hand= 2;
242                                 }
243                                 return seq;
244                         }
245                 }
246                 seq= seq->next;
247         }
248         return 0;
249 }
250
251 void update_seq_ipo_rect(Sequence * seq)
252 {
253         float start;
254         float end;
255
256         if (!seq || !seq->ipo) {
257                 return;
258         }
259         start =  -5.0;
260         end   =  105.0;
261
262         /* Adjust IPO window to sequence and 
263            avoid annoying snap-back to startframe 
264            when Lock Time is on */
265         if (G.v2d->flag & V2D_VIEWLOCK) {
266                 if ((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
267                         start = -5.0 + seq->startdisp;
268                         end = 5.0 + seq->enddisp;
269                 } else {
270                         start = (float)G.scene->r.sfra - 0.1;
271                         end = G.scene->r.efra;
272                 }
273         }
274
275         seq->ipo->cur.xmin= start;
276         seq->ipo->cur.xmax= end;
277 }
278
279 static int test_overlap_seq(Sequence *test)
280 {
281         Sequence *seq;
282         Editing *ed;
283
284         ed= G.scene->ed;
285         if(ed==0) return 0;
286
287         seq= ed->seqbasep->first;
288         while(seq) {
289                 if(seq!=test) {
290                         if(test->machine==seq->machine) {
291                                 if(test->depth==seq->depth) {
292                                         if( (test->enddisp <= seq->startdisp) || (test->startdisp >= seq->enddisp) );
293                                         else return 1;
294                                 }
295                         }
296                 }
297                 seq= seq->next;
298         }
299         return 0;
300 }
301
302 static void shuffle_seq(Sequence *test)
303 {
304         Editing *ed;
305         Sequence *seq;
306         int a, start;
307
308         ed= G.scene->ed;
309         if(ed==0) return;
310
311         /* is there more than 1 select: only shuffle y */
312         a=0;
313         seq= ed->seqbasep->first;
314         while(seq) {
315                 if(seq->flag & SELECT) a++;
316                 seq= seq->next;
317         }
318
319         if(a<2 && test->type==SEQ_IMAGE) {
320                 start= test->start;
321
322                 for(a= 1; a<50; a++) {
323                         test->start= start+a;
324                         calc_sequence(test);
325                         if( test_overlap_seq(test)==0) return;
326                         test->start= start-a;
327                         calc_sequence(test);
328                         if( test_overlap_seq(test)==0) return;
329                 }
330                 test->start= start;
331         }
332
333         test->machine++;
334         calc_sequence(test);
335         while( test_overlap_seq(test) ) {
336                 if(test->machine >= MAXSEQ) {
337                         error("There is no more space to add a sequence strip");
338
339                         BLI_remlink(ed->seqbasep, test);
340                         free_sequence(test);
341                         return;
342                 }
343                 test->machine++;
344                 calc_sequence(test);
345         }
346 }
347
348 static int seq_is_parent(Sequence *par, Sequence *seq)
349 {
350         return ((par->seq1 == seq) || (par->seq2 == seq) || (par->seq3 == seq));
351 }
352
353 static int seq_is_predecessor(Sequence *pred, Sequence *seq)
354 {
355         if(pred == seq) return 0;
356         else if(seq_is_parent(pred, seq)) return 1;
357         else if(pred->seq1 && seq_is_predecessor(pred->seq1, seq)) return 1;
358         else if(pred->seq2 && seq_is_predecessor(pred->seq2, seq)) return 1;
359         else if(pred->seq3 && seq_is_predecessor(pred->seq3, seq)) return 1;
360
361         return 0;
362 }
363
364 static void deselect_all_seq(void)
365 {
366         Sequence *seq;
367         Editing *ed;
368
369         ed= G.scene->ed;
370         if(ed==0) return;
371
372         WHILE_SEQ(ed->seqbasep) {
373                 seq->flag &= SEQ_DESEL;
374         }
375         END_SEQ
376                 
377         BIF_undo_push("(De)select all Sequencer");
378 }
379
380 static void recurs_sel_seq(Sequence *seqm)
381 {
382         Sequence *seq;
383
384         seq= seqm->seqbase.first;
385         while(seq) {
386
387                 if(seqm->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL)) seq->flag &= SEQ_DESEL;
388                 else if(seqm->flag & SELECT) seq->flag |= SELECT;
389                 else seq->flag &= SEQ_DESEL;
390
391                 if(seq->seqbase.first) recurs_sel_seq(seq);
392
393                 seq= seq->next;
394         }
395 }
396
397 void swap_select_seq(void)
398 {
399         Sequence *seq;
400         Editing *ed;
401         int sel=0;
402
403         ed= G.scene->ed;
404         if(ed==0) return;
405
406         WHILE_SEQ(ed->seqbasep) {
407                 if(seq->flag & SELECT) sel= 1;
408         }
409         END_SEQ
410
411         WHILE_SEQ(ed->seqbasep) {
412                 /* always deselect all to be sure */
413                 seq->flag &= SEQ_DESEL;
414                 if(sel==0) seq->flag |= SELECT;
415         }
416         END_SEQ
417
418         allqueue(REDRAWSEQ, 0);
419         BIF_undo_push("Swap select all Sequencer");
420
421 }
422
423 void mouse_select_seq(void)
424 {
425         Sequence *seq;
426         int hand;
427
428         seq= find_nearest_seq(&hand);
429
430         if(!(G.qual & LR_SHIFTKEY)) deselect_all_seq();
431
432         if(seq) {
433                 set_last_seq(seq);
434
435                 if ((seq->type == SEQ_IMAGE) || (seq->type == SEQ_MOVIE)) {
436                         if(seq->strip) {
437                                 strncpy(last_imagename, seq->strip->dir, FILE_MAXDIR-1);
438                         }
439                 } else
440                 if (seq->type == SEQ_HD_SOUND || seq->type == SEQ_RAM_SOUND) {
441                         if(seq->strip) {
442                                 strncpy(last_sounddir, seq->strip->dir, FILE_MAXDIR-1);
443                         }
444                 }
445
446                 if((G.qual & LR_SHIFTKEY) && (seq->flag & SELECT)) {
447                         if(hand==0) seq->flag &= SEQ_DESEL;
448                         else if(hand==1) {
449                                 if(seq->flag & SEQ_LEFTSEL) 
450                                         seq->flag &= ~SEQ_LEFTSEL;
451                                 else seq->flag |= SEQ_LEFTSEL;
452                         }
453                         else if(hand==2) {
454                                 if(seq->flag & SEQ_RIGHTSEL) 
455                                         seq->flag &= ~SEQ_RIGHTSEL;
456                                 else seq->flag |= SEQ_RIGHTSEL;
457                         }
458                 }
459                 else {
460                         seq->flag |= SELECT;
461                         if(hand==1) seq->flag |= SEQ_LEFTSEL;
462                         if(hand==2) seq->flag |= SEQ_RIGHTSEL;
463                 }
464                 recurs_sel_seq(seq);
465         }
466
467         force_draw(0);
468
469         if(get_last_seq()) allqueue(REDRAWIPO, 0);
470         BIF_undo_push("Select Sequencer");
471
472         std_rmouse_transform(transform_seq);
473 }
474
475 static Sequence *alloc_sequence(int cfra, int machine)
476 {
477         Editing *ed;
478         Sequence *seq;
479
480         ed= G.scene->ed;
481
482         seq= MEM_callocN( sizeof(Sequence), "addseq");
483         BLI_addtail(ed->seqbasep, seq);
484
485         set_last_seq(seq);
486
487         *( (short *)seq->name )= ID_SEQ;
488         seq->name[2]= 0;
489
490         seq->flag= SELECT;
491         seq->start= cfra;
492         seq->machine= machine;
493         seq->mul= 1.0;
494         
495         return seq;
496 }
497
498 static Sequence *sfile_to_sequence(SpaceFile *sfile, int cfra, int machine, int last)
499 {
500         Sequence *seq;
501         Strip *strip;
502         StripElem *se;
503         int totsel, a;
504         char name[160], rel[160];
505
506         /* are there selected files? */
507         totsel= 0;
508         for(a=0; a<sfile->totfile; a++) {
509                 if(sfile->filelist[a].flags & ACTIVE) {
510                         if( (sfile->filelist[a].type & S_IFDIR)==0 ) {
511                                 totsel++;
512                         }
513                 }
514         }
515
516         if(last) {
517                 /* if not, a file handed to us? */
518                 if(totsel==0 && sfile->file[0]) totsel= 1;
519         }
520
521         if(totsel==0) return 0;
522
523         /* make seq */
524         seq= alloc_sequence(cfra, machine);
525         seq->len= totsel;
526
527         if(totsel==1) {
528                 seq->startstill= 25;
529                 seq->endstill= 24;
530         }
531
532         calc_sequence(seq);
533         
534         if(sfile->flag & FILE_STRINGCODE) {
535                 strcpy(name, sfile->dir);
536                 strcpy(rel, G.sce);
537                 BLI_makestringcode(rel, name);
538         } else {
539                 strcpy(name, sfile->dir);
540         }
541
542         /* strip and stripdata */
543         seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
544         strip->len= totsel;
545         strip->us= 1;
546         strncpy(strip->dir, name, FILE_MAXDIR-1);
547         strip->stripdata= se= MEM_callocN(totsel*sizeof(StripElem), "stripelem");
548
549         for(a=0; a<sfile->totfile; a++) {
550                 if(sfile->filelist[a].flags & ACTIVE) {
551                         if( (sfile->filelist[a].type & S_IFDIR)==0 ) {
552                                 strncpy(se->name, sfile->filelist[a].relname, FILE_MAXFILE-1);
553                                 se->ok= 1;
554                                 se++;
555                         }
556                 }
557         }
558         /* no selected file: */
559         if(totsel==1 && se==strip->stripdata) {
560                 strncpy(se->name, sfile->file, FILE_MAXFILE-1);
561                 se->ok= 1;
562         }
563
564         /* last active name */
565         strncpy(last_imagename, seq->strip->dir, FILE_MAXDIR-1);
566
567         return seq;
568 }
569
570 static void sfile_to_mv_sequence(SpaceFile *sfile, int cfra, int machine)
571 {
572         Sequence *seq;
573         struct anim *anim;
574         Strip *strip;
575         StripElem *se;
576         int totframe, a;
577         char name[160], rel[160];
578         char str[FILE_MAXDIR+FILE_MAXFILE];
579
580         totframe= 0;
581
582         strncpy(str, sfile->dir, FILE_MAXDIR-1);
583         strncat(str, sfile->file, FILE_MAXDIR-1);
584
585         /* is it a movie? */
586         anim = openanim(str, IB_rect);
587         if(anim==0) {
588                 error("The selected file is not a movie or "
589                       "FFMPEG-support not compiled in!");
590                 return;
591         }
592
593         totframe= IMB_anim_get_duration(anim);
594
595         /* make seq */
596         seq= alloc_sequence(cfra, machine);
597         seq->len= totframe;
598         seq->type= SEQ_MOVIE;
599         seq->anim= anim;
600         seq->anim_preseek = IMB_anim_get_preseek(anim);
601
602         calc_sequence(seq);
603         
604         if(sfile->flag & FILE_STRINGCODE) {
605                 strcpy(name, sfile->dir);
606                 strcpy(rel, G.sce);
607                 BLI_makestringcode(rel, name);
608         } else {
609                 strcpy(name, sfile->dir);
610         }
611
612         /* strip and stripdata */
613         seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
614         strip->len= totframe;
615         strip->us= 1;
616         strncpy(strip->dir, name, FILE_MAXDIR-1);
617         strip->stripdata= se= MEM_callocN(totframe*sizeof(StripElem), "stripelem");
618
619         /* name movie in first strip */
620         strncpy(se->name, sfile->file, FILE_MAXFILE-1);
621
622         for(a=1; a<=totframe; a++, se++) {
623                 se->ok= 1;
624                 se->nr= a;
625         }
626
627         /* last active name */
628         strncpy(last_imagename, seq->strip->dir, FILE_MAXDIR-1);
629 }
630
631 static Sequence *sfile_to_ramsnd_sequence(SpaceFile *sfile, 
632                                           int cfra, int machine)
633 {
634         Sequence *seq;
635         bSound *sound;
636         Strip *strip;
637         StripElem *se;
638         double totframe;
639         int a;
640         char name[160], rel[160];
641         char str[256];
642
643         totframe= 0.0;
644
645         strncpy(str, sfile->dir, FILE_MAXDIR-1);
646         strncat(str, sfile->file, FILE_MAXFILE-1);
647
648         sound= sound_new_sound(str);
649         if (!sound || sound->sample->type == SAMPLE_INVALID) {
650                 error("Unsupported audio format");
651                 return 0;
652         }
653         if (sound->sample->bits != 16) {
654                 error("Only 16 bit audio is supported");
655                 return 0;
656         }
657         sound->id.us=1;
658         sound->flags |= SOUND_FLAGS_SEQUENCE;
659         audio_makestream(sound);
660
661         totframe= (int) ( ((float)(sound->streamlen-1)/( (float)G.scene->audio.mixrate*4.0 ))* (float)G.scene->r.frs_sec);
662
663         /* make seq */
664         seq= alloc_sequence(cfra, machine);
665         seq->len= totframe;
666         seq->type= SEQ_RAM_SOUND;
667         seq->sound = sound;
668
669         calc_sequence(seq);
670         
671         if(sfile->flag & FILE_STRINGCODE) {
672                 strcpy(name, sfile->dir);
673                 strcpy(rel, G.sce);
674                 BLI_makestringcode(rel, name);
675         } else {
676                 strcpy(name, sfile->dir);
677         }
678
679         /* strip and stripdata */
680         seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
681         strip->len= totframe;
682         strip->us= 1;
683         strncpy(strip->dir, name, FILE_MAXDIR-1);
684         strip->stripdata= se= MEM_callocN(totframe*sizeof(StripElem), "stripelem");
685
686         /* name sound in first strip */
687         strncpy(se->name, sfile->file, FILE_MAXFILE-1);
688
689         for(a=1; a<=totframe; a++, se++) {
690                 se->ok= 2; /* why? */
691                 se->ibuf= 0;
692                 se->nr= a;
693         }
694
695         /* last active name */
696         strncpy(last_sounddir, seq->strip->dir, FILE_MAXDIR-1);
697
698         return seq;
699 }
700
701 static void sfile_to_hdsnd_sequence(SpaceFile *sfile, int cfra, int machine)
702 {
703         Sequence *seq;
704         struct hdaudio *hdaudio;
705         Strip *strip;
706         StripElem *se;
707         int totframe, a;
708         char name[160], rel[160];
709         char str[FILE_MAXDIR+FILE_MAXFILE];
710
711         totframe= 0;
712
713         strncpy(str, sfile->dir, FILE_MAXDIR-1);
714         strncat(str, sfile->file, FILE_MAXDIR-1);
715
716         /* is it a sound file? */
717         hdaudio = sound_open_hdaudio(str);
718         if(hdaudio==0) {
719                 error("The selected file is not a sound file or "
720                       "FFMPEG-support not compiled in!");
721                 return;
722         }
723
724         totframe= sound_hdaudio_get_duration(hdaudio, G.scene->r.frs_sec);
725
726         /* make seq */
727         seq= alloc_sequence(cfra, machine);
728         seq->len= totframe;
729         seq->type= SEQ_HD_SOUND;
730         seq->hdaudio= hdaudio;
731
732         calc_sequence(seq);
733         
734         if(sfile->flag & FILE_STRINGCODE) {
735                 strcpy(name, sfile->dir);
736                 strcpy(rel, G.sce);
737                 BLI_makestringcode(rel, name);
738         } else {
739                 strcpy(name, sfile->dir);
740         }
741
742         /* strip and stripdata */
743         seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
744         strip->len= totframe;
745         strip->us= 1;
746         strncpy(strip->dir, name, FILE_MAXDIR-1);
747         strip->stripdata= se= MEM_callocN(totframe*sizeof(StripElem), "stripelem");
748
749         /* name movie in first strip */
750         strncpy(se->name, sfile->file, FILE_MAXFILE-1);
751
752         for(a=1; a<=totframe; a++, se++) {
753                 se->ok= 2;
754                 se->ibuf = 0;
755                 se->nr= a;
756         }
757
758         /* last active name */
759         strncpy(last_sounddir, seq->strip->dir, FILE_MAXDIR-1);
760 }
761
762
763 static void add_image_strips(char *name)
764 {
765         SpaceFile *sfile;
766         struct direntry *files;
767         float x, y;
768         int a, totfile, cfra, machine;
769         short mval[2];
770
771         deselect_all_seq();
772
773         /* restore windowmatrices */
774         areawinset(curarea->win);
775         drawseqspace(curarea, curarea->spacedata.first);
776
777         /* search sfile */
778         sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
779         if(sfile==0) return;
780
781         /* where will it be */
782         getmouseco_areawin(mval);
783         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
784         cfra= (int)(x+0.5);
785         machine= (int)(y+0.5);
786
787         waitcursor(1);
788
789         /* also read contents of directories */
790         files= sfile->filelist;
791         totfile= sfile->totfile;
792         sfile->filelist= 0;
793         sfile->totfile= 0;
794
795         for(a=0; a<totfile; a++) {
796                 if(files[a].flags & ACTIVE) {
797                         if( (files[a].type & S_IFDIR) ) {
798                                 strncat(sfile->dir, files[a].relname, FILE_MAXFILE-1);
799                                 strcat(sfile->dir,"/");
800                                 read_dir(sfile);
801
802                                 /* select all */
803                                 swapselect_file(sfile);
804
805                                 if ( sfile_to_sequence(sfile, cfra, machine, 0) ) machine++;
806
807                                 parent(sfile);
808                         }
809                 }
810         }
811
812         sfile->filelist= files;
813         sfile->totfile= totfile;
814
815         /* read directory itself */
816         sfile_to_sequence(sfile, cfra, machine, 1);
817
818         waitcursor(0);
819
820         BIF_undo_push("Add image strip Sequencer");
821         transform_seq('g', 0);
822
823 }
824
825 static void add_movie_strip(char *name)
826 {
827         SpaceFile *sfile;
828         float x, y;
829         int cfra, machine;
830         short mval[2];
831
832         deselect_all_seq();
833
834         /* restore windowmatrices */
835         areawinset(curarea->win);
836         drawseqspace(curarea, curarea->spacedata.first);
837
838         /* search sfile */
839         sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
840         if(sfile==0) return;
841
842         /* where will it be */
843         getmouseco_areawin(mval);
844         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
845         cfra= (int)(x+0.5);
846         machine= (int)(y+0.5);
847
848         waitcursor(1);
849
850         /* read directory itself */
851         sfile_to_mv_sequence(sfile, cfra, machine);
852
853         waitcursor(0);
854
855         BIF_undo_push("Add movie strip Sequencer");
856         transform_seq('g', 0);
857
858 }
859
860 static void add_movie_and_hdaudio_strip(char *name)
861 {
862         SpaceFile *sfile;
863         float x, y;
864         int cfra, machine;
865         short mval[2];
866
867         deselect_all_seq();
868
869         /* restore windowmatrices */
870         areawinset(curarea->win);
871         drawseqspace(curarea, curarea->spacedata.first);
872
873         /* search sfile */
874         sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
875         if(sfile==0) return;
876
877         /* where will it be */
878         getmouseco_areawin(mval);
879         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
880         cfra= (int)(x+0.5);
881         machine= (int)(y+0.5);
882
883         waitcursor(1);
884
885         /* read directory itself */
886         sfile_to_hdsnd_sequence(sfile, cfra, machine);
887         sfile_to_mv_sequence(sfile, cfra, machine);
888
889         waitcursor(0);
890
891         BIF_undo_push("Add movie and HD-audio strip Sequencer");
892         transform_seq('g', 0);
893
894 }
895
896 static void add_sound_strip_ram(char *name)
897 {
898         SpaceFile *sfile;
899         float x, y;
900         int cfra, machine;
901         short mval[2];
902
903         deselect_all_seq();
904
905         sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
906         if (sfile==0) return;
907
908         /* where will it be */
909         getmouseco_areawin(mval);
910         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
911         cfra= (int)(x+0.5);
912         machine= (int)(y+0.5);
913
914         waitcursor(1);
915
916         sfile_to_ramsnd_sequence(sfile, cfra, machine);
917
918         waitcursor(0);
919
920         BIF_undo_push("Add ram sound strip Sequencer");
921         transform_seq('g', 0);
922 }
923
924 static void add_sound_strip_hd(char *name)
925 {
926         SpaceFile *sfile;
927         float x, y;
928         int cfra, machine;
929         short mval[2];
930
931         deselect_all_seq();
932
933         sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
934         if (sfile==0) return;
935
936         /* where will it be */
937         getmouseco_areawin(mval);
938         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
939         cfra= (int)(x+0.5);
940         machine= (int)(y+0.5);
941
942         waitcursor(1);
943
944         sfile_to_hdsnd_sequence(sfile, cfra, machine);
945
946         waitcursor(0);
947
948         BIF_undo_push("Add hd sound strip Sequencer");
949         transform_seq('g', 0);
950 }
951
952 #if 0
953 static void reload_sound_strip(char *name)
954 {
955         Editing *ed;
956         Sequence *seq, *seqact;
957         SpaceFile *sfile;
958         Sequence *last_seq= get_last_seq();
959
960         ed= G.scene->ed;
961
962         if(last_seq==0 || last_seq->type!=SEQ_SOUND) return;
963         seqact= last_seq;       /* last_seq changes in alloc_sequence */
964
965         /* search sfile */
966         sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
967         if(sfile==0) return;
968
969         waitcursor(1);
970
971         seq = sfile_to_snd_sequence(sfile, seqact->start, seqact->machine);
972         printf("seq->type: %i\n", seq->type);
973         if(seq && seq!=seqact) {
974                 /* i'm not sure about this one, seems to work without it -- sgefant */
975                 free_strip(seqact->strip);
976
977                 seqact->strip= seq->strip;
978
979                 seqact->len= seq->len;
980                 calc_sequence(seqact);
981
982                 seq->strip= 0;
983                 free_sequence(seq);
984                 BLI_remlink(ed->seqbasep, seq);
985
986                 seq= ed->seqbasep->first;
987
988         }
989
990         waitcursor(0);
991
992         allqueue(REDRAWSEQ, 0);
993 }
994 #endif
995
996 static void reload_image_strip(char *name)
997 {
998         Editing *ed;
999         Sequence *seq, *seqact;
1000         SpaceFile *sfile;
1001         Sequence *last_seq= get_last_seq();
1002
1003         ed= G.scene->ed;
1004
1005         if(last_seq==0 || last_seq->type!=SEQ_IMAGE) return;
1006         seqact= last_seq;       /* last_seq changes in alloc_sequence */
1007
1008         /* search sfile */
1009         sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
1010         if(sfile==0) return;
1011
1012         waitcursor(1);
1013
1014         seq= sfile_to_sequence(sfile, seqact->start, seqact->machine, 1);
1015         if(seq && seq!=seqact) {
1016                 free_strip(seqact->strip);
1017
1018                 seqact->strip= seq->strip;
1019
1020                 seqact->len= seq->len;
1021                 calc_sequence(seqact);
1022
1023                 seq->strip= 0;
1024                 free_sequence(seq);
1025                 BLI_remlink(ed->seqbasep, seq);
1026
1027                 update_changed_seq_and_deps(seqact, 1, 1);
1028         }
1029         waitcursor(0);
1030
1031         allqueue(REDRAWSEQ, 0);
1032 }
1033
1034 static int event_to_efftype(int event)
1035 {
1036         if(event==2) return SEQ_CROSS;
1037         if(event==3) return SEQ_GAMCROSS;
1038         if(event==4) return SEQ_ADD;
1039         if(event==5) return SEQ_SUB;
1040         if(event==6) return SEQ_MUL;
1041         if(event==7) return SEQ_ALPHAOVER;
1042         if(event==8) return SEQ_ALPHAUNDER;
1043         if(event==9) return SEQ_OVERDROP;
1044         if(event==10) return SEQ_PLUGIN;
1045         if(event==13) return SEQ_WIPE;
1046         if(event==14) return SEQ_GLOW;
1047         if(event==15) return SEQ_TRANSFORM;
1048         if(event==16) return SEQ_COLOR;
1049         return 0;
1050 }
1051
1052 static int can_insert_seq_between(Sequence *seq1, 
1053                                   Sequence *seq2, Sequence *seq3)
1054 {
1055        Editing *ed= G.scene->ed;
1056        Sequence *seq;
1057
1058        if (seq1 == 0 || seq2 == 0 || seq3 == 0) {
1059                return 0;
1060        }
1061
1062        /* see if inserting inbetween would create a cycle */
1063        if(seq_is_predecessor(seq1, seq2) || seq_is_predecessor(seq2, seq1) ||
1064           seq_is_predecessor(seq2, seq3) || seq_is_predecessor(seq3, seq2) ||
1065           seq_is_predecessor(seq3, seq1) || seq_is_predecessor(seq1, seq3))
1066                return 0;
1067
1068        /* see if there is a parent that we can insert inbetween */
1069        for(seq=ed->seqbasep->first; seq; seq=seq->next)
1070                if((seq != seq1) && (seq != seq2) && (seq != seq3))
1071                        if(seq_is_parent(seq, seq1) || 
1072                           seq_is_parent(seq, seq2) ||
1073                           seq_is_parent(seq, seq3))
1074                                return 1;
1075
1076        return 0;
1077 }
1078
1079
1080 static int seq_effect_find_selected(Editing *ed, Sequence *activeseq, int type, Sequence **selseq1, Sequence **selseq2, Sequence **selseq3)
1081 {
1082         Sequence *seq1= 0, *seq2= 0, *seq3= 0, *seq;
1083         
1084         if (!activeseq)
1085                 seq2= get_last_seq();
1086
1087         for(seq=ed->seqbasep->first; seq; seq=seq->next) {
1088                 if(seq->flag & SELECT) {
1089                         if (seq->type == SEQ_RAM_SOUND
1090                             || seq->type == SEQ_HD_SOUND) { 
1091                                 error("Can't apply effects to "
1092                                       "audio sequence strips");
1093                                 return 0;
1094                         }
1095                         if((seq != activeseq) && (seq != seq2)) {
1096                                 if(seq2==0) seq2= seq;
1097                                 else if(seq1==0) seq1= seq;
1098                                 else if(seq3==0) seq3= seq;
1099                                 else {
1100                                        error("Can't apply effect to more than 3 sequence strips");
1101                                        return 0;
1102                                 }
1103                         }
1104                 }
1105         }
1106        
1107         /* make sequence selection a little bit more intuitive
1108            for 3 strips: the last-strip should be sequence3 */
1109         if (seq3 != 0 && seq2 != 0) {
1110                 Sequence *tmp = seq2;
1111                 seq2 = seq3;
1112                 seq3 = tmp;
1113         }
1114         
1115
1116         switch(get_sequence_effect_num_inputs(type)) {
1117         case 0:
1118                 seq1 = seq2 = seq3 = 0;
1119                 break;
1120         case 1:
1121                 if(seq2==0)  {
1122                         error("Need at least one selected sequence strip");
1123                         return 0;
1124                 }
1125                 if(seq1==0) seq1= seq2;
1126                 if(seq3==0) seq3= seq2;
1127         case 2:
1128                 if(seq1==0 || seq2==0) {
1129                         error("Need 2 selected sequence strips");
1130                         return 0;
1131                 }
1132                 if(seq3==0) seq3= seq2;
1133         }
1134
1135         *selseq1= seq1;
1136         *selseq2= seq2;
1137         *selseq3= seq3;
1138
1139         return 1;
1140 }
1141
1142 static void insert_seq_between(Sequence *newseq, Sequence *seq1, Sequence *seq2, Sequence *seq3)
1143 {
1144        Editing *ed= G.scene->ed;
1145        Sequence *seq, *firstseq = NULL;
1146        Sequence *oldseq[3];
1147        int i;
1148
1149        oldseq[0]= seq1;
1150        oldseq[1]= seq2;
1151        oldseq[2]= seq3;
1152
1153        for(seq=ed->seqbasep->first; seq; seq=seq->next) {
1154                if((seq != seq1) && (seq != seq2) && (seq != seq3)) {
1155                        /* set pointers to new children */
1156                        for(i=0; i < 3; i++) {
1157                                if(seq_is_parent(seq, oldseq[i]) && (seq != newseq)) {
1158                                        if(seq->seq1 == oldseq[i]) seq->seq1= newseq;
1159                                        if(seq->seq2 == oldseq[i]) seq->seq2= newseq;
1160                                        if(seq->seq3 == oldseq[i]) seq->seq3= newseq;
1161                                        if(!firstseq) firstseq= seq;
1162                                }
1163                        }
1164                }
1165        }
1166
1167        /* reinsert sequence in the list before the first sequence depending on it,
1168           this is needed for the strips to be evaluated in correct order */
1169        if(firstseq) {
1170                BLI_remlink(ed->seqbasep, newseq);
1171                BLI_insertlinkbefore(ed->seqbasep, firstseq, newseq);
1172        }
1173 }
1174
1175
1176 static int add_seq_effect(int type, char *str)
1177 {
1178         Editing *ed;
1179         Sequence *newseq, *seq1, *seq2, *seq3;
1180         Strip *strip;
1181         float x, y;
1182         int cfra, machine;
1183         short mval[2];
1184         struct SeqEffectHandle sh;
1185         int mode, insertbetween= 0;
1186
1187         if(G.scene->ed==0) return 0;
1188         ed= G.scene->ed;
1189
1190         if(!seq_effect_find_selected(ed, NULL, event_to_efftype(type), &seq1, &seq2, &seq3))
1191                 return 0;
1192
1193          if (can_insert_seq_between(seq1, seq2, seq3)) {
1194                 force_draw(0); /* to make sure popup is not drawn over file select */
1195                 mode= pupmenu("Insert Between %x1|Insert After %x2");
1196                 if(mode == 1)
1197                         insertbetween= 1;
1198         }
1199
1200         deselect_all_seq();
1201
1202         /* where will it be (cfra is not realy needed) */
1203         getmouseco_areawin(mval);
1204         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1205         cfra= (int)(x+0.5);
1206         machine= (int)(y+0.5);
1207
1208         /* allocate and initialize */
1209         newseq= alloc_sequence(cfra, machine);
1210         newseq->type= event_to_efftype(type);
1211
1212         sh = get_sequence_effect(newseq);
1213
1214         newseq->seq1= seq1;
1215         newseq->seq2= seq2;
1216         newseq->seq3= seq3;
1217
1218         sh.init(newseq);
1219
1220         if (!seq1) {
1221                 newseq->len= 1;
1222                 newseq->startstill= 25;
1223                 newseq->endstill= 24;
1224         }
1225
1226         calc_sequence(newseq);
1227
1228         newseq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
1229         strip->len= newseq->len;
1230         strip->us= 1;
1231         if(newseq->len>0)
1232                 strip->stripdata= MEM_callocN(newseq->len*sizeof(StripElem), "stripelem");
1233
1234         /* initialize plugin */
1235         if(newseq->type == SEQ_PLUGIN) {
1236                 sh.init_plugin(newseq, str);
1237
1238                 if(newseq->plugin==0) {
1239                         BLI_remlink(ed->seqbasep, newseq);
1240                         free_sequence(newseq);
1241                         set_last_seq(NULL);
1242                         return 0;
1243                 }
1244         }
1245
1246         /* set find a free spot to but the strip */
1247         if (newseq->seq1) {
1248                 newseq->machine= MAX3(newseq->seq1->machine, 
1249                                       newseq->seq2->machine,
1250                                       newseq->seq3->machine);
1251         }
1252         if(test_overlap_seq(newseq)) shuffle_seq(newseq);
1253
1254         /* set inbetween relation */
1255         if(insertbetween)
1256                 insert_seq_between(newseq, seq1, seq2, seq3);
1257
1258         update_changed_seq_and_deps(newseq, 1, 1);
1259
1260         /* push undo and go into grab mode */
1261         if(newseq->type == SEQ_PLUGIN) {
1262                 BIF_undo_push("Add plugin strip Sequencer");
1263         } else {
1264                 BIF_undo_push("Add effect strip Sequencer");
1265         }
1266
1267         transform_seq('g', 0);
1268
1269         return 1;
1270 }
1271
1272 static void load_plugin_seq(char *str)          /* called from fileselect */
1273 {
1274         add_seq_effect(10, str);
1275 }
1276
1277 void add_sequence(int type)
1278 {
1279         Editing *ed;
1280         Sequence *seq;
1281         Strip *strip;
1282         Scene *sce;
1283         float x, y;
1284         int cfra, machine;
1285         short nr, event, mval[2];
1286         char *str;
1287
1288         if (type >= 0){
1289                 /* bypass pupmenu for calls from menus (aphex) */
1290                 switch(type){
1291                 case SEQ_SCENE:
1292                         event = 101;
1293                         break;
1294                 case SEQ_IMAGE:
1295                         event = 1;
1296                         break;
1297                 case SEQ_MOVIE:
1298                         event = 102;
1299                         break;
1300                 case SEQ_RAM_SOUND:
1301                         event = 103;
1302                         break;
1303                 case SEQ_HD_SOUND:
1304                         event = 104;
1305                         break;
1306                 case SEQ_MOVIE_AND_HD_SOUND:
1307                         event = 105;
1308                         break;
1309                 case SEQ_PLUGIN:
1310                         event = 10;
1311                         break;
1312                 case SEQ_CROSS:
1313                         event = 2;
1314                         break;
1315                 case SEQ_ADD:
1316                         event = 4;
1317                         break;
1318                 case SEQ_SUB:
1319                         event = 5;
1320                         break;
1321                 case SEQ_ALPHAOVER:
1322                         event = 7;
1323                         break;
1324                 case SEQ_ALPHAUNDER:
1325                         event = 8;
1326                         break;
1327                 case SEQ_GAMCROSS:
1328                         event = 3;
1329                         break;
1330                 case SEQ_MUL:
1331                         event = 6;
1332                         break;
1333                 case SEQ_OVERDROP:
1334                         event = 9;
1335                         break;
1336                 case SEQ_WIPE:
1337                         event = 13;
1338                         break;
1339                 case SEQ_GLOW:
1340                         event = 14;
1341                         break;
1342                 case SEQ_TRANSFORM:
1343                         event = 15;
1344                         break;
1345                 case SEQ_COLOR:
1346                         event = 16;
1347                         break;
1348                 default:
1349                         event = 0;
1350                         break;
1351                 }
1352         }
1353         else {
1354                 event= pupmenu("Add Sequence Strip%t"
1355                                "|Images%x1"
1356                                "|Movie%x102"
1357 #ifdef WITH_FFMPEG
1358                                    "|Movie + Audio (HD)%x105"
1359                                "|Audio (RAM)%x103"
1360                                "|Audio (HD)%x104"
1361 #else
1362                                    "|Audio (Wav)%x103"
1363 #endif
1364                                "|Scene%x101"
1365                                "|Plugin%x10"
1366                                "|Cross%x2"
1367                                "|Gamma Cross%x3"
1368                                "|Add%x4"
1369                                "|Sub%x5"
1370                                "|Mul%x6"
1371                                "|Alpha Over%x7"
1372                                "|Alpha Under%x8"
1373                                "|Alpha Over Drop%x9"
1374                                "|Wipe%x13"
1375                                "|Glow%x14"
1376                                "|Transforms%x15"
1377                                "|Color Generator%x16");
1378         }
1379
1380         if(event<1) return;
1381
1382         if(G.scene->ed==0) {
1383                 ed= G.scene->ed= MEM_callocN( sizeof(Editing), "addseq");
1384                 ed->seqbasep= &ed->seqbase;
1385         }
1386         else ed= G.scene->ed;
1387
1388         switch(event) {
1389         case 1:
1390
1391                 activate_fileselect(FILE_SPECIAL, "Select Images", last_imagename, add_image_strips);
1392                 break;
1393         case 105:
1394                 activate_fileselect(FILE_SPECIAL, "Select Movie+Audio", last_imagename, add_movie_and_hdaudio_strip);
1395                 break;
1396         case 102:
1397
1398                 activate_fileselect(FILE_SPECIAL, "Select Movie", last_imagename, add_movie_strip);
1399                 break;
1400         case 101:
1401                 /* new menu: */
1402                 IDnames_to_pupstring(&str, NULL, NULL, &G.main->scene, (ID *)G.scene, NULL);
1403
1404                 event= pupmenu_col(str, 20);
1405
1406                 if(event> -1) {
1407                         nr= 1;
1408                         sce= G.main->scene.first;
1409                         while(sce) {
1410                                 if( event==nr) break;
1411                                 nr++;
1412                                 sce= sce->id.next;
1413                         }
1414                         if(sce) {
1415
1416                                 deselect_all_seq();
1417
1418                                 /* where ? */
1419                                 getmouseco_areawin(mval);
1420                                 areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1421                                 cfra= (int)(x+0.5);
1422                                 machine= (int)(y+0.5);
1423
1424                                 seq= alloc_sequence(cfra, machine);
1425                                 seq->type= SEQ_SCENE;
1426                                 seq->scene= sce;
1427                                 seq->sfra= sce->r.sfra;
1428                                 seq->len= sce->r.efra - sce->r.sfra + 1;
1429
1430                                 seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
1431                                 strncpy(seq->name + 2, sce->id.name + 2, 
1432                                         sizeof(seq->name) - 2);
1433                                 strip->len= seq->len;
1434                                 strip->us= 1;
1435                                 if(seq->len>0) strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
1436
1437                                 BIF_undo_push("Add scene strip Sequencer");
1438                                 transform_seq('g', 0);
1439                         }
1440                 }
1441                 MEM_freeN(str);
1442
1443                 break;
1444         case 2:
1445         case 3:
1446         case 4:
1447         case 5:
1448         case 6:
1449         case 7:
1450         case 8:
1451         case 9:
1452         case 10:
1453         case 13:
1454         case 14:
1455         case 15:
1456         case 16:
1457                 if(get_last_seq()==0 && 
1458                    get_sequence_effect_num_inputs( event_to_efftype(event))> 0)
1459                         error("Need at least one active sequence strip");
1460                 else if(event==10)
1461                         activate_fileselect(FILE_SPECIAL, "Select Plugin", U.plugseqdir, load_plugin_seq);
1462                 else
1463                         add_seq_effect(event, NULL);
1464
1465                 break;
1466         case 103:
1467                 if (!last_sounddir[0]) strncpy(last_sounddir, U.sounddir, FILE_MAXDIR-1);
1468                 activate_fileselect(FILE_SPECIAL, "Select Audio (RAM)", last_sounddir, add_sound_strip_ram);
1469                 break;
1470         case 104:
1471                 if (!last_sounddir[0]) strncpy(last_sounddir, U.sounddir, FILE_MAXDIR-1);
1472                 activate_fileselect(FILE_SPECIAL, "Select Audio (HD)", last_sounddir, add_sound_strip_hd);
1473                 break;
1474         }
1475 }
1476
1477 void change_sequence(void)
1478 {
1479         Sequence *last_seq= get_last_seq();
1480         Scene *sce;
1481         short event;
1482
1483         if(last_seq==0) return;
1484
1485         if(last_seq->type & SEQ_EFFECT) {
1486                 event = pupmenu("Change Effect%t"
1487                                 "|Switch A <-> B %x1"
1488                                 "|Switch B <-> C %x10"
1489                                 "|Plugin%x11"
1490                                 "|Recalculate%x12"
1491                                 "|Cross%x2"
1492                                 "|Gamma Cross%x3"
1493                                 "|Add%x4"
1494                                 "|Sub%x5"
1495                                 "|Mul%x6"
1496                                 "|Alpha Over%x7"
1497                                 "|Alpha Under%x8"
1498                                 "|Alpha Over Drop%x9"
1499                                 "|Wipe%x13"
1500                                 "|Glow%x14"
1501                                 "|Transform%x15"
1502                                 "|Color Generator%x16");
1503                 if(event > 0) {
1504                         if(event==1) {
1505                                 SWAP(Sequence *,last_seq->seq1,last_seq->seq2);
1506                         }
1507                         else if(event==10) {
1508                                 SWAP(Sequence *,last_seq->seq2,last_seq->seq3);
1509                         }
1510                         else if(event==11) {
1511                                 activate_fileselect(
1512                                         FILE_SPECIAL, "Select Plugin", 
1513                                         U.plugseqdir, change_plugin_seq);
1514                         }
1515                         else if(event==12);     
1516                                 /* recalculate: only new_stripdata */
1517                         else {
1518                                 /* free previous effect and init new effect */
1519                                 struct SeqEffectHandle sh;
1520
1521                                 if (get_sequence_effect_num_inputs(
1522                                             last_seq->type)
1523                                     < get_sequence_effect_num_inputs(
1524                                             event_to_efftype(event))) {
1525                                         error("New effect needs more "
1526                                               "input strips!");
1527                                 } else {
1528                                         sh = get_sequence_effect(last_seq);
1529                                         sh.free(last_seq);
1530                                         
1531                                         last_seq->type 
1532                                                 = event_to_efftype(event);
1533                                         
1534                                         sh = get_sequence_effect(last_seq);
1535                                         sh.init(last_seq);
1536                                 }
1537                         }
1538
1539                         update_changed_seq_and_deps(last_seq, 0, 1);
1540                         allqueue(REDRAWSEQ, 0);
1541                         BIF_undo_push("Change effect Sequencer");
1542                 }
1543         }
1544         else if(last_seq->type == SEQ_IMAGE) {
1545                 if(okee("Change images")) {
1546                         activate_fileselect(FILE_SPECIAL, 
1547                                             "Select Images", 
1548                                             last_imagename, 
1549                                             reload_image_strip);
1550                 }
1551         }
1552         else if(last_seq->type == SEQ_MOVIE) {
1553                 ;
1554         }
1555         else if(last_seq->type == SEQ_SCENE) {
1556                 event= pupmenu("Change Scene%t|Update Start and End");
1557
1558                 if(event==1) {
1559                         sce= last_seq->scene;
1560
1561                         last_seq->len= sce->r.efra - sce->r.sfra + 1;
1562                         last_seq->sfra= sce->r.sfra;
1563                         update_changed_seq_and_deps(last_seq, 1, 1);
1564
1565                         allqueue(REDRAWSEQ, 0);
1566                 }
1567         }
1568
1569 }
1570
1571 void reassign_inputs_seq_effect()
1572 {
1573         Editing *ed= G.scene->ed;
1574         Sequence *seq1, *seq2, *seq3, *last_seq = get_last_seq();
1575
1576         if(last_seq==0 || !(last_seq->type & SEQ_EFFECT)) return;
1577         if(ed==0) return;
1578
1579         if(!seq_effect_find_selected(ed, last_seq, last_seq->type, &seq1, &seq2, &seq3))
1580                 return;
1581
1582         /* see reassigning would create a cycle */
1583         if(seq_is_predecessor(seq1, last_seq) || seq_is_predecessor(seq2, last_seq) ||
1584            seq_is_predecessor(seq3, last_seq)) {
1585                 error("Can't reassign inputs: no cycles allowed");
1586                 return;
1587         }
1588         
1589         last_seq->seq1 = seq1;
1590         last_seq->seq2 = seq2;
1591         last_seq->seq3 = seq3;
1592
1593         update_changed_seq_and_deps(last_seq, 1, 1);
1594
1595         allqueue(REDRAWSEQ, 0);
1596 }
1597
1598 static Sequence *del_seq_find_replace_recurs(Sequence *seq)
1599 {
1600         Sequence *seq1, *seq2, *seq3;
1601
1602         /* try to find a replacement input sequence, and flag for later deletion if
1603            no replacement can be found */
1604
1605         if(!seq)
1606                 return NULL;
1607         else if(!(seq->type & SEQ_EFFECT))
1608                 return ((seq->flag & SELECT)? NULL: seq);
1609         else if(!(seq->flag & SELECT)) {
1610                 /* try to find replacement for effect inputs */
1611                 seq1= del_seq_find_replace_recurs(seq->seq1);
1612                 seq2= del_seq_find_replace_recurs(seq->seq2);
1613                 seq3= del_seq_find_replace_recurs(seq->seq3);
1614
1615                 if(seq1==seq->seq1 && seq2==seq->seq2 && seq3==seq->seq3);
1616                 else if(seq1 || seq2 || seq3) {
1617                         seq->seq1= (seq1)? seq1: (seq2)? seq2: seq3;
1618                         seq->seq2= (seq2)? seq2: (seq1)? seq1: seq3;
1619                         seq->seq3= (seq3)? seq3: (seq1)? seq1: seq2;
1620
1621                         update_changed_seq_and_deps(seq, 1, 1);
1622                 }
1623                 else
1624                         seq->flag |= SELECT; /* mark for delete */
1625         }
1626
1627         if (seq->flag & SELECT) {
1628                 if((seq1 = del_seq_find_replace_recurs(seq->seq1))) return seq1;
1629                 if((seq2 = del_seq_find_replace_recurs(seq->seq2))) return seq2;
1630                 if((seq3 = del_seq_find_replace_recurs(seq->seq3))) return seq3;
1631                 else return NULL;
1632         }
1633         else
1634                 return seq;
1635 }
1636
1637 static void recurs_del_seq_flag(ListBase *lb, short flag, short deleteall)
1638 {
1639         Sequence *seq, *seqn;
1640         Sequence *last_seq = get_last_seq();
1641
1642         seq= lb->first;
1643         while(seq) {
1644                 seqn= seq->next;
1645                 if((seq->flag & flag) || deleteall) {
1646                         if(seq->type==SEQ_RAM_SOUND && seq->sound) 
1647                                 seq->sound->id.us--;
1648
1649                         BLI_remlink(lb, seq);
1650                         if(seq==last_seq) set_last_seq(0);
1651                         if(seq->type==SEQ_META) recurs_del_seq_flag(&seq->seqbase, flag, 1);
1652                         if(seq->ipo) seq->ipo->id.us--;
1653                         free_sequence(seq);
1654                 }
1655                 seq= seqn;
1656         }
1657 }
1658
1659 void del_seq(void)
1660 {
1661         Sequence *seq;
1662         MetaStack *ms;
1663         Editing *ed;
1664
1665         if(okee("Erase selected")==0) return;
1666
1667         ed= G.scene->ed;
1668         if(ed==0) return;
1669
1670         /* free imbufs of all dependent strips */
1671         for(seq=ed->seqbasep->first; seq; seq=seq->next)
1672                 if(seq->flag & SELECT)
1673                         update_changed_seq_and_deps(seq, 1, 0);
1674
1675         /* for effects, try to find a replacement input */
1676         for(seq=ed->seqbasep->first; seq; seq=seq->next)
1677                 if((seq->type & SEQ_EFFECT) && !(seq->flag & SELECT))
1678                         del_seq_find_replace_recurs(seq);
1679
1680         /* delete all selected strips */
1681         recurs_del_seq_flag(ed->seqbasep, SELECT, 0);
1682
1683         /* updates lengths etc */
1684         seq= ed->seqbasep->first;
1685         while(seq) {
1686                 calc_sequence(seq);
1687                 seq= seq->next;
1688         }
1689
1690         /* free parent metas */
1691         ms= ed->metastack.last;
1692         while(ms) {
1693                 ms->parseq->strip->len= 0;              /* force new alloc */
1694                 calc_sequence(ms->parseq);
1695                 ms= ms->prev;
1696         }
1697
1698         BIF_undo_push("Delete from Sequencer");
1699         allqueue(REDRAWSEQ, 0);
1700 }
1701
1702 static void recurs_dupli_seq(ListBase *old, ListBase *new)
1703 {
1704         Sequence *seq, *seqn;
1705         StripElem *se;
1706         int a;
1707
1708         seq= old->first;
1709
1710         while(seq) {
1711                 seq->newseq= 0;
1712                 if(seq->flag & SELECT) {
1713
1714                         if(seq->type==SEQ_META) {
1715                                 seqn= MEM_dupallocN(seq);
1716                                 seq->newseq= seqn;
1717                                 BLI_addtail(new, seqn);
1718
1719                                 seqn->strip= MEM_dupallocN(seq->strip);
1720
1721                                 if(seq->len>0) seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
1722
1723                                 seq->flag &= SEQ_DESEL;
1724                                 seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
1725
1726                                 seqn->seqbase.first= seqn->seqbase.last= 0;
1727                                 recurs_dupli_seq(&seq->seqbase,&seqn->seqbase);
1728
1729                         }
1730                         else if(seq->type == SEQ_SCENE) {
1731                                 seqn= MEM_dupallocN(seq);
1732                                 seq->newseq= seqn;
1733                                 BLI_addtail(new, seqn);
1734
1735                                 seqn->strip= MEM_dupallocN(seq->strip);
1736
1737                                 if(seq->len>0) seqn->strip->stripdata = MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
1738
1739                                 seq->flag &= SEQ_DESEL;
1740                                 seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
1741                         }
1742                         else if(seq->type == SEQ_MOVIE) {
1743                                 seqn= MEM_dupallocN(seq);
1744                                 seq->newseq= seqn;
1745                                 BLI_addtail(new, seqn);
1746
1747                                 seqn->strip= MEM_dupallocN(seq->strip);
1748                                 seqn->anim= 0;
1749
1750                                 if(seqn->len>0) {
1751                                         seqn->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
1752                                         /* copy first elem */
1753                                         *seqn->strip->stripdata= *seq->strip->stripdata;
1754                                         se= seqn->strip->stripdata;
1755                                         a= seq->len;
1756                                         while(a--) {
1757                                                 se->ok= 1;
1758                                                 se++;
1759                                         }
1760                                 }
1761
1762                                 seq->flag &= SEQ_DESEL;
1763                                 seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
1764                         }
1765                         else if(seq->type == SEQ_RAM_SOUND) {
1766                                 seqn= MEM_dupallocN(seq);
1767                                 seq->newseq= seqn;
1768                                 BLI_addtail(new, seqn);
1769
1770                                 seqn->strip= MEM_dupallocN(seq->strip);
1771                                 seqn->anim= 0;
1772                                 seqn->sound->id.us++;
1773                                 if(seqn->ipo) seqn->ipo->id.us++;
1774
1775                                 if(seqn->len>0) {
1776                                         seqn->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
1777                                         /* copy first elem */
1778                                         *seqn->strip->stripdata= *seq->strip->stripdata;
1779                                         se= seqn->strip->stripdata;
1780                                         a= seq->len;
1781                                         while(a--) {
1782                                                 se->ok= 1;
1783                                                 se++;
1784                                         }
1785                                 }
1786
1787                                 seq->flag &= SEQ_DESEL;
1788                                 seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
1789                         }
1790                         else if(seq->type == SEQ_HD_SOUND) {
1791                                 seqn= MEM_dupallocN(seq);
1792                                 seq->newseq= seqn;
1793                                 BLI_addtail(new, seqn);
1794
1795                                 seqn->strip= MEM_dupallocN(seq->strip);
1796                                 seqn->anim= 0;
1797                                 seqn->hdaudio
1798                                         = sound_copy_hdaudio(seq->hdaudio);
1799                                 if(seqn->ipo) seqn->ipo->id.us++;
1800
1801                                 if(seqn->len>0) {
1802                                         seqn->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
1803                                         /* copy first elem */
1804                                         *seqn->strip->stripdata= *seq->strip->stripdata;
1805                                         se= seqn->strip->stripdata;
1806                                         a= seq->len;
1807                                         while(a--) {
1808                                                 se->ok= 1;
1809                                                 se++;
1810                                         }
1811                                 }
1812
1813                                 seq->flag &= SEQ_DESEL;
1814                                 seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
1815                         }
1816                         else if(seq->type < SEQ_EFFECT) {
1817                                 seqn= MEM_dupallocN(seq);
1818                                 seq->newseq= seqn;
1819                                 BLI_addtail(new, seqn);
1820
1821                                 seqn->strip->us++;
1822                                 seq->flag &= SEQ_DESEL;
1823
1824                                 seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
1825                         }
1826                         else {
1827                                 seqn= MEM_dupallocN(seq);
1828                                 seq->newseq= seqn;
1829                                 BLI_addtail(new, seqn);
1830
1831                                 if(seq->seq1 && seq->seq1->newseq) seqn->seq1= seq->seq1->newseq;
1832                                 if(seq->seq2 && seq->seq2->newseq) seqn->seq2= seq->seq2->newseq;
1833                                 if(seq->seq3 && seq->seq3->newseq) seqn->seq3= seq->seq3->newseq;
1834
1835                                 if(seqn->ipo) seqn->ipo->id.us++;
1836
1837                                 if (seq->type & SEQ_EFFECT) {
1838                                         struct SeqEffectHandle sh;
1839                                         sh = get_sequence_effect(seq);
1840                                         if(sh.copy)
1841                                                 sh.copy(seq, seqn);
1842                                 }
1843
1844                                 seqn->strip= MEM_dupallocN(seq->strip);
1845
1846                                 if(seq->len>0) seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
1847
1848                                 seq->flag &= SEQ_DESEL;
1849                                 
1850                                 seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
1851                         }
1852
1853                 }
1854                 seq= seq->next;
1855         }
1856 }
1857
1858 void add_duplicate_seq(void)
1859 {
1860         Editing *ed;
1861         ListBase new;
1862
1863         ed= G.scene->ed;
1864         if(ed==0) return;
1865
1866         new.first= new.last= 0;
1867
1868         recurs_dupli_seq(ed->seqbasep, &new);
1869         addlisttolist(ed->seqbasep, &new);
1870
1871         BIF_undo_push("Add duplicate Sequencer");
1872         transform_seq('g', 0);
1873 }
1874
1875 int insert_gap(int gap, int cfra)
1876 {
1877         Sequence *seq;
1878         Editing *ed;
1879         int done=0;
1880
1881         /* all strips >= cfra are shifted */
1882         ed= G.scene->ed;
1883         if(ed==0) return 0;
1884
1885         WHILE_SEQ(ed->seqbasep) {
1886                 if(seq->startdisp >= cfra) {
1887                         seq->start+= gap;
1888                         calc_sequence(seq);
1889                         done= 1;
1890                 }
1891         }
1892         END_SEQ
1893
1894         return done;
1895 }
1896
1897 void touch_seq_files(void)
1898 {
1899         Sequence *seq;
1900         Editing *ed;
1901         char str[256];
1902
1903         /* touch all strips with movies */
1904         ed= G.scene->ed;
1905         if(ed==0) return;
1906
1907         if(okee("Touch and print selected movies")==0) return;
1908
1909         waitcursor(1);
1910
1911         WHILE_SEQ(ed->seqbasep) {
1912                 if(seq->flag & SELECT) {
1913                         if(seq->type==SEQ_MOVIE) {
1914                                 if(seq->strip && seq->strip->stripdata) {
1915                                         BLI_make_file_string(G.sce, str, seq->strip->dir, seq->strip->stripdata->name);
1916                                         BLI_touch(seq->name);
1917                                 }
1918                         }
1919
1920                 }
1921         }
1922         END_SEQ
1923
1924         waitcursor(0);
1925 }
1926
1927 void set_filter_seq(void)
1928 {
1929         Sequence *seq;
1930         Editing *ed;
1931
1932         ed= G.scene->ed;
1933         if(ed==0) return;
1934
1935         if(okee("Set FilterY")==0) return;
1936
1937         WHILE_SEQ(ed->seqbasep) {
1938                 if(seq->flag & SELECT) {
1939                         if(seq->type==SEQ_MOVIE) {
1940                                 seq->flag |= SEQ_FILTERY;
1941                         }
1942
1943                 }
1944         }
1945         END_SEQ
1946
1947 }
1948
1949
1950
1951 void no_gaps(void)
1952 {
1953         Editing *ed;
1954         int cfra, first= 0, done;
1955
1956         ed= G.scene->ed;
1957         if(ed==0) return;
1958
1959         for(cfra= CFRA; cfra<=EFRA; cfra++) {
1960                 if(first==0) {
1961                         if( evaluate_seq_frame(cfra) ) first= 1;
1962                 }
1963                 else {
1964                         done= 1;
1965                         while( evaluate_seq_frame(cfra) == 0) {
1966                                 done= insert_gap(-1, cfra);
1967                                 if(done==0) break;
1968                         }
1969                         if(done==0) break;
1970                 }
1971         }
1972
1973         BIF_undo_push("No gaps Sequencer");
1974         allqueue(REDRAWSEQ, 0);
1975 }
1976
1977
1978 /* ****************** META ************************* */
1979
1980 void make_meta(void)
1981 {
1982         Sequence *seq, *seqm, *next;
1983         Editing *ed;
1984         int tot;
1985         
1986         ed= G.scene->ed;
1987         if(ed==0) return;
1988
1989         /* is there more than 1 select */
1990         tot= 0;
1991         seq= ed->seqbasep->first;
1992         while(seq) {
1993                 if(seq->flag & SELECT) {
1994                         tot++;
1995                         if (seq->type == SEQ_RAM_SOUND) { 
1996                                 error("Can't make Meta Strip from audio"); 
1997                                 return; 
1998                         }
1999                 }
2000                 seq= seq->next;
2001         }
2002         if(tot < 2) return;
2003
2004         if(okee("Make Meta Strip")==0) return;
2005
2006         /* test relationships */
2007         seq= ed->seqbasep->first;
2008         while(seq) {
2009                 if(seq->flag & SELECT) {
2010                         if(seq->type & SEQ_EFFECT) {
2011                                 if(seq->seq1 && 
2012                                    (seq->seq1->flag & SELECT)==0) tot= 0;
2013                                 if(seq->seq2 &&
2014                                    (seq->seq2->flag & SELECT)==0) tot= 0;
2015                                 if(seq->seq3 &&
2016                                    (seq->seq3->flag & SELECT)==0) tot= 0;
2017                         }
2018                 }
2019                 else if(seq->type & SEQ_EFFECT) {
2020                         if(seq->seq1 &&
2021                            (seq->seq1->flag & SELECT)) tot= 0;
2022                         if(seq->seq2 &&
2023                            (seq->seq2->flag & SELECT)) tot= 0;
2024                         if(seq->seq3 &&
2025                            (seq->seq3->flag & SELECT)) tot= 0;
2026                 }
2027                 if(tot==0) break;
2028                 seq= seq->next;
2029         }
2030         if(tot==0) {
2031                 error("Please select all related strips");
2032                 return;
2033         }
2034
2035         /* remove all selected from main list, and put in meta */
2036
2037         seqm= alloc_sequence(1, 1);
2038         seqm->type= SEQ_META;
2039         seqm->flag= SELECT;
2040
2041         seq= ed->seqbasep->first;
2042         while(seq) {
2043                 next= seq->next;
2044                 if(seq!=seqm && (seq->flag & SELECT)) {
2045                         BLI_remlink(ed->seqbasep, seq);
2046                         BLI_addtail(&seqm->seqbase, seq);
2047                 }
2048                 seq= next;
2049         }
2050         calc_sequence(seqm);
2051
2052         seqm->strip= MEM_callocN(sizeof(Strip), "metastrip");
2053         seqm->strip->len= seqm->len;
2054         seqm->strip->us= 1;
2055         if(seqm->len) seqm->strip->stripdata= MEM_callocN(seqm->len*sizeof(StripElem), "metastripdata");
2056         set_meta_stripdata(seqm);
2057
2058         BIF_undo_push("Make Meta Sequencer");
2059         allqueue(REDRAWSEQ, 0);
2060 }
2061
2062 static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
2063 {
2064         if (seq == seqm) return 1;
2065         else if (seq->seq1 && seq_depends_on_meta(seq->seq1, seqm)) return 1;
2066         else if (seq->seq2 && seq_depends_on_meta(seq->seq2, seqm)) return 1;
2067         else if (seq->seq3 && seq_depends_on_meta(seq->seq3, seqm)) return 1;
2068         else return 0;
2069 }
2070
2071 void un_meta(void)
2072 {
2073         Editing *ed;
2074         Sequence *seq, *last_seq = get_last_seq();
2075
2076         ed= G.scene->ed;
2077         if(ed==0) return;
2078
2079         if(last_seq==0 || last_seq->type!=SEQ_META) return;
2080
2081         if(okee("Un Meta")==0) return;
2082
2083         addlisttolist(ed->seqbasep, &last_seq->seqbase);
2084
2085         last_seq->seqbase.first= 0;
2086         last_seq->seqbase.last= 0;
2087
2088         BLI_remlink(ed->seqbasep, last_seq);
2089         free_sequence(last_seq);
2090
2091         /* emtpy meta strip, delete all effects depending on it */
2092         for(seq=ed->seqbasep->first; seq; seq=seq->next)
2093                 if((seq->type & SEQ_EFFECT) && seq_depends_on_meta(seq, last_seq))
2094                         seq->flag |= SEQ_FLAG_DELETE;
2095
2096         recurs_del_seq_flag(ed->seqbasep, SEQ_FLAG_DELETE, 0);
2097
2098         /* test for effects and overlap */
2099         WHILE_SEQ(ed->seqbasep) {
2100                 if(seq->flag & SELECT) {
2101                         seq->flag &= ~SEQ_OVERLAP;
2102                         if( test_overlap_seq(seq) ) {
2103                                 shuffle_seq(seq);
2104                         }
2105                 }
2106         }
2107         END_SEQ;
2108
2109         sort_seq();
2110
2111         BIF_undo_push("Un-make Meta Sequencer");
2112         allqueue(REDRAWSEQ, 0);
2113
2114 }
2115
2116 void exit_meta(void)
2117 {
2118         Sequence *seq;
2119         MetaStack *ms;
2120         Editing *ed;
2121
2122         ed= G.scene->ed;
2123         if(ed==0) return;
2124
2125         if(ed->metastack.first==0) return;
2126
2127         ms= ed->metastack.last;
2128         BLI_remlink(&ed->metastack, ms);
2129
2130         ed->seqbasep= ms->oldbasep;
2131
2132         /* recalc entire meta */
2133         set_meta_stripdata(ms->parseq);
2134
2135         /* recalc all: the meta can have effects connected to it */
2136         seq= ed->seqbasep->first;
2137         while(seq) {
2138                 calc_sequence(seq);
2139                 seq= seq->next;
2140         }
2141
2142         set_last_seq(ms->parseq);
2143
2144         ms->parseq->flag= SELECT;
2145         recurs_sel_seq(ms->parseq);
2146
2147         MEM_freeN(ms);
2148         allqueue(REDRAWSEQ, 0);
2149
2150         BIF_undo_push("Exit meta strip Sequence");
2151 }
2152
2153
2154 void enter_meta(void)
2155 {
2156         MetaStack *ms;
2157         Editing *ed;
2158         Sequence *last_seq= get_last_seq();
2159
2160         ed= G.scene->ed;
2161         if(ed==0) return;
2162
2163         if(last_seq==0 || last_seq->type!=SEQ_META || last_seq->flag==0) {
2164                 exit_meta();
2165                 return;
2166         }
2167
2168         ms= MEM_mallocN(sizeof(MetaStack), "metastack");
2169         BLI_addtail(&ed->metastack, ms);
2170         ms->parseq= last_seq;
2171         ms->oldbasep= ed->seqbasep;
2172
2173         ed->seqbasep= &last_seq->seqbase;
2174
2175         set_last_seq(NULL);
2176         allqueue(REDRAWSEQ, 0);
2177         BIF_undo_push("Enter meta strip Sequence");
2178 }
2179
2180
2181 /* ****************** END META ************************* */
2182
2183
2184 typedef struct TransSeq {
2185         int start, machine;
2186         int startstill, endstill;
2187         int startdisp, enddisp;
2188         int startofs, endofs;
2189         int len;
2190 } TransSeq;
2191
2192 void transform_seq(int mode, int context)
2193 {
2194         Sequence *seq;
2195         Editing *ed;
2196         float dx, dy, dvec[2], div;
2197         TransSeq *transmain, *ts;
2198         int tot=0, ix, iy, firsttime=1, afbreek=0, midtog= 0, proj= 0;
2199         unsigned short event = 0;
2200         short mval[2], val, xo, yo, xn, yn;
2201         char str[32];
2202
2203         if(mode!='g') return;   /* from gesture */
2204
2205         /* which seqs are involved */
2206         ed= G.scene->ed;
2207         if(ed==0) return;
2208
2209         WHILE_SEQ(ed->seqbasep) {
2210                 if(seq->flag & SELECT) tot++;
2211         }
2212         END_SEQ
2213
2214         if(tot==0) return;
2215
2216         G.moving= 1;
2217
2218         ts=transmain= MEM_callocN(tot*sizeof(TransSeq), "transseq");
2219
2220         WHILE_SEQ(ed->seqbasep) {
2221
2222                 if(seq->flag & SELECT) {
2223
2224                         ts->start= seq->start;
2225                         ts->machine= seq->machine;
2226                         ts->startstill= seq->startstill;
2227                         ts->endstill= seq->endstill;
2228                         ts->startofs= seq->startofs;
2229                         ts->endofs= seq->endofs;
2230
2231                         ts++;
2232                 }
2233         }
2234         END_SEQ
2235
2236         getmouseco_areawin(mval);
2237         xo=xn= mval[0];
2238         yo=yn= mval[1];
2239         dvec[0]= dvec[1]= 0.0;
2240
2241         while(afbreek==0) {
2242                 getmouseco_areawin(mval);
2243                 if(mval[0]!=xo || mval[1]!=yo || firsttime) {
2244                         firsttime= 0;
2245
2246                         if(mode=='g') {
2247
2248                                 dx= mval[0]- xo;
2249                                 dy= mval[1]- yo;
2250
2251                                 div= G.v2d->mask.xmax-G.v2d->mask.xmin;
2252                                 dx= (G.v2d->cur.xmax-G.v2d->cur.xmin)*(dx)/div;
2253
2254                                 div= G.v2d->mask.ymax-G.v2d->mask.ymin;
2255                                 dy= (G.v2d->cur.ymax-G.v2d->cur.ymin)*(dy)/div;
2256
2257                                 if(G.qual & LR_SHIFTKEY) {
2258                                         if(dx>1.0) dx= 1.0; else if(dx<-1.0) dx= -1.0;
2259                                 }
2260
2261                                 dvec[0]+= dx;
2262                                 dvec[1]+= dy;
2263
2264                                 if(midtog) dvec[proj]= 0.0;
2265                                 ix= floor(dvec[0]+0.5);
2266                                 iy= floor(dvec[1]+0.5);
2267
2268
2269                                 ts= transmain;
2270
2271                                 WHILE_SEQ(ed->seqbasep) {
2272                                         if(seq->flag & SELECT) {
2273                                                 if(seq->flag & SEQ_LEFTSEL) {
2274                                                         if(ts->startstill) {
2275                                                                 seq->startstill= ts->startstill-ix;
2276                                                                 if(seq->startstill<0) seq->startstill= 0;
2277                                                         }
2278                                                         else if(ts->startofs) {
2279                                                                 seq->startofs= ts->startofs+ix;
2280                                                                 if(seq->startofs<0) seq->startofs= 0;
2281                                                         }
2282                                                         else {
2283                                                                 if(ix>0) {
2284                                                                         seq->startofs= ix;
2285                                                                         seq->startstill= 0;
2286                                                                 }
2287                                                                 else if (seq->type != SEQ_RAM_SOUND && seq->type != SEQ_HD_SOUND) {
2288                                                                         seq->startstill= -ix;
2289                                                                         seq->startofs= 0;
2290                                                                 }
2291                                                         }
2292                                                         if(seq->len <= seq->startofs+seq->endofs) {
2293                                                                 seq->startofs= seq->len-seq->endofs-1;
2294                                                         }
2295                                                 }
2296                                                 if(seq->flag & SEQ_RIGHTSEL) {
2297                                                         if(ts->endstill) {
2298                                                                 seq->endstill= ts->endstill+ix;
2299                                                                 if(seq->endstill<0) seq->endstill= 0;
2300                                                         }
2301                                                         else if(ts->endofs) {
2302                                                                 seq->endofs= ts->endofs-ix;
2303                                                                 if(seq->endofs<0) seq->endofs= 0;
2304                                                         }
2305                                                         else {
2306                                                                 if(ix<0) {
2307                                                                         seq->endofs= -ix;
2308                                                                         seq->endstill= 0;
2309                                                                 }
2310                                                                 else if (seq->type != SEQ_RAM_SOUND && seq->type != SEQ_HD_SOUND) {
2311                                                                         seq->endstill= ix;
2312                                                                         seq->endofs= 0;
2313                                                                 }
2314                                                         }
2315                                                         if(seq->len <= seq->startofs+seq->endofs) {
2316                                                                 seq->endofs= seq->len-seq->startofs-1;
2317                                                         }
2318                                                 }
2319                                                 if( (seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))==0 ) {
2320                                                         if(sequence_is_free_transformable(seq)) seq->start= ts->start+ ix;
2321
2322                                                         if(seq->depth==0) seq->machine= ts->machine+ iy;
2323
2324                                                         if(seq->machine<1) seq->machine= 1;
2325                                                         else if(seq->machine>= MAXSEQ) seq->machine= MAXSEQ;
2326                                                 }
2327
2328                                                 calc_sequence(seq);
2329
2330                                                 ts++;
2331                                         }
2332                                 }
2333                                 END_SEQ
2334
2335                                 sprintf(str, "X: %d   Y: %d  ", ix, iy);
2336                                 headerprint(str);
2337                         }
2338
2339                         xo= mval[0];
2340                         yo= mval[1];
2341
2342                         /* test for effect and overlap */
2343
2344                         WHILE_SEQ(ed->seqbasep) {
2345                                 if(seq->flag & SELECT) {
2346                                         seq->flag &= ~SEQ_OVERLAP;
2347                                         if( test_overlap_seq(seq) ) {
2348                                                 seq->flag |= SEQ_OVERLAP;
2349                                         }
2350                                 }
2351                                 else if(seq->type & SEQ_EFFECT) {
2352                                         if(seq->seq1 && seq->seq1->flag & SELECT) calc_sequence(seq);
2353                                         else if(seq->seq2 && seq->seq2->flag & SELECT) calc_sequence(seq);
2354                                         else if(seq->seq3 && seq->seq3->flag & SELECT) calc_sequence(seq);
2355                                 }
2356                         }
2357                         END_SEQ;
2358
2359                         force_draw(0);
2360                 }
2361                 else BIF_wait_for_statechange();
2362
2363                 while(qtest()) {
2364                         event= extern_qread(&val);
2365                         if(val) {
2366                                 switch(event) {
2367                                 case ESCKEY:
2368                                 case LEFTMOUSE:
2369                                 case RIGHTMOUSE:
2370                                 case SPACEKEY:
2371                                 case RETKEY:
2372                                         afbreek= 1;
2373                                         break;
2374                                 case MIDDLEMOUSE:
2375                                         midtog= ~midtog;
2376                                         if(midtog) {
2377                                                 if( abs(mval[0]-xn) > abs(mval[1]-yn)) proj= 1;
2378                                                 else proj= 0;
2379                                                 firsttime= 1;
2380                                         }
2381                                         break;
2382                                 default:
2383                                         arrows_move_cursor(event);
2384                                 }
2385                         }
2386                         if(afbreek) break;
2387                 }
2388         }
2389
2390         if((event==ESCKEY) || (event==RIGHTMOUSE)) {
2391
2392                 ts= transmain;
2393                 WHILE_SEQ(ed->seqbasep) {
2394                         if(seq->flag & SELECT) {
2395                                 seq->start= ts->start;
2396                                 seq->machine= ts->machine;
2397                                 seq->startstill= ts->startstill;
2398                                 seq->endstill= ts->endstill;
2399                                 seq->startofs= ts->startofs;
2400                                 seq->endofs= ts->endofs;
2401
2402                                 calc_sequence(seq);
2403                                 seq->flag &= ~SEQ_OVERLAP;
2404
2405                                 ts++;
2406                         } else if(seq->type & SEQ_EFFECT) {
2407                                 if(seq->seq1 && seq->seq1->flag & SELECT) calc_sequence(seq);
2408                                 else if(seq->seq2 && seq->seq2->flag & SELECT) calc_sequence(seq);
2409                                 else if(seq->seq3 && seq->seq3->flag & SELECT) calc_sequence(seq);
2410                         }
2411
2412                 }
2413                 END_SEQ
2414         }
2415         else {
2416
2417                 /* images, effects and overlap */
2418                 WHILE_SEQ(ed->seqbasep) {
2419                         if(seq->type == SEQ_META) {
2420                                 calc_sequence(seq);
2421                                 seq->flag &= ~SEQ_OVERLAP;
2422                                 if( test_overlap_seq(seq) ) shuffle_seq(seq);
2423                         }
2424                         else if(seq->flag & SELECT) {
2425                                 calc_sequence(seq);
2426                                 seq->flag &= ~SEQ_OVERLAP;
2427                                 if( test_overlap_seq(seq) ) shuffle_seq(seq);
2428                         }
2429                         else if(seq->type & SEQ_EFFECT) calc_sequence(seq);
2430                 }
2431                 END_SEQ
2432
2433                 /* as last: */
2434                 sort_seq();
2435         }
2436
2437         G.moving= 0;
2438         MEM_freeN(transmain);
2439
2440         BIF_undo_push("Transform Sequencer");
2441         allqueue(REDRAWSEQ, 0);
2442 }
2443
2444 void seq_cut(int cutframe)
2445 {
2446         Editing *ed;
2447         Sequence *seq;
2448         TransSeq *ts, *transmain;
2449         int tot=0;
2450         ListBase newlist;
2451         
2452         ed= G.scene->ed;
2453         if(ed==0) return;
2454         
2455         /* test for validity */
2456         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
2457                 if(seq->flag & SELECT) {
2458                         if(cutframe > seq->startdisp && cutframe < seq->enddisp)
2459                                 if(seq->type==SEQ_META) break;
2460                 }
2461         }
2462         if(seq) {
2463                 error("Cannot cut Meta strips");
2464                 return;
2465         }
2466         
2467         /* we build an array of TransSeq, to denote which strips take part in cutting */
2468         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
2469                 if(seq->flag & SELECT) {
2470                         if(cutframe > seq->startdisp && cutframe < seq->enddisp)
2471                                 tot++;
2472                         else
2473                                 seq->flag &= ~SELECT;   // bad code, but we need it for recurs_dupli_seq... note that this ~SELECT assumption is used in loops below too (ton)
2474                 }
2475         }
2476         
2477         if(tot==0) {
2478                 error("No strips to cut");
2479                 return;
2480         }
2481         
2482         ts=transmain= MEM_callocN(tot*sizeof(TransSeq), "transseq");
2483         
2484         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
2485                 if(seq->flag & SELECT) {
2486                         
2487                         ts->start= seq->start;
2488                         ts->machine= seq->machine;
2489                         ts->startstill= seq->startstill;
2490                         ts->endstill= seq->endstill;
2491                         ts->startdisp= seq->startdisp;
2492                         ts->enddisp= seq->enddisp;
2493                         ts->startofs= seq->startofs;
2494                         ts->endofs= seq->endofs;
2495                         ts->len= seq->len;
2496                         
2497                         ts++;
2498                 }
2499         }
2500                 
2501         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
2502                 if(seq->flag & SELECT) {
2503                         
2504                         /* strips with extended stillframes before */
2505                         if ((seq->startstill) && (cutframe <seq->start)) {
2506                                 seq->start= cutframe -1;
2507                                 seq->startstill= cutframe -seq->startdisp -1;
2508                                 seq->len= 1;
2509                                 seq->endstill= 0;
2510                         }
2511                         
2512                         /* normal strip */
2513                         else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) {
2514                                 seq->endofs = (seq->start+seq->len) - cutframe;
2515                         }
2516                         
2517                         /* strips with extended stillframes after */
2518                         else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
2519                                 seq->endstill -= seq->enddisp - cutframe;
2520                         }
2521                         
2522                         calc_sequence(seq);
2523                 }
2524         }
2525                 
2526         newlist.first= newlist.last= NULL;
2527         
2528         /* now we duplicate the cut strip and move it into place afterwards */
2529         recurs_dupli_seq(ed->seqbasep, &newlist);
2530         addlisttolist(ed->seqbasep, &newlist);
2531         
2532         ts= transmain;
2533         
2534         /* go through all the strips and correct them based on their stored values */
2535         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
2536                 if(seq->flag & SELECT) {
2537
2538                         /* strips with extended stillframes before */
2539                         if ((seq->startstill) && (cutframe == seq->start + 1)) {
2540                                 seq->start = ts->start;
2541                                 seq->startstill= ts->start- cutframe;
2542                                 seq->len = ts->len;
2543                                 seq->endstill = ts->endstill;
2544                         }
2545                         
2546                         /* normal strip */
2547                         else if ((cutframe>=seq->start)&&(cutframe<=(seq->start+seq->len))) {
2548                                 seq->startstill = 0;
2549                                 seq->startofs = cutframe - ts->start;
2550                                 seq->endofs = ts->endofs;
2551                                 seq->endstill = ts->endstill;
2552                         }                               
2553                         
2554                         /* strips with extended stillframes after */
2555                         else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
2556                                 seq->start = cutframe - ts->len +1;
2557                                 seq->startofs = ts->len-1;
2558                                 seq->endstill = ts->enddisp - cutframe -1;
2559                                 seq->startstill = 0;
2560                         }
2561                         calc_sequence(seq);
2562                         
2563                         ts++;
2564                 }
2565         }
2566                 
2567         /* as last: */  
2568         sort_seq();
2569         MEM_freeN(transmain);
2570         
2571         allqueue(REDRAWSEQ, 0);
2572 }
2573
2574 void seq_snap_menu(void)
2575 {
2576         short event;
2577
2578         event= pupmenu("Snap %t|To Current Frame%x1");
2579         if(event < 1) return;
2580
2581         seq_snap(event);
2582 }
2583
2584 void seq_snap(short event)
2585 {
2586         Editing *ed;
2587         Sequence *seq;
2588
2589         ed= G.scene->ed;
2590         if(ed==0) return;
2591
2592         /* problem: contents of meta's are all shifted to the same position... */
2593
2594         /* also check metas */
2595         WHILE_SEQ(ed->seqbasep) {
2596                 if(seq->flag & SELECT) {
2597                         if(sequence_is_free_transformable(seq)) seq->start= CFRA-seq->startofs+seq->startstill;
2598                         calc_sequence(seq);
2599                 }
2600         }
2601         END_SEQ
2602
2603
2604         /* test for effects and overlap */
2605         WHILE_SEQ(ed->seqbasep) {
2606                 if(seq->flag & SELECT) {
2607                         seq->flag &= ~SEQ_OVERLAP;
2608                         if( test_overlap_seq(seq) ) {
2609                                 shuffle_seq(seq);
2610                         }
2611                 }
2612                 else if(seq->type & SEQ_EFFECT) {
2613                         if(seq->seq1->flag & SELECT) calc_sequence(seq);
2614                         else if(seq->seq2->flag & SELECT) calc_sequence(seq);
2615                         else if(seq->seq3->flag & SELECT) calc_sequence(seq);
2616                 }
2617         }
2618         END_SEQ;
2619
2620         /* as last: */
2621         sort_seq();
2622
2623         BIF_undo_push("Snap menu Sequencer");
2624         allqueue(REDRAWSEQ, 0);
2625 }
2626
2627 void borderselect_seq(void)
2628 {
2629         Sequence *seq;
2630         Editing *ed;
2631         rcti rect;
2632         rctf rectf, rq;
2633         int val;
2634         short mval[2];
2635
2636         ed= G.scene->ed;
2637         if(ed==0) return;
2638
2639         val= get_border(&rect, 3);
2640
2641         if(val) {
2642                 mval[0]= rect.xmin;
2643                 mval[1]= rect.ymin;
2644                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
2645                 mval[0]= rect.xmax;
2646                 mval[1]= rect.ymax;
2647                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
2648
2649                 seq= ed->seqbasep->first;
2650                 while(seq) {
2651
2652                         if(seq->startstill) rq.xmin= seq->start;
2653                         else rq.xmin= seq->startdisp;
2654                         rq.ymin= seq->machine+0.2;
2655                         if(seq->endstill) rq.xmax= seq->start+seq->len;
2656                         else rq.xmax= seq->enddisp;
2657                         rq.ymax= seq->machine+0.8;
2658
2659                         if(BLI_isect_rctf(&rq, &rectf, 0)) {
2660                                 if(val==LEFTMOUSE) {
2661                                         seq->flag |= SELECT;
2662                                 }
2663                                 else {
2664                                         seq->flag &= ~SELECT;
2665                                 }
2666                                 recurs_sel_seq(seq);
2667                         }
2668
2669                         seq= seq->next;
2670                 }
2671
2672                 BIF_undo_push("Border select Sequencer");
2673                 addqueue(curarea->win, REDRAW, 1);
2674         }
2675 }