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