bugfix [#8263] Video Sequence Editor > Sequence > Reassign Inputs > crash
[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_curve_types.h"
59 #include "DNA_scene_types.h"
60 #include "DNA_screen_types.h"
61 #include "DNA_space_types.h"
62 #include "DNA_sequence_types.h"
63 #include "DNA_view2d_types.h"
64 #include "DNA_userdef_types.h"
65 #include "DNA_sound_types.h"
66
67 #include "BKE_utildefines.h"
68 #include "BKE_plugin_types.h"
69 #include "BKE_global.h"
70 #include "BKE_image.h"
71 #include "BKE_library.h"
72 #include "BKE_main.h"
73 #include "BKE_scene.h"
74
75 #include "BIF_space.h"
76 #include "BIF_interface.h"
77 #include "BIF_screen.h"
78 #include "BIF_drawseq.h"
79 #include "BIF_editseq.h"
80 #include "BIF_mywindow.h"
81 #include "BIF_toolbox.h"
82 #include "BIF_writemovie.h"
83 #include "BIF_editview.h"
84 #include "BIF_scrarea.h"
85 #include "BIF_editsound.h"
86 #include "BIF_imasel.h"
87
88 #include "BSE_edit.h"
89 #include "BSE_sequence.h"
90 #include "BSE_seqeffects.h"
91 #include "BSE_filesel.h"
92 #include "BSE_drawipo.h"
93 #include "BSE_seqaudio.h"
94 #include "BSE_time.h"
95
96 #include "BDR_editobject.h"
97
98 #include "blendef.h"
99 #include "mydevice.h"
100
101 static Sequence *_last_seq=0;
102 static int _last_seq_init=0;
103
104 #ifdef WIN32
105 char last_imagename[FILE_MAXDIR+FILE_MAXFILE]= "c:\\";
106 #else
107 char last_imagename[FILE_MAXDIR+FILE_MAXFILE]= "/";
108 #endif
109
110 char last_sounddir[FILE_MAXDIR+FILE_MAXFILE]= "";
111
112 #define SEQ_DESEL       ~(SELECT+SEQ_LEFTSEL+SEQ_RIGHTSEL)
113
114 typedef struct TransSeq {
115         int start, machine;
116         int startstill, endstill;
117         int startdisp, enddisp;
118         int startofs, endofs;
119         int final_left, final_right;
120         int len;
121 } TransSeq;
122
123 Sequence *get_last_seq()
124 {
125         if(!_last_seq_init) {
126                 Editing *ed;
127                 Sequence *seq;
128
129                 ed= G.scene->ed;
130                 if(!ed) return NULL;
131
132                 for(seq= ed->seqbasep->first; seq; seq=seq->next)
133                         if(seq->flag & SELECT)
134                                 _last_seq= seq;
135
136                 _last_seq_init = 1;
137         }
138
139         return _last_seq;
140 }
141
142 void set_last_seq(Sequence *seq)
143 {
144         _last_seq = seq;
145         _last_seq_init = 1;
146 }
147
148 void clear_last_seq(Sequence *seq)
149 {
150         _last_seq = NULL;
151         _last_seq_init = 0;
152 }
153
154 Sequence *get_forground_frame_seq(int frame)
155 {
156         Editing *ed;
157         Sequence *seq, *best_seq=NULL;
158         int best_machine = -1;
159         ed= G.scene->ed;
160         if(!ed) return NULL;
161         
162         for (seq=ed->seqbasep->first; seq; seq= seq->next) {
163                 if(seq->startdisp > frame || seq->enddisp <= frame)
164                         continue;
165                 /* only use elements you can see - not */
166                 if (ELEM6(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE, SEQ_MOVIE_AND_HD_SOUND, SEQ_COLOR)) {
167                         if (seq->machine > best_machine) {
168                                 best_seq = seq;
169                                 best_machine = seq->machine;
170                         }
171                 }
172         }
173         return best_seq;
174 }
175
176 /* seq funcs's for transforming internally
177  notice the difference between start/end and left/right.
178  
179  left and right are the bounds at which the setuence is rendered,
180 start and end are from the start and fixed length of the sequence.
181 */
182 int seq_tx_get_start(Sequence *seq) {
183         return seq->start;
184 }
185 int seq_tx_get_end(Sequence *seq)
186 {
187         return seq->start+seq->len;
188 }
189
190 int seq_tx_get_final_left(Sequence *seq)
191 {
192         return (seq->start - seq->startstill) + seq->startofs;
193 }
194 int  seq_tx_get_final_right(Sequence *seq)
195 {
196         return ((seq->start+seq->len) + seq->endstill) - seq->endofs;
197 }
198
199 void seq_tx_set_final_left(Sequence *seq, int val)
200 {
201         if (val < (seq)->start) {
202                 seq->startstill = abs(val - (seq)->start);
203                                 (seq)->startofs = 0;
204         } else {
205                 seq->startofs = abs(val - (seq)->start);
206                 seq->startstill = 0;
207         }
208 }
209
210 void seq_tx_set_final_right(Sequence *seq, int val)
211 {
212         if (val > (seq)->start + (seq)->len) {
213                 seq->endstill = abs(val - (seq->start + (seq)->len));
214                 (seq)->endofs = 0;
215         } else {
216                 seq->endofs = abs(val - ((seq)->start + (seq)->len));
217                 seq->endstill = 0;
218         }
219 }
220
221 /* check if one side can be transformed */
222 int seq_tx_check_left(Sequence *seq)
223 {
224         if (seq->flag & SELECT) {
225                 if (seq->flag & SEQ_LEFTSEL)
226                         return 1;
227                 else if (seq->flag & SEQ_RIGHTSEL)
228                         return 0;
229                 
230                 return 1; /* selected and neither left or right handles are, so let us move both */
231         }
232         return 0;
233 }
234
235 int seq_tx_check_right(Sequence *seq)
236 {
237         if (seq->flag & SELECT) {
238                 if (seq->flag & SEQ_RIGHTSEL)
239                         return 1;
240                 else if (seq->flag & SEQ_LEFTSEL)
241                         return 0;
242                 
243                 return 1; /* selected and neither left or right handles are, so let us move both */
244         }
245         return 0;
246 }
247
248 /* used so we can do a quick check for single image seq
249    since they work a bit differently to normal image seq's (during transform) */
250 int check_single_seq(Sequence *seq)
251 {
252         if ( seq->len==1 && (seq->type == SEQ_IMAGE || seq->type == SEQ_COLOR))
253                 return 1;
254         else
255                 return 0;
256 }
257
258 static void fix_single_image_seq(Sequence *seq)
259 {
260         int left, start, offset;
261         if (!check_single_seq(seq))
262                 return;
263         
264         /* make sure the image is always at the start since there is only one,
265            adjusting its start should be ok */
266         left = seq_tx_get_final_left(seq);
267         start = seq->start;
268         if (start != left) {
269                 offset = left - start;
270                 seq_tx_set_final_left( seq, seq_tx_get_final_left(seq) - offset );
271                 seq_tx_set_final_right( seq, seq_tx_get_final_right(seq) - offset );
272                 seq->start += offset;
273         }
274 }
275
276 static void change_plugin_seq(char *str)        /* called from fileselect */
277 {
278         struct SeqEffectHandle sh;
279         Sequence *last_seq= get_last_seq();
280
281         if(last_seq && last_seq->type != SEQ_PLUGIN) return;
282
283         sh = get_sequence_effect(last_seq);
284         sh.free(last_seq);
285         sh.init_plugin(last_seq, str);
286
287         last_seq->machine = MAX3(last_seq->seq1->machine, 
288                                  last_seq->seq2->machine, 
289                                  last_seq->seq3->machine);
290
291         if( test_overlap_seq(last_seq) ) shuffle_seq(last_seq);
292         
293         BIF_undo_push("Load/Change Plugin, Sequencer");
294 }
295
296
297 void boundbox_seq(void)
298 {
299         Sequence *seq;
300         Editing *ed;
301         float min[2], max[2];
302
303         ed= G.scene->ed;
304         if(ed==0) return;
305
306         min[0]= 0.0;
307         max[0]= EFRA+1;
308         min[1]= 0.0;
309         max[1]= 8.0;
310
311         seq= ed->seqbasep->first;
312         while(seq) {
313
314                 if( min[0] > seq->startdisp-1) min[0]= seq->startdisp-1;
315                 if( max[0] < seq->enddisp+1) max[0]= seq->enddisp+1;
316                 if( max[1] < seq->machine+2.0) max[1]= seq->machine+2.0;
317
318                 seq= seq->next;
319         }
320
321         G.v2d->tot.xmin= min[0];
322         G.v2d->tot.xmax= max[0];
323         G.v2d->tot.ymin= min[1];
324         G.v2d->tot.ymax= max[1];
325
326 }
327
328 int sequence_is_free_transformable(Sequence * seq)
329 {
330         return seq->type < SEQ_EFFECT
331                 || (get_sequence_effect_num_inputs(seq->type) == 0);
332 }
333
334 char mouse_cfra_side( int frame ) {
335         short mval[2];
336         float xmouse, ymouse;
337         getmouseco_areawin(mval);
338         
339         /* choose the side based on which side of the playhead the mouse is on */
340         areamouseco_to_ipoco(G.v2d, mval, &xmouse, &ymouse);
341         return (xmouse > frame) ? 'R' : 'L';
342 }
343
344 Sequence *find_neighboring_sequence(Sequence *test, int lr, int sel) {
345 /*      looks to the left on lr==1, to the right on lr==2
346         sel - 0==unselected, 1==selected, -1==done care*/
347         Sequence *seq;
348         Editing *ed;
349
350         ed= G.scene->ed;
351         if(ed==0) return 0;
352
353         if (sel>0) sel = SELECT;
354         
355         seq= ed->seqbasep->first;
356         while(seq) {
357                 if(     (seq!=test) &&
358                         (test->machine==seq->machine) &&
359                         (test->depth==seq->depth) && 
360                         ((sel == -1) || (sel && (seq->flag & SELECT)) || (sel==0 && (seq->flag & SELECT)==0)  ))
361                 {
362                         switch (lr) {
363                         case 1:
364                                 if (test->startdisp == (seq->enddisp)) {
365                                         return seq;
366                                 }
367                                 break;
368                         case 2:
369                                 if (test->enddisp == (seq->startdisp)) {
370                                         return seq;
371                                 }
372                                 break;
373                         }
374                 }
375                 seq= seq->next;
376         }
377         return NULL;
378 }
379
380 Sequence *find_next_prev_sequence(Sequence *test, int lr, int sel) {
381 /*      looks to the left on lr==1, to the right on lr==2
382         sel - 0==unselected, 1==selected, -1==done care*/
383         Sequence *seq,*best_seq = NULL;
384         Editing *ed;
385         
386         int dist, best_dist;
387         best_dist = MAXFRAME*2;
388
389         ed= G.scene->ed;
390         if(ed==0) return 0;
391
392         if (sel) sel = SELECT;
393         
394         seq= ed->seqbasep->first;
395         while(seq) {
396                 if(             (seq!=test) &&
397                                 (test->machine==seq->machine) &&
398                                 (test->depth==seq->depth) &&
399                                 ((sel == -1) || (sel==(seq->flag & SELECT))))
400                 {
401                         dist = MAXFRAME*2;
402                         
403                         switch (lr) {
404                         case 1:
405                                 if (seq->enddisp <= test->startdisp) {
406                                         dist = test->enddisp - seq->startdisp;
407                                 }
408                                 break;
409                         case 2:
410                                 if (seq->startdisp >= test->enddisp) {
411                                         dist = seq->startdisp - test->enddisp;
412                                 }
413                                 break;
414                         }
415                         
416                         if (dist==0) {
417                                 best_seq = seq;
418                                 break;
419                         } else if (dist < best_dist) {
420                                 best_dist = dist;
421                                 best_seq = seq;
422                         }
423                 }
424                 seq= seq->next;
425         }
426         return best_seq; /* can be null */
427 }
428
429
430 Sequence *find_nearest_seq(int *hand)
431 {
432         Sequence *seq;
433         Editing *ed;
434         float x, y;
435         short mval[2];
436         float pixelx;
437         float handsize;
438         float displen;
439         View2D *v2d = G.v2d;
440         *hand= 0;
441
442         ed= G.scene->ed;
443         if(ed==0) return 0;
444         
445         pixelx = (v2d->cur.xmax - v2d->cur.xmin)/(v2d->mask.xmax - v2d->mask.xmin);
446
447         getmouseco_areawin(mval);
448         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
449         
450         seq= ed->seqbasep->first;
451         
452         while(seq) {
453                 if(seq->machine == (int)y) {
454                         /* check for both normal strips, and strips that have been flipped horizontally */
455                         if( ((seq->startdisp < seq->enddisp) && (seq->startdisp<=x && seq->enddisp>=x)) ||
456                                 ((seq->startdisp > seq->enddisp) && (seq->startdisp>=x && seq->enddisp<=x)) )
457                         {
458                                 if(sequence_is_free_transformable(seq)) {
459                                         
460                                         /* clamp handles to defined size in pixel space */
461                                         
462                                         handsize = seq->handsize;
463                                         displen = (float)abs(seq->startdisp - seq->enddisp);
464                                         
465                                         if (displen / pixelx > 16) { /* dont even try to grab the handles of small strips */
466                                                 /* Set the max value to handle to 1/3 of the total len when its less then 28.
467                                                 * This is important because otherwise selecting handles happens even when you click in the middle */
468                                                 
469                                                 if ((displen/3) < 30*pixelx) {
470                                                         handsize = displen/3;
471                                                 } else {
472                                                         CLAMP(handsize, 7*pixelx, 30*pixelx);
473                                                 }
474                                                 
475                                                 if( handsize+seq->startdisp >=x )
476                                                         *hand= 1;
477                                                 else if( -handsize+seq->enddisp <=x )
478                                                         *hand= 2;
479                                         }
480                                 }
481                                 return seq;
482                         }
483                 }
484                 seq= seq->next;
485         }
486         return 0;
487 }
488
489 void update_seq_ipo_rect(Sequence * seq)
490 {
491         float start;
492         float end;
493
494         if (!seq || !seq->ipo) {
495                 return;
496         }
497         start =  -5.0;
498         end   =  105.0;
499
500         /* Adjust IPO window to sequence and 
501            avoid annoying snap-back to startframe 
502            when Lock Time is on */
503         if (G.v2d->flag & V2D_VIEWLOCK) {
504                 if ((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
505                         start = -5.0 + seq->startdisp;
506                         end = 5.0 + seq->enddisp;
507                 } else {
508                         start = (float)G.scene->r.sfra - 0.1;
509                         end = G.scene->r.efra;
510                 }
511         }
512
513         seq->ipo->cur.xmin= start;
514         seq->ipo->cur.xmax= end;
515 }
516
517 void update_seq_icu_rects(Sequence * seq)
518 {
519         IpoCurve *icu= NULL;
520         struct SeqEffectHandle sh;
521
522         if (!seq || !seq->ipo) {
523                 return;
524         }
525
526         if(!(seq->type & SEQ_EFFECT)) {
527                 return;
528         }
529
530         sh = get_sequence_effect(seq);
531
532         for(icu= seq->ipo->curve.first; icu; icu= icu->next) {
533                 sh.store_icu_yrange(seq, icu->adrcode, &icu->ymin, &icu->ymax);
534         }
535 }
536
537 int test_overlap_seq(Sequence *test)
538 {
539         Sequence *seq;
540         Editing *ed;
541
542         ed= G.scene->ed;
543         if(ed==0) return 0;
544
545         seq= ed->seqbasep->first;
546         while(seq) {
547                 if(seq!=test) {
548                         if(test->machine==seq->machine) {
549                                 if(test->depth==seq->depth) {
550                                         if( (test->enddisp <= seq->startdisp) || (test->startdisp >= seq->enddisp) );
551                                         else return 1;
552                                 }
553                         }
554                 }
555                 seq= seq->next;
556         }
557         return 0;
558 }
559
560 void shuffle_seq(Sequence *test)
561 {
562         Editing *ed;
563         Sequence *seq;
564         int a, start;
565
566         ed= G.scene->ed;
567         if(ed==0) return;
568
569         /* is there more than 1 select: only shuffle y */
570         a=0;
571         seq= ed->seqbasep->first;
572         while(seq) {
573                 if(seq->flag & SELECT) a++;
574                 seq= seq->next;
575         }
576
577         if(a<2 && test->type==SEQ_IMAGE) {
578                 start= test->start;
579
580                 for(a= 1; a<50; a++) {
581                         test->start= start+a;
582                         calc_sequence(test);
583                         if( test_overlap_seq(test)==0) return;
584                         test->start= start-a;
585                         calc_sequence(test);
586                         if( test_overlap_seq(test)==0) return;
587                 }
588                 test->start= start;
589         }
590
591         test->machine++;
592         calc_sequence(test);
593         while( test_overlap_seq(test) ) {
594                 if(test->machine >= MAXSEQ) {
595                         error("There is no more space to add a sequence strip");
596
597                         BLI_remlink(ed->seqbasep, test);
598                         free_sequence(test);
599                         return;
600                 }
601                 test->machine++;
602                 calc_sequence(test);
603         }
604 }
605
606 static int seq_is_parent(Sequence *par, Sequence *seq)
607 {
608         return ((par->seq1 == seq) || (par->seq2 == seq) || (par->seq3 == seq));
609 }
610
611 static int seq_is_predecessor(Sequence *pred, Sequence *seq)
612 {
613         if(pred == seq) return 0;
614         else if(seq_is_parent(pred, seq)) return 1;
615         else if(pred->seq1 && seq_is_predecessor(pred->seq1, seq)) return 1;
616         else if(pred->seq2 && seq_is_predecessor(pred->seq2, seq)) return 1;
617         else if(pred->seq3 && seq_is_predecessor(pred->seq3, seq)) return 1;
618
619         return 0;
620 }
621
622 static void deselect_all_seq(void)
623 {
624         Sequence *seq;
625         Editing *ed;
626
627         ed= G.scene->ed;
628         if(ed==0) return;
629
630         WHILE_SEQ(ed->seqbasep) {
631                 seq->flag &= SEQ_DESEL;
632         }
633         END_SEQ
634                 
635         BIF_undo_push("(De)select all Strips, Sequencer");
636 }
637
638 static void recurs_sel_seq(Sequence *seqm)
639 {
640         Sequence *seq;
641
642         seq= seqm->seqbase.first;
643         while(seq) {
644
645                 if(seqm->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL)) seq->flag &= SEQ_DESEL;
646                 else if(seqm->flag & SELECT) seq->flag |= SELECT;
647                 else seq->flag &= SEQ_DESEL;
648
649                 if(seq->seqbase.first) recurs_sel_seq(seq);
650
651                 seq= seq->next;
652         }
653 }
654
655 void swap_select_seq(void)
656 {
657         Sequence *seq;
658         Editing *ed;
659         int sel=0;
660
661         ed= G.scene->ed;
662         if(ed==0) return;
663
664         WHILE_SEQ(ed->seqbasep) {
665                 if(seq->flag & SELECT) sel= 1;
666         }
667         END_SEQ
668
669         WHILE_SEQ(ed->seqbasep) {
670                 /* always deselect all to be sure */
671                 seq->flag &= SEQ_DESEL;
672                 if(sel==0) seq->flag |= SELECT;
673         }
674         END_SEQ
675
676         allqueue(REDRAWSEQ, 0);
677         BIF_undo_push("Swap Selected Strips, Sequencer");
678
679 }
680
681 void select_channel_direction(Sequence *test,int lr) {
682 /* selects all strips in a channel to one direction of the passed strip */
683         Sequence *seq;
684         Editing *ed;
685
686         ed= G.scene->ed;
687         if(ed==0) return;
688
689         seq= ed->seqbasep->first;
690         while(seq) {
691                 if(seq!=test) {
692                         if (test->machine==seq->machine) {
693                                 if(test->depth==seq->depth) {
694                                         if (((lr==1)&&(test->startdisp > (seq->startdisp)))||((lr==2)&&(test->startdisp < (seq->startdisp)))) {
695                                                 seq->flag |= SELECT;
696                                                 recurs_sel_seq(seq);
697                                         }
698                                 }
699                         }
700                 }
701                 seq= seq->next;
702         }
703         test->flag |= SELECT;
704         recurs_sel_seq(test);
705 }
706
707 void select_dir_from_last(int lr)
708 {
709         Sequence *seq=get_last_seq();
710         if (seq==NULL)
711                 return;
712         
713         select_channel_direction(seq,lr);
714         allqueue(REDRAWSEQ, 0);
715         
716         if (lr==1)      BIF_undo_push("Select Strips to the Left, Sequencer");
717         else            BIF_undo_push("Select Strips to the Right, Sequencer");
718 }
719
720 void select_surrounding_handles(Sequence *test) 
721 {
722         Sequence *neighbor;
723         
724         neighbor=find_neighboring_sequence(test, 1, -1);
725         if (neighbor) {
726                 neighbor->flag |= SELECT;
727                 recurs_sel_seq(neighbor);
728                 neighbor->flag |= SEQ_RIGHTSEL;
729         }
730         neighbor=find_neighboring_sequence(test, 2, -1);
731         if (neighbor) {
732                 neighbor->flag |= SELECT;
733                 recurs_sel_seq(neighbor);
734                 neighbor->flag |= SEQ_LEFTSEL;
735         }
736         test->flag |= SELECT;
737 }
738
739 void select_surround_from_last()
740 {
741         Sequence *seq=get_last_seq();
742         
743         if (seq==NULL)
744                 return;
745         
746         select_surrounding_handles(seq);
747         allqueue(REDRAWSEQ, 0);
748         BIF_undo_push("Select Surrounding Handles, Sequencer");
749 }
750
751 void select_neighbor_from_last(int lr)
752 {
753         Sequence *seq=get_last_seq();
754         Sequence *neighbor;
755         int change = 0;
756         if (seq) {
757                 neighbor=find_neighboring_sequence(seq, lr, -1);
758                 if (neighbor) {
759                         switch (lr) {
760                         case 1:
761                                 neighbor->flag |= SELECT;
762                                 recurs_sel_seq(neighbor);
763                                 neighbor->flag |= SEQ_RIGHTSEL;
764                                 seq->flag |= SEQ_LEFTSEL;
765                                 break;
766                         case 2:
767                                 neighbor->flag |= SELECT;
768                                 recurs_sel_seq(neighbor);
769                                 neighbor->flag |= SEQ_LEFTSEL;
770                                 seq->flag |= SEQ_RIGHTSEL;
771                                 break;
772                         }
773                 seq->flag |= SELECT;
774                 change = 1;
775                 }
776         }
777         if (change) {
778                 allqueue(REDRAWSEQ, 0);
779                 
780                 if (lr==1)      BIF_undo_push("Select Left Handles, Sequencer");
781                 else            BIF_undo_push("Select Right Handles, Sequencer");
782         }
783 }
784
785 void mouse_select_seq(void)
786 {
787         Sequence *seq,*neighbor;
788         int hand,seldir;
789         TimeMarker *marker;
790         
791         marker=find_nearest_marker(SCE_MARKERS, 1);
792         
793         if (marker) {
794                 int oldflag;
795                 /* select timeline marker */
796                 if (G.qual & LR_SHIFTKEY) {
797                         oldflag= marker->flag;
798                         deselect_markers(0, 0);
799                         
800                         if (oldflag & SELECT)
801                                 marker->flag &= ~SELECT;
802                         else
803                                 marker->flag |= SELECT;
804                 }
805                 else {
806                         marker->flag |= SELECT;                         
807                 }
808                 allqueue(REDRAWMARKER, 0);
809                 force_draw(0);
810
811                 BIF_undo_push("Select Strips, Sequencer");
812                 
813         } else {
814         
815                 seq= find_nearest_seq(&hand);
816                 if(!(G.qual & LR_SHIFTKEY)&&!(G.qual & LR_ALTKEY)&&!(G.qual & LR_CTRLKEY)) deselect_all_seq();
817         
818                 if(seq) {
819                         set_last_seq(seq);
820         
821                         if ((seq->type == SEQ_IMAGE) || (seq->type == SEQ_MOVIE)) {
822                                 if(seq->strip) {
823                                         strncpy(last_imagename, seq->strip->dir, FILE_MAXDIR-1);
824                                 }
825                         } else
826                         if (seq->type == SEQ_HD_SOUND || seq->type == SEQ_RAM_SOUND) {
827                                 if(seq->strip) {
828                                         strncpy(last_sounddir, seq->strip->dir, FILE_MAXDIR-1);
829                                 }
830                         }
831         
832                         if((G.qual & LR_SHIFTKEY) && (seq->flag & SELECT)) {
833                                 if(hand==0) seq->flag &= SEQ_DESEL;
834                                 else if(hand==1) {
835                                         if(seq->flag & SEQ_LEFTSEL) 
836                                                 seq->flag &= ~SEQ_LEFTSEL;
837                                         else seq->flag |= SEQ_LEFTSEL;
838                                 }
839                                 else if(hand==2) {
840                                         if(seq->flag & SEQ_RIGHTSEL) 
841                                                 seq->flag &= ~SEQ_RIGHTSEL;
842                                         else seq->flag |= SEQ_RIGHTSEL;
843                                 }
844                         }
845                         else {
846                                 seq->flag |= SELECT;
847                                 if(hand==1) seq->flag |= SEQ_LEFTSEL;
848                                 if(hand==2) seq->flag |= SEQ_RIGHTSEL;
849                         }
850                         
851                         /* On Ctrl-Alt selection, select the strip and bordering handles */
852                         if ((G.qual & LR_CTRLKEY) && (G.qual & LR_ALTKEY)) {
853                                 if (!(G.qual & LR_SHIFTKEY)) deselect_all_seq();
854                                 seq->flag |= SELECT;
855                                 select_surrounding_handles(seq);
856                                 
857                         /* Ctrl signals Left, Alt signals Right
858                         First click selects adjacent handles on that side.
859                         Second click selects all strips in that direction.
860                         If there are no adjacent strips, it just selects all in that direction. */
861                         } else if (((G.qual & LR_CTRLKEY) || (G.qual & LR_ALTKEY)) && (seq->flag & SELECT)) {
862                 
863                                 if (G.qual & LR_CTRLKEY) seldir=1;
864                                         else seldir=2;
865                                 neighbor=find_neighboring_sequence(seq, seldir, -1);
866                                 if (neighbor) {
867                                         switch (seldir) {
868                                         case 1:
869                                                 if ((seq->flag & SEQ_LEFTSEL)&&(neighbor->flag & SEQ_RIGHTSEL)) {
870                                                         if (!(G.qual & LR_SHIFTKEY)) deselect_all_seq();
871                                                         select_channel_direction(seq,1);
872                                                 } else {
873                                                         neighbor->flag |= SELECT;
874                                                         recurs_sel_seq(neighbor);
875                                                         neighbor->flag |= SEQ_RIGHTSEL;
876                                                         seq->flag |= SEQ_LEFTSEL;
877                                                 }
878                                                 break;
879                                         case 2:
880                                                 if ((seq->flag & SEQ_RIGHTSEL)&&(neighbor->flag & SEQ_LEFTSEL)) {
881                                                         if (!(G.qual & LR_SHIFTKEY)) deselect_all_seq();
882                                                         select_channel_direction(seq,2);
883                                                 } else {
884                                                         neighbor->flag |= SELECT;
885                                                         recurs_sel_seq(neighbor);
886                                                         neighbor->flag |= SEQ_LEFTSEL;
887                                                         seq->flag |= SEQ_RIGHTSEL;
888                                                 }
889                                                 break;
890                                         }
891                                 } else {
892                                         if (!(G.qual & LR_SHIFTKEY)) deselect_all_seq();
893                                         select_channel_direction(seq,seldir);
894                                 }
895                         }
896
897                         recurs_sel_seq(seq);
898                 }
899                 allqueue(REDRAWBUTSSCENE, 0);
900                 force_draw(0);
901
902                 if(get_last_seq()) allqueue(REDRAWIPO, 0);
903                 BIF_undo_push("Select Strips, Sequencer");
904
905                 std_rmouse_transform(transform_seq_nomarker);
906         }
907         
908         /* marker transform */
909         if (marker) {
910                 short mval[2], xo, yo;
911                 getmouseco_areawin(mval);
912                 xo= mval[0]; 
913                 yo= mval[1];
914                 
915                 while(get_mbut()&R_MOUSE) {             
916                         getmouseco_areawin(mval);
917                         if(abs(mval[0]-xo)+abs(mval[1]-yo) > 4) {
918                                 transform_markers('g', 0);
919                                 allqueue(REDRAWMARKER, 0);
920                                 return;
921                         }
922                         BIF_wait_for_statechange();
923                 }
924         }
925 }
926
927
928 Sequence *alloc_sequence(ListBase *lb, int cfra, int machine)
929 {
930         Sequence *seq;
931
932         /*ed= G.scene->ed;*/
933
934         seq= MEM_callocN( sizeof(Sequence), "addseq");
935         BLI_addtail(lb, seq);
936
937         set_last_seq(seq);
938
939         *( (short *)seq->name )= ID_SEQ;
940         seq->name[2]= 0;
941
942         seq->flag= SELECT;
943         seq->start= cfra;
944         seq->machine= machine;
945         seq->mul= 1.0;
946         seq->blend_opacity = 100.0;
947         
948         return seq;
949 }
950
951 static Sequence *sfile_to_sequence(SpaceFile *sfile, int cfra, int machine, int last)
952 {
953         Sequence *seq;
954         Strip *strip;
955         StripElem *se;
956         int totsel, a;
957         char name[160];
958
959         /* are there selected files? */
960         totsel= 0;
961         for(a=0; a<sfile->totfile; a++) {
962                 if(sfile->filelist[a].flags & ACTIVE) {
963                         if( (sfile->filelist[a].type & S_IFDIR)==0 ) {
964                                 totsel++;
965                         }
966                 }
967         }
968
969         if(last) {
970                 /* if not, a file handed to us? */
971                 if(totsel==0 && sfile->file[0]) totsel= 1;
972         }
973
974         if(totsel==0) return 0;
975
976         /* make seq */
977         seq= alloc_sequence(((Editing *)G.scene->ed)->seqbasep, cfra, machine);
978         seq->len= totsel;
979
980         if(totsel==1) {
981                 seq->startstill= 25;
982                 seq->endstill= 24;
983         }
984
985         calc_sequence(seq);
986         
987         if(sfile->flag & FILE_STRINGCODE) {
988                 strcpy(name, sfile->dir);
989                 BLI_makestringcode(G.sce, name);
990         } else {
991                 strcpy(name, sfile->dir);
992         }
993
994         /* strip and stripdata */
995         seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
996         strip->len= totsel;
997         strip->us= 1;
998         strncpy(strip->dir, name, FILE_MAXDIR-1);
999         strip->stripdata= se= MEM_callocN(totsel*sizeof(StripElem), "stripelem");
1000
1001         for(a=0; a<sfile->totfile; a++) {
1002                 if(sfile->filelist[a].flags & ACTIVE) {
1003                         if( (sfile->filelist[a].type & S_IFDIR)==0 ) {
1004                                 strncpy(se->name, sfile->filelist[a].relname, FILE_MAXFILE-1);
1005                                 se++;
1006                         }
1007                 }
1008         }
1009         /* no selected file: */
1010         if(totsel==1 && se==strip->stripdata) {
1011                 strncpy(se->name, sfile->file, FILE_MAXFILE-1);
1012         }
1013
1014         /* last active name */
1015         strncpy(last_imagename, seq->strip->dir, FILE_MAXDIR-1);
1016
1017         return seq;
1018 }
1019
1020
1021 static int sfile_to_mv_sequence_load(SpaceFile *sfile, int cfra, 
1022                                      int machine, int index )
1023 {
1024         Sequence *seq;
1025         struct anim *anim;
1026         Strip *strip;
1027         StripElem *se;
1028         int totframe;
1029         char name[160];
1030         char str[FILE_MAXDIR+FILE_MAXFILE];
1031
1032         totframe= 0;
1033
1034         strncpy(str, sfile->dir, FILE_MAXDIR-1);
1035         if(index<0)
1036                 strncat(str, sfile->file, FILE_MAXDIR-1);
1037         else
1038                 strncat(str, sfile->filelist[index].relname, FILE_MAXDIR-1);
1039
1040         /* is it a movie? */
1041         anim = openanim(str, IB_rect);
1042         if(anim==0) {
1043                 error("The selected file is not a movie or "
1044                       "FFMPEG-support not compiled in!");
1045                 return(cfra);
1046         }
1047         
1048         totframe= IMB_anim_get_duration(anim);
1049
1050         /* make seq */
1051         seq= alloc_sequence(((Editing *)G.scene->ed)->seqbasep, cfra, machine);
1052         seq->len= totframe;
1053         seq->type= SEQ_MOVIE;
1054         seq->anim= anim;
1055         seq->anim_preseek = IMB_anim_get_preseek(anim);
1056
1057         calc_sequence(seq);
1058         
1059         if(sfile->flag & FILE_STRINGCODE) {
1060                 strcpy(name, sfile->dir);
1061                 BLI_makestringcode(G.sce, name);
1062         } else {
1063                 strcpy(name, sfile->dir);
1064         }
1065
1066         /* strip and stripdata */
1067         seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
1068         strip->len= totframe;
1069         strip->us= 1;
1070         strncpy(strip->dir, name, FILE_MAXDIR-1);
1071         strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem");
1072
1073         /* name movie in first strip */
1074         if(index<0)
1075                 strncpy(se->name, sfile->file, FILE_MAXFILE-1);
1076         else
1077                 strncpy(se->name, sfile->filelist[index].relname, FILE_MAXFILE-1);
1078
1079         /* last active name */
1080         strncpy(last_imagename, seq->strip->dir, FILE_MAXDIR-1);
1081         return(cfra+totframe);
1082 }
1083
1084 static void sfile_to_mv_sequence(SpaceFile *sfile, int cfra, int machine)
1085 {
1086         int a, totsel;
1087
1088         totsel= 0;
1089         for(a= 0; a<sfile->totfile; a++) {
1090                 if(sfile->filelist[a].flags & ACTIVE) {
1091                         if ((sfile->filelist[a].type & S_IFDIR)==0) {
1092                                 totsel++;
1093                         }
1094                 }
1095         }
1096
1097         if((totsel==0) && (sfile->file[0])) {
1098                 cfra= sfile_to_mv_sequence_load(sfile, cfra, machine, -1);
1099                 return;
1100         }
1101
1102         if(totsel==0) return;
1103
1104         /* ok. check all the select file, and load it. */
1105         for(a= 0; a<sfile->totfile; a++) {
1106                 if(sfile->filelist[a].flags & ACTIVE) {
1107                         if ((sfile->filelist[a].type & S_IFDIR)==0) {
1108                                 /* load and update current frame. */
1109                                 cfra= sfile_to_mv_sequence_load(sfile, cfra, machine, a);
1110                         }
1111                 }
1112         }
1113 }
1114
1115 static Sequence *sfile_to_ramsnd_sequence(SpaceFile *sfile, 
1116                                           int cfra, int machine)
1117 {
1118         Sequence *seq;
1119         bSound *sound;
1120         Strip *strip;
1121         StripElem *se;
1122         double totframe;
1123         char name[160];
1124         char str[256];
1125
1126         totframe= 0.0;
1127
1128         strncpy(str, sfile->dir, FILE_MAXDIR-1);
1129         strncat(str, sfile->file, FILE_MAXFILE-1);
1130
1131         sound= sound_new_sound(str);
1132         if (!sound || sound->sample->type == SAMPLE_INVALID) {
1133                 error("Unsupported audio format");
1134                 return 0;
1135         }
1136         if (sound->sample->bits != 16) {
1137                 error("Only 16 bit audio is supported");
1138                 return 0;
1139         }
1140         sound->id.us=1;
1141         sound->flags |= SOUND_FLAGS_SEQUENCE;
1142         audio_makestream(sound);
1143
1144         totframe= (int) ( ((float)(sound->streamlen-1)/
1145                            ( (float)G.scene->audio.mixrate*4.0 ))* FPS);
1146
1147         /* make seq */
1148         seq= alloc_sequence(((Editing *)G.scene->ed)->seqbasep, cfra, machine);
1149         seq->len= totframe;
1150         seq->type= SEQ_RAM_SOUND;
1151         seq->sound = sound;
1152
1153         calc_sequence(seq);
1154         
1155         if(sfile->flag & FILE_STRINGCODE) {
1156                 strcpy(name, sfile->dir);
1157                 BLI_makestringcode(G.sce, name);
1158         } else {
1159                 strcpy(name, sfile->dir);
1160         }
1161
1162         /* strip and stripdata */
1163         seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
1164         strip->len= totframe;
1165         strip->us= 1;
1166         strncpy(strip->dir, name, FILE_MAXDIR-1);
1167         strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem");
1168
1169         /* name sound in first strip */
1170         strncpy(se->name, sfile->file, FILE_MAXFILE-1);
1171
1172         /* last active name */
1173         strncpy(last_sounddir, seq->strip->dir, FILE_MAXDIR-1);
1174
1175         return seq;
1176 }
1177
1178 static int sfile_to_hdsnd_sequence_load(SpaceFile *sfile, int cfra, 
1179                                         int machine, int index)
1180 {
1181         Sequence *seq;
1182         struct hdaudio *hdaudio;
1183         Strip *strip;
1184         StripElem *se;
1185         int totframe;
1186         char name[160];
1187         char str[FILE_MAXDIR+FILE_MAXFILE];
1188
1189         totframe= 0;
1190
1191         strncpy(str, sfile->dir, FILE_MAXDIR-1);
1192         if(index<0)
1193                 strncat(str, sfile->file, FILE_MAXDIR-1);
1194         else
1195                 strncat(str, sfile->filelist[index].relname, FILE_MAXDIR-1);
1196
1197         /* is it a sound file? */
1198         hdaudio = sound_open_hdaudio(str);
1199         if(hdaudio==0) {
1200                 error("The selected file is not a sound file or "
1201                       "FFMPEG-support not compiled in!");
1202                 return(cfra);
1203         }
1204
1205         totframe= sound_hdaudio_get_duration(hdaudio, FPS);
1206
1207         /* make seq */
1208         seq= alloc_sequence(((Editing *)G.scene->ed)->seqbasep, cfra, machine);
1209         seq->len= totframe;
1210         seq->type= SEQ_HD_SOUND;
1211         seq->hdaudio= hdaudio;
1212
1213         calc_sequence(seq);
1214         
1215         if(sfile->flag & FILE_STRINGCODE) {
1216                 strcpy(name, sfile->dir);
1217                 BLI_makestringcode(G.sce, name);
1218         } else {
1219                 strcpy(name, sfile->dir);
1220         }
1221
1222         /* strip and stripdata */
1223         seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
1224         strip->len= totframe;
1225         strip->us= 1;
1226         strncpy(strip->dir, name, FILE_MAXDIR-1);
1227         strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem");
1228
1229         /* name movie in first strip */
1230         if(index<0)
1231                 strncpy(se->name, sfile->file, FILE_MAXFILE-1);
1232         else
1233                 strncpy(se->name, sfile->filelist[index].relname, FILE_MAXFILE-1);
1234
1235         /* last active name */
1236         strncpy(last_sounddir, seq->strip->dir, FILE_MAXDIR-1);
1237         return(cfra+totframe);
1238 }
1239
1240 static void sfile_to_hdsnd_sequence(SpaceFile *sfile, int cfra, int machine)
1241 {
1242         int totsel, a;
1243
1244         totsel= 0;
1245         for(a= 0; a<sfile->totfile; a++) {
1246                 if(sfile->filelist[a].flags & ACTIVE) {
1247                         if((sfile->filelist[a].type & S_IFDIR)==0) {
1248                                 totsel++;
1249                         }
1250                 }
1251         }
1252
1253         if((totsel==0) && (sfile->file[0])) {
1254                 cfra= sfile_to_hdsnd_sequence_load(sfile, cfra, machine, -1);
1255                 return;
1256         }
1257
1258         if(totsel==0) return;
1259
1260         /* ok, check all the select file, and load it. */
1261         for(a= 0; a<sfile->totfile; a++) {
1262                 if(sfile->filelist[a].flags & ACTIVE) {
1263                         if((sfile->filelist[a].type & S_IFDIR)==0) {
1264                                 /* load and update current frame. */
1265                                 cfra= sfile_to_hdsnd_sequence_load(sfile, cfra, machine, a);
1266                         }
1267                 }
1268         }
1269 }
1270
1271
1272 static void add_image_strips(char *name)
1273 {
1274         SpaceFile *sfile;
1275         struct direntry *files;
1276         float x, y;
1277         int a, totfile, cfra, machine;
1278         short mval[2];
1279
1280         deselect_all_seq();
1281
1282         /* restore windowmatrices */
1283         areawinset(curarea->win);
1284         drawseqspace(curarea, curarea->spacedata.first);
1285
1286         /* search sfile */
1287         sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
1288         if(sfile==0) return;
1289
1290         /* where will it be */
1291         getmouseco_areawin(mval);
1292         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1293         cfra= (int)(x+0.5);
1294         machine= (int)(y+0.5);
1295
1296         waitcursor(1);
1297
1298         /* also read contents of directories */
1299         files= sfile->filelist;
1300         totfile= sfile->totfile;
1301         sfile->filelist= 0;
1302         sfile->totfile= 0;
1303
1304         for(a=0; a<totfile; a++) {
1305                 if(files[a].flags & ACTIVE) {
1306                         if( (files[a].type & S_IFDIR) ) {
1307                                 strncat(sfile->dir, files[a].relname, FILE_MAXFILE-1);
1308                                 strcat(sfile->dir,"/");
1309                                 read_dir(sfile);
1310
1311                                 /* select all */
1312                                 swapselect_file(sfile);
1313
1314                                 if ( sfile_to_sequence(sfile, cfra, machine, 0) ) machine++;
1315
1316                                 parent(sfile);
1317                         }
1318                 }
1319         }
1320
1321         sfile->filelist= files;
1322         sfile->totfile= totfile;
1323
1324         /* read directory itself */
1325         sfile_to_sequence(sfile, cfra, machine, 1);
1326
1327         waitcursor(0);
1328
1329         BIF_undo_push("Add Image Strip, Sequencer");
1330         transform_seq_nomarker('g', 0);
1331
1332 }
1333
1334 static void add_movie_strip(char *name)
1335 {
1336         SpaceFile *sfile;
1337         float x, y;
1338         int cfra, machine;
1339         short mval[2];
1340
1341         deselect_all_seq();
1342
1343         /* restore windowmatrices */
1344         areawinset(curarea->win);
1345         drawseqspace(curarea, curarea->spacedata.first);
1346
1347         /* search sfile */
1348         sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
1349         if(sfile==0) return;
1350
1351         /* where will it be */
1352         getmouseco_areawin(mval);
1353         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1354         cfra= (int)(x+0.5);
1355         machine= (int)(y+0.5);
1356
1357         waitcursor(1);
1358
1359         /* read directory itself */
1360         sfile_to_mv_sequence(sfile, cfra, machine);
1361
1362         waitcursor(0);
1363
1364         BIF_undo_push("Add Movie Strip, Sequencer");
1365         transform_seq_nomarker('g', 0);
1366
1367 }
1368
1369 static void add_movie_and_hdaudio_strip(char *name)
1370 {
1371         SpaceFile *sfile;
1372         float x, y;
1373         int cfra, machine;
1374         short mval[2];
1375
1376         deselect_all_seq();
1377
1378         /* restore windowmatrices */
1379         areawinset(curarea->win);
1380         drawseqspace(curarea, curarea->spacedata.first);
1381
1382         /* search sfile */
1383         sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
1384         if(sfile==0) return;
1385
1386         /* where will it be */
1387         getmouseco_areawin(mval);
1388         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1389         cfra= (int)(x+0.5);
1390         machine= (int)(y+0.5);
1391
1392         waitcursor(1);
1393
1394         /* read directory itself */
1395         sfile_to_hdsnd_sequence(sfile, cfra, machine);
1396         sfile_to_mv_sequence(sfile, cfra, machine);
1397
1398         waitcursor(0);
1399
1400         BIF_undo_push("Add Movie and HD-Audio Strip, Sequencer");
1401         transform_seq_nomarker('g', 0);
1402
1403 }
1404
1405 static void add_sound_strip_ram(char *name)
1406 {
1407         SpaceFile *sfile;
1408         float x, y;
1409         int cfra, machine;
1410         short mval[2];
1411
1412         deselect_all_seq();
1413
1414         sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
1415         if (sfile==0) return;
1416
1417         /* where will it be */
1418         getmouseco_areawin(mval);
1419         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1420         cfra= (int)(x+0.5);
1421         machine= (int)(y+0.5);
1422
1423         waitcursor(1);
1424
1425         sfile_to_ramsnd_sequence(sfile, cfra, machine);
1426
1427         waitcursor(0);
1428
1429         BIF_undo_push("Add Sound (RAM) Strip, Sequencer");
1430         transform_seq_nomarker('g', 0);
1431 }
1432
1433 static void add_sound_strip_hd(char *name)
1434 {
1435         SpaceFile *sfile;
1436         float x, y;
1437         int cfra, machine;
1438         short mval[2];
1439
1440         deselect_all_seq();
1441
1442         sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
1443         if (sfile==0) return;
1444
1445         /* where will it be */
1446         getmouseco_areawin(mval);
1447         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1448         cfra= (int)(x+0.5);
1449         machine= (int)(y+0.5);
1450
1451         waitcursor(1);
1452
1453         sfile_to_hdsnd_sequence(sfile, cfra, machine);
1454
1455         waitcursor(0);
1456
1457         BIF_undo_push("Add Sound (HD) Strip, Sequencer");
1458         transform_seq_nomarker('g', 0);
1459 }
1460
1461 static void add_scene_strip(short event)
1462 {
1463         Sequence *seq;
1464         Strip *strip;
1465         float x, y;
1466         int cfra, machine;
1467         short mval[2];
1468
1469         if(event> -1) {
1470                 int nr= 1;
1471                 Scene * sce= G.main->scene.first;
1472                 while(sce) {
1473                         if( event==nr) break;
1474                         nr++;
1475                         sce= sce->id.next;
1476                 }
1477                 if(sce) {
1478
1479                         deselect_all_seq();
1480
1481                         /* where ? */
1482                         getmouseco_areawin(mval);
1483                         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1484                         cfra= (int)(x+0.5);
1485                         machine= (int)(y+0.5);
1486                         
1487                         seq= alloc_sequence(((Editing *)G.scene->ed)->seqbasep, cfra, machine);
1488                         seq->type= SEQ_SCENE;
1489                         seq->scene= sce;
1490                         seq->sfra= sce->r.sfra;
1491                         seq->len= sce->r.efra - sce->r.sfra + 1;
1492                         
1493                         seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
1494                         strncpy(seq->name + 2, sce->id.name + 2, 
1495                                 sizeof(seq->name) - 2);
1496                         strip->len= seq->len;
1497                         strip->us= 1;
1498                         
1499                         BIF_undo_push("Add Scene Strip, Sequencer");
1500                         transform_seq_nomarker('g', 0);
1501                 }
1502         }
1503 }
1504
1505 #if 0
1506 static void reload_sound_strip(char *name)
1507 {
1508         Editing *ed;
1509         Sequence *seq, *seqact;
1510         SpaceFile *sfile;
1511         Sequence *last_seq= get_last_seq();
1512
1513         ed= G.scene->ed;
1514
1515         if(last_seq==0 || last_seq->type!=SEQ_SOUND) return;
1516         seqact= last_seq;       /* last_seq changes in alloc_sequence */
1517
1518         /* search sfile */
1519         sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
1520         if(sfile==0) return;
1521
1522         waitcursor(1);
1523
1524         seq = sfile_to_snd_sequence(sfile, seqact->start, seqact->machine);
1525         printf("seq->type: %i\n", seq->type);
1526         if(seq && seq!=seqact) {
1527                 /* i'm not sure about this one, seems to work without it -- sgefant */
1528                 free_strip(seqact->strip);
1529
1530                 seqact->strip= seq->strip;
1531
1532                 seqact->len= seq->len;
1533                 calc_sequence(seqact);
1534
1535                 seq->strip= 0;
1536                 free_sequence(seq);
1537                 BLI_remlink(ed->seqbasep, seq);
1538
1539                 seq= ed->seqbasep->first;
1540
1541         }
1542
1543         waitcursor(0);
1544
1545         allqueue(REDRAWSEQ, 0);
1546 }
1547 #endif
1548
1549 static void reload_image_strip(char *name)
1550 {
1551         Editing *ed;
1552         Sequence *seq, *seqact;
1553         SpaceFile *sfile;
1554         Sequence *last_seq= get_last_seq();
1555
1556         ed= G.scene->ed;
1557
1558         if(last_seq==0 || last_seq->type!=SEQ_IMAGE) return;
1559         seqact= last_seq;       /* last_seq changes in alloc_sequence */
1560
1561         /* search sfile */
1562         sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
1563         if(sfile==0) return;
1564
1565         waitcursor(1);
1566
1567         seq= sfile_to_sequence(sfile, seqact->start, seqact->machine, 1);
1568         if(seq && seq!=seqact) {
1569                 free_strip(seqact->strip);
1570
1571                 seqact->strip= seq->strip;
1572
1573                 seqact->len= seq->len;
1574                 calc_sequence(seqact);
1575
1576                 seq->strip= 0;
1577                 free_sequence(seq);
1578                 BLI_remlink(ed->seqbasep, seq);
1579
1580                 update_changed_seq_and_deps(seqact, 1, 1);
1581         }
1582         waitcursor(0);
1583
1584         allqueue(REDRAWSEQ, 0);
1585 }
1586
1587 static int event_to_efftype(int event)
1588 {
1589         if(event==2) return SEQ_CROSS;
1590         if(event==3) return SEQ_GAMCROSS;
1591         if(event==4) return SEQ_ADD;
1592         if(event==5) return SEQ_SUB;
1593         if(event==6) return SEQ_MUL;
1594         if(event==7) return SEQ_ALPHAOVER;
1595         if(event==8) return SEQ_ALPHAUNDER;
1596         if(event==9) return SEQ_OVERDROP;
1597         if(event==10) return SEQ_PLUGIN;
1598         if(event==13) return SEQ_WIPE;
1599         if(event==14) return SEQ_GLOW;
1600         if(event==15) return SEQ_TRANSFORM;
1601         if(event==16) return SEQ_COLOR;
1602         if(event==17) return SEQ_SPEED;
1603         return 0;
1604 }
1605
1606 static int seq_effect_find_selected(Editing *ed, Sequence *activeseq, int type, Sequence **selseq1, Sequence **selseq2, Sequence **selseq3)
1607 {
1608         Sequence *seq1= 0, *seq2= 0, *seq3= 0, *seq;
1609         
1610         if (!activeseq)
1611                 seq2= get_last_seq();
1612
1613         for(seq=ed->seqbasep->first; seq; seq=seq->next) {
1614                 if(seq->flag & SELECT) {
1615                         if (seq->type == SEQ_RAM_SOUND
1616                             || seq->type == SEQ_HD_SOUND) { 
1617                                 error("Can't apply effects to "
1618                                       "audio sequence strips");
1619                                 return 0;
1620                         }
1621                         if((seq != activeseq) && (seq != seq2)) {
1622                                 if(seq2==0) seq2= seq;
1623                                 else if(seq1==0) seq1= seq;
1624                                 else if(seq3==0) seq3= seq;
1625                                 else {
1626                                        error("Can't apply effect to more than 3 sequence strips");
1627                                        return 0;
1628                                 }
1629                         }
1630                 }
1631         }
1632        
1633         /* make sequence selection a little bit more intuitive
1634            for 3 strips: the last-strip should be sequence3 */
1635         if (seq3 != 0 && seq2 != 0) {
1636                 Sequence *tmp = seq2;
1637                 seq2 = seq3;
1638                 seq3 = tmp;
1639         }
1640         
1641
1642         switch(get_sequence_effect_num_inputs(type)) {
1643         case 0:
1644                 seq1 = seq2 = seq3 = 0;
1645                 break;
1646         case 1:
1647                 if(seq2==0)  {
1648                         error("Need at least one selected sequence strip");
1649                         return 0;
1650                 }
1651                 if(seq1==0) seq1= seq2;
1652                 if(seq3==0) seq3= seq2;
1653         case 2:
1654                 if(seq1==0 || seq2==0) {
1655                         error("Need 2 selected sequence strips");
1656                         return 0;
1657                 }
1658                 if(seq3==0) seq3= seq2;
1659         }
1660         
1661         if (seq1==NULL && seq2==NULL && seq3==NULL) return 0;
1662         
1663         *selseq1= seq1;
1664         *selseq2= seq2;
1665         *selseq3= seq3;
1666
1667         return 1;
1668 }
1669
1670 static int add_seq_effect(int type, char *str)
1671 {
1672         Editing *ed;
1673         Sequence *newseq, *seq1, *seq2, *seq3;
1674         Strip *strip;
1675         float x, y;
1676         int cfra, machine;
1677         short mval[2];
1678         struct SeqEffectHandle sh;
1679
1680         if(G.scene->ed==0) return 0;
1681         ed= G.scene->ed;
1682
1683         if(!seq_effect_find_selected(ed, NULL, event_to_efftype(type), &seq1, &seq2, &seq3))
1684                 return 0;
1685
1686         deselect_all_seq();
1687
1688         /* where will it be (cfra is not realy needed) */
1689         getmouseco_areawin(mval);
1690         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1691         cfra= (int)(x+0.5);
1692         machine= (int)(y+0.5);
1693
1694         /* allocate and initialize */
1695         newseq= alloc_sequence(((Editing *)G.scene->ed)->seqbasep, cfra, machine);
1696         newseq->type= event_to_efftype(type);
1697
1698         sh = get_sequence_effect(newseq);
1699
1700         newseq->seq1= seq1;
1701         newseq->seq2= seq2;
1702         newseq->seq3= seq3;
1703
1704         sh.init(newseq);
1705
1706         if (!seq1) {
1707                 newseq->len= 1;
1708                 newseq->startstill= 25;
1709                 newseq->endstill= 24;
1710         }
1711
1712         calc_sequence(newseq);
1713
1714         newseq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
1715         strip->len= newseq->len;
1716         strip->us= 1;
1717         if(newseq->len>0)
1718                 strip->stripdata= MEM_callocN(newseq->len*sizeof(StripElem), "stripelem");
1719
1720         /* initialize plugin */
1721         if(newseq->type == SEQ_PLUGIN) {
1722                 sh.init_plugin(newseq, str);
1723
1724                 if(newseq->plugin==0) {
1725                         BLI_remlink(ed->seqbasep, newseq);
1726                         free_sequence(newseq);
1727                         set_last_seq(NULL);
1728                         return 0;
1729                 }
1730         }
1731
1732         /* set find a free spot to but the strip */
1733         if (newseq->seq1) {
1734                 newseq->machine= MAX3(newseq->seq1->machine, 
1735                                       newseq->seq2->machine,
1736                                       newseq->seq3->machine);
1737         }
1738         if(test_overlap_seq(newseq)) shuffle_seq(newseq);
1739
1740         update_changed_seq_and_deps(newseq, 1, 1);
1741
1742         /* push undo and go into grab mode */
1743         if(newseq->type == SEQ_PLUGIN) {
1744                 BIF_undo_push("Add Plugin Strip, Sequencer");
1745         } else {
1746                 BIF_undo_push("Add Effect Strip, Sequencer");
1747         }
1748
1749         transform_seq_nomarker('g', 0);
1750
1751         return 1;
1752 }
1753
1754 static void load_plugin_seq(char *str)          /* called from fileselect */
1755 {
1756         add_seq_effect(10, str);
1757 }
1758
1759 void add_sequence(int type)
1760 {
1761         Editing *ed;
1762         short event;
1763         char *str;
1764
1765         if (type >= 0){
1766                 /* bypass pupmenu for calls from menus (aphex) */
1767                 switch(type){
1768                 case SEQ_SCENE:
1769                         event = 101;
1770                         break;
1771                 case SEQ_IMAGE:
1772                         event = 1;
1773                         break;
1774                 case SEQ_MOVIE:
1775                         event = 102;
1776                         break;
1777                 case SEQ_RAM_SOUND:
1778                         event = 103;
1779                         break;
1780                 case SEQ_HD_SOUND:
1781                         event = 104;
1782                         break;
1783                 case SEQ_MOVIE_AND_HD_SOUND:
1784                         event = 105;
1785                         break;
1786                 case SEQ_PLUGIN:
1787                         event = 10;
1788                         break;
1789                 case SEQ_CROSS:
1790                         event = 2;
1791                         break;
1792                 case SEQ_ADD:
1793                         event = 4;
1794                         break;
1795                 case SEQ_SUB:
1796                         event = 5;
1797                         break;
1798                 case SEQ_ALPHAOVER:
1799                         event = 7;
1800                         break;
1801                 case SEQ_ALPHAUNDER:
1802                         event = 8;
1803                         break;
1804                 case SEQ_GAMCROSS:
1805                         event = 3;
1806                         break;
1807                 case SEQ_MUL:
1808                         event = 6;
1809                         break;
1810                 case SEQ_OVERDROP:
1811                         event = 9;
1812                         break;
1813                 case SEQ_WIPE:
1814                         event = 13;
1815                         break;
1816                 case SEQ_GLOW:
1817                         event = 14;
1818                         break;
1819                 case SEQ_TRANSFORM:
1820                         event = 15;
1821                         break;
1822                 case SEQ_COLOR:
1823                         event = 16;
1824                         break;
1825                 case SEQ_SPEED:
1826                         event = 17;
1827                         break;
1828                 default:
1829                         event = 0;
1830                         break;
1831                 }
1832         }
1833         else {
1834                 event= pupmenu("Add Sequence Strip%t"
1835                                "|Image Sequence%x1"
1836                                "|Movie%x102"
1837 #ifdef WITH_FFMPEG
1838                                    "|Movie + Audio (HD)%x105"
1839                                "|Audio (RAM)%x103"
1840                                "|Audio (HD)%x104"
1841 #else
1842                                    "|Audio (Wav)%x103"
1843 #endif
1844                                "|Scene%x101"
1845                                "|Plugin%x10"
1846                                "|Cross%x2"
1847                                "|Gamma Cross%x3"
1848                                "|Add%x4"
1849                                "|Sub%x5"
1850                                "|Mul%x6"
1851                                "|Alpha Over%x7"
1852                                "|Alpha Under%x8"
1853                                "|Alpha Over Drop%x9"
1854                                "|Wipe%x13"
1855                                "|Glow%x14"
1856                                "|Transforms%x15"
1857                                "|Color Generator%x16"
1858                                "|Speed Control%x17");
1859         }
1860
1861         if(event<1) return;
1862
1863         if(G.scene->ed==0) {
1864                 ed= G.scene->ed= MEM_callocN( sizeof(Editing), "addseq");
1865                 ed->seqbasep= &ed->seqbase;
1866         }
1867         else ed= G.scene->ed;
1868
1869         switch(event) {
1870         case 1:
1871                 /* Image Dosnt work at the moment - TODO */
1872                 //if(G.qual & LR_CTRLKEY)
1873                 //      activate_imageselect(FILE_SPECIAL, "Select Images", last_imagename, add_image_strips);
1874                 //else
1875                         activate_fileselect(FILE_SPECIAL, "Select Images", last_imagename, add_image_strips);
1876                 break;
1877         case 105:
1878                 activate_fileselect(FILE_SPECIAL, "Select Movie+Audio", last_imagename, add_movie_and_hdaudio_strip);
1879                 break;
1880         case 102:
1881
1882                 activate_fileselect(FILE_SPECIAL, "Select Movie", last_imagename, add_movie_strip);
1883                 break;
1884         case 101:
1885                 /* new menu: */
1886                 IDnames_to_pupstring(&str, NULL, NULL, &G.main->scene, (ID *)G.scene, NULL);
1887
1888                 add_scene_strip(pupmenu_col(str, 20));
1889
1890                 MEM_freeN(str);
1891
1892                 break;
1893         case 2:
1894         case 3:
1895         case 4:
1896         case 5:
1897         case 6:
1898         case 7:
1899         case 8:
1900         case 9:
1901         case 10:
1902         case 13:
1903         case 14:
1904         case 15:
1905         case 16:
1906         case 17:
1907                 if(get_last_seq()==0 && 
1908                    get_sequence_effect_num_inputs( event_to_efftype(event))> 0)
1909                         error("Need at least one active sequence strip");
1910                 else if(event==10)
1911                         activate_fileselect(FILE_SPECIAL, "Select Plugin", U.plugseqdir, load_plugin_seq);
1912                 else
1913                         add_seq_effect(event, NULL);
1914
1915                 break;
1916         case 103:
1917                 if (!last_sounddir[0]) strncpy(last_sounddir, U.sounddir, FILE_MAXDIR-1);
1918                 activate_fileselect(FILE_SPECIAL, "Select Audio (RAM)", last_sounddir, add_sound_strip_ram);
1919                 break;
1920         case 104:
1921                 if (!last_sounddir[0]) strncpy(last_sounddir, U.sounddir, FILE_MAXDIR-1);
1922                 activate_fileselect(FILE_SPECIAL, "Select Audio (HD)", last_sounddir, add_sound_strip_hd);
1923                 break;
1924         }
1925 }
1926
1927 void change_sequence(void)
1928 {
1929         Sequence *last_seq= get_last_seq();
1930         Scene *sce;
1931         short event;
1932
1933         if(last_seq==0) return;
1934
1935         if(last_seq->type & SEQ_EFFECT) {
1936                 event = pupmenu("Change Effect%t"
1937                                 "|Switch A <-> B %x1"
1938                                 "|Switch B <-> C %x10"
1939                                 "|Plugin%x11"
1940                                 "|Recalculate%x12"
1941                                 "|Cross%x2"
1942                                 "|Gamma Cross%x3"
1943                                 "|Add%x4"
1944                                 "|Sub%x5"
1945                                 "|Mul%x6"
1946                                 "|Alpha Over%x7"
1947                                 "|Alpha Under%x8"
1948                                 "|Alpha Over Drop%x9"
1949                                 "|Wipe%x13"
1950                                 "|Glow%x14"
1951                                 "|Transform%x15"
1952                                 "|Color Generator%x16"
1953                                 "|Speed Control%x17");
1954                 if(event > 0) {
1955                         if(event==1) {
1956                                 SWAP(Sequence *,last_seq->seq1,last_seq->seq2);
1957                         }
1958                         else if(event==10) {
1959                                 SWAP(Sequence *,last_seq->seq2,last_seq->seq3);
1960                         }
1961                         else if(event==11) {
1962                                 activate_fileselect(
1963                                         FILE_SPECIAL, "Select Plugin", 
1964                                         U.plugseqdir, change_plugin_seq);
1965                         }
1966                         else if(event==12);     
1967                                 /* recalculate: only new_stripdata */
1968                         else {
1969                                 /* free previous effect and init new effect */
1970                                 struct SeqEffectHandle sh;
1971
1972                                 if (get_sequence_effect_num_inputs(
1973                                             last_seq->type)
1974                                     < get_sequence_effect_num_inputs(
1975                                             event_to_efftype(event))) {
1976                                         error("New effect needs more "
1977                                               "input strips!");
1978                                 } else {
1979                                         sh = get_sequence_effect(last_seq);
1980                                         sh.free(last_seq);
1981                                         
1982                                         last_seq->type 
1983                                                 = event_to_efftype(event);
1984                                         
1985                                         sh = get_sequence_effect(last_seq);
1986                                         sh.init(last_seq);
1987                                 }
1988                         }
1989
1990                         update_changed_seq_and_deps(last_seq, 0, 1);
1991                         allqueue(REDRAWSEQ, 0);
1992                         BIF_undo_push("Change Strip Effect, Sequencer");
1993                 }
1994         }
1995         else if(last_seq->type == SEQ_IMAGE) {
1996                 if(okee("Change images")) {
1997                         activate_fileselect(FILE_SPECIAL, 
1998                                             "Select Images", 
1999                                             last_imagename, 
2000                                             reload_image_strip);
2001                 }
2002         }
2003         else if(last_seq->type == SEQ_MOVIE) {
2004                 ;
2005         }
2006         else if(last_seq->type == SEQ_SCENE) {
2007                 event= pupmenu("Change Scene%t|Update Start and End");
2008
2009                 if(event==1) {
2010                         sce= last_seq->scene;
2011
2012                         last_seq->len= sce->r.efra - sce->r.sfra + 1;
2013                         last_seq->sfra= sce->r.sfra;
2014                         
2015                         /* bad code to change seq->len? update_changed_seq_and_deps() expects the strip->len to be OK */
2016                         new_tstripdata(last_seq);
2017                         
2018                         update_changed_seq_and_deps(last_seq, 1, 1);
2019
2020                         allqueue(REDRAWSEQ, 0);
2021                 }
2022         }
2023
2024 }
2025
2026 void reload_sequence(void)
2027 {
2028         Editing *ed= G.scene->ed;
2029         Sequence *seq;
2030         WHILE_SEQ(ed->seqbasep) {
2031                 if(seq->flag & SELECT) {
2032                         update_changed_seq_and_deps(seq, 0, 1);
2033                 }
2034         }
2035         END_SEQ
2036         allqueue(REDRAWSEQ, 0);
2037 }
2038
2039 void reassign_inputs_seq_effect()
2040 {
2041         Editing *ed= G.scene->ed;
2042         Sequence *seq1, *seq2, *seq3, *last_seq = get_last_seq();
2043
2044         if(last_seq==0 || !(last_seq->type & SEQ_EFFECT)) return;
2045         if(ed==0) return;
2046
2047         if(!seq_effect_find_selected(ed, last_seq, last_seq->type, &seq1, &seq2, &seq3))
2048                 return;
2049
2050         /* see reassigning would create a cycle */
2051         if(seq_is_predecessor(seq1, last_seq) || seq_is_predecessor(seq2, last_seq) ||
2052            seq_is_predecessor(seq3, last_seq)) {
2053                 error("Can't reassign inputs: no cycles allowed");
2054                 return;
2055         }
2056         
2057         last_seq->seq1 = seq1;
2058         last_seq->seq2 = seq2;
2059         last_seq->seq3 = seq3;
2060
2061         update_changed_seq_and_deps(last_seq, 1, 1);
2062
2063         allqueue(REDRAWSEQ, 0);
2064 }
2065
2066 static Sequence *del_seq_find_replace_recurs(Sequence *seq)
2067 {
2068         Sequence *seq1, *seq2, *seq3;
2069
2070         /* try to find a replacement input sequence, and flag for later deletion if
2071            no replacement can be found */
2072
2073         if(!seq)
2074                 return NULL;
2075         else if(!(seq->type & SEQ_EFFECT))
2076                 return ((seq->flag & SELECT)? NULL: seq);
2077         else if(!(seq->flag & SELECT)) {
2078                 /* try to find replacement for effect inputs */
2079                 seq1= del_seq_find_replace_recurs(seq->seq1);
2080                 seq2= del_seq_find_replace_recurs(seq->seq2);
2081                 seq3= del_seq_find_replace_recurs(seq->seq3);
2082
2083                 if(seq1==seq->seq1 && seq2==seq->seq2 && seq3==seq->seq3);
2084                 else if(seq1 || seq2 || seq3) {
2085                         seq->seq1= (seq1)? seq1: (seq2)? seq2: seq3;
2086                         seq->seq2= (seq2)? seq2: (seq1)? seq1: seq3;
2087                         seq->seq3= (seq3)? seq3: (seq1)? seq1: seq2;
2088
2089                         update_changed_seq_and_deps(seq, 1, 1);
2090                 }
2091                 else
2092                         seq->flag |= SELECT; /* mark for delete */
2093         }
2094
2095         if (seq->flag & SELECT) {
2096                 if((seq1 = del_seq_find_replace_recurs(seq->seq1))) return seq1;
2097                 if((seq2 = del_seq_find_replace_recurs(seq->seq2))) return seq2;
2098                 if((seq3 = del_seq_find_replace_recurs(seq->seq3))) return seq3;
2099                 else return NULL;
2100         }
2101         else
2102                 return seq;
2103 }
2104
2105 static void recurs_del_seq_flag(ListBase *lb, short flag, short deleteall)
2106 {
2107         Sequence *seq, *seqn;
2108         Sequence *last_seq = get_last_seq();
2109
2110         seq= lb->first;
2111         while(seq) {
2112                 seqn= seq->next;
2113                 if((seq->flag & flag) || deleteall) {
2114                         if(seq->type==SEQ_RAM_SOUND && seq->sound) 
2115                                 seq->sound->id.us--;
2116
2117                         BLI_remlink(lb, seq);
2118                         if(seq==last_seq) set_last_seq(0);
2119                         if(seq->type==SEQ_META) recurs_del_seq_flag(&seq->seqbase, flag, 1);
2120                         if(seq->ipo) seq->ipo->id.us--;
2121                         free_sequence(seq);
2122                 }
2123                 seq= seqn;
2124         }
2125 }
2126
2127 void del_seq(void)
2128 {
2129         Sequence *seq;
2130         MetaStack *ms;
2131         Editing *ed;
2132
2133         if(okee("Erase selected")==0) return;
2134
2135         ed= G.scene->ed;
2136         if(ed==0) return;
2137
2138         /* free imbufs of all dependent strips */
2139         for(seq=ed->seqbasep->first; seq; seq=seq->next)
2140                 if(seq->flag & SELECT)
2141                         update_changed_seq_and_deps(seq, 1, 0);
2142
2143         /* for effects, try to find a replacement input */
2144         for(seq=ed->seqbasep->first; seq; seq=seq->next)
2145                 if((seq->type & SEQ_EFFECT) && !(seq->flag & SELECT))
2146                         del_seq_find_replace_recurs(seq);
2147
2148         /* delete all selected strips */
2149         recurs_del_seq_flag(ed->seqbasep, SELECT, 0);
2150
2151         /* updates lengths etc */
2152         seq= ed->seqbasep->first;
2153         while(seq) {
2154                 calc_sequence(seq);
2155                 seq= seq->next;
2156         }
2157
2158         /* free parent metas */
2159         ms= ed->metastack.last;
2160         while(ms) {
2161                 ms->parseq->strip->len= 0;              /* force new alloc */
2162                 calc_sequence(ms->parseq);
2163                 ms= ms->prev;
2164         }
2165
2166         BIF_undo_push("Delete Strip(s), Sequencer");
2167         allqueue(REDRAWSEQ, 0);
2168 }
2169
2170 static Sequence *dupli_seq(Sequence *seq) 
2171 {
2172         Sequence *seqn = MEM_dupallocN(seq);
2173
2174         seq->tmp = seqn;
2175                 
2176         seqn->strip= MEM_dupallocN(seq->strip);
2177
2178         if(seqn->ipo) seqn->ipo->id.us++;
2179
2180         seqn->strip->tstripdata = 0;
2181         seqn->strip->tstripdata_startstill = 0;
2182         seqn->strip->tstripdata_endstill = 0;
2183
2184         if (seq->strip->crop) {
2185                 seqn->strip->crop = MEM_dupallocN(seq->strip->crop);
2186         }
2187
2188         if (seq->strip->transform) {
2189                 seqn->strip->transform = MEM_dupallocN(seq->strip->transform);
2190         }
2191
2192         if (seq->strip->proxy) {
2193                 seqn->strip->proxy = MEM_dupallocN(seq->strip->proxy);
2194         }
2195
2196         if (seq->strip->color_balance) {
2197                 seqn->strip->color_balance 
2198                         = MEM_dupallocN(seq->strip->color_balance);
2199         }
2200         
2201         if(seq->type==SEQ_META) {
2202                 seqn->strip->stripdata = 0;
2203
2204                 seqn->seqbase.first= seqn->seqbase.last= 0;
2205                 /* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */
2206                 /* - recurs_dupli_seq(&seq->seqbase,&seqn->seqbase);*/
2207         } else if(seq->type == SEQ_SCENE) {
2208                 seqn->strip->stripdata = 0;
2209         } else if(seq->type == SEQ_MOVIE) {
2210                 seqn->strip->stripdata = 
2211                                 MEM_dupallocN(seq->strip->stripdata);
2212                 seqn->anim= 0;
2213         } else if(seq->type == SEQ_RAM_SOUND) {
2214                 seqn->strip->stripdata = 
2215                                 MEM_dupallocN(seq->strip->stripdata);
2216                 seqn->sound->id.us++;
2217         } else if(seq->type == SEQ_HD_SOUND) {
2218                 seqn->strip->stripdata = 
2219                                 MEM_dupallocN(seq->strip->stripdata);
2220                 seqn->hdaudio = 0;
2221         } else if(seq->type == SEQ_IMAGE) {
2222                 seqn->strip->stripdata = 
2223                                 MEM_dupallocN(seq->strip->stripdata);
2224         } else if(seq->type >= SEQ_EFFECT) {
2225                 if(seq->seq1 && seq->seq1->tmp) seqn->seq1= seq->seq1->tmp;
2226                 if(seq->seq2 && seq->seq2->tmp) seqn->seq2= seq->seq2->tmp;
2227                 if(seq->seq3 && seq->seq3->tmp) seqn->seq3= seq->seq3->tmp;
2228
2229                 if (seq->type & SEQ_EFFECT) {
2230                         struct SeqEffectHandle sh;
2231                         sh = get_sequence_effect(seq);
2232                         if(sh.copy)
2233                                 sh.copy(seq, seqn);
2234                 }
2235
2236                 seqn->strip->stripdata = 0;
2237                 
2238         } else {
2239                 fprintf(stderr, "Aiiiiekkk! sequence type not "
2240                                 "handled in duplicate!\nExpect a crash"
2241                                                 " now...\n");
2242         }
2243         
2244         return seqn;
2245 }
2246
2247 static void recurs_dupli_seq(ListBase *old, ListBase *new)
2248 {
2249         Sequence *seq;
2250         Sequence *seqn = 0;
2251         Sequence *last_seq = get_last_seq();
2252
2253         for(seq= old->first; seq; seq= seq->next) {
2254                 seq->tmp= NULL;
2255                 if(seq->flag & SELECT) {
2256                         seqn = dupli_seq(seq);
2257                         if (seqn) { /*should never fail */
2258                                 seq->flag &= SEQ_DESEL;
2259                                 seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL+SEQ_LOCK);
2260
2261                                 BLI_addtail(new, seqn);
2262                                 if(seq->type==SEQ_META)
2263                                         recurs_dupli_seq(&seq->seqbase,&seqn->seqbase);
2264                                 
2265                                 if (seq == last_seq) {
2266                                         set_last_seq(seqn);
2267                                 }
2268                         }
2269                 }
2270         }
2271 }
2272
2273 /* like duplicate, but only duplicate and cut overlapping strips,
2274  * strips to the left of the cutframe are ignored and strips to the right are moved into the new list */
2275 static void recurs_cut_seq(ListBase *old, ListBase *new, int cutframe)
2276 {
2277         Sequence *seq, *seq_next;
2278         Sequence *seqn = 0;
2279         
2280         TransSeq ts;
2281
2282         seq= old->first;
2283         
2284         while(seq) {
2285                 seq_next = seq->next; /* we need this because we may remove seq */
2286                 
2287                 seq->tmp= NULL;
2288                 if(seq->flag & SELECT) {
2289                         if(cutframe > seq->startdisp && cutframe < seq->enddisp) {
2290                                 
2291                                 /* backup values */
2292                                 ts.start= seq->start;
2293                                 ts.machine= seq->machine;
2294                                 ts.startstill= seq->startstill;
2295                                 ts.endstill= seq->endstill;
2296                                 ts.startdisp= seq->startdisp;
2297                                 ts.enddisp= seq->enddisp;
2298                                 ts.startofs= seq->startofs;
2299                                 ts.endofs= seq->endofs;
2300                                 ts.len= seq->len;
2301                                 
2302                                 /* First Strip! */
2303                                 /* strips with extended stillfames before */
2304                                 if(seq->type!=SEQ_META) {
2305                                         
2306                                         if ((seq->startstill) && (cutframe <seq->start)) {
2307                                                 seq->start= cutframe -1;
2308                                                 seq->startstill= cutframe -seq->startdisp -1;
2309                                                 seq->len= 1;
2310                                                 seq->endstill= 0;
2311                                         }
2312                                 
2313                                         /* normal strip */
2314                                         else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) {
2315                                                 seq->endofs = (seq->start+seq->len) - cutframe;
2316                                         }
2317                                 
2318                                         /* strips with extended stillframes after */
2319                                         else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
2320                                                 seq->endstill -= seq->enddisp - cutframe;
2321                                         }
2322                                         
2323                                         calc_sequence(seq);
2324                                 }
2325                                 
2326                                 /* Duplicate AFTER the first change */
2327                                 seqn = dupli_seq(seq);
2328                                 
2329                                 if (seqn) { /* should never fail */
2330                                         seqn->flag |= SELECT;
2331                                         
2332                                         
2333                                         BLI_addtail(new, seqn);
2334                                         
2335                                         /* dont transform meta's - just do their children then recalc */
2336                                         if(seq->type==SEQ_META) {
2337                                                 recurs_cut_seq(&seq->seqbase,&seqn->seqbase, cutframe);
2338                                         } else {
2339                                                 /* Second Strip! */
2340                                                 /* strips with extended stillframes before */
2341                                                 if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
2342                                                         seqn->start = ts.start;
2343                                                         seqn->startstill= ts.start- cutframe;
2344                                                         seqn->len = ts.len;
2345                                                         seqn->endstill = ts.endstill;
2346                                                 }
2347                         
2348                                                 /* normal strip */
2349                                                 else if ((cutframe>=seqn->start)&&(cutframe<=(seqn->start+seqn->len))) {
2350                                                         seqn->startstill = 0;
2351                                                         seqn->startofs = cutframe - ts.start;
2352                                                         seqn->endofs = ts.endofs;
2353                                                         seqn->endstill = ts.endstill;
2354                                                 }                               
2355                         
2356                                                 /* strips with extended stillframes after */
2357                                                 else if (((seqn->start+seqn->len) < cutframe) && (seqn->endstill)) {
2358                                                         seqn->start = cutframe - ts.len +1;
2359                                                         seqn->startofs = ts.len-1;
2360                                                         seqn->endstill = ts.enddisp - cutframe -1;
2361                                                         seqn->startstill = 0;
2362                                                 }
2363                                         }
2364                                         
2365                                         if(seq->type==SEQ_META) /* account for strips within changing */
2366                                                 calc_sequence(seq);
2367                                         
2368                                         calc_sequence(seqn);
2369                                 }
2370                         } else if (seq->enddisp <= cutframe) {
2371                                 /* do nothing */
2372                         } else if (seq->startdisp >= cutframe) {
2373                                 /* move into new list */
2374                                 BLI_remlink(old, seq);
2375                                 BLI_addtail(new, seq);
2376                         }
2377                 }
2378                 seq = seq_next;
2379         }
2380 }
2381
2382 void seq_cut(int cutframe)
2383 {
2384         Editing *ed;
2385         ListBase newlist;
2386         char side;
2387         ed= G.scene->ed;
2388         if(ed==0) return;
2389         
2390         newlist.first= newlist.last= NULL;
2391         
2392         recurs_cut_seq(ed->seqbasep, &newlist, cutframe);
2393         
2394         if (newlist.first) { /* simple check to see if anything was done */
2395                 Sequence *seq;
2396                 addlisttolist(ed->seqbasep, &newlist);
2397                 
2398                 
2399                 /* change the selection, not strictly needed but nice */
2400                 side = mouse_cfra_side(cutframe);
2401                 
2402                 WHILE_SEQ(ed->seqbasep) {
2403                         if (side=='L') {
2404                                 if ( seq->startdisp >= cutframe ) {
2405                                         seq->flag &= ~SELECT;
2406                                 }
2407                         } else {
2408                                 if ( seq->enddisp <= cutframe ) {
2409                                         seq->flag &= ~SELECT;
2410                                 }
2411                         }
2412                 }
2413                 END_SEQ;
2414                 
2415                 /* as last: */
2416                 sort_seq();
2417                 
2418                 allqueue(REDRAWSEQ, 0);
2419                 BIF_undo_push("Cut Strips, Sequencer");
2420         }
2421 }
2422
2423 void add_duplicate_seq(void)
2424 {
2425         Editing *ed;
2426         ListBase new;
2427
2428         ed= G.scene->ed;
2429         if(ed==0) return;
2430
2431         new.first= new.last= 0;
2432
2433         recurs_dupli_seq(ed->seqbasep, &new);
2434         addlisttolist(ed->seqbasep, &new);
2435
2436         BIF_undo_push("Add Duplicate, Sequencer");
2437         transform_seq_nomarker('g', 0);
2438 }
2439
2440 int insert_gap(int gap, int cfra)
2441 {
2442         Sequence *seq;
2443         Editing *ed;
2444         int done=0;
2445
2446         /* all strips >= cfra are shifted */
2447         ed= G.scene->ed;
2448         if(ed==0) return 0;
2449
2450         WHILE_SEQ(ed->seqbasep) {
2451                 if(seq->startdisp >= cfra) {
2452                         seq->start+= gap;
2453                         calc_sequence(seq);
2454                         done= 1;
2455                 }
2456         }
2457         END_SEQ
2458
2459         return done;
2460 }
2461
2462 void touch_seq_files(void)
2463 {
2464         Sequence *seq;
2465         Editing *ed;
2466         char str[256];
2467
2468         /* touch all strips with movies */
2469         ed= G.scene->ed;
2470         if(ed==0) return;
2471
2472         if(okee("Touch and print selected movies")==0) return;
2473
2474         waitcursor(1);
2475
2476         WHILE_SEQ(ed->seqbasep) {
2477                 if(seq->flag & SELECT) {
2478                         if(seq->type==SEQ_MOVIE) {
2479                                 if(seq->strip && seq->strip->stripdata) {
2480                                         BLI_make_file_string(G.sce, str, seq->strip->dir, seq->strip->stripdata->name);
2481                                         BLI_touch(seq->name);
2482                                 }
2483                         }
2484
2485                 }
2486         }
2487         END_SEQ
2488
2489         waitcursor(0);
2490 }
2491
2492 void set_filter_seq(void)
2493 {
2494         Sequence *seq;
2495         Editing *ed;
2496
2497         ed= G.scene->ed;
2498         if(ed==0) return;
2499
2500         if(okee("Set FilterY")==0) return;
2501
2502         WHILE_SEQ(ed->seqbasep) {
2503                 if(seq->flag & SELECT) {
2504                         if(seq->type==SEQ_MOVIE) {
2505                                 seq->flag |= SEQ_FILTERY;
2506                         }
2507
2508                 }
2509         }
2510         END_SEQ
2511
2512 }
2513
2514 void seq_remap_paths(void)
2515 {
2516         Sequence *seq, *last_seq = get_last_seq();
2517         Editing *ed;
2518         char from[FILE_MAX], to[FILE_MAX], stripped[FILE_MAX];
2519         
2520         ed= G.scene->ed;
2521         if(ed==NULL || last_seq==NULL) 
2522                 return;
2523         
2524         BLI_strncpy(from, last_seq->strip->dir, FILE_MAX);
2525         if (0==sbutton(from, 0, sizeof(from)-1, "From: "))
2526                 return;
2527         
2528         strcpy(to, from);
2529         if (0==sbutton(to, 0, sizeof(to)-1, "To: "))
2530                 return;
2531         
2532         if (strcmp(to, from)==0)
2533                 return;
2534         
2535         WHILE_SEQ(ed->seqbasep) {
2536                 if(seq->flag & SELECT) {
2537                         if(strncmp(seq->strip->dir, from, strlen(from))==0) {
2538                                 printf("found %s\n", seq->strip->dir);
2539                                 
2540                                 /* strip off the beginning */
2541                                 stripped[0]= 0;
2542                                 BLI_strncpy(stripped, seq->strip->dir + strlen(from), FILE_MAX);
2543                                 
2544                                 /* new path */
2545                                 BLI_strncpy(seq->strip->dir, to, FILE_MAX);
2546                                 strcat(seq->strip->dir, stripped);
2547                                 printf("new %s\n", seq->strip->dir);
2548                         }
2549                 }
2550         }
2551         END_SEQ
2552                 
2553         BIF_undo_push("Remap Paths, Sequencer");
2554         allqueue(REDRAWSEQ, 0);
2555 }
2556
2557
2558 void no_gaps(void)
2559 {
2560         Editing *ed;
2561         int cfra, first= 0, done;
2562
2563         ed= G.scene->ed;
2564         if(ed==0) return;
2565
2566         for(cfra= CFRA; cfra<=EFRA; cfra++) {
2567                 if(first==0) {
2568                         if( evaluate_seq_frame(cfra) ) first= 1;
2569                 }
2570                 else {
2571                         done= 1;
2572                         while( evaluate_seq_frame(cfra) == 0) {
2573                                 done= insert_gap(-1, cfra);
2574                                 if(done==0) break;
2575                         }
2576                         if(done==0) break;
2577                 }
2578         }
2579
2580         BIF_undo_push("No Gaps, Sequencer");
2581         allqueue(REDRAWSEQ, 0);
2582 }
2583
2584
2585 /* ****************** META ************************* */
2586
2587 void make_meta(void)
2588 {
2589         Sequence *seq, *seqm, *next;
2590         Editing *ed;
2591         int tot;
2592         
2593         ed= G.scene->ed;
2594         if(ed==0) return;
2595
2596         /* is there more than 1 select */
2597         tot= 0;
2598         seq= ed->seqbasep->first;
2599         while(seq) {
2600                 if(seq->flag & SELECT) {
2601                         tot++;
2602                         if (seq->type == SEQ_RAM_SOUND) { 
2603                                 error("Can't make Meta Strip from audio"); 
2604                                 return; 
2605                         }
2606                 }
2607                 seq= seq->next;
2608         }
2609         if(tot < 1) return;
2610
2611         if(okee("Make Meta Strip")==0) return;
2612
2613         /* test relationships */
2614         seq= ed->seqbasep->first;
2615         while(seq) {
2616                 if(seq->flag & SELECT) {
2617                         if(seq->type & SEQ_EFFECT) {
2618                                 if(seq->seq1 && 
2619                                    (seq->seq1->flag & SELECT)==0) tot= 0;
2620                                 if(seq->seq2 &&
2621                                    (seq->seq2->flag & SELECT)==0) tot= 0;
2622                                 if(seq->seq3 &&
2623                                    (seq->seq3->flag & SELECT)==0) tot= 0;
2624                         }
2625                 }
2626                 else if(seq->type & SEQ_EFFECT) {
2627                         if(seq->seq1 &&
2628                            (seq->seq1->flag & SELECT)) tot= 0;
2629                         if(seq->seq2 &&
2630                            (seq->seq2->flag & SELECT)) tot= 0;
2631                         if(seq->seq3 &&
2632                            (seq->seq3->flag & SELECT)) tot= 0;
2633                 }
2634                 if(tot==0) break;
2635                 seq= seq->next;
2636         }
2637         if(tot==0) {
2638                 error("Please select all related strips");
2639                 return;
2640         }
2641
2642         /* remove all selected from main list, and put in meta */
2643
2644         seqm= alloc_sequence(((Editing *)G.scene->ed)->seqbasep, 1, 1);
2645         seqm->type= SEQ_META;
2646         seqm->flag= SELECT;
2647
2648         seq= ed->seqbasep->first;
2649         while(seq) {
2650                 next= seq->next;
2651                 if(seq!=seqm && (seq->flag & SELECT)) {
2652                         BLI_remlink(ed->seqbasep, seq);
2653                         BLI_addtail(&seqm->seqbase, seq);
2654                 }
2655                 seq= next;
2656         }
2657         calc_sequence(seqm);
2658
2659         seqm->strip= MEM_callocN(sizeof(Strip), "metastrip");
2660         seqm->strip->len= seqm->len;
2661         seqm->strip->us= 1;
2662
2663         set_meta_stripdata(seqm);
2664         
2665         if( test_overlap_seq(seqm) ) shuffle_seq(seqm);
2666         
2667         BIF_undo_push("Make Meta Strip, Sequencer");
2668         allqueue(REDRAWSEQ, 0);
2669 }
2670
2671 static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
2672 {
2673         if (seq == seqm) return 1;
2674         else if (seq->seq1 && seq_depends_on_meta(seq->seq1, seqm)) return 1;
2675         else if (seq->seq2 && seq_depends_on_meta(seq->seq2, seqm)) return 1;
2676         else if (seq->seq3 && seq_depends_on_meta(seq->seq3, seqm)) return 1;
2677         else return 0;
2678 }
2679
2680 void un_meta(void)
2681 {
2682         Editing *ed;
2683         Sequence *seq, *last_seq = get_last_seq();
2684
2685         ed= G.scene->ed;
2686         if(ed==0) return;
2687
2688         if(last_seq==0 || last_seq->type!=SEQ_META) return;
2689
2690         if(okee("Un Meta Strip")==0) return;
2691
2692         addlisttolist(ed->seqbasep, &last_seq->seqbase);
2693
2694         last_seq->seqbase.first= 0;
2695         last_seq->seqbase.last= 0;
2696
2697         BLI_remlink(ed->seqbasep, last_seq);
2698         free_sequence(last_seq);
2699
2700         /* emtpy meta strip, delete all effects depending on it */
2701         for(seq=ed->seqbasep->first; seq; seq=seq->next)
2702                 if((seq->type & SEQ_EFFECT) && seq_depends_on_meta(seq, last_seq))
2703                         seq->flag |= SEQ_FLAG_DELETE;
2704
2705         recurs_del_seq_flag(ed->seqbasep, SEQ_FLAG_DELETE, 0);
2706
2707         /* test for effects and overlap */
2708         WHILE_SEQ(ed->seqbasep) {
2709                 if(seq->flag & SELECT) {
2710                         seq->flag &= ~SEQ_OVERLAP;
2711                         if( test_overlap_seq(seq) ) {
2712                                 shuffle_seq(seq);
2713                         }
2714                 }
2715         }
2716         END_SEQ;
2717
2718         sort_seq();
2719
2720         BIF_undo_push("Un-Make Meta Strip, Sequencer");
2721         allqueue(REDRAWSEQ, 0);
2722
2723 }
2724
2725 void exit_meta(void)
2726 {
2727         Sequence *seq;
2728         MetaStack *ms;
2729         Editing *ed;
2730
2731         ed= G.scene->ed;
2732         if(ed==0) return;
2733
2734         if(ed->metastack.first==0) return;
2735
2736         ms= ed->metastack.last;
2737         BLI_remlink(&ed->metastack, ms);
2738
2739         ed->seqbasep= ms->oldbasep;
2740
2741         /* recalc entire meta */
2742         set_meta_stripdata(ms->parseq);
2743
2744         /* recalc all: the meta can have effects connected to it */
2745         seq= ed->seqbasep->first;
2746         while(seq) {
2747                 calc_sequence(seq);
2748                 seq= seq->next;
2749         }
2750
2751         set_last_seq(ms->parseq);
2752
2753         ms->parseq->flag |= SELECT;
2754         recurs_sel_seq(ms->parseq);
2755
2756         MEM_freeN(ms);
2757         allqueue(REDRAWSEQ, 0);
2758
2759         BIF_undo_push("Exit Meta Strip, Sequence");
2760 }
2761
2762
2763 void enter_meta(void)
2764 {
2765         MetaStack *ms;
2766         Editing *ed;
2767         Sequence *last_seq= get_last_seq();
2768
2769         ed= G.scene->ed;
2770         if(ed==0) return;
2771
2772         if(last_seq==0 || last_seq->type!=SEQ_META || last_seq->flag==0) {
2773                 exit_meta();
2774                 return;
2775         }
2776
2777         ms= MEM_mallocN(sizeof(MetaStack), "metastack");
2778         BLI_addtail(&ed->metastack, ms);
2779         ms->parseq= last_seq;
2780         ms->oldbasep= ed->seqbasep;
2781
2782         ed->seqbasep= &last_seq->seqbase;
2783
2784         set_last_seq(NULL);
2785         allqueue(REDRAWSEQ, 0);
2786         BIF_undo_push("Enter Meta Strip, Sequence");
2787 }
2788
2789
2790 /* ****************** END META ************************* */
2791
2792 static int seq_get_snaplimit(void)
2793 {
2794         /* fake mouse coords to get the snap value
2795         a bit lazy but its only done once pre transform */
2796         float xmouse, ymouse, x;
2797         short mval[2] = {24, 0}; /* 24 screen px snap */
2798         areamouseco_to_ipoco(G.v2d, mval, &xmouse, &ymouse);
2799         x = xmouse;
2800         mval[0] = 0;
2801         areamouseco_to_ipoco(G.v2d, mval, &xmouse, &ymouse);
2802         return (int)(x - xmouse);
2803 }
2804
2805 /* use to impose limits when dragging/extending - so impossible situations dont happen */
2806 static void transform_grab_xlimits(Sequence *seq, int leftflag, int rightflag)
2807 {
2808         if(leftflag) {
2809                 if (seq_tx_get_final_left(seq) >= seq_tx_get_final_right(seq)) {
2810                         seq_tx_set_final_left(seq, seq_tx_get_final_right(seq)-1);
2811                 }
2812                 
2813                 if (check_single_seq(seq)==0) {
2814                         if (seq_tx_get_final_left(seq) >= seq_tx_get_end(seq)) {
2815                                 seq_tx_set_final_left(seq, seq_tx_get_end(seq)-1);
2816                         }
2817                         
2818                         /* dosnt work now - TODO */
2819                         /*
2820                         if (seq_tx_get_start(seq) >= seq_tx_get_final_right(seq)) {
2821                                 int ofs;
2822                                 ofs = seq_tx_get_start(seq) - seq_tx_get_final_right(seq);
2823                                 seq->start -= ofs;
2824                                 seq_tx_set_final_left(seq, seq_tx_get_final_left(seq) + ofs );
2825                         }*/
2826                         
2827                 }
2828         }
2829         
2830         if(rightflag) {
2831                 if (seq_tx_get_final_right(seq) <=  seq_tx_get_final_left(seq)) {
2832                         seq_tx_set_final_right(seq, seq_tx_get_final_left(seq)+1);
2833                 }
2834                                                                         
2835                 if (check_single_seq(seq)==0) {
2836                         if (seq_tx_get_final_right(seq) <= seq_tx_get_start(seq)) {
2837                                 seq_tx_set_final_right(seq, seq_tx_get_start(seq)+1);
2838                         }
2839                 }
2840         }
2841         
2842         /* sounds cannot be extended past their endpoints */
2843         if (seq->type == SEQ_RAM_SOUND || seq->type == SEQ_HD_SOUND) {
2844                 seq->startstill= 0;
2845                 seq->endstill= 0;
2846         }
2847 }
2848
2849 static int can_transform_seq_test_func(Sequence * seq)
2850 {
2851         if((seq->flag & SELECT) && !(seq->depth==0 && seq->flag & SEQ_LOCK)) {
2852                 return BUILD_SEQAR_COUNT_CURRENT | BUILD_SEQAR_COUNT_CHILDREN;
2853         }
2854         if ((seq->depth==0 && seq->flag & SEQ_LOCK) && !(seq->type & SEQ_EFFECT)) {
2855                 if (seq->type != SEQ_META) {
2856                         return BUILD_SEQAR_COUNT_NOTHING;
2857                 } else {
2858                         return BUILD_SEQAR_COUNT_CURRENT;
2859                 }
2860         }
2861         return BUILD_SEQAR_COUNT_CURRENT | BUILD_SEQAR_COUNT_CHILDREN;
2862 }
2863
2864 void transform_seq(int mode, int context)
2865 {
2866         SpaceSeq *sseq= curarea->spacedata.first;
2867         Sequence *seq, *last_seq;
2868         Editing *ed;
2869         float dx, dy, dvec[2], div;
2870         TransSeq *transmain, *ts;
2871         int totstrip=0, firsttime=1, afbreek=0, midtog= 0, proj= 0;
2872         int ix, iy; /* these values are used for storing the mouses offset from its original location */
2873         int ix_old = 0;
2874         unsigned short event = 0;
2875         short mval[2], val, xo, yo, xn, yn;
2876         char str[32];
2877         char side= 'L'; /* for extend mode only - use to know which side to extend on */
2878         char marker_moved=0; /* if we mvoed a marker, redraw all marker views */
2879         /* used for extend in a number of places */
2880         int cfra = CFRA;
2881         
2882         /* for snapping */
2883         char snapskip = 0, snap, snap_old= 0;
2884         int snapdist_max = seq_get_snaplimit();
2885         /* at the moment there are only 4 possible snap points,
2886         -       last_seq (start,end)
2887         -       selected bounds (start/end)
2888         -       last_seq (next/prev)
2889         -       current frame */
2890         int snap_points[4], snap_point_num = 0;
2891         int j; /* loop on snap_points */
2892         
2893         /* for markers */
2894         int *oldframe = NULL, totmark=0, a;
2895         TimeMarker *marker;
2896         
2897         /* looping on sequences, WHILE_SEQ macro allocates memory each time */
2898         int totseq_index, seq_index; 
2899         Sequence **seqar = 0;
2900         
2901         if(mode!='g' && mode!='e') return;      /* from gesture */
2902
2903         /* which seqs are involved */
2904         ed= G.scene->ed;
2905         if(ed==0) return;
2906
2907         /* Build the sequence array once, be sure to free it */
2908         build_seqar_cb( ed->seqbasep,  &seqar, &totseq_index, 
2909                         can_transform_seq_test_func );
2910         
2911         if (seqar) {
2912                 for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) {
2913                         if((seq->flag & SELECT) && !(seq->depth==0 && seq->flag & SEQ_LOCK)) 
2914                                 totstrip++;
2915                 }
2916         }
2917         
2918         if (sseq->flag & SEQ_MARKER_TRANS) {
2919                 for(marker= G.scene->markers.first; marker; marker= marker->next) {
2920                         if(marker->flag & SELECT) totmark++;
2921                 }
2922         }
2923         
2924         if(totstrip==0 && totmark==0) {
2925                 if(seqar) MEM_freeN(seqar);
2926                 return;
2927         }
2928
2929         G.moving= 1;
2930         
2931         last_seq = get_last_seq();
2932         
2933         ts=transmain= MEM_callocN(totstrip*sizeof(TransSeq), "transseq");
2934
2935         for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) {
2936                 if((seq->flag & SELECT) && !(seq->depth==0 && seq->flag & SEQ_LOCK)) {
2937                         ts->start= seq->start;
2938                         ts->machine= seq->machine;
2939                         ts->startstill= seq->startstill;
2940                         ts->endstill= seq->endstill;
2941                         ts->startofs= seq->startofs;
2942                         ts->endofs= seq->endofs;
2943                         
2944                         /* for extend only */
2945                         if (mode=='e') {
2946                                 ts->final_left = seq_tx_get_final_left(seq);
2947                                 ts->final_right = seq_tx_get_final_right(seq);
2948                         }
2949                         ts++;
2950                 }
2951         }
2952         
2953         getmouseco_areawin(mval);
2954         
2955         /* choose the side based on which side of the playhead the mouse is on */
2956         if (mode=='e')
2957                 side = mouse_cfra_side(cfra);
2958         
2959         /* Markers */
2960         if (sseq->flag & SEQ_MARKER_TRANS && totmark) {
2961                 oldframe= MEM_mallocN(totmark*sizeof(int), "marker array");
2962                 for(a=0, marker= G.scene->markers.first; marker; marker= marker->next) {
2963                         if(marker->flag & SELECT) {
2964                                 if (mode=='e') {
2965                                         
2966                                         /* when extending, invalidate markers on the other side by using an invalid frame value */
2967                                         if ((side == 'L' && marker->frame > cfra) || (side == 'R' && marker->frame < cfra)) {
2968                                                 oldframe[a] = MAXFRAME+1;
2969                                         } else {
2970                                                 oldframe[a]= marker->frame;
2971                                         }
2972                                 } else {
2973                                         oldframe[a]= marker->frame;
2974                                 }
2975                                 a++;
2976                         }
2977                 }
2978         }
2979         
2980         xo=xn= mval[0];
2981         yo=yn= mval[1];
2982         dvec[0]= dvec[1]= 0.0;
2983
2984         while(afbreek==0) {
2985                 getmouseco_areawin(mval);
2986                 G.qual = get_qual();
2987                 snap = (G.qual & LR_CTRLKEY) ? 1 : 0;
2988                 
2989                 if(mval[0]!=xo || mval[1]!=yo || firsttime || snap != snap_old) {
2990                         if (firsttime) {
2991                                 snap_old = snap;
2992                                 firsttime= 0;
2993                         }
2994                         
2995                         /* run for either grab or extend */
2996                         dx= mval[0]- xo;
2997                         dy= mval[1]- yo;
2998
2999                         div= G.v2d->mask.xmax-G.v2d->mask.xmin;
3000                         dx= (G.v2d->cur.xmax-G.v2d->cur.xmin)*(dx)/div;
3001
3002                         div= G.v2d->mask.ymax-G.v2d->mask.ymin;
3003                         dy= (G.v2d->cur.ymax-G.v2d->cur.ymin)*(dy)/div;
3004
3005                         if(G.qual & LR_SHIFTKEY) {
3006                                 if(dx>1.0) dx= 1.0; else if(dx<-1.0) dx= -1.0;
3007                         }
3008
3009                         dvec[0]+= dx;
3010                         dvec[1]+= dy;
3011
3012                         if(midtog) dvec[proj]= 0.0;
3013                         ix= floor(dvec[0]+0.5);
3014                         iy= floor(dvec[1]+0.5);
3015                         
3016                         ts= transmain;
3017                         
3018                         /* SNAP! use the active Seq */
3019                         snap = G.qual & LR_CTRLKEY ? 1 : 0;
3020                         
3021                         if (!snap) {
3022                                 snapskip = 0;
3023                         } else {
3024                                 int dist;
3025                                 int snap_ofs= 0;
3026                                 int snap_dist= snapdist_max;
3027                                 
3028                                 /* Get sequence points to snap to the markers */
3029                                 
3030                                 snap_point_num=0;
3031                                 if (last_seq && (last_seq->flag & SELECT)) { /* active seq bounds */
3032                                         if(seq_tx_check_left(last_seq))
3033                                                 snap_points[snap_point_num++] = seq_tx_get_final_left(last_seq);
3034                                         if(seq_tx_check_right(last_seq))
3035                                                 snap_points[snap_point_num++] = seq_tx_get_final_right(last_seq);
3036                                         
3037                                 }
3038                                 if (totstrip > 1) { /* selection bounds */
3039                                         int bounds_left = MAXFRAME*2;
3040                                         int bounds_right = -(MAXFRAME*2);
3041                                         
3042                                         for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) {
3043                                                 if(seq->flag & SELECT) {
3044                                                         if(seq_tx_check_left(seq))
3045                                                                 bounds_left             = MIN2(bounds_left,     seq_tx_get_final_left(seq));
3046                                                         if(seq_tx_check_right(seq))
3047                                                                 bounds_right    = MAX2(bounds_right,seq_tx_get_final_right(seq));
3048                                                 }
3049                                         }
3050                                         
3051                                         /* its possible there were no points to set on either side */
3052                                         if (bounds_left != MAXFRAME*2)
3053                                                 snap_points[snap_point_num++] = bounds_left;
3054                                         if (bounds_right != -(MAXFRAME*2))
3055                                                 snap_points[snap_point_num++] = bounds_right;
3056                                 }
3057                                 
3058                                 
3059                                 /* Define so we can snap to other points without hassle */
3060                                 
3061 #define TESTSNAP(test_frame)\
3062                                 for(j=0; j<snap_point_num; j++) {\
3063                                         /* see if this beats the current best snap point */\
3064                                         dist = abs(snap_points[j] - test_frame);\
3065                                         if (dist < snap_dist) {\
3066                                                 snap_ofs = test_frame - snap_points[j];\
3067                                                 snap_dist = dist;\
3068                                         }\
3069                                 }
3070                                 
3071                                 
3072                                 /* Detect the best marker to snap to! */
3073                                 for(a=0, marker= G.scene->markers.first; marker; a++, marker= marker->next) {
3074                                         
3075                                         /* dont snap to a marker on the wrong extend side */
3076                                         if (mode=='e' && ((side == 'L' && marker->frame > cfra) || (side == 'R' && marker->frame < cfra)))
3077                                                 continue;
3078                                         
3079                                         /* when we are moving markers, dont snap to selected markers, durr */
3080                                         if ((sseq->flag & SEQ_MARKER_TRANS)==0 || (marker->flag & SELECT)==0) {
3081                                                 
3082                                                 /* loop over the sticky points - max 4 */
3083                                                 TESTSNAP(marker->frame);
3084                                                 if (snap_dist == 0) break; /* alredy snapped? - stop looking */
3085                                         }
3086                                 }
3087                                 
3088                                 if (snap_dist) {
3089                                         TESTSNAP(cfra);
3090                                 }
3091                                 
3092                                 /* check seq's next to the active also - nice for quick snapping */
3093                                 if (snap_dist && last_seq && seq_tx_check_left(last_seq)) {
3094                                         seq = find_next_prev_sequence(last_seq, 1, 0); /* left */
3095                                         if(seq && !seq_tx_check_right(seq))
3096                                                 TESTSNAP(seq_tx_get_final_right(seq));
3097                                 }
3098                                 
3099                                 if (snap_dist && last_seq && seq_tx_check_right(last_seq)) {
3100                                         seq = find_next_prev_sequence(last_seq, 2, 0); /* right */
3101                                         if(seq && !seq_tx_check_left(seq))
3102                                                 TESTSNAP(seq_tx_get_final_left(seq));
3103                                 }
3104
3105 #undef TESTSNAP
3106
3107                                 if (abs(ix_old-ix) >= snapdist_max) {
3108                                         /* mouse has moved out of snap range */
3109                                         snapskip = 0;
3110                                 } else if (snap_dist==0) {
3111                                         /* nowhere to move, dont do anything */
3112                                         snapskip = 1;
3113                                 } else if (snap_dist < snapdist_max) {
3114                                         /* do the snapping by adjusting the mouse offset value */
3115                                         ix = ix_old + snap_ofs;
3116                                 }
3117                         }
3118                         
3119                         if (mode=='g' && !snapskip) {
3120                                 /* Grab */
3121                                 for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) {
3122                                         if(seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK)) {
3123                                                 int myofs;
3124                                                 // SEQ_DEBUG_INFO(seq);
3125                                                 
3126                                                 /* X Transformation */
3127                                                 if(seq->flag & SEQ_LEFTSEL) {
3128                                                         myofs = (ts->startofs - ts->startstill);
3129                                                         seq_tx_set_final_left(seq, ts->start + (myofs + ix));
3130                                                 }
3131                                                 if(seq->flag & SEQ_RIGHTSEL) {
3132                                                         myofs = (ts->endstill - ts->endofs);
3133                                                         seq_tx_set_final_right(seq, ts->start + seq->len + (myofs + ix));
3134                                                 }
3135                                                 transform_grab_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
3136                                                 
3137                                                 if( (seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))==0 ) {
3138                                                         if(sequence_is_free_transformable(seq)) seq->start= ts->start+ ix;
3139
3140                                                         /* Y Transformation */
3141                                                         if(seq->depth==0) seq->machine= ts->machine+ iy;
3142
3143                                                         if(seq->machine<1) seq->machine= 1;
3144                                                         else if(seq->machine>= MAXSEQ) seq->machine= MAXSEQ;
3145                                                 }
3146                                                 calc_sequence(seq);
3147                                                 ts++;
3148                                         }
3149                                 }
3150                                 
3151                                 /* Markers */
3152                                 if (sseq->flag & SEQ_MARKER_TRANS) {
3153                                         for(a=0, marker= G.scene->markers.first; marker; marker= marker->next) {
3154                                                 if(marker->flag & SELECT) {
3155                                                         marker->frame= oldframe[a] + ix;
3156                                                         marker_moved=1;
3157                                                         a++;
3158                                                 }
3159                                         }
3160                                 }
3161                         
3162                         /* Extend, grabs one side of the current frame */
3163                         } else if (mode=='e' && !snapskip) {
3164                                 int myofs; /* offset from start of the seq clip */
3165                                 int xnew, final_left, final_right; /* just to store results from seq_tx_get_final_left/right */
3166                                 
3167                                 /* we dont use seq side selection flags for this,
3168                                 instead we need to calculate which sides to move
3169                                 based on its initial position from the cursor */
3170                                 int move_left, move_right;
3171                                 
3172                                 /* Extend, Similar to grab but operate on one side of the cursor */
3173                                 for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) {
3174                                         if(seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK)) {
3175                                                 /* only move the contents of the metastrip otherwise the transformation is applied twice */
3176                                                 if (sequence_is_free_transformable(seq) && seq->type != SEQ_META) {
3177                                                         
3178                                                         move_left = move_right = 0;
3179                                                         
3180                                                         //SEQ_DEBUG_INFO(seq);
3181                                                         
3182                                                         final_left =    seq_tx_get_final_left(seq);
3183                                                         final_right =   seq_tx_get_final_right(seq);
3184                                                         
3185                                                         /* Only X Axis moving */
3186                                                         
3187                                                         /* work out which sides to move first */
3188                                                         if (side=='L') {
3189                                                                 if (final_left <= cfra || ts->final_left <= cfra)       move_left = 1;
3190                                                                 if (final_right <= cfra || ts->final_right <= cfra)     move_right = 1;
3191                                                         } else {
3192                                                                 if (final_left >= cfra || ts->final_left >= cfra)       move_left = 1;
3193                                                                 if (final_right >= cfra || ts->final_right >= cfra)     move_right = 1;
3194                                                         }
3195                                                         
3196                                                         if (move_left && move_right) {
3197                                                                 /* simple move - dont need to do anything complicated */
3198                                                                 seq->start= ts->start+ ix;
3199                                                         } else {
3200                                                                 if (side=='L') {
3201                                                                         if (move_left) {
3202                                                                                 
3203                                                                                 /* Similar to other funcs */
3204                                                                                 myofs = (ts->startofs - ts->startstill);
3205                                                                                 xnew = ts->start + (ix + myofs);
3206                                                                                 
3207                                                                                 /* make sure the we dont resize down to 0 or less in size
3208                                                                                 also include the startstill so the contense dosnt go outside the bounds, 
3209                                                                                 if the seq->startofs is 0 then its ignored */
3210                                                                                 
3211                                                                                 /* TODO remove, add check to transform_grab_xlimits, works ok for now */
3212                                                                                 if (xnew + seq->startstill > final_right-1) {
3213                                                                                         xnew = (final_right-1) - seq->startstill;
3214                                                                                 }
3215                                                                                 /* Note, this is the only case where the start needs to be adjusted
3216                                                                                 since its not needed when modifying the end or when moving the entire sequence  */
3217                                                                                 //seq->start = ts->start+ix;   // This works when xnew is not clamped, line below takes clamping into account
3218                                                                                 seq->start= xnew - myofs;  /* TODO see above */
3219                                                                                 /* done with unique stuff */
3220                                                                                 
3221                                                                                 seq_tx_set_final_left(seq, xnew);
3222                                                                                 transform_grab_xlimits(seq, 1, 0);
3223