4995e106a305f0b4edfe062d78224070c9186137
[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         *selseq1= seq1;
1662         *selseq2= seq2;
1663         *selseq3= seq3;
1664
1665         return 1;
1666 }
1667
1668 static int add_seq_effect(int type, char *str)
1669 {
1670         Editing *ed;
1671         Sequence *newseq, *seq1, *seq2, *seq3;
1672         Strip *strip;
1673         float x, y;
1674         int cfra, machine;
1675         short mval[2];
1676         struct SeqEffectHandle sh;
1677
1678         if(G.scene->ed==0) return 0;
1679         ed= G.scene->ed;
1680
1681         if(!seq_effect_find_selected(ed, NULL, event_to_efftype(type), &seq1, &seq2, &seq3))
1682                 return 0;
1683
1684         deselect_all_seq();
1685
1686         /* where will it be (cfra is not realy needed) */
1687         getmouseco_areawin(mval);
1688         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1689         cfra= (int)(x+0.5);
1690         machine= (int)(y+0.5);
1691
1692         /* allocate and initialize */
1693         newseq= alloc_sequence(((Editing *)G.scene->ed)->seqbasep, cfra, machine);
1694         newseq->type= event_to_efftype(type);
1695
1696         sh = get_sequence_effect(newseq);
1697
1698         newseq->seq1= seq1;
1699         newseq->seq2= seq2;
1700         newseq->seq3= seq3;
1701
1702         sh.init(newseq);
1703
1704         if (!seq1) {
1705                 newseq->len= 1;
1706                 newseq->startstill= 25;
1707                 newseq->endstill= 24;
1708         }
1709
1710         calc_sequence(newseq);
1711
1712         newseq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
1713         strip->len= newseq->len;
1714         strip->us= 1;
1715         if(newseq->len>0)
1716                 strip->stripdata= MEM_callocN(newseq->len*sizeof(StripElem), "stripelem");
1717
1718         /* initialize plugin */
1719         if(newseq->type == SEQ_PLUGIN) {
1720                 sh.init_plugin(newseq, str);
1721
1722                 if(newseq->plugin==0) {
1723                         BLI_remlink(ed->seqbasep, newseq);
1724                         free_sequence(newseq);
1725                         set_last_seq(NULL);
1726                         return 0;
1727                 }
1728         }
1729
1730         /* set find a free spot to but the strip */
1731         if (newseq->seq1) {
1732                 newseq->machine= MAX3(newseq->seq1->machine, 
1733                                       newseq->seq2->machine,
1734                                       newseq->seq3->machine);
1735         }
1736         if(test_overlap_seq(newseq)) shuffle_seq(newseq);
1737
1738         update_changed_seq_and_deps(newseq, 1, 1);
1739
1740         /* push undo and go into grab mode */
1741         if(newseq->type == SEQ_PLUGIN) {
1742                 BIF_undo_push("Add Plugin Strip, Sequencer");
1743         } else {
1744                 BIF_undo_push("Add Effect Strip, Sequencer");
1745         }
1746
1747         transform_seq_nomarker('g', 0);
1748
1749         return 1;
1750 }
1751
1752 static void load_plugin_seq(char *str)          /* called from fileselect */
1753 {
1754         add_seq_effect(10, str);
1755 }
1756
1757 void add_sequence(int type)
1758 {
1759         Editing *ed;
1760         short event;
1761         char *str;
1762
1763         if (type >= 0){
1764                 /* bypass pupmenu for calls from menus (aphex) */
1765                 switch(type){
1766                 case SEQ_SCENE:
1767                         event = 101;
1768                         break;
1769                 case SEQ_IMAGE:
1770                         event = 1;
1771                         break;
1772                 case SEQ_MOVIE:
1773                         event = 102;
1774                         break;
1775                 case SEQ_RAM_SOUND:
1776                         event = 103;
1777                         break;
1778                 case SEQ_HD_SOUND:
1779                         event = 104;
1780                         break;
1781                 case SEQ_MOVIE_AND_HD_SOUND:
1782                         event = 105;
1783                         break;
1784                 case SEQ_PLUGIN:
1785                         event = 10;
1786                         break;
1787                 case SEQ_CROSS:
1788                         event = 2;
1789                         break;
1790                 case SEQ_ADD:
1791                         event = 4;
1792                         break;
1793                 case SEQ_SUB:
1794                         event = 5;
1795                         break;
1796                 case SEQ_ALPHAOVER:
1797                         event = 7;
1798                         break;
1799                 case SEQ_ALPHAUNDER:
1800                         event = 8;
1801                         break;
1802                 case SEQ_GAMCROSS:
1803                         event = 3;
1804                         break;
1805                 case SEQ_MUL:
1806                         event = 6;
1807                         break;
1808                 case SEQ_OVERDROP:
1809                         event = 9;
1810                         break;
1811                 case SEQ_WIPE:
1812                         event = 13;
1813                         break;
1814                 case SEQ_GLOW:
1815                         event = 14;
1816                         break;
1817                 case SEQ_TRANSFORM:
1818                         event = 15;
1819                         break;
1820                 case SEQ_COLOR:
1821                         event = 16;
1822                         break;
1823                 case SEQ_SPEED:
1824                         event = 17;
1825                         break;
1826                 default:
1827                         event = 0;
1828                         break;
1829                 }
1830         }
1831         else {
1832                 event= pupmenu("Add Sequence Strip%t"
1833                                "|Image Sequence%x1"
1834                                "|Movie%x102"
1835 #ifdef WITH_FFMPEG
1836                                    "|Movie + Audio (HD)%x105"
1837                                "|Audio (RAM)%x103"
1838                                "|Audio (HD)%x104"
1839 #else
1840                                    "|Audio (Wav)%x103"
1841 #endif
1842                                "|Scene%x101"
1843                                "|Plugin%x10"
1844                                "|Cross%x2"
1845                                "|Gamma Cross%x3"
1846                                "|Add%x4"
1847                                "|Sub%x5"
1848                                "|Mul%x6"
1849                                "|Alpha Over%x7"
1850                                "|Alpha Under%x8"
1851                                "|Alpha Over Drop%x9"
1852                                "|Wipe%x13"
1853                                "|Glow%x14"
1854                                "|Transforms%x15"
1855                                "|Color Generator%x16"
1856                                "|Speed Control%x17");
1857         }
1858
1859         if(event<1) return;
1860
1861         if(G.scene->ed==0) {
1862                 ed= G.scene->ed= MEM_callocN( sizeof(Editing), "addseq");
1863                 ed->seqbasep= &ed->seqbase;
1864         }
1865         else ed= G.scene->ed;
1866
1867         switch(event) {
1868         case 1:
1869                 /* Image Dosnt work at the moment - TODO */
1870                 //if(G.qual & LR_CTRLKEY)
1871                 //      activate_imageselect(FILE_SPECIAL, "Select Images", last_imagename, add_image_strips);
1872                 //else
1873                         activate_fileselect(FILE_SPECIAL, "Select Images", last_imagename, add_image_strips);
1874                 break;
1875         case 105:
1876                 activate_fileselect(FILE_SPECIAL, "Select Movie+Audio", last_imagename, add_movie_and_hdaudio_strip);
1877                 break;
1878         case 102:
1879
1880                 activate_fileselect(FILE_SPECIAL, "Select Movie", last_imagename, add_movie_strip);
1881                 break;
1882         case 101:
1883                 /* new menu: */
1884                 IDnames_to_pupstring(&str, NULL, NULL, &G.main->scene, (ID *)G.scene, NULL);
1885
1886                 add_scene_strip(pupmenu_col(str, 20));
1887
1888                 MEM_freeN(str);
1889
1890                 break;
1891         case 2:
1892         case 3:
1893         case 4:
1894         case 5:
1895         case 6:
1896         case 7:
1897         case 8:
1898         case 9:
1899         case 10:
1900         case 13:
1901         case 14:
1902         case 15:
1903         case 16:
1904         case 17:
1905                 if(get_last_seq()==0 && 
1906                    get_sequence_effect_num_inputs( event_to_efftype(event))> 0)
1907                         error("Need at least one active sequence strip");
1908                 else if(event==10)
1909                         activate_fileselect(FILE_SPECIAL, "Select Plugin", U.plugseqdir, load_plugin_seq);
1910                 else
1911                         add_seq_effect(event, NULL);
1912
1913                 break;
1914         case 103:
1915                 if (!last_sounddir[0]) strncpy(last_sounddir, U.sounddir, FILE_MAXDIR-1);
1916                 activate_fileselect(FILE_SPECIAL, "Select Audio (RAM)", last_sounddir, add_sound_strip_ram);
1917                 break;
1918         case 104:
1919                 if (!last_sounddir[0]) strncpy(last_sounddir, U.sounddir, FILE_MAXDIR-1);
1920                 activate_fileselect(FILE_SPECIAL, "Select Audio (HD)", last_sounddir, add_sound_strip_hd);
1921                 break;
1922         }
1923 }
1924
1925 void change_sequence(void)
1926 {
1927         Sequence *last_seq= get_last_seq();
1928         Scene *sce;
1929         short event;
1930
1931         if(last_seq==0) return;
1932
1933         if(last_seq->type & SEQ_EFFECT) {
1934                 event = pupmenu("Change Effect%t"
1935                                 "|Switch A <-> B %x1"
1936                                 "|Switch B <-> C %x10"
1937                                 "|Plugin%x11"
1938                                 "|Recalculate%x12"
1939                                 "|Cross%x2"
1940                                 "|Gamma Cross%x3"
1941                                 "|Add%x4"
1942                                 "|Sub%x5"
1943                                 "|Mul%x6"
1944                                 "|Alpha Over%x7"
1945                                 "|Alpha Under%x8"
1946                                 "|Alpha Over Drop%x9"
1947                                 "|Wipe%x13"
1948                                 "|Glow%x14"
1949                                 "|Transform%x15"
1950                                 "|Color Generator%x16"
1951                                 "|Speed Control%x17");
1952                 if(event > 0) {
1953                         if(event==1) {
1954                                 SWAP(Sequence *,last_seq->seq1,last_seq->seq2);
1955                         }
1956                         else if(event==10) {
1957                                 SWAP(Sequence *,last_seq->seq2,last_seq->seq3);
1958                         }
1959                         else if(event==11) {
1960                                 activate_fileselect(
1961                                         FILE_SPECIAL, "Select Plugin", 
1962                                         U.plugseqdir, change_plugin_seq);
1963                         }
1964                         else if(event==12);     
1965                                 /* recalculate: only new_stripdata */
1966                         else {
1967                                 /* free previous effect and init new effect */
1968                                 struct SeqEffectHandle sh;
1969
1970                                 if (get_sequence_effect_num_inputs(
1971                                             last_seq->type)
1972                                     < get_sequence_effect_num_inputs(
1973                                             event_to_efftype(event))) {
1974                                         error("New effect needs more "
1975                                               "input strips!");
1976                                 } else {
1977                                         sh = get_sequence_effect(last_seq);
1978                                         sh.free(last_seq);
1979                                         
1980                                         last_seq->type 
1981                                                 = event_to_efftype(event);
1982                                         
1983                                         sh = get_sequence_effect(last_seq);
1984                                         sh.init(last_seq);
1985                                 }
1986                         }
1987
1988                         update_changed_seq_and_deps(last_seq, 0, 1);
1989                         allqueue(REDRAWSEQ, 0);
1990                         BIF_undo_push("Change Strip Effect, Sequencer");
1991                 }
1992         }
1993         else if(last_seq->type == SEQ_IMAGE) {
1994                 if(okee("Change images")) {
1995                         activate_fileselect(FILE_SPECIAL, 
1996                                             "Select Images", 
1997                                             last_imagename, 
1998                                             reload_image_strip);
1999                 }
2000         }
2001         else if(last_seq->type == SEQ_MOVIE) {
2002                 ;
2003         }
2004         else if(last_seq->type == SEQ_SCENE) {
2005                 event= pupmenu("Change Scene%t|Update Start and End");
2006
2007                 if(event==1) {
2008                         sce= last_seq->scene;
2009
2010                         last_seq->len= sce->r.efra - sce->r.sfra + 1;
2011                         last_seq->sfra= sce->r.sfra;
2012                         
2013                         /* bad code to change seq->len? update_changed_seq_and_deps() expects the strip->len to be OK */
2014                         new_tstripdata(last_seq);
2015                         
2016                         update_changed_seq_and_deps(last_seq, 1, 1);
2017
2018                         allqueue(REDRAWSEQ, 0);
2019                 }
2020         }
2021
2022 }
2023
2024 void reload_sequence(void)
2025 {
2026         Editing *ed= G.scene->ed;
2027         Sequence *seq;
2028         WHILE_SEQ(ed->seqbasep) {
2029                 if(seq->flag & SELECT) {
2030                         update_changed_seq_and_deps(seq, 0, 1);
2031                 }
2032         }
2033         END_SEQ
2034         allqueue(REDRAWSEQ, 0);
2035 }
2036
2037 void reassign_inputs_seq_effect()
2038 {
2039         Editing *ed= G.scene->ed;
2040         Sequence *seq1, *seq2, *seq3, *last_seq = get_last_seq();
2041
2042         if(last_seq==0 || !(last_seq->type & SEQ_EFFECT)) return;
2043         if(ed==0) return;
2044
2045         if(!seq_effect_find_selected(ed, last_seq, last_seq->type, &seq1, &seq2, &seq3))
2046                 return;
2047
2048         /* see reassigning would create a cycle */
2049         if(seq_is_predecessor(seq1, last_seq) || seq_is_predecessor(seq2, last_seq) ||
2050            seq_is_predecessor(seq3, last_seq)) {
2051                 error("Can't reassign inputs: no cycles allowed");
2052                 return;
2053         }
2054         
2055         last_seq->seq1 = seq1;
2056         last_seq->seq2 = seq2;
2057         last_seq->seq3 = seq3;
2058
2059         update_changed_seq_and_deps(last_seq, 1, 1);
2060
2061         allqueue(REDRAWSEQ, 0);
2062 }
2063
2064 static Sequence *del_seq_find_replace_recurs(Sequence *seq)
2065 {
2066         Sequence *seq1, *seq2, *seq3;
2067
2068         /* try to find a replacement input sequence, and flag for later deletion if
2069            no replacement can be found */
2070
2071         if(!seq)
2072                 return NULL;
2073         else if(!(seq->type & SEQ_EFFECT))
2074                 return ((seq->flag & SELECT)? NULL: seq);
2075         else if(!(seq->flag & SELECT)) {
2076                 /* try to find replacement for effect inputs */
2077                 seq1= del_seq_find_replace_recurs(seq->seq1);
2078                 seq2= del_seq_find_replace_recurs(seq->seq2);
2079                 seq3= del_seq_find_replace_recurs(seq->seq3);
2080
2081                 if(seq1==seq->seq1 && seq2==seq->seq2 && seq3==seq->seq3);
2082                 else if(seq1 || seq2 || seq3) {
2083                         seq->seq1= (seq1)? seq1: (seq2)? seq2: seq3;
2084                         seq->seq2= (seq2)? seq2: (seq1)? seq1: seq3;
2085                         seq->seq3= (seq3)? seq3: (seq1)? seq1: seq2;
2086
2087                         update_changed_seq_and_deps(seq, 1, 1);
2088                 }
2089                 else
2090                         seq->flag |= SELECT; /* mark for delete */
2091         }
2092
2093         if (seq->flag & SELECT) {
2094                 if((seq1 = del_seq_find_replace_recurs(seq->seq1))) return seq1;
2095                 if((seq2 = del_seq_find_replace_recurs(seq->seq2))) return seq2;
2096                 if((seq3 = del_seq_find_replace_recurs(seq->seq3))) return seq3;
2097                 else return NULL;
2098         }
2099         else
2100                 return seq;
2101 }
2102
2103 static void recurs_del_seq_flag(ListBase *lb, short flag, short deleteall)
2104 {
2105         Sequence *seq, *seqn;
2106         Sequence *last_seq = get_last_seq();
2107
2108         seq= lb->first;
2109         while(seq) {
2110                 seqn= seq->next;
2111                 if((seq->flag & flag) || deleteall) {
2112                         if(seq->type==SEQ_RAM_SOUND && seq->sound) 
2113                                 seq->sound->id.us--;
2114
2115                         BLI_remlink(lb, seq);
2116                         if(seq==last_seq) set_last_seq(0);
2117                         if(seq->type==SEQ_META) recurs_del_seq_flag(&seq->seqbase, flag, 1);
2118                         if(seq->ipo) seq->ipo->id.us--;
2119                         free_sequence(seq);
2120                 }
2121                 seq= seqn;
2122         }
2123 }
2124
2125 void del_seq(void)
2126 {
2127         Sequence *seq;
2128         MetaStack *ms;
2129         Editing *ed;
2130
2131         if(okee("Erase selected")==0) return;
2132
2133         ed= G.scene->ed;
2134         if(ed==0) return;
2135
2136         /* free imbufs of all dependent strips */
2137         for(seq=ed->seqbasep->first; seq; seq=seq->next)
2138                 if(seq->flag & SELECT)
2139                         update_changed_seq_and_deps(seq, 1, 0);
2140
2141         /* for effects, try to find a replacement input */
2142         for(seq=ed->seqbasep->first; seq; seq=seq->next)
2143                 if((seq->type & SEQ_EFFECT) && !(seq->flag & SELECT))
2144                         del_seq_find_replace_recurs(seq);
2145
2146         /* delete all selected strips */
2147         recurs_del_seq_flag(ed->seqbasep, SELECT, 0);
2148
2149         /* updates lengths etc */
2150         seq= ed->seqbasep->first;
2151         while(seq) {
2152                 calc_sequence(seq);
2153                 seq= seq->next;
2154         }
2155
2156         /* free parent metas */
2157         ms= ed->metastack.last;
2158         while(ms) {
2159                 ms->parseq->strip->len= 0;              /* force new alloc */
2160                 calc_sequence(ms->parseq);
2161                 ms= ms->prev;
2162         }
2163
2164         BIF_undo_push("Delete Strip(s), Sequencer");
2165         allqueue(REDRAWSEQ, 0);
2166 }
2167
2168 static Sequence *dupli_seq(Sequence *seq) 
2169 {
2170         Sequence *seqn = MEM_dupallocN(seq);
2171
2172         seq->tmp = seqn;
2173                 
2174         seqn->strip= MEM_dupallocN(seq->strip);
2175
2176         if(seqn->ipo) seqn->ipo->id.us++;
2177
2178         seqn->strip->tstripdata = 0;
2179         seqn->strip->tstripdata_startstill = 0;
2180         seqn->strip->tstripdata_endstill = 0;
2181
2182         if (seq->strip->crop) {
2183                 seqn->strip->crop = MEM_dupallocN(seq->strip->crop);
2184         }
2185
2186         if (seq->strip->transform) {
2187                 seqn->strip->transform = MEM_dupallocN(seq->strip->transform);
2188         }
2189
2190         if (seq->strip->proxy) {
2191                 seqn->strip->proxy = MEM_dupallocN(seq->strip->proxy);
2192         }
2193
2194         if (seq->strip->color_balance) {
2195                 seqn->strip->color_balance 
2196                         = MEM_dupallocN(seq->strip->color_balance);
2197         }
2198         
2199         if(seq->type==SEQ_META) {
2200                 seqn->strip->stripdata = 0;
2201
2202                 seqn->seqbase.first= seqn->seqbase.last= 0;
2203                 /* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */
2204                 /* - recurs_dupli_seq(&seq->seqbase,&seqn->seqbase);*/
2205         } else if(seq->type == SEQ_SCENE) {
2206                 seqn->strip->stripdata = 0;
2207         } else if(seq->type == SEQ_MOVIE) {
2208                 seqn->strip->stripdata = 
2209                                 MEM_dupallocN(seq->strip->stripdata);
2210                 seqn->anim= 0;
2211         } else if(seq->type == SEQ_RAM_SOUND) {
2212                 seqn->strip->stripdata = 
2213                                 MEM_dupallocN(seq->strip->stripdata);
2214                 seqn->sound->id.us++;
2215         } else if(seq->type == SEQ_HD_SOUND) {
2216                 seqn->strip->stripdata = 
2217                                 MEM_dupallocN(seq->strip->stripdata);
2218                 seqn->hdaudio = 0;
2219         } else if(seq->type == SEQ_IMAGE) {
2220                 seqn->strip->stripdata = 
2221                                 MEM_dupallocN(seq->strip->stripdata);
2222         } else if(seq->type >= SEQ_EFFECT) {
2223                 if(seq->seq1 && seq->seq1->tmp) seqn->seq1= seq->seq1->tmp;
2224                 if(seq->seq2 && seq->seq2->tmp) seqn->seq2= seq->seq2->tmp;
2225                 if(seq->seq3 && seq->seq3->tmp) seqn->seq3= seq->seq3->tmp;
2226
2227                 if (seq->type & SEQ_EFFECT) {
2228                         struct SeqEffectHandle sh;
2229                         sh = get_sequence_effect(seq);
2230                         if(sh.copy)
2231                                 sh.copy(seq, seqn);
2232                 }
2233
2234                 seqn->strip->stripdata = 0;
2235                 
2236         } else {
2237                 fprintf(stderr, "Aiiiiekkk! sequence type not "
2238                                 "handled in duplicate!\nExpect a crash"
2239                                                 " now...\n");
2240         }
2241         
2242         return seqn;
2243 }
2244
2245 static void recurs_dupli_seq(ListBase *old, ListBase *new)
2246 {
2247         Sequence *seq;
2248         Sequence *seqn = 0;
2249         Sequence *last_seq = get_last_seq();
2250
2251         for(seq= old->first; seq; seq= seq->next) {
2252                 seq->tmp= NULL;
2253                 if(seq->flag & SELECT) {
2254                         seqn = dupli_seq(seq);
2255                         if (seqn) { /*should never fail */
2256                                 seq->flag &= SEQ_DESEL;
2257                                 seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL+SEQ_LOCK);
2258
2259                                 BLI_addtail(new, seqn);
2260                                 if(seq->type==SEQ_META)
2261                                         recurs_dupli_seq(&seq->seqbase,&seqn->seqbase);
2262                                 
2263                                 if (seq == last_seq) {
2264                                         set_last_seq(seqn);
2265                                 }
2266                         }
2267                 }
2268         }
2269 }
2270
2271 /* like duplicate, but only duplicate and cut overlapping strips,
2272  * strips to the left of the cutframe are ignored and strips to the right are moved into the new list */
2273 static void recurs_cut_seq(ListBase *old, ListBase *new, int cutframe)
2274 {
2275         Sequence *seq, *seq_next;
2276         Sequence *seqn = 0;
2277         
2278         TransSeq ts;
2279
2280         seq= old->first;
2281         
2282         while(seq) {
2283                 seq_next = seq->next; /* we need this because we may remove seq */
2284                 
2285                 seq->tmp= NULL;
2286                 if(seq->flag & SELECT) {
2287                         if(cutframe > seq->startdisp && cutframe < seq->enddisp) {
2288                                 
2289                                 /* backup values */
2290                                 ts.start= seq->start;
2291                                 ts.machine= seq->machine;
2292                                 ts.startstill= seq->startstill;
2293                                 ts.endstill= seq->endstill;
2294                                 ts.startdisp= seq->startdisp;
2295                                 ts.enddisp= seq->enddisp;
2296                                 ts.startofs= seq->startofs;
2297                                 ts.endofs= seq->endofs;
2298                                 ts.len= seq->len;
2299                                 
2300                                 /* First Strip! */
2301                                 /* strips with extended stillfames before */
2302                                 if(seq->type!=SEQ_META) {
2303                                         
2304                                         if ((seq->startstill) && (cutframe <seq->start)) {
2305                                                 seq->start= cutframe -1;
2306                                                 seq->startstill= cutframe -seq->startdisp -1;
2307                                                 seq->len= 1;
2308                                                 seq->endstill= 0;
2309                                         }
2310                                 
2311                                         /* normal strip */
2312                                         else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) {
2313                                                 seq->endofs = (seq->start+seq->len) - cutframe;
2314                                         }
2315                                 
2316                                         /* strips with extended stillframes after */
2317                                         else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
2318                                                 seq->endstill -= seq->enddisp - cutframe;
2319                                         }
2320                                         
2321                                         calc_sequence(seq);
2322                                 }
2323                                 
2324                                 /* Duplicate AFTER the first change */
2325                                 seqn = dupli_seq(seq);
2326                                 
2327                                 if (seqn) { /* should never fail */
2328                                         seqn->flag |= SELECT;
2329                                         
2330                                         
2331                                         BLI_addtail(new, seqn);
2332                                         
2333                                         /* dont transform meta's - just do their children then recalc */
2334                                         if(seq->type==SEQ_META) {
2335                                                 recurs_cut_seq(&seq->seqbase,&seqn->seqbase, cutframe);
2336                                         } else {
2337                                                 /* Second Strip! */
2338                                                 /* strips with extended stillframes before */
2339                                                 if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
2340                                                         seqn->start = ts.start;
2341                                                         seqn->startstill= ts.start- cutframe;
2342                                                         seqn->len = ts.len;
2343                                                         seqn->endstill = ts.endstill;
2344                                                 }
2345                         
2346                                                 /* normal strip */
2347                                                 else if ((cutframe>=seqn->start)&&(cutframe<=(seqn->start+seqn->len))) {
2348                                                         seqn->startstill = 0;
2349                                                         seqn->startofs = cutframe - ts.start;
2350                                                         seqn->endofs = ts.endofs;
2351                                                         seqn->endstill = ts.endstill;
2352                                                 }                               
2353                         
2354                                                 /* strips with extended stillframes after */
2355                                                 else if (((seqn->start+seqn->len) < cutframe) && (seqn->endstill)) {
2356                                                         seqn->start = cutframe - ts.len +1;
2357                                                         seqn->startofs = ts.len-1;
2358                                                         seqn->endstill = ts.enddisp - cutframe -1;
2359                                                         seqn->startstill = 0;
2360                                                 }
2361                                         }
2362                                         
2363                                         if(seq->type==SEQ_META) /* account for strips within changing */
2364                                                 calc_sequence(seq);
2365                                         
2366                                         calc_sequence(seqn);
2367                                 }
2368                         } else if (seq->enddisp <= cutframe) {
2369                                 /* do nothing */
2370                         } else if (seq->startdisp >= cutframe) {
2371                                 /* move into new list */
2372                                 BLI_remlink(old, seq);
2373                                 BLI_addtail(new, seq);
2374                         }
2375                 }
2376                 seq = seq_next;
2377         }
2378 }
2379
2380 void seq_cut(int cutframe)
2381 {
2382         Editing *ed;
2383         ListBase newlist;
2384         char side;
2385         ed= G.scene->ed;
2386         if(ed==0) return;
2387         
2388         newlist.first= newlist.last= NULL;
2389         
2390         recurs_cut_seq(ed->seqbasep, &newlist, cutframe);
2391         
2392         if (newlist.first) { /* simple check to see if anything was done */
2393                 Sequence *seq;
2394                 addlisttolist(ed->seqbasep, &newlist);
2395                 
2396                 
2397                 /* change the selection, not strictly needed but nice */
2398                 side = mouse_cfra_side(cutframe);
2399                 
2400                 WHILE_SEQ(ed->seqbasep) {
2401                         if (side=='L') {
2402                                 if ( seq->startdisp >= cutframe ) {
2403                                         seq->flag &= ~SELECT;
2404                                 }
2405                         } else {
2406                                 if ( seq->enddisp <= cutframe ) {
2407                                         seq->flag &= ~SELECT;
2408                                 }
2409                         }
2410                 }
2411                 END_SEQ;
2412                 
2413                 /* as last: */
2414                 sort_seq();
2415                 
2416                 allqueue(REDRAWSEQ, 0);
2417                 BIF_undo_push("Cut Strips, Sequencer");
2418         }
2419 }
2420
2421 void add_duplicate_seq(void)
2422 {
2423         Editing *ed;
2424         ListBase new;
2425
2426         ed= G.scene->ed;
2427         if(ed==0) return;
2428
2429         new.first= new.last= 0;
2430
2431         recurs_dupli_seq(ed->seqbasep, &new);
2432         addlisttolist(ed->seqbasep, &new);
2433
2434         BIF_undo_push("Add Duplicate, Sequencer");
2435         transform_seq_nomarker('g', 0);
2436 }
2437
2438 int insert_gap(int gap, int cfra)
2439 {
2440         Sequence *seq;
2441         Editing *ed;
2442         int done=0;
2443
2444         /* all strips >= cfra are shifted */
2445         ed= G.scene->ed;
2446         if(ed==0) return 0;
2447
2448         WHILE_SEQ(ed->seqbasep) {
2449                 if(seq->startdisp >= cfra) {
2450                         seq->start+= gap;
2451                         calc_sequence(seq);
2452                         done= 1;
2453                 }
2454         }
2455         END_SEQ
2456
2457         return done;
2458 }
2459
2460 void touch_seq_files(void)
2461 {
2462         Sequence *seq;
2463         Editing *ed;
2464         char str[256];
2465
2466         /* touch all strips with movies */
2467         ed= G.scene->ed;
2468         if(ed==0) return;
2469
2470         if(okee("Touch and print selected movies")==0) return;
2471
2472         waitcursor(1);
2473
2474         WHILE_SEQ(ed->seqbasep) {
2475                 if(seq->flag & SELECT) {
2476                         if(seq->type==SEQ_MOVIE) {
2477                                 if(seq->strip && seq->strip->stripdata) {
2478                                         BLI_make_file_string(G.sce, str, seq->strip->dir, seq->strip->stripdata->name);
2479                                         BLI_touch(seq->name);
2480                                 }
2481                         }
2482
2483                 }
2484         }
2485         END_SEQ
2486
2487         waitcursor(0);
2488 }
2489
2490 void set_filter_seq(void)
2491 {
2492         Sequence *seq;
2493         Editing *ed;
2494
2495         ed= G.scene->ed;
2496         if(ed==0) return;
2497
2498         if(okee("Set FilterY")==0) return;
2499
2500         WHILE_SEQ(ed->seqbasep) {
2501                 if(seq->flag & SELECT) {
2502                         if(seq->type==SEQ_MOVIE) {
2503                                 seq->flag |= SEQ_FILTERY;
2504                         }
2505
2506                 }
2507         }
2508         END_SEQ
2509
2510 }
2511
2512 void seq_remap_paths(void)
2513 {
2514         Sequence *seq, *last_seq = get_last_seq();
2515         Editing *ed;
2516         char from[FILE_MAX], to[FILE_MAX], stripped[FILE_MAX];
2517         
2518         ed= G.scene->ed;
2519         if(ed==NULL || last_seq==NULL) 
2520                 return;
2521         
2522         BLI_strncpy(from, last_seq->strip->dir, FILE_MAX);
2523         if (0==sbutton(from, 0, sizeof(from)-1, "From: "))
2524                 return;
2525         
2526         strcpy(to, from);
2527         if (0==sbutton(to, 0, sizeof(to)-1, "To: "))
2528                 return;
2529         
2530         if (strcmp(to, from)==0)
2531                 return;
2532         
2533         WHILE_SEQ(ed->seqbasep) {
2534                 if(seq->flag & SELECT) {
2535                         if(strncmp(seq->strip->dir, from, strlen(from))==0) {
2536                                 printf("found %s\n", seq->strip->dir);
2537                                 
2538                                 /* strip off the beginning */
2539                                 stripped[0]= 0;
2540                                 BLI_strncpy(stripped, seq->strip->dir + strlen(from), FILE_MAX);
2541                                 
2542                                 /* new path */
2543                                 BLI_strncpy(seq->strip->dir, to, FILE_MAX);
2544                                 strcat(seq->strip->dir, stripped);
2545                                 printf("new %s\n", seq->strip->dir);
2546                         }
2547                 }
2548         }
2549         END_SEQ
2550                 
2551         BIF_undo_push("Remap Paths, Sequencer");
2552         allqueue(REDRAWSEQ, 0);
2553 }
2554
2555
2556 void no_gaps(void)
2557 {
2558         Editing *ed;
2559         int cfra, first= 0, done;
2560
2561         ed= G.scene->ed;
2562         if(ed==0) return;
2563
2564         for(cfra= CFRA; cfra<=EFRA; cfra++) {
2565                 if(first==0) {
2566                         if( evaluate_seq_frame(cfra) ) first= 1;
2567                 }
2568                 else {
2569                         done= 1;
2570                         while( evaluate_seq_frame(cfra) == 0) {
2571                                 done= insert_gap(-1, cfra);
2572                                 if(done==0) break;
2573                         }
2574                         if(done==0) break;
2575                 }
2576         }
2577
2578         BIF_undo_push("No Gaps, Sequencer");
2579         allqueue(REDRAWSEQ, 0);
2580 }
2581
2582
2583 /* ****************** META ************************* */
2584
2585 void make_meta(void)
2586 {
2587         Sequence *seq, *seqm, *next;
2588         Editing *ed;
2589         int tot;
2590         
2591         ed= G.scene->ed;
2592         if(ed==0) return;
2593
2594         /* is there more than 1 select */
2595         tot= 0;
2596         seq= ed->seqbasep->first;
2597         while(seq) {
2598                 if(seq->flag & SELECT) {
2599                         tot++;
2600                         if (seq->type == SEQ_RAM_SOUND) { 
2601                                 error("Can't make Meta Strip from audio"); 
2602                                 return; 
2603                         }
2604                 }
2605                 seq= seq->next;
2606         }
2607         if(tot < 1) return;
2608
2609         if(okee("Make Meta Strip")==0) return;
2610
2611         /* test relationships */
2612         seq= ed->seqbasep->first;
2613         while(seq) {
2614                 if(seq->flag & SELECT) {
2615                         if(seq->type & SEQ_EFFECT) {
2616                                 if(seq->seq1 && 
2617                                    (seq->seq1->flag & SELECT)==0) tot= 0;
2618                                 if(seq->seq2 &&
2619                                    (seq->seq2->flag & SELECT)==0) tot= 0;
2620                                 if(seq->seq3 &&
2621                                    (seq->seq3->flag & SELECT)==0) tot= 0;
2622                         }
2623                 }
2624                 else if(seq->type & SEQ_EFFECT) {
2625                         if(seq->seq1 &&
2626                            (seq->seq1->flag & SELECT)) tot= 0;
2627                         if(seq->seq2 &&
2628                            (seq->seq2->flag & SELECT)) tot= 0;
2629                         if(seq->seq3 &&
2630                            (seq->seq3->flag & SELECT)) tot= 0;
2631                 }
2632                 if(tot==0) break;
2633                 seq= seq->next;
2634         }
2635         if(tot==0) {
2636                 error("Please select all related strips");
2637                 return;
2638         }
2639
2640         /* remove all selected from main list, and put in meta */
2641
2642         seqm= alloc_sequence(((Editing *)G.scene->ed)->seqbasep, 1, 1);
2643         seqm->type= SEQ_META;
2644         seqm->flag= SELECT;
2645
2646         seq= ed->seqbasep->first;
2647         while(seq) {
2648                 next= seq->next;
2649                 if(seq!=seqm && (seq->flag & SELECT)) {
2650                         BLI_remlink(ed->seqbasep, seq);
2651                         BLI_addtail(&seqm->seqbase, seq);
2652                 }
2653                 seq= next;
2654         }
2655         calc_sequence(seqm);
2656
2657         seqm->strip= MEM_callocN(sizeof(Strip), "metastrip");
2658         seqm->strip->len= seqm->len;
2659         seqm->strip->us= 1;
2660
2661         set_meta_stripdata(seqm);
2662         
2663         if( test_overlap_seq(seqm) ) shuffle_seq(seqm);
2664         
2665         BIF_undo_push("Make Meta Strip, Sequencer");
2666         allqueue(REDRAWSEQ, 0);
2667 }
2668
2669 static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
2670 {
2671         if (seq == seqm) return 1;
2672         else if (seq->seq1 && seq_depends_on_meta(seq->seq1, seqm)) return 1;
2673         else if (seq->seq2 && seq_depends_on_meta(seq->seq2, seqm)) return 1;
2674         else if (seq->seq3 && seq_depends_on_meta(seq->seq3, seqm)) return 1;
2675         else return 0;
2676 }
2677
2678 void un_meta(void)
2679 {
2680         Editing *ed;
2681         Sequence *seq, *last_seq = get_last_seq();
2682
2683         ed= G.scene->ed;
2684         if(ed==0) return;
2685
2686         if(last_seq==0 || last_seq->type!=SEQ_META) return;
2687
2688         if(okee("Un Meta Strip")==0) return;
2689
2690         addlisttolist(ed->seqbasep, &last_seq->seqbase);
2691
2692         last_seq->seqbase.first= 0;
2693         last_seq->seqbase.last= 0;
2694
2695         BLI_remlink(ed->seqbasep, last_seq);
2696         free_sequence(last_seq);
2697
2698         /* emtpy meta strip, delete all effects depending on it */
2699         for(seq=ed->seqbasep->first; seq; seq=seq->next)
2700                 if((seq->type & SEQ_EFFECT) && seq_depends_on_meta(seq, last_seq))
2701                         seq->flag |= SEQ_FLAG_DELETE;
2702
2703         recurs_del_seq_flag(ed->seqbasep, SEQ_FLAG_DELETE, 0);
2704
2705         /* test for effects and overlap */
2706         WHILE_SEQ(ed->seqbasep) {
2707                 if(seq->flag & SELECT) {
2708                         seq->flag &= ~SEQ_OVERLAP;
2709                         if( test_overlap_seq(seq) ) {
2710                                 shuffle_seq(seq);
2711                         }
2712                 }
2713         }
2714         END_SEQ;
2715
2716         sort_seq();
2717
2718         BIF_undo_push("Un-Make Meta Strip, Sequencer");
2719         allqueue(REDRAWSEQ, 0);
2720
2721 }
2722
2723 void exit_meta(void)
2724 {
2725         Sequence *seq;
2726         MetaStack *ms;
2727         Editing *ed;
2728
2729         ed= G.scene->ed;
2730         if(ed==0) return;
2731
2732         if(ed->metastack.first==0) return;
2733
2734         ms= ed->metastack.last;
2735         BLI_remlink(&ed->metastack, ms);
2736
2737         ed->seqbasep= ms->oldbasep;
2738
2739         /* recalc entire meta */
2740         set_meta_stripdata(ms->parseq);
2741
2742         /* recalc all: the meta can have effects connected to it */
2743         seq= ed->seqbasep->first;
2744         while(seq) {
2745                 calc_sequence(seq);
2746                 seq= seq->next;
2747         }
2748
2749         set_last_seq(ms->parseq);
2750
2751         ms->parseq->flag |= SELECT;
2752         recurs_sel_seq(ms->parseq);
2753
2754         MEM_freeN(ms);
2755         allqueue(REDRAWSEQ, 0);
2756
2757         BIF_undo_push("Exit Meta Strip, Sequence");
2758 }
2759
2760
2761 void enter_meta(void)
2762 {
2763         MetaStack *ms;
2764         Editing *ed;
2765         Sequence *last_seq= get_last_seq();
2766
2767         ed= G.scene->ed;
2768         if(ed==0) return;
2769
2770         if(last_seq==0 || last_seq->type!=SEQ_META || last_seq->flag==0) {
2771                 exit_meta();
2772                 return;
2773         }
2774
2775         ms= MEM_mallocN(sizeof(MetaStack), "metastack");
2776         BLI_addtail(&ed->metastack, ms);
2777         ms->parseq= last_seq;
2778         ms->oldbasep= ed->seqbasep;
2779
2780         ed->seqbasep= &last_seq->seqbase;
2781
2782         set_last_seq(NULL);
2783         allqueue(REDRAWSEQ, 0);
2784         BIF_undo_push("Enter Meta Strip, Sequence");
2785 }
2786
2787
2788 /* ****************** END META ************************* */
2789
2790 static int seq_get_snaplimit(void)
2791 {
2792         /* fake mouse coords to get the snap value
2793         a bit lazy but its only done once pre transform */
2794         float xmouse, ymouse, x;
2795         short mval[2] = {24, 0}; /* 24 screen px snap */
2796         areamouseco_to_ipoco(G.v2d, mval, &xmouse, &ymouse);
2797         x = xmouse;
2798         mval[0] = 0;
2799         areamouseco_to_ipoco(G.v2d, mval, &xmouse, &ymouse);
2800         return (int)(x - xmouse);
2801 }
2802
2803 /* use to impose limits when dragging/extending - so impossible situations dont happen */
2804 static void transform_grab_xlimits(Sequence *seq, int leftflag, int rightflag)
2805 {
2806         if(leftflag) {
2807                 if (seq_tx_get_final_left(seq) >= seq_tx_get_final_right(seq)) {
2808                         seq_tx_set_final_left(seq, seq_tx_get_final_right(seq)-1);
2809                 }
2810                 
2811                 if (check_single_seq(seq)==0) {
2812                         if (seq_tx_get_final_left(seq) >= seq_tx_get_end(seq)) {
2813                                 seq_tx_set_final_left(seq, seq_tx_get_end(seq)-1);
2814                         }
2815                         
2816                         /* dosnt work now - TODO */
2817                         /*
2818                         if (seq_tx_get_start(seq) >= seq_tx_get_final_right(seq)) {
2819                                 int ofs;
2820                                 ofs = seq_tx_get_start(seq) - seq_tx_get_final_right(seq);
2821                                 seq->start -= ofs;
2822                                 seq_tx_set_final_left(seq, seq_tx_get_final_left(seq) + ofs );
2823                         }*/
2824                         
2825                 }
2826         }
2827         
2828         if(rightflag) {
2829                 if (seq_tx_get_final_right(seq) <=  seq_tx_get_final_left(seq)) {
2830                         seq_tx_set_final_right(seq, seq_tx_get_final_left(seq)+1);
2831                 }
2832                                                                         
2833                 if (check_single_seq(seq)==0) {
2834                         if (seq_tx_get_final_right(seq) <= seq_tx_get_start(seq)) {
2835                                 seq_tx_set_final_right(seq, seq_tx_get_start(seq)+1);
2836                         }
2837                 }
2838         }
2839         
2840         /* sounds cannot be extended past their endpoints */
2841         if (seq->type == SEQ_RAM_SOUND || seq->type == SEQ_HD_SOUND) {
2842                 seq->startstill= 0;
2843                 seq->endstill= 0;
2844         }
2845 }
2846
2847 static int can_transform_seq_test_func(Sequence * seq)
2848 {
2849         if((seq->flag & SELECT) && !(seq->depth==0 && seq->flag & SEQ_LOCK)) {
2850                 return BUILD_SEQAR_COUNT_CURRENT | BUILD_SEQAR_COUNT_CHILDREN;
2851         }
2852         if ((seq->depth==0 && seq->flag & SEQ_LOCK) && !(seq->type & SEQ_EFFECT)) {
2853                 if (seq->type != SEQ_META) {
2854                         return BUILD_SEQAR_COUNT_NOTHING;
2855                 } else {
2856                         return BUILD_SEQAR_COUNT_CURRENT;
2857                 }
2858         }
2859         return BUILD_SEQAR_COUNT_CURRENT | BUILD_SEQAR_COUNT_CHILDREN;
2860 }
2861
2862 void transform_seq(int mode, int context)
2863 {
2864         SpaceSeq *sseq= curarea->spacedata.first;
2865         Sequence *seq, *last_seq;
2866         Editing *ed;
2867         float dx, dy, dvec[2], div;
2868         TransSeq *transmain, *ts;
2869         int totstrip=0, firsttime=1, afbreek=0, midtog= 0, proj= 0;
2870         int ix, iy; /* these values are used for storing the mouses offset from its original location */
2871         int ix_old = 0;
2872         unsigned short event = 0;
2873         short mval[2], val, xo, yo, xn, yn;
2874         char str[32];
2875         char side= 'L'; /* for extend mode only - use to know which side to extend on */
2876         char marker_moved=0; /* if we mvoed a marker, redraw all marker views */
2877         /* used for extend in a number of places */
2878         int cfra = CFRA;
2879         
2880         /* for snapping */
2881         char snapskip = 0, snap, snap_old= 0;
2882         int snapdist_max = seq_get_snaplimit();
2883         /* at the moment there are only 4 possible snap points,
2884         -       last_seq (start,end)
2885         -       selected bounds (start/end)
2886         -       last_seq (next/prev)
2887         -       current frame */
2888         int snap_points[4], snap_point_num = 0;
2889         int j; /* loop on snap_points */
2890         
2891         /* for markers */
2892         int *oldframe = NULL, totmark=0, a;
2893         TimeMarker *marker;
2894         
2895         /* looping on sequences, WHILE_SEQ macro allocates memory each time */
2896         int totseq_index, seq_index; 
2897         Sequence **seqar = 0;
2898         
2899         if(mode!='g' && mode!='e') return;      /* from gesture */
2900
2901         /* which seqs are involved */
2902         ed= G.scene->ed;
2903         if(ed==0) return;
2904
2905         /* Build the sequence array once, be sure to free it */
2906         build_seqar_cb( ed->seqbasep,  &seqar, &totseq_index, 
2907                         can_transform_seq_test_func );
2908         
2909         if (seqar) {
2910                 for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) {
2911                         if((seq->flag & SELECT) && !(seq->depth==0 && seq->flag & SEQ_LOCK)) 
2912                                 totstrip++;
2913                 }
2914         }
2915         
2916         if (sseq->flag & SEQ_MARKER_TRANS) {
2917                 for(marker= G.scene->markers.first; marker; marker= marker->next) {
2918                         if(marker->flag & SELECT) totmark++;
2919                 }
2920         }
2921         
2922         if(totstrip==0 && totmark==0) {
2923                 if(seqar) MEM_freeN(seqar);
2924                 return;
2925         }
2926
2927         G.moving= 1;
2928         
2929         last_seq = get_last_seq();
2930         
2931         ts=transmain= MEM_callocN(totstrip*sizeof(TransSeq), "transseq");
2932
2933         for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) {
2934                 if((seq->flag & SELECT) && !(seq->depth==0 && seq->flag & SEQ_LOCK)) {
2935                         ts->start= seq->start;
2936                         ts->machine= seq->machine;
2937                         ts->startstill= seq->startstill;
2938                         ts->endstill= seq->endstill;
2939                         ts->startofs= seq->startofs;
2940                         ts->endofs= seq->endofs;
2941                         
2942                         /* for extend only */
2943                         if (mode=='e') {
2944                                 ts->final_left = seq_tx_get_final_left(seq);
2945                                 ts->final_right = seq_tx_get_final_right(seq);
2946                         }
2947                         ts++;
2948                 }
2949         }
2950         
2951         getmouseco_areawin(mval);
2952         
2953         /* choose the side based on which side of the playhead the mouse is on */
2954         if (mode=='e')
2955                 side = mouse_cfra_side(cfra);
2956         
2957         /* Markers */
2958         if (sseq->flag & SEQ_MARKER_TRANS && totmark) {
2959                 oldframe= MEM_mallocN(totmark*sizeof(int), "marker array");
2960                 for(a=0, marker= G.scene->markers.first; marker; marker= marker->next) {
2961                         if(marker->flag & SELECT) {
2962                                 if (mode=='e') {
2963                                         
2964                                         /* when extending, invalidate markers on the other side by using an invalid frame value */
2965                                         if ((side == 'L' && marker->frame > cfra) || (side == 'R' && marker->frame < cfra)) {
2966                                                 oldframe[a] = MAXFRAME+1;
2967                                         } else {
2968                                                 oldframe[a]= marker->frame;
2969                                         }
2970                                 } else {
2971                                         oldframe[a]= marker->frame;
2972                                 }
2973                                 a++;
2974                         }
2975                 }
2976         }
2977         
2978         xo=xn= mval[0];
2979         yo=yn= mval[1];
2980         dvec[0]= dvec[1]= 0.0;
2981
2982         while(afbreek==0) {
2983                 getmouseco_areawin(mval);
2984                 G.qual = get_qual();
2985                 snap = (G.qual & LR_CTRLKEY) ? 1 : 0;
2986                 
2987                 if(mval[0]!=xo || mval[1]!=yo || firsttime || snap != snap_old) {
2988                         if (firsttime) {
2989                                 snap_old = snap;
2990                                 firsttime= 0;
2991                         }
2992                         
2993                         /* run for either grab or extend */
2994                         dx= mval[0]- xo;
2995                         dy= mval[1]- yo;
2996
2997                         div= G.v2d->mask.xmax-G.v2d->mask.xmin;
2998                         dx= (G.v2d->cur.xmax-G.v2d->cur.xmin)*(dx)/div;
2999
3000                         div= G.v2d->mask.ymax-G.v2d->mask.ymin;
3001                         dy= (G.v2d->cur.ymax-G.v2d->cur.ymin)*(dy)/div;
3002
3003                         if(G.qual & LR_SHIFTKEY) {
3004                                 if(dx>1.0) dx= 1.0; else if(dx<-1.0) dx= -1.0;
3005                         }
3006
3007                         dvec[0]+= dx;
3008                         dvec[1]+= dy;
3009
3010                         if(midtog) dvec[proj]= 0.0;
3011                         ix= floor(dvec[0]+0.5);
3012                         iy= floor(dvec[1]+0.5);
3013                         
3014                         ts= transmain;
3015                         
3016                         /* SNAP! use the active Seq */
3017                         snap = G.qual & LR_CTRLKEY ? 1 : 0;
3018                         
3019                         if (!snap) {
3020                                 snapskip = 0;
3021                         } else {
3022                                 int dist;
3023                                 int snap_ofs= 0;
3024                                 int snap_dist= snapdist_max;
3025                                 
3026                                 /* Get sequence points to snap to the markers */
3027                                 
3028                                 snap_point_num=0;
3029                                 if (last_seq && (last_seq->flag & SELECT)) { /* active seq bounds */
3030                                         if(seq_tx_check_left(last_seq))
3031                                                 snap_points[snap_point_num++] = seq_tx_get_final_left(last_seq);
3032                                         if(seq_tx_check_right(last_seq))
3033                                                 snap_points[snap_point_num++] = seq_tx_get_final_right(last_seq);
3034                                         
3035                                 }
3036                                 if (totstrip > 1) { /* selection bounds */
3037                                         int bounds_left = MAXFRAME*2;
3038                                         int bounds_right = -(MAXFRAME*2);
3039                                         
3040                                         for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) {
3041                                                 if(seq->flag & SELECT) {
3042                                                         if(seq_tx_check_left(seq))
3043                                                                 bounds_left             = MIN2(bounds_left,     seq_tx_get_final_left(seq));
3044                                                         if(seq_tx_check_right(seq))
3045                                                                 bounds_right    = MAX2(bounds_right,seq_tx_get_final_right(seq));
3046                                                 }
3047                                         }
3048                                         
3049                                         /* its possible there were no points to set on either side */
3050                                         if (bounds_left != MAXFRAME*2)
3051                                                 snap_points[snap_point_num++] = bounds_left;
3052                                         if (bounds_right != -(MAXFRAME*2))
3053                                                 snap_points[snap_point_num++] = bounds_right;
3054                                 }
3055                                 
3056                                 
3057                                 /* Define so we can snap to other points without hassle */
3058                                 
3059 #define TESTSNAP(test_frame)\
3060                                 for(j=0; j<snap_point_num; j++) {\
3061                                         /* see if this beats the current best snap point */\
3062                                         dist = abs(snap_points[j] - test_frame);\
3063                                         if (dist < snap_dist) {\
3064                                                 snap_ofs = test_frame - snap_points[j];\
3065                                                 snap_dist = dist;\
3066                                         }\
3067                                 }
3068                                 
3069                                 
3070                                 /* Detect the best marker to snap to! */
3071                                 for(a=0, marker= G.scene->markers.first; marker; a++, marker= marker->next) {
3072                                         
3073                                         /* dont snap to a marker on the wrong extend side */
3074                                         if (mode=='e' && ((side == 'L' && marker->frame > cfra) || (side == 'R' && marker->frame < cfra)))
3075                                                 continue;
3076                                         
3077                                         /* when we are moving markers, dont snap to selected markers, durr */
3078                                         if ((sseq->flag & SEQ_MARKER_TRANS)==0 || (marker->flag & SELECT)==0) {
3079                                                 
3080                                                 /* loop over the sticky points - max 4 */
3081                                                 TESTSNAP(marker->frame);
3082                                                 if (snap_dist == 0) break; /* alredy snapped? - stop looking */
3083                                         }
3084                                 }
3085                                 
3086                                 if (snap_dist) {
3087                                         TESTSNAP(cfra);
3088                                 }
3089                                 
3090                                 /* check seq's next to the active also - nice for quick snapping */
3091                                 if (snap_dist && last_seq && seq_tx_check_left(last_seq)) {
3092                                         seq = find_next_prev_sequence(last_seq, 1, 0); /* left */
3093                                         if(seq && !seq_tx_check_right(seq))
3094                                                 TESTSNAP(seq_tx_get_final_right(seq));
3095                                 }
3096                                 
3097                                 if (snap_dist && last_seq && seq_tx_check_right(last_seq)) {
3098                                         seq = find_next_prev_sequence(last_seq, 2, 0); /* right */
3099                                         if(seq && !seq_tx_check_left(seq))
3100                                                 TESTSNAP(seq_tx_get_final_left(seq));
3101                                 }
3102
3103 #undef TESTSNAP
3104
3105                                 if (abs(ix_old-ix) >= snapdist_max) {
3106                                         /* mouse has moved out of snap range */
3107                                         snapskip = 0;
3108                                 } else if (snap_dist==0) {
3109                                         /* nowhere to move, dont do anything */
3110                                         snapskip = 1;
3111                                 } else if (snap_dist < snapdist_max) {
3112                                         /* do the snapping by adjusting the mouse offset value */
3113                                         ix = ix_old + snap_ofs;
3114                                 }
3115                         }
3116                         
3117                         if (mode=='g' && !snapskip) {
3118                                 /* Grab */
3119                                 for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) {
3120                                         if(seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK)) {
3121                                                 int myofs;
3122                                                 // SEQ_DEBUG_INFO(seq);
3123                                                 
3124                                                 /* X Transformation */
3125                                                 if(seq->flag & SEQ_LEFTSEL) {
3126                                                         myofs = (ts->startofs - ts->startstill);
3127                                                         seq_tx_set_final_left(seq, ts->start + (myofs + ix));
3128                                                 }
3129                                                 if(seq->flag & SEQ_RIGHTSEL) {
3130                                                         myofs = (ts->endstill - ts->endofs);
3131                                                         seq_tx_set_final_right(seq, ts->start + seq->len + (myofs + ix));
3132                                                 }
3133                                                 transform_grab_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
3134                                                 
3135                                                 if( (seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))==0 ) {
3136                                                         if(sequence_is_free_transformable(seq)) seq->start= ts->start+ ix;
3137
3138                                                         /* Y Transformation */
3139                                                         if(seq->depth==0) seq->machine= ts->machine+ iy;
3140
3141                                                         if(seq->machine<1) seq->machine= 1;
3142                                                         else if(seq->machine>= MAXSEQ) seq->machine= MAXSEQ;
3143                                                 }
3144                                                 calc_sequence(seq);
3145                                                 ts++;
3146                                         }
3147                                 }
3148                                 
3149                                 /* Markers */
3150                                 if (sseq->flag & SEQ_MARKER_TRANS) {
3151                                         for(a=0, marker= G.scene->markers.first; marker; marker= marker->next) {
3152                                                 if(marker->flag & SELECT) {
3153                                                         marker->frame= oldframe[a] + ix;
3154                                                         marker_moved=1;
3155                                                         a++;
3156                                                 }
3157                                         }
3158                                 }
3159                         
3160                         /* Extend, grabs one side of the current frame */
3161                         } else if (mode=='e' && !snapskip) {
3162                                 int myofs; /* offset from start of the seq clip */
3163                                 int xnew, final_left, final_right; /* just to store results from seq_tx_get_final_left/right */
3164                                 
3165                                 /* we dont use seq side selection flags for this,
3166                                 instead we need to calculate which sides to move
3167                                 based on its initial position from the cursor */
3168                                 int move_left, move_right;
3169                                 
3170                                 /* Extend, Similar to grab but operate on one side of the cursor */
3171                                 for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) {
3172                                         if(seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK)) {
3173                                                 /* only move the contents of the metastrip otherwise the transformation is applied twice */
3174                                                 if (sequence_is_free_transformable(seq) && seq->type != SEQ_META) {
3175                                                         
3176                                                         move_left = move_right = 0;
3177                                                         
3178                                                         //SEQ_DEBUG_INFO(seq);
3179                                                         
3180                                                         final_left =    seq_tx_get_final_left(seq);
3181                                                         final_right =   seq_tx_get_final_right(seq);
3182                                                         
3183                                                         /* Only X Axis moving */
3184                                                         
3185                                                         /* work out which sides to move first */
3186                                                         if (side=='L') {
3187                                                                 if (final_left <= cfra || ts->final_left <= cfra)       move_left = 1;
3188                                                                 if (final_right <= cfra || ts->final_right <= cfra)     move_right = 1;
3189                                                         } else {
3190                                                                 if (final_left >= cfra || ts->final_left >= cfra)       move_left = 1;
3191                                                                 if (final_right >= cfra || ts->final_right >= cfra)     move_right = 1;
3192                                                         }
3193                                                         
3194                                                         if (move_left && move_right) {
3195                                                                 /* simple move - dont need to do anything complicated */
3196                                                                 seq->start= ts->start+ ix;
3197                                                         } else {
3198                                                                 if (side=='L') {
3199                                                                         if (move_left) {
3200                                                                                 
3201                                                                                 /* Similar to other funcs */
3202                                                                                 myofs = (ts->startofs - ts->startstill);
3203                                                                                 xnew = ts->start + (ix + myofs);
3204                                                                                 
3205                                                                                 /* make sure the we dont resize down to 0 or less in size
3206                                                                                 also include the startstill so the contense dosnt go outside the bounds, 
3207                                                                                 if the seq->startofs is 0 then its ignored */
3208                                                                                 
3209                                                                                 /* TODO remove, add check to transform_grab_xlimits, works ok for now */
3210                                                                                 if (xnew + seq->startstill > final_right-1) {
3211                                                                                         xnew = (final_right-1) - seq->startstill;
3212                                                                                 }
3213                                                                                 /* Note, this is the only case where the start needs to be adjusted
3214                                                                                 since its not needed when modifying the end or when moving the entire sequence  */
3215                                                                                 //seq->start = ts->start+ix;   // This works when xnew is not clamped, line below takes clamping into account
3216                                                                                 seq->start= xnew - myofs;  /* TODO see above */
3217                                                                                 /* done with unique stuff */
3218                                                                                 
3219                                                                                 seq_tx_set_final_left(seq, xnew);
3220 &nbs