svn merge -r40197:40311 ^/trunk/blender
[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 effects 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 effects 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         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1487         
1488         return OPERATOR_FINISHED;
1489 }
1490
1491
1492 static int sequencer_cut_invoke(bContext *C, wmOperator *op, wmEvent *event)
1493 {
1494         Scene *scene = CTX_data_scene(C);
1495         View2D *v2d= UI_view2d_fromcontext(C);
1496
1497         int cut_side= SEQ_SIDE_BOTH;
1498         int cut_frame= CFRA;
1499
1500         if (ED_operator_sequencer_active(C) && v2d)
1501                 cut_side= mouse_frame_side(v2d, event->mval[0], cut_frame);
1502         
1503         RNA_int_set(op->ptr, "frame", cut_frame);
1504         RNA_enum_set(op->ptr, "side", cut_side);
1505         /*RNA_enum_set(op->ptr, "type", cut_hard); */ /*This type is set from the key shortcut */
1506
1507         return sequencer_cut_exec(C, op);
1508 }
1509
1510
1511 void SEQUENCER_OT_cut(struct wmOperatorType *ot)
1512 {
1513         /* identifiers */
1514         ot->name= "Cut Strips";
1515         ot->idname= "SEQUENCER_OT_cut";
1516         ot->description="Cut the selected strips";
1517         
1518         /* api callbacks */
1519         ot->invoke= sequencer_cut_invoke;
1520         ot->exec= sequencer_cut_exec;
1521         ot->poll= sequencer_edit_poll;
1522         
1523         /* flags */
1524         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1525         
1526         RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be cut", INT_MIN, INT_MAX);
1527         RNA_def_enum(ot->srna, "type", prop_cut_types, SEQ_CUT_SOFT, "Type", "The type of cut operation to perform on strips");
1528         RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side that remains selected after cutting");
1529 }
1530
1531 /* duplicate operator */
1532 static int apply_unique_name_cb(Sequence *seq, void *arg_pt)
1533 {
1534         Scene *scene= (Scene *)arg_pt;
1535         char name[sizeof(seq->name)-2];
1536
1537         strcpy(name, seq->name+2);
1538         seqbase_unique_name_recursive(&scene->ed->seqbase, seq);
1539         seq_dupe_animdata(scene, name, seq->name+2);
1540         return 1;
1541
1542 }
1543
1544 static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
1545 {
1546         Scene *scene= CTX_data_scene(C);
1547         Editing *ed= seq_give_editing(scene, FALSE);
1548
1549         ListBase nseqbase= {NULL, NULL};
1550
1551         if(ed==NULL)
1552                 return OPERATOR_CANCELLED;
1553
1554         seqbase_dupli_recursive(scene, NULL, &nseqbase, ed->seqbasep, SEQ_DUPE_CONTEXT);
1555
1556         if(nseqbase.first) {
1557                 Sequence * seq= nseqbase.first;
1558                 /* rely on the nseqbase list being added at the end */
1559                 BLI_movelisttolist(ed->seqbasep, &nseqbase);
1560
1561                 for( ; seq; seq= seq->next)
1562                         seq_recursive_apply(seq, apply_unique_name_cb, scene);
1563
1564                 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1565                 return OPERATOR_FINISHED;
1566         }
1567
1568         return OPERATOR_CANCELLED;
1569 }
1570
1571 static int sequencer_add_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1572 {
1573         sequencer_add_duplicate_exec(C, op);
1574
1575         RNA_enum_set(op->ptr, "mode", TFM_TRANSLATION);
1576         WM_operator_name_call(C, "TRANSFORM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
1577
1578         return OPERATOR_FINISHED;
1579 }
1580
1581 void SEQUENCER_OT_duplicate(wmOperatorType *ot)
1582 {
1583         /* identifiers */
1584         ot->name= "Duplicate Strips";
1585         ot->idname= "SEQUENCER_OT_duplicate";
1586         ot->description="Duplicate the selected strips";
1587         
1588         /* api callbacks */
1589         ot->invoke= sequencer_add_duplicate_invoke;
1590         ot->exec= sequencer_add_duplicate_exec;
1591         ot->poll= ED_operator_sequencer_active;
1592         
1593         /* flags */
1594         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1595         
1596         /* to give to transform */
1597         RNA_def_enum(ot->srna, "mode", transform_mode_types, TFM_TRANSLATION, "Mode", "");
1598 }
1599
1600 /* delete operator */
1601 static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
1602 {
1603         Scene *scene= CTX_data_scene(C);
1604         Editing *ed= seq_give_editing(scene, FALSE);
1605         Sequence *seq;
1606         MetaStack *ms;
1607         int nothingSelected = TRUE;
1608
1609         seq=seq_active_get(scene);
1610         if (seq && seq->flag & SELECT) { /* avoid a loop since this is likely to be selected */
1611                 nothingSelected = FALSE;
1612         } else {
1613                 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1614                         if (seq->flag & SELECT) {
1615                                 nothingSelected = FALSE;
1616                                 break;
1617                         }
1618                 }
1619         }
1620
1621         if (nothingSelected)
1622                 return OPERATOR_FINISHED;
1623
1624         /* for effects, try to find a replacement input */
1625         for(seq=ed->seqbasep->first; seq; seq=seq->next)
1626                 if((seq->type & SEQ_EFFECT) && !(seq->flag & SELECT))
1627                         del_seq_find_replace_recurs(scene, seq);
1628
1629         /* delete all selected strips */
1630         recurs_del_seq_flag(scene, ed->seqbasep, SELECT, 0);
1631
1632         /* updates lengths etc */
1633         seq= ed->seqbasep->first;
1634         while(seq) {
1635                 calc_sequence(scene, seq);
1636                 seq= seq->next;
1637         }
1638
1639         /* free parent metas */
1640         ms= ed->metastack.last;
1641         while(ms) {
1642                 ms->parseq->strip->len= 0;              /* force new alloc */
1643                 calc_sequence(scene, ms->parseq);
1644                 ms= ms->prev;
1645         }
1646
1647         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1648         
1649         return OPERATOR_FINISHED;
1650 }
1651
1652
1653 void SEQUENCER_OT_delete(wmOperatorType *ot)
1654 {
1655
1656         /* identifiers */
1657         ot->name= "Erase Strips";
1658         ot->idname= "SEQUENCER_OT_delete";
1659         ot->description="Erase selected strips from the sequencer";
1660         
1661         /* api callbacks */
1662         ot->invoke= WM_operator_confirm;
1663         ot->exec= sequencer_delete_exec;
1664         ot->poll= sequencer_edit_poll;
1665         
1666         /* flags */
1667         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1668 }
1669
1670
1671 /* offset clear operator */
1672 static int sequencer_offset_clear_exec(bContext *C, wmOperator *UNUSED(op))
1673 {
1674         Scene *scene= CTX_data_scene(C);
1675         Editing *ed= seq_give_editing(scene, FALSE);
1676         Sequence *seq;
1677
1678         /* for effects, try to find a replacement input */
1679         for(seq=ed->seqbasep->first; seq; seq=seq->next) {
1680                 if((seq->type & SEQ_EFFECT)==0 && (seq->flag & SELECT)) {
1681                         seq->startofs= seq->endofs= seq->startstill= seq->endstill= 0;
1682                 }
1683         }
1684
1685         /* updates lengths etc */
1686         seq= ed->seqbasep->first;
1687         while(seq) {
1688                 calc_sequence(scene, seq);
1689                 seq= seq->next;
1690         }
1691
1692         for(seq=ed->seqbasep->first; seq; seq=seq->next) {
1693                 if((seq->type & SEQ_EFFECT)==0 && (seq->flag & SELECT)) {
1694                         if(seq_test_overlap(ed->seqbasep, seq)) {
1695                                 shuffle_seq(ed->seqbasep, seq, scene);
1696                         }
1697                 }
1698         }
1699
1700         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1701
1702         return OPERATOR_FINISHED;
1703 }
1704
1705
1706 void SEQUENCER_OT_offset_clear(wmOperatorType *ot)
1707 {
1708
1709         /* identifiers */
1710         ot->name= "Clear Strip Offset";
1711         ot->idname= "SEQUENCER_OT_offset_clear";
1712         ot->description="Clear strip offsets from the start and end frames";
1713
1714         /* api callbacks */
1715         ot->exec= sequencer_offset_clear_exec;
1716         ot->poll= sequencer_edit_poll;
1717
1718         /* flags */
1719         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1720 }
1721
1722
1723 /* separate_images operator */
1724 static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
1725 {
1726         Scene *scene= CTX_data_scene(C);
1727         Editing *ed= seq_give_editing(scene, FALSE);
1728         
1729         Sequence *seq, *seq_new;
1730         Strip *strip_new;
1731         StripElem *se, *se_new;
1732         int start_ofs, cfra, frame_end;
1733         int step= RNA_int_get(op->ptr, "length");
1734
1735         seq= ed->seqbasep->first; /* poll checks this is valid */
1736
1737         while (seq) {
1738                 if((seq->flag & SELECT) && (seq->type == SEQ_IMAGE) && (seq->len > 1)) {
1739                         /* remove seq so overlap tests dont conflict,
1740                         see seq_free_sequence below for the real free'ing */
1741                         BLI_remlink(ed->seqbasep, seq);
1742                         /* if(seq->ipo) seq->ipo->id.us--; */
1743                         /* XXX, remove fcurve and assign to split image strips */
1744
1745                         start_ofs = cfra = seq_tx_get_final_left(seq, 0);
1746                         frame_end = seq_tx_get_final_right(seq, 0);
1747
1748                         while (cfra < frame_end) {
1749                                 /* new seq */
1750                                 se = give_stripelem(seq, cfra);
1751
1752                                 seq_new= seq_dupli_recursive(scene, scene, seq, SEQ_DUPE_UNIQUE_NAME);
1753                                 BLI_addtail(ed->seqbasep, seq_new);
1754
1755                                 seq_new->start= start_ofs;
1756                                 seq_new->type= SEQ_IMAGE;
1757                                 seq_new->len = 1;
1758                                 seq_new->endstill = step-1;
1759
1760                                 /* new strip */
1761                                 strip_new= seq_new->strip;
1762                                 strip_new->len= 1;
1763                                 strip_new->us= 1;
1764
1765                                 /* new stripdata */
1766                                 se_new= strip_new->stripdata;
1767                                 BLI_strncpy(se_new->name, se->name, sizeof(se_new->name));
1768                                 calc_sequence(scene, seq_new);
1769
1770                                 if(step > 1) {
1771                                         seq_new->flag &= ~SEQ_OVERLAP;
1772                                         if (seq_test_overlap(ed->seqbasep, seq_new)) {
1773                                                 shuffle_seq(ed->seqbasep, seq_new, scene);
1774                                         }
1775                                 }
1776
1777                                 /* XXX, COPY FCURVES */
1778
1779                                 cfra++;
1780                                 start_ofs += step;
1781                         }
1782
1783                         seq_free_sequence(scene, seq);
1784                         seq = seq->next;
1785                 } else {
1786                         seq = seq->next;
1787                 }
1788         }
1789
1790         /* as last: */
1791         sort_seq(scene);
1792         
1793         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1794
1795         return OPERATOR_FINISHED;
1796 }
1797
1798
1799 void SEQUENCER_OT_images_separate(wmOperatorType *ot)
1800 {
1801         /* identifiers */
1802         ot->name= "Separate Images";
1803         ot->idname= "SEQUENCER_OT_images_separate";
1804         ot->description="On image sequences strips, it return a strip for each image";
1805         
1806         /* api callbacks */
1807         ot->exec= sequencer_separate_images_exec;
1808         ot->poll= sequencer_edit_poll;
1809         
1810         /* flags */
1811         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1812
1813         RNA_def_int(ot->srna, "length", 1, 1, 1000, "Length", "Length of each frame", 1, INT_MAX);
1814 }
1815
1816
1817 /* META Operators */
1818
1819 /* separate_meta_toggle operator */
1820 static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
1821 {
1822         Scene *scene= CTX_data_scene(C);
1823         Editing *ed= seq_give_editing(scene, FALSE);
1824         Sequence *last_seq= seq_active_get(scene);
1825         MetaStack *ms;
1826
1827         if(last_seq && last_seq->type==SEQ_META && last_seq->flag & SELECT) {
1828                 /* Enter Metastrip */
1829                 ms= MEM_mallocN(sizeof(MetaStack), "metastack");
1830                 BLI_addtail(&ed->metastack, ms);
1831                 ms->parseq= last_seq;
1832                 ms->oldbasep= ed->seqbasep;
1833
1834                 ed->seqbasep= &last_seq->seqbase;
1835
1836                 seq_active_set(scene, NULL);
1837
1838         }
1839         else {
1840                 /* Exit Metastrip (if possible) */
1841
1842                 Sequence *seq;
1843
1844                 if(ed->metastack.first==NULL)
1845                         return OPERATOR_CANCELLED;
1846
1847                 ms= ed->metastack.last;
1848                 BLI_remlink(&ed->metastack, ms);
1849
1850                 ed->seqbasep= ms->oldbasep;
1851
1852                 /* recalc all: the meta can have effects connected to it */
1853                 for(seq= ed->seqbasep->first; seq; seq= seq->next)
1854                         calc_sequence(scene, seq);
1855
1856                 seq_active_set(scene, ms->parseq);
1857
1858                 ms->parseq->flag |= SELECT;
1859                 recurs_sel_seq(ms->parseq);
1860
1861                 MEM_freeN(ms);
1862
1863         }
1864
1865         seq_update_muting(ed);
1866         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1867
1868         return OPERATOR_FINISHED;
1869 }
1870
1871 void SEQUENCER_OT_meta_toggle(wmOperatorType *ot)
1872 {
1873         /* identifiers */
1874         ot->name= "Toggle Meta Strip";
1875         ot->idname= "SEQUENCER_OT_meta_toggle";
1876         ot->description="Toggle a metastrip (to edit enclosed strips)";
1877         
1878         /* api callbacks */
1879         ot->exec= sequencer_meta_toggle_exec;
1880         ot->poll= sequencer_edit_poll;
1881         
1882         /* flags */
1883         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1884 }
1885
1886
1887 /* separate_meta_make operator */
1888 static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
1889 {
1890         Scene *scene= CTX_data_scene(C);
1891         Editing *ed= seq_give_editing(scene, FALSE);
1892         
1893         Sequence *seq, *seqm, *next, *last_seq = seq_active_get(scene);
1894         int channel_max= 1;
1895
1896         if(seqbase_isolated_sel_check(ed->seqbasep)==FALSE) {
1897                 BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
1898                 return OPERATOR_CANCELLED;
1899         }
1900
1901         /* remove all selected from main list, and put in meta */
1902
1903         seqm= alloc_sequence(ed->seqbasep, 1, 1); /* channel number set later */
1904         strcpy(seqm->name+2, "MetaStrip");
1905         seqm->type= SEQ_META;
1906         seqm->flag= SELECT;
1907
1908         seq= ed->seqbasep->first;
1909         while(seq) {
1910                 next= seq->next;
1911                 if(seq!=seqm && (seq->flag & SELECT)) {
1912                         channel_max= MAX2(seq->machine, channel_max);
1913                         BLI_remlink(ed->seqbasep, seq);
1914                         BLI_addtail(&seqm->seqbase, seq);
1915                 }
1916                 seq= next;
1917         }
1918         seqm->machine= last_seq ? last_seq->machine : channel_max;
1919         calc_sequence(scene, seqm);
1920
1921         seqm->strip= MEM_callocN(sizeof(Strip), "metastrip");
1922         seqm->strip->len= seqm->len;
1923         seqm->strip->us= 1;
1924         
1925         seq_active_set(scene, seqm);
1926
1927         if( seq_test_overlap(ed->seqbasep, seqm) ) shuffle_seq(ed->seqbasep, seqm, scene);
1928
1929         seq_update_muting(ed);
1930
1931         seqbase_unique_name_recursive(&scene->ed->seqbase, seqm);
1932
1933         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1934
1935         return OPERATOR_FINISHED;
1936 }
1937
1938 void SEQUENCER_OT_meta_make(wmOperatorType *ot)
1939 {
1940         /* identifiers */
1941         ot->name= "Make Meta Strip";
1942         ot->idname= "SEQUENCER_OT_meta_make";
1943         ot->description="Group selected strips into a metastrip";
1944         
1945         /* api callbacks */
1946         ot->invoke= WM_operator_confirm;
1947         ot->exec= sequencer_meta_make_exec;
1948         ot->poll= sequencer_edit_poll;
1949         
1950         /* flags */
1951         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1952 }
1953
1954
1955 static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
1956 {
1957         if (seq == seqm) return 1;
1958         else if (seq->seq1 && seq_depends_on_meta(seq->seq1, seqm)) return 1;
1959         else if (seq->seq2 && seq_depends_on_meta(seq->seq2, seqm)) return 1;
1960         else if (seq->seq3 && seq_depends_on_meta(seq->seq3, seqm)) return 1;
1961         else return 0;
1962 }
1963
1964 /* separate_meta_make operator */
1965 static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op))
1966 {
1967         Scene *scene= CTX_data_scene(C);
1968         Editing *ed= seq_give_editing(scene, FALSE);
1969
1970         Sequence *seq, *last_seq = seq_active_get(scene); /* last_seq checks ed==NULL */
1971
1972         if(last_seq==NULL || last_seq->type!=SEQ_META)
1973                 return OPERATOR_CANCELLED;
1974
1975         BLI_movelisttolist(ed->seqbasep, &last_seq->seqbase);
1976
1977         last_seq->seqbase.first= NULL;
1978         last_seq->seqbase.last= NULL;
1979
1980         BLI_remlink(ed->seqbasep, last_seq);
1981         seq_free_sequence(scene, last_seq);
1982
1983         /* emtpy meta strip, delete all effects depending on it */
1984         for(seq=ed->seqbasep->first; seq; seq=seq->next)
1985                 if((seq->type & SEQ_EFFECT) && seq_depends_on_meta(seq, last_seq))
1986                         seq->flag |= SEQ_FLAG_DELETE;
1987
1988         recurs_del_seq_flag(scene, ed->seqbasep, SEQ_FLAG_DELETE, 0);
1989
1990         /* test for effects and overlap
1991          * dont use SEQP_BEGIN since that would be recursive */
1992         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1993                 if(seq->flag & SELECT) {
1994                         seq->flag &= ~SEQ_OVERLAP;
1995                         if(seq_test_overlap(ed->seqbasep, seq)) {
1996                                 shuffle_seq(ed->seqbasep, seq, scene);
1997                         }
1998                 }
1999         }
2000
2001         sort_seq(scene);
2002         seq_update_muting(ed);
2003
2004         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2005
2006         return OPERATOR_FINISHED;
2007 }
2008
2009 void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
2010 {
2011         /* identifiers */
2012         ot->name= "UnMeta Strip";
2013         ot->idname= "SEQUENCER_OT_meta_separate";
2014         ot->description="Put the contents of a metastrip back in the sequencer";
2015         
2016         /* api callbacks */
2017         ot->invoke= WM_operator_confirm;
2018         ot->exec= sequencer_meta_separate_exec;
2019         ot->poll= sequencer_edit_poll;
2020         
2021         /* flags */
2022         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2023 }
2024
2025 /* view_all operator */
2026 static int sequencer_view_all_exec(bContext *C, wmOperator *UNUSED(op))
2027 {
2028         //Scene *scene= CTX_data_scene(C);
2029         bScreen *sc= CTX_wm_screen(C);
2030         ScrArea *area= CTX_wm_area(C);
2031         //ARegion *ar= CTX_wm_region(C);
2032         View2D *v2d= UI_view2d_fromcontext(C);
2033
2034         v2d->cur= v2d->tot;
2035         UI_view2d_curRect_validate(v2d);
2036         UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
2037         
2038         ED_area_tag_redraw(CTX_wm_area(C));
2039         return OPERATOR_FINISHED;
2040 }
2041
2042 void SEQUENCER_OT_view_all(wmOperatorType *ot)
2043 {
2044         /* identifiers */
2045         ot->name= "View All";
2046         ot->idname= "SEQUENCER_OT_view_all";
2047         ot->description="View all the strips in the sequencer";
2048         
2049         /* api callbacks */
2050         ot->exec= sequencer_view_all_exec;
2051         ot->poll= ED_operator_sequencer_active;
2052         
2053         /* flags */
2054         ot->flag= OPTYPE_REGISTER;
2055 }
2056
2057 /* view_all operator */
2058 static int sequencer_view_all_preview_exec(bContext *C, wmOperator *UNUSED(op))
2059 {
2060         bScreen *sc= CTX_wm_screen(C);
2061         ScrArea *area= CTX_wm_area(C);
2062 #if 0
2063         ARegion *ar= CTX_wm_region(C);
2064         SpaceSeq *sseq= area->spacedata.first;
2065         Scene *scene= CTX_data_scene(C);
2066 #endif
2067         View2D *v2d= UI_view2d_fromcontext(C);
2068
2069         v2d->cur= v2d->tot;
2070         UI_view2d_curRect_validate(v2d);
2071         UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
2072         
2073 #if 0
2074         /* Like zooming on an image view */
2075         float zoomX, zoomY;
2076         int width, height, imgwidth, imgheight;
2077
2078         width = ar->winx;
2079         height = ar->winy;
2080
2081         seq_reset_imageofs(sseq);
2082
2083         imgwidth= (scene->r.size*scene->r.xsch)/100;
2084         imgheight= (scene->r.size*scene->r.ysch)/100;
2085
2086         /* Apply aspect, dosnt need to be that accurate */
2087         imgwidth= (int)(imgwidth * (scene->r.xasp / scene->r.yasp));
2088
2089         if (((imgwidth >= width) || (imgheight >= height)) &&
2090                 ((width > 0) && (height > 0))) {
2091
2092                 /* Find the zoom value that will fit the image in the image space */
2093                 zoomX = ((float)width) / ((float)imgwidth);
2094                 zoomY = ((float)height) / ((float)imgheight);
2095                 sseq->zoom= (zoomX < zoomY) ? zoomX : zoomY;
2096
2097                 sseq->zoom = 1.0f / power_of_2(1/ MIN2(zoomX, zoomY) );
2098         }
2099         else {
2100                 sseq->zoom= 1.0f;
2101         }
2102 #endif
2103
2104         ED_area_tag_redraw(CTX_wm_area(C));
2105         return OPERATOR_FINISHED;
2106 }
2107
2108 void SEQUENCER_OT_view_all_preview(wmOperatorType *ot)
2109 {
2110         /* identifiers */
2111         ot->name= "View All";
2112         ot->idname= "SEQUENCER_OT_view_all_preview";
2113         ot->description="Zoom preview to fit in the area";
2114         
2115         /* api callbacks */
2116         ot->exec= sequencer_view_all_preview_exec;
2117         ot->poll= ED_operator_sequencer_active;
2118         
2119         /* flags */
2120         ot->flag= OPTYPE_REGISTER;
2121 }
2122
2123
2124 static int sequencer_view_zoom_ratio_exec(bContext *C, wmOperator *op)
2125 {
2126         RenderData *r= &CTX_data_scene(C)->r;
2127         View2D *v2d= UI_view2d_fromcontext(C);
2128
2129         float ratio= RNA_float_get(op->ptr, "ratio");
2130
2131         float winx= (int)(r->size * r->xsch)/100;
2132         float winy= (int)(r->size * r->ysch)/100;
2133
2134         float facx= (v2d->mask.xmax - v2d->mask.xmin) / winx;
2135         float facy= (v2d->mask.ymax - v2d->mask.ymin) / winy;
2136
2137         BLI_resize_rctf(&v2d->cur, (int)(winx*facx*ratio) + 1, (int)(winy*facy*ratio) + 1);
2138
2139         ED_region_tag_redraw(CTX_wm_region(C));
2140
2141         return OPERATOR_FINISHED;
2142 }
2143
2144 void SEQUENCER_OT_view_zoom_ratio(wmOperatorType *ot)
2145 {
2146         /* identifiers */
2147         ot->name= "Sequencer View Zoom Ratio";
2148         ot->idname= "SEQUENCER_OT_view_zoom_ratio";
2149         ot->description = "Change zoom ratio of sequencer preview";
2150
2151         /* api callbacks */
2152         ot->exec= sequencer_view_zoom_ratio_exec;
2153         ot->poll= ED_operator_sequencer_active;
2154
2155         /* properties */
2156         RNA_def_float(ot->srna, "ratio", 1.0f, 0.0f, FLT_MAX,
2157                 "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out.", -FLT_MAX, FLT_MAX);
2158 }
2159
2160
2161 #if 0
2162 static EnumPropertyItem view_type_items[] = {
2163                 {SEQ_VIEW_SEQUENCE, "SEQUENCER", ICON_SEQ_SEQUENCER, "Sequencer", ""},
2164                 {SEQ_VIEW_PREVIEW,  "PREVIEW", ICON_SEQ_PREVIEW, "Image Preview", ""},
2165                 {SEQ_VIEW_SEQUENCE_PREVIEW,  "SEQUENCER_PREVIEW", ICON_SEQ_SEQUENCER, "Sequencer and Image Preview", ""},
2166                 {0, NULL, 0, NULL, NULL}};
2167 #endif
2168
2169 /* view_all operator */
2170 static int sequencer_view_toggle_exec(bContext *C, wmOperator *UNUSED(op))
2171 {
2172         SpaceSeq *sseq= (SpaceSeq *)CTX_wm_space_data(C);
2173
2174         sseq->view++;
2175         if (sseq->view > SEQ_VIEW_SEQUENCE_PREVIEW) sseq->view = SEQ_VIEW_SEQUENCE;
2176
2177         ED_area_tag_refresh(CTX_wm_area(C));
2178
2179         return OPERATOR_FINISHED;
2180 }
2181
2182 void SEQUENCER_OT_view_toggle(wmOperatorType *ot)
2183 {
2184         /* identifiers */
2185         ot->name= "View Toggle";
2186         ot->idname= "SEQUENCER_OT_view_toggle";
2187         ot->description="Toggle between sequencer views (sequence, preview, both)";
2188         
2189         /* api callbacks */
2190         ot->exec= sequencer_view_toggle_exec;
2191         ot->poll= ED_operator_sequencer_active;
2192         
2193         /* flags */
2194         ot->flag= OPTYPE_REGISTER;
2195 }
2196
2197
2198 /* view_selected operator */
2199 static int sequencer_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
2200 {
2201         Scene *scene= CTX_data_scene(C);
2202         View2D *v2d= UI_view2d_fromcontext(C);
2203         ScrArea *area= CTX_wm_area(C);
2204         bScreen *sc= CTX_wm_screen(C);
2205         Editing *ed= seq_give_editing(scene, FALSE);
2206         Sequence *seq;
2207
2208         int xmin=  MAXFRAME*2;
2209         int xmax= -MAXFRAME*2;
2210         int ymin=  MAXSEQ+1;
2211         int ymax= 0;
2212         int orig_height;
2213         int ymid;
2214         int ymargin= 1;
2215         int xmargin= FPS;
2216
2217         if(ed==NULL)
2218                 return OPERATOR_CANCELLED;
2219
2220         for(seq=ed->seqbasep->first; seq; seq=seq->next) {
2221                 if(seq->flag & SELECT) {
2222                         xmin= MIN2(xmin, seq->startdisp);
2223                         xmax= MAX2(xmax, seq->enddisp);
2224
2225                         ymin= MIN2(ymin, seq->machine);
2226                         ymax= MAX2(ymax, seq->machine);
2227                 }
2228         }
2229
2230         if (ymax != 0) {
2231                 
2232                 xmax += xmargin;
2233                 xmin -= xmargin;
2234                 ymax += ymargin;
2235                 ymin -= ymargin;
2236
2237                 orig_height= v2d->cur.ymax - v2d->cur.ymin;
2238
2239                 v2d->cur.xmin= xmin;
2240                 v2d->cur.xmax= xmax;
2241
2242                 v2d->cur.ymin= ymin;
2243                 v2d->cur.ymax= ymax;
2244
2245                 /* only zoom out vertically */
2246                 if (orig_height > v2d->cur.ymax - v2d->cur.ymin) {
2247                         ymid= (v2d->cur.ymax + v2d->cur.ymin) / 2;
2248
2249                         v2d->cur.ymin= ymid - (orig_height/2);
2250                         v2d->cur.ymax= ymid + (orig_height/2);
2251                 }
2252
2253                 UI_view2d_curRect_validate(v2d);
2254                 UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
2255
2256                 ED_area_tag_redraw(CTX_wm_area(C));
2257         }
2258         
2259         return OPERATOR_FINISHED;
2260 }
2261
2262 void SEQUENCER_OT_view_selected(wmOperatorType *ot)
2263 {
2264         /* identifiers */
2265         ot->name= "View Selected";
2266         ot->idname= "SEQUENCER_OT_view_selected";
2267         ot->description="Zoom the sequencer on the selected strips";
2268         
2269         /* api callbacks */
2270         ot->exec= sequencer_view_selected_exec;
2271         ot->poll= ED_operator_sequencer_active;
2272         
2273         /* flags */
2274         ot->flag= OPTYPE_REGISTER;
2275 }
2276
2277
2278 static int find_next_prev_edit(Scene *scene, int cfra, int side)
2279 {
2280         Editing *ed= seq_give_editing(scene, FALSE);
2281         Sequence *seq,*best_seq = NULL,*frame_seq = NULL;
2282         
2283         int dist, best_dist;
2284         best_dist = MAXFRAME*2;
2285
2286         if(ed==NULL) return cfra;
2287         
2288         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
2289                 dist = MAXFRAME*2;
2290                         
2291                 switch (side) {
2292                         case SEQ_SIDE_LEFT:
2293                                 if (seq->startdisp < cfra) {
2294                                         dist = cfra - seq->startdisp;
2295                                 }
2296                                 break;
2297                         case SEQ_SIDE_RIGHT:
2298                                 if (seq->startdisp > cfra) {
2299                                         dist = seq->startdisp - cfra;
2300                                 } else if (seq->startdisp == cfra) {
2301                                         frame_seq=seq;
2302                                 }
2303                                 break;
2304                 }
2305
2306                 if (dist < best_dist) {
2307                         best_dist = dist;
2308                         best_seq = seq;
2309                 }
2310         }
2311
2312         /* if no sequence to the right is found and the
2313            frame is on the start of the last sequence,
2314            move to the end of the last sequence */
2315         if (frame_seq) cfra = frame_seq->enddisp;
2316
2317         return best_seq ? best_seq->startdisp : cfra;
2318 }
2319
2320 static int next_prev_edit_internal(Scene *scene, int side)
2321 {
2322         int change=0;
2323         int cfra = CFRA;
2324         int nfra= find_next_prev_edit(scene, cfra, side);
2325         
2326         if (nfra != cfra) {
2327                 CFRA = nfra;
2328                 change= 1;
2329         }
2330
2331         return change;
2332 }
2333
2334 /* move frame to next edit point operator */
2335 static int sequencer_next_edit_exec(bContext *C, wmOperator *UNUSED(op))
2336 {
2337         Scene *scene= CTX_data_scene(C);
2338         
2339         if(!next_prev_edit_internal(scene, SEQ_SIDE_RIGHT))
2340                 return OPERATOR_CANCELLED;
2341
2342         WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
2343
2344         return OPERATOR_FINISHED;
2345 }
2346
2347 void SEQUENCER_OT_next_edit(wmOperatorType *ot)
2348 {
2349         /* identifiers */
2350         ot->name= "Next Edit";
2351         ot->idname= "SEQUENCER_OT_next_edit";
2352         ot->description="Move frame to next edit point";
2353         
2354         /* api callbacks */
2355         ot->exec= sequencer_next_edit_exec;
2356         ot->poll= sequencer_edit_poll;
2357         
2358         /* flags */
2359         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2360         
2361         /* properties */
2362 }
2363
2364 /* move frame to previous edit point operator */
2365 static int sequencer_previous_edit_exec(bContext *C, wmOperator *UNUSED(op))
2366 {
2367         Scene *scene= CTX_data_scene(C);
2368         
2369         if(!next_prev_edit_internal(scene, SEQ_SIDE_LEFT))
2370                 return OPERATOR_CANCELLED;
2371
2372         WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
2373         
2374         return OPERATOR_FINISHED;
2375 }
2376
2377 void SEQUENCER_OT_previous_edit(wmOperatorType *ot)
2378 {
2379         /* identifiers */
2380         ot->name= "Previous Edit";
2381         ot->idname= "SEQUENCER_OT_previous_edit";
2382         ot->description="Move frame to previous edit point";
2383         
2384         /* api callbacks */
2385         ot->exec= sequencer_previous_edit_exec;
2386         ot->poll= sequencer_edit_poll;
2387         
2388         /* flags */
2389         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2390         
2391         /* properties */
2392 }
2393
2394 static void swap_sequence(Scene* scene, Sequence* seqa, Sequence* seqb)
2395 {
2396         int gap = seqb->startdisp - seqa->enddisp;
2397         seqb->start = (seqb->start - seqb->startdisp) + seqa->startdisp;
2398         calc_sequence(scene, seqb);
2399         seqa->start = (seqa->start - seqa->startdisp) + seqb->enddisp + gap;
2400         calc_sequence(scene, seqa);
2401 }
2402
2403 #if 0
2404 static Sequence* sequence_find_parent(Scene* scene, Sequence* child)
2405 {
2406         Editing *ed= seq_give_editing(scene, FALSE);
2407         Sequence *parent= NULL;
2408         Sequence *seq;
2409
2410         if(ed==NULL) return NULL;
2411
2412         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
2413                 if ( (seq != child) && seq_is_parent(seq, child) ) {
2414                         parent = seq;
2415                         break;
2416                 }
2417         }
2418
2419         return parent;
2420 }
2421 #endif
2422
2423 static int sequencer_swap_exec(bContext *C, wmOperator *op)
2424 {
2425         Scene *scene= CTX_data_scene(C);
2426         Editing *ed= seq_give_editing(scene, FALSE);
2427         Sequence *active_seq = seq_active_get(scene);
2428         Sequence *seq, *iseq;
2429         int side= RNA_enum_get(op->ptr, "side");
2430
2431         if(active_seq==NULL) return OPERATOR_CANCELLED;
2432
2433         seq = find_next_prev_sequence(scene, active_seq, side, -1);
2434         
2435         if(seq) {
2436                 
2437                 /* disallow effect strips */
2438                 if (get_sequence_effect_num_inputs(seq->type) >= 1 && (seq->effectdata || seq->seq1 || seq->seq2 || seq->seq3))
2439                         return OPERATOR_CANCELLED;
2440                 if ((get_sequence_effect_num_inputs(active_seq->type) >= 1) && (active_seq->effectdata || active_seq->seq1 || active_seq->seq2 || active_seq->seq3))
2441                         return OPERATOR_CANCELLED;
2442
2443                 switch (side) {
2444                         case SEQ_SIDE_LEFT: 
2445                                 swap_sequence(scene, seq, active_seq);
2446                                 break;
2447                         case SEQ_SIDE_RIGHT: 
2448                                 swap_sequence(scene, active_seq, seq);
2449                                 break;
2450                 }
2451
2452                 // XXX - should be a generic function
2453                 for(iseq= scene->ed->seqbasep->first; iseq; iseq= iseq->next) {
2454                         if((iseq->type & SEQ_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
2455                                 calc_sequence(scene, iseq);
2456                         }
2457                 }
2458
2459                 /* do this in a new loop since both effects need to be calculated first */
2460                 for(iseq= scene->ed->seqbasep->first; iseq; iseq= iseq->next) {
2461                         if((iseq->type & SEQ_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
2462                                 /* this may now overlap */
2463                                 if( seq_test_overlap(ed->seqbasep, iseq) ) {
2464                                         shuffle_seq(ed->seqbasep, iseq, scene);
2465                                 }
2466                         }
2467                 }
2468
2469
2470
2471                 sort_seq(scene);
2472
2473                 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2474
2475                 return OPERATOR_FINISHED;
2476         }
2477
2478         return OPERATOR_CANCELLED;
2479 }
2480
2481 void SEQUENCER_OT_swap(wmOperatorType *ot)
2482 {
2483         /* identifiers */
2484         ot->name= "Swap Strip";
2485         ot->idname= "SEQUENCER_OT_swap";
2486         ot->description="Swap active strip with strip to the left";
2487         
2488         /* api callbacks */
2489         ot->exec= sequencer_swap_exec;
2490         ot->poll= sequencer_edit_poll;
2491         
2492         /* flags */
2493         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2494         
2495         /* properties */
2496         RNA_def_enum(ot->srna, "side", prop_side_lr_types, SEQ_SIDE_RIGHT, "Side", "Side of the strip to swap");
2497 }
2498
2499 static int sequencer_rendersize_exec(bContext *C, wmOperator *UNUSED(op))
2500 {
2501         int retval = OPERATOR_CANCELLED;
2502         Scene *scene= CTX_data_scene(C);
2503         Sequence *active_seq = seq_active_get(scene);
2504         StripElem *se = NULL;
2505
2506         if(active_seq==NULL)
2507                 return OPERATOR_CANCELLED;
2508
2509
2510         if (active_seq->strip) {
2511                 switch (active_seq->type) {
2512                 case SEQ_IMAGE:
2513                         se = give_stripelem(active_seq, scene->r.cfra);
2514                         break;
2515                 case SEQ_MOVIE:
2516                         se = active_seq->strip->stripdata;
2517                         break;
2518                 case SEQ_SCENE:
2519                 case SEQ_META:
2520                 case SEQ_RAM_SOUND:
2521                 case SEQ_HD_SOUND:
2522                 default:
2523                         break;
2524                 }
2525         }
2526
2527         if (se) {
2528                 // prevent setting the render size if sequence values aren't initialized
2529                 if ( (se->orig_width > 0) && (se->orig_height > 0) ) {
2530                         scene->r.xsch= se->orig_width;
2531                         scene->r.ysch= se->orig_height;
2532                         WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
2533                         retval = OPERATOR_FINISHED;
2534                 }
2535         }
2536
2537         return retval;
2538 }
2539
2540 void SEQUENCER_OT_rendersize(wmOperatorType *ot)
2541 {
2542         /* identifiers */
2543         ot->name= "Set Render Size";
2544         ot->idname= "SEQUENCER_OT_rendersize";
2545         ot->description="Set render size and aspect from active sequence";
2546         
2547         /* api callbacks */
2548         ot->exec= sequencer_rendersize_exec;
2549         ot->poll= sequencer_edit_poll;
2550         
2551         /* flags */
2552         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2553         
2554         /* properties */
2555 }
2556
2557 static void seq_del_sound(Scene *scene, Sequence *seq)
2558 {
2559         if(seq->type == SEQ_META) {
2560                 Sequence *iseq;
2561                 for(iseq= seq->seqbase.first; iseq; iseq= iseq->next) {
2562                         seq_del_sound(scene, iseq);
2563                 }
2564         }
2565         else if(seq->scene_sound) {
2566                 sound_remove_scene_sound(scene, seq->scene_sound);
2567                 seq->scene_sound = NULL;
2568         }
2569 }
2570
2571 /* TODO, validate scenes */
2572 static int sequencer_copy_exec(bContext *C, wmOperator *op)
2573 {
2574         Scene *scene= CTX_data_scene(C);
2575         Editing *ed= seq_give_editing(scene, FALSE);
2576         Sequence *seq;
2577
2578         ListBase nseqbase= {NULL, NULL};
2579
2580         seq_free_clipboard();
2581
2582         if(seqbase_isolated_sel_check(ed->seqbasep)==FALSE) {
2583                 BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
2584                 return OPERATOR_CANCELLED;
2585         }
2586
2587         seqbase_dupli_recursive(scene, NULL, &nseqbase, ed->seqbasep, SEQ_DUPE_UNIQUE_NAME);
2588
2589         /* To make sure the copied strips have unique names between each other add
2590          * them temporarily to the end of the original seqbase. (bug 25932)
2591          */
2592         if(nseqbase.first) {
2593                 Sequence *seq, *first_seq = nseqbase.first;
2594                 BLI_movelisttolist(ed->seqbasep, &nseqbase);
2595
2596                 for(seq=first_seq; seq; seq=seq->next)
2597                         seq_recursive_apply(seq, apply_unique_name_cb, scene);
2598
2599                 seqbase_clipboard.first = first_seq;
2600                 seqbase_clipboard.last = ed->seqbasep->last;
2601
2602                 if(first_seq->prev) {
2603                         first_seq->prev->next = NULL;
2604                         ed->seqbasep->last = first_seq->prev;
2605                         first_seq->prev = NULL;
2606                 }
2607         }
2608
2609         seqbase_clipboard_frame= scene->r.cfra;
2610
2611         /* Need to remove anything that references the current scene */
2612         for(seq= seqbase_clipboard.first; seq; seq= seq->next) {
2613                 seq_del_sound(scene, seq);
2614         }
2615
2616         return OPERATOR_FINISHED;
2617 }
2618
2619 void SEQUENCER_OT_copy(wmOperatorType *ot)
2620 {
2621         /* identifiers */
2622         ot->name= "Copy";
2623         ot->idname= "SEQUENCER_OT_copy";
2624         ot->description="";
2625
2626         /* api callbacks */
2627         ot->exec= sequencer_copy_exec;
2628         ot->poll= sequencer_edit_poll;
2629
2630         /* flags */
2631         ot->flag= OPTYPE_REGISTER;
2632
2633         /* properties */
2634 }
2635
2636 static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op))
2637 {
2638         Scene *scene= CTX_data_scene(C);
2639         Editing *ed= seq_give_editing(scene, TRUE); /* create if needed */
2640         ListBase nseqbase = {NULL, NULL};
2641         int ofs;
2642         Sequence *iseq;
2643
2644         deselect_all_seq(scene);
2645         ofs = scene->r.cfra - seqbase_clipboard_frame;
2646
2647         seqbase_dupli_recursive(scene, NULL, &nseqbase, &seqbase_clipboard, SEQ_DUPE_UNIQUE_NAME);
2648
2649         /* transform pasted strips before adding */
2650         if(ofs) {
2651                 for(iseq= nseqbase.first; iseq; iseq= iseq->next) {
2652                         seq_translate(scene, iseq, ofs);
2653                         seq_sound_init(scene, iseq);
2654                 }
2655         }
2656
2657         iseq = nseqbase.first;
2658
2659         BLI_movelisttolist(ed->seqbasep, &nseqbase);
2660
2661         /* make sure the pasted strips have unique names between them */
2662         for(; iseq; iseq=iseq->next)
2663                 seq_recursive_apply(iseq, apply_unique_name_cb, scene);
2664
2665         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2666
2667         return OPERATOR_FINISHED;
2668 }
2669
2670 void SEQUENCER_OT_paste(wmOperatorType *ot)
2671 {
2672         /* identifiers */
2673         ot->name= "Paste";
2674         ot->idname= "SEQUENCER_OT_paste";
2675         ot->description="";
2676
2677         /* api callbacks */
2678         ot->exec= sequencer_paste_exec;
2679         ot->poll= ED_operator_sequencer_active;
2680
2681         /* flags */
2682         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2683
2684         /* properties */
2685 }
2686
2687 static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
2688 {
2689         Scene *scene= CTX_data_scene(C);
2690         Sequence *seq_act;
2691         Sequence *seq_other;
2692         const char *error_msg;
2693
2694         if(seq_active_pair_get(scene, &seq_act, &seq_other) == 0) {
2695                 BKE_report(op->reports, RPT_ERROR, "Must select 2 strips");
2696                 return OPERATOR_CANCELLED;
2697         }
2698
2699         if(seq_swap(seq_act, seq_other, &error_msg) == 0) {
2700                 BKE_report(op->reports, RPT_ERROR, error_msg);
2701                 return OPERATOR_CANCELLED;
2702         }
2703
2704         sound_remove_scene_sound(scene, seq_act->scene_sound);
2705         sound_remove_scene_sound(scene, seq_other->scene_sound);
2706
2707         seq_act->scene_sound= NULL;
2708         seq_other->scene_sound= NULL;
2709
2710         calc_sequence(scene, seq_act);
2711         calc_sequence(scene, seq_other);
2712
2713         if(seq_act->sound)              sound_add_scene_sound(scene, seq_act, seq_act->startdisp, seq_act->enddisp, seq_act->startofs + seq_act->anim_startofs);
2714         if(seq_other->sound)    sound_add_scene_sound(scene, seq_other, seq_other->startdisp, seq_other->enddisp, seq_other->startofs + seq_other->anim_startofs);
2715
2716         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2717
2718         return OPERATOR_FINISHED;
2719 }
2720
2721 void SEQUENCER_OT_swap_data(wmOperatorType *ot)
2722 {
2723         /* identifiers */
2724         ot->name= "Sequencer Swap Data";
2725         ot->idname= "SEQUENCER_OT_swap_data";
2726         ot->description="Swap 2 sequencer strips";
2727
2728         /* api callbacks */
2729         ot->exec= sequencer_swap_data_exec;
2730         ot->poll= ED_operator_sequencer_active;
2731
2732         /* flags */
2733         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2734
2735         /* properties */
2736 }
2737
2738 /* borderselect operator */
2739 static int view_ghost_border_exec(bContext *C, wmOperator *op)
2740 {
2741         Scene *scene= CTX_data_scene(C);
2742         Editing *ed= seq_give_editing(scene, FALSE);
2743         View2D *v2d= UI_view2d_fromcontext(C);
2744
2745         rctf rect;
2746
2747         /* convert coordinates of rect to 'tot' rect coordinates */
2748         UI_view2d_region_to_view(v2d, RNA_int_get(op->ptr, "xmin"), RNA_int_get(op->ptr, "ymin"), &rect.xmin, &rect.ymin);
2749         UI_view2d_region_to_view(v2d, RNA_int_get(op->ptr, "xmax"), RNA_int_get(op->ptr, "ymax"), &rect.xmax, &rect.ymax);
2750
2751         if(ed==NULL)
2752                 return OPERATOR_CANCELLED;
2753
2754         rect.xmin /=  (float)(ABS(v2d->tot.xmax - v2d->tot.xmin));
2755         rect.ymin /=  (float)(ABS(v2d->tot.ymax - v2d->tot.ymin));
2756
2757         rect.xmax /=  (float)(ABS(v2d->tot.xmax - v2d->tot.xmin));
2758         rect.ymax /=  (float)(ABS(v2d->tot.ymax - v2d->tot.ymin));
2759
2760         rect.xmin+=0.5f;
2761         rect.xmax+=0.5f;
2762         rect.ymin+=0.5f;
2763         rect.ymax+=0.5f;
2764
2765         CLAMP(rect.xmin, 0.0f, 1.0f);
2766         CLAMP(rect.ymin, 0.0f, 1.0f);
2767         CLAMP(rect.xmax, 0.0f, 1.0f);
2768         CLAMP(rect.ymax, 0.0f, 1.0f);
2769
2770         scene->ed->over_border= rect;
2771
2772         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2773
2774         return OPERATOR_FINISHED;
2775 }
2776
2777 /* ****** Border Select ****** */
2778 void SEQUENCER_OT_view_ghost_border(wmOperatorType *ot)
2779 {
2780         /* identifiers */
2781         ot->name= "Border Offset View";
2782         ot->idname= "SEQUENCER_OT_view_ghost_border";
2783         ot->description="Enable border select mode";
2784
2785         /* api callbacks */
2786         ot->invoke= WM_border_select_invoke;
2787         ot->exec= view_ghost_border_exec;
2788         ot->modal= WM_border_select_modal;
2789         ot->poll= sequencer_view_poll;
2790         ot->cancel= WM_border_select_cancel;
2791
2792         /* flags */
2793         ot->flag= 0;
2794
2795         /* rna */
2796         WM_operator_properties_gesture_border(ot, FALSE);
2797 }
2798
2799 /* rebuild_proxy operator */
2800 static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
2801 {
2802         Scene *scene = CTX_data_scene(C);
2803         Editing *ed = seq_give_editing(scene, FALSE);
2804         Sequence * seq;
2805
2806         SEQP_BEGIN(ed, seq) {
2807                 if ((seq->flag & SELECT)) {
2808                         seq_proxy_build_job(C, seq);
2809                 }
2810         }
2811         SEQ_END
2812                 
2813         return OPERATOR_FINISHED;
2814 }
2815
2816 void SEQUENCER_OT_rebuild_proxy(wmOperatorType *ot)
2817 {
2818         /* identifiers */
2819         ot->name= "Rebuild Proxy and Timecode Indices";
2820         ot->idname= "SEQUENCER_OT_rebuild_proxy";
2821         ot->description="Rebuild all selected proxies and timecode indeces using the job system";
2822         
2823         /* api callbacks */
2824         ot->exec= sequencer_rebuild_proxy_exec;
2825         ot->poll= ED_operator_sequencer_active;
2826         
2827         /* flags */
2828         ot->flag= OPTYPE_REGISTER;
2829 }
2830
2831 /* change ops */
2832
2833 static EnumPropertyItem prop_change_effect_input_types[] = {
2834         {0, "A_B", 0, "A -> B", ""},
2835         {1, "B_C", 0, "B -> C", ""},
2836         {2, "A_C", 0, "A -> C", ""},
2837         {0, NULL, 0, NULL, NULL}
2838 };
2839
2840 static int sequencer_change_effect_input_exec(bContext *C, wmOperator *op)
2841 {
2842         Scene *scene= CTX_data_scene(C);
2843         Editing *ed= seq_give_editing(scene, FALSE);
2844         Sequence *seq= seq_active_get(scene);
2845
2846         Sequence **seq_1, **seq_2;
2847
2848         switch(RNA_enum_get(op->ptr, "swap")) {
2849                 case 0:
2850                         seq_1= &seq->seq1;
2851                         seq_2= &seq->seq2;
2852                         break;
2853                 case 1:
2854                         seq_1= &seq->seq2;
2855                         seq_2= &seq->seq3;
2856                         break;
2857                 default: /* 2 */
2858                         seq_1= &seq->seq1;
2859                         seq_2= &seq->seq3;
2860                         break;
2861         }
2862
2863         if(*seq_1 == NULL || *seq_2 == NULL) {
2864                 BKE_report(op->reports, RPT_ERROR, "One of the effect inputs is unset, can't swap");
2865                 return OPERATOR_CANCELLED;
2866         }
2867         else {
2868                 SWAP(Sequence *, *seq_1, *seq_2);
2869         }
2870
2871         update_changed_seq_and_deps(scene, seq, 0, 1);
2872
2873         /* important else we dont get the imbuf cache flushed */
2874         free_imbuf_seq(scene, &ed->seqbase, FALSE, FALSE);
2875
2876         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2877
2878         return OPERATOR_FINISHED;
2879 }
2880
2881 void SEQUENCER_OT_change_effect_input(struct wmOperatorType *ot)
2882 {
2883         /* identifiers */
2884         ot->name= "Change Effect Input";
2885         ot->idname= "SEQUENCER_OT_change_effect_input";
2886         ot->description="";
2887
2888         /* api callbacks */
2889         ot->exec= sequencer_change_effect_input_exec;
2890         ot->poll= sequencer_effect_poll;
2891
2892         /* flags */
2893         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2894
2895         ot->prop= RNA_def_enum(ot->srna, "swap", prop_change_effect_input_types, 0, "Swap", "The effect inputs to swap");
2896 }
2897
2898 static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op)
2899 {
2900         Scene *scene= CTX_data_scene(C);
2901         Editing *ed= seq_give_editing(scene, FALSE);
2902         Sequence *seq= seq_active_get(scene);
2903         const int new_type= RNA_enum_get(op->ptr, "type");
2904
2905         /* free previous effect and init new effect */
2906         struct SeqEffectHandle sh;
2907
2908         if ((seq->type & SEQ_EFFECT) == 0) {
2909                 return OPERATOR_CANCELLED;
2910         }
2911
2912         /* can someone explain the logic behind only allowing to increse this,
2913          * copied from 2.4x - campbell */
2914         if (get_sequence_effect_num_inputs(seq->type) <
2915                 get_sequence_effect_num_inputs(new_type)
2916         ) {
2917                 BKE_report(op->reports, RPT_ERROR, "New effect needs more input strips");
2918                 return OPERATOR_CANCELLED;
2919         }
2920         else {
2921                 sh = get_sequence_effect(seq);
2922                 sh.free(seq);
2923
2924                 seq->type= new_type;
2925
2926                 sh = get_sequence_effect(seq);
2927                 sh.init(seq);
2928         }
2929
2930         /* update */
2931         update_changed_seq_and_deps(scene, seq, 0, 1);
2932
2933         /* important else we dont get the imbuf cache flushed */
2934         free_imbuf_seq(scene, &ed->seqbase, FALSE, FALSE);
2935
2936         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2937
2938         return OPERATOR_FINISHED;
2939 }
2940
2941 void SEQUENCER_OT_change_effect_type(struct wmOperatorType *ot)
2942 {
2943         /* identifiers */
2944         ot->name= "Change Effect Type";
2945         ot->idname= "SEQUENCER_OT_change_effect_type";
2946         ot->description="";
2947
2948         /* api callbacks */
2949         ot->exec= sequencer_change_effect_type_exec;
2950         ot->poll= sequencer_effect_poll;
2951
2952         /* flags */
2953         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2954
2955         ot->prop= RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_CROSS, "Type", "Sequencer effect type");
2956 }
2957
2958 static int sequencer_change_path_exec(bContext *C, wmOperator *op)
2959 {
2960         Scene *scene= CTX_data_scene(C);
2961         Editing *ed= seq_give_editing(scene, FALSE);
2962         Sequence *seq= seq_active_get(scene);
2963
2964         if(seq->type == SEQ_IMAGE) {
2965                 char directory[FILE_MAX];
2966                 const int len= RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
2967                 StripElem *se;
2968
2969                 if(len==0)
2970                         return OPERATOR_CANCELLED;
2971
2972                 RNA_string_get(op->ptr, "directory", directory);
2973                 BLI_strncpy(seq->strip->dir, directory, sizeof(seq->strip->dir));
2974
2975                 if(seq->strip->stripdata) {
2976                         MEM_freeN(seq->strip->stripdata);
2977                 }
2978                 seq->strip->stripdata= se= MEM_callocN(len*sizeof(StripElem), "stripelem");
2979
2980                 RNA_BEGIN(op->ptr, itemptr, "files") {
2981                         char *filename= RNA_string_get_alloc(&itemptr, "name", NULL, 0);
2982                         BLI_strncpy(se->name, filename, sizeof(se->name));
2983                         MEM_freeN(filename);
2984                         se++;
2985                 }
2986                 RNA_END;
2987
2988                 /* reset these else we wont see all the images */
2989                 seq->anim_startofs= seq->anim_endofs= 0;
2990
2991                 /* correct start/end frames so we dont move
2992                  * important not to set seq->len= len; allow the function to handle it */
2993                 reload_sequence_new_file(scene, seq, TRUE);
2994
2995                 calc_sequence(scene, seq);
2996
2997                 /* important else we dont get the imbuf cache flushed */
2998                 free_imbuf_seq(scene, &ed->seqbase, FALSE, FALSE);
2999         }
3000         else {
3001                 /* lame, set rna filepath */
3002                 PointerRNA seq_ptr;
3003                 PropertyRNA *prop;
3004                 char filepath[FILE_MAX];
3005
3006                 RNA_pointer_create(&scene->id, &RNA_Sequence, seq, &seq_ptr);
3007
3008                 RNA_string_get(op->ptr, "filepath", filepath);
3009                 prop= RNA_struct_find_property(&seq_ptr, "filepath");
3010                 RNA_property_string_set(&seq_ptr, prop, filepath);
3011                 RNA_property_update(C, &seq_ptr, prop);
3012         }
3013
3014         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
3015
3016         return OPERATOR_FINISHED;
3017 }
3018
3019 static int sequencer_change_path_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
3020 {
3021         Scene *scene= CTX_data_scene(C);
3022         Sequence *seq= seq_active_get(scene);
3023
3024         RNA_string_set(op->ptr, "directory", seq->strip->dir);
3025
3026         /* set default display depending on seq type */
3027         if(seq->type == SEQ_IMAGE) {
3028                 RNA_boolean_set(op->ptr, "filter_movie", 0);
3029         }
3030         else {
3031                 RNA_boolean_set(op->ptr, "filter_image", 0);
3032         }
3033
3034         WM_event_add_fileselect(C, op);
3035
3036         return OPERATOR_RUNNING_MODAL;
3037 }
3038
3039 void SEQUENCER_OT_change_path(struct wmOperatorType *ot)
3040 {
3041         /* identifiers */
3042         ot->name= "Change Data/Files";
3043         ot->idname= "SEQUENCER_OT_change_path";
3044         ot->description="";
3045
3046         /* api callbacks */
3047         ot->exec= sequencer_change_path_exec;
3048         ot->invoke= sequencer_change_path_invoke;
3049         ot->poll= sequencer_strip_has_path_poll;
3050
3051         /* flags */
3052         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
3053
3054         WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE|MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_DIRECTORY|WM_FILESEL_RELPATH|WM_FILESEL_FILEPATH|WM_FILESEL_FILES);
3055 }