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