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