Blender V2.61 - r43446

sequencer_add.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): Blender Foundation, 2003-2009, Campbell Barton
00022  *
00023  * ***** END GPL LICENSE BLOCK *****
00024  */
00025 
00031 #include <stdlib.h>
00032 #include <math.h>
00033 #include <string.h>
00034 
00035 #ifndef WIN32
00036 #include <unistd.h>
00037 #else
00038 #include <io.h>
00039 #endif
00040 #include <sys/types.h>
00041 
00042 #include "MEM_guardedalloc.h"
00043 
00044 #include "BLI_blenlib.h"
00045 #include "BLI_math.h"
00046 #include "BLI_utildefines.h"
00047 
00048 #include "DNA_scene_types.h"
00049 #include "DNA_userdef_types.h"
00050 
00051 #include "BKE_context.h"
00052 #include "BKE_global.h"
00053 #include "BKE_main.h"
00054 #include "BKE_sequencer.h"
00055 #include "BKE_report.h"
00056 
00057 
00058 #include "WM_api.h"
00059 #include "WM_types.h"
00060 
00061 #include "RNA_define.h"
00062 #include "RNA_enum_types.h"
00063 
00064 /* for menu/popup icons etc etc*/
00065 
00066 #include "ED_screen.h"
00067 
00068 #include "UI_view2d.h"
00069 
00070 #include "BKE_sound.h"
00071 
00072 #ifdef WITH_AUDASPACE
00073 #  include "AUD_C-API.h"
00074 #endif
00075 
00076 /* own include */
00077 #include "sequencer_intern.h"
00078 
00079 /* Generic functions, reused by add strip operators */
00080 
00081 /* avoid passing multiple args and be more verbose */
00082 #define SEQPROP_STARTFRAME  (1<<0)
00083 #define SEQPROP_ENDFRAME    (1<<1)
00084 #define SEQPROP_NOPATHS     (1<<2)
00085 #define SEQPROP_NOCHAN      (1<<3)
00086 
00087 #define SELECT 1
00088 
00089 static void sequencer_generic_props__internal(wmOperatorType *ot, int flag)
00090 {
00091     if(flag & SEQPROP_STARTFRAME)
00092         RNA_def_int(ot->srna, "frame_start", 0, INT_MIN, INT_MAX, "Start Frame", "Start frame of the sequence strip", INT_MIN, INT_MAX);
00093     
00094     if(flag & SEQPROP_ENDFRAME)
00095         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 */
00096     
00097     RNA_def_int(ot->srna, "channel", 1, 1, MAXSEQ, "Channel", "Channel to place this strip into", 1, MAXSEQ);
00098     
00099     RNA_def_boolean(ot->srna, "replace_sel", 1, "Replace Selection", "replace the current selection");
00100 
00101     RNA_def_boolean(ot->srna, "overlap", 0, "Allow Overlap", "Don't correct overlap on new sequence strips");
00102 }
00103 
00104 static void sequencer_generic_invoke_path__internal(bContext *C, wmOperator *op, const char *identifier)
00105 {
00106     if(RNA_struct_find_property(op->ptr, identifier)) {
00107         Scene *scene= CTX_data_scene(C);
00108         Sequence *last_seq= seq_active_get(scene);
00109         if(last_seq && last_seq->strip && SEQ_HAS_PATH(last_seq)) {
00110             char path[sizeof(last_seq->strip->dir)];
00111             BLI_strncpy(path, last_seq->strip->dir, sizeof(path));
00112             BLI_path_abs(path, G.main->name);
00113             RNA_string_set(op->ptr, identifier, path);
00114         }
00115     }
00116 }
00117 
00118 static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, wmEvent *event, int flag)
00119 {
00120     View2D *v2d= UI_view2d_fromcontext(C);
00121     
00122     float mval_v2d[2];
00123     
00124     UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mval_v2d[0], &mval_v2d[1]);
00125 
00126     /* effect strips dont need a channel initialized from the mouse */
00127     if(!(flag & SEQPROP_NOCHAN)) {
00128         RNA_int_set(op->ptr, "channel", (int)mval_v2d[1]+0.5f);
00129     }
00130 
00131     RNA_int_set(op->ptr, "frame_start", (int)mval_v2d[0]);
00132     
00133     if ((flag & SEQPROP_ENDFRAME) && RNA_struct_property_is_set(op->ptr, "frame_end")==0)
00134         RNA_int_set(op->ptr, "frame_end", (int)mval_v2d[0] + 25); // XXX arbitary but ok for now.
00135 
00136     if (!(flag & SEQPROP_NOPATHS)) {
00137         sequencer_generic_invoke_path__internal(C, op, "filepath");
00138         sequencer_generic_invoke_path__internal(C, op, "directory");
00139     }
00140 }
00141 
00142 static void seq_load_operator_info(SeqLoadInfo *seq_load, wmOperator *op)
00143 {
00144     int relative= RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path");
00145     int is_file= -1;
00146     memset(seq_load, 0, sizeof(SeqLoadInfo));
00147 
00148     seq_load->start_frame=  RNA_int_get(op->ptr, "frame_start");
00149     seq_load->end_frame=    seq_load->start_frame; /* un-set */
00150 
00151     seq_load->channel=      RNA_int_get(op->ptr, "channel");
00152     seq_load->len=          1; // images only, if endframe isnt set!
00153 
00154     if(RNA_struct_find_property(op->ptr, "filepath")) {
00155         RNA_string_get(op->ptr, "filepath", seq_load->path); /* full path, file is set by the caller */
00156         is_file= 1;
00157     } else if (RNA_struct_find_property(op->ptr, "directory")) {
00158         RNA_string_get(op->ptr, "directory", seq_load->path); /* full path, file is set by the caller */
00159         is_file= 0;
00160     }
00161 
00162     if((is_file != -1) && relative)
00163         BLI_path_rel(seq_load->path, G.main->name);
00164 
00165     
00166     if (RNA_struct_find_property(op->ptr, "frame_end")) {
00167         seq_load->end_frame = RNA_int_get(op->ptr, "frame_end");
00168     }
00169 
00170     if (RNA_struct_find_property(op->ptr, "replace_sel") && RNA_boolean_get(op->ptr, "replace_sel"))
00171         seq_load->flag |= SEQ_LOAD_REPLACE_SEL;
00172 
00173     if (RNA_struct_find_property(op->ptr, "cache") && RNA_boolean_get(op->ptr, "cache"))
00174         seq_load->flag |= SEQ_LOAD_SOUND_CACHE;
00175 
00176     if (RNA_struct_find_property(op->ptr, "sound") && RNA_boolean_get(op->ptr, "sound"))
00177         seq_load->flag |= SEQ_LOAD_MOVIE_SOUND;
00178 
00179     /* always use this for ops */
00180     seq_load->flag |= SEQ_LOAD_FRAME_ADVANCE;
00181 
00182 
00183     if(is_file==1) {
00184         BLI_strncpy(seq_load->name, BLI_path_basename(seq_load->path), sizeof(seq_load->name));
00185     }
00186     else if(RNA_struct_find_property(op->ptr, "files")) {
00187         /* used for image strip */
00188         /* best guess, first images name */
00189         RNA_BEGIN(op->ptr, itemptr, "files") {
00190             char *name= RNA_string_get_alloc(&itemptr, "name", NULL, 0);
00191             BLI_strncpy(seq_load->name, name, sizeof(seq_load->name));
00192             MEM_freeN(name);
00193             break;
00194         }
00195         RNA_END;
00196     }
00197 }
00198 
00199 /* add scene operator */
00200 static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
00201 {
00202     Scene *scene= CTX_data_scene(C);
00203     Editing *ed= seq_give_editing(scene, TRUE);
00204     
00205     Scene *sce_seq;
00206 
00207     Sequence *seq;  /* generic strip vars */
00208     Strip *strip;
00209     
00210     int start_frame, channel; /* operator props */
00211     
00212     start_frame= RNA_int_get(op->ptr, "frame_start");
00213     channel= RNA_int_get(op->ptr, "channel");
00214     
00215     sce_seq= BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene"));
00216     
00217     if (sce_seq==NULL) {
00218         BKE_report(op->reports, RPT_ERROR, "Scene not found");
00219         return OPERATOR_CANCELLED;
00220     }
00221     
00222     seq = alloc_sequence(ed->seqbasep, start_frame, channel);
00223     seq->type= SEQ_SCENE;
00224     seq->blend_mode= SEQ_CROSS; /* so alpha adjustment fade to the strip below */
00225 
00226     seq->scene= sce_seq;
00227     seq->sfra= sce_seq->r.sfra;
00228     
00229     /* basic defaults */
00230     seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
00231     strip->len = seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1;
00232     strip->us= 1;
00233     
00234     strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
00235     
00236     BLI_strncpy(seq->name+2, sce_seq->id.name+2, sizeof(seq->name)-2);
00237     seqbase_unique_name_recursive(&ed->seqbase, seq);
00238 
00239     seq->scene_sound = sound_scene_add_scene_sound(scene, seq, start_frame, start_frame + strip->len, 0);
00240 
00241     calc_sequence_disp(scene, seq);
00242     sort_seq(scene);
00243     
00244     if (RNA_boolean_get(op->ptr, "replace_sel")) {
00245         deselect_all_seq(scene);
00246         seq_active_set(scene, seq);
00247         seq->flag |= SELECT;
00248     }
00249 
00250     if(RNA_boolean_get(op->ptr, "overlap") == FALSE) {
00251         if(seq_test_overlap(ed->seqbasep, seq)) shuffle_seq(ed->seqbasep, seq, scene);
00252     }
00253 
00254     WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
00255     
00256     return OPERATOR_FINISHED;
00257 }
00258 
00259 
00260 static int sequencer_add_scene_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
00261 {
00262     if(!ED_operator_sequencer_active(C)) {
00263         BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
00264         return OPERATOR_CANCELLED;
00265     }
00266 
00267     if(!RNA_struct_property_is_set(op->ptr, "scene"))
00268         return WM_enum_search_invoke(C, op, event);
00269 
00270     sequencer_generic_invoke_xy__internal(C, op, event, 0);
00271     return sequencer_add_scene_strip_exec(C, op);
00272     // needs a menu
00273     // return WM_menu_invoke(C, op, event);
00274 }
00275 
00276 
00277 void SEQUENCER_OT_scene_strip_add(struct wmOperatorType *ot)
00278 {
00279     PropertyRNA *prop;
00280     
00281     /* identifiers */
00282     ot->name= "Add Scene Strip";
00283     ot->idname= "SEQUENCER_OT_scene_strip_add";
00284     ot->description= "Add a strip to the sequencer using a blender scene as a source";
00285 
00286     /* api callbacks */
00287     ot->invoke= sequencer_add_scene_strip_invoke;
00288     ot->exec= sequencer_add_scene_strip_exec;
00289 
00290     ot->poll= ED_operator_scene_editable;
00291     
00292     /* flags */
00293     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00294     
00295     sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
00296     prop= RNA_def_enum(ot->srna, "scene", DummyRNA_NULL_items, 0, "Scene", "");
00297     RNA_def_enum_funcs(prop, RNA_scene_itemf);
00298     ot->prop= prop;
00299 }
00300 
00301 static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoadFunc seq_load_func)
00302 {
00303     Scene *scene= CTX_data_scene(C); /* only for sound */
00304     Editing *ed= seq_give_editing(scene, TRUE);
00305     SeqLoadInfo seq_load;
00306     Sequence *seq;
00307     int tot_files;
00308     const short overlap= RNA_boolean_get(op->ptr, "overlap");
00309 
00310     seq_load_operator_info(&seq_load, op);
00311 
00312     if (seq_load.flag & SEQ_LOAD_REPLACE_SEL)
00313         deselect_all_seq(scene);
00314 
00315     tot_files= RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
00316 
00317     if(tot_files) {
00318         /* multiple files */
00319         char dir_only[FILE_MAX];
00320         char file_only[FILE_MAX];
00321 
00322         BLI_split_dir_part(seq_load.path, dir_only, sizeof(dir_only));
00323 
00324         RNA_BEGIN(op->ptr, itemptr, "files") {
00325             RNA_string_get(&itemptr, "name", file_only);
00326             BLI_join_dirfile(seq_load.path, sizeof(seq_load.path), dir_only, file_only);
00327 
00328             seq= seq_load_func(C, ed->seqbasep, &seq_load);
00329 
00330             if(overlap == FALSE) {
00331                 if(seq_test_overlap(ed->seqbasep, seq)) shuffle_seq(ed->seqbasep, seq, scene);
00332             }
00333         }
00334         RNA_END;
00335     }
00336     else {
00337         /* single file */
00338         seq= seq_load_func(C, ed->seqbasep, &seq_load);
00339 
00340         if(overlap == FALSE) {
00341             if(seq_test_overlap(ed->seqbasep, seq)) shuffle_seq(ed->seqbasep, seq, scene);
00342         }
00343     }
00344 
00345     if (seq_load.tot_success==0) {
00346         BKE_reportf(op->reports, RPT_ERROR, "File \"%s\" could not be loaded", seq_load.path);
00347         return OPERATOR_CANCELLED;
00348     }
00349 
00350     sort_seq(scene);
00351     seq_update_muting(ed);
00352 
00353     WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
00354 
00355     return OPERATOR_FINISHED;
00356 }
00357 
00358 /* add movie operator */
00359 static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
00360 {
00361     return sequencer_add_generic_strip_exec(C, op, sequencer_add_movie_strip);
00362 }
00363 
00364 
00365 static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
00366 {
00367 
00368     if(!ED_operator_sequencer_active(C)) {
00369         BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
00370         return OPERATOR_CANCELLED;
00371     }
00372 
00373     /* This is for drag and drop */
00374     if(RNA_collection_length(op->ptr, "files") || RNA_struct_property_is_set(op->ptr, "filepath")) {
00375         sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_NOPATHS);
00376         return sequencer_add_movie_strip_exec(C, op);
00377     }
00378     
00379     sequencer_generic_invoke_xy__internal(C, op, event, 0);
00380     
00381     WM_event_add_fileselect(C, op);
00382     return OPERATOR_RUNNING_MODAL;
00383 
00384     //return sequencer_add_movie_strip_exec(C, op);
00385 }
00386 
00387 
00388 void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
00389 {
00390     
00391     /* identifiers */
00392     ot->name= "Add Movie Strip";
00393     ot->idname= "SEQUENCER_OT_movie_strip_add";
00394     ot->description= "Add a movie strip to the sequencer";
00395 
00396     /* api callbacks */
00397     ot->invoke= sequencer_add_movie_strip_invoke;
00398     ot->exec= sequencer_add_movie_strip_exec;
00399 
00400     ot->poll= ED_operator_scene_editable;
00401     
00402     /* flags */
00403     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00404     
00405     WM_operator_properties_filesel(ot, FOLDERFILE|MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_FILEPATH|WM_FILESEL_RELPATH|WM_FILESEL_FILES);
00406     sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
00407     RNA_def_boolean(ot->srna, "sound", TRUE, "Sound", "Load sound with the movie");
00408 }
00409 
00410 /* add sound operator */
00411 
00412 static int sequencer_add_sound_strip_exec(bContext *C, wmOperator *op)
00413 {
00414     return sequencer_add_generic_strip_exec(C, op, sequencer_add_sound_strip);
00415 }
00416 
00417 static int sequencer_add_sound_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
00418 {
00419 
00420     if(!ED_operator_sequencer_active(C)) {
00421         BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
00422         return OPERATOR_CANCELLED;
00423     }
00424     
00425     /* This is for drag and drop */
00426     if(RNA_collection_length(op->ptr, "files") || RNA_struct_property_is_set(op->ptr, "filepath")) {
00427         sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_NOPATHS);
00428         return sequencer_add_sound_strip_exec(C, op);
00429     }
00430     
00431     sequencer_generic_invoke_xy__internal(C, op, event, 0);
00432 
00433     WM_event_add_fileselect(C, op);
00434     return OPERATOR_RUNNING_MODAL;
00435 
00436     //return sequencer_add_sound_strip_exec(C, op);
00437 }
00438 
00439 
00440 void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot)
00441 {
00442     
00443     /* identifiers */
00444     ot->name= "Add Sound Strip";
00445     ot->idname= "SEQUENCER_OT_sound_strip_add";
00446     ot->description= "Add a sound strip to the sequencer";
00447 
00448     /* api callbacks */
00449     ot->invoke= sequencer_add_sound_strip_invoke;
00450     ot->exec= sequencer_add_sound_strip_exec;
00451 
00452     ot->poll= ED_operator_scene_editable;
00453     
00454     /* flags */
00455     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00456     
00457     WM_operator_properties_filesel(ot, FOLDERFILE|SOUNDFILE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_FILEPATH|WM_FILESEL_RELPATH|WM_FILESEL_FILES);
00458     sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
00459     RNA_def_boolean(ot->srna, "cache", FALSE, "Cache", "Cache the sound in memory");
00460 }
00461 
00462 /* add image operator */
00463 static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
00464 {
00465     /* cant use the generic function for this */
00466 
00467     Scene *scene= CTX_data_scene(C); /* only for sound */
00468     Editing *ed= seq_give_editing(scene, TRUE);
00469     SeqLoadInfo seq_load;
00470     Sequence *seq;
00471 
00472     Strip *strip;
00473     StripElem *se;
00474 
00475     seq_load_operator_info(&seq_load, op);
00476 
00477     /* images are unique in how they handle this - 1 per strip elem */
00478     seq_load.len= RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
00479 
00480     if(seq_load.len==0)
00481         return OPERATOR_CANCELLED;
00482 
00483     if(seq_load.flag & SEQ_LOAD_REPLACE_SEL)
00484         deselect_all_seq(scene);
00485 
00486 
00487     /* main adding function */
00488     seq= sequencer_add_image_strip(C, ed->seqbasep, &seq_load);
00489     strip= seq->strip;
00490     se= strip->stripdata;
00491 
00492     RNA_BEGIN(op->ptr, itemptr, "files") {
00493         char *filename= RNA_string_get_alloc(&itemptr, "name", NULL, 0);
00494         BLI_strncpy(se->name, filename, sizeof(se->name));
00495         MEM_freeN(filename);
00496         se++;
00497     }
00498     RNA_END;
00499 
00500     if(seq_load.len == 1) {
00501         if(seq_load.start_frame < seq_load.end_frame) {
00502             seq->endstill= seq_load.end_frame - seq_load.start_frame;
00503         }
00504     }
00505     
00506     calc_sequence_disp(scene, seq);
00507 
00508     sort_seq(scene);
00509 
00510     /* last active name */
00511     strncpy(ed->act_imagedir, strip->dir, FILE_MAXDIR-1);
00512 
00513     if(RNA_boolean_get(op->ptr, "overlap") == FALSE) {
00514         if(seq_test_overlap(ed->seqbasep, seq)) shuffle_seq(ed->seqbasep, seq, scene);
00515     }
00516 
00517     WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
00518 
00519     return OPERATOR_FINISHED;
00520 }
00521 
00522 static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
00523 {
00524 
00525     if(!ED_operator_sequencer_active(C)) {
00526         BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
00527         return OPERATOR_CANCELLED;
00528     }
00529 
00530 
00531     /* drag drop has set the names */
00532     if(RNA_collection_length(op->ptr, "files")) {
00533         sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_ENDFRAME|SEQPROP_NOPATHS);
00534         return sequencer_add_image_strip_exec(C, op);
00535     }
00536     
00537     sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_ENDFRAME);
00538 
00539     WM_event_add_fileselect(C, op);
00540     return OPERATOR_RUNNING_MODAL;
00541 }
00542 
00543 
00544 void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
00545 {
00546     
00547     /* identifiers */
00548     ot->name= "Add Image Strip";
00549     ot->idname= "SEQUENCER_OT_image_strip_add";
00550     ot->description= "Add an image or image sequence to the sequencer";
00551 
00552     /* api callbacks */
00553     ot->invoke= sequencer_add_image_strip_invoke;
00554     ot->exec= sequencer_add_image_strip_exec;
00555 
00556     ot->poll= ED_operator_scene_editable;
00557     
00558     /* flags */
00559     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00560     
00561     WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_DIRECTORY|WM_FILESEL_RELPATH|WM_FILESEL_FILES);
00562     sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME|SEQPROP_ENDFRAME);
00563 }
00564 
00565 
00566 /* add_effect_strip operator */
00567 static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
00568 {
00569     Scene *scene= CTX_data_scene(C);
00570     Editing *ed= seq_give_editing(scene, TRUE);
00571 
00572     Sequence *seq;  /* generic strip vars */
00573     Strip *strip;
00574     struct SeqEffectHandle sh;
00575 
00576     int start_frame, end_frame, channel, type; /* operator props */
00577     
00578     Sequence *seq1, *seq2, *seq3;
00579     const char *error_msg;
00580 
00581     start_frame= RNA_int_get(op->ptr, "frame_start");
00582     end_frame= RNA_int_get(op->ptr, "frame_end");
00583     channel= RNA_int_get(op->ptr, "channel");
00584 
00585     type= RNA_enum_get(op->ptr, "type");
00586     
00587     // XXX move to invoke
00588     if(!seq_effect_find_selected(scene, NULL, type, &seq1, &seq2, &seq3, &error_msg)) {
00589         BKE_report(op->reports, RPT_ERROR, error_msg);
00590         return OPERATOR_CANCELLED;
00591     }
00592 
00593     /* If seq1 is NULL and no error was rasied it means the seq is standalone
00594      * (like color strips) and we need to check its start and end frames are valid */
00595     if (seq1==NULL && end_frame <= start_frame) {
00596         BKE_report(op->reports, RPT_ERROR, "Start and end frame are not set");
00597         return OPERATOR_CANCELLED;
00598     }
00599 
00600     seq = alloc_sequence(ed->seqbasep, start_frame, channel);
00601     seq->type= type;
00602 
00603     BLI_strncpy(seq->name+2, give_seqname(seq), sizeof(seq->name)-2);
00604     seqbase_unique_name_recursive(&ed->seqbase, seq);
00605 
00606     sh = get_sequence_effect(seq);
00607 
00608     seq->seq1= seq1;
00609     seq->seq2= seq2;
00610     seq->seq3= seq3;
00611 
00612     sh.init(seq);
00613 
00614     if (!seq1) { /* effect has no deps */
00615         seq->len= 1;
00616         seq_tx_set_final_right(seq, end_frame);
00617     }
00618 
00619     seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
00620 
00621     calc_sequence(scene, seq);
00622     
00623     /* basic defaults */
00624     seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
00625     strip->len = seq->len;
00626     strip->us= 1;
00627     if(seq->len>0)
00628         strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
00629 
00630     if (seq->type==SEQ_PLUGIN) {
00631         char path[FILE_MAX];
00632         RNA_string_get(op->ptr, "filepath", path);
00633 
00634         sh.init_plugin(seq, path);
00635 
00636         if(seq->plugin==NULL) {
00637             BLI_remlink(ed->seqbasep, seq);
00638             seq_free_sequence(scene, seq);
00639             BKE_reportf(op->reports, RPT_ERROR, "Sequencer plugin \"%s\" could not load", path);
00640             return OPERATOR_CANCELLED;
00641         }
00642     } else if (seq->type == SEQ_COLOR) {
00643         SolidColorVars *colvars= (SolidColorVars *)seq->effectdata;
00644         RNA_float_get_array(op->ptr, "color", colvars->col);
00645         seq->blend_mode= SEQ_CROSS; /* so alpha adjustment fade to the strip below */
00646 
00647     } else if (seq->type == SEQ_ADJUSTMENT) {
00648         seq->blend_mode= SEQ_CROSS;
00649     }
00650 
00651     /* an unset channel is a special case where we automatically go above
00652      * the other strips. */
00653     if(!RNA_struct_property_is_set(op->ptr, "channel")) {
00654         if(seq->seq1) {
00655             int chan= MAX3( seq->seq1 ? seq->seq1->machine : 0,
00656                             seq->seq2 ? seq->seq2->machine : 0,
00657                             seq->seq3 ? seq->seq3->machine : 0);
00658             if(chan < MAXSEQ)
00659                 seq->machine= chan;
00660         }
00661     }
00662 
00663     if(RNA_boolean_get(op->ptr, "overlap") == FALSE) {
00664         if(seq_test_overlap(ed->seqbasep, seq)) shuffle_seq(ed->seqbasep, seq, scene);
00665     }
00666 
00667     update_changed_seq_and_deps(scene, seq, 1, 1); /* runs calc_sequence */
00668 
00669 
00670     /* not sure if this is needed with update_changed_seq_and_deps.
00671      * it was NOT called in blender 2.4x, but wont hurt */
00672     sort_seq(scene); 
00673 
00674     if (RNA_boolean_get(op->ptr, "replace_sel")) {
00675         deselect_all_seq(scene);
00676         seq_active_set(scene, seq);
00677         seq->flag |= SELECT;
00678     }
00679 
00680     WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
00681 
00682     return OPERATOR_FINISHED;
00683 }
00684 
00685 
00686 /* add color */
00687 static int sequencer_add_effect_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
00688 {
00689     short is_type_set= RNA_struct_property_is_set(op->ptr, "type");
00690     int type= -1;
00691     int prop_flag= SEQPROP_ENDFRAME;
00692 
00693     if(!ED_operator_sequencer_active(C)) {
00694         BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
00695         return OPERATOR_CANCELLED;
00696     }
00697 
00698     if(is_type_set) {
00699         type= RNA_enum_get(op->ptr, "type");
00700 
00701         /* when invoking an effect strip which uses inputs,
00702          * skip initialzing the channel from the mouse.
00703          * Instead leave the property unset so exec() initializes it to be
00704          * above the strips its applied to. */
00705         if(get_sequence_effect_num_inputs(type) != 0) {
00706             prop_flag |= SEQPROP_NOCHAN;
00707         }
00708     }
00709 
00710     sequencer_generic_invoke_xy__internal(C, op, event, prop_flag);
00711 
00712     if (is_type_set && type==SEQ_PLUGIN) {
00713         /* only plugins need the file selector */
00714         return WM_operator_filesel(C, op, event);
00715     }
00716     else {
00717         return sequencer_add_effect_strip_exec(C, op);
00718     }
00719 }
00720 
00721 void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot)
00722 {
00723     /* identifiers */
00724     ot->name= "Add Effect Strip";
00725     ot->idname= "SEQUENCER_OT_effect_strip_add";
00726     ot->description= "Add an effect to the sequencer, most are applied on top of existing strips";
00727 
00728     /* api callbacks */
00729     ot->invoke= sequencer_add_effect_strip_invoke;
00730     ot->exec= sequencer_add_effect_strip_exec;
00731 
00732     ot->poll= ED_operator_scene_editable;
00733     
00734     /* flags */
00735     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00736     
00737     WM_operator_properties_filesel(ot, 0, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_FILEPATH|WM_FILESEL_RELPATH);
00738     sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME|SEQPROP_ENDFRAME);
00739     RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_CROSS, "Type", "Sequencer effect type");
00740     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);
00741 }