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