bugfix
[blender.git] / source / blender / src / drawseq.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include <string.h>
35 #include <math.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BMF_Api.h"
40
41 #include "BLI_blenlib.h"
42 #include "BLI_arithb.h"
43
44 #include "IMB_imbuf_types.h"
45
46 #include "DNA_sequence_types.h"
47 #include "DNA_scene_types.h"
48 #include "DNA_screen_types.h"
49 #include "DNA_space_types.h"
50 #include "DNA_view2d_types.h"
51 #include "DNA_userdef_types.h"
52
53 #include "BKE_global.h"
54 #include "BKE_plugin_types.h"
55 #include "BKE_scene.h"
56 #include "BKE_utildefines.h"
57  
58 #include "BIF_cursors.h"
59 #include "BIF_gl.h"
60 #include "BIF_graphics.h"
61 #include "BIF_mywindow.h"
62 #include "BIF_screen.h"
63 #include "BIF_drawseq.h"
64 #include "BIF_editseq.h"
65 #include "BIF_glutil.h"
66 #include "BIF_resources.h"
67 #include "BIF_space.h"
68 #include "BIF_interface.h"
69
70 #include "BSE_view.h"
71 #include "BSE_drawipo.h"
72 #include "BSE_sequence.h"
73 #include "BSE_seqeffects.h"
74 #include "BSE_seqscopes.h"
75 #include "BSE_seqaudio.h"
76 #include "BSE_time.h"
77
78 #include "IMB_imbuf_types.h"
79 #include "IMB_imbuf.h"
80
81 #include "blendef.h"    /* CFRA */
82 #include "mydevice.h"   /* REDRAWSEQ */
83 #include "interface.h"
84 #include "winlay.h"
85
86 #define SEQ_LEFTHANDLE          1
87 #define SEQ_RIGHTHANDLE 2
88
89 #define SEQ_STRIP_OFSBOTTOM             0.2
90 #define SEQ_STRIP_OFSTOP                0.8
91
92 /* Note, Dont use WHILE_SEQ while drawing! - it messes up transform, - Campbell */
93
94 int no_rightbox=0, no_leftbox= 0;
95 static void draw_seq_handle(Sequence *seq, SpaceSeq *sseq, float pixelx, short direction);
96 static void draw_seq_extensions(Sequence *seq, SpaceSeq *sseq);
97 static void draw_seq_text(Sequence *seq, float x1, float x2, float y1, float y2);
98 static void draw_shadedstrip(Sequence *seq, char *col, float x1, float y1, float x2, float y2);
99 static void draw_seq_strip(struct Sequence *seq, struct ScrArea *sa, struct SpaceSeq *sseq, int outline_tint, float pixelx);
100
101 static void draw_cfra_seq(void)
102 {
103         glColor3ub(0x30, 0x90, 0x50);
104         glLineWidth(2.0);
105         glBegin(GL_LINES);
106         glVertex2f(G.scene->r.cfra, G.v2d->cur.ymin);
107         glVertex2f(G.scene->r.cfra, G.v2d->cur.ymax);
108         glEnd();
109         glLineWidth(1.0);
110 }
111
112 static void get_seq_color3ubv(Sequence *seq, char *col)
113 {
114         char blendcol[3];
115         float hsv[3], rgb[3];
116         SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
117
118         switch(seq->type) {
119         case SEQ_IMAGE:
120                 BIF_GetThemeColor3ubv(TH_SEQ_IMAGE, col);
121                 break;
122         case SEQ_META:
123                 BIF_GetThemeColor3ubv(TH_SEQ_META, col);
124                 break;
125         case SEQ_MOVIE:
126                 BIF_GetThemeColor3ubv(TH_SEQ_MOVIE, col);
127                 break;
128         case SEQ_SCENE:
129                 BIF_GetThemeColor3ubv(TH_SEQ_SCENE, col);
130                 
131                 if(seq->scene==G.scene) {
132                         BIF_GetColorPtrBlendShade3ubv(col, col, col, 1.0, 20);
133                 }
134                 break;
135
136         /* transitions */
137         case SEQ_CROSS:
138         case SEQ_GAMCROSS:
139         case SEQ_WIPE:
140                 /* slightly offset hue to distinguish different effects */
141                 BIF_GetThemeColor3ubv(TH_SEQ_TRANSITION, col);
142                 
143                 rgb[0] = col[0]/255.0; rgb[1] = col[1]/255.0; rgb[2] = col[2]/255.0; 
144                 rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
145                 
146                 if (seq->type == SEQ_CROSS)             hsv[0]+= 0.04;
147                 if (seq->type == SEQ_GAMCROSS)  hsv[0]+= 0.08;
148                 if (seq->type == SEQ_WIPE)              hsv[0]+= 0.12;
149                 
150                 if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
151                 hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
152                 col[0] = (char)(rgb[0]*255); col[1] = (char)(rgb[1]*255); col[2] = (char)(rgb[2]*255); 
153                 break;
154                 
155         /* effects */
156         case SEQ_TRANSFORM:
157         case SEQ_SPEED:
158         case SEQ_ADD:
159         case SEQ_SUB:
160         case SEQ_MUL:
161         case SEQ_ALPHAOVER:
162         case SEQ_ALPHAUNDER:
163         case SEQ_OVERDROP:
164         case SEQ_GLOW:
165                 /* slightly offset hue to distinguish different effects */
166                 BIF_GetThemeColor3ubv(TH_SEQ_EFFECT, col);
167                 
168                 rgb[0] = col[0]/255.0; rgb[1] = col[1]/255.0; rgb[2] = col[2]/255.0; 
169                 rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
170                 
171                 if (seq->type == SEQ_ADD)               hsv[0]+= 0.04;
172                 if (seq->type == SEQ_SUB)               hsv[0]+= 0.08;
173                 if (seq->type == SEQ_MUL)               hsv[0]+= 0.12;
174                 if (seq->type == SEQ_ALPHAOVER) hsv[0]+= 0.16;
175                 if (seq->type == SEQ_ALPHAUNDER)        hsv[0]+= 0.20;
176                 if (seq->type == SEQ_OVERDROP)  hsv[0]+= 0.24;
177                 if (seq->type == SEQ_GLOW)              hsv[0]+= 0.28;
178                 if (seq->type == SEQ_TRANSFORM)         hsv[0]+= 0.36;
179
180                 if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
181                 hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
182                 col[0] = (char)(rgb[0]*255); col[1] = (char)(rgb[1]*255); col[2] = (char)(rgb[2]*255); 
183                 break;
184         case SEQ_COLOR:
185                 if (colvars->col) {
186                         col[0]= (char)(colvars->col[0]*255);
187                         col[1]= (char)(colvars->col[1]*255);
188                         col[2]= (char)(colvars->col[2]*255);
189                 } else {
190                         col[0] = col[1] = col[2] = 128;
191                 }
192                 break;
193         case SEQ_PLUGIN:
194                 BIF_GetThemeColor3ubv(TH_SEQ_PLUGIN, col);
195                 break;
196         case SEQ_HD_SOUND:
197         case SEQ_RAM_SOUND:
198                 BIF_GetThemeColor3ubv(TH_SEQ_AUDIO, col);
199                 blendcol[0] = blendcol[1] = blendcol[2] = 128;
200                 if(seq->flag & SEQ_MUTE) BIF_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.5, 20);
201                 break;
202         default:
203                 col[0] = 10; col[1] = 255; col[2] = 40;
204         }
205 }
206
207 static void drawmeta_contents(Sequence *seqm, float x1, float y1, float x2, float y2)
208 {
209         /* Note, this used to use WHILE_SEQ, but it messes up the seq->depth value, (needed by transform when doing overlap checks)
210          * so for now, just use the meta's immediate children, could be fixed but its only drawing - Campbell */
211         Sequence *seq;
212         float dx;
213         int nr;
214         char col[3];
215         
216         nr= BLI_countlist(&seqm->seqbase);
217
218         dx= (x2-x1)/nr;
219
220         if (seqm->flag & SEQ_MUTE) {
221                 glEnable(GL_POLYGON_STIPPLE);
222                 glPolygonStipple(stipple_halftone);
223                 
224                 glEnable(GL_LINE_STIPPLE);
225                 glLineStipple(1, 0x8888);
226         }
227         
228         for (seq= seqm->seqbase.first; seq; seq= seq->next) {
229                 get_seq_color3ubv(seq, col);
230                 
231                 glColor3ubv((GLubyte *)col);
232
233                 glRectf(x1,  y1,  x1+0.9*dx,  y2);
234                 
235                 BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -30);
236                 glColor3ubv((GLubyte *)col);
237
238                 fdrawbox(x1,  y1,  x1+0.9*dx,  y2);
239                 
240                 x1+= dx;
241         }
242         
243         if (seqm->flag & SEQ_MUTE) {
244                 glDisable(GL_POLYGON_STIPPLE);
245                 glDisable(GL_LINE_STIPPLE);
246         }
247 }
248
249 static void drawseqwave(Sequence *seq, float x1, float y1, float x2, float y2, int winx)
250 {
251         /*
252         x1 is the starting x value to draw the wave,
253         x2 the end x value, same for y1 and y2
254         winx is the zoom level.
255         */
256         
257         float
258         f, /* floating point value used to store the X draw location for the wave lines when openGL drawing*/
259         midy, /* fast access to the middle location (y1+y2)/2 */
260         clipxmin, /* the minimum X value, clip this with the window */
261         clipxmax, /* the maximum X value, clip this with the window */
262         sample_step, /* steps to move per sample, floating value must later translate into an int */
263         fsofs, /* steps to move per sample, floating value must later translate into an int */
264         feofs_sofs, /*  */
265         sound_width, /* convenience: x2-x1 */
266         wavemulti; /* scale the samples by this value when GL_LINE drawing so it renders the right height */
267         
268         int
269         offset, /* initial offset value for the wave drawing */
270         offset_next, /* when in the wave drawing loop this value is the samples intil the next vert */
271         sofs, /* Constrained offset value (~3) for the wave, start */
272         eofs, /* ditto, end */
273         wavesample, /* inner loop storage if the current wave sample value, used to make the 2 values below */
274         wavesamplemin, /* used for finding the min and max wave peaks */
275         wavesamplemax, /* ditto */
276         subsample_step=4; /* when the sample step is 4 every sample of
277         the wave is evaluated for min and max values used to draw the wave,
278         however this is slow ehrn zoomed out so when the sample step is above
279         1 (the larger the further out the zoom is) so not evaluate all samples, only some. */
280         
281         signed short* s;
282         bSound *sound;
283         Uint8 *stream;
284         
285         audio_makestream(seq->sound);
286         if(seq->sound==NULL || seq->sound->stream==NULL) return;
287         
288         if (seq->flag & SEQ_MUTE) glColor3ub(0x70, 0x80, 0x80); else glColor3ub(0x70, 0xc0, 0xc0);
289         
290         sofs = ((int)( FRA2TIME(seq->startdisp-seq->start+seq->anim_startofs)*(float)G.scene->audio.mixrate*4.0 )) & (~3);
291         eofs = ((int)( FRA2TIME(seq->enddisp-seq->start+seq->anim_startofs)*(float)G.scene->audio.mixrate*4.0 )) & (~3);
292         
293         /* clip the drawing area to the screen bounds to save time */
294         sample_step= (G.v2d->cur.xmax - G.v2d->cur.xmin)/winx;
295         clipxmin= MAX2(x1, G.v2d->cur.xmin);
296         clipxmax= MIN2(x2, G.v2d->cur.xmax);
297         
298         if (sample_step > 1)
299                 subsample_step= ((int)(subsample_step*sample_step*8)) & (~3);
300         
301         /* for speedy access */
302         midy = (y1+y2)/2;
303         fsofs= (float)sofs;
304         feofs_sofs= (float)(eofs-sofs);
305         sound_width= x2-x1;
306         sound = seq->sound;
307         stream = sound->stream;
308         wavemulti = (y2-y1)/196605; /*y2-y1 is the height*/
309         wavesample=0;
310         
311         /* we need to get the starting offset value, excuse the duplicate code */
312         f=clipxmin;
313         offset= (int) (fsofs + ((f-x1)/sound_width) * feofs_sofs) & (~3);
314         
315         /* start the loop, draw a line per sample_step -sample_step is about 1 line drawn per pixel */
316         glBegin(GL_LINES);
317         for (f=x1+sample_step; f<=clipxmax; f+=sample_step) {
318                 
319                 offset_next = (int) (fsofs + ((f-x1)/sound_width) * feofs_sofs) & (~3);
320                 if (f > G.v2d->cur.xmin) {
321                         /* if this is close to the last sample just exit */
322                         if (offset_next >= sound->streamlen) break;
323                         
324                         wavesamplemin = 131070;
325                         wavesamplemax = -131070;
326                         
327                         /*find with high and low of the waveform for this draw,
328                         evaluate small samples to find this range */
329                         while (offset < offset_next) {
330                                 s = (signed short*)(stream+offset);
331                                 
332                                 wavesample = s[0]*2 + s[1];
333                                 if (wavesamplemin>wavesample)
334                                         wavesamplemin=wavesample;
335                                 if (wavesamplemax<wavesample)
336                                         wavesamplemax=wavesample;
337                                 offset+=subsample_step;
338                         }
339                         /* draw the wave line, looks good up close and zoomed out */
340                         glVertex2f(f,  midy-(wavemulti*wavesamplemin) );
341                         glVertex2f(f,  midy-(wavemulti*wavesamplemax) );
342                 } else {
343                         while (offset < offset_next) offset+=subsample_step;
344                 }
345                 
346                 offset=offset_next;
347         }
348         glEnd();
349 }
350
351 /* draw a handle, for each end of a sequence strip */
352 static void draw_seq_handle(Sequence *seq, SpaceSeq *sseq, float pixelx, short direction)
353 {
354         float v1[2], v2[2], v3[2], rx1=0, rx2=0; //for triangles and rect
355         float x1, x2, y1, y2;
356         float handsize;
357         float minhandle, maxhandle;
358         char str[32];
359         unsigned int whichsel=0;
360         View2D *v2d;
361         
362         x1= seq->startdisp;
363         x2= seq->enddisp;
364         
365         y1= seq->machine+SEQ_STRIP_OFSBOTTOM;
366         y2= seq->machine+SEQ_STRIP_OFSTOP;
367         
368         v2d = &sseq->v2d;
369         
370         /* clamp handles to defined size in pixel space */
371         handsize = seq->handsize;
372         minhandle = 7;
373         maxhandle = 40;
374         CLAMP(handsize, minhandle*pixelx, maxhandle*pixelx);
375         
376         /* set up co-ordinates/dimensions for either left or right handle */
377         if (direction == SEQ_LEFTHANDLE) {      
378                 rx1 = x1;
379                 rx2 = x1+handsize*0.75;
380                 
381                 v1[0]= x1+handsize/4; v1[1]= y1+( ((y1+y2)/2.0 - y1)/2);
382                 v2[0]= x1+handsize/4; v2[1]= y2-( ((y1+y2)/2.0 - y1)/2);
383                 v3[0]= v2[0] + handsize/4; v3[1]= (y1+y2)/2.0;
384                 
385                 whichsel = SEQ_LEFTSEL;
386         } else if (direction == SEQ_RIGHTHANDLE) {      
387                 rx1 = x2-handsize*0.75;
388                 rx2 = x2;
389                 
390                 v1[0]= x2-handsize/4; v1[1]= y1+( ((y1+y2)/2.0 - y1)/2);
391                 v2[0]= x2-handsize/4; v2[1]= y2-( ((y1+y2)/2.0 - y1)/2);
392                 v3[0]= v2[0] - handsize/4; v3[1]= (y1+y2)/2.0;
393                 
394                 whichsel = SEQ_RIGHTSEL;
395         }
396         
397         /* draw! */
398         if(seq->type < SEQ_EFFECT || 
399            get_sequence_effect_num_inputs(seq->type) == 0) {
400                 glEnable( GL_BLEND );
401                 
402                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
403                 
404                 if(seq->flag & whichsel) glColor4ub(0, 0, 0, 80);
405                 else if (seq->flag & SELECT) glColor4ub(255, 255, 255, 30);
406                 else glColor4ub(0, 0, 0, 22);
407                 
408                 glRectf(rx1, y1, rx2, y2);
409                 
410                 if(seq->flag & whichsel) glColor4ub(255, 255, 255, 200);
411                 else glColor4ub(0, 0, 0, 50);
412                 
413                 glEnable( GL_POLYGON_SMOOTH );
414                 glBegin(GL_TRIANGLES);
415                 glVertex2fv(v1); glVertex2fv(v2); glVertex2fv(v3);
416                 glEnd();
417                 
418                 glDisable( GL_POLYGON_SMOOTH );
419                 glDisable( GL_BLEND );
420         }
421         
422         if(G.moving || (seq->flag & whichsel)) {
423                 cpack(0xFFFFFF);
424                 if (direction == SEQ_LEFTHANDLE) {
425                         sprintf(str, "%d", seq->startdisp);
426                         glRasterPos3f(rx1,  y1-0.15, 0.0);
427                 } else {
428                         sprintf(str, "%d", seq->enddisp - 1);
429                         glRasterPos3f((x2-BMF_GetStringWidth(G.fonts, str)*pixelx),  y2+0.05, 0.0);
430                 }
431                 BMF_DrawString(G.fonts, str);
432         }       
433 }
434
435 static void draw_seq_extensions(Sequence *seq, SpaceSeq *sseq)
436 {
437         float x1, x2, y1, y2, pixely, a;
438         char col[3], blendcol[3];
439         View2D *v2d;
440         
441         if(seq->type >= SEQ_EFFECT) return;
442
443         x1= seq->startdisp;
444         x2= seq->enddisp;
445         
446         y1= seq->machine+SEQ_STRIP_OFSBOTTOM;
447         y2= seq->machine+SEQ_STRIP_OFSTOP;
448         
449         v2d = &sseq->v2d;
450         pixely = (v2d->cur.ymax - v2d->cur.ymin)/(v2d->mask.ymax - v2d->mask.ymin);
451         
452         blendcol[0] = blendcol[1] = blendcol[2] = 120;
453
454         if(seq->startofs) {
455                 glEnable( GL_BLEND );
456                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
457                 
458                 get_seq_color3ubv(seq, col);
459                 
460                 if (seq->flag & SELECT) {
461                         BIF_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
462                         glColor4ub(col[0], col[1], col[2], 170);
463                 } else {
464                         BIF_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
465                         glColor4ub(col[0], col[1], col[2], 110);
466                 }
467                 
468                 glRectf((float)(seq->start), y1-SEQ_STRIP_OFSBOTTOM, x1, y1);
469                 
470                 if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
471                 else glColor4ub(col[0], col[1], col[2], 160);
472
473                 fdrawbox((float)(seq->start), y1-SEQ_STRIP_OFSBOTTOM, x1, y1);  //outline
474                 
475                 glDisable( GL_BLEND );
476         }
477         if(seq->endofs) {
478                 glEnable( GL_BLEND );
479                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
480                 
481                 get_seq_color3ubv(seq, col);
482                 
483                 if (seq->flag & SELECT) {
484                         BIF_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
485                         glColor4ub(col[0], col[1], col[2], 170);
486                 } else {
487                         BIF_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
488                         glColor4ub(col[0], col[1], col[2], 110);
489                 }
490                 
491                 glRectf(x2, y2, (float)(seq->start+seq->len), y2+SEQ_STRIP_OFSBOTTOM);
492                 
493                 if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
494                 else glColor4ub(col[0], col[1], col[2], 160);
495
496                 fdrawbox(x2, y2, (float)(seq->start+seq->len), y2+SEQ_STRIP_OFSBOTTOM); //outline
497                 
498                 glDisable( GL_BLEND );
499         }
500         if(seq->startstill) {
501                 get_seq_color3ubv(seq, col);
502                 BIF_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
503                 glColor3ubv((GLubyte *)col);
504                 
505                 draw_shadedstrip(seq, col, x1, y1, (float)(seq->start), y2);
506                 
507                 /* feint pinstripes, helps see exactly which is extended and which isn't,
508                 * especially when the extension is very small */ 
509                 if (seq->flag & SELECT) BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
510                 else BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -16);
511                 
512                 glColor3ubv((GLubyte *)col);
513                 
514                 for(a=y1; a< y2; a+= pixely*2.0 ) {
515                         fdrawline(x1,  a,  (float)(seq->start),  a);
516                 }
517         }
518         if(seq->endstill) {
519                 get_seq_color3ubv(seq, col);
520                 BIF_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
521                 glColor3ubv((GLubyte *)col);
522                 
523                 draw_shadedstrip(seq, col, (float)(seq->start+seq->len), y1, x2, y2);
524                 
525                 /* feint pinstripes, helps see exactly which is extended and which isn't,
526                 * especially when the extension is very small */ 
527                 if (seq->flag & SELECT) BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
528                 else BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -16);
529                 
530                 glColor3ubv((GLubyte *)col);
531                 
532                 for(a=y1; a< y2; a+= pixely*2.0 ) {
533                         fdrawline((float)(seq->start+seq->len),  a,  x2,  a);
534                 }
535         }
536 }
537
538 /* draw info text on a sequence strip */
539 static void draw_seq_text(Sequence *seq, float x1, float x2, float y1, float y2)
540 {
541         float v1[2], v2[2];
542         int len, size;
543         char str[32 + FILE_MAXDIR+FILE_MAXFILE], *strp;
544         short mval[2];
545         
546         v1[1]= y1;
547         v2[1]= y2;
548         
549         v1[0]= x1;
550         ipoco_to_areaco_noclip(G.v2d, v1, mval);
551         x1= mval[0];
552         v2[0]= x2;
553         ipoco_to_areaco_noclip(G.v2d, v2, mval);
554         x2= mval[0];
555         size= x2-x1;
556         
557         if(seq->name[2]) {
558                 sprintf(str, "%d | %s: %s", seq->len, give_seqname(seq), seq->name+2);
559         }else{
560                 if(seq->type == SEQ_META) {
561                         sprintf(str, "%d | %s", seq->len, give_seqname(seq));
562                 }
563                 else if(seq->type == SEQ_SCENE) {
564                         if(seq->scene) sprintf(str, "%d | %s: %s", seq->len, give_seqname(seq), seq->scene->id.name+2);
565                         else sprintf(str, "%d | %s", seq->len, give_seqname(seq));
566                         
567                 }
568                 else if(seq->type == SEQ_IMAGE) {
569                         sprintf(str, "%d | %s%s", seq->len, seq->strip->dir, seq->strip->stripdata->name);
570                 }
571                 else if(seq->type & SEQ_EFFECT) {
572                         int can_float = (seq->type != SEQ_PLUGIN)
573                                 || (seq->plugin && seq->plugin->version >= 4);
574
575                         if(seq->seq3!=seq->seq2 && seq->seq1!=seq->seq3)
576                                 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!");
577                         else if (seq->seq1 && seq->seq2)
578                                 sprintf(str, "%d | %s: %d>%d%s", seq->len, give_seqname(seq), seq->seq1->machine, seq->seq2->machine, can_float ? "" : " No float, upgrade plugin!");
579                         else 
580                                 sprintf(str, "%d | %s", seq->len, give_seqname(seq));
581                 }
582                 else if (seq->type == SEQ_RAM_SOUND) {
583                         sprintf(str, "%d | %s", seq->len, seq->strip->stripdata->name);
584                 }
585                 else if (seq->type == SEQ_HD_SOUND) {
586                         sprintf(str, "%d | %s", seq->len, seq->strip->stripdata->name);
587                 }
588                 else if (seq->type == SEQ_MOVIE) {
589                         sprintf(str, "%d | %s%s", seq->len, seq->strip->dir, seq->strip->stripdata->name);
590                 }
591         }
592         
593         strp= str;
594         
595         while( (len= BMF_GetStringWidth(G.font, strp)) > size) {
596                 if(len < 10) break;
597                 if(strp[1]==0) break;
598                 strp++;
599         }
600         
601         mval[0]= (x1+x2-len+1)/2;
602         mval[1]= 1;
603         areamouseco_to_ipoco(G.v2d, mval, &x1, &x2);
604         
605         if(seq->flag & SELECT) cpack(0xFFFFFF);
606         else cpack(0);
607         glRasterPos3f(x1,  y1+SEQ_STRIP_OFSBOTTOM, 0.0);
608         BMF_DrawString(G.font, strp);
609 }
610
611 /* draws a shaded strip, made from gradient + flat color + gradient */
612 static void draw_shadedstrip(Sequence *seq, char *col, float x1, float y1, float x2, float y2)
613 {
614         float ymid1, ymid2;
615         
616         if (seq->flag & SEQ_MUTE) {
617                 glEnable(GL_POLYGON_STIPPLE);
618                 glPolygonStipple(stipple_halftone);
619         }
620         
621         ymid1 = (y2-y1)*0.25 + y1;
622         ymid2 = (y2-y1)*0.65 + y1;
623         
624         glShadeModel(GL_SMOOTH);
625         glBegin(GL_QUADS);
626         
627         if(seq->flag & SELECT) BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -50);
628         else BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 0);
629         
630         glColor3ubv((GLubyte *)col);
631         
632         glVertex2f(x1,y1);
633         glVertex2f(x2,y1);
634         
635         if(seq->flag & SELECT) BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 5);
636         else BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -5);
637
638         glColor3ubv((GLubyte *)col);
639         
640         glVertex2f(x2,ymid1);
641         glVertex2f(x1,ymid1);
642         
643         glEnd();
644         
645         glRectf(x1,  ymid1,  x2,  ymid2);
646         
647         glBegin(GL_QUADS);
648         
649         glVertex2f(x1,ymid2);
650         glVertex2f(x2,ymid2);
651         
652         if(seq->flag & SELECT) BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -15);
653         else BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 25);
654         
655         glColor3ubv((GLubyte *)col);
656         
657         glVertex2f(x2,y2);
658         glVertex2f(x1,y2);
659         
660         glEnd();
661         
662         if (seq->flag & SEQ_MUTE) {
663                 glDisable(GL_POLYGON_STIPPLE);
664         }
665 }
666
667 /*
668 Draw a sequence strip, bounds check alredy made
669 ScrArea is currently only used to get the windows width in pixels
670 so wave file sample drawing precission is zoom adjusted
671 */
672 static void draw_seq_strip(Sequence *seq, ScrArea *sa, SpaceSeq *sseq, int outline_tint, float pixelx)
673 {
674         float x1, x2, y1, y2;
675         char col[3], is_single_image;
676
677         /* we need to know if this is a single image/color or not for drawing */
678         is_single_image = (char)check_single_seq(seq);
679         
680         /* body */
681         if(seq->startstill) x1= seq->start;
682         else x1= seq->startdisp;
683         y1= seq->machine+SEQ_STRIP_OFSBOTTOM;
684         if(seq->endstill) x2= seq->start+seq->len;
685         else x2= seq->enddisp;
686         y2= seq->machine+SEQ_STRIP_OFSTOP;
687         
688         
689         /* get the correct color per strip type*/
690         get_seq_color3ubv(seq, col);
691         
692         /* draw the main strip body */
693         if (is_single_image) /* single image */
694                 draw_shadedstrip(seq, col, seq_tx_get_final_left(seq, 0), y1, seq_tx_get_final_right(seq, 0), y2);
695         else /* normal operation */
696                 draw_shadedstrip(seq, col, x1, y1, x2, y2);
697         
698         /* draw additional info and controls */
699         if (seq->type == SEQ_RAM_SOUND)
700                 drawseqwave(seq, x1, y1, x2, y2, sa->winx);
701         
702         if (!is_single_image)
703                 draw_seq_extensions(seq, sseq);
704         
705         draw_seq_handle(seq, sseq, pixelx, SEQ_LEFTHANDLE);
706         draw_seq_handle(seq, sseq, pixelx, SEQ_RIGHTHANDLE);
707         
708         /* draw the strip outline */
709         x1= seq->startdisp;
710         x2= seq->enddisp;
711         
712         get_seq_color3ubv(seq, col);
713         if (G.moving && (seq->flag & SELECT)) {
714                 if(seq->flag & SEQ_OVERLAP) {
715                         col[0]= 255; col[1]= col[2]= 40;
716                 } else BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 120);
717         }
718
719         BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, outline_tint);
720         
721         glColor3ubv((GLubyte *)col);
722         
723         if (seq->flag & SEQ_MUTE) {
724                 glEnable(GL_LINE_STIPPLE);
725                 glLineStipple(1, 0x8888);
726         }
727         
728         gl_round_box_shade(GL_LINE_LOOP, x1, y1, x2, y2, 0.0, 0.1, 0.0);
729         
730         if (seq->flag & SEQ_MUTE) {
731                 glDisable(GL_LINE_STIPPLE);
732         }
733         
734         /* calculate if seq is long enough to print a name */
735         x1= seq->startdisp+seq->handsize;
736         x2= seq->enddisp-seq->handsize;
737
738         /* but first the contents of a meta */
739         if(seq->type==SEQ_META) drawmeta_contents(seq, x1, y1+0.15, x2, y2-0.15);
740
741         /* info text on the strip */
742         if(x1<G.v2d->cur.xmin) x1= G.v2d->cur.xmin;
743         else if(x1>G.v2d->cur.xmax) x1= G.v2d->cur.xmax;
744         if(x2<G.v2d->cur.xmin) x2= G.v2d->cur.xmin;
745         else if(x2>G.v2d->cur.xmax) x2= G.v2d->cur.xmax;
746
747         /* nice text here would require changing the view matrix for texture text */
748         if( (x2-x1) / pixelx > 32) {
749                 draw_seq_text(seq, x1, x2, y1, y2);
750         }
751 }
752
753 static Sequence *special_seq_update= 0;
754
755 void set_special_seq_update(int val)
756 {
757         int x;
758
759         /* if mouse over a sequence && LEFTMOUSE */
760         if(val) {
761                 special_seq_update= find_nearest_seq(&x);
762         }
763         else special_seq_update= 0;
764 }
765
766
767 static void draw_image_seq(ScrArea *sa)
768 {
769         SpaceSeq *sseq;
770         struct ImBuf *ibuf;
771         int x1, y1, rectx, recty;
772         int free_ibuf = 0;
773         static int recursive= 0;
774         float zoom;
775         float zoomx, zoomy;
776
777         glClearColor(0.0, 0.0, 0.0, 0.0);
778         glClear(GL_COLOR_BUFFER_BIT);
779
780         sseq= sa->spacedata.first;
781         if(sseq==0) return;
782
783         rectx= (G.scene->r.size*G.scene->r.xsch)/100;
784         recty= (G.scene->r.size*G.scene->r.ysch)/100;
785
786         /* BIG PROBLEM: the give_ibuf_seq() can call a rendering, which in turn calls redraws...
787            this shouldn't belong in a window drawing....
788            So: solve this once event based. 
789            Now we check for recursion, space type and active area again (ton) */
790         
791         if(recursive)
792                 return;
793         else {
794                 recursive= 1;
795                 if (special_seq_update) {
796                         ibuf= give_ibuf_seq_direct(
797                                 rectx, recty, (G.scene->r.cfra),
798                                 special_seq_update);
799                 } else if (!U.prefetchframes || (G.f & G_PLAYANIM) == 0) {
800                         ibuf= (ImBuf *)give_ibuf_seq(
801                                 rectx, recty, (G.scene->r.cfra), 
802                                 sseq->chanshown);
803                 } else {
804                         ibuf= (ImBuf *)give_ibuf_seq_threaded(
805                                 rectx, recty, (G.scene->r.cfra), 
806                                 sseq->chanshown);
807                 }
808                 recursive= 0;
809                 
810                 /* HURMF! the give_ibuf_seq can call image display in this window */
811                 if(sa->spacetype!=SPACE_SEQ)
812                         return;
813                 if(sa!=curarea) {
814                         areawinset(sa->win);
815                 }
816         }
817         
818         if(ibuf==NULL) 
819                 return;
820
821         if(ibuf->rect==NULL && ibuf->rect_float == NULL) 
822                 return;
823
824         switch(sseq->mainb) {
825         case SEQ_DRAW_IMG_IMBUF:
826                 if (sseq->zebra != 0) {
827                         ibuf = make_zebra_view_from_ibuf(ibuf, sseq->zebra);
828                         free_ibuf = 1;
829                 }
830                 break;
831         case SEQ_DRAW_IMG_WAVEFORM:
832                 if ((sseq->flag & SEQ_DRAW_COLOR_SEPERATED) != 0) {
833                         ibuf = make_sep_waveform_view_from_ibuf(ibuf);
834                 } else {
835                         ibuf = make_waveform_view_from_ibuf(ibuf);
836                 }
837                 free_ibuf = 1;
838                 break;
839         case SEQ_DRAW_IMG_VECTORSCOPE:
840                 ibuf = make_vectorscope_view_from_ibuf(ibuf);
841                 free_ibuf = 1;
842                 break;
843         case SEQ_DRAW_IMG_HISTOGRAM:
844                 ibuf = make_histogram_view_from_ibuf(ibuf);
845                 free_ibuf = 1;
846                 break;
847         }
848
849         if(ibuf->rect_float && ibuf->rect==NULL)
850                 IMB_rect_from_float(ibuf);
851
852         if (sseq->zoom > 0) {
853                 zoom = sseq->zoom;
854         } else if (sseq->zoom == 0) {
855                 zoom = 1.0;
856         } else {
857                 zoom = -1.0/sseq->zoom;
858         }
859
860         /* needed for gla draw */
861         glaDefine2DArea(&curarea->winrct);
862         if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
863                 zoomx = zoom * ((float)G.scene->r.xasp / (float)G.scene->r.yasp);
864                 zoomy = zoom;
865         } else {
866                 zoomx = zoomy = zoom;
867         }
868
869         /* calc location */
870         x1= (sa->winx-zoomx*ibuf->x)/2 + sseq->xof;
871         y1= (sa->winy-zoomy*ibuf->y)/2 + sseq->yof;
872         
873         glPixelZoom(zoomx, zoomy);
874         
875         glaDrawPixelsSafe(x1, y1, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
876         
877         glPixelZoom(1.0, 1.0);
878
879         /* safety border */
880         if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && 
881             (sseq->flag & SEQ_DRAW_SAFE_MARGINS) != 0) {
882                 float fac= 0.1;
883                 float x2 = x1 + ibuf->x * zoomx;
884                 float y2 = y1 + ibuf->y * zoomy;
885                 
886                 float a= fac*(x2-x1);
887                 x1+= a; 
888                 x2-= a;
889         
890                 a= fac*(y2-y1);
891                 y1+= a;
892                 y2-= a;
893         
894                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
895                 setlinestyle(3);
896
897                 BIF_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0);
898                 
899                 uiSetRoundBox(15);
900                 gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 12.0);
901
902                 setlinestyle(0);
903                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
904         }
905
906
907         if (free_ibuf) {
908                 IMB_freeImBuf(ibuf);
909         } 
910
911         sa->win_swap= WIN_BACK_OK;
912 }
913
914 void seq_reset_imageofs(SpaceSeq *sseq)
915 {
916         sseq->xof = sseq->yof = sseq->zoom = 0;
917 }
918
919 void seq_home(void)
920 {
921         SpaceSeq *sseq= curarea->spacedata.first;
922         
923         if (!sseq->mainb) {
924                 G.v2d->cur= G.v2d->tot;
925                 test_view2d(G.v2d, curarea->winx, curarea->winy);
926                 view2d_do_locks(curarea, V2D_LOCK_COPY);
927         } else {
928                 float zoomX, zoomY;
929                 int width, height, imgwidth, imgheight; 
930                 
931                 width = curarea->winx;
932                 height = curarea->winy;
933                 
934                 seq_reset_imageofs(sseq);
935                 
936                 imgwidth= (G.scene->r.size*G.scene->r.xsch)/100;
937                 imgheight= (G.scene->r.size*G.scene->r.ysch)/100;
938                 
939                 /* Apply aspect, dosnt need to be that accurate */
940                 imgwidth= (int)(imgwidth * ((float)G.scene->r.xasp / (float)G.scene->r.yasp));
941                 
942                 if (((imgwidth >= width) || (imgheight >= height)) && 
943                         ((width > 0) && (height > 0))) {
944                         
945                         /* Find the zoom value that will fit the image in the image space */
946                         zoomX = ((float)width) / ((float)imgwidth);
947                         zoomY = ((float)height) / ((float)imgheight);
948                         sseq->zoom= (zoomX < zoomY) ? zoomX : zoomY;
949         
950                         sseq->zoom = 1.0f / power_of_2(1/ MIN2(zoomX, zoomY) );
951                 }
952                 else {
953                         sseq->zoom= 1.0f;
954                 }
955         }
956         scrarea_queue_winredraw(curarea);
957 }
958
959 void seq_viewzoom(unsigned short event, int invert)
960 {
961         SpaceSeq *sseq= curarea->spacedata.first;
962
963         if(event==PAD1)
964                 sseq->zoom= 1.0;
965         else if(event==PAD2)
966                 sseq->zoom= (invert)? 2.0: 0.5;
967         else if(event==PAD4)
968                 sseq->zoom= (invert)? 4.0: 0.25;
969         else if(event==PAD8)
970                 sseq->zoom= (invert)? 8.0: 0.125;
971         
972         /* ensure pixel exact locations for draw */
973         sseq->xof= (int)sseq->xof;
974         sseq->yof= (int)sseq->yof;
975 }
976
977 void seq_viewmove(SpaceSeq *sseq)
978 {       
979         ScrArea *sa;
980         short mval[2], mvalo[2];
981         short rectx, recty, xmin, xmax, ymin, ymax, pad;
982         int oldcursor;
983         Window *win;
984         
985         sa = sseq->area;
986         rectx= (G.scene->r.size*G.scene->r.xsch)/100;
987         recty= (G.scene->r.size*G.scene->r.ysch)/100;
988         
989         pad = 10;
990         xmin = -(sa->winx/2) - rectx/2 + pad;
991         xmax = sa->winx/2 + rectx/2 - pad;
992         ymin = -(sa->winy/2) - recty/2 + pad;
993         ymax = sa->winy/2 + recty/2 - pad;
994         
995         getmouseco_sc(mvalo);
996
997         oldcursor=get_cursor();
998         win=winlay_get_active_window();
999         
1000         SetBlenderCursor(BC_NSEW_SCROLLCURSOR);
1001         
1002         while(get_mbut()&(L_MOUSE|M_MOUSE)) {
1003                 
1004                 getmouseco_sc(mval);
1005                 
1006                 if(mvalo[0]!=mval[0] || mvalo[1]!=mval[1]) {
1007
1008                         sseq->xof -= (mvalo[0]-mval[0]);
1009                         sseq->yof -= (mvalo[1]-mval[1]);
1010                         
1011                         /* prevent dragging image outside of the window and losing it! */
1012                         CLAMP(sseq->xof, xmin, xmax);
1013                         CLAMP(sseq->yof, ymin, ymax);
1014                         
1015                         mvalo[0]= mval[0];
1016                         mvalo[1]= mval[1];
1017                         
1018                         scrarea_do_windraw(curarea);
1019                         screen_swapbuffers();
1020                 }
1021                 else BIF_wait_for_statechange();
1022         }
1023         window_set_cursor(win, oldcursor);
1024 }
1025
1026
1027
1028 static void seq_blockhandlers(ScrArea *sa)
1029 {
1030         SpaceSeq *sseq= sa->spacedata.first;
1031         short a;
1032
1033         /* warning; blocks need to be freed each time, handlers dont remove (for ipo moved to drawipospace) */
1034         uiFreeBlocksWin(&sa->uiblocks, sa->win);
1035
1036         for(a=0; a<SPACE_MAXHANDLER; a+=2) {
1037                 /* clear action value for event */
1038                 sseq->blockhandler[a+1]= 0;
1039         }
1040         uiDrawBlocksPanels(sa, 0);
1041
1042 }
1043
1044 void drawprefetchseqspace(ScrArea *sa, void *spacedata)
1045 {
1046         SpaceSeq *sseq= sa->spacedata.first;
1047         int rectx, recty;
1048
1049         rectx= (G.scene->r.size*G.scene->r.xsch)/100;
1050         recty= (G.scene->r.size*G.scene->r.ysch)/100;
1051
1052         if(sseq->mainb) {
1053                 give_ibuf_prefetch_request(
1054                         rectx, recty, (G.scene->r.cfra), sseq->chanshown);
1055         }
1056 }
1057
1058 void drawseqspace(ScrArea *sa, void *spacedata)
1059 {
1060         SpaceSeq *sseq= sa->spacedata.first;
1061         View2D *v2d= &sseq->v2d;
1062         Editing *ed;
1063         Sequence *seq;
1064         float col[3];
1065         int ofsx, ofsy;
1066         int i;
1067
1068         ed= G.scene->ed;
1069
1070         if(sseq->mainb) {
1071                 draw_image_seq(sa);
1072                 return;
1073         }
1074
1075         bwin_clear_viewmat(sa->win);    /* clear buttons view */
1076         glLoadIdentity();
1077
1078         BIF_GetThemeColor3fv(TH_BACK, col);
1079         if(ed && ed->metastack.first) glClearColor(col[0], col[1], col[2]-0.1, 0.0);
1080         else glClearColor(col[0], col[1], col[2], 0.0);
1081
1082         glClear(GL_COLOR_BUFFER_BIT);
1083
1084         calc_scrollrcts(sa, v2d, sa->winx, sa->winy);
1085
1086         if(sa->winx>SCROLLB+10 && sa->winy>SCROLLH+10) {
1087                 if(v2d->scroll) {
1088                         ofsx= sa->winrct.xmin;  /* because of mywin */
1089                         ofsy= sa->winrct.ymin;
1090                         glViewport(ofsx+v2d->mask.xmin,  ofsy+v2d->mask.ymin, ( ofsx+v2d->mask.xmax-1)-(ofsx+v2d->mask.xmin)+1, ( ofsy+v2d->mask.ymax-1)-( ofsy+v2d->mask.ymin)+1);
1091                         glScissor(ofsx+v2d->mask.xmin,  ofsy+v2d->mask.ymin, ( ofsx+v2d->mask.xmax-1)-(ofsx+v2d->mask.xmin)+1, ( ofsy+v2d->mask.ymax-1)-( ofsy+v2d->mask.ymin)+1);
1092                 }
1093         }
1094
1095
1096         myortho2(v2d->cur.xmin, v2d->cur.xmax, v2d->cur.ymin, v2d->cur.ymax);
1097
1098         BIF_ThemeColorShade(TH_BACK, -20);
1099         glRectf(v2d->cur.xmin,  0.0,  v2d->cur.xmax,  1.0);
1100
1101         
1102         boundbox_seq();
1103         calc_ipogrid();
1104         
1105         /* Alternating horizontal stripes */
1106         i= MAX2(1, ((int)G.v2d->cur.ymin)-1);
1107
1108         glBegin(GL_QUADS);
1109         while (i<v2d->cur.ymax) {
1110                 if (((int)i) & 1)
1111                         BIF_ThemeColorShade(TH_BACK, -15);
1112                 else
1113                         BIF_ThemeColorShade(TH_BACK, -25);
1114                 
1115                 glVertex2f(v2d->cur.xmax, i);
1116                 glVertex2f(v2d->cur.xmin, i);
1117                 glVertex2f(v2d->cur.xmin, i+1);
1118                 glVertex2f(v2d->cur.xmax, i+1);
1119                 i+=1.0;
1120         }
1121         glEnd();
1122         
1123         /* Force grid lines */
1124         i= MAX2(1, ((int)G.v2d->cur.ymin)-1);
1125         glBegin(GL_LINES);
1126
1127         while (i<G.v2d->cur.ymax) {
1128                 BIF_ThemeColor(TH_GRID);
1129                 glVertex2f(G.v2d->cur.xmax, i);
1130                 glVertex2f(G.v2d->cur.xmin, i);
1131                 i+=1.0;
1132         }
1133         glEnd();
1134         
1135         
1136         draw_ipogrid();
1137         draw_cfra_seq();
1138
1139
1140         /* sequences: first deselect */
1141         if(ed) {
1142                 Sequence *last_seq = get_last_seq();
1143                 int sel = 0, j;
1144                 int outline_tint;
1145                 float pixelx = (v2d->cur.xmax - v2d->cur.xmin)/(v2d->mask.xmax - v2d->mask.xmin);
1146                 /* loop through twice, first unselected, then selected */
1147                 for (j=0; j<2; j++) {
1148                         seq= ed->seqbasep->first;
1149                         if (j==0)       outline_tint = -150;
1150                         else            outline_tint = -60;
1151                         
1152                         while(seq) { /* bound box test, dont draw outside the view */
1153                                 if (  ((seq->flag & SELECT) == sel) ||
1154                                                 seq == last_seq ||
1155                                                 MIN2(seq->startdisp, seq->start) > v2d->cur.xmax ||
1156                                                 MAX2(seq->enddisp, seq->start+seq->len) < v2d->cur.xmin ||
1157                                                 seq->machine+1.0 < v2d->cur.ymin ||
1158                                                 seq->machine > v2d->cur.ymax)
1159                                 {
1160                                         /* dont draw */
1161                                 } else {
1162                                         draw_seq_strip(seq, sa, sseq, outline_tint, pixelx);
1163                                 }
1164                                 seq= seq->next;
1165                         }
1166                         sel= SELECT; /* draw selected next time round */
1167                 }
1168                 /* draw the last selected last, removes some overlapping error */
1169                 if (last_seq) {
1170                         draw_seq_strip(last_seq, sa, sseq, 120, pixelx);
1171                 }
1172         }
1173
1174         /* Draw markers */
1175         draw_markers_timespace(SCE_MARKERS, DRAW_MARKERS_LINES);
1176         
1177         /* restore viewport */
1178         mywinset(sa->win);
1179
1180         /* ortho at pixel level sa */
1181         myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
1182
1183         if(sa->winx>SCROLLB+10 && sa->winy>SCROLLH+10) {
1184                 if(v2d->scroll) {
1185                         drawscroll(0);
1186                 }
1187         }
1188
1189         draw_area_emboss(sa);
1190
1191         if(sseq->mainb==0) {
1192                 /* it is important to end a view in a transform compatible with buttons */
1193                 bwin_scalematrix(sa->win, sseq->blockscale, sseq->blockscale, sseq->blockscale);
1194                 seq_blockhandlers(sa);
1195         }
1196
1197         sa->win_swap= WIN_BACK_OK;
1198 }
1199
1200