doxygen: blender/editors tagged.
[blender-staging.git] / source / blender / editors / space_sequencer / sequencer_add.c
1 /*
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * Contributor(s): Blender Foundation, 2003-2009, Campbell Barton
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/editors/space_sequencer/sequencer_add.c
28  *  \ingroup spseq
29  */
30
31
32 #include <stdlib.h>
33 #include <math.h>
34 #include <string.h>
35
36 #ifndef WIN32
37 #include <unistd.h>
38 #else
39 #include <io.h>
40 #endif
41 #include <sys/types.h>
42
43 #include "MEM_guardedalloc.h"
44
45 #include "BLI_blenlib.h"
46 #include "BLI_math.h"
47 #include "BLI_storage_types.h"
48 #include "BLI_utildefines.h"
49
50 #include "DNA_scene_types.h"
51 #include "DNA_userdef_types.h"
52
53 #include "BKE_context.h"
54 #include "BKE_global.h"
55 #include "BKE_main.h"
56 #include "BKE_sequencer.h"
57 #include "BKE_report.h"
58
59
60 #include "WM_api.h"
61 #include "WM_types.h"
62
63 #include "RNA_define.h"
64 #include "RNA_enum_types.h"
65
66 /* for menu/popup icons etc etc*/
67
68 #include "ED_screen.h"
69
70 #include "UI_view2d.h"
71
72 #include "BKE_sound.h"
73 #include "AUD_C-API.h"
74
75 /* own include */
76 #include "sequencer_intern.h"
77
78 /* Generic functions, reused by add strip operators */
79
80 /* avoid passing multiple args and be more verbose */
81 #define SEQPROP_STARTFRAME      (1<<0)
82 #define SEQPROP_ENDFRAME        (1<<1)
83 #define SEQPROP_FILES           (1<<2)
84 #define SEQPROP_NOPATHS         (1<<3)
85
86 #define SELECT 1
87
88 static void sequencer_generic_props__internal(wmOperatorType *ot, int flag)
89 {
90         if(flag & SEQPROP_STARTFRAME)
91                 RNA_def_int(ot->srna, "frame_start", 0, INT_MIN, INT_MAX, "Start Frame", "Start frame of the sequence strip", INT_MIN, INT_MAX);
92         
93         if(flag & SEQPROP_ENDFRAME)
94                 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 useual since most strips have a fixed length */
95         
96         RNA_def_int(ot->srna, "channel", 1, 1, MAXSEQ, "Channel", "Channel to place this strip into", 1, MAXSEQ);
97         
98         RNA_def_boolean(ot->srna, "replace_sel", 1, "Replace Selection", "replace the current selection");
99
100         if(flag & SEQPROP_FILES)
101                 RNA_def_collection_runtime(ot->srna, "files", &RNA_OperatorFileListElement, "Files", "");
102 }
103
104 static void sequencer_generic_invoke_path__internal(bContext *C, wmOperator *op, const char *identifier)
105 {
106         if(RNA_struct_find_property(op->ptr, identifier)) {
107                 Scene *scene= CTX_data_scene(C);
108                 Sequence *last_seq= seq_active_get(scene);
109                 if(last_seq && last_seq->strip && SEQ_HAS_PATH(last_seq)) {
110                         char path[sizeof(last_seq->strip->dir)];
111                         BLI_strncpy(path, last_seq->strip->dir, sizeof(path));
112                         BLI_path_abs(path, G.main->name);
113                         RNA_string_set(op->ptr, identifier, path);
114                 }
115         }
116 }
117
118 static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, wmEvent *event, int flag)
119 {
120         ARegion *ar= CTX_wm_region(C);
121         View2D *v2d= UI_view2d_fromcontext(C);
122         
123         short mval[2];  
124         float mval_v2d[2];
125         
126
127         mval[0]= event->x - ar->winrct.xmin;
128         mval[1]= event->y - ar->winrct.ymin;
129         
130         UI_view2d_region_to_view(v2d, mval[0], mval[1], &mval_v2d[0], &mval_v2d[1]);
131         
132         RNA_int_set(op->ptr, "channel", (int)mval_v2d[1]+0.5f);
133         RNA_int_set(op->ptr, "frame_start", (int)mval_v2d[0]);
134         
135         if ((flag & SEQPROP_ENDFRAME) && RNA_property_is_set(op->ptr, "frame_end")==0)
136                 RNA_int_set(op->ptr, "frame_end", (int)mval_v2d[0] + 25); // XXX arbitary but ok for now.
137
138         if (!(flag & SEQPROP_NOPATHS)) {
139                 sequencer_generic_invoke_path__internal(C, op, "filepath");
140                 sequencer_generic_invoke_path__internal(C, op, "directory");
141         }
142 }
143
144 static void seq_load_operator_info(SeqLoadInfo *seq_load, wmOperator *op)
145 {
146         int relative= RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path");
147         int is_file= -1;
148         memset(seq_load, 0, sizeof(SeqLoadInfo));
149
150         seq_load->start_frame=  RNA_int_get(op->ptr, "frame_start");
151         seq_load->end_frame=    seq_load->start_frame; /* un-set */
152
153         seq_load->channel=              RNA_int_get(op->ptr, "channel");
154         seq_load->len=                  1; // images only, if endframe isnt set!
155
156         if(RNA_struct_find_property(op->ptr, "filepath")) {
157                 RNA_string_get(op->ptr, "filepath", seq_load->path); /* full path, file is set by the caller */
158                 is_file= 1;
159         } else if (RNA_struct_find_property(op->ptr, "directory")) {
160                 RNA_string_get(op->ptr, "directory", seq_load->path); /* full path, file is set by the caller */
161                 is_file= 0;
162         }
163
164         if((is_file != -1) && relative)
165                 BLI_path_rel(seq_load->path, G.main->name);
166
167         
168         if (RNA_struct_find_property(op->ptr, "frame_end")) {
169                 seq_load->end_frame = RNA_int_get(op->ptr, "frame_end");
170         }
171
172         if (RNA_struct_find_property(op->ptr, "replace_sel") && RNA_boolean_get(op->ptr, "replace_sel"))
173                 seq_load->flag |= SEQ_LOAD_REPLACE_SEL;
174
175         if (RNA_struct_find_property(op->ptr, "cache") && RNA_boolean_get(op->ptr, "cache"))
176                 seq_load->flag |= SEQ_LOAD_SOUND_CACHE;
177
178         if (RNA_struct_find_property(op->ptr, "sound") && RNA_boolean_get(op->ptr, "sound"))
179                 seq_load->flag |= SEQ_LOAD_MOVIE_SOUND;
180
181         /* always use this for ops */
182         seq_load->flag |= SEQ_LOAD_FRAME_ADVANCE;
183
184
185         if(is_file==1) {
186                 BLI_strncpy(seq_load->name, BLI_path_basename(seq_load->path), sizeof(seq_load->name));
187         }
188         else if(RNA_struct_find_property(op->ptr, "files")) {
189                 /* used for image strip */
190                 /* best guess, first images name */
191                 RNA_BEGIN(op->ptr, itemptr, "files") {
192                         char *name= RNA_string_get_alloc(&itemptr, "name", NULL, 0);
193                         BLI_strncpy(seq_load->name, name, sizeof(seq_load->name));
194                         MEM_freeN(name);
195                         break;
196                 }
197                 RNA_END;
198         }
199 }
200
201 /* add scene operator */
202 static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
203 {
204         Scene *scene= CTX_data_scene(C);
205         Editing *ed= seq_give_editing(scene, TRUE);
206         
207         Scene *sce_seq;
208
209         Sequence *seq;  /* generic strip vars */
210         Strip *strip;
211         
212         int start_frame, channel; /* operator props */
213         
214         start_frame= RNA_int_get(op->ptr, "frame_start");
215         channel= RNA_int_get(op->ptr, "channel");
216         
217         sce_seq= BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene"));
218         
219         if (sce_seq==NULL) {
220                 BKE_report(op->reports, RPT_ERROR, "Scene not found");
221                 return OPERATOR_CANCELLED;
222         }
223         
224         seq = alloc_sequence(ed->seqbasep, start_frame, channel);
225         seq->type= SEQ_SCENE;
226         seq->blend_mode= SEQ_CROSS; /* so alpha adjustment fade to the strip below */
227
228         seq->scene= sce_seq;
229         seq->sfra= sce_seq->r.sfra;
230         
231         /* basic defaults */
232         seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
233         strip->len = seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1;
234         strip->us= 1;
235         
236         strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
237         
238         strcpy(seq->name+2, sce_seq->id.name+2);
239         seqbase_unique_name_recursive(&ed->seqbase, seq);
240
241         seq->scene_sound = sound_scene_add_scene_sound(scene, seq, start_frame, start_frame + strip->len, 0);
242
243         calc_sequence_disp(scene, seq);
244         sort_seq(scene);
245         
246         if (RNA_boolean_get(op->ptr, "replace_sel")) {
247                 deselect_all_seq(scene);
248                 seq_active_set(scene, seq);
249                 seq->flag |= SELECT;
250         }
251         
252         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
253         
254         return OPERATOR_FINISHED;
255 }
256
257
258 static int sequencer_add_scene_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
259 {
260         if(!ED_operator_sequencer_active(C)) {
261                 BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
262                 return OPERATOR_CANCELLED;
263         }
264
265         if(!RNA_property_is_set(op->ptr, "scene"))
266                 return WM_enum_search_invoke(C, op, event);
267
268         sequencer_generic_invoke_xy__internal(C, op, event, 0);
269         return sequencer_add_scene_strip_exec(C, op);
270         // needs a menu
271         // return WM_menu_invoke(C, op, event);
272 }
273
274
275 void SEQUENCER_OT_scene_strip_add(struct wmOperatorType *ot)
276 {
277         PropertyRNA *prop;
278         
279         /* identifiers */
280         ot->name= "Add Scene Strip";
281         ot->idname= "SEQUENCER_OT_scene_strip_add";
282         ot->description= "Add a strip to the sequencer using a blender scene as a source";
283
284         /* api callbacks */
285         ot->invoke= sequencer_add_scene_strip_invoke;
286         ot->exec= sequencer_add_scene_strip_exec;
287
288         ot->poll= ED_operator_scene_editable;
289         
290         /* flags */
291         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
292         
293         sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
294         prop= RNA_def_enum(ot->srna, "scene", DummyRNA_NULL_items, 0, "Scene", "");
295         RNA_def_enum_funcs(prop, RNA_scene_itemf);
296         ot->prop= prop;
297 }
298
299 static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoadFunc seq_load_func)
300 {
301         Scene *scene= CTX_data_scene(C); /* only for sound */
302         Editing *ed= seq_give_editing(scene, TRUE);
303         SeqLoadInfo seq_load;
304         Sequence *seq;
305         int tot_files;
306
307         seq_load_operator_info(&seq_load, op);
308
309         if (seq_load.flag & SEQ_LOAD_REPLACE_SEL)
310                 deselect_all_seq(scene);
311
312         tot_files= RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
313
314         if(tot_files) {
315                 /* multiple files */
316                 char dir_only[FILE_MAX];
317                 char file_only[FILE_MAX];
318
319                 BLI_split_dirfile(seq_load.path, dir_only, NULL);
320
321                 RNA_BEGIN(op->ptr, itemptr, "files") {
322                         RNA_string_get(&itemptr, "name", file_only);
323                         BLI_join_dirfile(seq_load.path, sizeof(seq_load.path), dir_only, file_only);
324
325                         seq= seq_load_func(C, ed->seqbasep, &seq_load);
326                 }
327                 RNA_END;
328         }
329         else {
330                 /* single file */
331                 seq= seq_load_func(C, ed->seqbasep, &seq_load);
332         }
333
334         if (seq_load.tot_success==0) {
335                 BKE_reportf(op->reports, RPT_ERROR, "File \"%s\" could not be loaded", seq_load.path);
336                 return OPERATOR_CANCELLED;
337         }
338
339         sort_seq(scene);
340         seq_update_muting(scene, ed);
341
342         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
343
344         return OPERATOR_FINISHED;
345 }
346
347 /* add movie operator */
348 static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
349 {
350         return sequencer_add_generic_strip_exec(C, op, sequencer_add_movie_strip);
351 }
352
353
354 static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
355 {
356
357         if(!ED_operator_sequencer_active(C)) {
358                 BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
359                 return OPERATOR_CANCELLED;
360         }
361
362         /* This is for drag and drop */
363         if(RNA_collection_length(op->ptr, "files") || RNA_property_is_set(op->ptr, "filepath")) {
364                 sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_NOPATHS);
365                 return sequencer_add_movie_strip_exec(C, op);
366         }
367         
368         sequencer_generic_invoke_xy__internal(C, op, event, 0);
369         
370         if(!RNA_property_is_set(op->ptr, "relative_path"))
371                 RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS);
372         
373         WM_event_add_fileselect(C, op);
374         return OPERATOR_RUNNING_MODAL;
375
376         //return sequencer_add_movie_strip_exec(C, op);
377 }
378
379
380 void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
381 {
382         
383         /* identifiers */
384         ot->name= "Add Movie Strip";
385         ot->idname= "SEQUENCER_OT_movie_strip_add";
386         ot->description= "Add a movie strip to the sequencer";
387
388         /* api callbacks */
389         ot->invoke= sequencer_add_movie_strip_invoke;
390         ot->exec= sequencer_add_movie_strip_exec;
391
392         ot->poll= ED_operator_scene_editable;
393         
394         /* flags */
395         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
396         
397         WM_operator_properties_filesel(ot, FOLDERFILE|MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_FILEPATH|WM_FILESEL_RELPATH);
398         sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME|SEQPROP_FILES);
399         RNA_def_boolean(ot->srna, "sound", TRUE, "Sound", "Load sound with the movie");
400 }
401
402 /* add sound operator */
403
404 static int sequencer_add_sound_strip_exec(bContext *C, wmOperator *op)
405 {
406         return sequencer_add_generic_strip_exec(C, op, sequencer_add_sound_strip);
407 }
408
409 static int sequencer_add_sound_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
410 {
411
412         if(!ED_operator_sequencer_active(C)) {
413                 BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
414                 return OPERATOR_CANCELLED;
415         }
416         
417         /* This is for drag and drop */
418         if(RNA_collection_length(op->ptr, "files") || RNA_property_is_set(op->ptr, "filepath")) {
419                 sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_NOPATHS);
420                 return sequencer_add_sound_strip_exec(C, op);
421         }
422         
423         sequencer_generic_invoke_xy__internal(C, op, event, 0);
424         
425         if(!RNA_property_is_set(op->ptr, "relative_path"))
426                 RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS);
427         
428         WM_event_add_fileselect(C, op);
429         return OPERATOR_RUNNING_MODAL;
430
431         //return sequencer_add_sound_strip_exec(C, op);
432 }
433
434
435 void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot)
436 {
437         
438         /* identifiers */
439         ot->name= "Add Sound Strip";
440         ot->idname= "SEQUENCER_OT_sound_strip_add";
441         ot->description= "Add a sound strip to the sequencer";
442
443         /* api callbacks */
444         ot->invoke= sequencer_add_sound_strip_invoke;
445         ot->exec= sequencer_add_sound_strip_exec;
446
447         ot->poll= ED_operator_scene_editable;
448         
449         /* flags */
450         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
451         
452         WM_operator_properties_filesel(ot, FOLDERFILE|SOUNDFILE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_FILEPATH|WM_FILESEL_RELPATH);
453         sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME|SEQPROP_FILES);
454         RNA_def_boolean(ot->srna, "cache", FALSE, "Cache", "Cache the sound in memory.");
455 }
456
457 /* add image operator */
458 static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
459 {
460         /* cant use the generic function for this */
461
462         Scene *scene= CTX_data_scene(C); /* only for sound */
463         Editing *ed= seq_give_editing(scene, TRUE);
464         SeqLoadInfo seq_load;
465         Sequence *seq;
466
467         Strip *strip;
468         StripElem *se;
469
470         seq_load_operator_info(&seq_load, op);
471
472         /* images are unique in how they handle this - 1 per strip elem */
473         seq_load.len= RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
474
475         if(seq_load.len==0)
476                 return OPERATOR_CANCELLED;
477
478         if(seq_load.flag & SEQ_LOAD_REPLACE_SEL)
479                 deselect_all_seq(scene);
480
481
482         /* main adding function */
483         seq= sequencer_add_image_strip(C, ed->seqbasep, &seq_load);
484         strip= seq->strip;
485         se= strip->stripdata;
486
487         RNA_BEGIN(op->ptr, itemptr, "files") {
488                 char *filename= RNA_string_get_alloc(&itemptr, "name", NULL, 0);
489                 BLI_strncpy(se->name, filename, sizeof(se->name));
490                 MEM_freeN(filename);
491                 se++;
492         }
493         RNA_END;
494
495         if(seq_load.len == 1) {
496                 if(seq_load.start_frame < seq_load.end_frame) {
497                         seq->endstill= seq_load.end_frame - seq_load.start_frame;
498                 }
499         }
500         
501         calc_sequence_disp(scene, seq);
502
503         sort_seq(scene);
504
505         /* last active name */
506         strncpy(ed->act_imagedir, strip->dir, FILE_MAXDIR-1);
507         
508         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
509
510         return OPERATOR_FINISHED;
511 }
512
513 static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
514 {
515
516         if(!ED_operator_sequencer_active(C)) {
517                 BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
518                 return OPERATOR_CANCELLED;
519         }
520
521
522         /* drag drop has set the names */
523         if(RNA_collection_length(op->ptr, "files")) {
524                 sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_ENDFRAME|SEQPROP_NOPATHS);
525                 return sequencer_add_image_strip_exec(C, op);
526         }
527         
528         sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_ENDFRAME);
529         
530         if(!RNA_property_is_set(op->ptr, "relative_path"))
531                 RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS);
532
533         WM_event_add_fileselect(C, op);
534         return OPERATOR_RUNNING_MODAL;
535 }
536
537
538 void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
539 {
540         
541         /* identifiers */
542         ot->name= "Add Image Strip";
543         ot->idname= "SEQUENCER_OT_image_strip_add";
544         ot->description= "Add an image or image sequence to the sequencer";
545
546         /* api callbacks */
547         ot->invoke= sequencer_add_image_strip_invoke;
548         ot->exec= sequencer_add_image_strip_exec;
549
550         ot->poll= ED_operator_scene_editable;
551         
552         /* flags */
553         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
554         
555         WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_DIRECTORY|WM_FILESEL_RELPATH);
556         sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME|SEQPROP_ENDFRAME|SEQPROP_FILES);
557 }
558
559
560 /* add_effect_strip operator */
561 static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
562 {
563         Scene *scene= CTX_data_scene(C);
564         Editing *ed= seq_give_editing(scene, TRUE);
565
566         Sequence *seq;  /* generic strip vars */
567         Strip *strip;
568         struct SeqEffectHandle sh;
569
570         int start_frame, end_frame, channel, type; /* operator props */
571         
572         Sequence *seq1, *seq2, *seq3;
573         const char *error_msg;
574
575         start_frame= RNA_int_get(op->ptr, "frame_start");
576         end_frame= RNA_int_get(op->ptr, "frame_end");
577         channel= RNA_int_get(op->ptr, "channel");
578
579         type= RNA_enum_get(op->ptr, "type");
580         
581         // XXX move to invoke
582         if(!seq_effect_find_selected(scene, NULL, type, &seq1, &seq2, &seq3, &error_msg)) {
583                 BKE_report(op->reports, RPT_ERROR, error_msg);
584                 return OPERATOR_CANCELLED;
585         }
586
587         /* If seq1 is NULL and no error was rasied it means the seq is standalone
588          * (like color strips) and we need to check its start and end frames are valid */
589         if (seq1==NULL && end_frame <= start_frame) {
590                 BKE_report(op->reports, RPT_ERROR, "Start and end frame are not set");
591                 return OPERATOR_CANCELLED;
592         }
593
594         seq = alloc_sequence(ed->seqbasep, start_frame, channel);
595         seq->type= type;
596
597         BLI_strncpy(seq->name+2, give_seqname(seq), sizeof(seq->name)-2);
598         seqbase_unique_name_recursive(&ed->seqbase, seq);
599
600         sh = get_sequence_effect(seq);
601
602         seq->seq1= seq1;
603         seq->seq2= seq2;
604         seq->seq3= seq3;
605
606         sh.init(seq);
607
608         if (!seq1) { /* effect has no deps */
609                 seq->len= 1;
610                 seq_tx_set_final_right(seq, end_frame);
611         }
612
613         seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
614
615         calc_sequence(scene, seq);
616         
617         /* basic defaults */
618         seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
619         strip->len = seq->len;
620         strip->us= 1;
621         if(seq->len>0)
622                 strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
623
624         if (seq->type==SEQ_PLUGIN) {
625                 char path[FILE_MAX];
626                 RNA_string_get(op->ptr, "filepath", path);
627
628                 sh.init_plugin(seq, path);
629
630                 if(seq->plugin==NULL) {
631                         BLI_remlink(ed->seqbasep, seq);
632                         seq_free_sequence(scene, seq);
633                         BKE_reportf(op->reports, RPT_ERROR, "Sequencer plugin \"%s\" could not load.", path);
634                         return OPERATOR_CANCELLED;
635                 }
636         }
637         else if (seq->type==SEQ_COLOR) {
638                 SolidColorVars *colvars= (SolidColorVars *)seq->effectdata;
639                 RNA_float_get_array(op->ptr, "color", colvars->col);
640                 seq->blend_mode= SEQ_CROSS; /* so alpha adjustment fade to the strip below */
641
642         }
643
644         // XXX, this conflicts with giving a channel with invoke, perhaps we should have an active channel
645         // but for now this is much more usable
646         if(seq->seq1 || seq->seq2 || seq->seq3) {
647                 int chan= MAX3( seq->seq1 ? seq->seq1->machine : 0,
648                                                 seq->seq2 ? seq->seq2->machine : 0,
649                                                 seq->seq3 ? seq->seq3->machine : 0);
650                 if(chan < MAXSEQ)
651                         seq->machine= chan;
652         }
653
654         if(seq_test_overlap(ed->seqbasep, seq)) shuffle_seq(ed->seqbasep, seq, scene);
655
656         update_changed_seq_and_deps(scene, seq, 1, 1); /* runs calc_sequence */
657
658
659         /* not sure if this is needed with update_changed_seq_and_deps.
660          * it was NOT called in blender 2.4x, but wont hurt */
661         sort_seq(scene); 
662
663         if (RNA_boolean_get(op->ptr, "replace_sel")) {
664                 deselect_all_seq(scene);
665                 seq_active_set(scene, seq);
666                 seq->flag |= SELECT;
667         }
668
669         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
670
671         return OPERATOR_FINISHED;
672 }
673
674
675 /* add color */
676 static int sequencer_add_effect_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
677 {
678         if(!ED_operator_sequencer_active(C)) {
679                 BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
680                 return OPERATOR_CANCELLED;
681         }
682
683         sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_ENDFRAME);
684
685         if (RNA_property_is_set(op->ptr, "type") && RNA_enum_get(op->ptr, "type")==SEQ_PLUGIN) {
686
687                 if(!RNA_property_is_set(op->ptr, "relative_path"))
688                         RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS);
689
690                 /* only plugins need the file selector */
691                 return WM_operator_filesel(C, op, event);
692         }
693         else {
694                 return sequencer_add_effect_strip_exec(C, op);
695         }
696 }
697
698 void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot)
699 {
700         /* identifiers */
701         ot->name= "Add Effect Strip";
702         ot->idname= "SEQUENCER_OT_effect_strip_add";
703         ot->description= "Add an effect to the sequencer, most are applied on top of existing strips";
704
705         /* api callbacks */
706         ot->invoke= sequencer_add_effect_strip_invoke;
707         ot->exec= sequencer_add_effect_strip_exec;
708
709         ot->poll= ED_operator_scene_editable;
710         
711         /* flags */
712         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
713         
714         WM_operator_properties_filesel(ot, 0, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_FILEPATH|WM_FILESEL_RELPATH);
715         sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME|SEQPROP_ENDFRAME);
716         RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_CROSS, "Type", "Sequencer effect type");
717         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);
718 }