replace MIN/MAX 3,4 with inline functions
[blender-staging.git] / source / blender / editors / space_sequencer / sequencer_add.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, 2003-2009, Campbell Barton
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/space_sequencer/sequencer_add.c
27  *  \ingroup spseq
28  */
29
30
31 #include <stdlib.h>
32 #include <math.h>
33 #include <string.h>
34
35 #ifndef WIN32
36 #include <unistd.h>
37 #else
38 #include <io.h>
39 #endif
40 #include <sys/types.h>
41
42 #include "MEM_guardedalloc.h"
43
44 #include "BLI_blenlib.h"
45 #include "BLI_math.h"
46 #include "BLI_utildefines.h"
47
48 #include "DNA_scene_types.h"
49 #include "DNA_mask_types.h"
50 #include "DNA_userdef_types.h"
51
52 #include "BKE_context.h"
53 #include "BKE_global.h"
54 #include "BKE_library.h"
55 #include "BKE_main.h"
56 #include "BKE_sequencer.h"
57 #include "BKE_movieclip.h"
58 #include "BKE_sequencer.h"
59 #include "BKE_mask.h"
60 #include "BKE_report.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_sequencer.h"
72
73 #include "UI_view2d.h"
74
75 #include "BKE_sound.h"
76
77 #ifdef WITH_AUDASPACE
78 #  include "AUD_C-API.h"
79 #endif
80
81 /* own include */
82 #include "sequencer_intern.h"
83
84 /* Generic functions, reused by add strip operators */
85
86 /* avoid passing multiple args and be more verbose */
87 #define SEQPROP_STARTFRAME  (1 << 0)
88 #define SEQPROP_ENDFRAME    (1 << 1)
89 #define SEQPROP_NOPATHS     (1 << 2)
90 #define SEQPROP_NOCHAN      (1 << 3)
91
92 #define SELECT 1
93
94 static void sequencer_generic_props__internal(wmOperatorType *ot, int flag)
95 {
96         PropertyRNA *prop;
97
98         if (flag & SEQPROP_STARTFRAME)
99                 RNA_def_int(ot->srna, "frame_start", 0, INT_MIN, INT_MAX, "Start Frame", "Start frame of the sequence strip", INT_MIN, INT_MAX);
100         
101         if (flag & SEQPROP_ENDFRAME)
102                 RNA_def_int(ot->srna, "frame_end", 0, INT_MIN, INT_MAX, "End Frame", "End frame for the color strip", INT_MIN, INT_MAX);  /* not usual since most strips have a fixed length */
103         
104         RNA_def_int(ot->srna, "channel", 1, 1, MAXSEQ, "Channel", "Channel to place this strip into", 1, MAXSEQ);
105         
106         RNA_def_boolean(ot->srna, "replace_sel", 1, "Replace Selection", "Replace the current selection");
107
108         /* only for python scripts which import strips and place them after */
109         prop = RNA_def_boolean(ot->srna, "overlap", 0, "Allow Overlap", "Don't correct overlap on new sequence strips");
110         RNA_def_property_flag(prop, PROP_HIDDEN);
111 }
112
113 static void sequencer_generic_invoke_path__internal(bContext *C, wmOperator *op, const char *identifier)
114 {
115         if (RNA_struct_find_property(op->ptr, identifier)) {
116                 Scene *scene = CTX_data_scene(C);
117                 Sequence *last_seq = BKE_sequencer_active_get(scene);
118                 if (last_seq && last_seq->strip && SEQ_HAS_PATH(last_seq)) {
119                         char path[sizeof(last_seq->strip->dir)];
120                         BLI_strncpy(path, last_seq->strip->dir, sizeof(path));
121                         BLI_path_abs(path, G.main->name);
122                         RNA_string_set(op->ptr, identifier, path);
123                 }
124         }
125 }
126
127 static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, wmEvent *event, int flag)
128 {
129         View2D *v2d = UI_view2d_fromcontext(C);
130         
131         float mval_v2d[2];
132         
133         UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mval_v2d[0], &mval_v2d[1]);
134
135         /* effect strips don't need a channel initialized from the mouse */
136         if (!(flag & SEQPROP_NOCHAN)) {
137                 RNA_int_set(op->ptr, "channel", (int)mval_v2d[1] + 0.5f);
138         }
139
140         RNA_int_set(op->ptr, "frame_start", (int)mval_v2d[0]);
141         
142         if ((flag & SEQPROP_ENDFRAME) && RNA_struct_property_is_set(op->ptr, "frame_end") == 0)
143                 RNA_int_set(op->ptr, "frame_end", (int)mval_v2d[0] + 25);  // XXX arbitary but ok for now.
144
145         if (!(flag & SEQPROP_NOPATHS)) {
146                 sequencer_generic_invoke_path__internal(C, op, "filepath");
147                 sequencer_generic_invoke_path__internal(C, op, "directory");
148         }
149 }
150
151 static void seq_load_operator_info(SeqLoadInfo *seq_load, wmOperator *op)
152 {
153         int relative = RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path");
154         int is_file = -1;
155         memset(seq_load, 0, sizeof(SeqLoadInfo));
156
157         seq_load->start_frame =  RNA_int_get(op->ptr, "frame_start");
158         seq_load->end_frame =    seq_load->start_frame; /* un-set */
159
160         seq_load->channel =      RNA_int_get(op->ptr, "channel");
161         seq_load->len =          1; // images only, if endframe isn't set!
162
163         if (RNA_struct_find_property(op->ptr, "filepath")) {
164                 RNA_string_get(op->ptr, "filepath", seq_load->path); /* full path, file is set by the caller */
165                 is_file = 1;
166         }
167         else if (RNA_struct_find_property(op->ptr, "directory")) {
168                 RNA_string_get(op->ptr, "directory", seq_load->path); /* full path, file is set by the caller */
169                 is_file = 0;
170         }
171
172         if ((is_file != -1) && relative)
173                 BLI_path_rel(seq_load->path, G.main->name);
174
175         
176         if (RNA_struct_find_property(op->ptr, "frame_end")) {
177                 seq_load->end_frame = RNA_int_get(op->ptr, "frame_end");
178         }
179
180         if (RNA_struct_find_property(op->ptr, "replace_sel") && RNA_boolean_get(op->ptr, "replace_sel"))
181                 seq_load->flag |= SEQ_LOAD_REPLACE_SEL;
182
183         if (RNA_struct_find_property(op->ptr, "cache") && RNA_boolean_get(op->ptr, "cache"))
184                 seq_load->flag |= SEQ_LOAD_SOUND_CACHE;
185
186         if (RNA_struct_find_property(op->ptr, "sound") && RNA_boolean_get(op->ptr, "sound"))
187                 seq_load->flag |= SEQ_LOAD_MOVIE_SOUND;
188
189         /* always use this for ops */
190         seq_load->flag |= SEQ_LOAD_FRAME_ADVANCE;
191
192
193         if (is_file == 1) {
194                 BLI_strncpy(seq_load->name, BLI_path_basename(seq_load->path), sizeof(seq_load->name));
195         }
196         else if (RNA_struct_find_property(op->ptr, "files")) {
197                 /* used for image strip */
198                 /* best guess, first images name */
199                 RNA_BEGIN (op->ptr, itemptr, "files")
200                 {
201                         char *name = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
202                         BLI_strncpy(seq_load->name, name, sizeof(seq_load->name));
203                         MEM_freeN(name);
204                         break;
205                 }
206                 RNA_END;
207         }
208 }
209
210 /* add scene operator */
211 static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
212 {
213         Scene *scene = CTX_data_scene(C);
214         Editing *ed = BKE_sequencer_editing_get(scene, TRUE);
215         
216         Scene *sce_seq;
217
218         Sequence *seq;  /* generic strip vars */
219         Strip *strip;
220         
221         int start_frame, channel; /* operator props */
222         
223         start_frame = RNA_int_get(op->ptr, "frame_start");
224         channel = RNA_int_get(op->ptr, "channel");
225         
226         sce_seq = BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene"));
227         
228         if (sce_seq == NULL) {
229                 BKE_report(op->reports, RPT_ERROR, "Scene not found");
230                 return OPERATOR_CANCELLED;
231         }
232         
233         seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel);
234         seq->type = SEQ_TYPE_SCENE;
235         seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
236
237         seq->scene = sce_seq;
238         
239         /* basic defaults */
240         seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
241         seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1;
242         strip->us = 1;
243         
244         BLI_strncpy(seq->name + 2, sce_seq->id.name + 2, sizeof(seq->name) - 2);
245         BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
246
247         seq->scene_sound = sound_scene_add_scene_sound(scene, seq, start_frame, start_frame + seq->len, 0);
248
249         BKE_sequence_calc_disp(scene, seq);
250         BKE_sequencer_sort(scene);
251         
252         if (RNA_boolean_get(op->ptr, "replace_sel")) {
253                 ED_sequencer_deselect_all(scene);
254                 BKE_sequencer_active_set(scene, seq);
255                 seq->flag |= SELECT;
256         }
257
258         if (RNA_boolean_get(op->ptr, "overlap") == FALSE) {
259                 if (BKE_sequence_test_overlap(ed->seqbasep, seq)) BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
260         }
261
262         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
263         
264         return OPERATOR_FINISHED;
265 }
266
267
268 static int sequencer_add_scene_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
269 {
270         if (!ED_operator_sequencer_active(C)) {
271                 BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
272                 return OPERATOR_CANCELLED;
273         }
274
275         if (!RNA_struct_property_is_set(op->ptr, "scene"))
276                 return WM_enum_search_invoke(C, op, event);
277
278         sequencer_generic_invoke_xy__internal(C, op, event, 0);
279         return sequencer_add_scene_strip_exec(C, op);
280         // needs a menu
281         // return WM_menu_invoke(C, op, event);
282 }
283
284
285 void SEQUENCER_OT_scene_strip_add(struct wmOperatorType *ot)
286 {
287         PropertyRNA *prop;
288         
289         /* identifiers */
290         ot->name = "Add Scene Strip";
291         ot->idname = "SEQUENCER_OT_scene_strip_add";
292         ot->description = "Add a strip to the sequencer using a blender scene as a source";
293
294         /* api callbacks */
295         ot->invoke = sequencer_add_scene_strip_invoke;
296         ot->exec = sequencer_add_scene_strip_exec;
297
298         ot->poll = ED_operator_scene_editable;
299         
300         /* flags */
301         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
302         
303         sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
304         prop = RNA_def_enum(ot->srna, "scene", DummyRNA_NULL_items, 0, "Scene", "");
305         RNA_def_enum_funcs(prop, RNA_scene_itemf);
306         ot->prop = prop;
307 }
308
309 /* add movieclip operator */
310 static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op)
311 {
312         Scene *scene = CTX_data_scene(C);
313         Editing *ed = BKE_sequencer_editing_get(scene, TRUE);
314         
315         MovieClip *clip;
316
317         Sequence *seq;  /* generic strip vars */
318         Strip *strip;
319         
320         int start_frame, channel; /* operator props */
321         
322         start_frame = RNA_int_get(op->ptr, "frame_start");
323         channel = RNA_int_get(op->ptr, "channel");
324         
325         clip = BLI_findlink(&CTX_data_main(C)->movieclip, RNA_enum_get(op->ptr, "clip"));
326         
327         if (clip == NULL) {
328                 BKE_report(op->reports, RPT_ERROR, "Movie clip not found");
329                 return OPERATOR_CANCELLED;
330         }
331         
332         seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel);
333         seq->type = SEQ_TYPE_MOVIECLIP;
334         seq->blend_mode = SEQ_TYPE_CROSS;
335         seq->clip = clip;
336
337         if (seq->clip->id.us == 0)
338                 seq->clip->id.us = 1;
339
340         /* basic defaults */
341         seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
342         seq->len =  BKE_movieclip_get_duration(clip);
343         strip->us = 1;
344         
345         BLI_strncpy(seq->name + 2, clip->id.name + 2, sizeof(seq->name) - 2);
346         BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
347
348         BKE_sequence_calc_disp(scene, seq);
349         BKE_sequencer_sort(scene);
350         
351         if (RNA_boolean_get(op->ptr, "replace_sel")) {
352                 ED_sequencer_deselect_all(scene);
353                 BKE_sequencer_active_set(scene, seq);
354                 seq->flag |= SELECT;
355         }
356
357         if (RNA_boolean_get(op->ptr, "overlap") == FALSE) {
358                 if (BKE_sequence_test_overlap(ed->seqbasep, seq)) BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
359         }
360
361         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
362         
363         return OPERATOR_FINISHED;
364 }
365
366 static int sequencer_add_movieclip_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
367 {
368         if (!ED_operator_sequencer_active(C)) {
369                 BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
370                 return OPERATOR_CANCELLED;
371         }
372
373         if (!RNA_struct_property_is_set(op->ptr, "clip"))
374                 return WM_enum_search_invoke(C, op, event);
375
376         sequencer_generic_invoke_xy__internal(C, op, event, 0);
377         return sequencer_add_movieclip_strip_exec(C, op);
378         // needs a menu
379         // return WM_menu_invoke(C, op, event);
380 }
381
382 void SEQUENCER_OT_movieclip_strip_add(struct wmOperatorType *ot)
383 {
384         PropertyRNA *prop;
385
386         /* identifiers */
387         ot->name = "Add MovieClip Strip";
388         ot->idname = "SEQUENCER_OT_movieclip_strip_add";
389         ot->description = "Add a movieclip strip to the sequencer";
390
391         /* api callbacks */
392         ot->invoke = sequencer_add_movieclip_strip_invoke;
393         ot->exec = sequencer_add_movieclip_strip_exec;
394
395         ot->poll = ED_operator_scene_editable;
396
397         /* flags */
398         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
399
400         sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
401         prop = RNA_def_enum(ot->srna, "clip", DummyRNA_NULL_items, 0, "Clip", "");
402         RNA_def_enum_funcs(prop, RNA_movieclip_itemf);
403         ot->prop = prop;
404 }
405
406 static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op)
407 {
408         Scene *scene = CTX_data_scene(C);
409         Editing *ed = BKE_sequencer_editing_get(scene, TRUE);
410
411         Mask *mask;
412
413         Sequence *seq;  /* generic strip vars */
414         Strip *strip;
415
416         int start_frame, channel; /* operator props */
417
418         start_frame = RNA_int_get(op->ptr, "frame_start");
419         channel = RNA_int_get(op->ptr, "channel");
420
421         mask = BLI_findlink(&CTX_data_main(C)->mask, RNA_enum_get(op->ptr, "mask"));
422
423         if (mask == NULL) {
424                 BKE_report(op->reports, RPT_ERROR, "Mask not found");
425                 return OPERATOR_CANCELLED;
426         }
427
428         seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel);
429         seq->type = SEQ_TYPE_MASK;
430         seq->blend_mode = SEQ_TYPE_CROSS;
431         seq->mask = mask;
432
433         if (seq->mask->id.us == 0)
434                 seq->mask->id.us = 1;
435
436         /* basic defaults */
437         seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
438         seq->len = BKE_mask_get_duration(mask);
439         strip->us = 1;
440
441         BLI_strncpy(seq->name + 2, mask->id.name + 2, sizeof(seq->name) - 2);
442         BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
443
444         BKE_sequence_calc_disp(scene, seq);
445         BKE_sequencer_sort(scene);
446
447         if (RNA_boolean_get(op->ptr, "replace_sel")) {
448                 ED_sequencer_deselect_all(scene);
449                 BKE_sequencer_active_set(scene, seq);
450                 seq->flag |= SELECT;
451         }
452
453         if (RNA_boolean_get(op->ptr, "overlap") == FALSE) {
454                 if (BKE_sequence_test_overlap(ed->seqbasep, seq)) BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
455         }
456
457         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
458
459         return OPERATOR_FINISHED;
460 }
461
462 static int sequencer_add_mask_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
463 {
464         if (!ED_operator_sequencer_active(C)) {
465                 BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
466                 return OPERATOR_CANCELLED;
467         }
468
469         if (!RNA_struct_property_is_set(op->ptr, "mask"))
470                 return WM_enum_search_invoke(C, op, event);
471
472         sequencer_generic_invoke_xy__internal(C, op, event, 0);
473         return sequencer_add_mask_strip_exec(C, op);
474         // needs a menu
475         // return WM_menu_invoke(C, op, event);
476 }
477
478
479 void SEQUENCER_OT_mask_strip_add(struct wmOperatorType *ot)
480 {
481         PropertyRNA *prop;
482
483         /* identifiers */
484         ot->name = "Add Mask Strip";
485         ot->idname = "SEQUENCER_OT_mask_strip_add";
486         ot->description = "Add a mask strip to the sequencer";
487
488         /* api callbacks */
489         ot->invoke = sequencer_add_mask_strip_invoke;
490         ot->exec = sequencer_add_mask_strip_exec;
491
492         ot->poll = ED_operator_scene_editable;
493
494         /* flags */
495         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
496
497         sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
498         prop = RNA_def_enum(ot->srna, "mask", DummyRNA_NULL_items, 0, "Mask", "");
499         RNA_def_enum_funcs(prop, RNA_mask_itemf);
500         ot->prop = prop;
501 }
502
503
504 static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoadFunc seq_load_func)
505 {
506         Scene *scene = CTX_data_scene(C); /* only for sound */
507         Editing *ed = BKE_sequencer_editing_get(scene, TRUE);
508         SeqLoadInfo seq_load;
509         Sequence *seq;
510         int tot_files;
511         const short overlap = RNA_boolean_get(op->ptr, "overlap");
512
513         seq_load_operator_info(&seq_load, op);
514
515         if (seq_load.flag & SEQ_LOAD_REPLACE_SEL)
516                 ED_sequencer_deselect_all(scene);
517
518         if (RNA_struct_property_is_set(op->ptr, "files"))
519                 tot_files = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
520         else
521                 tot_files = 0;
522
523         if (tot_files) {
524                 /* multiple files */
525                 char dir_only[FILE_MAX];
526                 char file_only[FILE_MAX];
527
528                 BLI_split_dir_part(seq_load.path, dir_only, sizeof(dir_only));
529
530                 RNA_BEGIN (op->ptr, itemptr, "files")
531                 {
532                         RNA_string_get(&itemptr, "name", file_only);
533                         BLI_join_dirfile(seq_load.path, sizeof(seq_load.path), dir_only, file_only);
534
535                         seq = seq_load_func(C, ed->seqbasep, &seq_load);
536                         if (seq) {
537                                 if (overlap == FALSE) {
538                                         if (BKE_sequence_test_overlap(ed->seqbasep, seq)) BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
539                                 }
540                         }
541                 }
542                 RNA_END;
543         }
544         else {
545                 /* single file */
546                 seq = seq_load_func(C, ed->seqbasep, &seq_load);
547                 if (seq) {
548                         if (overlap == FALSE) {
549                                 if (BKE_sequence_test_overlap(ed->seqbasep, seq))
550                                         BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
551                         }
552                 }
553         }
554
555         if (seq_load.tot_success == 0) {
556                 BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", seq_load.path);
557                 return OPERATOR_CANCELLED;
558         }
559
560         BKE_sequencer_sort(scene);
561         BKE_sequencer_update_muting(ed);
562
563         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
564
565         return OPERATOR_FINISHED;
566 }
567
568 /* add movie operator */
569 static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
570 {
571         return sequencer_add_generic_strip_exec(C, op, BKE_sequencer_add_movie_strip);
572 }
573
574
575 static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
576 {
577
578         if (!ED_operator_sequencer_active(C)) {
579                 BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
580                 return OPERATOR_CANCELLED;
581         }
582
583         /* This is for drag and drop */
584         if ((RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) ||
585             RNA_struct_property_is_set(op->ptr, "filepath"))
586         {
587                 sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_NOPATHS);
588                 return sequencer_add_movie_strip_exec(C, op);
589         }
590         
591         sequencer_generic_invoke_xy__internal(C, op, event, 0);
592         
593         WM_event_add_fileselect(C, op);
594         return OPERATOR_RUNNING_MODAL;
595
596         //return sequencer_add_movie_strip_exec(C, op);
597 }
598
599
600 void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
601 {
602         
603         /* identifiers */
604         ot->name = "Add Movie Strip";
605         ot->idname = "SEQUENCER_OT_movie_strip_add";
606         ot->description = "Add a movie strip to the sequencer";
607
608         /* api callbacks */
609         ot->invoke = sequencer_add_movie_strip_invoke;
610         ot->exec = sequencer_add_movie_strip_exec;
611
612         ot->poll = ED_operator_scene_editable;
613         
614         /* flags */
615         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
616         
617         WM_operator_properties_filesel(ot, FOLDERFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
618                                        WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY);
619         sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
620         RNA_def_boolean(ot->srna, "sound", TRUE, "Sound", "Load sound with the movie");
621 }
622
623 /* add sound operator */
624
625 static int sequencer_add_sound_strip_exec(bContext *C, wmOperator *op)
626 {
627         return sequencer_add_generic_strip_exec(C, op, BKE_sequencer_add_sound_strip);
628 }
629
630 static int sequencer_add_sound_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
631 {
632
633         if (!ED_operator_sequencer_active(C)) {
634                 BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
635                 return OPERATOR_CANCELLED;
636         }
637         
638         /* This is for drag and drop */
639         if ((RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) ||
640             RNA_struct_property_is_set(op->ptr, "filepath"))
641         {
642                 sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_NOPATHS);
643                 return sequencer_add_sound_strip_exec(C, op);
644         }
645         
646         sequencer_generic_invoke_xy__internal(C, op, event, 0);
647
648         WM_event_add_fileselect(C, op);
649         return OPERATOR_RUNNING_MODAL;
650
651         //return sequencer_add_sound_strip_exec(C, op);
652 }
653
654
655 void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot)
656 {
657         
658         /* identifiers */
659         ot->name = "Add Sound Strip";
660         ot->idname = "SEQUENCER_OT_sound_strip_add";
661         ot->description = "Add a sound strip to the sequencer";
662
663         /* api callbacks */
664         ot->invoke = sequencer_add_sound_strip_invoke;
665         ot->exec = sequencer_add_sound_strip_exec;
666
667         ot->poll = ED_operator_scene_editable;
668         
669         /* flags */
670         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
671         
672         WM_operator_properties_filesel(ot, FOLDERFILE | SOUNDFILE, FILE_SPECIAL, FILE_OPENFILE,
673                                        WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY);
674         sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
675         RNA_def_boolean(ot->srna, "cache", FALSE, "Cache", "Cache the sound in memory");
676 }
677
678 /* add image operator */
679 static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
680 {
681         /* cant use the generic function for this */
682
683         Scene *scene = CTX_data_scene(C); /* only for sound */
684         Editing *ed = BKE_sequencer_editing_get(scene, TRUE);
685         SeqLoadInfo seq_load;
686         Sequence *seq;
687
688         Strip *strip;
689         StripElem *se;
690
691         seq_load_operator_info(&seq_load, op);
692
693         /* images are unique in how they handle this - 1 per strip elem */
694         seq_load.len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
695
696         if (seq_load.len == 0)
697                 return OPERATOR_CANCELLED;
698
699         if (seq_load.flag & SEQ_LOAD_REPLACE_SEL)
700                 ED_sequencer_deselect_all(scene);
701
702
703         /* main adding function */
704         seq = BKE_sequencer_add_image_strip(C, ed->seqbasep, &seq_load);
705         strip = seq->strip;
706         se = strip->stripdata;
707
708         RNA_BEGIN (op->ptr, itemptr, "files")
709         {
710                 char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
711                 BLI_strncpy(se->name, filename, sizeof(se->name));
712                 MEM_freeN(filename);
713                 se++;
714         }
715         RNA_END;
716
717         if (seq_load.len == 1) {
718                 if (seq_load.start_frame < seq_load.end_frame) {
719                         seq->endstill = seq_load.end_frame - seq_load.start_frame;
720                 }
721         }
722
723         BKE_sequence_init_colorspace(seq);
724
725         BKE_sequence_calc_disp(scene, seq);
726
727         BKE_sequencer_sort(scene);
728
729         /* last active name */
730         strncpy(ed->act_imagedir, strip->dir, FILE_MAXDIR - 1);
731
732         if (RNA_boolean_get(op->ptr, "overlap") == FALSE) {
733                 if (BKE_sequence_test_overlap(ed->seqbasep, seq))
734                         BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
735         }
736
737         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
738
739         return OPERATOR_FINISHED;
740 }
741
742 static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
743 {
744
745         if (!ED_operator_sequencer_active(C)) {
746                 BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
747                 return OPERATOR_CANCELLED;
748         }
749
750
751         /* drag drop has set the names */
752         if (RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) {
753                 sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_ENDFRAME | SEQPROP_NOPATHS);
754                 return sequencer_add_image_strip_exec(C, op);
755         }
756         
757         sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_ENDFRAME);
758
759         WM_event_add_fileselect(C, op);
760         return OPERATOR_RUNNING_MODAL;
761 }
762
763
764 void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
765 {
766         
767         /* identifiers */
768         ot->name = "Add Image Strip";
769         ot->idname = "SEQUENCER_OT_image_strip_add";
770         ot->description = "Add an image or image sequence to the sequencer";
771
772         /* api callbacks */
773         ot->invoke = sequencer_add_image_strip_invoke;
774         ot->exec = sequencer_add_image_strip_exec;
775
776         ot->poll = ED_operator_scene_editable;
777         
778         /* flags */
779         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
780         
781         WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE, FILE_SPECIAL, FILE_OPENFILE,
782                                        WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY);
783         sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME);
784 }
785
786
787 /* add_effect_strip operator */
788 static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
789 {
790         Scene *scene = CTX_data_scene(C);
791         Editing *ed = BKE_sequencer_editing_get(scene, TRUE);
792
793         Sequence *seq;  /* generic strip vars */
794         Strip *strip;
795         struct SeqEffectHandle sh;
796
797         int start_frame, end_frame, channel, type; /* operator props */
798         
799         Sequence *seq1, *seq2, *seq3;
800         const char *error_msg;
801
802         start_frame = RNA_int_get(op->ptr, "frame_start");
803         end_frame = RNA_int_get(op->ptr, "frame_end");
804         channel = RNA_int_get(op->ptr, "channel");
805
806         type = RNA_enum_get(op->ptr, "type");
807         
808         // XXX move to invoke
809         if (!seq_effect_find_selected(scene, NULL, type, &seq1, &seq2, &seq3, &error_msg)) {
810                 BKE_report(op->reports, RPT_ERROR, error_msg);
811                 return OPERATOR_CANCELLED;
812         }
813
814         /* If seq1 is NULL and no error was raised it means the seq is standalone
815          * (like color strips) and we need to check its start and end frames are valid */
816         if (seq1 == NULL && end_frame <= start_frame) {
817                 BKE_report(op->reports, RPT_ERROR, "Start and end frame are not set");
818                 return OPERATOR_CANCELLED;
819         }
820
821         seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel);
822         seq->type = type;
823
824         BLI_strncpy(seq->name + 2, BKE_sequence_give_name(seq), sizeof(seq->name) - 2);
825         BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
826
827         sh = BKE_sequence_get_effect(seq);
828
829         seq->seq1 = seq1;
830         seq->seq2 = seq2;
831         seq->seq3 = seq3;
832
833         sh.init(seq);
834
835         if (!seq1) { /* effect has no deps */
836                 seq->len = 1;
837                 BKE_sequence_tx_set_final_right(seq, end_frame);
838         }
839
840         seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
841
842         BKE_sequence_calc(scene, seq);
843         
844         /* basic defaults */
845         seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
846         strip->us = 1;
847
848         if (seq->type == SEQ_TYPE_COLOR) {
849                 SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
850                 RNA_float_get_array(op->ptr, "color", colvars->col);
851                 seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
852
853         }
854         else if (seq->type == SEQ_TYPE_ADJUSTMENT) {
855                 seq->blend_mode = SEQ_TYPE_CROSS;
856         }
857
858         /* an unset channel is a special case where we automatically go above
859          * the other strips. */
860         if (!RNA_struct_property_is_set(op->ptr, "channel")) {
861                 if (seq->seq1) {
862                         int chan = max_iii(seq->seq1 ? seq->seq1->machine : 0,
863                                            seq->seq2 ? seq->seq2->machine : 0,
864                                            seq->seq3 ? seq->seq3->machine : 0);
865                         if (chan < MAXSEQ)
866                                 seq->machine = chan;
867                 }
868         }
869
870         if (RNA_boolean_get(op->ptr, "overlap") == FALSE) {
871                 if (BKE_sequence_test_overlap(ed->seqbasep, seq)) BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
872         }
873
874         BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1); /* runs calc_sequence */
875
876
877         /* not sure if this is needed with update_changed_seq_and_deps.
878          * it was NOT called in blender 2.4x, but wont hurt */
879         BKE_sequencer_sort(scene); 
880
881         if (RNA_boolean_get(op->ptr, "replace_sel")) {
882                 ED_sequencer_deselect_all(scene);
883                 BKE_sequencer_active_set(scene, seq);
884                 seq->flag |= SELECT;
885         }
886
887         WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
888
889         return OPERATOR_FINISHED;
890 }
891
892
893 /* add color */
894 static int sequencer_add_effect_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
895 {
896         short is_type_set = RNA_struct_property_is_set(op->ptr, "type");
897         int type = -1;
898         int prop_flag = SEQPROP_ENDFRAME;
899
900         if (!ED_operator_sequencer_active(C)) {
901                 BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
902                 return OPERATOR_CANCELLED;
903         }
904
905         if (is_type_set) {
906                 type = RNA_enum_get(op->ptr, "type");
907
908                 /* when invoking an effect strip which uses inputs,
909                  * skip initializing the channel from the mouse.
910                  * Instead leave the property unset so exec() initializes it to be
911                  * above the strips its applied to. */
912                 if (BKE_sequence_effect_get_num_inputs(type) != 0) {
913                         prop_flag |= SEQPROP_NOCHAN;
914                 }
915         }
916
917         sequencer_generic_invoke_xy__internal(C, op, event, prop_flag);
918
919         return sequencer_add_effect_strip_exec(C, op);
920 }
921
922 void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot)
923 {
924         /* identifiers */
925         ot->name = "Add Effect Strip";
926         ot->idname = "SEQUENCER_OT_effect_strip_add";
927         ot->description = "Add an effect to the sequencer, most are applied on top of existing strips";
928
929         /* api callbacks */
930         ot->invoke = sequencer_add_effect_strip_invoke;
931         ot->exec = sequencer_add_effect_strip_exec;
932
933         ot->poll = ED_operator_scene_editable;
934         
935         /* flags */
936         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
937         
938         WM_operator_properties_filesel(ot, 0, FILE_SPECIAL, FILE_OPENFILE,
939                                        WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
940         sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME);
941         RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_TYPE_CROSS, "Type", "Sequencer effect type");
942         RNA_def_float_vector(ot->srna, "color", 3, NULL, 0.0f, 1.0f, "Color", "Initialize the strip with this color (only used when type='COLOR')", 0.0f, 1.0f);
943 }