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