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