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