Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/space_sequencer')
-rw-r--r--source/blender/editors/space_sequencer/Makefile56
-rw-r--r--source/blender/editors/space_sequencer/SConscript10
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c652
-rw-r--r--source/blender/editors/space_sequencer/sequencer_buttons.c136
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c1093
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c2409
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h154
-rw-r--r--source/blender/editors/space_sequencer/sequencer_ops.c185
-rw-r--r--source/blender/editors/space_sequencer/sequencer_scopes.c701
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c819
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c301
11 files changed, 6516 insertions, 0 deletions
diff --git a/source/blender/editors/space_sequencer/Makefile b/source/blender/editors/space_sequencer/Makefile
new file mode 100644
index 00000000000..80699db4baa
--- /dev/null
+++ b/source/blender/editors/space_sequencer/Makefile
@@ -0,0 +1,56 @@
+#
+# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Makes module object directory and bounces make to subdirectories.
+
+LIBNAME = ed_sequencer
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+
+# not very neat....
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../python
+CPPFLAGS += -I../../blenfont
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+# own include
+
+CPPFLAGS += -I../include
diff --git a/source/blender/editors/space_sequencer/SConscript b/source/blender/editors/space_sequencer/SConscript
new file mode 100644
index 00000000000..ab51068a529
--- /dev/null
+++ b/source/blender/editors/space_sequencer/SConscript
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '../include ../../blenlib ../../blenkernel ../../blenfont ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' ../../makesrna'
+
+env.BlenderLib ( 'bf_editors_space_sequencer', sources, Split(incs), [], libtype=['core'], priority=[100] )
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
new file mode 100644
index 00000000000..f6cf6de4b00
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -0,0 +1,652 @@
+/**
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2003-2009, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+#include <sys/types.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_storage_types.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_ipo_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_view2d_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_sound_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_plugin_types.h"
+#include "BKE_sequence.h"
+#include "BKE_scene.h"
+#include "BKE_utildefines.h"
+#include "BKE_report.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+/* for menu/popup icons etc etc*/
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "ED_anim_api.h"
+#include "ED_space_api.h"
+#include "ED_types.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+#include "ED_fileselect.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+/* own include */
+#include "sequencer_intern.h"
+
+/* Generic functions, reused by add strip operators */
+
+/* avoid passing multiple args and be more verbose */
+#define SEQPROP_STARTFRAME 1<<0
+#define SEQPROP_ENDFRAME 1<<1
+#define SEQPROP_FILENAME 1<<2
+
+static void sequencer_generic_props__internal(wmOperatorType *ot, int flag)
+{
+ RNA_def_string(ot->srna, "name", "", MAX_ID_NAME-2, "Name", "Name of the new sequence strip");
+
+ if(flag & SEQPROP_STARTFRAME)
+ RNA_def_int(ot->srna, "start_frame", 0, INT_MIN, INT_MAX, "Start Frame", "Start frame of the sequence strip", INT_MIN, INT_MAX);
+
+ if(flag & SEQPROP_ENDFRAME)
+ RNA_def_int(ot->srna, "end_frame", 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 */
+
+ RNA_def_int(ot->srna, "channel", 1, 1, MAXSEQ, "Channel", "Channel to place this strip into", 1, MAXSEQ);
+
+ if(flag & SEQPROP_FILENAME)
+ RNA_def_string(ot->srna, "filename", "", FILE_MAX, "Scene Name", "full path to load the strip data from");
+
+ RNA_def_boolean(ot->srna, "replace_sel", 1, "Replace Selection", "replace the current selection");
+}
+
+static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, wmEvent *event, int flag)
+{
+ ARegion *ar= CTX_wm_region(C);
+ View2D *v2d= UI_view2d_fromcontext(C);
+
+ short mval[2];
+ float mval_v2d[2];
+
+
+ mval[0]= event->x - ar->winrct.xmin;
+ mval[1]= event->y - ar->winrct.ymin;
+
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &mval_v2d[0], &mval_v2d[1]);
+
+ RNA_int_set(op->ptr, "channel", (int)mval_v2d[1]+0.5f);
+ RNA_int_set(op->ptr, "start_frame", (int)mval_v2d[0]);
+
+ if ((flag & SEQPROP_ENDFRAME) && RNA_property_is_set(op->ptr, "end_frame")==0)
+ RNA_int_set(op->ptr, "end_frame", (int)mval_v2d[0] + 25); // XXX arbitary but ok for now.
+
+}
+
+/* add scene operator */
+static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, TRUE);
+
+ Scene *sce_seq;
+ char sce_name[MAX_ID_NAME-2];
+
+ Sequence *seq; /* generic strip vars */
+ Strip *strip;
+ StripElem *se;
+
+ int start_frame, channel; /* operator props */
+
+ start_frame= RNA_int_get(op->ptr, "start_frame");
+ channel= RNA_int_get(op->ptr, "channel");
+
+ RNA_string_get(op->ptr, "scene", sce_name);
+
+ sce_seq= (Scene *)find_id("SC", sce_name);
+
+ if (sce_seq==NULL) {
+ BKE_reportf(op->reports, RPT_ERROR, "Scene \"%s\" not found", sce_name);
+ return OPERATOR_CANCELLED;
+ }
+
+ seq = alloc_sequence(ed->seqbasep, start_frame, channel);
+
+ seq->type= SEQ_SCENE;
+ seq->scene= sce_seq;
+
+ /* basic defaults */
+ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+ strip->len = seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1;
+ strip->us= 1;
+
+ strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+
+
+ RNA_string_get(op->ptr, "name", seq->name);
+
+ calc_sequence_disp(seq);
+ sort_seq(scene);
+
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ deselect_all_seq(scene);
+ set_last_seq(scene, seq);
+ seq->flag |= SELECT;
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+
+static int sequencer_add_scene_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sequencer_generic_invoke_xy__internal(C, op, event, 0);
+
+ /* scene can be left default */
+ RNA_string_set(op->ptr, "scene", "Scene"); // XXX should popup a menu but ton says 2.5 will have some better feature for this
+
+ return sequencer_add_scene_strip_exec(C, op);
+}
+
+
+void SEQUENCER_OT_scene_strip_add(struct wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Add Scene Strip";
+ ot->idname= "SEQUENCER_OT_scene_strip_add";
+ ot->description= "Add a strip to the sequencer using a blender scene as a source";
+
+ /* api callbacks */
+ ot->invoke= sequencer_add_scene_strip_invoke;
+ ot->exec= sequencer_add_scene_strip_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
+ RNA_def_string(ot->srna, "scene", "", MAX_ID_NAME-2, "Scene Name", "Scene name to add as a strip");
+}
+
+/* add movie operator */
+static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, TRUE);
+
+ struct anim *an;
+ char filename[FILE_MAX];
+
+ Sequence *seq; /* generic strip vars */
+ Strip *strip;
+ StripElem *se;
+
+ int start_frame, channel; /* operator props */
+
+ start_frame= RNA_int_get(op->ptr, "start_frame");
+ channel= RNA_int_get(op->ptr, "channel");
+
+ RNA_string_get(op->ptr, "filename", filename);
+
+ an = openanim(filename, IB_rect);
+
+ if (an==NULL) {
+ BKE_reportf(op->reports, RPT_ERROR, "Filename \"%s\" could not be loaded as a movie", filename);
+ return OPERATOR_CANCELLED;
+ }
+
+ seq = alloc_sequence(ed->seqbasep, start_frame, channel);
+
+ seq->type= SEQ_MOVIE;
+ seq->anim= an;
+ seq->anim_preseek = IMB_anim_get_preseek(an);
+
+ /* basic defaults */
+ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+ strip->len = seq->len = IMB_anim_get_duration( an );
+ strip->us= 1;
+
+ strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+
+ BLI_split_dirfile_basic(filename, strip->dir, se->name);
+
+ RNA_string_get(op->ptr, "name", seq->name);
+
+ calc_sequence_disp(seq);
+ sort_seq(scene);
+
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ deselect_all_seq(scene);
+ set_last_seq(scene, seq);
+ seq->flag |= SELECT;
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+
+static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sequencer_generic_invoke_xy__internal(C, op, event, 0);
+ return WM_operator_filesel(C, op, event);
+ //return sequencer_add_movie_strip_exec(C, op);
+}
+
+
+void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Add Movie Strip";
+ ot->idname= "SEQUENCER_OT_movie_strip_add";
+ ot->description= "Add a movie strip to the sequencer";
+
+ /* api callbacks */
+ ot->invoke= sequencer_add_movie_strip_invoke;
+ ot->exec= sequencer_add_movie_strip_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME|SEQPROP_FILENAME);
+ RNA_def_boolean(ot->srna, "sound", FALSE, "Sound", "Load hd sound with the movie"); // XXX need to impliment this
+}
+
+
+/* add sound operator */
+static int sequencer_add_sound_strip_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, TRUE);
+
+ bSound *sound;
+
+ char filename[FILE_MAX];
+
+ Sequence *seq; /* generic strip vars */
+ Strip *strip;
+ StripElem *se;
+
+ int start_frame, channel; /* operator props */
+
+ start_frame= RNA_int_get(op->ptr, "start_frame");
+ channel= RNA_int_get(op->ptr, "channel");
+
+ RNA_string_get(op->ptr, "filename", filename);
+
+ /* XXX if(sfile->flag & FILE_STRINGCODE) {
+ BLI_makestringcode(G.sce, str);
+ }*/
+
+// XXX sound= sound_new_sound(filename);
+ sound= NULL;
+
+ if (sound==NULL || sound->sample->type == SAMPLE_INVALID) {
+ BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (sound==NULL || sound->sample->bits != 16) {
+ BKE_report(op->reports, RPT_ERROR, "Only 16 bit audio is supported");
+ return OPERATOR_CANCELLED;
+ }
+
+ sound->flags |= SOUND_FLAGS_SEQUENCE;
+// XXX audio_makestream(sound);
+
+ seq = alloc_sequence(ed->seqbasep, start_frame, channel);
+
+ seq->type= SEQ_RAM_SOUND;
+ seq->sound= sound;
+
+ /* basic defaults */
+ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+ strip->len = seq->len = (int) ( ((float)(sound->streamlen-1) / ( (float)scene->r.audio.mixrate*4.0 ))* FPS);
+ strip->us= 1;
+
+ strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+
+ BLI_split_dirfile_basic(filename, strip->dir, se->name);
+
+ RNA_string_get(op->ptr, "name", seq->name);
+
+ calc_sequence_disp(seq);
+ sort_seq(scene);
+
+ /* last active name */
+ strncpy(ed->act_sounddir, strip->dir, FILE_MAXDIR-1);
+
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ deselect_all_seq(scene);
+ set_last_seq(scene, seq);
+ seq->flag |= SELECT;
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+
+static int sequencer_add_sound_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sequencer_generic_invoke_xy__internal(C, op, event, 0);
+ return WM_operator_filesel(C, op, event);
+ //return sequencer_add_sound_strip_exec(C, op);
+}
+
+
+void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Add Sound Strip";
+ ot->idname= "SEQUENCER_OT_sound_strip_add";
+ ot->description= "Add a sound strip to the sequencer";
+
+ /* api callbacks */
+ ot->invoke= sequencer_add_sound_strip_invoke;
+ ot->exec= sequencer_add_sound_strip_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME|SEQPROP_FILENAME);
+ RNA_def_boolean(ot->srna, "hd", FALSE, "HD Sound", "Load the sound as streaming audio"); // XXX need to impliment this
+}
+
+/* add image operator */
+static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, TRUE);
+
+ int tot_images;
+
+ char filename[FILE_MAX];
+
+ Sequence *seq; /* generic strip vars */
+ Strip *strip;
+ StripElem *se;
+
+ int start_frame, channel; /* operator props */
+
+ start_frame= RNA_int_get(op->ptr, "start_frame");
+ channel= RNA_int_get(op->ptr, "channel");
+
+ RNA_string_get(op->ptr, "filename", filename);
+
+ seq = alloc_sequence(ed->seqbasep, start_frame, channel);
+ seq->type= SEQ_IMAGE;
+
+ /* basic defaults */
+ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+ BLI_split_dirfile_basic(filename, strip->dir, NULL);
+
+ tot_images= RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
+
+ strip->len = seq->len = tot_images?tot_images:1;
+ strip->us= 1;
+
+ strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+
+ if(tot_images) {
+ RNA_BEGIN(op->ptr, itemptr, "files") {
+ RNA_string_get(&itemptr, "name", se->name);
+ se++;
+ }
+ RNA_END;
+ }
+ else {
+ BLI_split_dirfile_basic(filename, NULL, se->name);
+ }
+
+ RNA_string_get(op->ptr, "name", seq->name);
+
+ calc_sequence_disp(seq);
+ sort_seq(scene);
+
+ /* last active name */
+ strncpy(ed->act_imagedir, strip->dir, FILE_MAXDIR-1);
+
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ deselect_all_seq(scene);
+ set_last_seq(scene, seq);
+ seq->flag |= SELECT;
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+
+static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sequencer_generic_invoke_xy__internal(C, op, event, 0);
+ return WM_operator_filesel(C, op, event);
+ //return sequencer_add_image_strip_exec(C, op);
+}
+
+
+void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Add Image Strip";
+ ot->idname= "SEQUENCER_OT_image_strip_add";
+ ot->description= "Add an image or image sequence to the sequencer";
+
+ /* api callbacks */
+ ot->invoke= sequencer_add_image_strip_invoke;
+ ot->exec= sequencer_add_image_strip_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME|SEQPROP_FILENAME);
+
+ RNA_def_collection_runtime(ot->srna, "files", &RNA_OperatorFileListElement, "Files", "");
+}
+
+
+/* add_effect_strip operator */
+static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, TRUE);
+
+ Sequence *seq; /* generic strip vars */
+ Strip *strip;
+ StripElem *se;
+ struct SeqEffectHandle sh;
+
+ int start_frame, end_frame, channel, type; /* operator props */
+
+ Sequence *seq1, *seq2, *seq3;
+ char *error_msg;
+
+ start_frame= RNA_int_get(op->ptr, "start_frame");
+ end_frame= RNA_int_get(op->ptr, "end_frame");
+ channel= RNA_int_get(op->ptr, "channel");
+
+ type= RNA_enum_get(op->ptr, "type");
+
+ // XXX We need unique names and move to invoke
+ if(!seq_effect_find_selected(scene, NULL, type, &seq1, &seq2, &seq3, &error_msg)) {
+ BKE_report(op->reports, RPT_ERROR, error_msg);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* If seq1 is NULL and no error was rasied it means the seq is standalone
+ * (like color strips) and we need to check its start and end frames are valid */
+ if (seq1==NULL && end_frame <= start_frame) {
+ BKE_report(op->reports, RPT_ERROR, "Start and end frame are not set");
+ return OPERATOR_CANCELLED;
+ }
+
+ seq = alloc_sequence(ed->seqbasep, start_frame, channel);
+ seq->type= type;
+
+ sh = get_sequence_effect(seq);
+
+ seq->seq1= seq1;
+ seq->seq2= seq2;
+ seq->seq3= seq3;
+
+ sh.init(seq);
+
+ if (!seq1) { /* effect has no deps */
+ seq->len= 1;
+ seq_tx_set_final_right(seq, end_frame);
+ }
+
+ calc_sequence(seq);
+
+ /* basic defaults */
+ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
+ strip->len = seq->len;
+ strip->us= 1;
+ if(seq->len>0)
+ strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+
+ if (seq->type==SEQ_PLUGIN) {
+ char filename[FILE_MAX];
+ RNA_string_get(op->ptr, "filename", filename);
+
+ sh.init_plugin(seq, filename);
+
+ if(seq->plugin==NULL) {
+ BLI_remlink(ed->seqbasep, seq);
+ seq_free_sequence(ed, seq);
+ BKE_reportf(op->reports, RPT_ERROR, "Sequencer plugin \"%s\" could not load.", filename);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else if (seq->type==SEQ_COLOR) {
+ SolidColorVars *colvars= (SolidColorVars *)seq->effectdata;
+ RNA_float_get_array(op->ptr, "color", colvars->col);
+ }
+
+ if(seq_test_overlap(ed->seqbasep, seq)) shuffle_seq(ed->seqbasep, seq);
+
+ update_changed_seq_and_deps(scene, seq, 1, 1); /* runs calc_sequence */
+
+
+ /* not sure if this is needed with update_changed_seq_and_deps.
+ * it was NOT called in blender 2.4x, but wont hurt */
+ sort_seq(scene);
+
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ deselect_all_seq(scene);
+ set_last_seq(scene, seq);
+ seq->flag |= SELECT;
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ return OPERATOR_FINISHED;
+}
+
+
+/* add color */
+static int sequencer_add_effect_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_ENDFRAME);
+
+ if (RNA_property_is_set(op->ptr, "type") && RNA_enum_get(op->ptr, "type")==SEQ_PLUGIN) {
+ /* only plugins need the file selector */
+ return WM_operator_filesel(C, op, event);
+ }
+ else {
+ return sequencer_add_effect_strip_exec(C, op);
+ }
+}
+
+void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Effect Strip";
+ ot->idname= "SEQUENCER_OT_effect_strip_add";
+ ot->description= "Add an effect to the sequencer, most are applied ontop of existing strips";
+
+ /* api callbacks */
+ ot->invoke= sequencer_add_effect_strip_invoke;
+ ot->exec= sequencer_add_effect_strip_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME|SEQPROP_ENDFRAME|SEQPROP_FILENAME);
+ RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_CROSS, "Type", "Sequencer effect type");
+ 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);
+}
diff --git a/source/blender/editors/space_sequencer/sequencer_buttons.c b/source/blender/editors/space_sequencer/sequencer_buttons.c
new file mode 100644
index 00000000000..f127ab4b0cf
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_buttons.c
@@ -0,0 +1,136 @@
+/**
+ * $Id: sequencer_buttons.c 20279 2009-05-19 17:13:33Z blendix $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 by Blender Foundation
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "ED_screen.h"
+#include "ED_sequencer.h"
+#include "ED_util.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "sequencer_intern.h"
+
+
+static void do_sequencer_panel_events(bContext *C, void *arg, int event)
+{
+
+}
+
+
+static void sequencer_panel_view_properties(const bContext *C, Panel *pa)
+{
+ uiBlock *block;
+
+ block= uiLayoutFreeBlock(pa->layout);
+ uiBlockSetHandleFunc(block, do_sequencer_panel_events, NULL);
+
+}
+
+
+static void sequencer_panel_properties(const bContext *C, Panel *pa)
+{
+ uiBlock *block;
+
+ block= uiLayoutFreeBlock(pa->layout);
+ uiBlockSetHandleFunc(block, do_sequencer_panel_events, NULL);
+
+}
+
+void sequencer_buttons_register(ARegionType *art)
+{
+ PanelType *pt;
+
+ pt= MEM_callocN(sizeof(PanelType), "spacetype sequencer strip properties");
+ strcpy(pt->idname, "SEQUENCER_PT_properties");
+ strcpy(pt->label, "Strip Properties");
+ pt->draw= sequencer_panel_properties;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt= MEM_callocN(sizeof(PanelType), "spacetype sequencer view properties");
+ strcpy(pt->idname, "SEQUENCER_PT_view_properties");
+ strcpy(pt->label, "View Properties");
+ pt->draw= sequencer_panel_view_properties;
+ BLI_addtail(&art->paneltypes, pt);
+
+}
+
+/* **************** operator to open/close properties view ************* */
+
+static int sequencer_properties(bContext *C, wmOperator *op)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= sequencer_has_buttons_region(sa);
+
+ if(ar) {
+ ar->flag ^= RGN_FLAG_HIDDEN;
+ ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */
+
+ ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
+ ED_area_tag_redraw(sa);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_properties(wmOperatorType *ot)
+{
+ ot->name= "Properties";
+ ot->idname= "SEQUENCER_OT_properties";
+
+ ot->exec= sequencer_properties;
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= 0;
+}
+
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
new file mode 100644
index 00000000000..bd31d8d86ff
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -0,0 +1,1093 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2003-2009
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view2d_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_plugin_types.h"
+#include "BKE_sequence.h"
+#include "BKE_scene.h"
+#include "BKE_utildefines.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "ED_anim_api.h"
+#include "ED_space_api.h"
+#include "ED_sequencer.h"
+#include "ED_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+/* own include */
+#include "sequencer_intern.h"
+
+#define SEQ_LEFTHANDLE 1
+#define SEQ_RIGHTHANDLE 2
+
+
+/* Note, Dont use WHILE_SEQ while drawing! - it messes up transform, - Campbell */
+
+int no_rightbox=0, no_leftbox= 0;
+static void draw_shadedstrip(Sequence *seq, char *col, float x1, float y1, float x2, float y2);
+
+
+static void draw_cfra_seq(View2D *v2d, int cfra)
+{
+ glColor3ub(0x30, 0x90, 0x50);
+ glLineWidth(2.0);
+ glBegin(GL_LINES);
+ glVertex2f(cfra, v2d->cur.ymin);
+ glVertex2f(cfra, v2d->cur.ymax);
+ glEnd();
+ glLineWidth(1.0);
+}
+
+static void get_seq_color3ubv(Scene *curscene, Sequence *seq, char *col)
+{
+ char blendcol[3];
+ float hsv[3], rgb[3];
+ SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
+
+ switch(seq->type) {
+ case SEQ_IMAGE:
+ UI_GetThemeColor3ubv(TH_SEQ_IMAGE, col);
+ break;
+ case SEQ_META:
+ UI_GetThemeColor3ubv(TH_SEQ_META, col);
+ break;
+ case SEQ_MOVIE:
+ UI_GetThemeColor3ubv(TH_SEQ_MOVIE, col);
+ break;
+ case SEQ_SCENE:
+ UI_GetThemeColor3ubv(TH_SEQ_SCENE, col);
+
+ if(seq->scene==curscene) {
+ UI_GetColorPtrBlendShade3ubv(col, col, col, 1.0, 20);
+ }
+ break;
+
+ /* transitions */
+ case SEQ_CROSS:
+ case SEQ_GAMCROSS:
+ case SEQ_WIPE:
+ /* slightly offset hue to distinguish different effects */
+ UI_GetThemeColor3ubv(TH_SEQ_TRANSITION, col);
+
+ rgb[0] = col[0]/255.0; rgb[1] = col[1]/255.0; rgb[2] = col[2]/255.0;
+ rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
+
+ if (seq->type == SEQ_CROSS) hsv[0]+= 0.04;
+ if (seq->type == SEQ_GAMCROSS) hsv[0]+= 0.08;
+ if (seq->type == SEQ_WIPE) hsv[0]+= 0.12;
+
+ if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
+ hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
+ col[0] = (char)(rgb[0]*255); col[1] = (char)(rgb[1]*255); col[2] = (char)(rgb[2]*255);
+ break;
+
+ /* effects */
+ case SEQ_TRANSFORM:
+ case SEQ_SPEED:
+ case SEQ_ADD:
+ case SEQ_SUB:
+ case SEQ_MUL:
+ case SEQ_ALPHAOVER:
+ case SEQ_ALPHAUNDER:
+ case SEQ_OVERDROP:
+ case SEQ_GLOW:
+ /* slightly offset hue to distinguish different effects */
+ UI_GetThemeColor3ubv(TH_SEQ_EFFECT, col);
+
+ rgb[0] = col[0]/255.0; rgb[1] = col[1]/255.0; rgb[2] = col[2]/255.0;
+ rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
+
+ if (seq->type == SEQ_ADD) hsv[0]+= 0.04;
+ if (seq->type == SEQ_SUB) hsv[0]+= 0.08;
+ if (seq->type == SEQ_MUL) hsv[0]+= 0.12;
+ if (seq->type == SEQ_ALPHAOVER) hsv[0]+= 0.16;
+ if (seq->type == SEQ_ALPHAUNDER) hsv[0]+= 0.20;
+ if (seq->type == SEQ_OVERDROP) hsv[0]+= 0.24;
+ if (seq->type == SEQ_GLOW) hsv[0]+= 0.28;
+ if (seq->type == SEQ_TRANSFORM) hsv[0]+= 0.36;
+
+ if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
+ hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
+ col[0] = (char)(rgb[0]*255); col[1] = (char)(rgb[1]*255); col[2] = (char)(rgb[2]*255);
+ break;
+ case SEQ_COLOR:
+ if (colvars->col) {
+ col[0]= (char)(colvars->col[0]*255);
+ col[1]= (char)(colvars->col[1]*255);
+ col[2]= (char)(colvars->col[2]*255);
+ } else {
+ col[0] = col[1] = col[2] = 128;
+ }
+ break;
+ case SEQ_PLUGIN:
+ UI_GetThemeColor3ubv(TH_SEQ_PLUGIN, col);
+ break;
+ case SEQ_HD_SOUND:
+ case SEQ_RAM_SOUND:
+ UI_GetThemeColor3ubv(TH_SEQ_AUDIO, col);
+ blendcol[0] = blendcol[1] = blendcol[2] = 128;
+ if(seq->flag & SEQ_MUTE) UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.5, 20);
+ break;
+ default:
+ col[0] = 10; col[1] = 255; col[2] = 40;
+ }
+}
+
+static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, float x2, float y2)
+{
+ /* Note, this used to use WHILE_SEQ, but it messes up the seq->depth value, (needed by transform when doing overlap checks)
+ * so for now, just use the meta's immediate children, could be fixed but its only drawing - Campbell */
+ Sequence *seq;
+ float dx;
+ int nr;
+ char col[3];
+
+ nr= BLI_countlist(&seqm->seqbase);
+
+ dx= (x2-x1)/nr;
+
+ if (seqm->flag & SEQ_MUTE) {
+ glEnable(GL_POLYGON_STIPPLE);
+ glPolygonStipple(stipple_halftone);
+
+ glEnable(GL_LINE_STIPPLE);
+ glLineStipple(1, 0x8888);
+ }
+
+ for (seq= seqm->seqbase.first; seq; seq= seq->next) {
+ get_seq_color3ubv(scene, seq, col);
+
+ glColor3ubv((GLubyte *)col);
+
+ glRectf(x1, y1, x1+0.9*dx, y2);
+
+ UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -30);
+ glColor3ubv((GLubyte *)col);
+
+ fdrawbox(x1, y1, x1+0.9*dx, y2);
+
+ x1+= dx;
+ }
+
+ if (seqm->flag & SEQ_MUTE) {
+ glDisable(GL_POLYGON_STIPPLE);
+ glDisable(GL_LINE_STIPPLE);
+ }
+}
+
+static void drawseqwave(Scene *scene, View2D *v2d, Sequence *seq, float x1, float y1, float x2, float y2, int winx)
+{
+ /*
+ x1 is the starting x value to draw the wave,
+ x2 the end x value, same for y1 and y2
+ winx is the zoom level.
+ */
+
+ float
+ f, /* floating point value used to store the X draw location for the wave lines when openGL drawing*/
+ midy, /* fast access to the middle location (y1+y2)/2 */
+ clipxmin, /* the minimum X value, clip this with the window */
+ clipxmax, /* the maximum X value, clip this with the window */
+ sample_step, /* steps to move per sample, floating value must later translate into an int */
+ fsofs, /* steps to move per sample, floating value must later translate into an int */
+ feofs_sofs, /* */
+ sound_width, /* convenience: x2-x1 */
+ wavemulti; /* scale the samples by this value when GL_LINE drawing so it renders the right height */
+
+ int
+ offset, /* initial offset value for the wave drawing */
+ offset_next, /* when in the wave drawing loop this value is the samples intil the next vert */
+ sofs, /* Constrained offset value (~3) for the wave, start */
+ eofs, /* ditto, end */
+ wavesample, /* inner loop storage if the current wave sample value, used to make the 2 values below */
+ wavesamplemin, /* used for finding the min and max wave peaks */
+ wavesamplemax, /* ditto */
+ subsample_step=4; /* when the sample step is 4 every sample of
+ the wave is evaluated for min and max values used to draw the wave,
+ however this is slow ehrn zoomed out so when the sample step is above
+ 1 (the larger the further out the zoom is) so not evaluate all samples, only some. */
+
+ signed short* s;
+ bSound *sound;
+ uint8_t *stream;
+
+// XXX audio_makestream(seq->sound);
+ if(seq->sound==NULL || seq->sound->stream==NULL) return;
+
+ if (seq->flag & SEQ_MUTE) glColor3ub(0x70, 0x80, 0x80); else glColor3ub(0x70, 0xc0, 0xc0);
+
+ sofs = ((int)( FRA2TIME(seq->startdisp-seq->start+seq->anim_startofs)*(float)scene->r.audio.mixrate*4.0 )) & (~3);
+ eofs = ((int)( FRA2TIME(seq->enddisp-seq->start+seq->anim_startofs)*(float)scene->r.audio.mixrate*4.0 )) & (~3);
+
+ /* clip the drawing area to the screen bounds to save time */
+ sample_step= (v2d->cur.xmax - v2d->cur.xmin)/winx;
+ clipxmin= MAX2(x1, v2d->cur.xmin);
+ clipxmax= MIN2(x2, v2d->cur.xmax);
+
+ if (sample_step > 1)
+ subsample_step= ((int)(subsample_step*sample_step*8)) & (~3);
+
+ /* for speedy access */
+ midy = (y1+y2)/2;
+ fsofs= (float)sofs;
+ feofs_sofs= (float)(eofs-sofs);
+ sound_width= x2-x1;
+ sound = seq->sound;
+ stream = sound->stream;
+ wavemulti = (y2-y1)/196605; /*y2-y1 is the height*/
+ wavesample=0;
+
+ /* we need to get the starting offset value, excuse the duplicate code */
+ f=clipxmin;
+ offset= (int) (fsofs + ((f-x1)/sound_width) * feofs_sofs) & (~3);
+
+ /* start the loop, draw a line per sample_step -sample_step is about 1 line drawn per pixel */
+ glBegin(GL_LINES);
+ for (f=x1+sample_step; f<=clipxmax; f+=sample_step) {
+
+ offset_next = (int) (fsofs + ((f-x1)/sound_width) * feofs_sofs) & (~3);
+ if (f > v2d->cur.xmin) {
+ /* if this is close to the last sample just exit */
+ if (offset_next >= sound->streamlen) break;
+
+ wavesamplemin = 131070;
+ wavesamplemax = -131070;
+
+ /*find with high and low of the waveform for this draw,
+ evaluate small samples to find this range */
+ while (offset < offset_next) {
+ s = (signed short*)(stream+offset);
+
+ wavesample = s[0]*2 + s[1];
+ if (wavesamplemin>wavesample)
+ wavesamplemin=wavesample;
+ if (wavesamplemax<wavesample)
+ wavesamplemax=wavesample;
+ offset+=subsample_step;
+ }
+ /* draw the wave line, looks good up close and zoomed out */
+ glVertex2f(f, midy-(wavemulti*wavesamplemin) );
+ glVertex2f(f, midy-(wavemulti*wavesamplemax) );
+ } else {
+ while (offset < offset_next) offset+=subsample_step;
+ }
+
+ offset=offset_next;
+ }
+ glEnd();
+}
+
+/* draw a handle, for each end of a sequence strip */
+static void draw_seq_handle(View2D *v2d, Sequence *seq, float pixelx, short direction)
+{
+ float v1[2], v2[2], v3[2], rx1=0, rx2=0; //for triangles and rect
+ float x1, x2, y1, y2;
+ float handsize;
+ float minhandle, maxhandle;
+ char str[32];
+ unsigned int whichsel=0;
+
+ x1= seq->startdisp;
+ x2= seq->enddisp;
+
+ y1= seq->machine+SEQ_STRIP_OFSBOTTOM;
+ y2= seq->machine+SEQ_STRIP_OFSTOP;
+
+ /* clamp handles to defined size in pixel space */
+ handsize = seq->handsize;
+ minhandle = 7;
+ maxhandle = 40;
+ CLAMP(handsize, minhandle*pixelx, maxhandle*pixelx);
+
+ /* set up co-ordinates/dimensions for either left or right handle */
+ if (direction == SEQ_LEFTHANDLE) {
+ rx1 = x1;
+ rx2 = x1+handsize*0.75;
+
+ v1[0]= x1+handsize/4; v1[1]= y1+( ((y1+y2)/2.0 - y1)/2);
+ v2[0]= x1+handsize/4; v2[1]= y2-( ((y1+y2)/2.0 - y1)/2);
+ v3[0]= v2[0] + handsize/4; v3[1]= (y1+y2)/2.0;
+
+ whichsel = SEQ_LEFTSEL;
+ } else if (direction == SEQ_RIGHTHANDLE) {
+ rx1 = x2-handsize*0.75;
+ rx2 = x2;
+
+ v1[0]= x2-handsize/4; v1[1]= y1+( ((y1+y2)/2.0 - y1)/2);
+ v2[0]= x2-handsize/4; v2[1]= y2-( ((y1+y2)/2.0 - y1)/2);
+ v3[0]= v2[0] - handsize/4; v3[1]= (y1+y2)/2.0;
+
+ whichsel = SEQ_RIGHTSEL;
+ }
+
+ /* draw! */
+ if(seq->type < SEQ_EFFECT ||
+ get_sequence_effect_num_inputs(seq->type) == 0) {
+ glEnable( GL_BLEND );
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ if(seq->flag & whichsel) glColor4ub(0, 0, 0, 80);
+ else if (seq->flag & SELECT) glColor4ub(255, 255, 255, 30);
+ else glColor4ub(0, 0, 0, 22);
+
+ glRectf(rx1, y1, rx2, y2);
+
+ if(seq->flag & whichsel) glColor4ub(255, 255, 255, 200);
+ else glColor4ub(0, 0, 0, 50);
+
+ glEnable( GL_POLYGON_SMOOTH );
+ glBegin(GL_TRIANGLES);
+ glVertex2fv(v1); glVertex2fv(v2); glVertex2fv(v3);
+ glEnd();
+
+ glDisable( GL_POLYGON_SMOOTH );
+ glDisable( GL_BLEND );
+ }
+
+ if(G.moving || (seq->flag & whichsel)) {
+ cpack(0xFFFFFF);
+ if (direction == SEQ_LEFTHANDLE) {
+ sprintf(str, "%d", seq->startdisp);
+ x1= rx1;
+ y1 -= 0.45;
+ } else {
+ sprintf(str, "%d", seq->enddisp - 1);
+ x1= x2 - handsize*0.75;
+ y1= y2 + 0.05;
+ }
+ UI_view2d_text_cache_add(v2d, x1, y1, str);
+ }
+}
+
+static void draw_seq_extensions(Scene *scene, SpaceSeq *sseq, Sequence *seq)
+{
+ float x1, x2, y1, y2, pixely, a;
+ char col[3], blendcol[3];
+ View2D *v2d;
+
+ if(seq->type >= SEQ_EFFECT) return;
+
+ x1= seq->startdisp;
+ x2= seq->enddisp;
+
+ y1= seq->machine+SEQ_STRIP_OFSBOTTOM;
+ y2= seq->machine+SEQ_STRIP_OFSTOP;
+
+ v2d = &sseq->v2d;
+ pixely = (v2d->cur.ymax - v2d->cur.ymin)/(v2d->mask.ymax - v2d->mask.ymin);
+
+ blendcol[0] = blendcol[1] = blendcol[2] = 120;
+
+ if(seq->startofs) {
+ glEnable( GL_BLEND );
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ get_seq_color3ubv(scene, seq, col);
+
+ if (seq->flag & SELECT) {
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
+ glColor4ub(col[0], col[1], col[2], 170);
+ } else {
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
+ glColor4ub(col[0], col[1], col[2], 110);
+ }
+
+ glRectf((float)(seq->start), y1-SEQ_STRIP_OFSBOTTOM, x1, y1);
+
+ if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
+ else glColor4ub(col[0], col[1], col[2], 160);
+
+ fdrawbox((float)(seq->start), y1-SEQ_STRIP_OFSBOTTOM, x1, y1); //outline
+
+ glDisable( GL_BLEND );
+ }
+ if(seq->endofs) {
+ glEnable( GL_BLEND );
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ get_seq_color3ubv(scene, seq, col);
+
+ if (seq->flag & SELECT) {
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
+ glColor4ub(col[0], col[1], col[2], 170);
+ } else {
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
+ glColor4ub(col[0], col[1], col[2], 110);
+ }
+
+ glRectf(x2, y2, (float)(seq->start+seq->len), y2+SEQ_STRIP_OFSBOTTOM);
+
+ if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
+ else glColor4ub(col[0], col[1], col[2], 160);
+
+ fdrawbox(x2, y2, (float)(seq->start+seq->len), y2+SEQ_STRIP_OFSBOTTOM); //outline
+
+ glDisable( GL_BLEND );
+ }
+ if(seq->startstill) {
+ get_seq_color3ubv(scene, seq, col);
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
+ glColor3ubv((GLubyte *)col);
+
+ draw_shadedstrip(seq, col, x1, y1, (float)(seq->start), y2);
+
+ /* feint pinstripes, helps see exactly which is extended and which isn't,
+ * especially when the extension is very small */
+ if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
+ else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -16);
+
+ glColor3ubv((GLubyte *)col);
+
+ for(a=y1; a< y2; a+= pixely*2.0 ) {
+ fdrawline(x1, a, (float)(seq->start), a);
+ }
+ }
+ if(seq->endstill) {
+ get_seq_color3ubv(scene, seq, col);
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
+ glColor3ubv((GLubyte *)col);
+
+ draw_shadedstrip(seq, col, (float)(seq->start+seq->len), y1, x2, y2);
+
+ /* feint pinstripes, helps see exactly which is extended and which isn't,
+ * especially when the extension is very small */
+ if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
+ else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -16);
+
+ glColor3ubv((GLubyte *)col);
+
+ for(a=y1; a< y2; a+= pixely*2.0 ) {
+ fdrawline((float)(seq->start+seq->len), a, x2, a);
+ }
+ }
+}
+
+/* draw info text on a sequence strip */
+static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float y1, float y2, char *background_col)
+{
+ rctf rect;
+ char str[32 + FILE_MAXDIR+FILE_MAXFILE];
+
+ if(seq->name[2]) {
+ sprintf(str, "%d | %s: %s", seq->len, give_seqname(seq), seq->name+2);
+ }
+ else{
+ if(seq->type == SEQ_META) {
+ sprintf(str, "%d | %s", seq->len, give_seqname(seq));
+ }
+ else if(seq->type == SEQ_SCENE) {
+ if(seq->scene) sprintf(str, "%d | %s: %s", seq->len, give_seqname(seq), seq->scene->id.name+2);
+ else sprintf(str, "%d | %s", seq->len, give_seqname(seq));
+
+ }
+ else if(seq->type == SEQ_IMAGE) {
+ sprintf(str, "%d | %s%s", seq->len, seq->strip->dir, seq->strip->stripdata->name);
+ }
+ else if(seq->type & SEQ_EFFECT) {
+ int can_float = (seq->type != SEQ_PLUGIN)
+ || (seq->plugin && seq->plugin->version >= 4);
+
+ if(seq->seq3!=seq->seq2 && seq->seq1!=seq->seq3)
+ sprintf(str, "%d | %s: %d>%d (use %d)%s", seq->len, give_seqname(seq), seq->seq1->machine, seq->seq2->machine, seq->seq3->machine, can_float ? "" : " No float, upgrade plugin!");
+ else if (seq->seq1 && seq->seq2)
+ sprintf(str, "%d | %s: %d>%d%s", seq->len, give_seqname(seq), seq->seq1->machine, seq->seq2->machine, can_float ? "" : " No float, upgrade plugin!");
+ else
+ sprintf(str, "%d | %s", seq->len, give_seqname(seq));
+ }
+ else if (seq->type == SEQ_RAM_SOUND) {
+ sprintf(str, "%d | %s", seq->len, seq->strip->stripdata->name);
+ }
+ else if (seq->type == SEQ_HD_SOUND) {
+ sprintf(str, "%d | %s", seq->len, seq->strip->stripdata->name);
+ }
+ else if (seq->type == SEQ_MOVIE) {
+ sprintf(str, "%d | %s%s", seq->len, seq->strip->dir, seq->strip->stripdata->name);
+ }
+ }
+
+ if(seq->flag & SELECT){
+ cpack(0xFFFFFF);
+ }else if ((((int)background_col[0] + (int)background_col[1] + (int)background_col[2]) / 3) < 50){
+ cpack(0x505050); /* use lighter text colour for dark background */
+ }else{
+ cpack(0);
+ }
+
+ rect.xmin= x1;
+ rect.ymin= y1;
+ rect.xmax= x2;
+ rect.ymax= y2;
+ UI_view2d_text_cache_rectf(v2d, &rect, str);
+}
+
+/* draws a shaded strip, made from gradient + flat color + gradient */
+static void draw_shadedstrip(Sequence *seq, char *col, float x1, float y1, float x2, float y2)
+{
+ float ymid1, ymid2;
+
+ if (seq->flag & SEQ_MUTE) {
+ glEnable(GL_POLYGON_STIPPLE);
+ glPolygonStipple(stipple_halftone);
+ }
+
+ ymid1 = (y2-y1)*0.25 + y1;
+ ymid2 = (y2-y1)*0.65 + y1;
+
+ glShadeModel(GL_SMOOTH);
+ glBegin(GL_QUADS);
+
+ if(seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -50);
+ else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 0);
+
+ glColor3ubv((GLubyte *)col);
+
+ glVertex2f(x1,y1);
+ glVertex2f(x2,y1);
+
+ if(seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 5);
+ else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -5);
+
+ glColor3ubv((GLubyte *)col);
+
+ glVertex2f(x2,ymid1);
+ glVertex2f(x1,ymid1);
+
+ glEnd();
+
+ glRectf(x1, ymid1, x2, ymid2);
+
+ glBegin(GL_QUADS);
+
+ glVertex2f(x1,ymid2);
+ glVertex2f(x2,ymid2);
+
+ if(seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -15);
+ else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 25);
+
+ glColor3ubv((GLubyte *)col);
+
+ glVertex2f(x2,y2);
+ glVertex2f(x1,y2);
+
+ glEnd();
+
+ if (seq->flag & SEQ_MUTE) {
+ glDisable(GL_POLYGON_STIPPLE);
+ }
+}
+
+/*
+Draw a sequence strip, bounds check alredy made
+ARegion is currently only used to get the windows width in pixels
+so wave file sample drawing precission is zoom adjusted
+*/
+static void draw_seq_strip(Scene *scene, ARegion *ar, SpaceSeq *sseq, Sequence *seq, int outline_tint, float pixelx)
+{
+ // XXX
+ extern void gl_round_box_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown);
+ View2D *v2d= &ar->v2d;
+ float x1, x2, y1, y2;
+ char col[3], background_col[3], is_single_image;
+
+ /* we need to know if this is a single image/color or not for drawing */
+ is_single_image = (char)check_single_seq(seq);
+
+ /* body */
+ if(seq->startstill) x1= seq->start;
+ else x1= seq->startdisp;
+ y1= seq->machine+SEQ_STRIP_OFSBOTTOM;
+ if(seq->endstill) x2= seq->start+seq->len;
+ else x2= seq->enddisp;
+ y2= seq->machine+SEQ_STRIP_OFSTOP;
+
+
+ /* get the correct color per strip type*/
+ //get_seq_color3ubv(scene, seq, col);
+ get_seq_color3ubv(scene, seq, background_col);
+
+ /* draw the main strip body */
+ if (is_single_image) /* single image */
+ draw_shadedstrip(seq, background_col, seq_tx_get_final_left(seq, 0), y1, seq_tx_get_final_right(seq, 0), y2);
+ else /* normal operation */
+ draw_shadedstrip(seq, background_col, x1, y1, x2, y2);
+
+ /* draw additional info and controls */
+ if (seq->type == SEQ_RAM_SOUND)
+ drawseqwave(scene, v2d, seq, x1, y1, x2, y2, ar->winx);
+
+ if (!is_single_image)
+ draw_seq_extensions(scene, sseq, seq);
+
+ draw_seq_handle(v2d, seq, pixelx, SEQ_LEFTHANDLE);
+ draw_seq_handle(v2d, seq, pixelx, SEQ_RIGHTHANDLE);
+
+ /* draw the strip outline */
+ x1= seq->startdisp;
+ x2= seq->enddisp;
+
+ get_seq_color3ubv(scene, seq, col);
+ if (G.moving && (seq->flag & SELECT)) {
+ if(seq->flag & SEQ_OVERLAP) {
+ col[0]= 255; col[1]= col[2]= 40;
+ } else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 120);
+ }
+
+ UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, outline_tint);
+
+ glColor3ubv((GLubyte *)col);
+
+ if (seq->flag & SEQ_MUTE) {
+ glEnable(GL_LINE_STIPPLE);
+ glLineStipple(1, 0x8888);
+ }
+
+ gl_round_box_shade(GL_LINE_LOOP, x1, y1, x2, y2, 0.0, 0.1, 0.0);
+
+ if (seq->flag & SEQ_MUTE) {
+ glDisable(GL_LINE_STIPPLE);
+ }
+
+ /* calculate if seq is long enough to print a name */
+ x1= seq->startdisp+seq->handsize;
+ x2= seq->enddisp-seq->handsize;
+
+ /* but first the contents of a meta */
+ if(seq->type==SEQ_META) drawmeta_contents(scene, seq, x1, y1+0.15, x2, y2-0.15);
+
+ /* info text on the strip */
+ if(x1<v2d->cur.xmin) x1= v2d->cur.xmin;
+ else if(x1>v2d->cur.xmax) x1= v2d->cur.xmax;
+ if(x2<v2d->cur.xmin) x2= v2d->cur.xmin;
+ else if(x2>v2d->cur.xmax) x2= v2d->cur.xmax;
+
+ /* nice text here would require changing the view matrix for texture text */
+ if( (x2-x1) / pixelx > 32) {
+ draw_seq_text(v2d, seq, x1, x2, y1, y2, background_col);
+ }
+}
+
+static Sequence *special_seq_update= 0;
+
+void set_special_seq_update(int val)
+{
+// int x;
+
+ /* if mouse over a sequence && LEFTMOUSE */
+ if(val) {
+// XXX special_seq_update= find_nearest_seq(&x);
+ }
+ else special_seq_update= 0;
+}
+
+
+static void draw_image_seq(Scene *scene, ARegion *ar, SpaceSeq *sseq)
+{
+ extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad);
+ struct ImBuf *ibuf;
+ int x1, y1, rectx, recty;
+ int free_ibuf = 0;
+ static int recursive= 0;
+ float zoom;
+ float zoomx, zoomy;
+ int render_size = 0;
+
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ render_size = sseq->render_size;
+ if (render_size == 0) {
+ render_size = scene->r.size;
+ }
+ if (render_size < 0) {
+ return;
+ }
+
+ rectx= (render_size*scene->r.xsch)/100;
+ recty= (render_size*scene->r.ysch)/100;
+
+ /* BIG PROBLEM: the give_ibuf_seq() can call a rendering, which in turn calls redraws...
+ this shouldn't belong in a window drawing....
+ So: solve this once event based.
+ Now we check for recursion, space type and active area again (ton) */
+
+ if(recursive)
+ return;
+ else {
+ recursive= 1;
+ if (special_seq_update) {
+ ibuf= give_ibuf_seq_direct(scene, rectx, recty, (scene->r.cfra), render_size, special_seq_update);
+ }
+ else if (!U.prefetchframes) { // XXX || (G.f & G_PLAYANIM) == 0) {
+ ibuf= (ImBuf *)give_ibuf_seq(scene, rectx, recty, (scene->r.cfra), sseq->chanshown, render_size);
+ }
+ else {
+ ibuf= (ImBuf *)give_ibuf_seq_threaded(scene, rectx, recty, (scene->r.cfra), sseq->chanshown, render_size);
+ }
+ recursive= 0;
+
+ /* XXX HURMF! the give_ibuf_seq can call image display in this window */
+// if(sa->spacetype!=SPACE_SEQ)
+// return;
+// if(sa!=curarea) {
+// areawinset(sa->win);
+// }
+ }
+
+ if(ibuf==NULL)
+ return;
+
+ if(ibuf->rect==NULL && ibuf->rect_float == NULL)
+ return;
+
+ switch(sseq->mainb != SEQ_DRAW_SEQUENCE) {
+ case SEQ_DRAW_IMG_IMBUF:
+ if (sseq->zebra != 0) {
+ ibuf = make_zebra_view_from_ibuf(ibuf, sseq->zebra);
+ free_ibuf = 1;
+ }
+ break;
+ case SEQ_DRAW_IMG_WAVEFORM:
+ if ((sseq->flag & SEQ_DRAW_COLOR_SEPERATED) != 0) {
+ ibuf = make_sep_waveform_view_from_ibuf(ibuf);
+ } else {
+ ibuf = make_waveform_view_from_ibuf(ibuf);
+ }
+ free_ibuf = 1;
+ break;
+ case SEQ_DRAW_IMG_VECTORSCOPE:
+ ibuf = make_vectorscope_view_from_ibuf(ibuf);
+ free_ibuf = 1;
+ break;
+ case SEQ_DRAW_IMG_HISTOGRAM:
+ ibuf = make_histogram_view_from_ibuf(ibuf);
+ free_ibuf = 1;
+ break;
+ }
+
+ if(ibuf->rect_float && ibuf->rect==NULL)
+ IMB_rect_from_float(ibuf);
+
+ /* needed for gla draw */
+ glaDefine2DArea(&ar->winrct);
+
+ zoom= SEQ_ZOOM_FAC(sseq->zoom);
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
+ zoom /= render_size / 100.0;
+ zoomx = zoom * ((float)scene->r.xasp / (float)scene->r.yasp);
+ zoomy = zoom;
+ } else {
+ zoomx = zoomy = zoom;
+ }
+
+ /* calc location */
+ x1= (ar->winx-zoomx*ibuf->x)/2 + sseq->xof;
+ y1= (ar->winy-zoomy*ibuf->y)/2 + sseq->yof;
+
+ glPixelZoom(zoomx, zoomy);
+
+ glaDrawPixelsSafe(x1, y1, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+
+ glPixelZoom(1.0, 1.0);
+
+ /* safety border */
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF &&
+ (sseq->flag & SEQ_DRAW_SAFE_MARGINS) != 0) {
+ float fac= 0.1;
+ float x2 = x1 + ibuf->x * zoomx;
+ float y2 = y1 + ibuf->y * zoomy;
+
+ float a= fac*(x2-x1);
+ x1+= a;
+ x2-= a;
+
+ a= fac*(y2-y1);
+ y1+= a;
+ y2-= a;
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ setlinestyle(3);
+
+ UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0);
+
+ uiSetRoundBox(15);
+ gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 12.0);
+
+ setlinestyle(0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+
+ /* draw grease-pencil (image aligned) */
+// if (sseq->flag & SEQ_DRAW_GPENCIL)
+// XXX draw_gpencil_2dimage(sa, ibuf);
+
+ if (free_ibuf) {
+ IMB_freeImBuf(ibuf);
+ }
+
+ /* draw grease-pencil (screen aligned) */
+// if (sseq->flag & SEQ_DRAW_GPENCIL)
+// XXX draw_gpencil_2dview(sa, 0);
+
+ /* ortho at pixel level sa */
+// XXX myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
+
+}
+
+void seq_reset_imageofs(SpaceSeq *sseq)
+{
+ sseq->xof = sseq->yof = sseq->zoom = 0;
+}
+
+
+#if 0
+/* XXX - these should really be made to use View2D instead of so wacko private system - Aligorith */
+
+void seq_viewzoom(SpaceSeq *sseq, unsigned short event, int invert)
+{
+
+ if(event==PAD1)
+ sseq->zoom= 1.0;
+ else if(event==PAD2)
+ sseq->zoom= (invert)? 2.0: 0.5;
+ else if(event==PAD4)
+ sseq->zoom= (invert)? 4.0: 0.25;
+ else if(event==PAD8)
+ sseq->zoom= (invert)? 8.0: 0.125;
+
+ /* ensure pixel exact locations for draw */
+ sseq->xof= (int)sseq->xof;
+ sseq->yof= (int)sseq->yof;
+}
+
+void seq_viewmove(Scene *scene, ARegion *ar, SpaceSeq *sseq)
+{
+ short mval[2], mvalo[2];
+ short rectx, recty, xmin, xmax, ymin, ymax, pad;
+ int oldcursor;
+ Window *win;
+
+ sa = sseq->area;
+ rectx= (scene->r.size*scene->r.xsch)/100;
+ recty= (scene->r.size*scene->r.ysch)/100;
+
+ pad = 10;
+ xmin = -(ar->winx/2) - rectx/2 + pad;
+ xmax = ar->winx/2 + rectx/2 - pad;
+ ymin = -(ar->winy/2) - recty/2 + pad;
+ ymax = ar->winy/2 + recty/2 - pad;
+
+ getmouseco_sc(mvalo);
+
+ oldcursor=get_cursor();
+ win=winlay_get_active_window();
+
+ SetBlenderCursor(BC_NSEW_SCROLLCURSOR);
+
+ while(get_mbut()&(L_MOUSE|M_MOUSE)) {
+
+ getmouseco_sc(mval);
+
+ if(mvalo[0]!=mval[0] || mvalo[1]!=mval[1]) {
+
+ sseq->xof -= (mvalo[0]-mval[0]);
+ sseq->yof -= (mvalo[1]-mval[1]);
+
+ /* prevent dragging image outside of the window and losing it! */
+ CLAMP(sseq->xof, xmin, xmax);
+ CLAMP(sseq->yof, ymin, ymax);
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+
+ }
+ }
+}
+#endif
+
+void drawprefetchseqspace(Scene *scene, ARegion *ar, SpaceSeq *sseq)
+{
+ int rectx, recty;
+ int render_size = sseq->render_size;
+ if (render_size == 0) {
+ render_size = scene->r.size;
+ }
+ if (render_size < 0) {
+ return;
+ }
+
+ rectx= (render_size*scene->r.xsch)/100;
+ recty= (render_size*scene->r.ysch)/100;
+
+ if(sseq->mainb != SEQ_DRAW_SEQUENCE) {
+ give_ibuf_prefetch_request(
+ rectx, recty, (scene->r.cfra), sseq->chanshown,
+ render_size);
+ }
+}
+
+void drawseqspace(const bContext *C, ARegion *ar)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ SpaceSeq *sseq= sa->spacedata.first;
+ Scene *scene= CTX_data_scene(C);
+ View2D *v2d= &ar->v2d;
+ View2DScrollers *scrollers;
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+ float col[3];
+ int i;
+
+ if(sseq->mainb != SEQ_DRAW_SEQUENCE) {
+ draw_image_seq(scene, ar, sseq);
+ return;
+ }
+
+ UI_GetThemeColor3fv(TH_BACK, col);
+ if(ed && ed->metastack.first) glClearColor(col[0], col[1], col[2]-0.1, 0.0);
+ else glClearColor(col[0], col[1], col[2], 0.0);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ UI_view2d_view_ortho(C, v2d);
+
+ UI_ThemeColorShade(TH_BACK, -20);
+ glRectf(v2d->cur.xmin, 0.0, v2d->cur.xmax, 1.0);
+
+ boundbox_seq(scene, &v2d->tot);
+
+ /* Alternating horizontal stripes */
+ i= MAX2(1, ((int)v2d->cur.ymin)-1);
+
+ glBegin(GL_QUADS);
+ while (i<v2d->cur.ymax) {
+ if (((int)i) & 1)
+ UI_ThemeColorShade(TH_BACK, -15);
+ else
+ UI_ThemeColorShade(TH_BACK, -25);
+
+ glVertex2f(v2d->cur.xmax, i);
+ glVertex2f(v2d->cur.xmin, i);
+ glVertex2f(v2d->cur.xmin, i+1);
+ glVertex2f(v2d->cur.xmax, i+1);
+ i+=1.0;
+ }
+ glEnd();
+
+ /* Force grid lines */
+ i= MAX2(1, ((int)v2d->cur.ymin)-1);
+ glBegin(GL_LINES);
+
+ while (i<v2d->cur.ymax) {
+ UI_ThemeColor(TH_GRID);
+ glVertex2f(v2d->cur.xmax, i);
+ glVertex2f(v2d->cur.xmin, i);
+ i+=1.0;
+ }
+ glEnd();
+
+ UI_view2d_constant_grid_draw(C, v2d);
+
+ draw_cfra_seq(v2d, scene->r.cfra);
+
+ /* sequences: first deselect */
+ if(ed) {
+ Sequence *last_seq = get_last_seq(scene);
+ int sel = 0, j;
+ int outline_tint;
+ float pixelx = (v2d->cur.xmax - v2d->cur.xmin)/(v2d->mask.xmax - v2d->mask.xmin);
+ /* loop through twice, first unselected, then selected */
+ for (j=0; j<2; j++) {
+ seq= ed->seqbasep->first;
+ if (j==0) outline_tint = -150;
+ else outline_tint = -60;
+
+ while(seq) { /* bound box test, dont draw outside the view */
+ if ( ((seq->flag & SELECT) == sel) ||
+ seq == last_seq ||
+ MIN2(seq->startdisp, seq->start) > v2d->cur.xmax ||
+ MAX2(seq->enddisp, seq->start+seq->len) < v2d->cur.xmin ||
+ seq->machine+1.0 < v2d->cur.ymin ||
+ seq->machine > v2d->cur.ymax)
+ {
+ /* dont draw */
+ } else {
+ draw_seq_strip(scene, ar, sseq, seq, outline_tint, pixelx);
+ }
+ seq= seq->next;
+ }
+ sel= SELECT; /* draw selected next time round */
+ }
+ /* draw the last selected last, removes some overlapping error */
+ if (last_seq) {
+ draw_seq_strip(scene, ar, sseq, last_seq, 120, pixelx);
+ }
+ }
+
+ /* text draw cached, in pixelspace now */
+ UI_view2d_text_cache_draw(ar);
+
+ /* Draw markers */
+// draw_markers_timespace(SCE_MARKERS, DRAW_MARKERS_LINES);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_UNIT_SECONDSSEQ, V2D_GRID_CLAMP, V2D_UNIT_VALUES, V2D_GRID_CLAMP);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+}
+
+
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
new file mode 100644
index 00000000000..9c3191c93d6
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -0,0 +1,2409 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2003-2009
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+#include <sys/types.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_storage_types.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_ipo_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_view2d_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_sound_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_plugin_types.h"
+#include "BKE_sequence.h"
+#include "BKE_scene.h"
+#include "BKE_utildefines.h"
+#include "BKE_report.h"
+
+#include "BIF_transform.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+/* for menu/popup icons etc etc*/
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "ED_anim_api.h"
+#include "ED_space_api.h"
+#include "ED_types.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+/* own include */
+#include "sequencer_intern.h"
+
+/* XXX */
+//static Sequence *_last_seq=0;
+//static int _last_seq_init=0;
+/* XXX */
+static void error() {}
+static void waitcursor() {}
+static void activate_fileselect() {}
+static int pupmenu() {return 0;}
+static int okee() {return 0;}
+
+
+/* XXX */
+/* RNA Enums, used in multiple files */
+EnumPropertyItem sequencer_prop_effect_types[] = {
+ {SEQ_CROSS, "CROSS", "Crossfade", "Crossfade effect strip type"},
+ {SEQ_ADD, "ADD", "Add", "Add effect strip type"},
+ {SEQ_SUB, "SUBTRACT", "Subtract", "Subtract effect strip type"},
+ {SEQ_ALPHAOVER, "ALPHA_OVER", "Alpha Over", "Alpha Over effect strip type"},
+ {SEQ_ALPHAUNDER, "ALPHA_UNDER", "Alpha Under", "Alpha Under effect strip type"},
+ {SEQ_GAMCROSS, "GAMMA_CROSS", "Gamma Cross", "Gamma Cross effect strip type"},
+ {SEQ_MUL, "MULTIPLY", "Multiply", "Multiply effect strip type"},
+ {SEQ_OVERDROP, "OVER_DROP", "Alpha Over Drop", "Alpha Over Drop effect strip type"},
+ {SEQ_PLUGIN, "PLUGIN", "Plugin", "Plugin effect strip type"},
+ {SEQ_WIPE, "WIPE", "Wipe", "Wipe effect strip type"},
+ {SEQ_GLOW, "GLOW", "Glow", "Glow effect strip type"},
+ {SEQ_TRANSFORM, "TRANSFORM", "Transform", "Transform effect strip type"},
+ {SEQ_COLOR, "COLOR", "Color", "Color effect strip type"},
+ {SEQ_SPEED, "SPEED", "Speed", "Color effect strip type"},
+ {0, NULL, NULL, NULL}
+};
+
+/* mute operator */
+EnumPropertyItem sequencer_prop_operate_types[] = { /* better name? */
+ {SEQ_SELECTED, "SELECTED", "Selected", ""},
+ {SEQ_UNSELECTED, "UNSELECTED", "Unselected ", ""},
+ {0, NULL, NULL, NULL}
+};
+
+ EnumPropertyItem prop_side_types[] = {
+ {SEQ_SIDE_LEFT, "LEFT", "Left", ""},
+ {SEQ_SIDE_RIGHT, "RIGHT", "Right", ""},
+ {SEQ_SIDE_BOTH, "BOTH", "Both", ""},
+ {0, NULL, NULL, NULL}
+};
+
+typedef struct TransSeq {
+ int start, machine;
+ int startstill, endstill;
+ int startdisp, enddisp;
+ int startofs, endofs;
+ int final_left, final_right;
+ int len;
+} TransSeq;
+
+Sequence *get_last_seq(Scene *scene)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ if(ed==NULL) return NULL;
+ return ed->act_seq;
+}
+
+void set_last_seq(Scene *scene, Sequence *seq)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ if(ed==NULL) return;
+
+ ed->act_seq= seq;
+}
+
+Sequence *get_foreground_frame_seq(Scene *scene, int frame)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq, *best_seq=NULL;
+ int best_machine = -1;
+
+ if(!ed) return NULL;
+
+ for (seq=ed->seqbasep->first; seq; seq= seq->next) {
+ if(seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame)
+ continue;
+ /* only use elements you can see - not */
+ if (ELEM6(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE, SEQ_MOVIE_AND_HD_SOUND, SEQ_COLOR)) {
+ if (seq->machine > best_machine) {
+ best_seq = seq;
+ best_machine = seq->machine;
+ }
+ }
+ }
+ return best_seq;
+}
+
+void seq_rectf(Sequence *seq, rctf *rectf)
+{
+ if(seq->startstill) rectf->xmin= seq->start;
+ else rectf->xmin= seq->startdisp;
+ rectf->ymin= seq->machine+SEQ_STRIP_OFSBOTTOM;
+ if(seq->endstill) rectf->xmax= seq->start+seq->len;
+ else rectf->xmax= seq->enddisp;
+ rectf->ymax= seq->machine+SEQ_STRIP_OFSTOP;
+}
+
+static void change_plugin_seq(Scene *scene, char *str) /* called from fileselect */
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ struct SeqEffectHandle sh;
+ Sequence *last_seq= get_last_seq(scene);
+
+ if(last_seq && last_seq->type != SEQ_PLUGIN) return;
+
+ sh = get_sequence_effect(last_seq);
+ sh.free(last_seq);
+ sh.init_plugin(last_seq, str);
+
+ last_seq->machine = MAX3(last_seq->seq1->machine,
+ last_seq->seq2->machine,
+ last_seq->seq3->machine);
+
+ if( seq_test_overlap(ed->seqbasep, last_seq) ) shuffle_seq(ed->seqbasep, last_seq);
+
+}
+
+
+void boundbox_seq(Scene *scene, rctf *rect)
+{
+ Sequence *seq;
+ Editing *ed= seq_give_editing(scene, FALSE);
+ float min[2], max[2];
+
+
+ if(ed==NULL) return;
+
+ min[0]= 0.0;
+ max[0]= EFRA+1;
+ min[1]= 0.0;
+ max[1]= 8.0;
+
+ seq= ed->seqbasep->first;
+ while(seq) {
+
+ if( min[0] > seq->startdisp-1) min[0]= seq->startdisp-1;
+ if( max[0] < seq->enddisp+1) max[0]= seq->enddisp+1;
+ if( max[1] < seq->machine+2.0) max[1]= seq->machine+2.0;
+
+ seq= seq->next;
+ }
+
+ rect->xmin= min[0];
+ rect->xmax= max[0];
+ rect->ymin= min[1];
+ rect->ymax= max[1];
+
+}
+
+int mouse_frame_side(View2D *v2d, short mouse_x, int frame )
+{
+ short mval[2];
+ float mouseloc[2];
+
+ mval[0]= mouse_x;
+ mval[1]= 0;
+
+ /* choose the side based on which side of the playhead the mouse is on */
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouseloc[0], &mouseloc[1]);
+
+ return mouseloc[0] > frame ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT;
+}
+
+
+Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int sel)
+{
+ /* sel - 0==unselected, 1==selected, -1==done care*/
+ Sequence *seq;
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ if(ed==NULL) return NULL;
+
+ if (sel>0) sel = SELECT;
+
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ if( (seq!=test) &&
+ (test->machine==seq->machine) &&
+ ((sel == -1) || (sel && (seq->flag & SELECT)) || (sel==0 && (seq->flag & SELECT)==0) ))
+ {
+ switch (lr) {
+ case SEQ_SIDE_LEFT:
+ if (test->startdisp == (seq->enddisp)) {
+ return seq;
+ }
+ break;
+ case SEQ_SIDE_RIGHT:
+ if (test->enddisp == (seq->startdisp)) {
+ return seq;
+ }
+ break;
+ }
+ }
+ }
+ return NULL;
+}
+
+Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, int sel)
+{
+ /* sel - 0==unselected, 1==selected, -1==done care*/
+ Sequence *seq,*best_seq = NULL;
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ int dist, best_dist;
+ best_dist = MAXFRAME*2;
+
+
+ if(ed==NULL) return NULL;
+
+ if (sel) sel = SELECT;
+
+ seq= ed->seqbasep->first;
+ while(seq) {
+ if( (seq!=test) &&
+ (test->machine==seq->machine) &&
+ (test->depth==seq->depth) &&
+ ((sel == -1) || (sel==(seq->flag & SELECT))))
+ {
+ dist = MAXFRAME*2;
+
+ switch (lr) {
+ case SEQ_SIDE_LEFT:
+ if (seq->enddisp <= test->startdisp) {
+ dist = test->enddisp - seq->startdisp;
+ }
+ break;
+ case SEQ_SIDE_RIGHT:
+ if (seq->startdisp >= test->enddisp) {
+ dist = seq->startdisp - test->enddisp;
+ }
+ break;
+ }
+
+ if (dist==0) {
+ best_seq = seq;
+ break;
+ } else if (dist < best_dist) {
+ best_dist = dist;
+ best_seq = seq;
+ }
+ }
+ seq= seq->next;
+ }
+ return best_seq; /* can be null */
+}
+
+
+Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, short mval[2])
+{
+ Sequence *seq;
+ Editing *ed= seq_give_editing(scene, FALSE);
+ float x, y;
+ float pixelx;
+ float handsize;
+ float displen;
+ *hand= SEQ_SIDE_NONE;
+
+
+ if(ed==NULL) return NULL;
+
+ pixelx = (v2d->cur.xmax - v2d->cur.xmin)/(v2d->mask.xmax - v2d->mask.xmin);
+
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
+
+ seq= ed->seqbasep->first;
+
+ while(seq) {
+ if(seq->machine == (int)y) {
+ /* check for both normal strips, and strips that have been flipped horizontally */
+ if( ((seq->startdisp < seq->enddisp) && (seq->startdisp<=x && seq->enddisp>=x)) ||
+ ((seq->startdisp > seq->enddisp) && (seq->startdisp>=x && seq->enddisp<=x)) )
+ {
+ if(seq_tx_test(seq)) {
+
+ /* clamp handles to defined size in pixel space */
+
+ handsize = seq->handsize;
+ displen = (float)abs(seq->startdisp - seq->enddisp);
+
+ if (displen / pixelx > 16) { /* dont even try to grab the handles of small strips */
+ /* Set the max value to handle to 1/3 of the total len when its less then 28.
+ * This is important because otherwise selecting handles happens even when you click in the middle */
+
+ if ((displen/3) < 30*pixelx) {
+ handsize = displen/3;
+ } else {
+ CLAMP(handsize, 7*pixelx, 30*pixelx);
+ }
+
+ if( handsize+seq->startdisp >=x )
+ *hand= SEQ_SIDE_LEFT;
+ else if( -handsize+seq->enddisp <=x )
+ *hand= SEQ_SIDE_RIGHT;
+ }
+ }
+ return seq;
+ }
+ }
+ seq= seq->next;
+ }
+ return 0;
+}
+
+void update_seq_ipo_rect(Scene *scene, View2D *v2d, Sequence *seq)
+{
+ float start;
+ float end;
+
+ if (!seq || !seq->ipo) {
+ return;
+ }
+ start = -5.0;
+ end = 105.0;
+
+
+ /* Adjust IPO window to sequence and
+ avoid annoying snap-back to startframe
+ when Lock Time is on */
+ if (0) { // XXX v2d->flag & V2D_VIEWLOCK) {
+ if ((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
+ start = -5.0 + seq->startdisp;
+ end = 5.0 + seq->enddisp;
+ } else {
+ start = (float)scene->r.sfra - 0.1;
+ end = scene->r.efra;
+ }
+ }
+
+ seq->ipo->cur.xmin= start;
+ seq->ipo->cur.xmax= end;
+}
+
+void update_seq_icu_rects(Sequence * seq)
+{
+ IpoCurve *icu= NULL;
+ struct SeqEffectHandle sh;
+
+ if (!seq || !seq->ipo) {
+ return;
+ }
+
+ if(!(seq->type & SEQ_EFFECT)) {
+ return;
+ }
+
+ sh = get_sequence_effect(seq);
+
+ for(icu= seq->ipo->curve.first; icu; icu= icu->next) {
+ sh.store_icu_yrange(seq, icu->adrcode, &icu->ymin, &icu->ymax);
+ }
+}
+
+
+static int seq_is_parent(Sequence *par, Sequence *seq)
+{
+ return ((par->seq1 == seq) || (par->seq2 == seq) || (par->seq3 == seq));
+}
+
+static int seq_is_predecessor(Sequence *pred, Sequence *seq)
+{
+ if (!pred) return 0;
+ if(pred == seq) return 0;
+ else if(seq_is_parent(pred, seq)) return 1;
+ else if(pred->seq1 && seq_is_predecessor(pred->seq1, seq)) return 1;
+ else if(pred->seq2 && seq_is_predecessor(pred->seq2, seq)) return 1;
+ else if(pred->seq3 && seq_is_predecessor(pred->seq3, seq)) return 1;
+
+ return 0;
+}
+
+void deselect_all_seq(Scene *scene)
+{
+ Sequence *seq;
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+
+ if(ed==NULL) return;
+
+ SEQP_BEGIN(ed, seq) {
+ seq->flag &= SEQ_DESEL;
+ }
+ SEQ_END
+
+}
+
+void recurs_sel_seq(Sequence *seqm)
+{
+ Sequence *seq;
+
+ seq= seqm->seqbase.first;
+ while(seq) {
+
+ if(seqm->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL)) seq->flag &= SEQ_DESEL;
+ else if(seqm->flag & SELECT) seq->flag |= SELECT;
+ else seq->flag &= SEQ_DESEL;
+
+ if(seq->seqbase.first) recurs_sel_seq(seq);
+
+ seq= seq->next;
+ }
+}
+
+Sequence *alloc_sequence(ListBase *lb, int cfra, int machine)
+{
+ Sequence *seq;
+
+ /*ed= scene->ed;*/
+
+ seq= MEM_callocN( sizeof(Sequence), "addseq");
+ BLI_addtail(lb, seq);
+
+ //set_last_seq(scene, seq); // Probably not a great idea at such a low level anyway - Campbell
+
+ *( (short *)seq->name )= ID_SEQ;
+ seq->name[2]= 0;
+
+ seq->flag= SELECT;
+ seq->start= cfra;
+ seq->machine= machine;
+ seq->mul= 1.0;
+ seq->blend_opacity = 100.0;
+
+ return seq;
+}
+
+int event_to_efftype(int event)
+{
+ if(event==2) return SEQ_CROSS;
+ if(event==3) return SEQ_GAMCROSS;
+ if(event==4) return SEQ_ADD;
+ if(event==5) return SEQ_SUB;
+ if(event==6) return SEQ_MUL;
+ if(event==7) return SEQ_ALPHAOVER;
+ if(event==8) return SEQ_ALPHAUNDER;
+ if(event==9) return SEQ_OVERDROP;
+ if(event==10) return SEQ_PLUGIN;
+ if(event==13) return SEQ_WIPE;
+ if(event==14) return SEQ_GLOW;
+ if(event==15) return SEQ_TRANSFORM;
+ if(event==16) return SEQ_COLOR;
+ if(event==17) return SEQ_SPEED;
+ return 0;
+}
+
+#if 0
+static void reload_sound_strip(Scene *scene, char *name)
+{
+ Editing *ed;
+ Sequence *seq, *seqact;
+ SpaceFile *sfile;
+ Sequence *last_seq= get_last_seq(scene);
+
+ ed= scene->ed;
+
+ if(last_seq==0 || last_seq->type!=SEQ_SOUND) return;
+ seqact= last_seq; /* last_seq changes in alloc_sequence */
+
+ /* search sfile */
+// sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
+ if(sfile==0) return;
+
+ waitcursor(1);
+
+ seq = sfile_to_snd_sequence(sfile, seqact->start, seqact->machine);
+ printf("seq->type: %i\n", seq->type);
+ if(seq && seq!=seqact) {
+ /* i'm not sure about this one, seems to work without it -- sgefant */
+ seq_free_strip(seqact->strip);
+
+ seqact->strip= seq->strip;
+
+ seqact->len= seq->len;
+ calc_sequence(seqact);
+
+ seq->strip= 0;
+ seq_free_sequence(ed, seq);
+ BLI_remlink(ed->seqbasep, seq);
+
+ seq= ed->seqbasep->first;
+
+ }
+
+ waitcursor(0);
+
+}
+#endif
+
+static void reload_image_strip(Scene *scene, char *name)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq=NULL, *seqact;
+ SpaceFile *sfile=NULL;
+ Sequence *last_seq= get_last_seq(scene);
+
+
+
+ if(last_seq==0 || last_seq->type!=SEQ_IMAGE) return;
+ seqact= last_seq; /* last_seq changes in alloc_sequence */
+
+ /* search sfile */
+// sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
+ if(sfile==0) return;
+
+ waitcursor(1);
+
+// seq= sfile_to_sequence(scene, sfile, seqact->start, seqact->machine, 1); // XXX ADD BACK
+ if(seq && seq!=seqact) {
+ seq_free_strip(seqact->strip);
+
+ seqact->strip= seq->strip;
+
+ seqact->len= seq->len;
+ calc_sequence(seqact);
+
+ seq->strip= 0;
+ seq_free_sequence(ed, seq);
+ BLI_remlink(ed->seqbasep, seq);
+
+ update_changed_seq_and_deps(scene, seqact, 1, 1);
+ }
+ waitcursor(0);
+
+}
+
+
+void change_sequence(Scene *scene)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *last_seq= get_last_seq(scene);
+ Scene *sce;
+ short event;
+
+ if(last_seq==0) return;
+
+ if(last_seq->type & SEQ_EFFECT) {
+ event = pupmenu("Change Effect%t"
+ "|Switch A <-> B %x1"
+ "|Switch B <-> C %x10"
+ "|Plugin%x11"
+ "|Recalculate%x12"
+ "|Cross%x2"
+ "|Gamma Cross%x3"
+ "|Add%x4"
+ "|Sub%x5"
+ "|Mul%x6"
+ "|Alpha Over%x7"
+ "|Alpha Under%x8"
+ "|Alpha Over Drop%x9"
+ "|Wipe%x13"
+ "|Glow%x14"
+ "|Transform%x15"
+ "|Color Generator%x16"
+ "|Speed Control%x17");
+ if(event > 0) {
+ if(event==1) {
+ SWAP(Sequence *,last_seq->seq1,last_seq->seq2);
+ }
+ else if(event==10) {
+ SWAP(Sequence *,last_seq->seq2,last_seq->seq3);
+ }
+ else if(event==11) {
+ activate_fileselect(
+ FILE_SPECIAL, "Select Plugin",
+ U.plugseqdir, change_plugin_seq);
+ }
+ else if(event==12);
+ /* recalculate: only new_stripdata */
+ else {
+ /* free previous effect and init new effect */
+ struct SeqEffectHandle sh;
+
+ if (get_sequence_effect_num_inputs(
+ last_seq->type)
+ < get_sequence_effect_num_inputs(
+ event_to_efftype(event))) {
+ error("New effect needs more "
+ "input strips!");
+ } else {
+ sh = get_sequence_effect(last_seq);
+ sh.free(last_seq);
+
+ last_seq->type
+ = event_to_efftype(event);
+
+ sh = get_sequence_effect(last_seq);
+ sh.init(last_seq);
+ }
+ }
+
+ update_changed_seq_and_deps(scene, last_seq, 0, 1);
+ }
+ }
+ else if(last_seq->type == SEQ_IMAGE) {
+ if(okee("Change images")) {
+ activate_fileselect(FILE_SPECIAL,
+ "Select Images",
+ ed->act_imagedir,
+ reload_image_strip);
+ }
+ }
+ else if(last_seq->type == SEQ_MOVIE) {
+ ;
+ }
+ else if(last_seq->type == SEQ_SCENE) {
+ event= pupmenu("Change Scene%t|Update Start and End");
+
+ if(event==1) {
+ sce= last_seq->scene;
+
+ last_seq->len= sce->r.efra - sce->r.sfra + 1;
+ last_seq->sfra= sce->r.sfra;
+
+ /* bad code to change seq->len? update_changed_seq_and_deps() expects the strip->len to be OK */
+ new_tstripdata(last_seq);
+
+ update_changed_seq_and_deps(scene, last_seq, 1, 1);
+
+ }
+ }
+
+}
+
+int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequence **selseq1, Sequence **selseq2, Sequence **selseq3, char **error_str)
+{
+ Editing *ed = seq_give_editing(scene, FALSE);
+ Sequence *seq1= 0, *seq2= 0, *seq3= 0, *seq;
+
+ *error_str= NULL;
+
+ if (!activeseq)
+ seq2= get_last_seq(scene);
+
+ for(seq=ed->seqbasep->first; seq; seq=seq->next) {
+ if(seq->flag & SELECT) {
+ if (seq->type == SEQ_RAM_SOUND || seq->type == SEQ_HD_SOUND) {
+ *error_str= "Can't apply effects to audio sequence strips";
+ return 0;
+ }
+ if((seq != activeseq) && (seq != seq2)) {
+ if(seq2==0) seq2= seq;
+ else if(seq1==0) seq1= seq;
+ else if(seq3==0) seq3= seq;
+ else {
+ *error_str= "Can't apply effect to more than 3 sequence strips";
+ return 0;
+ }
+ }
+ }
+ }
+
+ /* make sequence selection a little bit more intuitive
+ for 3 strips: the last-strip should be sequence3 */
+ if (seq3 != 0 && seq2 != 0) {
+ Sequence *tmp = seq2;
+ seq2 = seq3;
+ seq3 = tmp;
+ }
+
+
+ switch(get_sequence_effect_num_inputs(type)) {
+ case 0:
+ *selseq1 = *selseq2 = *selseq3 = 0;
+ return 1; /* succsess */
+ case 1:
+ if(seq2==0) {
+ *error_str= "Need at least one selected sequence strip";
+ return 0;
+ }
+ if(seq1==0) seq1= seq2;
+ if(seq3==0) seq3= seq2;
+ case 2:
+ if(seq1==0 || seq2==0) {
+ *error_str= "Need 2 selected sequence strips";
+ return 0;
+ }
+ if(seq3==0) seq3= seq2;
+ }
+
+ if (seq1==NULL && seq2==NULL && seq3==NULL) {
+ *error_str= "TODO: in what cases does this happen?";
+ return 0;
+ }
+
+ *selseq1= seq1;
+ *selseq2= seq2;
+ *selseq3= seq3;
+
+ return 1;
+}
+
+void reassign_inputs_seq_effect(Scene *scene)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq1, *seq2, *seq3, *last_seq = get_last_seq(scene);
+ char *error_msg;
+
+ if(last_seq==0 || !(last_seq->type & SEQ_EFFECT)) return;
+ if(ed==NULL) return;
+
+ if(!seq_effect_find_selected(scene, last_seq, last_seq->type, &seq1, &seq2, &seq3, &error_msg)) {
+ //BKE_report(op->reports, RPT_ERROR, error_msg); // XXX operatorify
+ return;
+ }
+ /* see reassigning would create a cycle */
+ if( seq_is_predecessor(seq1, last_seq) ||
+ seq_is_predecessor(seq2, last_seq) ||
+ seq_is_predecessor(seq3, last_seq)
+ ) {
+ //BKE_report(op->reports, RPT_ERROR, "Can't reassign inputs: no cycles allowed"); // XXX operatorify
+ return;
+ }
+
+ last_seq->seq1 = seq1;
+ last_seq->seq2 = seq2;
+ last_seq->seq3 = seq3;
+
+ update_changed_seq_and_deps(scene, last_seq, 1, 1);
+
+}
+
+static Sequence *del_seq_find_replace_recurs(Scene *scene, Sequence *seq)
+{
+ Sequence *seq1, *seq2, *seq3;
+
+ /* try to find a replacement input sequence, and flag for later deletion if
+ no replacement can be found */
+
+ if(!seq)
+ return NULL;
+ else if(!(seq->type & SEQ_EFFECT))
+ return ((seq->flag & SELECT)? NULL: seq);
+ else if(!(seq->flag & SELECT)) {
+ /* try to find replacement for effect inputs */
+ seq1= del_seq_find_replace_recurs(scene, seq->seq1);
+ seq2= del_seq_find_replace_recurs(scene, seq->seq2);
+ seq3= del_seq_find_replace_recurs(scene, seq->seq3);
+
+ if(seq1==seq->seq1 && seq2==seq->seq2 && seq3==seq->seq3);
+ else if(seq1 || seq2 || seq3) {
+ seq->seq1= (seq1)? seq1: (seq2)? seq2: seq3;
+ seq->seq2= (seq2)? seq2: (seq1)? seq1: seq3;
+ seq->seq3= (seq3)? seq3: (seq1)? seq1: seq2;
+
+ update_changed_seq_and_deps(scene, seq, 1, 1);
+ }
+ else
+ seq->flag |= SELECT; /* mark for delete */
+ }
+
+ if (seq->flag & SELECT) {
+ if((seq1 = del_seq_find_replace_recurs(scene, seq->seq1))) return seq1;
+ if((seq2 = del_seq_find_replace_recurs(scene, seq->seq2))) return seq2;
+ if((seq3 = del_seq_find_replace_recurs(scene, seq->seq3))) return seq3;
+ else return NULL;
+ }
+ else
+ return seq;
+}
+
+static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short deleteall)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq, *seqn;
+ Sequence *last_seq = get_last_seq(scene);
+
+ seq= lb->first;
+ while(seq) {
+ seqn= seq->next;
+ if((seq->flag & flag) || deleteall) {
+ if(seq->type==SEQ_RAM_SOUND && seq->sound)
+ seq->sound->id.us--;
+
+ BLI_remlink(lb, seq);
+ if(seq==last_seq) set_last_seq(scene, NULL);
+ if(seq->type==SEQ_META) recurs_del_seq_flag(scene, &seq->seqbase, flag, 1);
+ if(seq->ipo) seq->ipo->id.us--;
+ seq_free_sequence(ed, seq);
+ }
+ seq= seqn;
+ }
+}
+
+static Sequence *dupli_seq(Sequence *seq)
+{
+ Sequence *seqn = MEM_dupallocN(seq);
+ // XXX animato: ID *id;
+
+ seq->tmp = seqn;
+
+ seqn->strip= MEM_dupallocN(seq->strip);
+
+ // XXX animato
+#if 0
+ if (seqn->ipo) {
+ if (U.dupflag & USER_DUP_IPO) {
+ id= (ID *)seqn->ipo;
+ seqn->ipo= copy_ipo(seqn->ipo);
+ /* we don't need to decrease the number
+ * of the ipo because we never increase it,
+ * for example, adduplicate need decrease
+ * the number but only because copy_object
+ * call id_us_plus for the ipo block and
+ * single_ipo_users only work if id->us > 1.
+ *
+ * need call ipo_idnew here, for drivers ??
+ * - Diego
+ */
+ }
+ else
+ seqn->ipo->id.us++;
+ }
+#endif
+
+ seqn->strip->tstripdata = 0;
+ seqn->strip->tstripdata_startstill = 0;
+ seqn->strip->tstripdata_endstill = 0;
+ seqn->strip->ibuf_startstill = 0;
+ seqn->strip->ibuf_endstill = 0;
+
+ if (seq->strip->crop) {
+ seqn->strip->crop = MEM_dupallocN(seq->strip->crop);
+ }
+
+ if (seq->strip->transform) {
+ seqn->strip->transform = MEM_dupallocN(seq->strip->transform);
+ }
+
+ if (seq->strip->proxy) {
+ seqn->strip->proxy = MEM_dupallocN(seq->strip->proxy);
+ }
+
+ if (seq->strip->color_balance) {
+ seqn->strip->color_balance
+ = MEM_dupallocN(seq->strip->color_balance);
+ }
+
+ if(seq->type==SEQ_META) {
+ seqn->strip->stripdata = 0;
+
+ seqn->seqbase.first= seqn->seqbase.last= 0;
+ /* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */
+ /* - recurs_dupli_seq(&seq->seqbase,&seqn->seqbase);*/
+ } else if(seq->type == SEQ_SCENE) {
+ seqn->strip->stripdata = 0;
+ } else if(seq->type == SEQ_MOVIE) {
+ seqn->strip->stripdata =
+ MEM_dupallocN(seq->strip->stripdata);
+ seqn->anim= 0;
+ } else if(seq->type == SEQ_RAM_SOUND) {
+ seqn->strip->stripdata =
+ MEM_dupallocN(seq->strip->stripdata);
+ seqn->sound->id.us++;
+ } else if(seq->type == SEQ_HD_SOUND) {
+ seqn->strip->stripdata =
+ MEM_dupallocN(seq->strip->stripdata);
+ seqn->hdaudio = 0;
+ } else if(seq->type == SEQ_IMAGE) {
+ seqn->strip->stripdata =
+ MEM_dupallocN(seq->strip->stripdata);
+ } else if(seq->type >= SEQ_EFFECT) {
+ if(seq->seq1 && seq->seq1->tmp) seqn->seq1= seq->seq1->tmp;
+ if(seq->seq2 && seq->seq2->tmp) seqn->seq2= seq->seq2->tmp;
+ if(seq->seq3 && seq->seq3->tmp) seqn->seq3= seq->seq3->tmp;
+
+ if (seq->type & SEQ_EFFECT) {
+ struct SeqEffectHandle sh;
+ sh = get_sequence_effect(seq);
+ if(sh.copy)
+ sh.copy(seq, seqn);
+ }
+
+ seqn->strip->stripdata = 0;
+
+ } else {
+ fprintf(stderr, "Aiiiiekkk! sequence type not "
+ "handled in duplicate!\nExpect a crash"
+ " now...\n");
+ }
+
+ return seqn;
+}
+
+static Sequence * deep_dupli_seq(Sequence * seq)
+{
+ Sequence * seqn = dupli_seq(seq);
+ if (seq->type == SEQ_META) {
+ Sequence * s;
+ for(s= seq->seqbase.first; s; s = s->next) {
+ Sequence * n = deep_dupli_seq(s);
+ if (n) {
+ BLI_addtail(&seqn->seqbase, n);
+ }
+ }
+ }
+ return seqn;
+}
+
+
+static void recurs_dupli_seq(Scene *scene, ListBase *old, ListBase *new)
+{
+ Sequence *seq;
+ Sequence *seqn = 0;
+ Sequence *last_seq = get_last_seq(scene);
+
+ for(seq= old->first; seq; seq= seq->next) {
+ seq->tmp= NULL;
+ if(seq->flag & SELECT) {
+ seqn = dupli_seq(seq);
+ if (seqn) { /*should never fail */
+ seq->flag &= SEQ_DESEL;
+ seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL+SEQ_LOCK);
+
+ BLI_addtail(new, seqn);
+ if(seq->type==SEQ_META)
+ recurs_dupli_seq(scene, &seq->seqbase,&seqn->seqbase);
+
+ if (seq == last_seq) {
+ set_last_seq(scene, seqn);
+ }
+ }
+ }
+ }
+}
+
+static Sequence *cut_seq_hard(Scene *scene, Sequence * seq, int cutframe)
+{
+ TransSeq ts;
+ Sequence *seqn = 0;
+ int skip_dup = FALSE;
+
+ /* backup values */
+ ts.start= seq->start;
+ ts.machine= seq->machine;
+ ts.startstill= seq->startstill;
+ ts.endstill= seq->endstill;
+ ts.startdisp= seq->startdisp;
+ ts.enddisp= seq->enddisp;
+ ts.startofs= seq->anim_startofs;
+ ts.endofs= seq->anim_endofs;
+ ts.len= seq->len;
+
+ /* First Strip! */
+ /* strips with extended stillfames before */
+
+ if ((seq->startstill) && (cutframe <seq->start)) {
+ /* don't do funny things with METAs ... */
+ if (seq->type == SEQ_META) {
+ skip_dup = TRUE;
+ seq->startstill = seq->start - cutframe;
+ } else {
+ seq->start= cutframe -1;
+ seq->startstill= cutframe -seq->startdisp -1;
+ seq->anim_endofs += seq->len - 1;
+ seq->endstill= 0;
+ }
+ }
+ /* normal strip */
+ else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) {
+ seq->endofs = 0;
+ seq->endstill = 0;
+ seq->anim_endofs += (seq->start+seq->len) - cutframe;
+ }
+ /* strips with extended stillframes after */
+ else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
+ seq->endstill -= seq->enddisp - cutframe;
+ /* don't do funny things with METAs ... */
+ if (seq->type == SEQ_META) {
+ skip_dup = TRUE;
+ }
+ }
+
+ reload_sequence_new_file(scene, seq);
+ calc_sequence(seq);
+
+ if (!skip_dup) {
+ /* Duplicate AFTER the first change */
+ seqn = deep_dupli_seq(seq);
+ }
+
+ if (seqn) {
+ seqn->flag |= SELECT;
+
+ /* Second Strip! */
+ /* strips with extended stillframes before */
+ if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
+ seqn->start = ts.start;
+ seqn->startstill= ts.start- cutframe;
+ seqn->anim_endofs = ts.endofs;
+ seqn->endstill = ts.endstill;
+ }
+
+ /* normal strip */
+ else if ((cutframe>=seqn->start)&&(cutframe<=(seqn->start+seqn->len))) {
+ seqn->start = cutframe;
+ seqn->startstill = 0;
+ seqn->startofs = 0;
+ seqn->anim_startofs += cutframe - ts.start;
+ seqn->anim_endofs = ts.endofs;
+ seqn->endstill = ts.endstill;
+ }
+
+ /* strips with extended stillframes after */
+ else if (((seqn->start+seqn->len) < cutframe) && (seqn->endstill)) {
+ seqn->start = cutframe;
+ seqn->startofs = 0;
+ seqn->anim_startofs += ts.len-1;
+ seqn->endstill = ts.enddisp - cutframe -1;
+ seqn->startstill = 0;
+ }
+
+ reload_sequence_new_file(scene, seqn);
+ calc_sequence(seqn);
+ }
+ return seqn;
+}
+
+static Sequence *cut_seq_soft(Scene *scene, Sequence * seq, int cutframe)
+{
+ TransSeq ts;
+ Sequence *seqn = 0;
+ int skip_dup = FALSE;
+
+ /* backup values */
+ ts.start= seq->start;
+ ts.machine= seq->machine;
+ ts.startstill= seq->startstill;
+ ts.endstill= seq->endstill;
+ ts.startdisp= seq->startdisp;
+ ts.enddisp= seq->enddisp;
+ ts.startofs= seq->startofs;
+ ts.endofs= seq->endofs;
+ ts.len= seq->len;
+
+ /* First Strip! */
+ /* strips with extended stillfames before */
+
+ if ((seq->startstill) && (cutframe <seq->start)) {
+ /* don't do funny things with METAs ... */
+ if (seq->type == SEQ_META) {
+ skip_dup = TRUE;
+ seq->startstill = seq->start - cutframe;
+ } else {
+ seq->start= cutframe -1;
+ seq->startstill= cutframe -seq->startdisp -1;
+ seq->endofs = seq->len - 1;
+ seq->endstill= 0;
+ }
+ }
+ /* normal strip */
+ else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) {
+ seq->endofs = (seq->start+seq->len) - cutframe;
+ }
+ /* strips with extended stillframes after */
+ else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
+ seq->endstill -= seq->enddisp - cutframe;
+ /* don't do funny things with METAs ... */
+ if (seq->type == SEQ_META) {
+ skip_dup = TRUE;
+ }
+ }
+
+ calc_sequence(seq);
+
+ if (!skip_dup) {
+ /* Duplicate AFTER the first change */
+ seqn = deep_dupli_seq(seq);
+ }
+
+ if (seqn) {
+ seqn->flag |= SELECT;
+
+ /* Second Strip! */
+ /* strips with extended stillframes before */
+ if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
+ seqn->start = ts.start;
+ seqn->startstill= ts.start- cutframe;
+ seqn->endofs = ts.endofs;
+ seqn->endstill = ts.endstill;
+ }
+
+ /* normal strip */
+ else if ((cutframe>=seqn->start)&&(cutframe<=(seqn->start+seqn->len))) {
+ seqn->startstill = 0;
+ seqn->startofs = cutframe - ts.start;
+ seqn->endofs = ts.endofs;
+ seqn->endstill = ts.endstill;
+ }
+
+ /* strips with extended stillframes after */
+ else if (((seqn->start+seqn->len) < cutframe) && (seqn->endstill)) {
+ seqn->start = cutframe - ts.len +1;
+ seqn->startofs = ts.len-1;
+ seqn->endstill = ts.enddisp - cutframe -1;
+ seqn->startstill = 0;
+ }
+
+ calc_sequence(seqn);
+ }
+ return seqn;
+}
+
+
+/* like duplicate, but only duplicate and cut overlapping strips,
+ * strips to the left of the cutframe are ignored and strips to the right are moved into the new list */
+static int cut_seq_list(Scene *scene, ListBase *old, ListBase *new, int cutframe,
+ Sequence * (*cut_seq)(Scene *, Sequence *, int))
+{
+ int did_something = FALSE;
+ Sequence *seq, *seq_next;
+
+ seq= old->first;
+
+ while(seq) {
+ seq_next = seq->next; /* we need this because we may remove seq */
+
+ seq->tmp= NULL;
+ if(seq->flag & SELECT) {
+ if(cutframe > seq->startdisp &&
+ cutframe < seq->enddisp) {
+ Sequence * seqn = cut_seq(scene, seq, cutframe);
+ if (seqn) {
+ BLI_addtail(new, seqn);
+ }
+ did_something = TRUE;
+ } else if (seq->enddisp <= cutframe) {
+ /* do nothing */
+ } else if (seq->startdisp >= cutframe) {
+ /* move into new list */
+ BLI_remlink(old, seq);
+ BLI_addtail(new, seq);
+ }
+ }
+ seq = seq_next;
+ }
+ return did_something;
+}
+
+int insert_gap(Scene *scene, int gap, int cfra)
+{
+ Sequence *seq;
+ Editing *ed= seq_give_editing(scene, FALSE);
+ int done=0;
+
+ /* all strips >= cfra are shifted */
+
+ if(ed==NULL) return 0;
+
+ SEQP_BEGIN(ed, seq) {
+ if(seq->startdisp >= cfra) {
+ seq->start+= gap;
+ calc_sequence(seq);
+ done= 1;
+ }
+ }
+ SEQ_END
+
+ return done;
+}
+
+void touch_seq_files(Scene *scene)
+{
+ Sequence *seq;
+ Editing *ed= seq_give_editing(scene, FALSE);
+ char str[256];
+
+ /* touch all strips with movies */
+
+ if(ed==NULL) return;
+
+ if(okee("Touch and print selected movies")==0) return;
+
+ waitcursor(1);
+
+ SEQP_BEGIN(ed, seq) {
+ if(seq->flag & SELECT) {
+ if(seq->type==SEQ_MOVIE) {
+ if(seq->strip && seq->strip->stripdata) {
+ BLI_make_file_string(G.sce, str, seq->strip->dir, seq->strip->stripdata->name);
+ BLI_touch(seq->name);
+ }
+ }
+
+ }
+ }
+ SEQ_END
+
+ waitcursor(0);
+}
+
+void set_filter_seq(Scene *scene)
+{
+ Sequence *seq;
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+
+ if(ed==NULL) return;
+
+ if(okee("Set Deinterlace")==0) return;
+
+ SEQP_BEGIN(ed, seq) {
+ if(seq->flag & SELECT) {
+ if(seq->type==SEQ_MOVIE) {
+ seq->flag |= SEQ_FILTERY;
+ reload_sequence_new_file(scene, seq);
+ }
+
+ }
+ }
+ SEQ_END
+
+}
+
+void seq_remap_paths(Scene *scene)
+{
+ Sequence *seq, *last_seq = get_last_seq(scene);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ char from[FILE_MAX], to[FILE_MAX], stripped[FILE_MAX];
+
+
+ if(last_seq==NULL)
+ return;
+
+ BLI_strncpy(from, last_seq->strip->dir, FILE_MAX);
+// XXX if (0==sbutton(from, 0, sizeof(from)-1, "From: "))
+// return;
+
+ strcpy(to, from);
+// XXX if (0==sbutton(to, 0, sizeof(to)-1, "To: "))
+// return;
+
+ if (strcmp(to, from)==0)
+ return;
+
+ SEQP_BEGIN(ed, seq) {
+ if(seq->flag & SELECT) {
+ if(strncmp(seq->strip->dir, from, strlen(from))==0) {
+ printf("found %s\n", seq->strip->dir);
+
+ /* strip off the beginning */
+ stripped[0]= 0;
+ BLI_strncpy(stripped, seq->strip->dir + strlen(from), FILE_MAX);
+
+ /* new path */
+ BLI_strncpy(seq->strip->dir, to, FILE_MAX);
+ strcat(seq->strip->dir, stripped);
+ printf("new %s\n", seq->strip->dir);
+ }
+ }
+ }
+ SEQ_END
+
+}
+
+
+void no_gaps(Scene *scene)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ int cfra, first= 0, done;
+
+
+ if(ed==NULL) return;
+
+ for(cfra= CFRA; cfra<=EFRA; cfra++) {
+ if(first==0) {
+ if( evaluate_seq_frame(scene, cfra) ) first= 1;
+ }
+ else {
+ done= 1;
+ while( evaluate_seq_frame(scene, cfra) == 0) {
+ done= insert_gap(scene, -1, cfra);
+ if(done==0) break;
+ }
+ if(done==0) break;
+ }
+ }
+
+}
+
+#if 0
+static int seq_get_snaplimit(View2D *v2d)
+{
+ /* fake mouse coords to get the snap value
+ a bit lazy but its only done once pre transform */
+ float xmouse, ymouse, x;
+ short mval[2] = {24, 0}; /* 24 screen px snap */
+
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
+ x = xmouse;
+ mval[0] = 0;
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
+ return (int)(x - xmouse);
+}
+#endif
+
+void seq_snap(Scene *scene, short event)
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+
+
+ if(ed==NULL) return;
+
+ /* problem: contents of meta's are all shifted to the same position... */
+
+ /* also check metas */
+ SEQP_BEGIN(ed, seq) {
+ if (seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK) &&
+ seq_tx_test(seq)) {
+ if((seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))==0) {
+ seq->start= CFRA-seq->startofs+seq->startstill;
+ } else {
+ if(seq->flag & SEQ_LEFTSEL) {
+ seq_tx_set_final_left(seq, CFRA);
+ } else { /* SEQ_RIGHTSEL */
+ seq_tx_set_final_right(seq, CFRA);
+ }
+ seq_tx_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
+ }
+ calc_sequence(seq);
+ }
+ }
+ SEQ_END
+
+ /* test for effects and overlap */
+ SEQP_BEGIN(ed, seq) {
+ if(seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK)) {
+ seq->flag &= ~SEQ_OVERLAP;
+ if( seq_test_overlap(ed->seqbasep, seq) ) {
+ shuffle_seq(ed->seqbasep, seq);
+ }
+ }
+ else if(seq->type & SEQ_EFFECT) {
+ if(seq->seq1 && (seq->seq1->flag & SELECT))
+ calc_sequence(seq);
+ else if(seq->seq2 && (seq->seq2->flag & SELECT))
+ calc_sequence(seq);
+ else if(seq->seq3 && (seq->seq3->flag & SELECT))
+ calc_sequence(seq);
+ }
+ }
+ SEQ_END;
+
+ /* as last: */
+ sort_seq(scene);
+
+}
+
+void seq_snap_menu(Scene *scene)
+{
+ short event;
+
+ event= pupmenu("Snap %t|To Current Frame%x1");
+ if(event < 1) return;
+
+ seq_snap(scene, event);
+}
+
+/* Operator functions */
+
+static int sequencer_mute_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+ int selected;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ selected= RNA_enum_is_equal(op->ptr, "type", "SELECTED");
+
+
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ if ((seq->flag & SEQ_LOCK)==0) {
+ if(selected){ /* mute unselected */
+ if (seq->flag & SELECT) {
+ seq->flag |= SEQ_MUTE;
+ }
+ }
+ else {
+ if ((seq->flag & SELECT)==0) {
+ seq->flag |= SEQ_MUTE;
+ }
+ }
+ }
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_mute(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mute Strips";
+ ot->idname= "SEQUENCER_OT_mute";
+
+ /* api callbacks */
+ ot->exec= sequencer_mute_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", sequencer_prop_operate_types, SEQ_SELECTED, "Type", "");
+}
+
+
+/* unmute operator */
+static int sequencer_unmute_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+ int selected;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ selected= RNA_enum_is_equal(op->ptr, "type", "SELECTED");
+
+
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ if ((seq->flag & SEQ_LOCK)==0) {
+ if(selected){ /* unmute unselected */
+ if (seq->flag & SELECT) {
+ seq->flag &= ~SEQ_MUTE;
+ }
+ }
+ else {
+ if ((seq->flag & SELECT)==0) {
+ seq->flag &= ~SEQ_MUTE;
+ }
+ }
+ }
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_unmute(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "UnMute Strips";
+ ot->idname= "SEQUENCER_OT_unmute";
+
+ /* api callbacks */
+ ot->exec= sequencer_unmute_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", sequencer_prop_operate_types, SEQ_SELECTED, "Type", "");
+}
+
+
+/* lock operator */
+static int sequencer_lock_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ if (seq->flag & SELECT) {
+ seq->flag |= SEQ_LOCK;
+ }
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_lock(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Lock Strips";
+ ot->idname= "SEQUENCER_OT_lock";
+
+ /* api callbacks */
+ ot->exec= sequencer_lock_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* unlock operator */
+static int sequencer_unlock_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ if (seq->flag & SELECT) {
+ seq->flag &= ~SEQ_LOCK;
+ }
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_unlock(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "UnLock Strips";
+ ot->idname= "SEQUENCER_OT_unlock";
+
+ /* api callbacks */
+ ot->exec= sequencer_unlock_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* reload operator */
+static int sequencer_reload_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ if(seq->flag & SELECT) {
+ update_changed_seq_and_deps(scene, seq, 0, 1);
+ }
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_reload(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Reload Strips";
+ ot->idname= "SEQUENCER_OT_reload";
+
+ /* api callbacks */
+ ot->exec= sequencer_reload_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* reload operator */
+static int sequencer_refresh_all_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ free_imbuf_seq(&ed->seqbase);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_refresh_all(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Refresh Sequencer";
+ ot->idname= "SEQUENCER_OT_refresh_all";
+
+ /* api callbacks */
+ ot->exec= sequencer_refresh_all_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* cut operator */
+static EnumPropertyItem prop_cut_types[] = {
+ {SEQ_CUT_SOFT, "SOFT", "Soft", ""},
+ {SEQ_CUT_HARD, "HARD", "Hard", ""},
+ {0, NULL, NULL, NULL}
+};
+
+static int sequencer_cut_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ int cut_side, cut_hard, cut_frame;
+
+ ListBase newlist;
+ int changed;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ cut_frame= RNA_int_get(op->ptr, "frame");
+ cut_hard= RNA_enum_get(op->ptr, "type");
+ cut_side= RNA_enum_get(op->ptr, "side");
+
+ newlist.first= newlist.last= NULL;
+
+ if (cut_hard==SEQ_CUT_HARD) {
+ changed = cut_seq_list(scene,
+ ed->seqbasep, &newlist, cut_frame, cut_seq_hard);
+ } else {
+ changed = cut_seq_list(scene,
+ ed->seqbasep, &newlist, cut_frame, cut_seq_soft);
+ }
+
+ if (newlist.first) { /* got new strips ? */
+ Sequence *seq;
+ addlisttolist(ed->seqbasep, &newlist);
+
+ if (cut_side != SEQ_SIDE_BOTH) {
+ SEQP_BEGIN(ed, seq) {
+ if (cut_side==SEQ_SIDE_LEFT) {
+ if ( seq->startdisp >= cut_frame ) {
+ seq->flag &= SEQ_DESEL;
+ }
+ } else {
+ if ( seq->enddisp <= cut_frame ) {
+ seq->flag &= SEQ_DESEL;
+ }
+ }
+ }
+ SEQ_END;
+ }
+ /* as last: */
+ sort_seq(scene);
+ }
+
+ if (changed) {
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+
+static int sequencer_cut_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar= CTX_wm_region(C);
+ View2D *v2d= UI_view2d_fromcontext(C);
+
+ int cut_side, cut_frame;
+
+ cut_frame= CFRA;
+ cut_side= mouse_frame_side(v2d, event->x - ar->winrct.xmin, cut_frame);
+
+ RNA_int_set(op->ptr, "frame", cut_frame);
+ RNA_enum_set(op->ptr, "side", cut_side);
+ /*RNA_enum_set(op->ptr, "type", cut_hard); */ /*This type is set from the key shortcut */
+
+ return sequencer_cut_exec(C, op);
+}
+
+
+void SEQUENCER_OT_cut(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Cut Strips";
+ ot->idname= "SEQUENCER_OT_cut";
+
+ /* api callbacks */
+ ot->invoke= sequencer_cut_invoke;
+ ot->exec= sequencer_cut_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be cut", INT_MIN, INT_MAX);
+ RNA_def_enum(ot->srna, "type", prop_cut_types, SEQ_CUT_SOFT, "Type", "the type of cut operation to perform on strips");
+ RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side that remains selected after cutting");
+}
+
+/* duplicate operator */
+static int sequencer_add_duplicate_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ ListBase new= {NULL, NULL};
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ recurs_dupli_seq(scene, ed->seqbasep, &new);
+ addlisttolist(ed->seqbasep, &new);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+static int sequencer_add_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sequencer_add_duplicate_exec(C, op);
+
+ RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
+ WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_duplicate_add(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Add Duplicate";
+ ot->idname= "SEQUENCER_OT_duplicate_add";
+
+ /* api callbacks */
+ ot->invoke= sequencer_add_duplicate_invoke;
+ ot->exec= sequencer_add_duplicate_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* to give to transform */
+ RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+}
+
+/* delete operator */
+static int sequencer_delete_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+ MetaStack *ms;
+ int nothingSelected = TRUE;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ seq=get_last_seq(scene);
+ if (seq && seq->flag & SELECT) { /* avoid a loop since this is likely to be selected */
+ nothingSelected = FALSE;
+ } else {
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (seq->flag & SELECT) {
+ nothingSelected = FALSE;
+ break;
+ }
+ }
+ }
+
+ if (nothingSelected)
+ return OPERATOR_FINISHED;
+
+ /* free imbufs of all dependent strips */
+ for(seq=ed->seqbasep->first; seq; seq=seq->next)
+ if(seq->flag & SELECT)
+ update_changed_seq_and_deps(scene, seq, 1, 0);
+
+ /* for effects, try to find a replacement input */
+ for(seq=ed->seqbasep->first; seq; seq=seq->next)
+ if((seq->type & SEQ_EFFECT) && !(seq->flag & SELECT))
+ del_seq_find_replace_recurs(scene, seq);
+
+ /* delete all selected strips */
+ recurs_del_seq_flag(scene, ed->seqbasep, SELECT, 0);
+
+ /* updates lengths etc */
+ seq= ed->seqbasep->first;
+ while(seq) {
+ calc_sequence(seq);
+ seq= seq->next;
+ }
+
+ /* free parent metas */
+ ms= ed->metastack.last;
+ while(ms) {
+ ms->parseq->strip->len= 0; /* force new alloc */
+ calc_sequence(ms->parseq);
+ ms= ms->prev;
+ }
+
+ //ED_area_tag_redraw(CTX_wm_area(C));
+ WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, NULL); /* redraw other sequencer views */
+
+ return OPERATOR_FINISHED;
+}
+
+
+void SEQUENCER_OT_delete(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name= "Erase Strips";
+ ot->idname= "SEQUENCER_OT_delete";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= sequencer_delete_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+/* separate_images operator */
+static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ Sequence *seq, *seq_new, *seq_next;
+ Strip *strip_new;
+ StripElem *se, *se_new;
+ int start_ofs, cfra, frame_end;
+ static int step= 1;
+
+// add_numbut(0, NUM|INT, "Image Duration:", 1, 256, &step, NULL);
+// if (!do_clever_numbuts("Separate Images", 1, REDRAW))
+// return;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ seq= ed->seqbasep->first;
+
+ while (seq) {
+ if((seq->flag & SELECT) && (seq->type == SEQ_IMAGE) && (seq->len > 1)) {
+ /* remove seq so overlap tests dont conflict,
+ see seq_free_sequence below for the real free'ing */
+ seq_next = seq->next;
+ BLI_remlink(ed->seqbasep, seq);
+ if(seq->ipo) seq->ipo->id.us--;
+
+ start_ofs = cfra = seq_tx_get_final_left(seq, 0);
+ frame_end = seq_tx_get_final_right(seq, 0);
+
+ while (cfra < frame_end) {
+ /* new seq */
+ se = give_stripelem(seq, cfra);
+
+ seq_new= alloc_sequence(ed->seqbasep, start_ofs, seq->machine);
+ seq_new->type= SEQ_IMAGE;
+ seq_new->len = 1;
+ seq_new->endstill = step-1;
+
+ /* new strip */
+ seq_new->strip= strip_new= MEM_callocN(sizeof(Strip)*1, "strip");
+ strip_new->len= 1;
+ strip_new->us= 1;
+ strncpy(strip_new->dir, seq->strip->dir, FILE_MAXDIR-1);
+
+ /* new stripdata */
+ strip_new->stripdata= se_new= MEM_callocN(sizeof(StripElem)*1, "stripelem");
+ strncpy(se_new->name, se->name, FILE_MAXFILE-1);
+ calc_sequence(seq_new);
+ seq_new->flag &= ~SEQ_OVERLAP;
+ if (seq_test_overlap(ed->seqbasep, seq_new)) {
+ shuffle_seq(ed->seqbasep, seq_new);
+ }
+
+ cfra++;
+ start_ofs += step;
+ }
+
+ seq_free_sequence(ed, seq);
+ seq = seq->next;
+ } else {
+ seq = seq->next;
+ }
+ }
+
+ /* as last: */
+ sort_seq(scene);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+
+void SEQUENCER_OT_images_separate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Separate Images";
+ ot->idname= "SEQUENCER_OT_images_separate";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= sequencer_separate_images_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+/* META Operators */
+
+/* separate_meta_toggle operator */
+static int sequencer_meta_toggle_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *last_seq= get_last_seq(scene);
+ MetaStack *ms;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ if(last_seq && last_seq->type==SEQ_META && last_seq->flag & SELECT) {
+ /* Enter Metastrip */
+ ms= MEM_mallocN(sizeof(MetaStack), "metastack");
+ BLI_addtail(&ed->metastack, ms);
+ ms->parseq= last_seq;
+ ms->oldbasep= ed->seqbasep;
+
+ ed->seqbasep= &last_seq->seqbase;
+
+ set_last_seq(scene, NULL);
+
+ }
+ else {
+ /* Exit Metastrip (if possible) */
+
+ Sequence *seq;
+
+ if(ed->metastack.first==NULL)
+ return OPERATOR_CANCELLED;
+
+ ms= ed->metastack.last;
+ BLI_remlink(&ed->metastack, ms);
+
+ ed->seqbasep= ms->oldbasep;
+
+ /* recalc all: the meta can have effects connected to it */
+ for(seq= ed->seqbasep->first; seq; seq= seq->next)
+ calc_sequence(seq);
+
+ set_last_seq(scene, ms->parseq);
+
+ ms->parseq->flag |= SELECT;
+ recurs_sel_seq(ms->parseq);
+
+ MEM_freeN(ms);
+
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_meta_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Toggle Meta Strip";
+ ot->idname= "SEQUENCER_OT_meta_toggle";
+
+ /* api callbacks */
+ ot->exec= sequencer_meta_toggle_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+/* separate_meta_make operator */
+static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ Sequence *seq, *seqm, *next;
+
+ int tot;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ /* is there more than 1 select */
+ tot= 0;
+ seq= ed->seqbasep->first;
+ while(seq) {
+ if(seq->flag & SELECT) {
+ tot++;
+ if (seq->type == SEQ_RAM_SOUND) {
+ BKE_report(op->reports, RPT_ERROR, "Can't make Meta Strip from audio");
+ return OPERATOR_CANCELLED;;
+ }
+ }
+ seq= seq->next;
+ }
+ if(tot < 1) return OPERATOR_CANCELLED;;
+
+
+ /* test relationships */
+ seq= ed->seqbasep->first;
+ while(seq) {
+ if(seq->flag & SELECT) {
+ if(seq->type & SEQ_EFFECT) {
+ if(seq->seq1 &&
+ (seq->seq1->flag & SELECT)==0) tot= 0;
+ if(seq->seq2 &&
+ (seq->seq2->flag & SELECT)==0) tot= 0;
+ if(seq->seq3 &&
+ (seq->seq3->flag & SELECT)==0) tot= 0;
+ }
+ }
+ else if(seq->type & SEQ_EFFECT) {
+ if(seq->seq1 &&
+ (seq->seq1->flag & SELECT)) tot= 0;
+ if(seq->seq2 &&
+ (seq->seq2->flag & SELECT)) tot= 0;
+ if(seq->seq3 &&
+ (seq->seq3->flag & SELECT)) tot= 0;
+ }
+ if(tot==0) break;
+ seq= seq->next;
+ }
+
+ if(tot==0) {
+ BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* remove all selected from main list, and put in meta */
+
+ seqm= alloc_sequence(ed->seqbasep, 1, 1);
+ seqm->type= SEQ_META;
+ seqm->flag= SELECT;
+
+ seq= ed->seqbasep->first;
+ while(seq) {
+ next= seq->next;
+ if(seq!=seqm && (seq->flag & SELECT)) {
+ BLI_remlink(ed->seqbasep, seq);
+ BLI_addtail(&seqm->seqbase, seq);
+ }
+ seq= next;
+ }
+ calc_sequence(seqm);
+
+ seqm->strip= MEM_callocN(sizeof(Strip), "metastrip");
+ seqm->strip->len= seqm->len;
+ seqm->strip->us= 1;
+
+ set_last_seq(scene, seqm);
+
+ if( seq_test_overlap(ed->seqbasep, seqm) ) shuffle_seq(ed->seqbasep, seqm);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_meta_make(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Make Meta Strip";
+ ot->idname= "SEQUENCER_OT_meta_make";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= sequencer_meta_make_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
+{
+ if (seq == seqm) return 1;
+ else if (seq->seq1 && seq_depends_on_meta(seq->seq1, seqm)) return 1;
+ else if (seq->seq2 && seq_depends_on_meta(seq->seq2, seqm)) return 1;
+ else if (seq->seq3 && seq_depends_on_meta(seq->seq3, seqm)) return 1;
+ else return 0;
+}
+
+/* separate_meta_make operator */
+static int sequencer_meta_separate_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ Sequence *seq, *last_seq = get_last_seq(scene); /* last_seq checks ed==NULL */
+
+ if(last_seq==NULL || last_seq->type!=SEQ_META)
+ return OPERATOR_CANCELLED;
+
+ addlisttolist(ed->seqbasep, &last_seq->seqbase);
+
+ last_seq->seqbase.first= 0;
+ last_seq->seqbase.last= 0;
+
+ BLI_remlink(ed->seqbasep, last_seq);
+ seq_free_sequence(ed, last_seq);
+
+ /* emtpy meta strip, delete all effects depending on it */
+ for(seq=ed->seqbasep->first; seq; seq=seq->next)
+ if((seq->type & SEQ_EFFECT) && seq_depends_on_meta(seq, last_seq))
+ seq->flag |= SEQ_FLAG_DELETE;
+
+ recurs_del_seq_flag(scene, ed->seqbasep, SEQ_FLAG_DELETE, 0);
+
+ /* test for effects and overlap */
+ SEQP_BEGIN(ed, seq) {
+ if(seq->flag & SELECT) {
+ seq->flag &= ~SEQ_OVERLAP;
+ if( seq_test_overlap(ed->seqbasep, seq) ) {
+ shuffle_seq(ed->seqbasep, seq);
+ }
+ }
+ }
+ SEQ_END;
+
+ sort_seq(scene);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "UnMeta Strip";
+ ot->idname= "SEQUENCER_OT_meta_separate";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= sequencer_meta_separate_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* view_all operator */
+static int sequencer_view_all_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ bScreen *sc= CTX_wm_screen(C);
+ ScrArea *area= CTX_wm_area(C);
+ ARegion *ar= CTX_wm_region(C);
+ SpaceSeq *sseq= area->spacedata.first;
+ View2D *v2d= UI_view2d_fromcontext(C);
+
+ if (sseq->mainb==SEQ_DRAW_SEQUENCE) {
+ v2d->cur= v2d->tot;
+ UI_view2d_curRect_validate(v2d);
+ UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
+ } else {
+ /* Like zooming on an image view */
+ float zoomX, zoomY;
+ int width, height, imgwidth, imgheight;
+
+ width = ar->winx;
+ height = ar->winy;
+
+ seq_reset_imageofs(sseq);
+
+ imgwidth= (scene->r.size*scene->r.xsch)/100;
+ imgheight= (scene->r.size*scene->r.ysch)/100;
+
+ /* Apply aspect, dosnt need to be that accurate */
+ imgwidth= (int)(imgwidth * ((float)scene->r.xasp / (float)scene->r.yasp));
+
+ if (((imgwidth >= width) || (imgheight >= height)) &&
+ ((width > 0) && (height > 0))) {
+
+ /* Find the zoom value that will fit the image in the image space */
+ zoomX = ((float)width) / ((float)imgwidth);
+ zoomY = ((float)height) / ((float)imgheight);
+ sseq->zoom= (zoomX < zoomY) ? zoomX : zoomY;
+
+ sseq->zoom = 1.0f / power_of_2(1/ MIN2(zoomX, zoomY) );
+ }
+ else {
+ sseq->zoom= 1.0f;
+ }
+ }
+
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_view_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View All";
+ ot->idname= "SEQUENCER_OT_view_all";
+
+ /* api callbacks */
+ ot->exec= sequencer_view_all_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
+
+
+/* view_all operator */
+static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ View2D *v2d= UI_view2d_fromcontext(C);
+ ScrArea *area= CTX_wm_area(C);
+ bScreen *sc= CTX_wm_screen(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+
+ int xmin= MAXFRAME*2;
+ int xmax= -MAXFRAME*2;
+ int ymin= MAXSEQ+1;
+ int ymax= 0;
+ int orig_height;
+ int ymid;
+ int ymargin= 1;
+ int xmargin= FPS;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ for(seq=ed->seqbasep->first; seq; seq=seq->next) {
+ if(seq->flag & SELECT) {
+ xmin= MIN2(xmin, seq->startdisp);
+ xmax= MAX2(xmax, seq->enddisp);
+
+ ymin= MIN2(ymin, seq->machine);
+ ymax= MAX2(ymax, seq->machine);
+ }
+ }
+
+ if (ymax != 0) {
+
+ xmax += xmargin;
+ xmin -= xmargin;
+ ymax += ymargin;
+ ymin -= ymargin;
+
+ orig_height= v2d->cur.ymax - v2d->cur.ymin;
+
+ v2d->cur.xmin= xmin;
+ v2d->cur.xmax= xmax;
+
+ v2d->cur.ymin= ymin;
+ v2d->cur.ymax= ymax;
+
+ /* only zoom out vertically */
+ if (orig_height > v2d->cur.ymax - v2d->cur.ymin) {
+ ymid= (v2d->cur.ymax + v2d->cur.ymin) / 2;
+
+ v2d->cur.ymin= ymid - (orig_height/2);
+ v2d->cur.ymax= ymid + (orig_height/2);
+ }
+
+ UI_view2d_curRect_validate(v2d);
+ UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_view_selected(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "View Selected";
+ ot->idname= "SEQUENCER_OT_view_selected";
+
+ /* api callbacks */
+ ot->exec= sequencer_view_selected_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+}
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
new file mode 100644
index 00000000000..1f78c4d5199
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -0,0 +1,154 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_SEQUENCER_INTERN_H
+#define ED_SEQUENCER_INTERN_H
+
+#include "RNA_access.h"
+#include "DNA_sequence_types.h"
+
+/* internal exports only */
+
+struct Sequence;
+struct bContext;
+struct rctf;
+struct SpaceSeq;
+struct ScrArea;
+struct ARegion;
+struct ARegionType;
+struct Scene;
+
+/* space_sequencer.c */
+struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa);
+
+/* sequencer_header.c */
+// void sequencer_header_buttons(const struct bContext *C, struct ARegion *ar);
+
+/* sequencer_draw.c */
+void drawseqspace(const struct bContext *C, struct ARegion *ar);
+void seq_reset_imageofs(struct SpaceSeq *sseq);
+
+/* sequencer_edit.c */
+struct View2D;
+int check_single_seq(struct Sequence *seq);
+int seq_tx_get_final_left(struct Sequence *seq, int metaclip);
+int seq_tx_get_final_right(struct Sequence *seq, int metaclip);
+void seq_rectf(struct Sequence *seq, struct rctf *rectf);
+void boundbox_seq(struct Scene *scene, struct rctf *rect);
+struct Sequence *get_last_seq(struct Scene *scene);
+struct Sequence *find_nearest_seq(struct Scene *scene, struct View2D *v2d, int *hand, short mval[2]);
+struct Sequence *find_neighboring_sequence(struct Scene *scene, struct Sequence *test, int lr, int sel);
+void deselect_all_seq(struct Scene *scene);
+void recurs_sel_seq(struct Sequence *seqm);
+int event_to_efftype(int event);
+void set_last_seq(struct Scene *scene, struct Sequence *seq);
+int seq_effect_find_selected(struct Scene *scene, struct Sequence *activeseq, int type, struct Sequence **selseq1, struct Sequence **selseq2, struct Sequence **selseq3, char **error_str);
+struct Sequence *alloc_sequence(struct ListBase *lb, int cfra, int machine);
+
+/* externs */
+extern EnumPropertyItem sequencer_prop_effect_types[];
+extern EnumPropertyItem prop_side_types[];
+
+/* operators */
+struct wmOperatorType;
+struct wmWindowManager;
+void SEQUENCER_OT_cut(struct wmOperatorType *ot);
+void SEQUENCER_OT_mute(struct wmOperatorType *ot);
+void SEQUENCER_OT_unmute(struct wmOperatorType *ot);
+void SEQUENCER_OT_lock(struct wmOperatorType *ot);
+void SEQUENCER_OT_unlock(struct wmOperatorType *ot);
+void SEQUENCER_OT_reload(struct wmOperatorType *ot);
+void SEQUENCER_OT_refresh_all(struct wmOperatorType *ot);
+void SEQUENCER_OT_duplicate_add(struct wmOperatorType *ot);
+void SEQUENCER_OT_delete(struct wmOperatorType *ot);
+void SEQUENCER_OT_images_separate(struct wmOperatorType *ot);
+void SEQUENCER_OT_meta_toggle(struct wmOperatorType *ot);
+void SEQUENCER_OT_meta_make(struct wmOperatorType *ot);
+void SEQUENCER_OT_meta_separate(struct wmOperatorType *ot);
+
+void SEQUENCER_OT_view_all(struct wmOperatorType *ot);
+void SEQUENCER_OT_view_selected(struct wmOperatorType *ot);
+
+/* sequencer_select.c */
+void SEQUENCER_OT_select_all_toggle(struct wmOperatorType *ot);
+void SEQUENCER_OT_select(struct wmOperatorType *ot);
+void SEQUENCER_OT_select_more(struct wmOperatorType *ot);
+void SEQUENCER_OT_select_less(struct wmOperatorType *ot);
+void SEQUENCER_OT_select_linked(struct wmOperatorType *ot);
+void SEQUENCER_OT_select_linked_pick(struct wmOperatorType *ot);
+void SEQUENCER_OT_select_handles(struct wmOperatorType *ot);
+void SEQUENCER_OT_select_active_side(struct wmOperatorType *ot);
+void SEQUENCER_OT_select_border(struct wmOperatorType *ot);
+void SEQUENCER_OT_select_invert(struct wmOperatorType *ot);
+
+
+/* sequencer_select.c */
+void SEQUENCER_OT_scene_strip_add(struct wmOperatorType *ot);
+void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot);
+void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot);
+void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot);
+void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot);
+
+/* RNA enums, just to be more readable */
+enum {
+ SEQ_SIDE_NONE=0,
+ SEQ_SIDE_LEFT,
+ SEQ_SIDE_RIGHT,
+ SEQ_SIDE_BOTH,
+};
+enum {
+ SEQ_CUT_SOFT,
+ SEQ_CUT_HARD,
+};
+enum {
+ SEQ_SELECTED,
+ SEQ_UNSELECTED,
+};
+
+/* defines used internally */
+#define SEQ_ALLSEL (SELECT+SEQ_LEFTSEL+SEQ_RIGHTSEL)
+#define SEQ_DESEL ~SEQ_ALLSEL
+#define SCE_MARKERS 0 // XXX - dummy
+
+/* sequencer_ops.c */
+void sequencer_operatortypes(void);
+void sequencer_keymap(struct wmWindowManager *wm);
+
+/* sequencer_scope.c */
+struct ImBuf *make_waveform_view_from_ibuf(struct ImBuf * ibuf);
+struct ImBuf *make_sep_waveform_view_from_ibuf(struct ImBuf * ibuf);
+struct ImBuf *make_vectorscope_view_from_ibuf(struct ImBuf * ibuf);
+struct ImBuf *make_zebra_view_from_ibuf(struct ImBuf * ibuf, float perc);
+struct ImBuf *make_histogram_view_from_ibuf(struct ImBuf * ibuf);
+
+/* sequencer_buttons.c */
+
+void SEQUENCER_OT_properties(struct wmOperatorType *ot);
+void sequencer_buttons_register(struct ARegionType *art);
+
+#endif /* ED_SEQUENCER_INTERN_H */
+
diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c
new file mode 100644
index 00000000000..600ef87e1b3
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_ops.c
@@ -0,0 +1,185 @@
+
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "BIF_transform.h" /* transform keymap */
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+
+#include "sequencer_intern.h"
+
+
+/* ************************** registration **********************************/
+
+
+void sequencer_operatortypes(void)
+{
+ /* sequencer_edit.c */
+ WM_operatortype_append(SEQUENCER_OT_cut);
+ WM_operatortype_append(SEQUENCER_OT_mute);
+ WM_operatortype_append(SEQUENCER_OT_unmute);
+ WM_operatortype_append(SEQUENCER_OT_lock);
+ WM_operatortype_append(SEQUENCER_OT_unlock);
+ WM_operatortype_append(SEQUENCER_OT_reload);
+ WM_operatortype_append(SEQUENCER_OT_refresh_all);
+ WM_operatortype_append(SEQUENCER_OT_duplicate_add);
+ WM_operatortype_append(SEQUENCER_OT_delete);
+ WM_operatortype_append(SEQUENCER_OT_images_separate);
+ WM_operatortype_append(SEQUENCER_OT_meta_toggle);
+ WM_operatortype_append(SEQUENCER_OT_meta_make);
+ WM_operatortype_append(SEQUENCER_OT_meta_separate);
+
+ WM_operatortype_append(SEQUENCER_OT_view_all);
+ WM_operatortype_append(SEQUENCER_OT_view_selected);
+
+ /* sequencer_select.c */
+ WM_operatortype_append(SEQUENCER_OT_select_all_toggle);
+ WM_operatortype_append(SEQUENCER_OT_select_invert);
+ WM_operatortype_append(SEQUENCER_OT_select);
+ WM_operatortype_append(SEQUENCER_OT_select_more);
+ WM_operatortype_append(SEQUENCER_OT_select_less);
+ WM_operatortype_append(SEQUENCER_OT_select_linked_pick);
+ WM_operatortype_append(SEQUENCER_OT_select_linked);
+ WM_operatortype_append(SEQUENCER_OT_select_handles);
+ WM_operatortype_append(SEQUENCER_OT_select_active_side);
+ WM_operatortype_append(SEQUENCER_OT_select_border);
+
+ /* sequencer_add.c */
+ WM_operatortype_append(SEQUENCER_OT_scene_strip_add);
+ WM_operatortype_append(SEQUENCER_OT_movie_strip_add);
+ WM_operatortype_append(SEQUENCER_OT_sound_strip_add);
+ WM_operatortype_append(SEQUENCER_OT_image_strip_add);
+ WM_operatortype_append(SEQUENCER_OT_effect_strip_add);
+ WM_operatortype_append(SEQUENCER_OT_properties);
+}
+
+
+void sequencer_keymap(wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "Sequencer", SPACE_SEQ, 0);
+ wmKeymapItem *kmi;
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_properties", NKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_select_invert", IKEY, KM_PRESS, KM_CTRL, 0);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_cut", KKEY, KM_PRESS, 0, 0)->ptr, "type", SEQ_CUT_SOFT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_cut", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", SEQ_CUT_HARD);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_mute", HKEY, KM_PRESS, 0, 0)->ptr, "type", SEQ_SELECTED);
+ RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_mute", HKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", SEQ_UNSELECTED);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_unmute", HKEY, KM_PRESS, KM_ALT, 0)->ptr, "type", SEQ_SELECTED);
+ RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_unmute", HKEY, KM_PRESS, KM_ALT|KM_SHIFT, 0)->ptr, "type", SEQ_UNSELECTED);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_lock", LKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_unlock", HKEY, KM_PRESS, KM_SHIFT|KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_reload", RKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_duplicate_add", DKEY, KM_PRESS, KM_SHIFT, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_delete", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_delete", DELKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_images_separate", YKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_meta_toggle", TABKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_meta_make", MKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_meta_separate", MKEY, KM_PRESS, KM_ALT, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
+
+
+ /* Mouse selection, a bit verbose :/ */
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "linked_left", 1);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "linked_right", 1);
+
+ kmi= WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_CTRL|KM_ALT, 0);
+ RNA_boolean_set(kmi->ptr, "linked_left", 1);
+ RNA_boolean_set(kmi->ptr, "linked_right", 1);
+
+ kmi= WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT|KM_CTRL|KM_ALT, 0);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+ RNA_boolean_set(kmi->ptr, "linked_left", 1);
+ RNA_boolean_set(kmi->ptr, "linked_right", 1);
+
+ kmi= WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+ RNA_boolean_set(kmi->ptr, "linked_left", 1);
+
+ kmi= WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT|KM_ALT, 0);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+ RNA_boolean_set(kmi->ptr, "linked_right", 1);
+
+
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_select_linked_pick", LKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_select_linked_pick", LKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_select_border", BKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_verify_item(keymap, "ANIM_OT_change_frame", LEFTMOUSE, KM_PRESS, 0, 0);
+
+ transform_keymap_for_space(wm, keymap, SPACE_SEQ);
+}
+
diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c
new file mode 100644
index 00000000000..e26f445ae44
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_scopes.c
@@ -0,0 +1,701 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Peter Schlaile < peter [at] schlaile [dot] de >
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "BKE_utildefines.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "sequencer_intern.h"
+
+static void rgb_to_yuv(float rgb[3], float yuv[3])
+{
+ yuv[0]= 0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2];
+ yuv[1]= 0.492*(rgb[2] - yuv[0]);
+ yuv[2]= 0.877*(rgb[0] - yuv[0]);
+
+ /* Normalize */
+ yuv[1]*= 255.0/(122*2.0);
+ yuv[1]+= 0.5;
+
+ yuv[2]*= 255.0/(157*2.0);
+ yuv[2]+= 0.5;
+}
+
+static void scope_put_pixel(unsigned char* table, unsigned char * pos)
+{
+ char newval = table[*pos];
+ pos[0] = pos[1] = pos[2] = newval;
+ pos[3] = 255;
+}
+
+static void scope_put_pixel_single(unsigned char* table, unsigned char * pos,
+ int col)
+{
+ char newval = table[pos[col]];
+ pos[col] = newval;
+ pos[3] = 255;
+}
+
+static void wform_put_line(int w,
+ unsigned char * last_pos, unsigned char * new_pos)
+{
+ if (last_pos > new_pos) {
+ unsigned char* temp = new_pos;
+ new_pos = last_pos;
+ last_pos = temp;
+ }
+
+ while (last_pos < new_pos) {
+ if (last_pos[0] == 0) {
+ last_pos[0] = last_pos[1] = last_pos[2] = 32;
+ last_pos[3] = 255;
+ }
+ last_pos += 4*w;
+ }
+}
+
+static void wform_put_line_single(
+ int w, unsigned char * last_pos, unsigned char * new_pos, int col)
+{
+ if (last_pos > new_pos) {
+ unsigned char* temp = new_pos;
+ new_pos = last_pos;
+ last_pos = temp;
+ }
+
+ while (last_pos < new_pos) {
+ if (last_pos[col] == 0) {
+ last_pos[col] = 32;
+ last_pos[3] = 255;
+ }
+ last_pos += 4*w;
+ }
+}
+
+static void wform_put_border(unsigned char * tgt, int w, int h)
+{
+ int x, y;
+
+ for (x = 0; x < w; x++) {
+ unsigned char * p = tgt + 4 * x;
+ p[1] = p[3] = 255.0;
+ p[4 * w + 1] = p[4 * w + 3] = 255.0;
+ p = tgt + 4 * (w * (h - 1) + x);
+ p[1] = p[3] = 255.0;
+ p[-4 * w + 1] = p[-4 * w + 3] = 255.0;
+ }
+
+ for (y = 0; y < h; y++) {
+ unsigned char * p = tgt + 4 * w * y;
+ p[1] = p[3] = 255.0;
+ p[4 + 1] = p[4 + 3] = 255.0;
+ p = tgt + 4 * (w * y + w - 1);
+ p[1] = p[3] = 255.0;
+ p[-4 + 1] = p[-4 + 3] = 255.0;
+ }
+}
+
+static void wform_put_gridrow(unsigned char * tgt, float perc, int w, int h)
+{
+ int i;
+
+ tgt += (int) (perc/100.0 * h) * w * 4;
+
+ for (i = 0; i < w*2; i++) {
+ tgt[0] = 255;
+
+ tgt += 4;
+ }
+}
+
+static void wform_put_grid(unsigned char * tgt, int w, int h)
+{
+ wform_put_gridrow(tgt, 90.0, w, h);
+ wform_put_gridrow(tgt, 70.0, w, h);
+ wform_put_gridrow(tgt, 10.0, w, h);
+}
+
+static struct ImBuf *make_waveform_view_from_ibuf_byte(struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect, 0);
+ int x,y;
+ unsigned char* src = (unsigned char*) ibuf->rect;
+ unsigned char* tgt = (unsigned char*) rval->rect;
+ int w = ibuf->x + 3;
+ int h = 515;
+ float waveform_gamma = 0.2;
+ unsigned char wtable[256];
+
+ wform_put_grid(tgt, w, h);
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
+ waveform_gamma)*255);
+ }
+
+ for (y = 0; y < ibuf->y; y++) {
+ unsigned char * last_p = 0;
+
+ for (x = 0; x < ibuf->x; x++) {
+ unsigned char * rgb = src + 4 * (ibuf->x * y + x);
+ float v = 1.0 *
+ ( 0.299*rgb[0]
+ + 0.587*rgb[1]
+ + 0.114*rgb[2]) / 255.0;
+ unsigned char * p = tgt;
+ p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1);
+
+ scope_put_pixel(wtable, p);
+ p += 4 * w;
+ scope_put_pixel(wtable, p);
+
+ if (last_p != 0) {
+ wform_put_line(w, last_p, p);
+ }
+ last_p = p;
+ }
+ }
+
+ wform_put_border(tgt, w, h);
+
+ return rval;
+}
+
+static struct ImBuf *make_waveform_view_from_ibuf_float(struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect, 0);
+ int x,y;
+ float* src = ibuf->rect_float;
+ unsigned char* tgt = (unsigned char*) rval->rect;
+ int w = ibuf->x + 3;
+ int h = 515;
+ float waveform_gamma = 0.2;
+ unsigned char wtable[256];
+
+ wform_put_grid(tgt, w, h);
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
+ waveform_gamma)*255);
+ }
+
+ for (y = 0; y < ibuf->y; y++) {
+ unsigned char * last_p = 0;
+
+ for (x = 0; x < ibuf->x; x++) {
+ float * rgb = src + 4 * (ibuf->x * y + x);
+ float v = 1.0 *
+ ( 0.299*rgb[0]
+ + 0.587*rgb[1]
+ + 0.114*rgb[2]);
+ unsigned char * p = tgt;
+
+ CLAMP(v, 0.0, 1.0);
+
+ p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1);
+
+ scope_put_pixel(wtable, p);
+ p += 4 * w;
+ scope_put_pixel(wtable, p);
+
+ if (last_p != 0) {
+ wform_put_line(w, last_p, p);
+ }
+ last_p = p;
+ }
+ }
+
+ wform_put_border(tgt, w, h);
+
+ return rval;
+}
+
+struct ImBuf *make_waveform_view_from_ibuf(struct ImBuf * ibuf)
+{
+ if (ibuf->rect_float) {
+ return make_waveform_view_from_ibuf_float(ibuf);
+ } else {
+ return make_waveform_view_from_ibuf_byte(ibuf);
+ }
+}
+
+
+static struct ImBuf *make_sep_waveform_view_from_ibuf_byte(struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(
+ ibuf->x + 3, 515, 32, IB_rect, 0);
+ int x,y;
+ unsigned char* src = (unsigned char*) ibuf->rect;
+ unsigned char* tgt = (unsigned char*) rval->rect;
+ int w = ibuf->x + 3;
+ int sw = ibuf->x/3;
+ int h = 515;
+ float waveform_gamma = 0.2;
+ unsigned char wtable[256];
+
+ wform_put_grid(tgt, w, h);
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
+ waveform_gamma)*255);
+ }
+
+ for (y = 0; y < ibuf->y; y++) {
+ unsigned char * last_p[3] = {0,0,0};
+
+ for (x = 0; x < ibuf->x; x++) {
+ int c;
+ unsigned char * rgb = src + 4 * (ibuf->x * y + x);
+ for (c = 0; c < 3; c++) {
+ unsigned char * p = tgt;
+ p += 4 * (w * ((rgb[c] * (h - 3))/255 + 1)
+ + c * sw + x/3 + 1);
+
+ scope_put_pixel_single(wtable, p, c);
+ p += 4 * w;
+ scope_put_pixel_single(wtable, p, c);
+
+ if (last_p[c] != 0) {
+ wform_put_line_single(
+ w, last_p[c], p, c);
+ }
+ last_p[c] = p;
+ }
+ }
+ }
+
+ wform_put_border(tgt, w, h);
+
+ return rval;
+}
+
+static struct ImBuf *make_sep_waveform_view_from_ibuf_float(
+ struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(
+ ibuf->x + 3, 515, 32, IB_rect, 0);
+ int x,y;
+ float* src = ibuf->rect_float;
+ unsigned char* tgt = (unsigned char*) rval->rect;
+ int w = ibuf->x + 3;
+ int sw = ibuf->x/3;
+ int h = 515;
+ float waveform_gamma = 0.2;
+ unsigned char wtable[256];
+
+ wform_put_grid(tgt, w, h);
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
+ waveform_gamma)*255);
+ }
+
+ for (y = 0; y < ibuf->y; y++) {
+ unsigned char * last_p[3] = {0, 0, 0};
+
+ for (x = 0; x < ibuf->x; x++) {
+ int c;
+ float * rgb = src + 4 * (ibuf->x * y + x);
+ for (c = 0; c < 3; c++) {
+ unsigned char * p = tgt;
+ float v = rgb[c];
+
+ CLAMP(v, 0.0, 1.0);
+
+ p += 4 * (w * ((int) (v * (h - 3)) + 1)
+ + c * sw + x/3 + 1);
+
+ scope_put_pixel_single(wtable, p, c);
+ p += 4 * w;
+ scope_put_pixel_single(wtable, p, c);
+
+ if (last_p[c] != 0) {
+ wform_put_line_single(
+ w, last_p[c], p, c);
+ }
+ last_p[c] = p;
+ }
+ }
+ }
+
+ wform_put_border(tgt, w, h);
+
+ return rval;
+}
+
+struct ImBuf *make_sep_waveform_view_from_ibuf(struct ImBuf * ibuf)
+{
+ if (ibuf->rect_float) {
+ return make_sep_waveform_view_from_ibuf_float(ibuf);
+ } else {
+ return make_sep_waveform_view_from_ibuf_byte(ibuf);
+ }
+}
+
+static void draw_zebra_byte(struct ImBuf * src,struct ImBuf * ibuf, float perc)
+{
+ unsigned int limit = 255 * perc / 100.0;
+ unsigned char * p = (unsigned char*) src->rect;
+ unsigned char * o = (unsigned char*) ibuf->rect;
+ int x;
+ int y;
+
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ unsigned char r = *p++;
+ unsigned char g = *p++;
+ unsigned char b = *p++;
+ unsigned char a = *p++;
+
+ if (r >= limit || g >= limit || b >= limit) {
+ if (((x + y) & 0x08) != 0) {
+ r = 255 - r;
+ g = 255 - g;
+ b = 255 - b;
+ }
+ }
+ *o++ = r;
+ *o++ = g;
+ *o++ = b;
+ *o++ = a;
+ }
+ }
+}
+
+
+static void draw_zebra_float(struct ImBuf * src,struct ImBuf * ibuf,float perc)
+{
+ float limit = perc / 100.0;
+ float * p = src->rect_float;
+ unsigned char * o = (unsigned char*) ibuf->rect;
+ int x;
+ int y;
+
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ float r = *p++;
+ float g = *p++;
+ float b = *p++;
+ float a = *p++;
+
+ if (r >= limit || g >= limit || b >= limit) {
+ if (((x + y) & 0x08) != 0) {
+ r = -r;
+ g = -g;
+ b = -b;
+ }
+ }
+
+ *o++ = FTOCHAR(r);
+ *o++ = FTOCHAR(g);
+ *o++ = FTOCHAR(b);
+ *o++ = FTOCHAR(a);
+ }
+ }
+}
+
+struct ImBuf * make_zebra_view_from_ibuf(struct ImBuf * src, float perc)
+{
+ struct ImBuf * ibuf = IMB_allocImBuf(src->x, src->y, 32, IB_rect, 0);
+
+ if (src->rect_float) {
+ draw_zebra_float(src, ibuf, perc);
+ } else {
+ draw_zebra_byte(src, ibuf, perc);
+ }
+ return ibuf;
+}
+
+static void draw_histogram_marker(struct ImBuf * ibuf, int x)
+{
+ unsigned char * p = (unsigned char*) ibuf->rect;
+ int barh = ibuf->y * 0.1;
+ int i;
+
+ p += 4 * (x + ibuf->x * (ibuf->y - barh + 1));
+
+ for (i = 0; i < barh-1; i++) {
+ p[0] = p[1] = p[2] = 255;
+ p += ibuf->x * 4;
+ }
+}
+
+static void draw_histogram_bar(struct ImBuf * ibuf, int x,float val, int col)
+{
+ unsigned char * p = (unsigned char*) ibuf->rect;
+ int barh = ibuf->y * val * 0.9;
+ int i;
+
+ p += 4 * (x + ibuf->x);
+
+ for (i = 0; i < barh; i++) {
+ p[col] = 255;
+ p += ibuf->x * 4;
+ }
+}
+
+static struct ImBuf *make_histogram_view_from_ibuf_byte(
+ struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(515, 128, 32, IB_rect, 0);
+ int n,c,x,y;
+ unsigned char* src = (unsigned char*) ibuf->rect;
+
+ unsigned int bins[3][256];
+
+ memset(bins, 0, 3 * 256* sizeof(unsigned int));
+
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ bins[0][*src++]++;
+ bins[1][*src++]++;
+ bins[2][*src++]++;
+ src++;
+ }
+ }
+
+ n = 0;
+ for (c = 0; c < 3; c++) {
+ for (x = 0; x < 256; x++) {
+ if (bins[c][x] > n) {
+ n = bins[c][x];
+ }
+ }
+ }
+
+ for (c = 0; c < 3; c++) {
+ for (x = 0; x < 256; x++) {
+ draw_histogram_bar(rval, x*2+1,
+ ((float) bins[c][x])/n, c);
+ draw_histogram_bar(rval, x*2+2,
+ ((float) bins[c][x])/n, c);
+ }
+ }
+
+ wform_put_border((unsigned char*) rval->rect, rval->x, rval->y);
+
+ return rval;
+}
+
+static int get_bin_float(float f)
+{
+ if (f < -0.25) {
+ f = -0.25;
+ } else if (f > 1.25) {
+ f = 1.25;
+ }
+
+ return (int) (((f + 0.25) / 1.5) * 512);
+}
+
+static struct ImBuf *make_histogram_view_from_ibuf_float(
+ struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(515, 128, 32, IB_rect, 0);
+ int n,c,x,y;
+ float* src = ibuf->rect_float;
+
+ unsigned int bins[3][512];
+
+ memset(bins, 0, 3 * 256* sizeof(unsigned int));
+
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ bins[0][get_bin_float(*src++)]++;
+ bins[1][get_bin_float(*src++)]++;
+ bins[2][get_bin_float(*src++)]++;
+ src++;
+ }
+ }
+
+ draw_histogram_marker(rval, get_bin_float(0.0));
+ draw_histogram_marker(rval, get_bin_float(1.0));
+
+ n = 0;
+ for (c = 0; c < 3; c++) {
+ for (x = 0; x < 512; x++) {
+ if (bins[c][x] > n) {
+ n = bins[c][x];
+ }
+ }
+ }
+ for (c = 0; c < 3; c++) {
+ for (x = 0; x < 512; x++) {
+ draw_histogram_bar(rval, x+1, (float) bins[c][x]/n, c);
+ }
+ }
+
+ wform_put_border((unsigned char*) rval->rect, rval->x, rval->y);
+
+ return rval;
+}
+
+struct ImBuf *make_histogram_view_from_ibuf(struct ImBuf * ibuf)
+{
+ if (ibuf->rect_float) {
+ return make_histogram_view_from_ibuf_float(ibuf);
+ } else {
+ return make_histogram_view_from_ibuf_byte(ibuf);
+ }
+}
+
+static void vectorscope_put_cross(unsigned char r, unsigned char g,
+ unsigned char b,
+ char * tgt, int w, int h, int size)
+{
+ float rgb[3], yuv[3];
+ char * p;
+ int x = 0;
+ int y = 0;
+
+ rgb[0]= (float)r/255.0;
+ rgb[1]= (float)g/255.0;
+ rgb[2]= (float)b/255.0;
+ rgb_to_yuv(rgb, yuv);
+
+ p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1))
+ + (int) ((yuv[1] * (w - 3) + 1)));
+
+ if (r == 0 && g == 0 && b == 0) {
+ r = 255;
+ }
+
+ for (y = -size; y <= size; y++) {
+ for (x = -size; x <= size; x++) {
+ char * q = p + 4 * (y * w + x);
+ q[0] = r; q[1] = g; q[2] = b; q[3] = 255;
+ }
+ }
+}
+
+static struct ImBuf *make_vectorscope_view_from_ibuf_byte(struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(515, 515, 32, IB_rect, 0);
+ int x,y;
+ char* src = (char*) ibuf->rect;
+ char* tgt = (char*) rval->rect;
+ float rgb[3], yuv[3];
+ int w = 515;
+ int h = 515;
+ float scope_gamma = 0.2;
+ unsigned char wtable[256];
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
+ scope_gamma)*255);
+ }
+
+ for (x = 0; x <= 255; x++) {
+ vectorscope_put_cross(255 , 0,255 - x, tgt, w, h, 1);
+ vectorscope_put_cross(255 , x, 0, tgt, w, h, 1);
+ vectorscope_put_cross(255- x, 255, 0, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
+ vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
+ }
+
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ char * src1 = src + 4 * (ibuf->x * y + x);
+ char * p;
+
+ rgb[0]= (float)src1[0]/255.0;
+ rgb[1]= (float)src1[1]/255.0;
+ rgb[2]= (float)src1[2]/255.0;
+ rgb_to_yuv(rgb, yuv);
+
+ p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1))
+ + (int) ((yuv[1] * (w - 3) + 1)));
+ scope_put_pixel(wtable, (unsigned char*)p);
+ }
+ }
+
+ vectorscope_put_cross(0, 0, 0, tgt, w, h, 3);
+
+ return rval;
+}
+
+static struct ImBuf *make_vectorscope_view_from_ibuf_float(struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(515, 515, 32, IB_rect, 0);
+ int x,y;
+ float* src = ibuf->rect_float;
+ char* tgt = (char*) rval->rect;
+ float rgb[3], yuv[3];
+ int w = 515;
+ int h = 515;
+ float scope_gamma = 0.2;
+ unsigned char wtable[256];
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
+ scope_gamma)*255);
+ }
+
+ for (x = 0; x <= 255; x++) {
+ vectorscope_put_cross(255 , 0,255 - x, tgt, w, h, 1);
+ vectorscope_put_cross(255 , x, 0, tgt, w, h, 1);
+ vectorscope_put_cross(255- x, 255, 0, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
+ vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
+ }
+
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ float * src1 = src + 4 * (ibuf->x * y + x);
+ char * p;
+
+ memcpy(rgb, src1, 3 * sizeof(float));
+
+ CLAMP(rgb[0], 0.0, 1.0);
+ CLAMP(rgb[1], 0.0, 1.0);
+ CLAMP(rgb[2], 0.0, 1.0);
+
+ rgb_to_yuv(rgb, yuv);
+
+ p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1))
+ + (int) ((yuv[1] * (w - 3) + 1)));
+ scope_put_pixel(wtable, (unsigned char*)p);
+ }
+ }
+
+ vectorscope_put_cross(0, 0, 0, tgt, w, h, 3);
+
+ return rval;
+}
+
+struct ImBuf *make_vectorscope_view_from_ibuf(struct ImBuf * ibuf)
+{
+ if (ibuf->rect_float) {
+ return make_vectorscope_view_from_ibuf_float(ibuf);
+ } else {
+ return make_vectorscope_view_from_ibuf_byte(ibuf);
+ }
+}
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
new file mode 100644
index 00000000000..bfd89ccdffb
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -0,0 +1,819 @@
+/**
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2003-2009, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+#include <sys/types.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_view2d_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_sequence.h"
+#include "BKE_scene.h"
+#include "BKE_utildefines.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+/* for menu/popup icons etc etc*/
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "ED_anim_api.h"
+#include "ED_space_api.h"
+#include "ED_types.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+/* own include */
+#include "sequencer_intern.h"
+static void *find_nearest_marker() {return NULL;}
+static void deselect_markers() {}
+
+void select_surrounding_handles(Scene *scene, Sequence *test) /* XXX BRING BACK */
+{
+ Sequence *neighbor;
+
+ neighbor=find_neighboring_sequence(scene, test, SEQ_SIDE_LEFT, -1);
+ if (neighbor) {
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_RIGHTSEL;
+ }
+ neighbor=find_neighboring_sequence(scene, test, SEQ_SIDE_RIGHT, -1);
+ if (neighbor) {
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_LEFTSEL;
+ }
+ test->flag |= SELECT;
+}
+
+/* used for mouse selection and for SEQUENCER_OT_select_active_side() */
+static void select_active_side(ListBase *seqbase, int sel_side, int channel, int frame)
+{
+ Sequence *seq;
+
+ for(seq= seqbase->first; seq; seq=seq->next) {
+ if(channel==seq->machine) {
+ switch(sel_side) {
+ case SEQ_SIDE_LEFT:
+ if (frame > (seq->startdisp)) {
+ seq->flag &= ~(SEQ_RIGHTSEL|SEQ_LEFTSEL);
+ seq->flag |= SELECT;
+ }
+ break;
+ case SEQ_SIDE_RIGHT:
+ if (frame < (seq->startdisp)) {
+ seq->flag &= ~(SEQ_RIGHTSEL|SEQ_LEFTSEL);
+ seq->flag |= SELECT;
+ }
+ break;
+ case SEQ_SIDE_BOTH:
+ seq->flag &= ~(SEQ_RIGHTSEL|SEQ_LEFTSEL);
+ break;
+ }
+ }
+ }
+}
+
+#if 0 // BRING BACK
+void select_surround_from_last(Scene *scene)
+{
+ Sequence *seq=get_last_seq(scene);
+
+ if (seq==NULL)
+ return;
+
+ select_surrounding_handles(scene, seq);
+}
+#endif
+
+
+void select_single_seq(Scene *scene, Sequence *seq, int deselect_all) /* BRING BACK */
+{
+ Editing *ed= seq_give_editing(scene, FALSE);
+
+ if(deselect_all)
+ deselect_all_seq(scene);
+ set_last_seq(scene, seq);
+
+ if((seq->type==SEQ_IMAGE) || (seq->type==SEQ_MOVIE)) {
+ if(seq->strip)
+ strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR-1);
+ }
+ else if((seq->type==SEQ_HD_SOUND) || (seq->type==SEQ_RAM_SOUND)) {
+ if(seq->strip)
+ strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR-1);
+ }
+ seq->flag|= SELECT;
+ recurs_sel_seq(seq);
+}
+
+// remove this function, replace with invert operator
+//void swap_select_seq(Scene *scene)
+
+void select_neighbor_from_last(Scene *scene, int lr)
+{
+ Sequence *seq=get_last_seq(scene);
+ Sequence *neighbor;
+ int change = 0;
+ if (seq) {
+ neighbor=find_neighboring_sequence(scene, seq, lr, -1);
+ if (neighbor) {
+ switch (lr) {
+ case SEQ_SIDE_LEFT:
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_RIGHTSEL;
+ seq->flag |= SEQ_LEFTSEL;
+ break;
+ case SEQ_SIDE_RIGHT:
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_LEFTSEL;
+ seq->flag |= SEQ_RIGHTSEL;
+ break;
+ }
+ seq->flag |= SELECT;
+ change = 1;
+ }
+ }
+ if (change) {
+ }
+}
+
+
+/* (de)select operator */
+static int sequencer_deselect_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+ int desel = 0;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ for(seq= ed->seqbasep->first; seq; seq=seq->next) {
+ if(seq->flag & SEQ_ALLSEL) {
+ desel= 1;
+ break;
+ }
+ }
+
+ for(seq= ed->seqbasep->first; seq; seq=seq->next) {
+ if (desel) {
+ seq->flag &= SEQ_DESEL;
+ }
+ else {
+ seq->flag &= (SEQ_LEFTSEL+SEQ_RIGHTSEL);
+ seq->flag |= SELECT;
+ }
+ }
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_select_all_toggle(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "(De)Select All";
+ ot->idname= "SEQUENCER_OT_select_all_toggle";
+
+ /* api callbacks */
+ ot->exec= sequencer_deselect_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+/* (de)select operator */
+static int sequencer_select_invert_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ for(seq= ed->seqbasep->first; seq; seq=seq->next) {
+ if (seq->flag & SELECT) {
+ seq->flag &= SEQ_DESEL;
+ }
+ else {
+ seq->flag &= (SEQ_LEFTSEL+SEQ_RIGHTSEL);
+ seq->flag |= SELECT;
+ }
+ }
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_select_invert(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Invert";
+ ot->idname= "SEQUENCER_OT_select_invert";
+
+ /* api callbacks */
+ ot->exec= sequencer_select_invert_exec;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int sequencer_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ View2D *v2d= UI_view2d_fromcontext(C);
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ short extend= RNA_boolean_get(op->ptr, "extend");
+ short linked_left= RNA_boolean_get(op->ptr, "linked_left");
+ short linked_right= RNA_boolean_get(op->ptr, "linked_right");
+
+ short mval[2];
+
+ Sequence *seq,*neighbor;
+ int hand,sel_side, shift= 0; // XXX
+ TimeMarker *marker;
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ marker=find_nearest_marker(SCE_MARKERS, 1); //XXX - dummy function for now
+
+ mval[0]= event->x - ar->winrct.xmin;
+ mval[1]= event->y - ar->winrct.ymin;
+
+ if (marker) {
+ int oldflag;
+ /* select timeline marker */
+ if (shift) {
+ oldflag= marker->flag;
+ if (oldflag & SELECT)
+ marker->flag &= ~SELECT;
+ else
+ marker->flag |= SELECT;
+ }
+ else {
+ deselect_markers(0, 0);
+ marker->flag |= SELECT;
+ }
+
+ } else {
+
+ seq= find_nearest_seq(scene, v2d, &hand, mval);
+
+ if(extend == 0 && linked_left==0 && linked_right==0)
+ deselect_all_seq(scene);
+
+ if(seq) {
+ set_last_seq(scene, seq);
+
+ if ((seq->type == SEQ_IMAGE) || (seq->type == SEQ_MOVIE)) {
+ if(seq->strip) {
+ strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR-1);
+ }
+ } else
+ if (seq->type == SEQ_HD_SOUND || seq->type == SEQ_RAM_SOUND) {
+ if(seq->strip) {
+ strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR-1);
+ }
+ }
+
+ if(extend && (seq->flag & SELECT)) {
+ switch(hand) {
+ case SEQ_SIDE_NONE:
+ if (linked_left==0 && linked_right==0)
+ seq->flag &= SEQ_DESEL;
+ break;
+ case SEQ_SIDE_LEFT:
+ seq->flag ^= SEQ_LEFTSEL;
+ break;
+ case SEQ_SIDE_RIGHT:
+ seq->flag ^= SEQ_RIGHTSEL;
+ break;
+ }
+ }
+ else {
+ seq->flag |= SELECT;
+ if(hand==SEQ_SIDE_LEFT) seq->flag |= SEQ_LEFTSEL;
+ if(hand==SEQ_SIDE_RIGHT) seq->flag |= SEQ_RIGHTSEL;
+ }
+
+ /* On Ctrl-Alt selection, select the strip and bordering handles */
+ if (linked_left && linked_right) {
+ if(extend==0) deselect_all_seq(scene);
+ seq->flag |= SELECT;
+ select_surrounding_handles(scene, seq);
+ }
+ else if ((linked_left || linked_right) && (seq->flag & SELECT)) {
+ /*
+ * First click selects adjacent handles on that side.
+ * Second click selects all strips in that direction.
+ * If there are no adjacent strips, it just selects all in that direction.
+ */
+ sel_side= linked_left ? SEQ_SIDE_LEFT:SEQ_SIDE_RIGHT;
+ neighbor=find_neighboring_sequence(scene, seq, sel_side, -1);
+ if (neighbor) {
+ switch (sel_side) {
+ case SEQ_SIDE_LEFT:
+ if ((seq->flag & SEQ_LEFTSEL) && (neighbor->flag & SEQ_RIGHTSEL)) {
+ if(extend==0) deselect_all_seq(scene);
+ seq->flag |= SELECT;
+
+ select_active_side(ed->seqbasep, SEQ_SIDE_LEFT, seq->machine, seq->startdisp);
+ } else {
+ if(extend==0) deselect_all_seq(scene);
+ seq->flag |= SELECT;
+
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_RIGHTSEL;
+ seq->flag |= SEQ_LEFTSEL;
+ }
+ break;
+ case SEQ_SIDE_RIGHT:
+ if ((seq->flag & SEQ_RIGHTSEL) && (neighbor->flag & SEQ_LEFTSEL)) {
+ if(extend==0) deselect_all_seq(scene);
+ seq->flag |= SELECT;
+
+ select_active_side(ed->seqbasep, SEQ_SIDE_RIGHT, seq->machine, seq->startdisp);
+ } else {
+ if(extend==0) deselect_all_seq(scene);
+ seq->flag |= SELECT;
+
+ neighbor->flag |= SELECT;
+ recurs_sel_seq(neighbor);
+ neighbor->flag |= SEQ_LEFTSEL;
+ seq->flag |= SEQ_RIGHTSEL;
+ }
+ break;
+ }
+ } else {
+ if(extend==0) deselect_all_seq(scene);
+ select_active_side(ed->seqbasep, sel_side, seq->machine, seq->startdisp);
+ }
+ }
+ recurs_sel_seq(seq);
+ }
+ }
+
+ /* marker transform */
+#if 0 // XXX probably need to redo this differently for 2.5
+ if (marker) {
+ short mval[2], xo, yo;
+// getmouseco_areawin(mval);
+ xo= mval[0];
+ yo= mval[1];
+
+ while(get_mbut()) {
+// getmouseco_areawin(mval);
+ if(abs(mval[0]-xo)+abs(mval[1]-yo) > 4) {
+ transform_markers('g', 0);
+ return;
+ }
+ }
+ }
+#endif
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+ /* allowing tweaks */
+ return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
+}
+
+void SEQUENCER_OT_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Activate/Select";
+ ot->idname= "SEQUENCER_OT_select";
+
+ /* api callbacks */
+ ot->invoke= sequencer_select_invoke;
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "extend the selection");
+ RNA_def_boolean(ot->srna, "linked_left", 0, "Linked Left", "Select strips to the left of the active strip");
+ RNA_def_boolean(ot->srna, "linked_right", 0, "Linked Right", "Select strips to the right of the active strip");
+}
+
+
+
+
+/* run recursivly to select linked */
+static int select_more_less_seq__internal(Scene *scene, int sel, int linked) {
+ Editing *ed= seq_give_editing(scene, FALSE);
+ Sequence *seq, *neighbor;
+ int change=0;
+ int isel;
+
+ if(ed==NULL) return 0;
+
+ if (sel) {
+ sel = SELECT;
+ isel = 0;
+ } else {
+ sel = 0;
+ isel = SELECT;
+ }
+
+ if (!linked) {
+ /* if not linked we only want to touch each seq once, newseq */
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ seq->tmp = NULL;
+ }
+ }
+
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ if((int)(seq->flag & SELECT) == sel) {
+ if ((linked==0 && seq->tmp)==0) {
+ /* only get unselected nabours */
+ neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, isel);
+ if (neighbor) {
+ if (sel) {neighbor->flag |= SELECT; recurs_sel_seq(neighbor);}
+ else neighbor->flag &= ~SELECT;
+ if (linked==0) neighbor->tmp = (Sequence *)1;
+ change = 1;
+ }
+ neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, isel);
+ if (neighbor) {
+ if (sel) {neighbor->flag |= SELECT; recurs_sel_seq(neighbor);}
+ else neighbor->flag &= ~SELECT;
+ if (linked==0) neighbor->tmp = (void *)1;
+ change = 1;
+ }
+ }
+ }
+ }
+
+ return change;
+}
+
+
+
+/* select more operator */
+static int sequencer_select_more_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+
+ if (select_more_less_seq__internal(scene, 0, 0)) {
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_select_more(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select More";
+ ot->idname= "SEQUENCER_OT_select_more";
+
+ /* api callbacks */
+ ot->exec= sequencer_select_more_exec;
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+}
+
+
+/* select less operator */
+static int sequencer_select_less_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+
+ if (select_more_less_seq__internal(scene, 1, 0)) {
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_select_less(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select less";
+ ot->idname= "SEQUENCER_OT_select_less";
+
+ /* api callbacks */
+ ot->exec= sequencer_select_less_exec;
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+}
+
+
+/* select pick linked operator (uses the mouse) */
+static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Scene *scene= CTX_data_scene(C);
+ ARegion *ar= CTX_wm_region(C);
+ View2D *v2d= UI_view2d_fromcontext(C);
+
+ short extend= RNA_boolean_get(op->ptr, "extend");
+ short mval[2];
+
+ Sequence *mouse_seq;
+ int selected, hand;
+
+ mval[0]= event->x - ar->winrct.xmin;
+ mval[1]= event->y - ar->winrct.ymin;
+
+ /* this works like UV, not mesh */
+ mouse_seq= find_nearest_seq(scene, v2d, &hand, mval);
+ if (!mouse_seq)
+ return OPERATOR_FINISHED; /* user error as with mesh?? */
+
+ if (extend==0)
+ deselect_all_seq(scene);
+
+ mouse_seq->flag |= SELECT;
+ recurs_sel_seq(mouse_seq);
+
+ selected = 1;
+ while (selected) {
+ selected = select_more_less_seq__internal(scene, 1, 1);
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_select_linked_pick(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select pick linked";
+ ot->idname= "SEQUENCER_OT_select_linked_pick";
+
+ /* api callbacks */
+ ot->invoke= sequencer_select_linked_pick_invoke;
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "extend the selection");
+}
+
+
+/* select linked operator */
+static int sequencer_select_linked_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ int selected;
+
+ selected = 1;
+ while (selected) {
+ selected = select_more_less_seq__internal(scene, 1, 1);
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select linked";
+ ot->idname= "SEQUENCER_OT_select_linked";
+
+ /* api callbacks */
+ ot->exec= sequencer_select_linked_exec;
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+}
+
+
+/* select handles operator */
+static int sequencer_select_handles_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, 0);
+ Sequence *seq;
+ int sel_side= RNA_enum_get(op->ptr, "side");
+
+ if (ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ for(seq= ed->seqbasep->first; seq; seq=seq->next) {
+ if (seq->flag & SELECT) {
+ switch(sel_side) {
+ case SEQ_SIDE_LEFT:
+ seq->flag &= ~SEQ_RIGHTSEL;
+ seq->flag |= SEQ_LEFTSEL;
+ break;
+ case SEQ_SIDE_RIGHT:
+ seq->flag &= ~SEQ_LEFTSEL;
+ seq->flag |= SEQ_RIGHTSEL;
+ break;
+ case SEQ_SIDE_BOTH:
+ seq->flag |= SEQ_LEFTSEL+SEQ_RIGHTSEL;
+ break;
+ }
+ }
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_select_handles(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Handles";
+ ot->idname= "SEQUENCER_OT_select_handles";
+
+ /* api callbacks */
+ ot->exec= sequencer_select_handles_exec;
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side of the handle that is selected");
+}
+
+/* select side operator */
+static int sequencer_select_active_side_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, 0);
+ Sequence *seq_act=get_last_seq(scene);
+
+ if (ed==NULL || seq_act==NULL)
+ return OPERATOR_CANCELLED;
+
+ seq_act->flag |= SELECT;
+
+ select_active_side(ed->seqbasep, RNA_enum_get(op->ptr, "side"), seq_act->machine, seq_act->startdisp);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_select_active_side(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Active Side";
+ ot->idname= "SEQUENCER_OT_select_active_side";
+
+ /* api callbacks */
+ ot->exec= sequencer_select_active_side_exec;
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side of the handle that is selected");
+}
+
+
+/* borderselect operator */
+static int sequencer_borderselect_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Editing *ed= seq_give_editing(scene, FALSE);
+ View2D *v2d= UI_view2d_fromcontext(C);
+
+ Sequence *seq;
+ rcti rect;
+ rctf rectf, rq;
+ int val;
+ short mval[2];
+
+ if(ed==NULL)
+ return OPERATOR_CANCELLED;
+
+ val= RNA_int_get(op->ptr, "event_type");
+ rect.xmin= RNA_int_get(op->ptr, "xmin");
+ rect.ymin= RNA_int_get(op->ptr, "ymin");
+ rect.xmax= RNA_int_get(op->ptr, "xmax");
+ rect.ymax= RNA_int_get(op->ptr, "ymax");
+
+ mval[0]= rect.xmin;
+ mval[1]= rect.ymin;
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &rectf.xmin, &rectf.ymin);
+ mval[0]= rect.xmax;
+ mval[1]= rect.ymax;
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &rectf.xmax, &rectf.ymax);
+
+ for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+ seq_rectf(seq, &rq);
+
+ if(BLI_isect_rctf(&rq, &rectf, 0)) {
+ if(val==LEFTMOUSE) seq->flag |= SELECT;
+ else seq->flag &= SEQ_DESEL;
+ recurs_sel_seq(seq);
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+
+/* ****** Border Select ****** */
+void SEQUENCER_OT_select_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Border Select";
+ ot->idname= "SEQUENCER_OT_select_border";
+
+ /* api callbacks */
+ ot->invoke= WM_border_select_invoke;
+ ot->exec= sequencer_borderselect_exec;
+ ot->modal= WM_border_select_modal;
+
+ ot->poll= ED_operator_sequencer_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* rna */
+ RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+}
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
new file mode 100644
index 00000000000..c7c92b71861
--- /dev/null
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -0,0 +1,301 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_sequence.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "ED_markers.h"
+
+#include "sequencer_intern.h" // own include
+
+/* ******************** manage regions ********************* */
+
+ARegion *sequencer_has_buttons_region(ScrArea *sa)
+{
+ ARegion *ar, *arnew;
+
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ if(ar->regiontype==RGN_TYPE_UI)
+ return ar;
+
+ /* add subdiv level; after header */
+ for(ar= sa->regionbase.first; ar; ar= ar->next)
+ if(ar->regiontype==RGN_TYPE_HEADER)
+ break;
+
+ /* is error! */
+ if(ar==NULL) return NULL;
+
+ arnew= MEM_callocN(sizeof(ARegion), "buttons for sequencer");
+
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype= RGN_TYPE_UI;
+ arnew->alignment= RGN_ALIGN_RIGHT;
+
+ arnew->flag = RGN_FLAG_HIDDEN;
+
+ return arnew;
+}
+
+
+/* ******************** default callbacks for sequencer space ***************** */
+
+static SpaceLink *sequencer_new(const bContext *C)
+{
+ Scene *scene= CTX_data_scene(C);
+ ARegion *ar;
+ SpaceSeq *sseq;
+
+ sseq= MEM_callocN(sizeof(SpaceSeq), "initsequencer");
+ sseq->spacetype= SPACE_SEQ;
+ sseq->zoom= 4;
+ sseq->chanshown = 0;
+
+
+ /* header */
+ ar= MEM_callocN(sizeof(ARegion), "header for sequencer");
+
+ BLI_addtail(&sseq->regionbase, ar);
+ ar->regiontype= RGN_TYPE_HEADER;
+ ar->alignment= RGN_ALIGN_BOTTOM;
+
+ /* buttons/list view */
+ ar= MEM_callocN(sizeof(ARegion), "buttons for sequencer");
+
+ BLI_addtail(&sseq->regionbase, ar);
+ ar->regiontype= RGN_TYPE_UI;
+ ar->alignment= RGN_ALIGN_RIGHT;
+ ar->flag = RGN_FLAG_HIDDEN;
+
+ /* main area */
+ ar= MEM_callocN(sizeof(ARegion), "main area for sequencer");
+
+ BLI_addtail(&sseq->regionbase, ar);
+ ar->regiontype= RGN_TYPE_WINDOW;
+
+
+ /* seq space goes from (0,8) to (0, efra) */
+
+ ar->v2d.tot.xmin= 0.0f;
+ ar->v2d.tot.ymin= 0.0f;
+ ar->v2d.tot.xmax= scene->r.efra;
+ ar->v2d.tot.ymax= 8.0f;
+
+ ar->v2d.cur= ar->v2d.tot;
+
+ ar->v2d.min[0]= 10.0f;
+ ar->v2d.min[1]= 4.0f;
+
+ ar->v2d.max[0]= MAXFRAMEF;
+ ar->v2d.max[1]= MAXSEQ;
+
+ ar->v2d.minzoom= 0.01f;
+ ar->v2d.maxzoom= 100.0f;
+
+ ar->v2d.scroll |= (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.scroll |= (V2D_SCROLL_LEFT|V2D_SCROLL_SCALE_VERTICAL);
+ ar->v2d.keepzoom= 0;
+ ar->v2d.keeptot= 0;
+ ar->v2d.align= V2D_ALIGN_NO_NEG_Y;
+
+ return (SpaceLink *)sseq;
+}
+
+/* not spacelink itself */
+static void sequencer_free(SpaceLink *sl)
+{
+// SpaceSeq *sseq= (SpaceSequencer*) sl;
+
+// XXX if(sseq->gpd) free_gpencil_data(sseq->gpd);
+
+}
+
+
+/* spacetype; init callback */
+static void sequencer_init(struct wmWindowManager *wm, ScrArea *sa)
+{
+
+}
+
+static SpaceLink *sequencer_duplicate(SpaceLink *sl)
+{
+ SpaceSeq *sseqn= MEM_dupallocN(sl);
+
+ /* clear or remove stuff from old */
+// XXX sseq->gpd= gpencil_data_duplicate(sseq->gpd);
+
+ return (SpaceLink *)sseqn;
+}
+
+
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void sequencer_main_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "Sequencer", SPACE_SEQ, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void sequencer_header_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ED_region_header_init(ar);
+}
+
+static void sequencer_header_area_draw(const bContext *C, ARegion *ar)
+{
+ ED_region_header(C, ar);
+}
+
+static void sequencer_main_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ switch(wmn->data) {
+ case ND_FRAME:
+ case ND_MARKERS:
+ case ND_SEQUENCER:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ }
+}
+
+/* *********************** buttons region ************************ */
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void sequencer_buttons_area_init(wmWindowManager *wm, ARegion *ar)
+{
+
+ ED_region_panels_init(wm, ar);
+
+}
+
+static void sequencer_buttons_area_draw(const bContext *C, ARegion *ar)
+{
+ ED_region_panels(C, ar, 1, NULL);
+}
+
+static void sequencer_buttons_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+
+ }
+}
+/* ************************************* */
+
+/* only called once, from space/spacetypes.c */
+void ED_spacetype_sequencer(void)
+{
+ SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype sequencer");
+ ARegionType *art;
+
+ st->spaceid= SPACE_SEQ;
+
+ st->new= sequencer_new;
+ st->free= sequencer_free;
+ st->init= sequencer_init;
+ st->duplicate= sequencer_duplicate;
+ st->operatortypes= sequencer_operatortypes;
+ st->keymap= sequencer_keymap;
+
+ /* regions: main window */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init= sequencer_main_area_init;
+ art->draw= drawseqspace;
+ art->listener= sequencer_main_area_listener;
+ art->keymapflag= ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: listview/buttons */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
+ art->regionid = RGN_TYPE_UI;
+ art->minsizex= 220; // XXX
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
+ art->listener= sequencer_buttons_area_listener;
+ art->init= sequencer_buttons_area_init;
+ art->draw= sequencer_buttons_area_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* Keep as python only for now
+ sequencer_buttons_register(art);
+ */
+
+ /* regions: header */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->minsizey= HEADERY;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
+
+ art->init= sequencer_header_area_init;
+ art->draw= sequencer_header_area_draw;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
+}
+