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