fix [#28880] relative paths don't work with Change Path/Files
[blender.git] / source / blender / editors / space_sequencer / sequencer_edit.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 /** \file blender/editors/space_sequencer/sequencer_edit.c
29  *  \ingroup spseq
30  */
31
32
33 #include <stdlib.h>
34 #include <math.h>
35 #include <string.h>
36
37 #ifndef WIN32
38 #include <unistd.h>
39 #else
40 #include <io.h>
41 #endif
42 #include <sys/types.h>
43
44 #include "MEM_guardedalloc.h"
45
46 #include "BLI_blenlib.h"
47 #include "BLI_math.h"
48 #include "BLI_storage_types.h"
49 #include "BLI_utildefines.h"
50 #include "BLI_threads.h"
51
52 #include "DNA_scene_types.h"
53 #include "DNA_userdef_types.h"
54
55 #include "BKE_context.h"
56 #include "BKE_global.h"
57 #include "BKE_main.h"
58 #include "BKE_sequencer.h"
59 #include "BKE_report.h"
60 #include "BKE_sound.h"
61
62 #include "WM_api.h"
63 #include "WM_types.h"
64
65 #include "RNA_define.h"
66 #include "RNA_enum_types.h"
67
68 /* for menu/popup icons etc etc*/
69
70 #include "ED_screen.h"
71 #include "ED_transform.h"
72 #include "ED_sequencer.h"
73
74 #include "UI_view2d.h"
75
76 /* own include */
77 #include "sequencer_intern.h"
78
79 static int okee(const char *UNUSED(dummy)) {return 0;}
80
81
82 /* XXX */
83 /* RNA Enums, used in multiple files */
84 EnumPropertyItem sequencer_prop_effect_types[] = {
85         {SEQ_CROSS, "CROSS", 0, "Crossfade", "Crossfade effect strip type"},
86         {SEQ_ADD, "ADD", 0, "Add", "Add effect strip type"},
87         {SEQ_SUB, "SUBTRACT", 0, "Subtract", "Subtract effect strip type"},
88         {SEQ_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", "Alpha Over effect strip type"},
89         {SEQ_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", "Alpha Under effect strip type"},
90         {SEQ_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", "Gamma Cross effect strip type"},
91         {SEQ_MUL, "MULTIPLY", 0, "Multiply", "Multiply effect strip type"},
92         {SEQ_OVERDROP, "OVER_DROP", 0, "Alpha Over Drop", "Alpha Over Drop effect strip type"},
93         {SEQ_PLUGIN, "PLUGIN", 0, "Plugin", "Plugin effect strip type"},
94         {SEQ_WIPE, "WIPE", 0, "Wipe", "Wipe effect strip type"},
95         {SEQ_GLOW, "GLOW", 0, "Glow", "Glow effect strip type"},
96         {SEQ_TRANSFORM, "TRANSFORM", 0, "Transform", "Transform effect strip type"},
97         {SEQ_COLOR, "COLOR", 0, "Color", "Color effect strip type"},
98         {SEQ_SPEED, "SPEED", 0, "Speed", "Color effect strip type"},
99         {SEQ_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
100         {SEQ_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
101         {0, NULL, 0, NULL, NULL}
102 };
103
104 /* mute operator */
105
106 EnumPropertyItem prop_side_types[] = {
107         {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""},
108         {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
109         {SEQ_SIDE_BOTH, "BOTH", 0, "Both", ""},
110         {0, NULL, 0, NULL, NULL}
111 };
112
113 static EnumPropertyItem prop_side_lr_types[] = {
114         {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""},
115         {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
116         {0, NULL, 0, NULL, NULL}
117 };
118
119 typedef struct TransSeq {
120         int start, machine;
121         int startstill, endstill;
122         int startdisp, enddisp;
123         int startofs, endofs;
124         int anim_startofs, anim_endofs;
125         /* int final_left, final_right; */ /* UNUSED */
126         int len;
127 } TransSeq;
128
129 /* ********************************************************************** */
130
131 /* ***************** proxy job manager ********************** */
132
133 typedef struct ProxyBuildJob {
134         Scene *scene; 
135         struct Main * main;
136         ListBase queue;
137         ThreadMutex queue_lock;
138 } ProxyJob;
139
140 static void proxy_freejob(void *pjv)
141 {
142         ProxyJob *pj= pjv;
143         Sequence * seq;
144
145         for (seq = pj->queue.first; seq; seq = seq->next) {
146                 BLI_remlink(&pj->queue, seq);
147                 seq_free_sequence_recurse(pj->scene, seq);
148         }
149
150         BLI_mutex_end(&pj->queue_lock);
151
152         MEM_freeN(pj);
153 }
154
155 /* only this runs inside thread */
156 static void proxy_startjob(void *pjv, short *stop, short *do_update, float *progress)
157 {
158         ProxyJob *pj = pjv;
159
160         while (!*stop) {
161                 Sequence * seq;
162
163                 BLI_mutex_lock(&pj->queue_lock);
164                 
165                 if (!pj->queue.first) {
166                         BLI_mutex_unlock(&pj->queue_lock);
167                         break;
168                 }
169
170                 seq = pj->queue.first;
171
172                 BLI_remlink(&pj->queue, seq);
173                 BLI_mutex_unlock(&pj->queue_lock);
174
175                 seq_proxy_rebuild(pj->main, pj->scene, seq, 
176                                   stop, do_update, progress);
177                 seq_free_sequence_recurse(pj->scene, seq);
178         }
179
180         if (*stop) {
181                 fprintf(stderr, 
182                         "Canceling proxy rebuild on users request...\n");
183         }
184 }
185
186 static void proxy_endjob(void *UNUSED(customdata))
187 {
188
189 }
190
191 static void seq_proxy_build_job(const bContext *C, Sequence * seq)
192 {
193         wmJob * steve;
194         ProxyJob *pj;
195         Scene *scene= CTX_data_scene(C);
196         ScrArea * sa= CTX_wm_area(C);
197
198         seq = seq_dupli_recursive(scene, scene, seq, 0);
199
200         steve = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), 
201                             sa, "Building Proxies", WM_JOB_PROGRESS);
202
203         pj = WM_jobs_get_customdata(steve);
204
205         if (!pj) {
206                 pj = MEM_callocN(sizeof(ProxyJob), "proxy rebuild job");
207         
208                 pj->scene= scene;
209                 pj->main = CTX_data_main(C);
210
211                 BLI_mutex_init(&pj->queue_lock);
212
213                 WM_jobs_customdata(steve, pj, proxy_freejob);
214                 WM_jobs_timer(steve, 0.1, NC_SCENE|ND_SEQUENCER,
215                               NC_SCENE|ND_SEQUENCER);
216                 WM_jobs_callbacks(steve, proxy_startjob, NULL, NULL, 
217                                   proxy_endjob);
218         }
219
220         BLI_mutex_lock(&pj->queue_lock);
221         BLI_addtail(&pj->queue, seq);
222         BLI_mutex_unlock(&pj->queue_lock);
223
224         if (!WM_jobs_is_running(steve)) {
225                 G.afbreek = 0;
226                 WM_jobs_start(CTX_wm_manager(C), steve);
227         }
228
229         ED_area_tag_redraw(CTX_wm_area(C));
230 }
231
232 /* ********************************************************************** */
233
234 void seq_rectf(Sequence *seq, rctf *rectf)
235 {
236         if(seq->startstill) rectf->xmin= seq->start;
237         else rectf->xmin= seq->startdisp;
238         rectf->ymin= seq->machine+SEQ_STRIP_OFSBOTTOM;
239         if(seq->endstill) rectf->xmax= seq->start+seq->len;
240         else rectf->xmax= seq->enddisp;
241         rectf->ymax= seq->machine+SEQ_STRIP_OFSTOP;
242 }
243
244 static void UNUSED_FUNCTION(change_plugin_seq)(Scene *scene, char *str) /* called from fileselect */
245 {
246         Editing *ed= seq_give_editing(scene, FALSE);
247         struct SeqEffectHandle sh;
248         Sequence *last_seq= seq_active_get(scene);
249
250         if(last_seq==NULL || last_seq->type != SEQ_PLUGIN) return;
251
252         sh = get_sequence_effect(last_seq);
253         sh.free(last_seq);
254         sh.init_plugin(last_seq, str);
255
256         last_seq->machine = MAX3(last_seq->seq1->machine, 
257                                  last_seq->seq2->machine, 
258                                  last_seq->seq3->machine);
259
260         if( seq_test_overlap(ed->seqbasep, last_seq) ) shuffle_seq(ed->seqbasep, last_seq, scene);
261         
262 }
263
264
265 void boundbox_seq(Scene *scene, rctf *rect)
266 {
267         Sequence *seq;
268         Editing *ed= seq_give_editing(scene, FALSE);
269         float min[2], max[2];
270
271         
272         if(ed==NULL) return;
273
274         min[0]= 0.0;
275         max[0]= EFRA+1;
276         min[1]= 0.0;
277         max[1]= 8.0;
278
279         seq= ed->seqbasep->first;
280         while(seq) {
281
282                 if( min[0] > seq->startdisp-1) min[0]= seq->startdisp-1;
283                 if( max[0] < seq->enddisp+1) max[0]= seq->enddisp+1;
284                 if( max[1] < seq->machine+2) max[1]= seq->machine+2;
285
286                 seq= seq->next;
287         }
288
289         rect->xmin= min[0];
290         rect->xmax= max[0];
291         rect->ymin= min[1];
292         rect->ymax= max[1];
293
294 }
295
296 static int mouse_frame_side(View2D *v2d, short mouse_x, int frame ) 
297 {
298         int mval[2];
299         float mouseloc[2];
300         
301         mval[0]= mouse_x;
302         mval[1]= 0;
303         
304         /* choose the side based on which side of the playhead the mouse is on */
305         UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouseloc[0], &mouseloc[1]);
306         
307         return mouseloc[0] > frame ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT;
308 }
309
310
311 Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int sel) 
312 {
313         /* sel - 0==unselected, 1==selected, -1==done care*/
314         Sequence *seq;
315         Editing *ed= seq_give_editing(scene, FALSE);
316
317         if(ed==NULL) return NULL;
318
319         if (sel>0) sel = SELECT;
320         
321         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
322                 if(     (seq!=test) &&
323                         (test->machine==seq->machine) &&
324                         ((sel == -1) || (sel && (seq->flag & SELECT)) || (sel==0 && (seq->flag & SELECT)==0)  ))
325                 {
326                         switch (lr) {
327                         case SEQ_SIDE_LEFT:
328                                 if (test->startdisp == (seq->enddisp)) {
329                                         return seq;
330                                 }
331                                 break;
332                         case SEQ_SIDE_RIGHT:
333                                 if (test->enddisp == (seq->startdisp)) {
334                                         return seq;
335                                 }
336                                 break;
337                         }
338                 }
339         }
340         return NULL;
341 }
342
343 static Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, int sel) 
344 {
345         /* sel - 0==unselected, 1==selected, -1==done care*/
346         Sequence *seq,*best_seq = NULL;
347         Editing *ed= seq_give_editing(scene, FALSE);
348         
349         int dist, best_dist;
350         best_dist = MAXFRAME*2;
351
352         
353         if(ed==NULL) return NULL;
354
355         seq= ed->seqbasep->first;
356         while(seq) {
357                 if(             (seq!=test) &&
358                                 (test->machine==seq->machine) &&
359                                 (test->depth==seq->depth) &&
360                                 ((sel == -1) || (sel==(seq->flag & SELECT))))
361                 {
362                         dist = MAXFRAME*2;
363                         
364                         switch (lr) {
365                         case SEQ_SIDE_LEFT:
366                                 if (seq->enddisp <= test->startdisp) {
367                                         dist = test->enddisp - seq->startdisp;
368                                 }
369                                 break;
370                         case SEQ_SIDE_RIGHT:
371                                 if (seq->startdisp >= test->enddisp) {
372                                         dist = seq->startdisp - test->enddisp;
373                                 }
374                                 break;
375                         }
376                         
377                         if (dist==0) {
378                                 best_seq = seq;
379                                 break;
380                         } else if (dist < best_dist) {
381                                 best_dist = dist;
382                                 best_seq = seq;
383                         }
384                 }
385                 seq= seq->next;
386         }
387         return best_seq; /* can be null */
388 }
389
390
391 Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[2])
392 {
393         Sequence *seq;
394         Editing *ed= seq_give_editing(scene, FALSE);
395         float x, y;
396         float pixelx;
397         float handsize;
398         float displen;
399         *hand= SEQ_SIDE_NONE;
400
401         
402         if(ed==NULL) return NULL;
403         
404         pixelx = (v2d->cur.xmax - v2d->cur.xmin)/(v2d->mask.xmax - v2d->mask.xmin);
405
406         UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
407         
408         seq= ed->seqbasep->first;
409         
410         while(seq) {
411                 if(seq->machine == (int)y) {
412                         /* check for both normal strips, and strips that have been flipped horizontally */
413                         if( ((seq->startdisp < seq->enddisp) && (seq->startdisp<=x && seq->enddisp>=x)) ||
414                                 ((seq->startdisp > seq->enddisp) && (seq->startdisp>=x && seq->enddisp<=x)) )
415                         {
416                                 if(seq_tx_test(seq)) {
417                                         
418                                         /* clamp handles to defined size in pixel space */
419                                         
420                                         handsize = seq->handsize;
421                                         displen = (float)abs(seq->startdisp - seq->enddisp);
422                                         
423                                         if (displen / pixelx > 16) { /* dont even try to grab the handles of small strips */
424                                                 /* Set the max value to handle to 1/3 of the total len when its less then 28.
425                                                 * This is important because otherwise selecting handles happens even when you click in the middle */
426                                                 
427                                                 if ((displen/3) < 30*pixelx) {
428                                                         handsize = displen/3;
429                                                 } else {
430                                                         CLAMP(handsize, 7*pixelx, 30*pixelx);
431                                                 }
432                                                 
433                                                 if( handsize+seq->startdisp >=x )
434                                                         *hand= SEQ_SIDE_LEFT;
435                                                 else if( -handsize+seq->enddisp <=x )
436                                                         *hand= SEQ_SIDE_RIGHT;
437                                         }
438                                 }
439                                 return seq;
440                         }
441                 }
442                 seq= seq->next;
443         }
444         return NULL;
445 }
446
447
448 static int seq_is_parent(Sequence *par, Sequence *seq)
449 {
450         return ((par->seq1 == seq) || (par->seq2 == seq) || (par->seq3 == seq));
451 }
452
453 static int seq_is_predecessor(Sequence *pred, Sequence *seq)
454 {
455         if (!pred) return 0;
456         if(pred == seq) return 0;
457         else if(seq_is_parent(pred, seq)) return 1;
458         else if(pred->seq1 && seq_is_predecessor(pred->seq1, seq)) return 1;
459         else if(pred->seq2 && seq_is_predecessor(pred->seq2, seq)) return 1;
460         else if(pred->seq3 && seq_is_predecessor(pred->seq3, seq)) return 1;
461
462         return 0;
463 }
464
465 void deselect_all_seq(Scene *scene)
466 {
467         Sequence *seq;
468         Editing *ed= seq_give_editing(scene, FALSE);
469
470         
471         if(ed==NULL) return;
472
473         SEQP_BEGIN(ed, seq) {
474                 seq->flag &= ~SEQ_ALLSEL;
475         }
476         SEQ_END
477                 
478 }
479
480 void recurs_sel_seq(Sequence *seqm)
481 {
482         Sequence *seq;
483
484         seq= seqm->seqbase.first;
485         while(seq) {
486
487                 if(seqm->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL)) seq->flag &= ~SEQ_ALLSEL;
488                 else if(seqm->flag & SELECT) seq->flag |= SELECT;
489                 else seq->flag &= ~SEQ_ALLSEL;
490
491                 if(seq->seqbase.first) recurs_sel_seq(seq);
492
493                 seq= seq->next;
494         }
495 }
496
497 int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequence **selseq1, Sequence **selseq2, Sequence **selseq3, const char **error_str)
498 {
499         Editing *ed = seq_give_editing(scene, FALSE);
500         Sequence *seq1= NULL, *seq2= NULL, *seq3= NULL, *seq;
501         
502         *error_str= NULL;
503
504         if (!activeseq)
505                 seq2= seq_active_get(scene);
506
507         for(seq=ed->seqbasep->first; seq; seq=seq->next) {
508                 if(seq->flag & SELECT) {
509                         if (seq->type == SEQ_SOUND && get_sequence_effect_num_inputs(type) != 0) {
510                                 *error_str= "Can't apply effects to audio sequence strips";
511                                 return 0;
512                         }
513                         if((seq != activeseq) && (seq != seq2)) {
514                                                                 if(seq2 == NULL) seq2= seq;
515                                                                 else if(seq1 == NULL) seq1= seq;
516                                                                 else if(seq3 == NULL) seq3= seq;
517                                                                 else {
518                                                                         *error_str= "Can't apply effect to more than 3 sequence strips";
519                                                                         return 0;
520                                                                 }
521                         }
522                 }
523         }
524
525         /* make sequence selection a little bit more intuitive
526            for 3 strips: the last-strip should be sequence3 */
527         if (seq3 != NULL && seq2 != NULL) {
528                 Sequence *tmp = seq2;
529                 seq2 = seq3;
530                 seq3 = tmp;
531         }
532         
533
534         switch(get_sequence_effect_num_inputs(type)) {
535         case 0:
536                 *selseq1 = *selseq2 = *selseq3 = NULL;
537                 return 1; /* succsess */
538         case 1:
539                 if(seq2==NULL)  {
540                         *error_str= "Need at least one selected sequence strip";
541                         return 0;
542                 }
543                 if(seq1==NULL) seq1= seq2;
544                 if(seq3==NULL) seq3= seq2;
545         case 2:
546                 if(seq1==NULL || seq2==NULL) {
547                         *error_str= "Need 2 selected sequence strips";
548                         return 0;
549                 }
550                 if(seq3 == NULL) seq3= seq2;
551         }
552         
553         if (seq1==NULL && seq2==NULL && seq3==NULL) {
554                 *error_str= "TODO: in what cases does this happen?";
555                 return 0;
556         }
557         
558         *selseq1= seq1;
559         *selseq2= seq2;
560         *selseq3= seq3;
561
562         return 1;
563 }
564
565 static Sequence *del_seq_find_replace_recurs(Scene *scene, Sequence *seq)
566 {
567         Sequence *seq1, *seq2, *seq3;
568
569         /* try to find a replacement input sequence, and flag for later deletion if
570            no replacement can be found */
571
572         if(!seq)
573                 return NULL;
574         else if(!(seq->type & SEQ_EFFECT))
575                 return ((seq->flag & SELECT)? NULL: seq);
576         else if(!(seq->flag & SELECT)) {
577                 /* try to find replacement for effect inputs */
578                 seq1= del_seq_find_replace_recurs(scene, seq->seq1);
579                 seq2= del_seq_find_replace_recurs(scene, seq->seq2);
580                 seq3= del_seq_find_replace_recurs(scene, seq->seq3);
581
582                 if(seq1==seq->seq1 && seq2==seq->seq2 && seq3==seq->seq3);
583                 else if(seq1 || seq2 || seq3) {
584                         seq->seq1= (seq1)? seq1: (seq2)? seq2: seq3;
585                         seq->seq2= (seq2)? seq2: (seq1)? seq1: seq3;
586                         seq->seq3= (seq3)? seq3: (seq1)? seq1: seq2;
587
588                         update_changed_seq_and_deps(scene, seq, 1, 1);
589                 }
590                 else
591                         seq->flag |= SELECT; /* mark for delete */
592         }
593
594         if (seq->flag & SELECT) {
595                 if((seq1 = del_seq_find_replace_recurs(scene, seq->seq1))) return seq1;
596                 if((seq2 = del_seq_find_replace_recurs(scene, seq->seq2))) return seq2;
597                 if((seq3 = del_seq_find_replace_recurs(scene, seq->seq3))) return seq3;
598                 else return NULL;
599         }
600         else
601                 return seq;
602 }
603
604 static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short deleteall)
605 {
606         Sequence *seq, *seqn;
607         Sequence *last_seq = seq_active_get(scene);
608
609         seq= lb->first;
610         while(seq) {
611                 seqn= seq->next;
612                 if((seq->flag & flag) || deleteall) {
613                         BLI_remlink(lb, seq);
614                         if(seq==last_seq) seq_active_set(scene, NULL);
615                         if(seq->type==SEQ_META) recurs_del_seq_flag(scene, &seq->seqbase, flag, 1);
616                         seq_free_sequence(scene, seq);
617                 }
618                 seq= seqn;
619         }
620 }
621
622
623 static Sequence *cut_seq_hard(Scene *scene, Sequence * seq, int cutframe)
624 {
625         TransSeq ts;
626         Sequence *seqn = NULL;
627         int skip_dup = FALSE;
628
629         /* backup values */
630         ts.start= seq->start;
631         ts.machine= seq->machine;
632         ts.startstill= seq->startstill;
633         ts.endstill= seq->endstill;
634         ts.startdisp= seq->startdisp;
635         ts.enddisp= seq->enddisp;
636         ts.startofs= seq->startofs;
637         ts.endofs= seq->endofs;
638         ts.anim_startofs= seq->anim_startofs;
639         ts.anim_endofs= seq->anim_endofs;
640         ts.len= seq->len;
641         
642         /* First Strip! */
643         /* strips with extended stillfames before */
644         
645         if ((seq->startstill) && (cutframe <seq->start)) {
646                 /* don't do funny things with METAs ... */
647                 if (seq->type == SEQ_META) {
648                         skip_dup = TRUE;
649                         seq->startstill = seq->start - cutframe;
650                 } else {
651                         seq->start= cutframe -1;
652                         seq->startstill= cutframe -seq->startdisp -1;
653                         seq->anim_endofs += seq->len - 1;
654                         seq->endstill= 0;
655                 }
656         }
657         /* normal strip */
658         else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) {
659                 seq->endofs = 0;
660                 seq->endstill = 0;
661                 seq->anim_endofs += (seq->start+seq->len) - cutframe;
662         }
663         /* strips with extended stillframes after */
664         else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
665                 seq->endstill -= seq->enddisp - cutframe;
666                 /* don't do funny things with METAs ... */
667                 if (seq->type == SEQ_META) {
668                         skip_dup = TRUE;
669                 }
670         }
671         
672         reload_sequence_new_file(scene, seq, FALSE);
673         calc_sequence(scene, seq);
674         new_tstripdata(seq); 
675
676         if (!skip_dup) {
677                 /* Duplicate AFTER the first change */
678                 seqn = seq_dupli_recursive(scene, NULL, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
679         }
680         
681         if (seqn) { 
682                 seqn->flag |= SELECT;
683                         
684                 /* Second Strip! */
685                 /* strips with extended stillframes before */
686                 if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
687                         seqn->start = ts.start;
688                         seqn->startstill= ts.start- cutframe;
689                         seqn->anim_endofs = ts.anim_endofs;
690                         seqn->endstill = ts.endstill;
691                 }
692                 
693                 /* normal strip */
694                 else if ((cutframe>=seqn->start)&&(cutframe<=(seqn->start+seqn->len))) {
695                         seqn->start = cutframe;
696                         seqn->startstill = 0;
697                         seqn->startofs = 0;
698                         seqn->endofs = ts.endofs;
699                         seqn->anim_startofs += cutframe - ts.start;
700                         seqn->anim_endofs = ts.anim_endofs;
701                         seqn->endstill = ts.endstill;
702                 }                               
703                 
704                 /* strips with extended stillframes after */
705                 else if (((seqn->start+seqn->len) < cutframe) && (seqn->endstill)) {
706                         seqn->start = cutframe;
707                         seqn->startofs = 0;
708                         seqn->anim_startofs += ts.len-1;
709                         seqn->endstill = ts.enddisp - cutframe -1;
710                         seqn->startstill = 0;
711                 }
712                 
713                 reload_sequence_new_file(scene, seqn, FALSE);
714                 calc_sequence(scene, seqn);
715                 new_tstripdata(seqn);
716         }
717         return seqn;
718 }
719
720 static Sequence *cut_seq_soft(Scene *scene, Sequence * seq, int cutframe)
721 {
722         TransSeq ts;
723         Sequence *seqn = NULL;
724         int skip_dup = FALSE;
725
726         /* backup values */
727         ts.start= seq->start;
728         ts.machine= seq->machine;
729         ts.startstill= seq->startstill;
730         ts.endstill= seq->endstill;
731         ts.startdisp= seq->startdisp;
732         ts.enddisp= seq->enddisp;
733         ts.startofs= seq->startofs;
734         ts.endofs= seq->endofs;
735         ts.anim_startofs= seq->anim_startofs;
736         ts.anim_endofs= seq->anim_endofs;
737         ts.len= seq->len;
738         
739         /* First Strip! */
740         /* strips with extended stillfames before */
741         
742         if ((seq->startstill) && (cutframe <seq->start)) {
743                 /* don't do funny things with METAs ... */
744                 if (seq->type == SEQ_META) {
745                         skip_dup = TRUE;
746                         seq->startstill = seq->start - cutframe;
747                 } else {
748                         seq->start= cutframe -1;
749                         seq->startstill= cutframe -seq->startdisp -1;
750                         seq->endofs = seq->len - 1;
751                         seq->endstill= 0;
752                 }
753         }
754         /* normal strip */
755         else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) {
756                 seq->endofs = (seq->start+seq->len) - cutframe;
757         }
758         /* strips with extended stillframes after */
759         else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
760                 seq->endstill -= seq->enddisp - cutframe;
761                 /* don't do funny things with METAs ... */
762                 if (seq->type == SEQ_META) {
763                         skip_dup = TRUE;
764                 }
765         }
766         
767         calc_sequence(scene, seq);
768         new_tstripdata(seq);
769
770         if (!skip_dup) {
771                 /* Duplicate AFTER the first change */
772                 seqn = seq_dupli_recursive(scene, NULL, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
773         }
774         
775         if (seqn) { 
776                 seqn->flag |= SELECT;
777                         
778                 /* Second Strip! */
779                 /* strips with extended stillframes before */
780                 if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
781                         seqn->start = ts.start;
782                         seqn->startstill= ts.start- cutframe;
783                         seqn->endofs = ts.endofs;
784                         seqn->endstill = ts.endstill;
785                 }
786                 
787                 /* normal strip */
788                 else if ((cutframe>=seqn->start)&&(cutframe<=(seqn->start+seqn->len))) {
789                         seqn->startstill = 0;
790                         seqn->startofs = cutframe - ts.start;
791                         seqn->endofs = ts.endofs;
792                         seqn->endstill = ts.endstill;
793                 }                               
794                 
795                 /* strips with extended stillframes after */
796                 else if (((seqn->start+seqn->len) < cutframe) && (seqn->endstill)) {
797                         seqn->start = cutframe - ts.len +1;
798                         seqn->startofs = ts.len-1;
799                         seqn->endstill = ts.enddisp - cutframe -1;
800                         seqn->startstill = 0;
801                 }
802                 
803                 calc_sequence(scene, seqn);
804                 new_tstripdata(seqn);
805         }
806         return seqn;
807 }
808
809
810 /* like duplicate, but only duplicate and cut overlapping strips,
811  * strips to the left of the cutframe are ignored and strips to the right are moved into the new list */
812 static int cut_seq_list(Scene *scene, ListBase *old, ListBase *new, int cutframe,
813                         Sequence * (*cut_seq)(Scene *, Sequence *, int))
814 {
815         int did_something = FALSE;
816         Sequence *seq, *seq_next_iter;
817         
818         seq= old->first;
819         
820         while(seq) {
821                 seq_next_iter = seq->next; /* we need this because we may remove seq */
822                 
823                 seq->tmp= NULL;
824                 if(seq->flag & SELECT) {
825                         if(cutframe > seq->startdisp && 
826                            cutframe < seq->enddisp) {
827                                 Sequence * seqn = cut_seq(scene, seq, cutframe);
828                                 if (seqn) {
829                                         BLI_addtail(new, seqn);
830                                 }
831                                 did_something = TRUE;
832                         } else if (seq->enddisp <= cutframe) {
833                                 /* do nothing */
834                         } else if (seq->startdisp >= cutframe) {
835                                 /* move into new list */
836                                 BLI_remlink(old, seq);
837                                 BLI_addtail(new, seq);
838                         }
839                 }
840                 seq = seq_next_iter;
841         }
842         return did_something;
843 }
844
845 static int insert_gap(Scene *scene, int gap, int cfra)
846 {
847         Sequence *seq;
848         Editing *ed= seq_give_editing(scene, FALSE);
849         int done=0;
850
851         /* all strips >= cfra are shifted */
852         
853         if(ed==NULL) return 0;
854
855         SEQP_BEGIN(ed, seq) {
856                 if(seq->startdisp >= cfra) {
857                         seq->start+= gap;
858                         calc_sequence(scene, seq);
859                         done= 1;
860                 }
861         }
862         SEQ_END
863
864         return done;
865 }
866
867 static void UNUSED_FUNCTION(touch_seq_files)(Scene *scene)
868 {
869         Sequence *seq;
870         Editing *ed= seq_give_editing(scene, FALSE);
871         char str[256];
872
873         /* touch all strips with movies */
874         
875         if(ed==NULL) return;
876
877         if(okee("Touch and print selected movies")==0) return;
878
879         WM_cursor_wait(1);
880
881         SEQP_BEGIN(ed, seq) {
882                 if(seq->flag & SELECT) {
883                         if(seq->type==SEQ_MOVIE) {
884                                 if(seq->strip && seq->strip->stripdata) {
885                                         BLI_make_file_string(G.main->name, str, seq->strip->dir, seq->strip->stripdata->name);
886                                         BLI_touch(seq->name);
887                                 }
888                         }
889
890                 }
891         }
892         SEQ_END
893
894         WM_cursor_wait(0);
895 }
896
897 /*
898 static void set_filter_seq(Scene *scene)
899 {
900         Sequence *seq;
901         Editing *ed= seq_give_editing(scene, FALSE);
902
903         
904         if(ed==NULL) return;
905
906         if(okee("Set Deinterlace")==0) return;
907
908         SEQP_BEGIN(ed, seq) {
909                 if(seq->flag & SELECT) {
910                         if(seq->type==SEQ_MOVIE) {
911                                 seq->flag |= SEQ_FILTERY;
912                                 reload_sequence_new_file(scene, seq, FALSE);
913                                 calc_sequence(scene, seq);
914                         }
915
916                 }
917         }
918         SEQ_END
919 }
920 */
921
922 static void UNUSED_FUNCTION(seq_remap_paths)(Scene *scene)
923 {
924         Sequence *seq, *last_seq = seq_active_get(scene);
925         Editing *ed= seq_give_editing(scene, FALSE);
926         char from[FILE_MAX], to[FILE_MAX], stripped[FILE_MAX];
927         
928         
929         if(last_seq==NULL) 
930                 return;
931         
932         BLI_strncpy(from, last_seq->strip->dir, FILE_MAX);
933 // XXX  if (0==sbutton(from, 0, sizeof(from)-1, "From: "))
934 //              return;
935         
936         strcpy(to, from);
937 // XXX  if (0==sbutton(to, 0, sizeof(to)-1, "To: "))
938 //              return;
939         
940         if (strcmp(to, from)==0)
941                 return;
942         
943         SEQP_BEGIN(ed, seq) {
944                 if(seq->flag & SELECT) {
945                         if(strncmp(seq->strip->dir, from, strlen(from))==0) {
946                                 printf("found %s\n", seq->strip->dir);
947                                 
948                                 /* strip off the beginning */
949                                 stripped[0]= 0;
950                                 BLI_strncpy(stripped, seq->strip->dir + strlen(from), FILE_MAX);
951                                 
952                                 /* new path */
953                                 BLI_snprintf(seq->strip->dir, sizeof(seq->strip->dir), "%s%s", to, stripped);
954                                 printf("new %s\n", seq->strip->dir);
955                         }
956                 }
957         }
958         SEQ_END
959                 
960 }
961
962
963 static void UNUSED_FUNCTION(no_gaps)(Scene *scene)
964 {
965         Editing *ed= seq_give_editing(scene, FALSE);
966         int cfra, first= 0, done;
967
968         
969         if(ed==NULL) return;
970
971         for(cfra= CFRA; cfra<=EFRA; cfra++) {
972                 if(first==0) {
973                         if( evaluate_seq_frame(scene, cfra) ) first= 1;
974                 }
975                 else {
976                         done= 1;
977                         while( evaluate_seq_frame(scene, cfra) == 0) {
978                                 done= insert_gap(scene, -1, cfra);
979                                 if(done==0) break;
980                         }
981                         if(done==0) break;
982                 }
983         }
984
985 }
986
987 #if 0
988 static int seq_get_snaplimit(View2D *v2d)
989 {
990         /* fake mouse coords to get the snap value
991         a bit lazy but its only done once pre transform */
992         float xmouse, ymouse, x;
993         int mval[2] = {24, 0}; /* 24 screen px snap */
994         
995         UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
996         x = xmouse;
997         mval[0] = 0;
998         UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
999         return (int)(x - xmouse);
1000 }
1001 #endif
1002
1003 /* Operator functions */
1004 int sequencer_edit_poll(bContext *C)
1005 {
1006         return (seq_give_editing(CTX_data_scene(C), FALSE) != NULL);
1007 }
1008
1009 int sequencer_strip_poll(bContext *C)
1010 {
1011         Editing *ed;
1012         return (((ed= seq_give_editing(CTX_data_scene(C), FALSE)) != NULL) && (ed->act_seq != NULL));
1013 }
1014
1015 int sequencer_strip_has_path_poll(bContext *C)
1016 {
1017         Editing *ed;
1018         Sequence *seq;
1019         return (((ed= seq_give_editing(CTX_data_scene(C), FALSE)) != NULL) && ((seq= ed->act_seq) != NULL) && (SEQ_HAS_PATH(seq)));
1020 }
1021
1022 int sequencer_view_poll(bContext *C)
1023 {
1024         SpaceSeq *sseq= CTX_wm_space_seq(C);
1025         Editing *ed= seq_give_editing(CTX_data_scene(C), FALSE);
1026         if (ed && sseq && (sseq->mainb == SEQ_DRAW_IMG_IMBUF))
1027                 return 1;
1028
1029         return 0;
1030 }
1031
1032 /* snap operator*/
1033 static int sequencer_snap_exec(bContext *C, wmOperator *op)
1034 {
1035         Scene *scene= CTX_data_scene(C);
1036         
1037         Editing *ed= seq_give_editing(scene, FALSE);
1038         Sequence *seq;
1039         int snap_frame;
1040
1041         snap_frame= RNA_int_get(op->ptr, "frame");
1042
1043         /* also check metas */
1044         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1045                 if (seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK) &&
1046                         seq_tx_test(seq)) {
1047                         if((seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))==0) {
1048                                 /* simple but no anim update */
1049                                 /* seq->start= snap_frame-seq->startofs+seq->startstill; */
1050
1051                                 seq_translate(scene, seq, (snap_frame-seq->startofs+seq->startstill) - seq->start);
1052                         } else { 
1053                                 if(seq->flag & SEQ_LEFTSEL) {
1054                                         seq_tx_set_final_left(seq, snap_frame);
1055                                 } else { /* SEQ_RIGHTSEL */
1056                                         seq_tx_set_final_right(seq, snap_frame);
1057                                 }
1058                                 seq_tx_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
1059                         }
1060                         calc_sequence(scene, seq);
1061                 }
1062         }
1063
1064         /* test for effects and overlap
1065          * dont use SEQP_BEGIN since that would be recursive */
1066         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1067                 if(seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK)) {
1068                         seq->flag &= ~SEQ_OVERLAP;
1069                         if( seq_test_overlap(ed->seqbasep, seq) ) {
1070                                 shuffle_seq(ed->seqbasep, seq, scene);
1071                         }
1072                 }
1073                 else if(seq->type & SEQ_EFFECT) {
1074                         if(seq->seq1 && (seq->seq1->flag & SELECT)) 
1075                                 calc_sequence(scene, seq);
1076                         else if(seq->seq2 && (seq->seq2->flag & SELECT)) 
1077                                 calc_sequence(scene, seq);
1078                         else if(seq->seq3 && (seq->seq3->flag & SELECT)) 
1079                                 calc_sequence(scene, seq);
1080                 }
1081         }
1082
1083         /* as last: */
1084         sort_seq(scene);
1085         
1086         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1087         
1088         return OPERATOR_FINISHED;
1089 }
1090
1091 static int sequencer_snap_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1092 {
1093         Scene *scene = CTX_data_scene(C);
1094         
1095         int snap_frame;
1096         
1097         snap_frame= CFRA;
1098         
1099         RNA_int_set(op->ptr, "frame", snap_frame);
1100         return sequencer_snap_exec(C, op);
1101 }
1102
1103 void SEQUENCER_OT_snap(struct wmOperatorType *ot)
1104 {
1105         /* identifiers */
1106         ot->name= "Snap strips";
1107         ot->idname= "SEQUENCER_OT_snap";
1108         ot->description="Frame where selected strips will be snapped";
1109         
1110         /* api callbacks */
1111         ot->invoke= sequencer_snap_invoke;
1112         ot->exec= sequencer_snap_exec;
1113         ot->poll= sequencer_edit_poll;
1114         
1115         /* flags */
1116         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1117         
1118         RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be snapped", INT_MIN, INT_MAX);
1119 }
1120
1121 /* mute operator */
1122 static int sequencer_mute_exec(bContext *C, wmOperator *op)
1123 {
1124         Scene *scene= CTX_data_scene(C);
1125         Editing *ed= seq_give_editing(scene, FALSE);
1126         Sequence *seq;
1127         int selected;
1128
1129         selected= !RNA_boolean_get(op->ptr, "unselected");
1130         
1131         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1132                 if ((seq->flag & SEQ_LOCK)==0) {
1133                         if(selected){ /* mute unselected */
1134                                 if(seq->flag & SELECT)
1135                                         seq->flag |= SEQ_MUTE;
1136                         }
1137                         else {
1138                                 if((seq->flag & SELECT)==0)
1139                                         seq->flag |= SEQ_MUTE;
1140                         }
1141                 }
1142         }
1143         
1144         seq_update_muting(ed);
1145         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1146         
1147         return OPERATOR_FINISHED;
1148 }
1149
1150 void SEQUENCER_OT_mute(struct wmOperatorType *ot)
1151 {
1152         /* identifiers */
1153         ot->name= "Mute Strips";
1154         ot->idname= "SEQUENCER_OT_mute";
1155         ot->description="Mute selected strips";
1156         
1157         /* api callbacks */
1158         ot->exec= sequencer_mute_exec;
1159         ot->poll= sequencer_edit_poll;
1160         
1161         /* flags */
1162         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1163         
1164         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Mute unselected rather than selected strips");
1165 }
1166
1167
1168 /* unmute operator */
1169 static int sequencer_unmute_exec(bContext *C, wmOperator *op)
1170 {
1171         Scene *scene= CTX_data_scene(C);
1172         Editing *ed= seq_give_editing(scene, FALSE);
1173         Sequence *seq;
1174         int selected;
1175
1176         selected= !RNA_boolean_get(op->ptr, "unselected");
1177         
1178         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1179                 if ((seq->flag & SEQ_LOCK)==0) {
1180                         if(selected){ /* unmute unselected */
1181                                 if(seq->flag & SELECT)
1182                                         seq->flag &= ~SEQ_MUTE;
1183                         }
1184                         else {
1185                                 if((seq->flag & SELECT)==0)
1186                                         seq->flag &= ~SEQ_MUTE;
1187                         }
1188                 }
1189         }
1190         
1191         seq_update_muting(ed);
1192         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1193         
1194         return OPERATOR_FINISHED;
1195 }
1196
1197 void SEQUENCER_OT_unmute(struct wmOperatorType *ot)
1198 {
1199         /* identifiers */
1200         ot->name= "Un-Mute Strips";
1201         ot->idname= "SEQUENCER_OT_unmute";
1202         ot->description="Un-Mute unselected rather than selected strips";
1203         
1204         /* api callbacks */
1205         ot->exec= sequencer_unmute_exec;
1206         ot->poll= sequencer_edit_poll;
1207         
1208         /* flags */
1209         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1210         
1211         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "UnMute unselected rather than selected strips");
1212 }
1213
1214
1215 /* lock operator */
1216 static int sequencer_lock_exec(bContext *C, wmOperator *UNUSED(op))
1217 {
1218         Scene *scene= CTX_data_scene(C);
1219         Editing *ed= seq_give_editing(scene, FALSE);
1220         Sequence *seq;
1221
1222         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1223                 if (seq->flag & SELECT) {
1224                         seq->flag |= SEQ_LOCK;
1225                 }
1226         }
1227
1228         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1229
1230         return OPERATOR_FINISHED;
1231 }
1232
1233 void SEQUENCER_OT_lock(struct wmOperatorType *ot)
1234 {
1235         /* identifiers */
1236         ot->name= "Lock Strips";
1237         ot->idname= "SEQUENCER_OT_lock";
1238         ot->description="Lock the active strip so that it can't be transformed";
1239         
1240         /* api callbacks */
1241         ot->exec= sequencer_lock_exec;
1242         ot->poll= sequencer_edit_poll;
1243         
1244         /* flags */
1245         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1246 }
1247
1248 /* unlock operator */
1249 static int sequencer_unlock_exec(bContext *C, wmOperator *UNUSED(op))
1250 {
1251         Scene *scene= CTX_data_scene(C);
1252         Editing *ed= seq_give_editing(scene, FALSE);
1253         Sequence *seq;
1254
1255         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1256                 if (seq->flag & SELECT) {
1257                         seq->flag &= ~SEQ_LOCK;
1258                 }
1259         }
1260
1261         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1262
1263         return OPERATOR_FINISHED;
1264 }
1265
1266 void SEQUENCER_OT_unlock(struct wmOperatorType *ot)
1267 {
1268         /* identifiers */
1269         ot->name= "UnLock Strips";
1270         ot->idname= "SEQUENCER_OT_unlock";
1271         ot->description="Unlock the active strip so that it can't be transformed";
1272         
1273         /* api callbacks */
1274         ot->exec= sequencer_unlock_exec;
1275         ot->poll= sequencer_edit_poll;
1276         
1277         /* flags */
1278         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1279 }
1280
1281 /* reload operator */
1282 static int sequencer_reload_exec(bContext *C, wmOperator *UNUSED(op))
1283 {
1284         Scene *scene= CTX_data_scene(C);
1285         Editing *ed= seq_give_editing(scene, FALSE);
1286         Sequence *seq;
1287
1288         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1289                 if(seq->flag & SELECT) {
1290                         update_changed_seq_and_deps(scene, seq, 0, 1);
1291                 }
1292         }
1293
1294         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1295
1296         return OPERATOR_FINISHED;
1297 }
1298
1299 void SEQUENCER_OT_reload(struct wmOperatorType *ot)
1300 {
1301         /* identifiers */
1302         ot->name= "Reload Strips";
1303         ot->idname= "SEQUENCER_OT_reload";
1304         ot->description="Reload strips in the sequencer";
1305         
1306         /* api callbacks */
1307         ot->exec= sequencer_reload_exec;
1308         ot->poll= sequencer_edit_poll;
1309         
1310         /* flags */
1311         ot->flag= OPTYPE_REGISTER; /* no undo, the data changed is stored outside 'main' */
1312 }
1313
1314 /* reload operator */
1315 static int sequencer_refresh_all_exec(bContext *C, wmOperator *UNUSED(op))
1316 {
1317         Scene *scene= CTX_data_scene(C);
1318         Editing *ed= seq_give_editing(scene, FALSE);
1319
1320         free_imbuf_seq(scene, &ed->seqbase, FALSE, FALSE);
1321
1322         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1323
1324         return OPERATOR_FINISHED;
1325 }
1326
1327 void SEQUENCER_OT_refresh_all(struct wmOperatorType *ot)
1328 {
1329         /* identifiers */
1330         ot->name= "Refresh Sequencer";
1331         ot->idname= "SEQUENCER_OT_refresh_all";
1332         ot->description="Refresh the sequencer editor";
1333         
1334         /* api callbacks */
1335         ot->exec= sequencer_refresh_all_exec;
1336         ot->poll= sequencer_edit_poll;
1337 }
1338
1339 static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op)
1340 {
1341         Scene *scene= CTX_data_scene(C);
1342         Sequence *seq1, *seq2, *seq3, *last_seq = seq_active_get(scene);
1343         const char *error_msg;
1344
1345         if(!seq_effect_find_selected(scene, last_seq, last_seq->type, &seq1, &seq2, &seq3, &error_msg)) {
1346                 BKE_report(op->reports, RPT_ERROR, error_msg);
1347                 return OPERATOR_CANCELLED;
1348         }
1349         /* see reassigning would create a cycle */
1350         if(     seq_is_predecessor(seq1, last_seq) ||
1351                 seq_is_predecessor(seq2, last_seq) ||
1352                 seq_is_predecessor(seq3, last_seq)
1353         ) {
1354                 BKE_report(op->reports, RPT_ERROR, "Can't reassign inputs: no cycles allowed");
1355                 return OPERATOR_CANCELLED;
1356         }
1357
1358         last_seq->seq1 = seq1;
1359         last_seq->seq2 = seq2;
1360         last_seq->seq3 = seq3;
1361
1362         update_changed_seq_and_deps(scene, last_seq, 1, 1);
1363
1364         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1365
1366         return OPERATOR_FINISHED;
1367 }
1368
1369 static int sequencer_effect_poll(bContext *C)
1370 {
1371         Scene *scene= CTX_data_scene(C);
1372         Editing *ed= seq_give_editing(scene, FALSE);
1373
1374         if(ed) {
1375                 Sequence *last_seq= seq_active_get(scene);
1376                 if(last_seq && (last_seq->type & SEQ_EFFECT)) {
1377                         return 1;
1378                 }
1379         }
1380
1381         return 0;
1382 }
1383
1384 void SEQUENCER_OT_reassign_inputs(struct wmOperatorType *ot)
1385 {
1386         /* identifiers */
1387         ot->name= "Reassign Inputs";
1388         ot->idname= "SEQUENCER_OT_reassign_inputs";
1389         ot->description="Reassign the inputs for the effect strip";
1390
1391         /* api callbacks */
1392         ot->exec= sequencer_reassign_inputs_exec;
1393         ot->poll= sequencer_effect_poll;
1394
1395         /* flags */
1396         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1397 }
1398
1399
1400 static int sequencer_swap_inputs_exec(bContext *C, wmOperator *op)
1401 {
1402         Scene *scene= CTX_data_scene(C);
1403         Sequence *seq, *last_seq = seq_active_get(scene);
1404
1405         if(last_seq->seq1==NULL || last_seq->seq2 == NULL) {
1406                 BKE_report(op->reports, RPT_ERROR, "No valid inputs to swap");
1407                 return OPERATOR_CANCELLED;
1408         }
1409
1410         seq = last_seq->seq1;
1411         last_seq->seq1 = last_seq->seq2;
1412         last_seq->seq2 = seq;
1413
1414         update_changed_seq_and_deps(scene, last_seq, 1, 1);
1415
1416         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1417
1418         return OPERATOR_FINISHED;
1419 }
1420 void SEQUENCER_OT_swap_inputs(struct wmOperatorType *ot)
1421 {
1422         /* identifiers */
1423         ot->name= "Swap Inputs";
1424         ot->idname= "SEQUENCER_OT_swap_inputs";
1425         ot->description="Swap the first two inputs for the effect strip";
1426
1427         /* api callbacks */
1428         ot->exec= sequencer_swap_inputs_exec;
1429         ot->poll= sequencer_effect_poll;
1430
1431         /* flags */
1432         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1433 }
1434
1435
1436 /* cut operator */
1437 static EnumPropertyItem prop_cut_types[] = {
1438         {SEQ_CUT_SOFT, "SOFT", 0, "Soft", ""},
1439         {SEQ_CUT_HARD, "HARD", 0, "Hard", ""},
1440         {0, NULL, 0, NULL, NULL}
1441 };
1442
1443 static int sequencer_cut_exec(bContext *C, wmOperator *op)
1444 {
1445         Scene *scene= CTX_data_scene(C);
1446         Editing *ed= seq_give_editing(scene, FALSE);
1447         int cut_side, cut_hard, cut_frame;
1448
1449         ListBase newlist;
1450         int changed;
1451
1452         cut_frame= RNA_int_get(op->ptr, "frame");
1453         cut_hard= RNA_enum_get(op->ptr, "type");
1454         cut_side= RNA_enum_get(op->ptr, "side");
1455         
1456         newlist.first= newlist.last= NULL;
1457
1458         if (cut_hard==SEQ_CUT_HARD) {
1459                 changed = cut_seq_list(scene, ed->seqbasep, &newlist, cut_frame, cut_seq_hard);
1460         } else {
1461                 changed = cut_seq_list(scene, ed->seqbasep, &newlist, cut_frame, cut_seq_soft);
1462         }
1463         
1464         if (newlist.first) { /* got new strips ? */
1465                 Sequence *seq;
1466                 BLI_movelisttolist(ed->seqbasep, &newlist);
1467
1468                 if (cut_side != SEQ_SIDE_BOTH) {
1469                         SEQP_BEGIN(ed, seq) {
1470                                 if (cut_side==SEQ_SIDE_LEFT) {
1471                                         if ( seq->startdisp >= cut_frame ) {
1472                                                 seq->flag &= ~SEQ_ALLSEL;
1473                                         }
1474                                 } else {
1475                                         if ( seq->enddisp <= cut_frame ) {
1476                                                 seq->flag &= ~SEQ_ALLSEL;
1477                                         }
1478                                 }
1479                         }
1480                         SEQ_END;
1481                 }
1482                 /* as last: */
1483                 sort_seq(scene);
1484         }
1485
1486         if(changed) {
1487                 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1488                 return OPERATOR_FINISHED;
1489         }
1490         else {
1491                 return OPERATOR_CANCELLED;
1492         }
1493 }
1494
1495
1496 static int sequencer_cut_invoke(bContext *C, wmOperator *op, wmEvent *event)
1497 {
1498         Scene *scene = CTX_data_scene(C);
1499         View2D *v2d= UI_view2d_fromcontext(C);
1500
1501         int cut_side= SEQ_SIDE_BOTH;
1502         int cut_frame= CFRA;
1503
1504         if (ED_operator_sequencer_active(C) && v2d)
1505                 cut_side= mouse_frame_side(v2d, event->mval[0], cut_frame);
1506         
1507         RNA_int_set(op->ptr, "frame", cut_frame);
1508         RNA_enum_set(op->ptr, "side", cut_side);
1509         /*RNA_enum_set(op->ptr, "type", cut_hard); */ /*This type is set from the key shortcut */
1510
1511         return sequencer_cut_exec(C, op);
1512 }
1513
1514
1515 void SEQUENCER_OT_cut(struct wmOperatorType *ot)
1516 {
1517         /* identifiers */
1518         ot->name= "Cut Strips";
1519         ot->idname= "SEQUENCER_OT_cut";
1520         ot->description="Cut the selected strips";
1521         
1522         /* api callbacks */
1523         ot->invoke= sequencer_cut_invoke;
1524         ot->exec= sequencer_cut_exec;
1525         ot->poll= sequencer_edit_poll;
1526         
1527         /* flags */
1528         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1529         
1530         RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be cut", INT_MIN, INT_MAX);
1531         RNA_def_enum(ot->srna, "type", prop_cut_types, SEQ_CUT_SOFT, "Type", "The type of cut operation to perform on strips");
1532         RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side that remains selected after cutting");
1533 }
1534
1535 /* duplicate operator */
1536 static int apply_unique_name_cb(Sequence *seq, void *arg_pt)
1537 {
1538         Scene *scene= (Scene *)arg_pt;
1539         char name[sizeof(seq->name)-2];
1540
1541         strcpy(name, seq->name+2);
1542         seqbase_unique_name_recursive(&scene->ed->seqbase, seq);
1543         seq_dupe_animdata(scene, name, seq->name+2);
1544         return 1;
1545
1546 }
1547
1548 static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
1549 {
1550         Scene *scene= CTX_data_scene(C);
1551         Editing *ed= seq_give_editing(scene, FALSE);
1552
1553         ListBase nseqbase= {NULL, NULL};
1554
1555         if(ed==NULL)
1556                 return OPERATOR_CANCELLED;
1557
1558         seqbase_dupli_recursive(scene, NULL, &nseqbase, ed->seqbasep, SEQ_DUPE_CONTEXT);
1559
1560         if(nseqbase.first) {
1561                 Sequence * seq= nseqbase.first;
1562                 /* rely on the nseqbase list being added at the end */
1563                 BLI_movelisttolist(ed->seqbasep, &nseqbase);
1564
1565                 for( ; seq; seq= seq->next)
1566                         seq_recursive_apply(seq, apply_unique_name_cb, scene);
1567
1568                 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1569                 return OPERATOR_FINISHED;
1570         }
1571
1572         return OPERATOR_CANCELLED;
1573 }
1574
1575 static int sequencer_add_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1576 {
1577         sequencer_add_duplicate_exec(C, op);
1578
1579         RNA_enum_set(op->ptr, "mode", TFM_TRANSLATION);
1580         WM_operator_name_call(C, "TRANSFORM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
1581
1582         return OPERATOR_FINISHED;
1583 }
1584
1585 void SEQUENCER_OT_duplicate(wmOperatorType *ot)
1586 {
1587         /* identifiers */
1588         ot->name= "Duplicate Strips";
1589         ot->idname= "SEQUENCER_OT_duplicate";
1590         ot->description="Duplicate the selected strips";
1591         
1592         /* api callbacks */
1593         ot->invoke= sequencer_add_duplicate_invoke;
1594         ot->exec= sequencer_add_duplicate_exec;
1595         ot->poll= ED_operator_sequencer_active;
1596         
1597         /* flags */
1598         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1599         
1600         /* to give to transform */
1601         RNA_def_enum(ot->srna, "mode", transform_mode_types, TFM_TRANSLATION, "Mode", "");
1602 }
1603
1604 /* delete operator */
1605 static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
1606 {
1607         Scene *scene= CTX_data_scene(C);
1608         Editing *ed= seq_give_editing(scene, FALSE);
1609         Sequence *seq;
1610         MetaStack *ms;
1611         int nothingSelected = TRUE;
1612
1613         seq=seq_active_get(scene);
1614         if (seq && seq->flag & SELECT) { /* avoid a loop since this is likely to be selected */
1615                 nothingSelected = FALSE;
1616         } else {
1617                 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1618                         if (seq->flag & SELECT) {
1619                                 nothingSelected = FALSE;
1620                                 break;
1621                         }
1622                 }
1623         }
1624
1625         if (nothingSelected)
1626                 return OPERATOR_FINISHED;
1627
1628         /* for effects, try to find a replacement input */
1629         for(seq=ed->seqbasep->first; seq; seq=seq->next)
1630                 if((seq->type & SEQ_EFFECT) && !(seq->flag & SELECT))
1631                         del_seq_find_replace_recurs(scene, seq);
1632
1633         /* delete all selected strips */
1634         recurs_del_seq_flag(scene, ed->seqbasep, SELECT, 0);
1635
1636         /* updates lengths etc */
1637         seq= ed->seqbasep->first;
1638         while(seq) {
1639                 calc_sequence(scene, seq);
1640                 seq= seq->next;
1641         }
1642
1643         /* free parent metas */
1644         ms= ed->metastack.last;
1645         while(ms) {
1646                 ms->parseq->strip->len= 0;              /* force new alloc */
1647                 calc_sequence(scene, ms->parseq);
1648                 ms= ms->prev;
1649         }
1650
1651         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1652         
1653         return OPERATOR_FINISHED;
1654 }
1655
1656
1657 void SEQUENCER_OT_delete(wmOperatorType *ot)
1658 {
1659
1660         /* identifiers */
1661         ot->name= "Erase Strips";
1662         ot->idname= "SEQUENCER_OT_delete";
1663         ot->description="Erase selected strips from the sequencer";
1664         
1665         /* api callbacks */
1666         ot->invoke= WM_operator_confirm;
1667         ot->exec= sequencer_delete_exec;
1668         ot->poll= sequencer_edit_poll;
1669         
1670         /* flags */
1671         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1672 }
1673
1674
1675 /* offset clear operator */
1676 static int sequencer_offset_clear_exec(bContext *C, wmOperator *UNUSED(op))
1677 {
1678         Scene *scene= CTX_data_scene(C);
1679         Editing *ed= seq_give_editing(scene, FALSE);
1680         Sequence *seq;
1681
1682         /* for effects, try to find a replacement input */
1683         for(seq=ed->seqbasep->first; seq; seq=seq->next) {
1684                 if((seq->type & SEQ_EFFECT)==0 && (seq->flag & SELECT)) {
1685                         seq->startofs= seq->endofs= seq->startstill= seq->endstill= 0;
1686                 }
1687         }
1688
1689         /* updates lengths etc */
1690         seq= ed->seqbasep->first;
1691         while(seq) {
1692                 calc_sequence(scene, seq);
1693                 seq= seq->next;
1694         }
1695
1696         for(seq=ed->seqbasep->first; seq; seq=seq->next) {
1697                 if((seq->type & SEQ_EFFECT)==0 && (seq->flag & SELECT)) {
1698                         if(seq_test_overlap(ed->seqbasep, seq)) {
1699                                 shuffle_seq(ed->seqbasep, seq, scene);
1700                         }
1701                 }
1702         }
1703
1704         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1705
1706         return OPERATOR_FINISHED;
1707 }
1708
1709
1710 void SEQUENCER_OT_offset_clear(wmOperatorType *ot)
1711 {
1712
1713         /* identifiers */
1714         ot->name= "Clear Strip Offset";
1715         ot->idname= "SEQUENCER_OT_offset_clear";
1716         ot->description="Clear strip offsets from the start and end frames";
1717
1718         /* api callbacks */
1719         ot->exec= sequencer_offset_clear_exec;
1720         ot->poll= sequencer_edit_poll;
1721
1722         /* flags */
1723         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1724 }
1725
1726
1727 /* separate_images operator */
1728 static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
1729 {
1730         Scene *scene= CTX_data_scene(C);
1731         Editing *ed= seq_give_editing(scene, FALSE);
1732         
1733         Sequence *seq, *seq_new;
1734         Strip *strip_new;
1735         StripElem *se, *se_new;
1736         int start_ofs, cfra, frame_end;
1737         int step= RNA_int_get(op->ptr, "length");
1738
1739         seq= ed->seqbasep->first; /* poll checks this is valid */
1740
1741         while (seq) {
1742                 if((seq->flag & SELECT) && (seq->type == SEQ_IMAGE) && (seq->len > 1)) {
1743                         /* remove seq so overlap tests dont conflict,
1744                         see seq_free_sequence below for the real free'ing */
1745                         BLI_remlink(ed->seqbasep, seq);
1746                         /* if(seq->ipo) seq->ipo->id.us--; */
1747                         /* XXX, remove fcurve and assign to split image strips */
1748
1749                         start_ofs = cfra = seq_tx_get_final_left(seq, 0);
1750                         frame_end = seq_tx_get_final_right(seq, 0);
1751
1752                         while (cfra < frame_end) {
1753                                 /* new seq */
1754                                 se = give_stripelem(seq, cfra);
1755
1756                                 seq_new= seq_dupli_recursive(scene, scene, seq, SEQ_DUPE_UNIQUE_NAME);
1757                                 BLI_addtail(ed->seqbasep, seq_new);
1758
1759                                 seq_new->start= start_ofs;
1760                                 seq_new->type= SEQ_IMAGE;
1761                                 seq_new->len = 1;
1762                                 seq_new->endstill = step-1;
1763
1764                                 /* new strip */
1765                                 strip_new= seq_new->strip;
1766                                 strip_new->len= 1;
1767                                 strip_new->us= 1;
1768
1769                                 /* new stripdata */
1770                                 se_new= strip_new->stripdata;
1771                                 BLI_strncpy(se_new->name, se->name, sizeof(se_new->name));
1772                                 calc_sequence(scene, seq_new);
1773
1774                                 if(step > 1) {
1775                                         seq_new->flag &= ~SEQ_OVERLAP;
1776                                         if (seq_test_overlap(ed->seqbasep, seq_new)) {
1777                                                 shuffle_seq(ed->seqbasep, seq_new, scene);
1778                                         }
1779                                 }
1780
1781                                 /* XXX, COPY FCURVES */
1782
1783                                 cfra++;
1784                                 start_ofs += step;
1785                         }
1786
1787                         seq_free_sequence(scene, seq);
1788                         seq = seq->next;
1789                 } else {
1790                         seq = seq->next;
1791                 }
1792         }
1793
1794         /* as last: */
1795         sort_seq(scene);
1796         
1797         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1798
1799         return OPERATOR_FINISHED;
1800 }
1801
1802
1803 void SEQUENCER_OT_images_separate(wmOperatorType *ot)
1804 {
1805         /* identifiers */
1806         ot->name= "Separate Images";
1807         ot->idname= "SEQUENCER_OT_images_separate";
1808         ot->description="On image sequence strips, it returns a strip for each image";
1809         
1810         /* api callbacks */
1811         ot->exec= sequencer_separate_images_exec;
1812         ot->poll= sequencer_edit_poll;
1813         
1814         /* flags */
1815         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1816
1817         RNA_def_int(ot->srna, "length", 1, 1, 1000, "Length", "Length of each frame", 1, INT_MAX);
1818 }
1819
1820
1821 /* META Operators */
1822
1823 /* separate_meta_toggle operator */
1824 static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
1825 {
1826         Scene *scene= CTX_data_scene(C);
1827         Editing *ed= seq_give_editing(scene, FALSE);
1828         Sequence *last_seq= seq_active_get(scene);
1829         MetaStack *ms;
1830
1831         if(last_seq && last_seq->type==SEQ_META && last_seq->flag & SELECT) {
1832                 /* Enter Metastrip */
1833                 ms= MEM_mallocN(sizeof(MetaStack), "metastack");
1834                 BLI_addtail(&ed->metastack, ms);
1835                 ms->parseq= last_seq;
1836                 ms->oldbasep= ed->seqbasep;
1837
1838                 ed->seqbasep= &last_seq->seqbase;
1839
1840                 seq_active_set(scene, NULL);
1841
1842         }
1843         else {
1844                 /* Exit Metastrip (if possible) */
1845
1846                 Sequence *seq;
1847
1848                 if(ed->metastack.first==NULL)
1849                         return OPERATOR_CANCELLED;
1850
1851                 ms= ed->metastack.last;
1852                 BLI_remlink(&ed->metastack, ms);
1853
1854                 ed->seqbasep= ms->oldbasep;
1855
1856                 /* recalc all: the meta can have effects connected to it */
1857                 for(seq= ed->seqbasep->first; seq; seq= seq->next)
1858                         calc_sequence(scene, seq);
1859
1860                 seq_active_set(scene, ms->parseq);
1861
1862                 ms->parseq->flag |= SELECT;
1863                 recurs_sel_seq(ms->parseq);
1864
1865                 MEM_freeN(ms);
1866
1867         }
1868
1869         seq_update_muting(ed);
1870         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1871
1872         return OPERATOR_FINISHED;
1873 }
1874
1875 void SEQUENCER_OT_meta_toggle(wmOperatorType *ot)
1876 {
1877         /* identifiers */
1878         ot->name= "Toggle Meta Strip";
1879         ot->idname= "SEQUENCER_OT_meta_toggle";
1880         ot->description="Toggle a metastrip (to edit enclosed strips)";
1881         
1882         /* api callbacks */
1883         ot->exec= sequencer_meta_toggle_exec;
1884         ot->poll= sequencer_edit_poll;
1885         
1886         /* flags */
1887         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1888 }
1889
1890
1891 /* separate_meta_make operator */
1892 static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
1893 {
1894         Scene *scene= CTX_data_scene(C);
1895         Editing *ed= seq_give_editing(scene, FALSE);
1896         
1897         Sequence *seq, *seqm, *next, *last_seq = seq_active_get(scene);
1898         int channel_max= 1;
1899
1900         if(seqbase_isolated_sel_check(ed->seqbasep)==FALSE) {
1901                 BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
1902                 return OPERATOR_CANCELLED;
1903         }
1904
1905         /* remove all selected from main list, and put in meta */
1906
1907         seqm= alloc_sequence(ed->seqbasep, 1, 1); /* channel number set later */
1908         strcpy(seqm->name+2, "MetaStrip");
1909         seqm->type= SEQ_META;
1910         seqm->flag= SELECT;
1911
1912         seq= ed->seqbasep->first;
1913         while(seq) {
1914                 next= seq->next;
1915                 if(seq!=seqm && (seq->flag & SELECT)) {
1916                         channel_max= MAX2(seq->machine, channel_max);
1917                         BLI_remlink(ed->seqbasep, seq);
1918                         BLI_addtail(&seqm->seqbase, seq);
1919                 }
1920                 seq= next;
1921         }
1922         seqm->machine= last_seq ? last_seq->machine : channel_max;
1923         calc_sequence(scene, seqm);
1924
1925         seqm->strip= MEM_callocN(sizeof(Strip), "metastrip");
1926         seqm->strip->len= seqm->len;
1927         seqm->strip->us= 1;
1928         
1929         seq_active_set(scene, seqm);
1930
1931         if( seq_test_overlap(ed->seqbasep, seqm) ) shuffle_seq(ed->seqbasep, seqm, scene);
1932
1933         seq_update_muting(ed);
1934
1935         seqbase_unique_name_recursive(&scene->ed->seqbase, seqm);
1936
1937         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1938
1939         return OPERATOR_FINISHED;
1940 }
1941
1942 void SEQUENCER_OT_meta_make(wmOperatorType *ot)
1943 {
1944         /* identifiers */
1945         ot->name= "Make Meta Strip";
1946         ot->idname= "SEQUENCER_OT_meta_make";
1947         ot->description="Group selected strips into a metastrip";
1948         
1949         /* api callbacks */
1950         ot->invoke= WM_operator_confirm;
1951         ot->exec= sequencer_meta_make_exec;
1952         ot->poll= sequencer_edit_poll;
1953         
1954         /* flags */
1955         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1956 }
1957
1958
1959 static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
1960 {
1961         if (seq == seqm) return 1;
1962         else if (seq->seq1 && seq_depends_on_meta(seq->seq1, seqm)) return 1;
1963         else if (seq->seq2 && seq_depends_on_meta(seq->seq2, seqm)) return 1;
1964         else if (seq->seq3 && seq_depends_on_meta(seq->seq3, seqm)) return 1;
1965         else return 0;
1966 }
1967
1968 /* separate_meta_make operator */
1969 static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op))
1970 {
1971         Scene *scene= CTX_data_scene(C);
1972         Editing *ed= seq_give_editing(scene, FALSE);
1973
1974         Sequence *seq, *last_seq = seq_active_get(scene); /* last_seq checks ed==NULL */
1975
1976         if(last_seq==NULL || last_seq->type!=SEQ_META)
1977                 return OPERATOR_CANCELLED;
1978
1979         BLI_movelisttolist(ed->seqbasep, &last_seq->seqbase);
1980
1981         last_seq->seqbase.first= NULL;
1982         last_seq->seqbase.last= NULL;
1983
1984         BLI_remlink(ed->seqbasep, last_seq);
1985         seq_free_sequence(scene, last_seq);
1986
1987         /* emtpy meta strip, delete all effects depending on it */
1988         for(seq=ed->seqbasep->first; seq; seq=seq->next)
1989                 if((seq->type & SEQ_EFFECT) && seq_depends_on_meta(seq, last_seq))
1990                         seq->flag |= SEQ_FLAG_DELETE;
1991
1992         recurs_del_seq_flag(scene, ed->seqbasep, SEQ_FLAG_DELETE, 0);
1993
1994         /* test for effects and overlap
1995          * dont use SEQP_BEGIN since that would be recursive */
1996         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1997                 if(seq->flag & SELECT) {
1998                         seq->flag &= ~SEQ_OVERLAP;
1999                         if(seq_test_overlap(ed->seqbasep, seq)) {
2000                                 shuffle_seq(ed->seqbasep, seq, scene);
2001                         }
2002                 }
2003         }
2004
2005         sort_seq(scene);
2006         seq_update_muting(ed);
2007
2008         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2009
2010         return OPERATOR_FINISHED;
2011 }
2012
2013 void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
2014 {
2015         /* identifiers */
2016         ot->name= "UnMeta Strip";
2017         ot->idname= "SEQUENCER_OT_meta_separate";
2018         ot->description="Put the contents of a metastrip back in the sequencer";
2019         
2020         /* api callbacks */
2021         ot->invoke= WM_operator_confirm;
2022         ot->exec= sequencer_meta_separate_exec;
2023         ot->poll= sequencer_edit_poll;
2024         
2025         /* flags */
2026         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2027 }
2028
2029 /* view_all operator */
2030 static int sequencer_view_all_exec(bContext *C, wmOperator *UNUSED(op))
2031 {
2032         //Scene *scene= CTX_data_scene(C);
2033         bScreen *sc= CTX_wm_screen(C);
2034         ScrArea *area= CTX_wm_area(C);
2035         //ARegion *ar= CTX_wm_region(C);
2036         View2D *v2d= UI_view2d_fromcontext(C);
2037
2038         v2d->cur= v2d->tot;
2039         UI_view2d_curRect_validate(v2d);
2040         UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
2041         
2042         ED_area_tag_redraw(CTX_wm_area(C));
2043         return OPERATOR_FINISHED;
2044 }
2045
2046 void SEQUENCER_OT_view_all(wmOperatorType *ot)
2047 {
2048         /* identifiers */
2049         ot->name= "View All";
2050         ot->idname= "SEQUENCER_OT_view_all";
2051         ot->description="View all the strips in the sequencer";
2052         
2053         /* api callbacks */
2054         ot->exec= sequencer_view_all_exec;
2055         ot->poll= ED_operator_sequencer_active;
2056         
2057         /* flags */
2058         ot->flag= OPTYPE_REGISTER;
2059 }
2060
2061 /* view_all operator */
2062 static int sequencer_view_all_preview_exec(bContext *C, wmOperator *UNUSED(op))
2063 {
2064         bScreen *sc= CTX_wm_screen(C);
2065         ScrArea *area= CTX_wm_area(C);
2066 #if 0
2067         ARegion *ar= CTX_wm_region(C);
2068         SpaceSeq *sseq= area->spacedata.first;
2069         Scene *scene= CTX_data_scene(C);
2070 #endif
2071         View2D *v2d= UI_view2d_fromcontext(C);
2072
2073         v2d->cur= v2d->tot;
2074         UI_view2d_curRect_validate(v2d);
2075         UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
2076         
2077 #if 0
2078         /* Like zooming on an image view */
2079         float zoomX, zoomY;
2080         int width, height, imgwidth, imgheight;
2081
2082         width = ar->winx;
2083         height = ar->winy;
2084
2085         seq_reset_imageofs(sseq);
2086
2087         imgwidth= (scene->r.size*scene->r.xsch)/100;
2088         imgheight= (scene->r.size*scene->r.ysch)/100;
2089
2090         /* Apply aspect, dosnt need to be that accurate */
2091         imgwidth= (int)(imgwidth * (scene->r.xasp / scene->r.yasp));
2092
2093         if (((imgwidth >= width) || (imgheight >= height)) &&
2094                 ((width > 0) && (height > 0))) {
2095
2096                 /* Find the zoom value that will fit the image in the image space */
2097                 zoomX = ((float)width) / ((float)imgwidth);
2098                 zoomY = ((float)height) / ((float)imgheight);
2099                 sseq->zoom= (zoomX < zoomY) ? zoomX : zoomY;
2100
2101                 sseq->zoom = 1.0f / power_of_2(1/ MIN2(zoomX, zoomY) );
2102         }
2103         else {
2104                 sseq->zoom= 1.0f;
2105         }
2106 #endif
2107
2108         ED_area_tag_redraw(CTX_wm_area(C));
2109         return OPERATOR_FINISHED;
2110 }
2111
2112 void SEQUENCER_OT_view_all_preview(wmOperatorType *ot)
2113 {
2114         /* identifiers */
2115         ot->name= "View All";
2116         ot->idname= "SEQUENCER_OT_view_all_preview";
2117         ot->description="Zoom preview to fit in the area";
2118         
2119         /* api callbacks */
2120         ot->exec= sequencer_view_all_preview_exec;
2121         ot->poll= ED_operator_sequencer_active;
2122         
2123         /* flags */
2124         ot->flag= OPTYPE_REGISTER;
2125 }
2126
2127
2128 static int sequencer_view_zoom_ratio_exec(bContext *C, wmOperator *op)
2129 {
2130         RenderData *r= &CTX_data_scene(C)->r;
2131         View2D *v2d= UI_view2d_fromcontext(C);
2132
2133         float ratio= RNA_float_get(op->ptr, "ratio");
2134
2135         float winx= (int)(r->size * r->xsch)/100;
2136         float winy= (int)(r->size * r->ysch)/100;
2137
2138         float facx= (v2d->mask.xmax - v2d->mask.xmin) / winx;
2139         float facy= (v2d->mask.ymax - v2d->mask.ymin) / winy;
2140
2141         BLI_resize_rctf(&v2d->cur, (int)(winx*facx*ratio) + 1, (int)(winy*facy*ratio) + 1);
2142
2143         ED_region_tag_redraw(CTX_wm_region(C));
2144
2145         return OPERATOR_FINISHED;
2146 }
2147
2148 void SEQUENCER_OT_view_zoom_ratio(wmOperatorType *ot)
2149 {
2150         /* identifiers */
2151         ot->name= "Sequencer View Zoom Ratio";
2152         ot->idname= "SEQUENCER_OT_view_zoom_ratio";
2153         ot->description = "Change zoom ratio of sequencer preview";
2154
2155         /* api callbacks */
2156         ot->exec= sequencer_view_zoom_ratio_exec;
2157         ot->poll= ED_operator_sequencer_active;
2158
2159         /* properties */
2160         RNA_def_float(ot->srna, "ratio", 1.0f, 0.0f, FLT_MAX,
2161                 "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out", -FLT_MAX, FLT_MAX);
2162 }
2163
2164
2165 #if 0
2166 static EnumPropertyItem view_type_items[] = {
2167                 {SEQ_VIEW_SEQUENCE, "SEQUENCER", ICON_SEQ_SEQUENCER, "Sequencer", ""},
2168                 {SEQ_VIEW_PREVIEW,  "PREVIEW", ICON_SEQ_PREVIEW, "Image Preview", ""},
2169                 {SEQ_VIEW_SEQUENCE_PREVIEW,  "SEQUENCER_PREVIEW", ICON_SEQ_SEQUENCER, "Sequencer and Image Preview", ""},
2170                 {0, NULL, 0, NULL, NULL}};
2171 #endif
2172
2173 /* view_all operator */
2174 static int sequencer_view_toggle_exec(bContext *C, wmOperator *UNUSED(op))
2175 {
2176         SpaceSeq *sseq= (SpaceSeq *)CTX_wm_space_data(C);
2177
2178         sseq->view++;
2179         if (sseq->view > SEQ_VIEW_SEQUENCE_PREVIEW) sseq->view = SEQ_VIEW_SEQUENCE;
2180
2181         ED_area_tag_refresh(CTX_wm_area(C));
2182
2183         return OPERATOR_FINISHED;
2184 }
2185
2186 void SEQUENCER_OT_view_toggle(wmOperatorType *ot)
2187 {
2188         /* identifiers */
2189         ot->name= "View Toggle";
2190         ot->idname= "SEQUENCER_OT_view_toggle";
2191         ot->description="Toggle between sequencer views (sequence, preview, both)";
2192         
2193         /* api callbacks */
2194         ot->exec= sequencer_view_toggle_exec;
2195         ot->poll= ED_operator_sequencer_active;
2196         
2197         /* flags */
2198         ot->flag= OPTYPE_REGISTER;
2199 }
2200
2201
2202 /* view_selected operator */
2203 static int sequencer_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
2204 {
2205         Scene *scene= CTX_data_scene(C);
2206         View2D *v2d= UI_view2d_fromcontext(C);
2207         ScrArea *area= CTX_wm_area(C);
2208         bScreen *sc= CTX_wm_screen(C);
2209         Editing *ed= seq_give_editing(scene, FALSE);
2210         Sequence *seq;
2211
2212         int xmin=  MAXFRAME*2;
2213         int xmax= -MAXFRAME*2;
2214         int ymin=  MAXSEQ+1;
2215         int ymax= 0;
2216         int orig_height;
2217         int ymid;
2218         int ymargin= 1;
2219         int xmargin= FPS;
2220
2221         if(ed==NULL)
2222                 return OPERATOR_CANCELLED;
2223
2224         for(seq=ed->seqbasep->first; seq; seq=seq->next) {
2225                 if(seq->flag & SELECT) {
2226                         xmin= MIN2(xmin, seq->startdisp);
2227                         xmax= MAX2(xmax, seq->enddisp);
2228
2229                         ymin= MIN2(ymin, seq->machine);
2230                         ymax= MAX2(ymax, seq->machine);
2231                 }
2232         }
2233
2234         if (ymax != 0) {
2235                 
2236                 xmax += xmargin;
2237                 xmin -= xmargin;
2238                 ymax += ymargin;
2239                 ymin -= ymargin;
2240
2241                 orig_height= v2d->cur.ymax - v2d->cur.ymin;
2242
2243                 v2d->cur.xmin= xmin;
2244                 v2d->cur.xmax= xmax;
2245
2246                 v2d->cur.ymin= ymin;
2247                 v2d->cur.ymax= ymax;
2248
2249                 /* only zoom out vertically */
2250                 if (orig_height > v2d->cur.ymax - v2d->cur.ymin) {
2251                         ymid= (v2d->cur.ymax + v2d->cur.ymin) / 2;
2252
2253                         v2d->cur.ymin= ymid - (orig_height/2);
2254                         v2d->cur.ymax= ymid + (orig_height/2);
2255                 }
2256
2257                 UI_view2d_curRect_validate(v2d);
2258                 UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
2259
2260                 ED_area_tag_redraw(CTX_wm_area(C));
2261         }
2262         
2263         return OPERATOR_FINISHED;
2264 }
2265
2266 void SEQUENCER_OT_view_selected(wmOperatorType *ot)
2267 {
2268         /* identifiers */
2269         ot->name= "View Selected";
2270         ot->idname= "SEQUENCER_OT_view_selected";
2271         ot->description="Zoom the sequencer on the selected strips";
2272         
2273         /* api callbacks */
2274         ot->exec= sequencer_view_selected_exec;
2275         ot->poll= ED_operator_sequencer_active;
2276         
2277         /* flags */
2278         ot->flag= OPTYPE_REGISTER;
2279 }
2280
2281
2282 static int find_next_prev_edit(Scene *scene, int cfra, int side)
2283 {
2284         Editing *ed= seq_give_editing(scene, FALSE);
2285         Sequence *seq,*best_seq = NULL,*frame_seq = NULL;
2286         
2287         int dist, best_dist;
2288         best_dist = MAXFRAME*2;
2289
2290         if(ed==NULL) return cfra;
2291         
2292         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
2293                 dist = MAXFRAME*2;
2294                         
2295                 switch (side) {
2296                         case SEQ_SIDE_LEFT:
2297                                 if (seq->startdisp < cfra) {
2298                                         dist = cfra - seq->startdisp;
2299                                 }
2300                                 break;
2301                         case SEQ_SIDE_RIGHT:
2302                                 if (seq->startdisp > cfra) {
2303                                         dist = seq->startdisp - cfra;
2304                                 } else if (seq->startdisp == cfra) {
2305                                         frame_seq=seq;
2306                                 }
2307                                 break;
2308                 }
2309
2310                 if (dist < best_dist) {
2311                         best_dist = dist;
2312                         best_seq = seq;
2313                 }
2314         }
2315
2316         /* if no sequence to the right is found and the
2317            frame is on the start of the last sequence,
2318            move to the end of the last sequence */
2319         if (frame_seq) cfra = frame_seq->enddisp;
2320
2321         return best_seq ? best_seq->startdisp : cfra;
2322 }
2323
2324 static int next_prev_edit_internal(Scene *scene, int side)
2325 {
2326         int change=0;
2327         int cfra = CFRA;
2328         int nfra= find_next_prev_edit(scene, cfra, side);
2329         
2330         if (nfra != cfra) {
2331                 CFRA = nfra;
2332                 change= 1;
2333         }
2334
2335         return change;
2336 }
2337
2338 /* move frame to next edit point operator */
2339 static int sequencer_next_edit_exec(bContext *C, wmOperator *UNUSED(op))
2340 {
2341         Scene *scene= CTX_data_scene(C);
2342         
2343         if(!next_prev_edit_internal(scene, SEQ_SIDE_RIGHT))
2344                 return OPERATOR_CANCELLED;
2345
2346         WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
2347
2348         return OPERATOR_FINISHED;
2349 }
2350
2351 void SEQUENCER_OT_next_edit(wmOperatorType *ot)
2352 {
2353         /* identifiers */
2354         ot->name= "Next Edit";
2355         ot->idname= "SEQUENCER_OT_next_edit";
2356         ot->description="Move frame to next edit point";
2357         
2358         /* api callbacks */
2359         ot->exec= sequencer_next_edit_exec;
2360         ot->poll= sequencer_edit_poll;
2361         
2362         /* flags */
2363         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2364         
2365         /* properties */
2366 }
2367
2368 /* move frame to previous edit point operator */
2369 static int sequencer_previous_edit_exec(bContext *C, wmOperator *UNUSED(op))
2370 {
2371         Scene *scene= CTX_data_scene(C);
2372         
2373         if(!next_prev_edit_internal(scene, SEQ_SIDE_LEFT))
2374                 return OPERATOR_CANCELLED;
2375
2376         WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
2377         
2378         return OPERATOR_FINISHED;
2379 }
2380
2381 void SEQUENCER_OT_previous_edit(wmOperatorType *ot)
2382 {
2383         /* identifiers */
2384         ot->name= "Previous Edit";
2385         ot->idname= "SEQUENCER_OT_previous_edit";
2386         ot->description="Move frame to previous edit point";
2387         
2388         /* api callbacks */
2389         ot->exec= sequencer_previous_edit_exec;
2390         ot->poll= sequencer_edit_poll;
2391         
2392         /* flags */
2393         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2394         
2395         /* properties */
2396 }
2397
2398 static void swap_sequence(Scene* scene, Sequence* seqa, Sequence* seqb)
2399 {
2400         int gap = seqb->startdisp - seqa->enddisp;
2401         seqb->start = (seqb->start - seqb->startdisp) + seqa->startdisp;
2402         calc_sequence(scene, seqb);
2403         seqa->start = (seqa->start - seqa->startdisp) + seqb->enddisp + gap;
2404         calc_sequence(scene, seqa);
2405 }
2406
2407 #if 0
2408 static Sequence* sequence_find_parent(Scene* scene, Sequence* child)
2409 {
2410         Editing *ed= seq_give_editing(scene, FALSE);
2411         Sequence *parent= NULL;
2412         Sequence *seq;
2413
2414         if(ed==NULL) return NULL;
2415
2416         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
2417                 if ( (seq != child) && seq_is_parent(seq, child) ) {
2418                         parent = seq;
2419                         break;
2420                 }
2421         }
2422
2423         return parent;
2424 }
2425 #endif
2426
2427 static int sequencer_swap_exec(bContext *C, wmOperator *op)
2428 {
2429         Scene *scene= CTX_data_scene(C);
2430         Editing *ed= seq_give_editing(scene, FALSE);
2431         Sequence *active_seq = seq_active_get(scene);
2432         Sequence *seq, *iseq;
2433         int side= RNA_enum_get(op->ptr, "side");
2434
2435         if(active_seq==NULL) return OPERATOR_CANCELLED;
2436
2437         seq = find_next_prev_sequence(scene, active_seq, side, -1);
2438         
2439         if(seq) {
2440                 
2441                 /* disallow effect strips */
2442                 if (get_sequence_effect_num_inputs(seq->type) >= 1 && (seq->effectdata || seq->seq1 || seq->seq2 || seq->seq3))
2443                         return OPERATOR_CANCELLED;
2444                 if ((get_sequence_effect_num_inputs(active_seq->type) >= 1) && (active_seq->effectdata || active_seq->seq1 || active_seq->seq2 || active_seq->seq3))
2445                         return OPERATOR_CANCELLED;
2446
2447                 switch (side) {
2448                         case SEQ_SIDE_LEFT: 
2449                                 swap_sequence(scene, seq, active_seq);
2450                                 break;
2451                         case SEQ_SIDE_RIGHT: 
2452                                 swap_sequence(scene, active_seq, seq);
2453                                 break;
2454                 }
2455
2456                 // XXX - should be a generic function
2457                 for(iseq= scene->ed->seqbasep->first; iseq; iseq= iseq->next) {
2458                         if((iseq->type & SEQ_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
2459                                 calc_sequence(scene, iseq);
2460                         }
2461                 }
2462
2463                 /* do this in a new loop since both effects need to be calculated first */
2464                 for(iseq= scene->ed->seqbasep->first; iseq; iseq= iseq->next) {
2465                         if((iseq->type & SEQ_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
2466                                 /* this may now overlap */
2467                                 if( seq_test_overlap(ed->seqbasep, iseq) ) {
2468                                         shuffle_seq(ed->seqbasep, iseq, scene);
2469                                 }
2470                         }
2471                 }
2472
2473
2474
2475                 sort_seq(scene);
2476
2477                 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2478
2479                 return OPERATOR_FINISHED;
2480         }
2481
2482         return OPERATOR_CANCELLED;
2483 }
2484
2485 void SEQUENCER_OT_swap(wmOperatorType *ot)
2486 {
2487         /* identifiers */
2488         ot->name= "Swap Strip";
2489         ot->idname= "SEQUENCER_OT_swap";
2490         ot->description="Swap active strip with strip to the right or left";
2491         
2492         /* api callbacks */
2493         ot->exec= sequencer_swap_exec;
2494         ot->poll= sequencer_edit_poll;
2495         
2496         /* flags */
2497         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2498         
2499         /* properties */
2500         RNA_def_enum(ot->srna, "side", prop_side_lr_types, SEQ_SIDE_RIGHT, "Side", "Side of the strip to swap");
2501 }
2502
2503 static int sequencer_rendersize_exec(bContext *C, wmOperator *UNUSED(op))
2504 {
2505         int retval = OPERATOR_CANCELLED;
2506         Scene *scene= CTX_data_scene(C);
2507         Sequence *active_seq = seq_active_get(scene);
2508         StripElem *se = NULL;
2509
2510         if(active_seq==NULL)
2511                 return OPERATOR_CANCELLED;
2512
2513
2514         if (active_seq->strip) {
2515                 switch (active_seq->type) {
2516                 case SEQ_IMAGE:
2517                         se = give_stripelem(active_seq, scene->r.cfra);
2518                         break;
2519                 case SEQ_MOVIE:
2520                         se = active_seq->strip->stripdata;
2521                         break;
2522                 case SEQ_SCENE:
2523                 case SEQ_META:
2524                 case SEQ_RAM_SOUND:
2525                 case SEQ_HD_SOUND:
2526                 default:
2527                         break;
2528                 }
2529         }
2530
2531         if (se) {
2532                 // prevent setting the render size if sequence values aren't initialized
2533                 if ( (se->orig_width > 0) && (se->orig_height > 0) ) {
2534                         scene->r.xsch= se->orig_width;
2535                         scene->r.ysch= se->orig_height;
2536                         WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
2537                         retval = OPERATOR_FINISHED;
2538                 }
2539         }
2540
2541         return retval;
2542 }
2543
2544 void SEQUENCER_OT_rendersize(wmOperatorType *ot)
2545 {
2546         /* identifiers */
2547         ot->name= "Set Render Size";
2548         ot->idname= "SEQUENCER_OT_rendersize";
2549         ot->description="Set render size and aspect from active sequence";
2550         
2551         /* api callbacks */
2552         ot->exec= sequencer_rendersize_exec;
2553         ot->poll= sequencer_edit_poll;
2554         
2555         /* flags */
2556         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2557         
2558         /* properties */
2559 }
2560
2561 static void seq_del_sound(Scene *scene, Sequence *seq)
2562 {
2563         if(seq->type == SEQ_META) {
2564                 Sequence *iseq;
2565                 for(iseq= seq->seqbase.first; iseq; iseq= iseq->next) {
2566                         seq_del_sound(scene, iseq);
2567                 }
2568         }
2569         else if(seq->scene_sound) {
2570                 sound_remove_scene_sound(scene, seq->scene_sound);
2571                 seq->scene_sound = NULL;
2572         }
2573 }
2574
2575 /* TODO, validate scenes */
2576 static int sequencer_copy_exec(bContext *C, wmOperator *op)
2577 {
2578         Scene *scene= CTX_data_scene(C);
2579         Editing *ed= seq_give_editing(scene, FALSE);
2580         Sequence *seq;
2581
2582         ListBase nseqbase= {NULL, NULL};
2583
2584         seq_free_clipboard();
2585
2586         if(seqbase_isolated_sel_check(ed->seqbasep)==FALSE) {
2587                 BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
2588                 return OPERATOR_CANCELLED;
2589         }
2590
2591         seqbase_dupli_recursive(scene, NULL, &nseqbase, ed->seqbasep, SEQ_DUPE_UNIQUE_NAME);
2592
2593         /* To make sure the copied strips have unique names between each other add
2594          * them temporarily to the end of the original seqbase. (bug 25932)
2595          */
2596         if(nseqbase.first) {
2597                 Sequence *seq, *first_seq = nseqbase.first;
2598                 BLI_movelisttolist(ed->seqbasep, &nseqbase);
2599
2600                 for(seq=first_seq; seq; seq=seq->next)
2601                         seq_recursive_apply(seq, apply_unique_name_cb, scene);
2602
2603                 seqbase_clipboard.first = first_seq;
2604                 seqbase_clipboard.last = ed->seqbasep->last;
2605
2606                 if(first_seq->prev) {
2607                         first_seq->prev->next = NULL;
2608                         ed->seqbasep->last = first_seq->prev;
2609                         first_seq->prev = NULL;
2610                 }
2611         }
2612
2613         seqbase_clipboard_frame= scene->r.cfra;
2614
2615         /* Need to remove anything that references the current scene */
2616         for(seq= seqbase_clipboard.first; seq; seq= seq->next) {
2617                 seq_del_sound(scene, seq);
2618         }
2619
2620         return OPERATOR_FINISHED;
2621 }
2622
2623 void SEQUENCER_OT_copy(wmOperatorType *ot)
2624 {
2625         /* identifiers */
2626         ot->name= "Copy";
2627         ot->idname= "SEQUENCER_OT_copy";
2628         ot->description="";
2629
2630         /* api callbacks */
2631         ot->exec= sequencer_copy_exec;
2632         ot->poll= sequencer_edit_poll;
2633
2634         /* flags */
2635         ot->flag= OPTYPE_REGISTER;
2636
2637         /* properties */
2638 }
2639
2640 static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op))
2641 {
2642         Scene *scene= CTX_data_scene(C);
2643         Editing *ed= seq_give_editing(scene, TRUE); /* create if needed */
2644         ListBase nseqbase = {NULL, NULL};
2645         int ofs;
2646         Sequence *iseq;
2647
2648         deselect_all_seq(scene);
2649         ofs = scene->r.cfra - seqbase_clipboard_frame;
2650
2651         seqbase_dupli_recursive(scene, NULL, &nseqbase, &seqbase_clipboard, SEQ_DUPE_UNIQUE_NAME);
2652
2653         /* transform pasted strips before adding */
2654         if(ofs) {
2655                 for(iseq= nseqbase.first; iseq; iseq= iseq->next) {
2656                         seq_translate(scene, iseq, ofs);
2657                         seq_sound_init(scene, iseq);
2658                 }
2659         }
2660
2661         iseq = nseqbase.first;
2662
2663         BLI_movelisttolist(ed->seqbasep, &nseqbase);
2664
2665         /* make sure the pasted strips have unique names between them */
2666         for(; iseq; iseq=iseq->next)
2667                 seq_recursive_apply(iseq, apply_unique_name_cb, scene);
2668
2669         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2670
2671         return OPERATOR_FINISHED;
2672 }
2673
2674 void SEQUENCER_OT_paste(wmOperatorType *ot)
2675 {
2676         /* identifiers */
2677         ot->name= "Paste";
2678         ot->idname= "SEQUENCER_OT_paste";
2679         ot->description="";
2680
2681         /* api callbacks */
2682         ot->exec= sequencer_paste_exec;
2683         ot->poll= ED_operator_sequencer_active;
2684
2685         /* flags */
2686         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2687
2688         /* properties */
2689 }
2690
2691 static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
2692 {
2693         Scene *scene= CTX_data_scene(C);
2694         Sequence *seq_act;
2695         Sequence *seq_other;
2696         const char *error_msg;
2697
2698         if(seq_active_pair_get(scene, &seq_act, &seq_other) == 0) {
2699                 BKE_report(op->reports, RPT_ERROR, "Must select 2 strips");
2700                 return OPERATOR_CANCELLED;
2701         }
2702
2703         if(seq_swap(seq_act, seq_other, &error_msg) == 0) {
2704                 BKE_report(op->reports, RPT_ERROR, error_msg);
2705                 return OPERATOR_CANCELLED;
2706         }
2707
2708         sound_remove_scene_sound(scene, seq_act->scene_sound);
2709         sound_remove_scene_sound(scene, seq_other->scene_sound);
2710
2711         seq_act->scene_sound= NULL;
2712         seq_other->scene_sound= NULL;
2713
2714         calc_sequence(scene, seq_act);
2715         calc_sequence(scene, seq_other);
2716
2717         if(seq_act->sound)              sound_add_scene_sound(scene, seq_act, seq_act->startdisp, seq_act->enddisp, seq_act->startofs + seq_act->anim_startofs);
2718         if(seq_other->sound)    sound_add_scene_sound(scene, seq_other, seq_other->startdisp, seq_other->enddisp, seq_other->startofs + seq_other->anim_startofs);
2719
2720         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2721
2722         return OPERATOR_FINISHED;
2723 }
2724
2725 void SEQUENCER_OT_swap_data(wmOperatorType *ot)
2726 {
2727         /* identifiers */
2728         ot->name= "Sequencer Swap Data";
2729         ot->idname= "SEQUENCER_OT_swap_data";
2730         ot->description="Swap 2 sequencer strips";
2731
2732         /* api callbacks */
2733         ot->exec= sequencer_swap_data_exec;
2734         ot->poll= ED_operator_sequencer_active;
2735
2736         /* flags */
2737         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2738
2739         /* properties */
2740 }
2741
2742 /* borderselect operator */
2743 static int view_ghost_border_exec(bContext *C, wmOperator *op)
2744 {
2745         Scene *scene= CTX_data_scene(C);
2746         Editing *ed= seq_give_editing(scene, FALSE);
2747         View2D *v2d= UI_view2d_fromcontext(C);
2748
2749         rctf rect;
2750
2751         /* convert coordinates of rect to 'tot' rect coordinates */
2752         UI_view2d_region_to_view(v2d, RNA_int_get(op->ptr, "xmin"), RNA_int_get(op->ptr, "ymin"), &rect.xmin, &rect.ymin);
2753         UI_view2d_region_to_view(v2d, RNA_int_get(op->ptr, "xmax"), RNA_int_get(op->ptr, "ymax"), &rect.xmax, &rect.ymax);
2754
2755         if(ed==NULL)
2756                 return OPERATOR_CANCELLED;
2757
2758         rect.xmin /=  (float)(ABS(v2d->tot.xmax - v2d->tot.xmin));
2759         rect.ymin /=  (float)(ABS(v2d->tot.ymax - v2d->tot.ymin));
2760
2761         rect.xmax /=  (float)(ABS(v2d->tot.xmax - v2d->tot.xmin));
2762         rect.ymax /=  (float)(ABS(v2d->tot.ymax - v2d->tot.ymin));
2763
2764         rect.xmin+=0.5f;
2765         rect.xmax+=0.5f;
2766         rect.ymin+=0.5f;
2767         rect.ymax+=0.5f;
2768
2769         CLAMP(rect.xmin, 0.0f, 1.0f);
2770         CLAMP(rect.ymin, 0.0f, 1.0f);
2771         CLAMP(rect.xmax, 0.0f, 1.0f);
2772         CLAMP(rect.ymax, 0.0f, 1.0f);
2773
2774         scene->ed->over_border= rect;
2775
2776         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2777
2778         return OPERATOR_FINISHED;
2779 }
2780
2781 /* ****** Border Select ****** */
2782 void SEQUENCER_OT_view_ghost_border(wmOperatorType *ot)
2783 {
2784         /* identifiers */
2785         ot->name= "Border Offset View";
2786         ot->idname= "SEQUENCER_OT_view_ghost_border";
2787         ot->description="Enable border select mode";
2788
2789         /* api callbacks */
2790         ot->invoke= WM_border_select_invoke;
2791         ot->exec= view_ghost_border_exec;
2792         ot->modal= WM_border_select_modal;
2793         ot->poll= sequencer_view_poll;
2794         ot->cancel= WM_border_select_cancel;
2795
2796         /* flags */
2797         ot->flag= 0;
2798
2799         /* rna */
2800         WM_operator_properties_gesture_border(ot, FALSE);
2801 }
2802
2803 /* rebuild_proxy operator */
2804 static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
2805 {
2806         Scene *scene = CTX_data_scene(C);
2807         Editing *ed = seq_give_editing(scene, FALSE);
2808         Sequence * seq;
2809
2810         SEQP_BEGIN(ed, seq) {
2811                 if ((seq->flag & SELECT)) {
2812                         seq_proxy_build_job(C, seq);
2813                 }
2814         }
2815         SEQ_END
2816                 
2817         return OPERATOR_FINISHED;
2818 }
2819
2820 void SEQUENCER_OT_rebuild_proxy(wmOperatorType *ot)
2821 {
2822         /* identifiers */
2823         ot->name= "Rebuild Proxy and Timecode Indices";
2824         ot->idname= "SEQUENCER_OT_rebuild_proxy";
2825         ot->description="Rebuild all selected proxies and timecode indeces using the job system";
2826         
2827         /* api callbacks */
2828         ot->exec= sequencer_rebuild_proxy_exec;
2829         ot->poll= ED_operator_sequencer_active;
2830         
2831         /* flags */
2832         ot->flag= OPTYPE_REGISTER;
2833 }
2834
2835 /* change ops */
2836
2837 static EnumPropertyItem prop_change_effect_input_types[] = {
2838         {0, "A_B", 0, "A -> B", ""},
2839         {1, "B_C", 0, "B -> C", ""},
2840         {2, "A_C", 0, "A -> C", ""},
2841         {0, NULL, 0, NULL, NULL}
2842 };
2843
2844 static int sequencer_change_effect_input_exec(bContext *C, wmOperator *op)
2845 {
2846         Scene *scene= CTX_data_scene(C);
2847         Editing *ed= seq_give_editing(scene, FALSE);
2848         Sequence *seq= seq_active_get(scene);
2849
2850         Sequence **seq_1, **seq_2;
2851
2852         switch(RNA_enum_get(op->ptr, "swap")) {
2853                 case 0:
2854                         seq_1= &seq->seq1;
2855                         seq_2= &seq->seq2;
2856                         break;
2857                 case 1:
2858                         seq_1= &seq->seq2;
2859                         seq_2= &seq->seq3;
2860                         break;
2861                 default: /* 2 */
2862                         seq_1= &seq->seq1;
2863                         seq_2= &seq->seq3;
2864                         break;
2865         }
2866
2867         if(*seq_1 == NULL || *seq_2 == NULL) {
2868                 BKE_report(op->reports, RPT_ERROR, "One of the effect inputs is unset, can't swap");
2869                 return OPERATOR_CANCELLED;
2870         }
2871         else {
2872                 SWAP(Sequence *, *seq_1, *seq_2);
2873         }
2874
2875         update_changed_seq_and_deps(scene, seq, 0, 1);
2876
2877         /* important else we dont get the imbuf cache flushed */
2878         free_imbuf_seq(scene, &ed->seqbase, FALSE, FALSE);
2879
2880         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2881
2882         return OPERATOR_FINISHED;
2883 }
2884
2885 void SEQUENCER_OT_change_effect_input(struct wmOperatorType *ot)
2886 {
2887         /* identifiers */
2888         ot->name= "Change Effect Input";
2889         ot->idname= "SEQUENCER_OT_change_effect_input";
2890         ot->description="";
2891
2892         /* api callbacks */
2893         ot->exec= sequencer_change_effect_input_exec;
2894         ot->poll= sequencer_effect_poll;
2895
2896         /* flags */
2897         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2898
2899         ot->prop= RNA_def_enum(ot->srna, "swap", prop_change_effect_input_types, 0, "Swap", "The effect inputs to swap");
2900 }
2901
2902 static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op)
2903 {
2904         Scene *scene= CTX_data_scene(C);
2905         Editing *ed= seq_give_editing(scene, FALSE);
2906         Sequence *seq= seq_active_get(scene);
2907         const int new_type= RNA_enum_get(op->ptr, "type");
2908
2909         /* free previous effect and init new effect */
2910         struct SeqEffectHandle sh;
2911
2912         if ((seq->type & SEQ_EFFECT) == 0) {
2913                 return OPERATOR_CANCELLED;
2914         }
2915
2916         /* can someone explain the logic behind only allowing to increse this,
2917          * copied from 2.4x - campbell */
2918         if (get_sequence_effect_num_inputs(seq->type) <
2919                 get_sequence_effect_num_inputs(new_type)
2920         ) {
2921                 BKE_report(op->reports, RPT_ERROR, "New effect needs more input strips");
2922                 return OPERATOR_CANCELLED;
2923         }
2924         else {
2925                 sh = get_sequence_effect(seq);
2926                 sh.free(seq);
2927
2928                 seq->type= new_type;
2929
2930                 sh = get_sequence_effect(seq);
2931                 sh.init(seq);
2932         }
2933
2934         /* update */
2935         update_changed_seq_and_deps(scene, seq, 0, 1);
2936
2937         /* important else we dont get the imbuf cache flushed */
2938         free_imbuf_seq(scene, &ed->seqbase, FALSE, FALSE);
2939
2940         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2941
2942         return OPERATOR_FINISHED;
2943 }
2944
2945 void SEQUENCER_OT_change_effect_type(struct wmOperatorType *ot)
2946 {
2947         /* identifiers */
2948         ot->name= "Change Effect Type";
2949         ot->idname= "SEQUENCER_OT_change_effect_type";
2950         ot->description="";
2951
2952         /* api callbacks */
2953         ot->exec= sequencer_change_effect_type_exec;
2954         ot->poll= sequencer_effect_poll;
2955
2956         /* flags */
2957         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2958
2959         ot->prop= RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_CROSS, "Type", "Sequencer effect type");
2960 }
2961
2962 static int sequencer_change_path_exec(bContext *C, wmOperator *op)
2963 {
2964         Main *bmain= CTX_data_main(C);
2965         Scene *scene= CTX_data_scene(C);
2966         Editing *ed= seq_give_editing(scene, FALSE);
2967         Sequence *seq= seq_active_get(scene);
2968         const int is_relative_path= RNA_boolean_get(op->ptr, "relative_path");
2969
2970         if(seq->type == SEQ_IMAGE) {
2971                 char directory[FILE_MAX];
2972                 const int len= RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
2973                 StripElem *se;
2974
2975                 if(len==0)
2976                         return OPERATOR_CANCELLED;
2977
2978                 RNA_string_get(op->ptr, "directory", directory);
2979                 if (is_relative_path) {
2980                         /* TODO, shouldnt this already be relative from the filesel?
2981                          * (as the 'filepath' is) for now just make relative here,
2982                          * but look into changing after 2.60 - campbell */
2983                         BLI_path_rel(directory, bmain->name);
2984                 }
2985                 BLI_strncpy(seq->strip->dir, directory, sizeof(seq->strip->dir));
2986
2987                 if(seq->strip->stripdata) {
2988                         MEM_freeN(seq->strip->stripdata);
2989                 }
2990                 seq->strip->stripdata= se= MEM_callocN(len*sizeof(StripElem), "stripelem");
2991
2992                 RNA_BEGIN(op->ptr, itemptr, "files") {
2993                         char *filename= RNA_string_get_alloc(&itemptr, "name", NULL, 0);
2994                         BLI_strncpy(se->name, filename, sizeof(se->name));
2995                         MEM_freeN(filename);
2996                         se++;
2997                 }
2998                 RNA_END;
2999
3000                 /* reset these else we wont see all the images */
3001                 seq->anim_startofs= seq->anim_endofs= 0;
3002
3003                 /* correct start/end frames so we dont move
3004                  * important not to set seq->len= len; allow the function to handle it */
3005                 reload_sequence_new_file(scene, seq, TRUE);
3006
3007                 calc_sequence(scene, seq);
3008
3009                 /* important else we dont get the imbuf cache flushed */
3010                 free_imbuf_seq(scene, &ed->seqbase, FALSE, FALSE);
3011         }
3012         else {
3013                 /* lame, set rna filepath */
3014                 PointerRNA seq_ptr;
3015                 PropertyRNA *prop;
3016                 char filepath[FILE_MAX];
3017
3018                 RNA_pointer_create(&scene->id, &RNA_Sequence, seq, &seq_ptr);
3019
3020                 RNA_string_get(op->ptr, "filepath", filepath);
3021                 prop= RNA_struct_find_property(&seq_ptr, "filepath");
3022                 RNA_property_string_set(&seq_ptr, prop, filepath);
3023                 RNA_property_update(C, &seq_ptr, prop);
3024         }
3025
3026         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
3027
3028         return OPERATOR_FINISHED;
3029 }
3030
3031 static int sequencer_change_path_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
3032 {
3033         Scene *scene= CTX_data_scene(C);
3034         Sequence *seq= seq_active_get(scene);
3035
3036         RNA_string_set(op->ptr, "directory", seq->strip->dir);
3037
3038         /* set default display depending on seq type */
3039         if(seq->type == SEQ_IMAGE) {
3040                 RNA_boolean_set(op->ptr, "filter_movie", 0);
3041         }
3042         else {
3043                 RNA_boolean_set(op->ptr, "filter_image", 0);
3044         }
3045
3046         WM_event_add_fileselect(C, op);
3047
3048         return OPERATOR_RUNNING_MODAL;
3049 }
3050
3051 void SEQUENCER_OT_change_path(struct wmOperatorType *ot)
3052 {
3053         /* identifiers */
3054         ot->name= "Change Data/Files";
3055         ot->idname= "SEQUENCER_OT_change_path";
3056         ot->description="";
3057
3058         /* api callbacks */
3059         ot->exec= sequencer_change_path_exec;
3060         ot->invoke= sequencer_change_path_invoke;
3061         ot->poll= sequencer_strip_has_path_poll;
3062
3063         /* flags */
3064         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
3065
3066         WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE|MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_DIRECTORY|WM_FILESEL_RELPATH|WM_FILESEL_FILEPATH|WM_FILESEL_FILES);
3067 }