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