Politically correct terrible consequencer changes

This patch includes the work done in the terrible consequencer branch
that hasn't been merged to master minus a few controversial and WIP
stuff, like strip parenting, new sequence data structs and cuddly
widgets.

What is included:

* Strip extensions only when slipping. It can very easily be made an
option but with a few strips with overlapping durations it makes view
too crowded and difficult to make out.
* Threaded waveform loading + code that restores waveforms on undo (not
used though, since sound_load recreates everything. There's a patch for
review D876)
* Toggle to enable backdrop in the strip sequence editor
* Toggle to easily turn on/off waveform display
* Snapping during transform on sequence boundaries. Snapping to start or
end of selection depends on position of mouse when invoking the operator
* Snapping of timeline indicator in sequencer to strip boundaries. To
use just press and hold ctrl while dragging.

Reviewers: campbellbarton

Differential Revision: https://developer.blender.org/D904
This commit is contained in:
Antonis Ryakiotakis 2014-11-24 18:18:35 +01:00
parent aa0b268acb
commit 649a2bcc3d
29 changed files with 789 additions and 288 deletions

View File

@ -46,6 +46,7 @@
#include <cstring>
#include <cmath>
#include <sstream>
#include <iostream>
#include "AUD_NULLDevice.h"
#include "AUD_I3DDevice.h"
@ -317,8 +318,9 @@ AUD_SoundInfo AUD_getInfo(AUD_Sound *sound)
info.length = reader->getLength() / (float) info.specs.rate;
}
}
catch(AUD_Exception&)
catch(AUD_Exception &ae)
{
std::cout << ae.str << std::endl;
}
return info;
@ -1084,7 +1086,7 @@ int AUD_doesPlayback()
return -1;
}
int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second)
int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second, short *interrupt)
{
AUD_DeviceSpecs specs;
sample_t *buf;
@ -1107,6 +1109,9 @@ int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_pe
for (int i = 0; i < length; i++) {
len = floor(samplejump * (i+1)) - floor(samplejump * i);
if (*interrupt) {
return 0;
}
aBuffer.assureSize(len * AUD_SAMPLE_SIZE(specs));
buf = aBuffer.getBuffer();

View File

@ -646,7 +646,7 @@ extern int AUD_doesPlayback(void);
* \param samples_per_second How many samples to read per second of the sound.
* \return How many samples really have been read. Always <= length.
*/
extern int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second);
extern int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second, short *interrupt);
/**
* Copies a sound.

View File

@ -71,6 +71,7 @@ class SEQUENCER_HT_header(Header):
row.prop(scene, "lock_frame_selection_to_range", text="", toggle=True)
layout.prop(st, "view_type", expand=True, text="")
layout.prop(st, "waveform_draw_type", text="")
if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
layout.prop(st, "display_mode", expand=True, text="")
@ -82,6 +83,7 @@ class SEQUENCER_HT_header(Header):
layout.separator()
layout.operator("sequencer.refresh_all")
layout.prop(st, "show_backdrop")
else:
if st.view_type == 'SEQUENCER_PREVIEW':
layout.separator()
@ -716,6 +718,7 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
st = context.space_data
strip = act_strip(context)
sound = strip.sound
@ -734,7 +737,9 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel):
row.prop(sound, "use_memory_cache")
layout.prop(strip, "show_waveform")
if st.waveform_draw_type == 'DEFAULT_WAVEFORMS':
layout.prop(strip, "show_waveform")
layout.prop(strip, "volume")
layout.prop(strip, "pitch")
layout.prop(strip, "pan")

View File

@ -377,6 +377,17 @@ struct Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine);
void BKE_sequence_alpha_mode_from_extension(struct Sequence *seq);
void BKE_sequence_init_colorspace(struct Sequence *seq);
/* RNA enums, just to be more readable */
enum {
SEQ_SIDE_NONE = 0,
SEQ_SIDE_LEFT,
SEQ_SIDE_RIGHT,
SEQ_SIDE_BOTH
};
int BKE_sequencer_find_next_prev_edit(
struct Scene *scene, int cfra, const short side,
const bool do_skip_mute, const bool do_center, const bool do_unselected);
struct Sequence *BKE_sequencer_add_image_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
struct Sequence *BKE_sequencer_add_sound_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
struct Sequence *BKE_sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);

View File

@ -71,8 +71,6 @@ void sound_delete(struct Main *bmain, struct bSound *sound);
void sound_cache(struct bSound *sound);
void sound_cache_notifying(struct Main *main, struct bSound *sound);
void sound_delete_cache(struct bSound *sound);
void sound_load(struct Main *main, struct bSound *sound);
@ -132,7 +130,7 @@ int sound_scene_playing(struct Scene *scene);
void sound_free_waveform(struct bSound *sound);
void sound_read_waveform(struct bSound *sound);
void sound_read_waveform(struct bSound *sound, bool locked, short *stop);
void sound_update_scene(struct Main *bmain, struct Scene *scene);

View File

@ -892,7 +892,6 @@ void BKE_sequencer_sort(Scene *scene)
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq, *seqt;
if (ed == NULL)
return;
@ -4675,3 +4674,70 @@ bool BKE_sequence_is_valid_check(Sequence *seq)
return true;
}
int BKE_sequencer_find_next_prev_edit(
Scene *scene, int cfra, const short side,
const bool do_skip_mute, const bool do_center, const bool do_unselected)
{
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq;
int dist, best_dist, best_frame = cfra;
int seq_frames[2], seq_frames_tot;
/* in case where both is passed, frame just finds the nearest end while frame_left the nearest start */
best_dist = MAXFRAME * 2;
if (ed == NULL) return cfra;
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
int i;
if (do_skip_mute && (seq->flag & SEQ_MUTE)) {
continue;
}
if (do_unselected && (seq->flag & SELECT))
continue;
if (do_center) {
seq_frames[0] = (seq->startdisp + seq->enddisp) / 2;
seq_frames_tot = 1;
}
else {
seq_frames[0] = seq->startdisp;
seq_frames[1] = seq->enddisp;
seq_frames_tot = 2;
}
for (i = 0; i < seq_frames_tot; i++) {
const int seq_frame = seq_frames[i];
dist = MAXFRAME * 2;
switch (side) {
case SEQ_SIDE_LEFT:
if (seq_frame < cfra) {
dist = cfra - seq_frame;
}
break;
case SEQ_SIDE_RIGHT:
if (seq_frame > cfra) {
dist = seq_frame - cfra;
}
break;
case SEQ_SIDE_BOTH:
dist = abs(seq_frame - cfra);
break;
}
if (dist < best_dist) {
best_frame = seq_frame;
best_dist = dist;
}
}
}
return best_frame;
}

View File

@ -36,6 +36,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_threads.h"
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
@ -116,6 +117,12 @@ void BKE_sound_free(bSound *sound)
}
sound_free_waveform(sound);
if (sound->mutex) {
BLI_mutex_free(sound->mutex);
sound->mutex = NULL;
}
#endif /* WITH_AUDASPACE */
}
@ -296,12 +303,6 @@ void sound_cache(bSound *sound)
sound->playback_handle = sound->handle;
}
void sound_cache_notifying(struct Main *main, bSound *sound)
{
sound_cache(sound);
sound_update_sequencer(main, sound);
}
void sound_delete_cache(bSound *sound)
{
sound->flags &= ~SOUND_FLAGS_CACHING;
@ -680,22 +681,40 @@ void sound_free_waveform(bSound *sound)
sound->waveform = NULL;
}
void sound_read_waveform(bSound *sound)
void sound_read_waveform(bSound *sound, bool locked, short *stop)
{
AUD_SoundInfo info;
SoundWaveform *waveform = NULL;
info = AUD_getInfo(sound->playback_handle);
if (info.length > 0) {
SoundWaveform *waveform = MEM_mallocN(sizeof(SoundWaveform), "SoundWaveform");
int length = info.length * SOUND_WAVE_SAMPLES_PER_SECOND;
waveform = MEM_mallocN(sizeof(SoundWaveform), "SoundWaveform");
waveform->data = MEM_mallocN(length * sizeof(float) * 3, "SoundWaveform.samples");
waveform->length = AUD_readSound(sound->playback_handle, waveform->data, length, SOUND_WAVE_SAMPLES_PER_SECOND);
waveform->length = AUD_readSound(sound->playback_handle, waveform->data, length, SOUND_WAVE_SAMPLES_PER_SECOND, stop);
if (*stop) {
MEM_freeN(waveform->data);
MEM_freeN(waveform);
if (locked)
BLI_mutex_lock(sound->mutex);
sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
if (locked)
BLI_mutex_unlock(sound->mutex);
return;
}
sound_free_waveform(sound);
sound->waveform = waveform;
}
if (locked)
BLI_mutex_lock(sound->mutex);
sound->waveform = waveform;
sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
if (locked)
BLI_mutex_unlock(sound->mutex);
}
void sound_update_scene(Main *bmain, struct Scene *scene)
@ -830,7 +849,7 @@ void sound_stop_scene(struct Scene *UNUSED(scene)) {}
void sound_seek_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {}
float sound_sync_scene(struct Scene *UNUSED(scene)) { return NAN_FLT; }
int sound_scene_playing(struct Scene *UNUSED(scene)) { return -1; }
void sound_read_waveform(struct bSound *UNUSED(sound)) {}
void sound_read_waveform(struct bSound *sound, bool locked, short *stop) { UNUSED_VARS(sound, locked, stop); }
void sound_init_main(struct Main *UNUSED(bmain)) {}
void sound_set_cfra(int UNUSED(cfra)) {}
void sound_update_sequencer(struct Main *UNUSED(main), struct bSound *UNUSED(sound)) {}

View File

@ -308,6 +308,9 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
/* makes lookup of existing video clips in old main */
blo_make_movieclip_pointer_map(fd, oldmain);
/* make lookups of existing sound data in old main */
blo_make_sound_pointer_map(fd, oldmain);
/* removed packed data from this trick - it's internal data that needs saves */
@ -318,7 +321,10 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
/* ensures relinked movie clips are not freed */
blo_end_movieclip_pointer_map(fd, oldmain);
/* ensures relinked sounds are not freed */
blo_end_sound_pointer_map(fd, oldmain);
/* move libraries from old main to new main */
if (bfd && mainlist.first != mainlist.last) {

View File

@ -1128,6 +1128,8 @@ void blo_freefiledata(FileData *fd)
oldnewmap_free(fd->imamap);
if (fd->movieclipmap)
oldnewmap_free(fd->movieclipmap);
if (fd->soundmap)
oldnewmap_free(fd->soundmap);
if (fd->packedmap)
oldnewmap_free(fd->packedmap);
if (fd->libmap && !(fd->flags & FD_FLAGS_NOT_MY_LIBMAP))
@ -1221,6 +1223,13 @@ static void *newmclipadr(FileData *fd, void *adr) /* used to restore movie
return NULL;
}
static void *newsoundadr(FileData *fd, void *adr) /* used to restore sound data after undo */
{
if (fd->soundmap && adr)
return oldnewmap_lookup_and_inc(fd->soundmap, adr, true);
return NULL;
}
static void *newpackedadr(FileData *fd, void *adr) /* used to restore packed data after undo */
{
if (fd->packedmap && adr)
@ -1437,6 +1446,37 @@ void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain)
}
}
void blo_make_sound_pointer_map(FileData *fd, Main *oldmain)
{
bSound *sound = oldmain->sound.first;
fd->soundmap = oldnewmap_new();
for (; sound; sound = sound->id.next) {
if (sound->waveform)
oldnewmap_insert(fd->soundmap, sound->waveform, sound->waveform, 0);
}
}
/* set old main sound caches to zero if it has been restored */
/* this works because freeing old main only happens after this call */
void blo_end_sound_pointer_map(FileData *fd, Main *oldmain)
{
OldNew *entry = fd->soundmap->entries;
bSound *sound = oldmain->sound.first;
int i;
/* used entries were restored, so we put them to zero */
for (i = 0; i < fd->soundmap->nentries; i++, entry++) {
if (entry->nr > 0)
entry->newp = NULL;
}
for (; sound; sound = sound->id.next) {
sound->waveform = newsoundadr(fd, sound->waveform);
}
}
/* XXX disabled this feature - packed files also belong in temp saves and quit.blend, to make restore work */
static void insert_packedmap(FileData *fd, PackedFile *pf)
@ -5457,7 +5497,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
}
if (sce->ed) {
ListBase *old_seqbasep = &((Editing *)sce->ed)->seqbase;
ListBase *old_seqbasep = &sce->ed->seqbase;
ed = sce->ed = newdataadr(fd, sce->ed);
@ -5471,6 +5511,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
seq->seq1= newdataadr(fd, seq->seq1);
seq->seq2= newdataadr(fd, seq->seq2);
seq->seq3= newdataadr(fd, seq->seq3);
/* a patch: after introduction of effects with 3 input strips */
if (seq->seq3 == NULL) seq->seq3 = seq->seq2;
@ -6776,14 +6817,26 @@ static void direct_link_sound(FileData *fd, bSound *sound)
{
sound->handle = NULL;
sound->playback_handle = NULL;
sound->waveform = NULL;
// versioning stuff, if there was a cache, then we enable caching:
/* versioning stuff, if there was a cache, then we enable caching: */
if (sound->cache) {
sound->flags |= SOUND_FLAGS_CACHING;
sound->cache = NULL;
}
if (fd->soundmap) {
sound->waveform = newsoundadr(fd, sound->waveform);
}
else {
sound->waveform = NULL;
}
if (sound->mutex)
sound->mutex = BLI_mutex_alloc();
/* clear waveform loading flag */
sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
sound->packedfile = direct_link_packedfile(fd, sound->packedfile);
sound->newpackedfile = direct_link_packedfile(fd, sound->newpackedfile);
}

View File

@ -88,6 +88,7 @@ typedef struct FileData {
struct OldNewMap *libmap;
struct OldNewMap *imamap;
struct OldNewMap *movieclipmap;
struct OldNewMap *soundmap;
struct OldNewMap *packedmap;
struct BHeadSort *bheadmap;
@ -133,6 +134,8 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain);
void blo_end_image_pointer_map(FileData *fd, Main *oldmain);
void blo_make_movieclip_pointer_map(FileData *fd, Main *oldmain);
void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain);
void blo_make_sound_pointer_map(FileData *fd, Main *oldmain);
void blo_end_sound_pointer_map(FileData *fd, Main *oldmain);
void blo_make_packed_pointer_map(FileData *fd, Main *oldmain);
void blo_end_packed_pointer_map(FileData *fd, Main *oldmain);
void blo_add_library_pointer_map(ListBase *mainlist, FileData *fd);

View File

@ -156,6 +156,7 @@
#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_sequencer.h"
#include "BKE_sound.h"
#include "BKE_subsurf.h"
#include "BKE_modifier.h"
#include "BKE_fcurve.h"

View File

@ -41,6 +41,7 @@
#include "DNA_scene_types.h"
#include "BKE_context.h"
#include "BKE_sequencer.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_sound.h"
@ -92,9 +93,15 @@ static void change_frame_apply(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
int frame = RNA_int_get(op->ptr, "frame");
bool do_snap = RNA_boolean_get(op->ptr, "snap");
if (do_snap && CTX_wm_space_seq(C)) {
frame = BKE_sequencer_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false);
}
/* set the new frame number */
CFRA = RNA_int_get(op->ptr, "frame");
CFRA = frame;
FRAMENUMBER_MIN_CLAMP(CFRA);
SUBFRA = 0.0f;
@ -144,7 +151,7 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
* click-dragging over a range (modal scrubbing).
*/
RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
change_frame_apply(C, op);
/* add temp handler */
@ -175,6 +182,16 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event->val == KM_RELEASE)
return OPERATOR_FINISHED;
break;
case LEFTCTRLKEY:
case RIGHTCTRLKEY:
if (event->val == KM_RELEASE) {
RNA_boolean_set(op->ptr, "snap", false);
}
else if (event->val == KM_PRESS) {
RNA_boolean_set(op->ptr, "snap", true);
}
break;
}
return OPERATOR_RUNNING_MODAL;
@ -182,6 +199,8 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void ANIM_OT_change_frame(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name = "Change Frame";
ot->idname = "ANIM_OT_change_frame";
@ -198,6 +217,8 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
/* rna */
ot->prop = RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
prop = RNA_def_boolean(ot->srna, "snap", false, "Snap", "");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ****************** set preview range operator ****************************/

View File

@ -43,6 +43,7 @@ set(SRC
sequencer_edit.c
sequencer_modifier.c
sequencer_ops.c
sequencer_preview.c
sequencer_scopes.c
sequencer_select.c
sequencer_view.c

View File

@ -34,6 +34,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_threads.h"
#include "IMB_imbuf_types.h"
@ -62,6 +63,7 @@
#include "ED_mask.h"
#include "ED_sequencer.h"
#include "ED_space_api.h"
#include "ED_screen.h"
#include "UI_interface.h"
#include "UI_resources.h"
@ -69,6 +71,8 @@
#include "WM_api.h"
#include "MEM_guardedalloc.h"
/* own include */
#include "sequencer_intern.h"
@ -86,9 +90,7 @@
#undef SEQP_BEGIN
#undef SEQ_END
static void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2);
static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[3])
void color3ubv_from_seq(Scene *curscene, Sequence *seq, unsigned char col[3])
{
unsigned char blendcol[3];
SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
@ -179,14 +181,14 @@ static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[
}
}
static void drawseqwave(Scene *scene, Sequence *seq, float x1, float y1, float x2, float y2, float stepsize)
static void drawseqwave(const bContext *C, SpaceSeq *sseq, Scene *scene, Sequence *seq, float x1, float y1, float x2, float y2, float stepsize)
{
/*
* x1 is the starting x value to draw the wave,
* x2 the end x value, same for y1 and y2
* stepsize is width of a pixel.
*/
if (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM) {
if ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM)) {
int i, j, pos;
int length = floor((x2 - x1) / stepsize) + 1;
float ymid = (y1 + y2) / 2;
@ -194,20 +196,30 @@ static void drawseqwave(Scene *scene, Sequence *seq, float x1, float y1, float x
float samplestep;
float startsample, endsample;
float value;
bSound *sound = seq->sound;
SoundWaveform *waveform;
if (!seq->sound->waveform)
sound_read_waveform(seq->sound);
if (!seq->sound->waveform)
return; /* zero length sound */
if (!sound->mutex)
sound->mutex = BLI_mutex_alloc();
BLI_mutex_lock(sound->mutex);
if (!seq->sound->waveform) {
if(!(sound->flags & SOUND_FLAGS_WAVEFORM_LOADING)) {
/* prevent sounds from reloading */
seq->sound->flags |= SOUND_FLAGS_WAVEFORM_LOADING;
BLI_mutex_unlock(sound->mutex);
sequencer_preview_add_sound(C, seq);
}
else {
BLI_mutex_unlock(sound->mutex);
}
return; /* nothing to draw */
}
BLI_mutex_unlock(sound->mutex);
waveform = seq->sound->waveform;
if (!waveform)
return;
startsample = floor((seq->startofs + seq->anim_startofs) / FPS * SOUND_WAVE_SAMPLES_PER_SECOND);
endsample = ceil((seq->startofs + seq->anim_startofs + seq->enddisp - seq->startdisp) / FPS * SOUND_WAVE_SAMPLES_PER_SECOND);
samplestep = (endsample - startsample) * stepsize / (x2 - x1);
@ -303,7 +315,7 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
if ((seqm->flag & SEQ_MUTE) == 0 && (seq->flag & SEQ_MUTE))
drawmeta_stipple(1);
get_seq_color3ubv(scene, seq, col);
color3ubv_from_seq(scene, seq, col);
glColor4ubv(col);
@ -422,112 +434,6 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla
}
}
static void draw_seq_extensions(Scene *scene, ARegion *ar, Sequence *seq)
{
float x1, x2, y1, y2, pixely, a;
unsigned char col[3], blendcol[3];
View2D *v2d = &ar->v2d;
if (seq->type >= SEQ_TYPE_EFFECT) return;
x1 = seq->startdisp;
x2 = seq->enddisp;
y1 = seq->machine + SEQ_STRIP_OFSBOTTOM;
y2 = seq->machine + SEQ_STRIP_OFSTOP;
pixely = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
if (pixely <= 0) return; /* can happen when the view is split/resized */
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_GetColorPtrShade3ubv(col, col, -16);
glColor3ubv((GLubyte *)col);
for (a = y1; a < y2; a += pixely * 2.0f) {
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_GetColorPtrShade3ubv(col, col, 24);
else UI_GetColorPtrShade3ubv(col, col, -16);
glColor3ubv((GLubyte *)col);
for (a = y1; a < y2; a += pixely * 2.0f) {
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, const unsigned char background_col[3])
{
@ -634,7 +540,7 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float
}
/* draws a shaded strip, made from gradient + flat color + gradient */
static void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2)
void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2)
{
float ymid1, ymid2;
@ -696,7 +602,7 @@ static void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, floa
* ARegion is currently only used to get the windows width in pixels
* so wave file sample drawing precision is zoom adjusted
*/
static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline_tint, float pixelx)
static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, ARegion *ar, Sequence *seq, int outline_tint, float pixelx)
{
View2D *v2d = &ar->v2d;
float x1, x2, y1, y2;
@ -714,8 +620,8 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
/* get the correct color per strip type*/
//get_seq_color3ubv(scene, seq, col);
get_seq_color3ubv(scene, seq, background_col);
//color3ubv_from_seq(scene, seq, col);
color3ubv_from_seq(scene, seq, background_col);
/* draw the main strip body */
if (is_single_image) { /* single image */
@ -727,10 +633,6 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
draw_shadedstrip(seq, background_col, x1, y1, x2, y2);
}
/* draw additional info and controls */
if (!is_single_image)
draw_seq_extensions(scene, ar, seq);
draw_seq_handle(v2d, seq, handsize_clamped, SEQ_LEFTHANDLE);
draw_seq_handle(v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE);
@ -740,7 +642,9 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
/* draw sound wave */
if (seq->type == SEQ_TYPE_SOUND_RAM) {
drawseqwave(scene, seq, x1, y1, x2, y2, BLI_rctf_size_x(&ar->v2d.cur) / ar->winx);
if(!(sseq->flag & SEQ_NO_WAVEFORMS)) {
drawseqwave(C, sseq, scene, seq, x1, y1, x2, y2, BLI_rctf_size_x(&ar->v2d.cur) / ar->winx);
}
}
/* draw lock */
@ -773,7 +677,7 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
glDisable(GL_POLYGON_STIPPLE);
}
get_seq_color3ubv(scene, seq, col);
color3ubv_from_seq(scene, seq, col);
if ((G.moving & G_TRANSFORM_SEQ) && (seq->flag & SELECT)) {
if (seq->flag & SEQ_OVERLAP) {
col[0] = 255; col[1] = col[2] = 40;
@ -924,7 +828,7 @@ static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scop
return scope;
}
void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, bool draw_overlay)
void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, bool draw_overlay, bool draw_backdrop)
{
struct Main *bmain = CTX_data_main(C);
struct ImBuf *ibuf = NULL;
@ -980,7 +884,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
viewrecty /= proxy_size / 100.0f;
}
if (!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) {
if ((!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) && !draw_backdrop) {
UI_GetThemeColor3fv(TH_SEQ_PREVIEW, col);
glClearColor(col[0], col[1], col[2], 0.0);
glClear(GL_COLOR_BUFFER_BIT);
@ -1055,23 +959,25 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
/* without this colors can flicker from previous opengl state */
glColor4ub(255, 255, 255, 255);
UI_view2d_totRect_set(v2d, viewrectx + 0.5f, viewrecty + 0.5f);
UI_view2d_curRect_validate(v2d);
/* setting up the view - actual drawing starts here */
UI_view2d_view_ortho(v2d);
/* only draw alpha for main buffer */
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
if (sseq->flag & SEQ_USE_ALPHA) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
glColor4f(1.0, 1.0, 1.0, 1.0);
if (!draw_backdrop) {
UI_view2d_totRect_set(v2d, viewrectx + 0.5f, viewrecty + 0.5f);
UI_view2d_curRect_validate(v2d);
/* setting up the view - actual drawing starts here */
UI_view2d_view_ortho(v2d);
/* only draw alpha for main buffer */
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
if (sseq->flag & SEQ_USE_ALPHA) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
glColor4f(1.0, 1.0, 1.0, 1.0);
}
}
}
if (scope) {
IMB_freeImBuf(ibuf);
ibuf = scope;
@ -1161,6 +1067,14 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, format, type, display_buffer);
if (draw_backdrop) {
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
}
glBegin(GL_QUADS);
if (draw_overlay) {
@ -1183,6 +1097,25 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
}
}
else if (draw_backdrop) {
float aspect = BLI_rcti_size_x(&ar->winrct) / (float)BLI_rcti_size_y(&ar->winrct);
float image_aspect = viewrectx/viewrecty;
float imagex, imagey;
if (aspect >= image_aspect) {
imagex = image_aspect/aspect;
imagey = 1.0f;
}
else {
imagex = 1.0f;
imagey = aspect/image_aspect;
}
glTexCoord2f(0.0f, 0.0f); glVertex2f(-imagex, -imagey);
glTexCoord2f(0.0f, 1.0f); glVertex2f(-imagex, imagey);
glTexCoord2f(1.0f, 1.0f); glVertex2f(imagex, imagey);
glTexCoord2f(1.0f, 0.0f); glVertex2f(imagex, -imagey);
}
else {
glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
@ -1190,6 +1123,15 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
}
glEnd();
if (draw_backdrop) {
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
glBindTexture(GL_TEXTURE_2D, last_texid);
glDisable(GL_TEXTURE_2D);
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA)
@ -1199,6 +1141,16 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
if (glsl_used)
IMB_colormanagement_finish_glsl_draw();
if (cache_handle)
IMB_display_buffer_release(cache_handle);
if (!scope)
IMB_freeImBuf(ibuf);
if (draw_backdrop) {
return;
}
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
float x1 = v2d->tot.xmin;
@ -1248,9 +1200,6 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
ED_gpencil_draw_2dimage(C);
}
}
if (!scope)
IMB_freeImBuf(ibuf);
/* ortho at pixel level */
UI_view2d_view_restore(C);
@ -1287,9 +1236,6 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
NULL, C);
}
}
if (cache_handle)
IMB_display_buffer_release(cache_handle);
}
#if 0
@ -1366,6 +1312,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
{
Scene *scene = CTX_data_scene(C);
View2D *v2d = &ar->v2d;
SpaceSeq *sseq = CTX_wm_space_seq(C);
Sequence *last_seq = BKE_sequencer_active_get(scene);
int sel = 0, j;
float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
@ -1386,7 +1333,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
else if (seq->machine > v2d->cur.ymax) continue;
/* strip passed all tests unscathed... so draw it now */
draw_seq_strip(scene, ar, seq, outline_tint, pixelx);
draw_seq_strip(C, sseq, scene, ar, seq, outline_tint, pixelx);
}
/* draw selected next time round */
@ -1395,7 +1342,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
/* draw the last selected last (i.e. 'active' in other parts of Blender), removes some overlapping error */
if (last_seq)
draw_seq_strip(scene, ar, last_seq, 120, pixelx);
draw_seq_strip(C, sseq, scene, ar, last_seq, 120, pixelx);
}
static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
@ -1473,6 +1420,12 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
// NOTE: the gridlines are currently spaced every 25 frames, which is only fine for 25 fps, but maybe not for 30...
UI_view2d_constant_grid_draw(v2d);
if (sseq->draw_flag & SEQ_DRAW_BACKDROP) {
draw_image_seq(C, scene, ar, sseq, scene->r.cfra, 0, false, true);
UI_SetTheme(SPACE_SEQ, RGN_TYPE_WINDOW);
UI_view2d_view_ortho(v2d);
}
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
seq_draw_sfra_efra(scene, v2d);

View File

@ -62,8 +62,13 @@
#include "ED_screen.h"
#include "ED_transform.h"
#include "ED_sequencer.h"
#include "ED_space_api.h"
#include "UI_view2d.h"
#include "UI_resources.h"
#include "GL/glew.h"
#include "BIF_glutil.h"
/* own include */
#include "sequencer_intern.h"
@ -1231,7 +1236,6 @@ void SEQUENCER_OT_snap(struct wmOperatorType *ot)
RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be snapped", INT_MIN, INT_MAX);
}
typedef struct SlipData {
int init_mouse[2];
float init_mouseloc[2];
@ -1241,6 +1245,7 @@ typedef struct SlipData {
int num_seq;
bool slow;
int slow_offset; /* offset at the point where offset was turned on */
void *draw_handle;
} SlipData;
static void transseq_backup(TransSeq *ts, Sequence *seq)
@ -1274,15 +1279,129 @@ static void transseq_restore(TransSeq *ts, Sequence *seq)
seq->len = ts->len;
}
static int slip_add_sequences_rec(ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool first_level)
static void draw_slip_extensions(const bContext *C, ARegion *ar, void *data)
{
Scene *scene = CTX_data_scene(C);
float x1, x2, y1, y2, pixely, a;
unsigned char col[3], blendcol[3];
View2D *v2d = &ar->v2d;
SlipData *td = data;
int i;
for (i = 0; i < td->num_seq; i++) {
Sequence *seq = td->seq_array[i];
if ((seq->type != SEQ_TYPE_META) && td->trim[i]) {
x1 = seq->startdisp;
x2 = seq->enddisp;
y1 = seq->machine + SEQ_STRIP_OFSBOTTOM;
y2 = seq->machine + SEQ_STRIP_OFSTOP;
pixely = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
if (pixely <= 0) return; /* can happen when the view is split/resized */
blendcol[0] = blendcol[1] = blendcol[2] = 120;
if (seq->startofs) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
color3ubv_from_seq(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);
color3ubv_from_seq(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) {
color3ubv_from_seq(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_GetColorPtrShade3ubv(col, col, -16);
glColor3ubv((GLubyte *)col);
for (a = y1; a < y2; a += pixely * 2.0f) {
fdrawline(x1, a, (float)(seq->start), a);
}
}
if (seq->endstill) {
color3ubv_from_seq(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_GetColorPtrShade3ubv(col, col, 24);
else UI_GetColorPtrShade3ubv(col, col, -16);
glColor3ubv((GLubyte *)col);
for (a = y1; a < y2; a += pixely * 2.0f) {
fdrawline((float)(seq->start + seq->len), a, x2, a);
}
}
}
}
}
static int slip_add_sequences_rec(ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool do_trim)
{
Sequence *seq;
int num_items = 0;
for (seq = seqbasep->first; seq; seq = seq->next) {
if (!first_level || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
if (!do_trim || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
seq_array[offset + num_items] = seq;
trim[offset + num_items] = first_level;
trim[offset + num_items] = do_trim;
num_items++;
if (seq->type == SEQ_TYPE_META) {
@ -1322,6 +1441,7 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
SlipData *data;
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
ARegion *ar = CTX_wm_region(C);
float mouseloc[2];
int num_seq, i;
View2D *v2d = UI_view2d_fromcontext(C);
@ -1344,6 +1464,8 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
transseq_backup(data->ts + i, data->seq_array[i]);
}
data->draw_handle = ED_region_draw_cb_activate(ar->type, draw_slip_extensions, data, REGION_DRAW_POST_VIEW);
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
copy_v2_v2_int(data->init_mouse, event->mval);
@ -1353,6 +1475,9 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
WM_event_add_modal_handler(C, op);
/* notify so we draw extensions immediately */
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_RUNNING_MODAL;
}
@ -1463,6 +1588,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
Scene *scene = CTX_data_scene(C);
SlipData *data = (SlipData *)op->customdata;
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
switch (event->type) {
case MOUSEMOVE:
@ -1504,6 +1630,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
case LEFTMOUSE:
{
ED_region_draw_cb_exit(ar->type, data->draw_handle);
MEM_freeN(data->seq_array);
MEM_freeN(data->trim);
MEM_freeN(data->ts);
@ -1532,6 +1659,8 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
BKE_sequence_calc(scene, seq);
}
ED_region_draw_cb_exit(ar->type, data->draw_handle);
MEM_freeN(data->seq_array);
MEM_freeN(data->ts);
MEM_freeN(data->trim);
@ -1587,7 +1716,6 @@ void SEQUENCER_OT_slip(struct wmOperatorType *ot)
INT32_MIN, INT32_MAX);
}
/* mute operator */
static int sequencer_mute_exec(bContext *C, wmOperator *op)
{
@ -2810,74 +2938,13 @@ void SEQUENCER_OT_view_selected(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER;
}
static int find_next_prev_edit(Scene *scene, int cfra,
const short side,
const bool do_skip_mute, const bool do_center)
{
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq;
int dist, best_dist, best_frame = cfra;
int seq_frames[2], seq_frames_tot;
best_dist = MAXFRAME * 2;
if (ed == NULL) return cfra;
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
int i;
if (do_skip_mute && (seq->flag & SEQ_MUTE)) {
continue;
}
if (do_center) {
seq_frames[0] = (seq->startdisp + seq->enddisp) / 2;
seq_frames_tot = 1;
}
else {
seq_frames[0] = seq->startdisp;
seq_frames[1] = seq->enddisp;
seq_frames_tot = 2;
}
for (i = 0; i < seq_frames_tot; i++) {
const int seq_frame = seq_frames[i];
dist = MAXFRAME * 2;
switch (side) {
case SEQ_SIDE_LEFT:
if (seq_frame < cfra) {
dist = cfra - seq_frame;
}
break;
case SEQ_SIDE_RIGHT:
if (seq_frame > cfra) {
dist = seq_frame - cfra;
}
break;
}
if (dist < best_dist) {
best_frame = seq_frame;
best_dist = dist;
}
}
}
return best_frame;
}
static bool strip_jump_internal(Scene *scene,
const short side,
const bool do_skip_mute, const bool do_center)
{
bool changed = false;
int cfra = CFRA;
int nfra = find_next_prev_edit(scene, cfra, side, do_skip_mute, do_center);
int nfra = BKE_sequencer_find_next_prev_edit(scene, cfra, side, do_skip_mute, do_center, false);
if (nfra != cfra) {
CFRA = nfra;
@ -3623,4 +3690,3 @@ void SEQUENCER_OT_change_path(struct wmOperatorType *ot)
WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILEPATH | WM_FILESEL_FILES,
FILE_DEFAULTDISPLAY);
}

View File

@ -45,6 +45,7 @@ struct ARegion;
struct ARegionType;
struct Scene;
struct Main;
struct SequencePreview;
/* space_sequencer.c */
struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa);
@ -52,7 +53,9 @@ struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa);
/* sequencer_draw.c */
void draw_timeline_seq(const struct bContext *C, struct ARegion *ar);
void draw_image_seq(const struct bContext *C, struct Scene *scene, struct ARegion *ar, struct SpaceSeq *sseq, int cfra, int offset, bool draw_overlay);
void draw_image_seq(const struct bContext *C, struct Scene *scene, struct ARegion *ar, struct SpaceSeq *sseq, int cfra, int offset, bool draw_overlay, bool draw_backdrop);
void color3ubv_from_seq(struct Scene *curscene, struct Sequence *seq, unsigned char col[3]);
void draw_shadedstrip(struct Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2);
/* UNUSED */
// void seq_reset_imageofs(struct SpaceSeq *sseq);
@ -150,13 +153,6 @@ 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
@ -199,5 +195,8 @@ void SEQUENCER_OT_strip_modifier_move(struct wmOperatorType *ot);
/* sequencer_view.c */
void SEQUENCER_OT_sample(struct wmOperatorType *ot);
/* sequencer_preview.c */
void sequencer_preview_add_sound(const struct bContext *C, struct Sequence *seq);
#endif /* __SEQUENCER_INTERN_H__ */

View File

@ -40,6 +40,8 @@
#include "ED_markers.h"
#include "ED_transform.h" /* transform keymap */
#include "BKE_sequencer.h"
#include "sequencer_intern.h"

View File

@ -0,0 +1,172 @@
/*
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* Contributor(s): Blender Foundation, 2003-2009, Antony Riakiotakis
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/editors/space_sequencer/sequencer_preview.c
* \ingroup spseq
*/
#include "DNA_sequence_types.h"
#include "DNA_sound_types.h"
#include "BLI_listbase.h"
#include "BLI_threads.h"
#include "BKE_sound.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "WM_api.h"
#include "WM_types.h"
#include "ED_screen.h"
#include "MEM_guardedalloc.h"
#include "sequencer_intern.h"
typedef struct PreviewJob {
ListBase previews;
ThreadMutex *mutex;
Scene *scene;
int total;
int processed;
} PreviewJob;
typedef struct PreviewJobAudio {
struct PreviewJobAudio *next, *prev;
bSound *sound;
int lr; /* sample left or right */
int startframe;
bool waveform; /* reload sound or waveform */
} PreviewJobAudio;
static void free_preview_job(void *data)
{
PreviewJob *pj = (PreviewJob *)data;
BLI_mutex_free(pj->mutex);
BLI_freelistN(&pj->previews);
MEM_freeN(pj);
}
/* only this runs inside thread */
static void preview_startjob(void *data, short *stop, short *do_update, float *progress)
{
PreviewJob *pj = data;
PreviewJobAudio *previewjb;
BLI_mutex_lock(pj->mutex);
previewjb = pj->previews.first;
BLI_mutex_unlock(pj->mutex);
while (previewjb) {
PreviewJobAudio *preview_next;
bSound *sound = previewjb->sound;
sound_read_waveform(sound, true, stop);
if (*stop || G.is_break) {
BLI_mutex_lock(pj->mutex);
previewjb = previewjb->next;
BLI_mutex_unlock(pj->mutex);
while (previewjb) {
sound = previewjb->sound;
/* make sure we cleanup the loading flag! */
BLI_mutex_lock(sound->mutex);
sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
BLI_mutex_unlock(sound->mutex);
BLI_mutex_lock(pj->mutex);
previewjb = previewjb->next;
BLI_mutex_unlock(pj->mutex);
}
BLI_mutex_lock(pj->mutex);
BLI_freelistN(&pj->previews);
pj->total = 0;
pj->processed = 0;
BLI_mutex_unlock(pj->mutex);
break;
}
BLI_mutex_lock(pj->mutex);
preview_next = previewjb->next;
BLI_freelinkN(&pj->previews, previewjb);
previewjb = preview_next;
pj->processed++;
*progress = (pj->total > 0) ? (float)pj->processed / (float)pj->total : 1.0;
*do_update = true;
BLI_mutex_unlock(pj->mutex);
}
}
static void preview_endjob(void *data)
{
PreviewJob *pj = data;
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, pj->scene);
}
void sequencer_preview_add_sound(const bContext *C, Sequence *seq)
{
/* first, get the preview job, if it exists */
wmJob *wm_job;
PreviewJob *pj;
ScrArea *sa = CTX_wm_area(C);
PreviewJobAudio *audiojob = MEM_callocN(sizeof(PreviewJobAudio), "preview_audio");
wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Strip Previews",
WM_JOB_PROGRESS, WM_JOB_TYPE_SEQ_BUILD_PREVIEW);
pj = WM_jobs_customdata_get(wm_job);
if (!pj) {
pj = MEM_callocN(sizeof(PreviewJob), "preview rebuild job");
pj->mutex = BLI_mutex_alloc();
pj->scene = CTX_data_scene(C);
WM_jobs_customdata_set(wm_job, pj, free_preview_job);
WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_SEQUENCER, NC_SCENE | ND_SEQUENCER);
WM_jobs_callbacks(wm_job, preview_startjob, NULL, NULL, preview_endjob);
}
/* attempt to lock mutex of job here */
audiojob->sound = seq->sound;
BLI_mutex_lock(pj->mutex);
BLI_addtail(&pj->previews, audiojob);
pj->total++;
BLI_mutex_unlock(pj->mutex);
if (!WM_jobs_is_running(wm_job)) {
G.is_break = false;
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
ED_area_tag_redraw(sa);
}

View File

@ -559,7 +559,7 @@ static void sequencer_preview_area_draw(const bContext *C, ARegion *ar)
if (sseq->mainb == SEQ_DRAW_SEQUENCE) sseq->mainb = SEQ_DRAW_IMG_IMBUF;
if (!show_split || sseq->overlay_type != SEQ_DRAW_OVERLAY_REFERENCE)
draw_image_seq(C, scene, ar, sseq, scene->r.cfra, 0, false);
draw_image_seq(C, scene, ar, sseq, scene->r.cfra, 0, false, false);
if (show_split && sseq->overlay_type != SEQ_DRAW_OVERLAY_CURRENT) {
int over_cfra;
@ -570,7 +570,7 @@ static void sequencer_preview_area_draw(const bContext *C, ARegion *ar)
over_cfra = scene->r.cfra + scene->ed->over_ofs;
if (over_cfra != scene->r.cfra || sseq->overlay_type != SEQ_DRAW_OVERLAY_RECT)
draw_image_seq(C, scene, ar, sseq, scene->r.cfra, over_cfra - scene->r.cfra, true);
draw_image_seq(C, scene, ar, sseq, scene->r.cfra, over_cfra - scene->r.cfra, true, false);
}
if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_playing(wm)) {

View File

@ -7126,10 +7126,11 @@ static void headerSeqSlide(TransInfo *t, float val[2], char str[MAX_INFO_LEN])
WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0));
}
static void applySeqSlideValue(TransInfo *t, const float val[2])
static void applySeqSlideValue(TransInfo *t, const float val[2], int frame)
{
TransData *td = t->data;
int i;
TransSeq *ts = t->customData;
for (i = 0; i < t->total; i++, td++) {
float tvec[2];
@ -7144,15 +7145,21 @@ static void applySeqSlideValue(TransInfo *t, const float val[2])
mul_v2_fl(tvec, td->factor);
td->loc[0] = td->iloc[0] + tvec[0];
if (t->modifiers & MOD_SNAP_INVERT) {
td->loc[0] = frame + td->factor * (td->iloc[0] - ts->min);
}
else {
td->loc[0] = td->iloc[0] + tvec[0];
}
td->loc[1] = td->iloc[1] + tvec[1];
}
}
static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
static void applySeqSlide(TransInfo *t, const int mval[2])
{
char str[MAX_INFO_LEN];
int snap_frame = 0;
if (t->con.mode & CON_APPLY) {
float pvec[3] = {0.0f, 0.0f, 0.0f};
float tvec[3];
@ -7160,7 +7167,8 @@ static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
copy_v3_v3(t->values, tvec);
}
else {
snapGridIncrement(t, t->values);
snap_frame = snapSequenceBounds(t, mval);
// snapGridIncrement(t, t->values);
applyNumInput(&t->num, t->values);
}
@ -7168,7 +7176,7 @@ static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
t->values[1] = floor(t->values[1] + 0.5f);
headerSeqSlide(t, t->values, str);
applySeqSlideValue(t, t->values);
applySeqSlideValue(t, t->values, snap_frame);
recalcData(t);

View File

@ -173,6 +173,13 @@ typedef struct TransDataSeq {
} TransDataSeq;
typedef struct TransSeq {
TransDataSeq *tdseq;
int min;
int max;
bool snap_left;
} TransSeq;
/* for NLA transform (stored in td->extra pointer) */
typedef struct TransDataNla {
ID *id; /* ID-block NLA-data is attached to */
@ -588,6 +595,8 @@ typedef enum {
void snapGridIncrement(TransInfo *t, float *val);
void snapGridIncrementAction(TransInfo *t, float *val, GearsType action);
int snapSequenceBounds(TransInfo *t, const int mval[2]);
bool activeSnap(TransInfo *t);
bool validSnap(TransInfo *t);

View File

@ -4528,10 +4528,47 @@ static int SeqToTransData_Recursive(TransInfo *t, ListBase *seqbase, TransData *
}
}
}
return tot;
}
static void SeqTransDataBounds(TransInfo *t, ListBase *seqbase, TransSeq *ts)
{
Sequence *seq;
int recursive, count, flag;
int max = INT32_MIN, min = INT32_MAX;
for (seq = seqbase->first; seq; seq = seq->next) {
/* just to get the flag since there are corner cases where this isn't totally obvious */
SeqTransInfo(t, seq, &recursive, &count, &flag);
/* use 'flag' which is derived from seq->flag but modified for special cases */
if (flag & SELECT) {
if (flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
if (flag & SEQ_LEFTSEL) {
min = min_ii(seq->startdisp, min);
max = max_ii(seq->startdisp, max);
}
if (flag & SEQ_RIGHTSEL) {
min = min_ii(seq->enddisp, min);
max = max_ii(seq->enddisp, max);
}
}
else {
min = min_ii(seq->startdisp, min);
max = max_ii(seq->enddisp, max);
}
}
}
if (ts) {
ts->max = max;
ts->min = min;
}
}
static void freeSeqData(TransInfo *t)
{
Editing *ed = BKE_sequencer_editing_get(t->scene, false);
@ -4694,6 +4731,8 @@ static void freeSeqData(TransInfo *t)
}
if ((t->customData != NULL) && (t->flag & T_FREE_CUSTOMDATA)) {
TransSeq *ts = t->customData;
MEM_freeN(ts->tdseq);
MEM_freeN(t->customData);
t->customData = NULL;
}
@ -4713,6 +4752,8 @@ static void createTransSeqData(bContext *C, TransInfo *t)
TransData *td = NULL;
TransData2D *td2d = NULL;
TransDataSeq *tdsq = NULL;
TransSeq *ts = NULL;
float xmouse, ymouse;
int count = 0;
@ -4723,12 +4764,11 @@ static void createTransSeqData(bContext *C, TransInfo *t)
t->customFree = freeSeqData;
UI_view2d_region_to_view(v2d, t->imval[0], t->imval[1], &xmouse, &ymouse);
/* which side of the current frame should be allowed */
if (t->mode == TFM_TIME_EXTEND) {
/* only side on which mouse is gets transformed */
float xmouse, ymouse;
UI_view2d_region_to_view(v2d, t->imval[0], t->imval[1], &xmouse, &ymouse);
t->frame_side = (xmouse > CFRA) ? 'R' : 'L';
}
else {
@ -4768,15 +4808,19 @@ static void createTransSeqData(bContext *C, TransInfo *t)
return;
}
t->customData = ts = MEM_mallocN(sizeof(TransSeq), "transseq");
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransSeq TransData");
td2d = t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransSeq TransData2D");
tdsq = t->customData = MEM_callocN(t->total * sizeof(TransDataSeq), "TransSeq TransDataSeq");
ts->tdseq = tdsq = MEM_callocN(t->total * sizeof(TransDataSeq), "TransSeq TransDataSeq");
t->flag |= T_FREE_CUSTOMDATA;
/* loop 2: build transdata array */
SeqToTransData_Recursive(t, ed->seqbasep, td, td2d, tdsq);
SeqTransDataBounds(t, ed->seqbasep, ts);
/* set the snap mode based on how close the mouse is at the end/start points */
if (abs(xmouse - ts->max) > abs(xmouse - ts->min))
ts->snap_left = true;
#undef XXX_DURIAN_ANIM_TX_HACK
}

View File

@ -59,6 +59,7 @@
#include "BKE_anim.h" /* for duplis */
#include "BKE_context.h"
#include "BKE_editmesh.h"
#include "BKE_sequencer.h"
#include "BKE_main.h"
#include "BKE_tracking.h"
@ -2430,6 +2431,27 @@ void snapGridIncrement(TransInfo *t, float *val)
snapGridIncrementAction(t, val, action);
}
int snapSequenceBounds(TransInfo *t, const int mval[2])
{
float xmouse, ymouse;
int frame;
int mframe;
TransSeq *ts = t->customData;
/* reuse increment, strictly speaking could be another snap mode, but leave as is */
if (!(t->modifiers & MOD_SNAP_INVERT))
return 0;
/* convert to frame range */
UI_view2d_region_to_view(&t->ar->v2d, mval[0], mval[1], &xmouse, &ymouse);
mframe = iroundf(xmouse);
/* now find the closest sequence */
frame = BKE_sequencer_find_next_prev_edit(t->scene, mframe, SEQ_SIDE_BOTH, true, false, true);
if (!ts->snap_left)
frame = frame - (ts->max - ts->min);
return frame;
}
static void applyGridIncrement(TransInfo *t, float *val, int max_index, const float fac[3], GearsType action)
{

View File

@ -131,10 +131,11 @@ typedef struct Sequence {
int flag, type; /*flags bitmap (see below) and the type of sequence*/
int len; /* the length of the contents of this strip - before handles are applied */
int start, startofs, endofs;
int startstill, endstill;
int start; /* start frame of contents of strip in absolute frame coordinates. For metastrips start of first strip startdisp */
int startofs, endofs; /* frames after the first frame where display starts, frames before the last frame where display ends */
int startstill, endstill; /* frames that use the first frame before data begins, frames that use the last frame after data ends */
int machine, depth; /*machine - the strip channel, depth - the depth in the sequence when dealing with metastrips */
int startdisp, enddisp; /*starting and ending points in the sequence*/
int startdisp, enddisp; /* starting and ending points of the strip in the sequence*/
float sat;
float mul, handsize;

View File

@ -95,6 +95,8 @@ typedef struct bSound {
*/
void *playback_handle;
/* mutex for asynchronous loading of sounds */
void *mutex;
/* XXX unused currently (SOUND_TYPE_LIMITER) */
/* float start, end; */
} bSound;
@ -116,9 +118,10 @@ enum {
};
enum {
SOUND_FLAGS_3D = (1 << 3), /* deprecated! used for sound actuator loading */
SOUND_FLAGS_CACHING = (1 << 4),
SOUND_FLAGS_MONO = (1 << 5),
SOUND_FLAGS_3D = (1 << 3), /* deprecated! used for sound actuator loading */
SOUND_FLAGS_CACHING = (1 << 4),
SOUND_FLAGS_MONO = (1 << 5),
SOUND_FLAGS_WAVEFORM_LOADING = (1 << 6),
};
#if (DNA_DEPRECATED_GCC_POISON == 1)

View File

@ -497,6 +497,8 @@ typedef struct SpaceSeq {
float zoom DNA_DEPRECATED; /* deprecated, handled by View2D now */
int view; /* see SEQ_VIEW_* below */
int overlay_type;
int draw_flag; /* overlay an image of the editing on below the strips */
int pad;
struct bGPdata *gpd; /* grease-pencil data */
@ -513,6 +515,12 @@ typedef enum eSpaceSeq_RegionType {
SEQ_DRAW_IMG_HISTOGRAM = 4,
} eSpaceSeq_RegionType;
/* sseq->draw_flag */
typedef enum eSpaceSeq_DrawFlag {
SEQ_DRAW_BACKDROP = (1 << 0),
} eSpaceSeq_DrawFlag;
/* sseq->flag */
typedef enum eSpaceSeq_Flag {
SEQ_DRAWFRAMES = (1 << 0),
@ -522,6 +530,8 @@ typedef enum eSpaceSeq_Flag {
SEQ_SHOW_GPENCIL = (1 << 4),
SEQ_NO_DRAW_CFRANUM = (1 << 5),
SEQ_USE_ALPHA = (1 << 6), /* use RGBA display mode for preview */
SEQ_ALL_WAVEFORMS = (1 << 7), /* draw all waveforms */
SEQ_NO_WAVEFORMS = (1 << 8), /* draw no waveforms */
} eSpaceSeq_Flag;
/* sseq->view */

View File

@ -38,6 +38,7 @@
#include "BKE_sound.h"
#include "BKE_context.h"
#include "BKE_sequencer.h"
static void rna_Sound_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
@ -59,9 +60,9 @@ static void rna_Sound_caching_set(PointerRNA *ptr, const int value)
sound_delete_cache(sound);
}
static void rna_Sound_caching_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
static void rna_Sound_caching_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
{
sound_update_sequencer(bmain, (bSound *)(ptr->data));
BKE_sequencer_update_sound(scene, (bSound *)(ptr->data));
}
#else

View File

@ -2514,6 +2514,16 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem waveform_type_draw_items[] = {
{SEQ_NO_WAVEFORMS, "NO_WAVEFORMS", 0, "Waveforms Off",
"No waveforms drawn for all sound strips"},
{SEQ_ALL_WAVEFORMS, "ALL_WAVEFORMS", 0, "Waveforms On",
"Waveforms drawn for all sound strips"},
{0, "DEFAULT_WAVEFORMS", 0, "Use Strip Option",
"Waveforms drawn according to strip setting"},
{0, NULL, 0, NULL, NULL}
};
srna = RNA_def_struct(brna, "SpaceSequenceEditor", "Space");
RNA_def_struct_sdna(srna, "SpaceSeq");
RNA_def_struct_ui_text(srna, "Space Sequence Editor", "Sequence editor space data");
@ -2583,6 +2593,12 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Draw Channels", "Channels of the preview to draw");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
prop = RNA_def_property(srna, "waveform_draw_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, waveform_type_draw_items);
RNA_def_property_ui_text(prop, "Waveform Drawing", "How Waveforms are drawn");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
prop = RNA_def_property(srna, "draw_overexposed", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "zebra");
RNA_def_property_ui_text(prop, "Show Overexposed", "Show overexposed areas with zebra stripes");
@ -2609,6 +2625,11 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_enum_items(prop, overlay_type_items);
RNA_def_property_ui_text(prop, "Overlay Type", "Overlay draw type");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
prop = RNA_def_property(srna, "show_backdrop", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "draw_flag", SEQ_DRAW_BACKDROP);
RNA_def_property_ui_text(prop, "Use Backdrop", "Display result under strips");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
}
static void rna_def_space_text(BlenderRNA *brna)

View File

@ -398,6 +398,7 @@ enum {
WM_JOB_TYPE_CLIP_SOLVE_CAMERA,
WM_JOB_TYPE_CLIP_PREFETCH,
WM_JOB_TYPE_SEQ_BUILD_PROXY,
WM_JOB_TYPE_SEQ_BUILD_PREVIEW,
/* add as needed, screencast, seq proxy build
* if having hard coded values is a problem */
};