Cleanup: ensure '_END' macros end with a semicolon
[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                                         if (displen / pixelx > 16) { /* don't even try to grab the handles of small strips */
404                                                 /* Set the max value to handle to 1/3 of the total len when its less than 28.
405                                                  * This is important because otherwise selecting handles happens even when you click in the middle */
406
407                                                 if ((displen / 3) < 30 * pixelx) {
408                                                         handsize = displen / 3;
409                                                 }
410                                                 else {
411                                                         CLAMP(handsize, 7 * pixelx, 30 * pixelx);
412                                                 }
413
414                                                 if (handsize + seq->startdisp >= x)
415                                                         *hand = SEQ_SIDE_LEFT;
416                                                 else if (-handsize + seq->enddisp <= x)
417                                                         *hand = SEQ_SIDE_RIGHT;
418                                         }
419                                 }
420                                 return seq;
421                         }
422                 }
423                 seq = seq->next;
424         }
425         return NULL;
426 }
427
428
429 static bool seq_is_parent(Sequence *par, Sequence *seq)
430 {
431         return ((par->seq1 == seq) || (par->seq2 == seq) || (par->seq3 == seq));
432 }
433
434 static bool seq_is_predecessor(Sequence *pred, Sequence *seq)
435 {
436         if (!pred) return 0;
437         if (pred == seq) return 0;
438         else if (seq_is_parent(pred, seq)) return 1;
439         else if (pred->seq1 && seq_is_predecessor(pred->seq1, seq)) return 1;
440         else if (pred->seq2 && seq_is_predecessor(pred->seq2, seq)) return 1;
441         else if (pred->seq3 && seq_is_predecessor(pred->seq3, seq)) return 1;
442
443         return 0;
444 }
445
446 void ED_sequencer_deselect_all(Scene *scene)
447 {
448         Sequence *seq;
449         Editing *ed = BKE_sequencer_editing_get(scene, false);
450
451
452         if (ed == NULL) return;
453
454         SEQP_BEGIN (ed, seq)
455         {
456                 seq->flag &= ~SEQ_ALLSEL;
457         } SEQ_END;
458
459 }
460
461 void recurs_sel_seq(Sequence *seqm)
462 {
463         Sequence *seq;
464
465         seq = seqm->seqbase.first;
466         while (seq) {
467
468                 if (seqm->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) seq->flag &= ~SEQ_ALLSEL;
469                 else if (seqm->flag & SELECT) seq->flag |= SELECT;
470                 else seq->flag &= ~SEQ_ALLSEL;
471
472                 if (seq->seqbase.first) recurs_sel_seq(seq);
473
474                 seq = seq->next;
475         }
476 }
477
478 bool ED_space_sequencer_maskedit_mask_poll(bContext *C)
479 {
480         /* in this case both funcs are the same, for clip editor not */
481         return ED_space_sequencer_maskedit_poll(C);
482 }
483
484 bool ED_space_sequencer_check_show_maskedit(SpaceSeq *sseq, Scene *scene)
485 {
486         if (sseq && sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
487                 return (BKE_sequencer_mask_get(scene) != NULL);
488         }
489
490         return false;
491 }
492
493 bool ED_space_sequencer_maskedit_poll(bContext *C)
494 {
495         SpaceSeq *sseq = CTX_wm_space_seq(C);
496
497         if (sseq) {
498                 Scene *scene = CTX_data_scene(C);
499                 return ED_space_sequencer_check_show_maskedit(sseq, scene);
500         }
501
502         return false;
503 }
504
505 /* are we displaying the seq output (not channels or histogram)*/
506 bool ED_space_sequencer_check_show_imbuf(SpaceSeq *sseq)
507 {
508         return (ELEM(sseq->view, SEQ_VIEW_PREVIEW, SEQ_VIEW_SEQUENCE_PREVIEW) &&
509                 ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF));
510 }
511
512 bool ED_space_sequencer_check_show_strip(SpaceSeq *sseq)
513 {
514         return (ELEM(sseq->view, SEQ_VIEW_SEQUENCE, SEQ_VIEW_SEQUENCE_PREVIEW) &&
515                 ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF));
516 }
517
518
519 int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequence **selseq1, Sequence **selseq2, Sequence **selseq3, const char **error_str)
520 {
521         Editing *ed = BKE_sequencer_editing_get(scene, false);
522         Sequence *seq1 = NULL, *seq2 = NULL, *seq3 = NULL, *seq;
523
524         *error_str = NULL;
525
526         if (!activeseq)
527                 seq2 = BKE_sequencer_active_get(scene);
528
529         for (seq = ed->seqbasep->first; seq; seq = seq->next) {
530                 if (seq->flag & SELECT) {
531                         if (seq->type == SEQ_TYPE_SOUND_RAM && BKE_sequence_effect_get_num_inputs(type) != 0) {
532                                 *error_str = N_("Cannot apply effects to audio sequence strips");
533                                 return 0;
534                         }
535                         if ((seq != activeseq) && (seq != seq2)) {
536                                 if      (seq2 == NULL) seq2 = seq;
537                                 else if (seq1 == NULL) seq1 = seq;
538                                 else if (seq3 == NULL) seq3 = seq;
539                                 else {
540                                         *error_str = N_("Cannot apply effect to more than 3 sequence strips");
541                                         return 0;
542                                 }
543                         }
544                 }
545         }
546
547         /* make sequence selection a little bit more intuitive
548          * for 3 strips: the last-strip should be sequence3 */
549         if (seq3 != NULL && seq2 != NULL) {
550                 Sequence *tmp = seq2;
551                 seq2 = seq3;
552                 seq3 = tmp;
553         }
554
555
556         switch (BKE_sequence_effect_get_num_inputs(type)) {
557                 case 0:
558                         *selseq1 = *selseq2 = *selseq3 = NULL;
559                         return 1; /* success */
560                 case 1:
561                         if (seq2 == NULL) {
562                                 *error_str = N_("At least one selected sequence strip is needed");
563                                 return 0;
564                         }
565                         if (seq1 == NULL) seq1 = seq2;
566                         if (seq3 == NULL) seq3 = seq2;
567                         ATTR_FALLTHROUGH;
568                 case 2:
569                         if (seq1 == NULL || seq2 == NULL) {
570                                 *error_str = N_("2 selected sequence strips are needed");
571                                 return 0;
572                         }
573                         if (seq3 == NULL) seq3 = seq2;
574                         break;
575         }
576
577         if (seq1 == NULL && seq2 == NULL && seq3 == NULL) {
578                 *error_str = N_("TODO: in what cases does this happen?");
579                 return 0;
580         }
581
582         *selseq1 = seq1;
583         *selseq2 = seq2;
584         *selseq3 = seq3;
585
586         return 1;
587 }
588
589 static Sequence *del_seq_find_replace_recurs(Scene *scene, Sequence *seq)
590 {
591         Sequence *seq1, *seq2, *seq3;
592
593         /* try to find a replacement input sequence, and flag for later deletion if
594          * no replacement can be found */
595
596         if (!seq)
597                 return NULL;
598         else if (!(seq->type & SEQ_TYPE_EFFECT))
599                 return ((seq->flag & SELECT) ? NULL : seq);
600         else if (!(seq->flag & SELECT)) {
601                 /* try to find replacement for effect inputs */
602                 seq1 = del_seq_find_replace_recurs(scene, seq->seq1);
603                 seq2 = del_seq_find_replace_recurs(scene, seq->seq2);
604                 seq3 = del_seq_find_replace_recurs(scene, seq->seq3);
605
606                 if (seq1 == seq->seq1 && seq2 == seq->seq2 && seq3 == seq->seq3) {
607                         /* pass */
608                 }
609                 else if (seq1 || seq2 || seq3) {
610                         seq->seq1 = (seq1) ? seq1 : (seq2) ? seq2 : seq3;
611                         seq->seq2 = (seq2) ? seq2 : (seq1) ? seq1 : seq3;
612                         seq->seq3 = (seq3) ? seq3 : (seq1) ? seq1 : seq2;
613
614                         BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1);
615                 }
616                 else
617                         seq->flag |= SELECT;  /* mark for delete */
618         }
619
620         if (seq->flag & SELECT) {
621                 if ((seq1 = del_seq_find_replace_recurs(scene, seq->seq1))) return seq1;
622                 if ((seq2 = del_seq_find_replace_recurs(scene, seq->seq2))) return seq2;
623                 if ((seq3 = del_seq_find_replace_recurs(scene, seq->seq3))) return seq3;
624                 else return NULL;
625         }
626         else
627                 return seq;
628 }
629
630 static void del_seq_clear_modifiers_recurs(Scene *scene, Sequence *deleting_sequence)
631 {
632         Editing *ed = BKE_sequencer_editing_get(scene, false);
633         Sequence *current_sequence;
634
635         SEQP_BEGIN(ed, current_sequence)
636         {
637                 if (!(current_sequence->flag & SELECT) && current_sequence != deleting_sequence) {
638                         SequenceModifierData *smd;
639
640                         for (smd = current_sequence->modifiers.first; smd; smd = smd->next) {
641                                 if (smd->mask_sequence == deleting_sequence) {
642                                         smd->mask_sequence = NULL;
643                                 }
644                         }
645                 }
646         } SEQ_END;
647 }
648
649 static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short deleteall)
650 {
651         Sequence *seq, *seqn;
652         Sequence *last_seq = BKE_sequencer_active_get(scene);
653
654         seq = lb->first;
655         while (seq) {
656                 seqn = seq->next;
657                 if ((seq->flag & flag) || deleteall) {
658                         BLI_remlink(lb, seq);
659                         if (seq == last_seq) BKE_sequencer_active_set(scene, NULL);
660                         if (seq->type == SEQ_TYPE_META) recurs_del_seq_flag(scene, &seq->seqbase, flag, 1);
661                         BKE_sequence_free(scene, seq);
662                 }
663                 seq = seqn;
664         }
665 }
666
667
668 static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
669 {
670         TransSeq ts;
671         Sequence *seqn = NULL;
672         bool skip_dup = false;
673
674         /* Unlike soft-cut, it's important to use the same value for both strips. */
675         const bool is_end_exact = ((seq->start + seq->len) == cutframe);
676
677         /* backup values */
678         ts.start = seq->start;
679         ts.machine = seq->machine;
680         ts.startstill = seq->startstill;
681         ts.endstill = seq->endstill;
682         ts.startdisp = seq->startdisp;
683         ts.enddisp = seq->enddisp;
684         ts.startofs = seq->startofs;
685         ts.endofs = seq->endofs;
686         ts.anim_startofs = seq->anim_startofs;
687         ts.anim_endofs = seq->anim_endofs;
688         ts.len = seq->len;
689
690         /* First Strip! */
691         /* strips with extended stillfames before */
692
693         /* Precaution, needed because the length saved on-disk may not match the length saved in the blend file,
694          * or our code may have minor differences reading file length between versions.
695          * This causes hard-cut to fail, see: T47862 */
696         if (seq->type != SEQ_TYPE_META) {
697                 BKE_sequence_reload_new_file(scene, seq, true);
698                 BKE_sequence_calc(scene, seq);
699         }
700
701         /* Important to offset the start when 'cutframe == seq->start'
702          * because we need at least one frame of content after start/end still have clipped it. */
703         if ((seq->startstill) && (cutframe <= seq->start)) {
704                 /* don't do funny things with METAs ... */
705                 if (seq->type == SEQ_TYPE_META) {
706                         skip_dup = true;
707                         seq->startstill = seq->start - cutframe;
708                 }
709                 else {
710                         seq->start = cutframe - 1;
711                         seq->startstill = cutframe - seq->startdisp - 1;
712                         seq->anim_endofs += seq->len - 1;
713                         seq->endstill = 0;
714                 }
715         }
716         /* normal strip */
717         else if ((is_end_exact == false) &&
718                  ((cutframe >= seq->start) && (cutframe <= (seq->start + seq->len))))
719         {
720                 seq->endofs = 0;
721                 seq->endstill = 0;
722                 seq->anim_endofs += (seq->start + seq->len) - cutframe;
723         }
724         /* strips with extended stillframes after */
725         else if ((is_end_exact == true) ||
726                  (((seq->start + seq->len) < cutframe) && (seq->endstill)))
727         {
728                 seq->endstill -= seq->enddisp - cutframe;
729                 /* don't do funny things with METAs ... */
730                 if (seq->type == SEQ_TYPE_META) {
731                         skip_dup = true;
732                 }
733         }
734
735         BKE_sequence_reload_new_file(scene, seq, false);
736         BKE_sequence_calc(scene, seq);
737
738         if (!skip_dup) {
739                 /* Duplicate AFTER the first change */
740                 seqn = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_ANIM);
741         }
742
743         if (seqn) {
744                 seqn->flag |= SELECT;
745
746                 /* Important not to re-assign this (unlike soft-cut) */
747 #if 0
748                 is_end_exact = ((seqn->start + seqn->len) == cutframe);
749 #endif
750                 /* Second Strip! */
751                 /* strips with extended stillframes before */
752                 if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
753                         seqn->start = ts.start;
754                         seqn->startstill = ts.start - cutframe;
755                         seqn->anim_endofs = ts.anim_endofs;
756                         seqn->endstill = ts.endstill;
757                 }
758
759                 /* normal strip */
760                 else if ((is_end_exact == false) &&
761                          ((cutframe >= seqn->start) && (cutframe <= (seqn->start + seqn->len))))
762                 {
763                         seqn->start = cutframe;
764                         seqn->startstill = 0;
765                         seqn->startofs = 0;
766                         seqn->endofs = ts.endofs;
767                         seqn->anim_startofs += cutframe - ts.start;
768                         seqn->anim_endofs = ts.anim_endofs;
769                         seqn->endstill = ts.endstill;
770                 }
771
772                 /* strips with extended stillframes after */
773                 else if ((is_end_exact == true) ||
774                          (((seqn->start + seqn->len) < cutframe) && (seqn->endstill)))
775                 {
776                         seqn->start = cutframe;
777                         seqn->startofs = 0;
778                         seqn->anim_startofs += ts.len - 1;
779                         seqn->endstill = ts.enddisp - cutframe - 1;
780                         seqn->startstill = 0;
781                 }
782
783                 BKE_sequence_reload_new_file(scene, seqn, false);
784                 BKE_sequence_calc(scene, seqn);
785         }
786         return seqn;
787 }
788
789 static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
790 {
791         TransSeq ts;
792         Sequence *seqn = NULL;
793         bool skip_dup = false;
794
795         bool is_end_exact = ((seq->start + seq->len) == cutframe);
796
797         /* backup values */
798         ts.start = seq->start;
799         ts.machine = seq->machine;
800         ts.startstill = seq->startstill;
801         ts.endstill = seq->endstill;
802         ts.startdisp = seq->startdisp;
803         ts.enddisp = seq->enddisp;
804         ts.startofs = seq->startofs;
805         ts.endofs = seq->endofs;
806         ts.anim_startofs = seq->anim_startofs;
807         ts.anim_endofs = seq->anim_endofs;
808         ts.len = seq->len;
809
810         /* First Strip! */
811         /* strips with extended stillfames before */
812
813         /* Important to offset the start when 'cutframe == seq->start'
814          * because we need at least one frame of content after start/end still have clipped it. */
815         if ((seq->startstill) && (cutframe <= seq->start)) {
816                 /* don't do funny things with METAs ... */
817                 if (seq->type == SEQ_TYPE_META) {
818                         skip_dup = true;
819                         seq->startstill = seq->start - cutframe;
820                 }
821                 else {
822                         seq->start = cutframe - 1;
823                         seq->startstill = cutframe - seq->startdisp - 1;
824                         seq->endofs = seq->len - 1;
825                         seq->endstill = 0;
826                 }
827         }
828         /* normal strip */
829         else if ((is_end_exact == false) &&
830                  (cutframe >= seq->start) && (cutframe <= (seq->start + seq->len)))
831         {
832                 seq->endofs = (seq->start + seq->len) - cutframe;
833         }
834         /* strips with extended stillframes after */
835         else if ((is_end_exact == true) ||
836                  (((seq->start + seq->len) < cutframe) && (seq->endstill)))
837         {
838                 seq->endstill -= seq->enddisp - cutframe;
839                 /* don't do funny things with METAs ... */
840                 if (seq->type == SEQ_TYPE_META) {
841                         skip_dup = true;
842                 }
843         }
844
845         BKE_sequence_calc(scene, seq);
846
847         if (!skip_dup) {
848                 /* Duplicate AFTER the first change */
849                 seqn = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_ANIM);
850         }
851
852         if (seqn) {
853                 seqn->flag |= SELECT;
854
855                 is_end_exact = ((seqn->start + seqn->len) == cutframe);
856
857                 /* Second Strip! */
858                 /* strips with extended stillframes before */
859                 if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
860                         seqn->start = ts.start;
861                         seqn->startstill = ts.start - cutframe;
862                         seqn->endofs = ts.endofs;
863                         seqn->endstill = ts.endstill;
864                 }
865
866                 /* normal strip */
867                 else if ((is_end_exact == false) &&
868                          (cutframe >= seqn->start) && (cutframe <= (seqn->start + seqn->len)))
869                 {
870                         seqn->startstill = 0;
871                         seqn->startofs = cutframe - ts.start;
872                         seqn->endofs = ts.endofs;
873                         seqn->endstill = ts.endstill;
874                 }
875
876                 /* strips with extended stillframes after */
877                 else if ((is_end_exact == true) ||
878                          (((seqn->start + seqn->len) < cutframe) && (seqn->endstill)))
879                 {
880                         seqn->start = cutframe - ts.len + 1;
881                         seqn->startofs = ts.len - 1;
882                         seqn->endstill = ts.enddisp - cutframe - 1;
883                         seqn->startstill = 0;
884                 }
885
886                 BKE_sequence_calc(scene, seqn);
887         }
888         return seqn;
889 }
890
891
892 /* like duplicate, but only duplicate and cut overlapping strips,
893  * strips to the left of the cutframe are ignored and strips to the right
894  * are moved to the end of slist
895  * we have to work on the same slist (not using a separate list), since
896  * otherwise dupli_seq can't check for duplicate names properly and
897  * may generate strips with the same name (which will mess up animdata)
898  */
899
900 static bool cut_seq_list(Scene *scene, ListBase *slist, int cutframe,
901                          Sequence * (*cut_seq)(Scene *, Sequence *, int))
902 {
903         Sequence *seq, *seq_next_iter;
904         Sequence *seq_first_new = NULL;
905
906         seq = slist->first;
907
908         while (seq && seq != seq_first_new) {
909                 seq_next_iter = seq->next; /* we need this because we may remove seq */
910                 seq->tmp = NULL;
911                 if (seq->flag & SELECT) {
912                         if (cutframe > seq->startdisp &&
913                             cutframe < seq->enddisp)
914                         {
915                                 Sequence *seqn = cut_seq(scene, seq, cutframe);
916                                 if (seqn) {
917                                         BLI_addtail(slist, seqn);
918                                         if (seq_first_new == NULL) {
919                                                 seq_first_new = seqn;
920                                         }
921                                 }
922                         }
923                         else if (seq->enddisp <= cutframe) {
924                                 /* do nothing */
925                         }
926                         else if (seq->startdisp >= cutframe) {
927                                 /* move to tail */
928                                 BLI_remlink(slist, seq);
929                                 BLI_addtail(slist, seq);
930
931                                 if (seq_first_new == NULL) {
932                                         seq_first_new = seq;
933                                 }
934                         }
935                 }
936                 seq = seq_next_iter;
937         }
938
939         return (seq_first_new != NULL);
940 }
941
942 static bool sequence_offset_after_frame(Scene *scene, const int delta, const int cfra)
943 {
944         Sequence *seq;
945         Editing *ed = BKE_sequencer_editing_get(scene, false);
946         bool done = false;
947         TimeMarker *marker;
948
949         /* all strips >= cfra are shifted */
950
951         if (ed == NULL) return 0;
952
953         for (seq = ed->seqbasep->first; seq; seq = seq->next) {
954                 if (seq->startdisp >= cfra) {
955                         BKE_sequence_translate(scene, seq, delta);
956                         BKE_sequence_calc(scene, seq);
957                         done = true;
958                 }
959         }
960
961         if (!scene->toolsettings->lock_markers) {
962                 for (marker = scene->markers.first; marker; marker = marker->next) {
963                         if (marker->frame >= cfra) {
964                                 marker->frame += delta;
965                         }
966                 }
967         }
968
969         return done;
970 }
971
972 #if 0
973 static void set_filter_seq(Scene *scene)
974 {
975         Sequence *seq;
976         Editing *ed = BKE_sequencer_editing_get(scene, false);
977
978
979         if (ed == NULL) return;
980
981         if (okee("Set Deinterlace") == 0) return;
982
983         SEQP_BEGIN (ed, seq)
984         {
985                 if (seq->flag & SELECT) {
986                         if (seq->type == SEQ_TYPE_MOVIE) {
987                                 seq->flag |= SEQ_FILTERY;
988                                 BKE_sequence_reload_new_file(scene, seq, false);
989                                 BKE_sequence_calc(scene, seq);
990                         }
991
992                 }
993         } SEQ_END;
994 }
995 #endif
996
997 static void UNUSED_FUNCTION(seq_remap_paths) (Scene *scene)
998 {
999         Sequence *seq, *last_seq = BKE_sequencer_active_get(scene);
1000         Editing *ed = BKE_sequencer_editing_get(scene, false);
1001         char from[FILE_MAX], to[FILE_MAX], stripped[FILE_MAX];
1002
1003
1004         if (last_seq == NULL)
1005                 return;
1006
1007         BLI_strncpy(from, last_seq->strip->dir, sizeof(from));
1008 // XXX  if (0 == sbutton(from, 0, sizeof(from) - 1, "From: "))
1009 //              return;
1010
1011         BLI_strncpy(to, from, sizeof(to));
1012 // XXX  if (0 == sbutton(to, 0, sizeof(to) - 1, "To: "))
1013 //              return;
1014
1015         if (STREQ(to, from))
1016                 return;
1017
1018         SEQP_BEGIN (ed, seq)
1019         {
1020                 if (seq->flag & SELECT) {
1021                         if (STREQLEN(seq->strip->dir, from, strlen(from))) {
1022                                 printf("found %s\n", seq->strip->dir);
1023
1024                                 /* strip off the beginning */
1025                                 stripped[0] = 0;
1026                                 BLI_strncpy(stripped, seq->strip->dir + strlen(from), FILE_MAX);
1027
1028                                 /* new path */
1029                                 BLI_snprintf(seq->strip->dir, sizeof(seq->strip->dir), "%s%s", to, stripped);
1030                                 printf("new %s\n", seq->strip->dir);
1031                         }
1032                 }
1033         } SEQ_END;
1034
1035 }
1036
1037
1038 static int sequencer_gap_remove_exec(bContext *C, wmOperator *op)
1039 {
1040         Scene *scene = CTX_data_scene(C);
1041         rctf rectf;
1042         int cfra, efra, sfra;
1043         bool first = false, done;
1044         bool do_all = RNA_boolean_get(op->ptr, "all");
1045
1046         /* get first and last frame */
1047         boundbox_seq(scene, &rectf);
1048         sfra = (int)rectf.xmin;
1049         efra = (int)rectf.xmax;
1050
1051         /* first check if the current frame has a gap already */
1052         for (cfra = CFRA; cfra >= sfra; cfra--) {
1053                 if (BKE_sequencer_evaluate_frame(scene, cfra)) {
1054                         first = true;
1055                         break;
1056                 }
1057         }
1058
1059         for ( ; cfra < efra; cfra++) {
1060                 /* first == 0 means there's still no strip to remove a gap for */
1061                 if (first == false) {
1062                         if (BKE_sequencer_evaluate_frame(scene, cfra) ) first = true;
1063                 }
1064                 else if (BKE_sequencer_evaluate_frame(scene, cfra) == 0) {
1065                         done = true;
1066                         while (BKE_sequencer_evaluate_frame(scene, cfra) == 0) {
1067                                 done = sequence_offset_after_frame(scene, -1, cfra);
1068                                 if (done == false) break;
1069                         }
1070                         if (done == false || do_all == false) break;
1071                 }
1072         }
1073
1074         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1075
1076         return OPERATOR_FINISHED;
1077
1078 }
1079
1080
1081 void SEQUENCER_OT_gap_remove(struct wmOperatorType *ot)
1082 {
1083         /* identifiers */
1084         ot->name = "Remove Gaps";
1085         ot->idname = "SEQUENCER_OT_gap_remove";
1086         ot->description = "Remove gap at current frame to first strip at the right, independent of selection or locked state of strips";
1087
1088         /* api callbacks */
1089 //      ot->invoke = sequencer_snap_invoke;
1090         ot->exec = sequencer_gap_remove_exec;
1091         ot->poll = sequencer_edit_poll;
1092
1093         /* flags */
1094         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1095
1096         RNA_def_boolean(ot->srna, "all", 0, "All Gaps", "Do all gaps to right of current frame");
1097 }
1098
1099 static int sequencer_gap_insert_exec(bContext *C, wmOperator *op)
1100 {
1101         Scene *scene = CTX_data_scene(C);
1102         int frames = RNA_int_get(op->ptr, "frames");
1103
1104         sequence_offset_after_frame(scene, frames, CFRA);
1105
1106         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1107
1108         return OPERATOR_FINISHED;
1109
1110 }
1111
1112 void SEQUENCER_OT_gap_insert(struct wmOperatorType *ot)
1113 {
1114         /* identifiers */
1115         ot->name = "Insert Gaps";
1116         ot->idname = "SEQUENCER_OT_gap_insert";
1117         ot->description = "Insert gap at current frame to first strips at the right, independent of selection or locked state of strips";
1118
1119         /* api callbacks */
1120         //      ot->invoke = sequencer_snap_invoke;
1121         ot->exec = sequencer_gap_insert_exec;
1122         ot->poll = sequencer_edit_poll;
1123
1124         /* flags */
1125         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1126
1127         RNA_def_int(ot->srna, "frames", 10, 0, INT_MAX, "Frames", "Frames to insert after current strip", 0, 1000);
1128 }
1129
1130
1131 #if 0
1132 static int seq_get_snaplimit(View2D *v2d)
1133 {
1134         /* fake mouse coords to get the snap value
1135          * a bit lazy but its only done once pre transform */
1136         float xmouse, ymouse, x;
1137         int mval[2] = {24, 0}; /* 24 screen px snap */
1138
1139         UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
1140         x = xmouse;
1141         mval[0] = 0;
1142         UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
1143         return (int)(x - xmouse);
1144 }
1145 #endif
1146
1147 /* Operator functions */
1148 bool sequencer_edit_poll(bContext *C)
1149 {
1150         return (BKE_sequencer_editing_get(CTX_data_scene(C), false) != NULL);
1151 }
1152
1153 #if 0 /* UNUSED */
1154 bool sequencer_strip_poll(bContext *C)
1155 {
1156         Editing *ed;
1157         return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) && (ed->act_seq != NULL));
1158 }
1159 #endif
1160
1161 bool sequencer_strip_has_path_poll(bContext *C)
1162 {
1163         Editing *ed;
1164         Sequence *seq;
1165         return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) && ((seq = ed->act_seq) != NULL) && (SEQ_HAS_PATH(seq)));
1166 }
1167
1168 bool sequencer_view_preview_poll(bContext *C)
1169 {
1170         SpaceSeq *sseq = CTX_wm_space_seq(C);
1171         Editing *ed = BKE_sequencer_editing_get(CTX_data_scene(C), false);
1172         if (ed && sseq && (sseq->mainb == SEQ_DRAW_IMG_IMBUF))
1173                 return 1;
1174
1175         return 0;
1176 }
1177
1178 bool sequencer_view_strips_poll(bContext *C)
1179 {
1180         SpaceSeq *sseq = CTX_wm_space_seq(C);
1181         if (sseq && ED_space_sequencer_check_show_strip(sseq))
1182                 return 1;
1183
1184         return 0;
1185 }
1186
1187 /* snap operator*/
1188 static int sequencer_snap_exec(bContext *C, wmOperator *op)
1189 {
1190         Scene *scene = CTX_data_scene(C);
1191
1192         Editing *ed = BKE_sequencer_editing_get(scene, false);
1193         Sequence *seq;
1194         int snap_frame;
1195
1196         snap_frame = RNA_int_get(op->ptr, "frame");
1197
1198         /* also check metas */
1199         for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1200                 if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK) &&
1201                     BKE_sequence_tx_test(seq))
1202                 {
1203                         if ((seq->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) == 0) {
1204                                 /* simple but no anim update */
1205                                 /* seq->start = snap_frame-seq->startofs+seq->startstill; */
1206
1207                                 BKE_sequence_translate(scene, seq, (snap_frame - seq->startofs + seq->startstill) - seq->start);
1208                         }
1209                         else {
1210                                 if (seq->flag & SEQ_LEFTSEL) {
1211                                         BKE_sequence_tx_set_final_left(seq, snap_frame);
1212                                 }
1213                                 else { /* SEQ_RIGHTSEL */
1214                                         BKE_sequence_tx_set_final_right(seq, snap_frame);
1215                                 }
1216                                 BKE_sequence_tx_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
1217                                 BKE_sequence_single_fix(seq);
1218                         }
1219                         BKE_sequence_calc(scene, seq);
1220                 }
1221         }
1222
1223         /* test for effects and overlap
1224          * don't use SEQP_BEGIN since that would be recursive */
1225         for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1226                 if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK)) {
1227                         seq->flag &= ~SEQ_OVERLAP;
1228                         if (BKE_sequence_test_overlap(ed->seqbasep, seq) ) {
1229                                 BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
1230                         }
1231                 }
1232                 else if (seq->type & SEQ_TYPE_EFFECT) {
1233                         if (seq->seq1 && (seq->seq1->flag & SELECT))
1234                                 BKE_sequence_calc(scene, seq);
1235                         else if (seq->seq2 && (seq->seq2->flag & SELECT))
1236                                 BKE_sequence_calc(scene, seq);
1237                         else if (seq->seq3 && (seq->seq3->flag & SELECT))
1238                                 BKE_sequence_calc(scene, seq);
1239                 }
1240         }
1241
1242         /* as last: */
1243         BKE_sequencer_sort(scene);
1244
1245         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1246
1247         return OPERATOR_FINISHED;
1248 }
1249
1250 static int sequencer_snap_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1251 {
1252         Scene *scene = CTX_data_scene(C);
1253
1254         int snap_frame;
1255
1256         snap_frame = CFRA;
1257
1258         RNA_int_set(op->ptr, "frame", snap_frame);
1259         return sequencer_snap_exec(C, op);
1260 }
1261
1262 void SEQUENCER_OT_snap(struct wmOperatorType *ot)
1263 {
1264         /* identifiers */
1265         ot->name = "Snap Strips to Frame";
1266         ot->idname = "SEQUENCER_OT_snap";
1267         ot->description = "Frame where selected strips will be snapped";
1268
1269         /* api callbacks */
1270         ot->invoke = sequencer_snap_invoke;
1271         ot->exec = sequencer_snap_exec;
1272         ot->poll = sequencer_edit_poll;
1273
1274         /* flags */
1275         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1276
1277         RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be snapped", INT_MIN, INT_MAX);
1278 }
1279
1280 typedef struct SlipData {
1281         int init_mouse[2];
1282         float init_mouseloc[2];
1283         TransSeq *ts;
1284         Sequence **seq_array;
1285         bool *trim;
1286         int num_seq;
1287         bool slow;
1288         int slow_offset; /* offset at the point where offset was turned on */
1289         void *draw_handle;
1290         NumInput num_input;
1291 } SlipData;
1292
1293 static void transseq_backup(TransSeq *ts, Sequence *seq)
1294 {
1295         ts->start = seq->start;
1296         ts->machine = seq->machine;
1297         ts->startstill = seq->startstill;
1298         ts->endstill = seq->endstill;
1299         ts->startdisp = seq->startdisp;
1300         ts->enddisp = seq->enddisp;
1301         ts->startofs = seq->startofs;
1302         ts->endofs = seq->endofs;
1303         ts->anim_startofs = seq->anim_startofs;
1304         ts->anim_endofs = seq->anim_endofs;
1305         ts->len = seq->len;
1306 }
1307
1308
1309 static void transseq_restore(TransSeq *ts, Sequence *seq)
1310 {
1311         seq->start = ts->start;
1312         seq->machine = ts->machine;
1313         seq->startstill = ts->startstill;
1314         seq->endstill = ts->endstill;
1315         seq->startdisp = ts->startdisp;
1316         seq->enddisp = ts->enddisp;
1317         seq->startofs = ts->startofs;
1318         seq->endofs = ts->endofs;
1319         seq->anim_startofs = ts->anim_startofs;
1320         seq->anim_endofs = ts->anim_endofs;
1321         seq->len = ts->len;
1322 }
1323
1324 static void draw_slip_extensions(const bContext *C, ARegion *ar, void *data)
1325 {
1326         Scene *scene = CTX_data_scene(C);
1327         SlipData *td = data;
1328         int i;
1329
1330         for (i = 0; i < td->num_seq; i++) {
1331                 Sequence *seq = td->seq_array[i];
1332
1333                 if ((seq->type != SEQ_TYPE_META) && td->trim[i]) {
1334                         draw_sequence_extensions(scene, ar, seq);
1335                 }
1336         }
1337 }
1338
1339 static int slip_add_sequences_rec(ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool do_trim)
1340 {
1341         Sequence *seq;
1342         int num_items = 0;
1343
1344         for (seq = seqbasep->first; seq; seq = seq->next) {
1345                 if (!do_trim || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
1346                         seq_array[offset + num_items] = seq;
1347                         trim[offset + num_items] = do_trim;
1348                         num_items++;
1349
1350                         if (seq->type == SEQ_TYPE_META) {
1351                                 /* trim the sub-sequences */
1352                                 num_items += slip_add_sequences_rec(&seq->seqbase, seq_array, trim, num_items + offset, false);
1353                         }
1354                         else if (seq->type & SEQ_TYPE_EFFECT) {
1355                                 trim[offset + num_items] = false;
1356                         }
1357                 }
1358         }
1359
1360         return num_items;
1361 }
1362
1363 static int slip_count_sequences_rec(ListBase *seqbasep, bool first_level)
1364 {
1365         Sequence *seq;
1366         int trimmed_sequences = 0;
1367
1368         for (seq = seqbasep->first; seq; seq = seq->next) {
1369                 if (!first_level || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
1370                         trimmed_sequences++;
1371
1372                         if (seq->type == SEQ_TYPE_META) {
1373                                 /* trim the sub-sequences */
1374                                 trimmed_sequences += slip_count_sequences_rec(&seq->seqbase, false);
1375                         }
1376                 }
1377         }
1378
1379         return trimmed_sequences;
1380 }
1381
1382 static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1383 {
1384         SlipData *data;
1385         Scene *scene = CTX_data_scene(C);
1386         Editing *ed = BKE_sequencer_editing_get(scene, false);
1387         ARegion *ar = CTX_wm_region(C);
1388         float mouseloc[2];
1389         int num_seq, i;
1390         View2D *v2d = UI_view2d_fromcontext(C);
1391
1392         /* first recursively count the trimmed elements */
1393         num_seq = slip_count_sequences_rec(ed->seqbasep, true);
1394
1395         if (num_seq == 0)
1396                 return OPERATOR_CANCELLED;
1397
1398         data = op->customdata = MEM_mallocN(sizeof(SlipData), "trimdata");
1399         data->ts = MEM_mallocN(num_seq * sizeof(TransSeq), "trimdata_transform");
1400         data->seq_array = MEM_mallocN(num_seq * sizeof(Sequence *), "trimdata_sequences");
1401         data->trim = MEM_mallocN(num_seq * sizeof(bool), "trimdata_trim");
1402         data->num_seq = num_seq;
1403
1404         initNumInput(&data->num_input);
1405         data->num_input.idx_max = 0;
1406         data->num_input.val_flag[0] |= NUM_NO_FRACTION;
1407         data->num_input.unit_sys = USER_UNIT_NONE;
1408         data->num_input.unit_type[0] = 0;
1409
1410
1411         slip_add_sequences_rec(ed->seqbasep, data->seq_array, data->trim, 0, true);
1412
1413         for (i = 0; i < num_seq; i++) {
1414                 transseq_backup(data->ts + i, data->seq_array[i]);
1415         }
1416
1417         data->draw_handle = ED_region_draw_cb_activate(ar->type, draw_slip_extensions, data, REGION_DRAW_POST_VIEW);
1418
1419         UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
1420
1421         copy_v2_v2_int(data->init_mouse, event->mval);
1422         copy_v2_v2(data->init_mouseloc, mouseloc);
1423
1424         data->slow = false;
1425
1426         WM_event_add_modal_handler(C, op);
1427
1428         /* notify so we draw extensions immediately */
1429         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1430
1431         return OPERATOR_RUNNING_MODAL;
1432 }
1433
1434 static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
1435 {
1436
1437         /* only data types supported for now */
1438         if (offset != 0) {
1439                 Editing *ed = BKE_sequencer_editing_get(scene, false);
1440                 int i;
1441
1442                 /* we iterate in reverse so metastrips are iterated after their children */
1443                 for (i = data->num_seq - 1; i >= 0; i--) {
1444                         Sequence *seq = data->seq_array[i];
1445                         int endframe;
1446                         /* we have the offset, do the terrible math */
1447
1448                         /* first, do the offset */
1449                         seq->start = data->ts[i].start + offset;
1450
1451                         if (data->trim[i]) {
1452                                 /* find the endframe */
1453                                 endframe = seq->start + seq->len;
1454
1455                                 /* now compute the terrible offsets */
1456                                 if (endframe > seq->enddisp) {
1457                                         seq->endstill = 0;
1458                                         seq->endofs = endframe - seq->enddisp;
1459                                 }
1460                                 else if (endframe <= seq->enddisp) {
1461                                         seq->endstill = seq->enddisp - endframe;
1462                                         seq->endofs = 0;
1463                                 }
1464
1465                                 if (seq->start > seq->startdisp) {
1466                                         seq->startstill = seq->start - seq->startdisp;
1467                                         seq->startofs = 0;
1468                                 }
1469                                 else if (seq->start <= seq->startdisp) {
1470                                         seq->startstill = 0;
1471                                         seq->startofs = seq->startdisp - seq->start;
1472                                 }
1473                         }
1474                         else {
1475                                 /* if no real trim, don't change the data, rather transform the strips themselves */
1476                                 seq->startdisp = data->ts[i].startdisp + offset;
1477                                 seq->enddisp = data->ts[i].enddisp + offset;
1478                         }
1479
1480                         /* 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
1481                          * This way we can avoid an extra loop just for effects*/
1482                         if (!(seq->type & SEQ_TYPE_EFFECT))
1483                                 BKE_sequence_calc(scene, seq);
1484                 }
1485                 BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
1486
1487                 return true;
1488         }
1489
1490         return false;
1491 }
1492
1493 static int sequencer_slip_exec(bContext *C, wmOperator *op)
1494 {
1495         SlipData *data;
1496         Scene *scene = CTX_data_scene(C);
1497         Editing *ed = BKE_sequencer_editing_get(scene, false);
1498         int num_seq, i;
1499         int offset = RNA_int_get(op->ptr, "offset");
1500         bool success = false;
1501
1502         /* first recursively count the trimmed elements */
1503         num_seq = slip_count_sequences_rec(ed->seqbasep, true);
1504
1505         if (num_seq == 0)
1506                 return OPERATOR_CANCELLED;
1507
1508         data = op->customdata = MEM_mallocN(sizeof(SlipData), "trimdata");
1509         data->ts = MEM_mallocN(num_seq * sizeof(TransSeq), "trimdata_transform");
1510         data->seq_array = MEM_mallocN(num_seq * sizeof(Sequence *), "trimdata_sequences");
1511         data->trim = MEM_mallocN(num_seq * sizeof(bool), "trimdata_trim");
1512         data->num_seq = num_seq;
1513
1514         slip_add_sequences_rec(ed->seqbasep, data->seq_array, data->trim, 0, true);
1515
1516         for (i = 0; i < num_seq; i++) {
1517                 transseq_backup(data->ts + i, data->seq_array[i]);
1518         }
1519
1520         success = sequencer_slip_recursively(scene, data, offset);
1521
1522         MEM_freeN(data->seq_array);
1523         MEM_freeN(data->trim);
1524         MEM_freeN(data->ts);
1525         MEM_freeN(data);
1526
1527         if (success) {
1528                 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1529                 return OPERATOR_FINISHED;
1530         }
1531         else {
1532                 return OPERATOR_CANCELLED;
1533         }
1534 }
1535
1536
1537 static void sequencer_slip_update_header(Scene *scene, ScrArea *sa, SlipData *data, int offset)
1538 {
1539         char msg[UI_MAX_DRAW_STR];
1540
1541         if (sa) {
1542                 if (hasNumInput(&data->num_input)) {
1543                         char num_str[NUM_STR_REP_LEN];
1544                         outputNumInput(&data->num_input, num_str, &scene->unit);
1545                         BLI_snprintf(msg, sizeof(msg), IFACE_("Trim offset: %s"), num_str);
1546                 }
1547                 else {
1548                         BLI_snprintf(msg, sizeof(msg), IFACE_("Trim offset: %d"), offset);
1549                 }
1550         }
1551
1552         ED_area_headerprint(sa, msg);
1553 }
1554
1555 static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *event)
1556 {
1557         Scene *scene = CTX_data_scene(C);
1558         SlipData *data = (SlipData *)op->customdata;
1559         ScrArea *sa = CTX_wm_area(C);
1560         ARegion *ar = CTX_wm_region(C);
1561         const bool has_numInput = hasNumInput(&data->num_input);
1562         bool handled = true;
1563
1564         /* Modal numinput active, try to handle numeric inputs first... */
1565         if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &data->num_input, event)) {
1566                 float offset;
1567                 applyNumInput(&data->num_input, &offset);
1568
1569                 sequencer_slip_update_header(scene, sa, data, (int)offset);
1570
1571                 RNA_int_set(op->ptr, "offset", offset);
1572
1573                 if (sequencer_slip_recursively(scene, data, offset)) {
1574                         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1575                 }
1576
1577                 return OPERATOR_RUNNING_MODAL;
1578         }
1579
1580         switch (event->type) {
1581                 case MOUSEMOVE:
1582                 {
1583                         if (!has_numInput) {
1584                                 float mouseloc[2];
1585                                 int offset;
1586                                 int mouse_x;
1587                                 View2D *v2d = UI_view2d_fromcontext(C);
1588
1589                                 if (data->slow) {
1590                                         mouse_x = event->mval[0] - data->slow_offset;
1591                                         mouse_x *= 0.1f;
1592                                         mouse_x += data->slow_offset;
1593                                 }
1594                                 else {
1595                                         mouse_x = event->mval[0];
1596                                 }
1597
1598
1599                                 /* choose the side based on which side of the playhead the mouse is on */
1600                                 UI_view2d_region_to_view(v2d, mouse_x, 0, &mouseloc[0], &mouseloc[1]);
1601                                 offset = mouseloc[0] - data->init_mouseloc[0];
1602
1603                                 sequencer_slip_update_header(scene, sa, data, offset);
1604
1605                                 RNA_int_set(op->ptr, "offset", offset);
1606
1607                                 if (sequencer_slip_recursively(scene, data, offset)) {
1608                                         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1609                                 }
1610                         }
1611                         break;
1612                 }
1613
1614                 case LEFTMOUSE:
1615                 case RETKEY:
1616                 case SPACEKEY:
1617                 {
1618                         ED_region_draw_cb_exit(ar->type, data->draw_handle);
1619                         MEM_freeN(data->seq_array);
1620                         MEM_freeN(data->trim);
1621                         MEM_freeN(data->ts);
1622                         MEM_freeN(data);
1623                         op->customdata = NULL;
1624                         if (sa) {
1625                                 ED_area_headerprint(sa, NULL);
1626                         }
1627                         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1628                         return OPERATOR_FINISHED;
1629                 }
1630
1631                 case ESCKEY:
1632                 case RIGHTMOUSE:
1633                 {
1634                         int i;
1635                         Editing *ed = BKE_sequencer_editing_get(scene, false);
1636
1637                         for (i = 0; i < data->num_seq; i++) {
1638                                 transseq_restore(data->ts + i, data->seq_array[i]);
1639                         }
1640
1641                         for (i = 0; i < data->num_seq; i++) {
1642                                 Sequence *seq = data->seq_array[i];
1643                                 BKE_sequence_reload_new_file(scene, seq, false);
1644                                 BKE_sequence_calc(scene, seq);
1645                         }
1646
1647                         ED_region_draw_cb_exit(ar->type, data->draw_handle);
1648
1649                         MEM_freeN(data->seq_array);
1650                         MEM_freeN(data->ts);
1651                         MEM_freeN(data->trim);
1652                         MEM_freeN(data);
1653                         op->customdata = NULL;
1654
1655                         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1656
1657                         BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
1658
1659                         if (sa) {
1660                                 ED_area_headerprint(sa, NULL);
1661                         }
1662
1663                         return OPERATOR_CANCELLED;
1664                 }
1665
1666                 case RIGHTSHIFTKEY:
1667                 case LEFTSHIFTKEY:
1668                         if (!has_numInput) {
1669                                 if (event->val == KM_PRESS) {
1670                                         data->slow = true;
1671                                         data->slow_offset = event->mval[0];
1672                                 }
1673                                 else if (event->val == KM_RELEASE) {
1674                                         data->slow = false;
1675                                 }
1676                         }
1677                         break;
1678
1679                 default:
1680                         handled = false;
1681                         break;
1682         }
1683
1684         /* Modal numinput inactive, try to handle numeric inputs last... */
1685         if (!handled && event->val == KM_PRESS && handleNumInput(C, &data->num_input, event)) {
1686                 float offset;
1687                 applyNumInput(&data->num_input, &offset);
1688
1689                 sequencer_slip_update_header(scene, sa, data, (int)offset);
1690
1691                 RNA_int_set(op->ptr, "offset", offset);
1692
1693                 if (sequencer_slip_recursively(scene, data, offset)) {
1694                         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1695                 }
1696         }
1697
1698         return OPERATOR_RUNNING_MODAL;
1699 }
1700
1701 void SEQUENCER_OT_slip(struct wmOperatorType *ot)
1702 {
1703         /* identifiers */
1704         ot->name = "Trim Strips";
1705         ot->idname = "SEQUENCER_OT_slip";
1706         ot->description = "Trim the contents of the active strip";
1707
1708         /* api callbacks */
1709         ot->invoke = sequencer_slip_invoke;
1710         ot->modal = sequencer_slip_modal;
1711         ot->exec = sequencer_slip_exec;
1712         ot->poll = sequencer_edit_poll;
1713
1714         /* flags */
1715         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1716
1717         RNA_def_int(ot->srna, "offset", 0, INT32_MIN, INT32_MAX, "Offset", "Offset to the data of the strip",
1718                     INT32_MIN, INT32_MAX);
1719 }
1720
1721 /* mute operator */
1722 static int sequencer_mute_exec(bContext *C, wmOperator *op)
1723 {
1724         Scene *scene = CTX_data_scene(C);
1725         Editing *ed = BKE_sequencer_editing_get(scene, false);
1726         Sequence *seq;
1727         bool selected;
1728
1729         selected = !RNA_boolean_get(op->ptr, "unselected");
1730
1731         for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1732                 if ((seq->flag & SEQ_LOCK) == 0) {
1733                         if (selected) { /* mute unselected */
1734                                 if (seq->flag & SELECT) {
1735                                         seq->flag |= SEQ_MUTE;
1736                                         BKE_sequence_invalidate_dependent(scene, seq);
1737                                 }
1738                         }
1739                         else {
1740                                 if ((seq->flag & SELECT) == 0) {
1741                                         seq->flag |= SEQ_MUTE;
1742                                         BKE_sequence_invalidate_dependent(scene, seq);
1743                                 }
1744                         }
1745                 }
1746         }
1747
1748         BKE_sequencer_update_muting(ed);
1749         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1750
1751         return OPERATOR_FINISHED;
1752 }
1753
1754 void SEQUENCER_OT_mute(struct wmOperatorType *ot)
1755 {
1756         /* identifiers */
1757         ot->name = "Mute Strips";
1758         ot->idname = "SEQUENCER_OT_mute";
1759         ot->description = "Mute (un)selected strips";
1760
1761         /* api callbacks */
1762         ot->exec = sequencer_mute_exec;
1763         ot->poll = sequencer_edit_poll;
1764
1765         /* flags */
1766         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1767
1768         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Mute unselected rather than selected strips");
1769 }
1770
1771
1772 /* unmute operator */
1773 static int sequencer_unmute_exec(bContext *C, wmOperator *op)
1774 {
1775         Scene *scene = CTX_data_scene(C);
1776         Editing *ed = BKE_sequencer_editing_get(scene, false);
1777         Sequence *seq;
1778         bool selected;
1779
1780         selected = !RNA_boolean_get(op->ptr, "unselected");
1781
1782         for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1783                 if ((seq->flag & SEQ_LOCK) == 0) {
1784                         if (selected) { /* unmute unselected */
1785                                 if (seq->flag & SELECT) {
1786                                         seq->flag &= ~SEQ_MUTE;
1787                                         BKE_sequence_invalidate_dependent(scene, seq);
1788                                 }
1789                         }
1790                         else {
1791                                 if ((seq->flag & SELECT) == 0) {
1792                                         seq->flag &= ~SEQ_MUTE;
1793                                         BKE_sequence_invalidate_dependent(scene, seq);
1794                                 }
1795                         }
1796                 }
1797         }
1798
1799         BKE_sequencer_update_muting(ed);
1800         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1801
1802         return OPERATOR_FINISHED;
1803 }
1804
1805 void SEQUENCER_OT_unmute(struct wmOperatorType *ot)
1806 {
1807         /* identifiers */
1808         ot->name = "Un-Mute Strips";
1809         ot->idname = "SEQUENCER_OT_unmute";
1810         ot->description = "Unmute (un)selected strips";
1811
1812         /* api callbacks */
1813         ot->exec = sequencer_unmute_exec;
1814         ot->poll = sequencer_edit_poll;
1815
1816         /* flags */
1817         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1818
1819         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Unmute unselected rather than selected strips");
1820 }
1821
1822
1823 /* lock operator */
1824 static int sequencer_lock_exec(bContext *C, wmOperator *UNUSED(op))
1825 {
1826         Scene *scene = CTX_data_scene(C);
1827         Editing *ed = BKE_sequencer_editing_get(scene, false);
1828         Sequence *seq;
1829
1830         for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1831                 if (seq->flag & SELECT) {
1832                         seq->flag |= SEQ_LOCK;
1833                 }
1834         }
1835
1836         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1837
1838         return OPERATOR_FINISHED;
1839 }
1840
1841 void SEQUENCER_OT_lock(struct wmOperatorType *ot)
1842 {
1843         /* identifiers */
1844         ot->name = "Lock Strips";
1845         ot->idname = "SEQUENCER_OT_lock";
1846         ot->description = "Lock the active strip so that it can't be transformed";
1847
1848         /* api callbacks */
1849         ot->exec = sequencer_lock_exec;
1850         ot->poll = sequencer_edit_poll;
1851
1852         /* flags */
1853         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1854 }
1855
1856 /* unlock operator */
1857 static int sequencer_unlock_exec(bContext *C, wmOperator *UNUSED(op))
1858 {
1859         Scene *scene = CTX_data_scene(C);
1860         Editing *ed = BKE_sequencer_editing_get(scene, false);
1861         Sequence *seq;
1862
1863         for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1864                 if (seq->flag & SELECT) {
1865                         seq->flag &= ~SEQ_LOCK;
1866                 }
1867         }
1868
1869         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1870
1871         return OPERATOR_FINISHED;
1872 }
1873
1874 void SEQUENCER_OT_unlock(struct wmOperatorType *ot)
1875 {
1876         /* identifiers */
1877         ot->name = "UnLock Strips";
1878         ot->idname = "SEQUENCER_OT_unlock";
1879         ot->description = "Unlock the active strip so that it can't be transformed";
1880
1881         /* api callbacks */
1882         ot->exec = sequencer_unlock_exec;
1883         ot->poll = sequencer_edit_poll;
1884
1885         /* flags */
1886         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1887 }
1888
1889 /* reload operator */
1890 static int sequencer_reload_exec(bContext *C, wmOperator *op)
1891 {
1892         Scene *scene = CTX_data_scene(C);
1893         Editing *ed = BKE_sequencer_editing_get(scene, false);
1894         Sequence *seq;
1895         const bool adjust_length = RNA_boolean_get(op->ptr, "adjust_length");
1896
1897         for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1898                 if (seq->flag & SELECT) {
1899                         BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1);
1900                         BKE_sequence_reload_new_file(scene, seq, !adjust_length);
1901
1902                         if (adjust_length) {
1903                                 if (BKE_sequence_test_overlap(ed->seqbasep, seq))
1904                                         BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
1905                         }
1906                 }
1907         }
1908
1909         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1910
1911         return OPERATOR_FINISHED;
1912 }
1913
1914 void SEQUENCER_OT_reload(struct wmOperatorType *ot)
1915 {
1916         PropertyRNA *prop;
1917
1918         /* identifiers */
1919         ot->name = "Reload Strips";
1920         ot->idname = "SEQUENCER_OT_reload";
1921         ot->description = "Reload strips in the sequencer";
1922
1923         /* api callbacks */
1924         ot->exec = sequencer_reload_exec;
1925         ot->poll = sequencer_edit_poll;
1926
1927         /* flags */
1928         ot->flag = OPTYPE_REGISTER; /* no undo, the data changed is stored outside 'main' */
1929
1930         prop = RNA_def_boolean(ot->srna, "adjust_length", 0, "Adjust Length",
1931                                "Adjust length of strips to their data length");
1932         RNA_def_property_flag(prop, PROP_SKIP_SAVE);
1933 }
1934
1935 /* reload operator */
1936 static bool sequencer_refresh_all_poll(bContext *C)
1937 {
1938         if (G.is_rendering) {
1939                 return 0;
1940         }
1941         return sequencer_edit_poll(C);
1942 }
1943
1944 static int sequencer_refresh_all_exec(bContext *C, wmOperator *UNUSED(op))
1945 {
1946         Scene *scene = CTX_data_scene(C);
1947         Editing *ed = BKE_sequencer_editing_get(scene, false);
1948
1949         BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
1950
1951         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1952
1953         return OPERATOR_FINISHED;
1954 }
1955
1956 void SEQUENCER_OT_refresh_all(struct wmOperatorType *ot)
1957 {
1958         /* identifiers */
1959         ot->name = "Refresh Sequencer";
1960         ot->idname = "SEQUENCER_OT_refresh_all";
1961         ot->description = "Refresh the sequencer editor";
1962
1963         /* api callbacks */
1964         ot->exec = sequencer_refresh_all_exec;
1965         ot->poll = sequencer_refresh_all_poll;
1966 }
1967
1968 static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op)
1969 {
1970         Scene *scene = CTX_data_scene(C);
1971         Sequence *seq1, *seq2, *seq3, *last_seq = BKE_sequencer_active_get(scene);
1972         const char *error_msg;
1973
1974         if (!seq_effect_find_selected(scene, last_seq, last_seq->type, &seq1, &seq2, &seq3, &error_msg)) {
1975                 BKE_report(op->reports, RPT_ERROR, error_msg);
1976                 return OPERATOR_CANCELLED;
1977         }
1978         /* see reassigning would create a cycle */
1979         if (seq_is_predecessor(seq1, last_seq) ||
1980             seq_is_predecessor(seq2, last_seq) ||
1981             seq_is_predecessor(seq3, last_seq))
1982         {
1983                 BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: no cycles allowed");
1984                 return OPERATOR_CANCELLED;
1985         }
1986
1987         last_seq->seq1 = seq1;
1988         last_seq->seq2 = seq2;
1989         last_seq->seq3 = seq3;
1990
1991         BKE_sequencer_update_changed_seq_and_deps(scene, last_seq, 1, 1);
1992
1993         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1994
1995         return OPERATOR_FINISHED;
1996 }
1997
1998 static bool sequencer_effect_poll(bContext *C)
1999 {
2000         Scene *scene = CTX_data_scene(C);
2001         Editing *ed = BKE_sequencer_editing_get(scene, false);
2002
2003         if (ed) {
2004                 Sequence *last_seq = BKE_sequencer_active_get(scene);
2005                 if (last_seq && (last_seq->type & SEQ_TYPE_EFFECT)) {
2006                         return 1;
2007                 }
2008         }
2009
2010         return 0;
2011 }
2012
2013 void SEQUENCER_OT_reassign_inputs(struct wmOperatorType *ot)
2014 {
2015         /* identifiers */
2016         ot->name = "Reassign Inputs";
2017         ot->idname = "SEQUENCER_OT_reassign_inputs";
2018         ot->description = "Reassign the inputs for the effect strip";
2019
2020         /* api callbacks */
2021         ot->exec = sequencer_reassign_inputs_exec;
2022         ot->poll = sequencer_effect_poll;
2023
2024         /* flags */
2025         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2026 }
2027
2028
2029 static int sequencer_swap_inputs_exec(bContext *C, wmOperator *op)
2030 {
2031         Scene *scene = CTX_data_scene(C);
2032         Sequence *seq, *last_seq = BKE_sequencer_active_get(scene);
2033
2034         if (last_seq->seq1 == NULL || last_seq->seq2 == NULL) {
2035                 BKE_report(op->reports, RPT_ERROR, "No valid inputs to swap");
2036                 return OPERATOR_CANCELLED;
2037         }
2038
2039         seq = last_seq->seq1;
2040         last_seq->seq1 = last_seq->seq2;
2041         last_seq->seq2 = seq;
2042
2043         BKE_sequencer_update_changed_seq_and_deps(scene, last_seq, 1, 1);
2044
2045         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2046
2047         return OPERATOR_FINISHED;
2048 }
2049 void SEQUENCER_OT_swap_inputs(struct wmOperatorType *ot)
2050 {
2051         /* identifiers */
2052         ot->name = "Swap Inputs";
2053         ot->idname = "SEQUENCER_OT_swap_inputs";
2054         ot->description = "Swap the first two inputs for the effect strip";
2055
2056         /* api callbacks */
2057         ot->exec = sequencer_swap_inputs_exec;
2058         ot->poll = sequencer_effect_poll;
2059
2060         /* flags */
2061         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2062 }
2063
2064
2065 /* cut operator */
2066 static const EnumPropertyItem prop_cut_types[] = {
2067         {SEQ_CUT_SOFT, "SOFT", 0, "Soft", ""},
2068         {SEQ_CUT_HARD, "HARD", 0, "Hard", ""},
2069         {0, NULL, 0, NULL, NULL}
2070 };
2071
2072 static int sequencer_cut_exec(bContext *C, wmOperator *op)
2073 {
2074         Scene *scene = CTX_data_scene(C);
2075         Editing *ed = BKE_sequencer_editing_get(scene, false);
2076         int cut_side, cut_hard, cut_frame;
2077
2078         bool changed;
2079
2080         cut_frame = RNA_int_get(op->ptr, "frame");
2081         cut_hard = RNA_enum_get(op->ptr, "type");
2082         cut_side = RNA_enum_get(op->ptr, "side");
2083
2084         if (cut_hard == SEQ_CUT_HARD) {
2085                 changed = cut_seq_list(scene, ed->seqbasep, cut_frame, cut_seq_hard);
2086         }
2087         else {
2088                 changed = cut_seq_list(scene, ed->seqbasep, cut_frame, cut_seq_soft);
2089         }
2090
2091         if (changed) { /* got new strips ? */
2092                 Sequence *seq;
2093
2094                 if (cut_side != SEQ_SIDE_BOTH) {
2095                         SEQP_BEGIN (ed, seq)
2096                         {
2097                                 if (cut_side == SEQ_SIDE_LEFT) {
2098                                         if (seq->startdisp >= cut_frame) {
2099                                                 seq->flag &= ~SEQ_ALLSEL;
2100                                         }
2101                                 }
2102                                 else {
2103                                         if (seq->enddisp <= cut_frame) {
2104                                                 seq->flag &= ~SEQ_ALLSEL;
2105                                         }
2106                                 }
2107                         }
2108                         SEQ_END;
2109                 }
2110
2111                 SEQP_BEGIN (ed, seq)
2112                 {
2113                         BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
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, seq, SEQ_DUPE_UNIQUE_NAME);
2416                                 BLI_addtail(ed->seqbasep, seq_new);
2417
2418                                 seq_new->start = start_ofs;
2419                                 seq_new->type = SEQ_TYPE_IMAGE;
2420                                 seq_new->len = 1;
2421                                 seq_new->endstill = step - 1;
2422
2423                                 /* new strip */
2424                                 strip_new = seq_new->strip;
2425                                 strip_new->us = 1;
2426
2427                                 /* new stripdata (only one element now!) */
2428                                 /* Note this assume all elements (images) have the same dimension, 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
3185         if (se) {
3186                 // prevent setting the render size if sequence values aren't initialized
3187                 if ((se->orig_width > 0) && (se->orig_height > 0)) {
3188                         scene->r.xsch = se->orig_width;
3189                         scene->r.ysch = se->orig_height;