Fixed a few problems with wave drawing-
[blender.git] / source / blender / src / drawseq.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36
37 #include <string.h>
38 #include <math.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "BMF_Api.h"
43
44 #include "BLI_blenlib.h"
45 #include "BLI_arithb.h"
46
47 #include "IMB_imbuf_types.h"
48
49 #include "DNA_sequence_types.h"
50 #include "DNA_scene_types.h"
51 #include "DNA_screen_types.h"
52 #include "DNA_space_types.h"
53 #include "DNA_view2d_types.h"
54
55 #include "BKE_global.h"
56 #include "BKE_plugin_types.h"
57 #include "BKE_scene.h"
58 #include "BKE_utildefines.h"
59
60 #include "BIF_gl.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_seqaudio.h"
74
75 #include "IMB_imbuf_types.h"
76 #include "IMB_imbuf.h"
77
78 #include "blendef.h"    /* CFRA */
79 #include "mydevice.h"   /* REDRAWSEQ */
80
81 int no_rightbox=0, no_leftbox= 0;
82
83 static void EmbossBoxf(float x1, float y1, float x2, float y2, int sel, unsigned int dark, unsigned int light)
84 {
85
86         if(sel) cpack(dark);
87         else cpack(light);
88         if(sel) glLineWidth(2.0);
89         fdrawline(x1,  y2,  x2,  y2);   /* top */
90         if(no_leftbox==0) fdrawline(x1,  y1,  x1,  y2); /* left */
91
92         if(sel) glLineWidth(1.0);
93
94         if(sel) cpack(light);
95         else cpack(dark);
96         fdrawline(x1,  y1,  x2,  y1); /* bottom */
97         if(no_rightbox==0) fdrawline(x2,  y1,  x2,  y2);        /* right */
98
99 }
100
101 static char *give_seqname(Sequence *seq)
102 {
103         if(seq->type==SEQ_META) {
104                 if(seq->name[2]) return seq->name+2;
105                 return "META";
106         }
107         else if(seq->type==SEQ_IMAGE) return "IMAGE";
108         else if(seq->type==SEQ_SCENE) return "SCENE";
109         else if(seq->type==SEQ_MOVIE) return "MOVIE";
110         else if(seq->type==SEQ_SOUND) return "AUDIO";
111         else if(seq->type<SEQ_EFFECT) return seq->strip->dir;
112         else if(seq->type==SEQ_CROSS) return "CROSS";
113         else if(seq->type==SEQ_GAMCROSS) return "GAMMA CROSS";
114         else if(seq->type==SEQ_ADD) return "ADD";
115         else if(seq->type==SEQ_SUB) return "SUB";
116         else if(seq->type==SEQ_MUL) return "MUL";
117         else if(seq->type==SEQ_ALPHAOVER) return "ALPHAOVER";
118         else if(seq->type==SEQ_ALPHAUNDER) return "ALPHAUNDER";
119         else if(seq->type==SEQ_OVERDROP) return "OVER DROP";
120         else if(seq->type==SEQ_WIPE) return "WIPE";
121         else if(seq->type==SEQ_GLOW) return "GLOW";
122         else if(seq->type==SEQ_PLUGIN) {
123                 if(seq->plugin && seq->plugin->doit) return seq->plugin->pname;
124                 return "PLUGIN";
125         }
126         else return "EFFECT";
127
128 }
129 static void draw_cfra_seq(void)
130 {
131         glColor3ub(0x30, 0x90, 0x50);
132         glLineWidth(2.0);
133         glBegin(GL_LINES);
134         glVertex2f(G.scene->r.cfra, G.v2d->cur.ymin);
135         glVertex2f(G.scene->r.cfra, G.v2d->cur.ymax);
136         glEnd();
137         glLineWidth(1.0);
138 }
139
140 static unsigned int seq_color(Sequence *seq)
141 {
142         switch(seq->type) {
143         case SEQ_META:
144                 return 0x509090;
145         case SEQ_MOVIE:
146                 return 0x805040;
147         case SEQ_SCENE:
148                 if(seq->scene==G.scene) return 0x709050;
149                 return 0x609060;
150         case SEQ_CROSS:
151                 return 0x505090;
152         case SEQ_GAMCROSS:
153                 return 0x5040A0;
154         case SEQ_ADD:
155                 return 0x6060A0;
156         case SEQ_SUB:
157                 return 0x8060A0;
158         case SEQ_MUL:
159                 return 0x8080A0;
160         case SEQ_ALPHAOVER:
161                 return 0x6080A0;
162         case SEQ_ALPHAUNDER:
163                 return 0x9080A0;
164         case SEQ_OVERDROP:
165                 return 0x5080B0;
166         case SEQ_WIPE:
167                 return 0x2080B0;
168         case SEQ_GLOW:
169                 return 0x0080B0;
170         case SEQ_PLUGIN:
171                 return 0x906000;
172         case SEQ_SOUND:
173                 if(seq->flag & SEQ_MUTE) return 0x707060; else return 0x787850;
174         default:
175                 return 0x906060;
176         }
177
178 }
179 static void drawmeta_contents(Sequence *seqm, float x1, float y1, float x2, float y2)
180 {
181         Sequence *seq;
182         float dx;
183         int nr;
184
185         nr= 0;
186         WHILE_SEQ(&seqm->seqbase) {
187                 nr++;
188         }
189         END_SEQ
190
191         dx= (x2-x1)/nr;
192
193         WHILE_SEQ(&seqm->seqbase) {
194                 cpack(seq_color(seq));
195                 glRectf(x1,  y1,  x1+0.9*dx,  y2);
196                 EmbossBoxf(x1, y1, x1+0.9*dx, y2, 0, 0x404040, 0xB0B0B0);
197                 x1+= dx;
198         }
199         END_SEQ
200 }
201
202 static void drawseqwave(Sequence *seq, float x1, float y1, float x2, float y2, int winx)
203 {
204         float f, height, midy, clipxmin, clipxmax, sample_step;
205         int offset, offset_next, sofs, eofs;
206         signed short* s;
207         bSound *sound;
208         int wavesample, wavesamplemin, wavesamplemax, subsample_step=4; /* used for finding the min and max wave peaks */
209         Uint8 *stream;
210         float fsofs, feofs_sofs, sound_width; /* for faster access in the loop */
211         
212         audio_makestream(seq->sound);
213         if(seq->sound->stream==NULL) return;    
214         
215         if (seq->flag & SEQ_MUTE) glColor3ub(0x70, 0x80, 0x80); else glColor3ub(0x70, 0xc0, 0xc0);
216         
217         sofs = ((int)( (((float)(seq->startdisp-seq->start))/(float)G.scene->r.frs_sec)*(float)G.scene->audio.mixrate*4.0 )) & (~3);
218         eofs = ((int)( (((float)(seq->enddisp-seq->start))/(float)G.scene->r.frs_sec)*(float)G.scene->audio.mixrate*4.0 )) & (~3);
219         
220         /* clip the drawing area to the screen bounds to save time */
221         sample_step= (G.v2d->cur.xmax-G.v2d->cur.xmin)/winx;
222         clipxmin= MAX2(x1, G.v2d->cur.xmin);
223         clipxmax= MIN2(x2, G.v2d->cur.xmax);
224         
225         
226         /* Align the clipxmin to the sample step
227         this stops dithering when the wave is being clipped on the left hand side
228         With adaptive sample picking (subsample_step>4) this dosent work */
229         
230         /* f=x1;
231         while (f<clipxmin)
232                 f+=sample_step;
233         clipxmin=f; */
234         
235         
236         /* when the sample step is 4 every sample of the wave is evaluated for min and max
237         values used to draw the wave, however this is slow ehrn zoomed out
238         so when the sample step is above 1 (the larger the further out the zoom is)
239         so not evaluate all samples, only some.*/
240         if (sample_step > 1)
241                 subsample_step= ((int)(subsample_step*sample_step*8)) & (~3);
242         
243         /* for speedy access */
244         midy = (y1+y2)/2;
245         fsofs= (float)sofs;
246         feofs_sofs= (float)(eofs-sofs);
247         sound_width= x2-x1;
248         height= y2-y1;
249         sound = seq->sound;
250         stream = sound->stream;
251         wavesample=0;
252         
253         /* we need to get the starting offset value, excuse the duplicate code */
254         f=clipxmin;
255         offset = (int) (fsofs + ((f-x1)/sound_width) * feofs_sofs) & (~3);
256         
257         /* start the loop, draw a line per sample_step -sample_step is about 1 line drawn per pixel */
258         glBegin(GL_LINES);
259         for (f=clipxmin+sample_step; f<=clipxmax; f+=sample_step) {
260                 
261                 offset_next = (int) (fsofs + ((f-x1)/sound_width) * feofs_sofs) & (~3);
262                 
263                 /* if this is close to the last sample just exit */
264                 if (offset_next >= sound->streamlen) break;
265                 
266                 wavesamplemin = 655360;
267                 wavesamplemax = -655360;
268                 
269                 /*find with high and low of the waveform for this draw,
270                 evaluate small samples to find this range */
271                 while (offset <= offset_next) {
272                         s = (signed short*)(stream+offset);
273                         
274                         wavesample = s[0] + s[1]/2;
275                         if (wavesamplemin>wavesample)
276                                 wavesamplemin=wavesample;
277                         if (wavesamplemax<wavesample)
278                                 wavesamplemax=wavesample;
279                         offset+=subsample_step;
280                 }
281                 /* draw the wave line, looks good up close and zoomed out */
282                 glVertex2f(f,  midy-(((((float)wavesamplemin)/65536)* height)/2) );
283                 glVertex2f(f,  midy-(((((float)wavesamplemax)/65536)* height)/2) );
284                 offset=offset_next;
285         }
286         glEnd();
287 }
288
289 /*
290 Draw a sequencer block, bounds check alredy made
291 ScrArea is currently only used to get the windows width in pixels
292 so wave file sample drawing precission is zoom adjusted
293 */
294 void drawseq(Sequence *seq, ScrArea *sa)
295 {
296         float v1[2], v2[2], x1, x2, y1, y2, color_tint[4];
297         unsigned int body, dark, light;
298         int len, size;
299         short mval[2];
300         char str[120], *strp;
301
302
303         if(seq->startdisp > seq->enddisp) body= 0x707070;
304
305         body= seq_color(seq);
306         dark= 0x202020;
307         light= 0xB0B0B0;
308
309         if(G.moving && (seq->flag & SELECT)) {
310                 if(seq->flag & SEQ_OVERLAP) dark= light= 0x4040FF;
311                 else {
312                         if(seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL));
313                         else dark= light= 0xFFFFFF;
314                 }
315         }
316
317         /* body */
318         if(seq->startstill) x1= seq->start;
319         else x1= seq->startdisp;
320         y1= seq->machine+0.2;
321         if(seq->endstill) x2= seq->start+seq->len;
322         else x2= seq->enddisp;
323         y2= seq->machine+0.8;
324
325         cpack(body);
326         glRectf(x1,  y1,  x2,  y2);
327         if (seq->type == SEQ_SOUND) drawseqwave(seq, x1, y1, x2, y2, sa->winx);
328         EmbossBoxf(x1, y1, x2, y2, seq->flag & 1, dark, light);
329
330         v1[1]= y1;
331         v2[1]= y2;
332         if(seq->type < SEQ_EFFECT) {
333
334                 /* decoration: the bars */
335                 x1= seq->startdisp;
336                 x2= seq->enddisp;
337
338                 if(seq->startofs) {
339                         cpack(0x707070);
340                         glRectf((float)(seq->start),  y1-0.2,  x1,  y1);
341                         EmbossBoxf((float)(seq->start), y1-0.2, x1, y1, seq->flag & 1, dark, light);
342                 }
343                 if(seq->endofs) {
344                         cpack(0x707070);
345                         glRectf(x2,  y2,  (float)(seq->start+seq->len),  y2+0.2);
346                         EmbossBoxf(x2, y2, (float)(seq->start+seq->len), y2+0.2, seq->flag & 1, dark, light);
347                 }
348
349                 if(seq->startstill) {
350                         cpack(body);
351                         glRectf(x1,  y1+0.1,  (float)(seq->start),  y1+0.5);
352                         no_rightbox= 1;
353                         EmbossBoxf(x1, y1+0.1, (float)(seq->start), y1+0.5, seq->flag & 1, dark, light);
354                         no_rightbox= 0;
355                 }
356                 if(seq->endstill) {
357                         cpack(body);
358                         glRectf((float)(seq->start+seq->len),  y1+0.1,  x2,  y1+0.5);
359                         no_leftbox= 1;
360                         EmbossBoxf((float)(seq->start+seq->len), y1+0.1, x2, y1+0.5, seq->flag & 1, dark, light);
361                         no_leftbox= 0;
362                 }
363
364         }
365
366         /* calculate if seq is long enough to print a name */
367         x1= seq->startdisp+seq->handsize;
368         x2= seq->enddisp-seq->handsize;
369
370         /* but first the contents of a meta */
371         if(seq->type==SEQ_META) drawmeta_contents(seq, x1, y1+0.15, x2, y2-0.15);
372
373         if(x1<G.v2d->cur.xmin) x1= G.v2d->cur.xmin;
374         else if(x1>G.v2d->cur.xmax) x1= G.v2d->cur.xmax;
375         if(x2<G.v2d->cur.xmin) x2= G.v2d->cur.xmin;
376         else if(x2>G.v2d->cur.xmax) x2= G.v2d->cur.xmax;
377
378         if(x1 != x2) {
379                 v1[0]= x1;
380                 ipoco_to_areaco_noclip(G.v2d, v1, mval);
381                 x1= mval[0];
382                 v2[0]= x2;
383                 ipoco_to_areaco_noclip(G.v2d, v2, mval);
384                 x2= mval[0];
385                 size= x2-x1;
386
387                 if(seq->name[2]) {
388                         sprintf(str, "%s: %s (%d)", give_seqname(seq), seq->name+2, seq->len);
389                 }else{
390                         if(seq->type == SEQ_META) {
391                                 sprintf(str, "%d %s", seq->len, give_seqname(seq));
392                         }
393                         else if(seq->type == SEQ_SCENE) {
394                                 if(seq->scene) sprintf(str, "%d %s %s", seq->len, give_seqname(seq), seq->scene->id.name+2);
395                                 else sprintf(str, "%d %s", seq->len, give_seqname(seq));
396
397                         }
398                         else if(seq->type == SEQ_IMAGE) {
399                                 sprintf(str, "%d %s%s", seq->len, seq->strip->dir, seq->strip->stripdata->name);
400                         }
401                         else if(seq->type & SEQ_EFFECT) {
402                                 if(seq->seq3!=seq->seq2 && seq->seq1!=seq->seq3)
403                                         sprintf(str, "%d %s: %d-%d (use %d)", seq->len, give_seqname(seq), seq->seq1->machine, seq->seq2->machine, seq->seq3->machine);
404                                 else
405                                         sprintf(str, "%d %s: %d-%d", seq->len, give_seqname(seq), seq->seq1->machine, seq->seq2->machine);
406                         }
407                         else if (seq->type == SEQ_SOUND) {
408                                 sprintf(str, "%d %s", seq->len, seq->strip->stripdata->name);
409                         }
410                         else if (seq->type == SEQ_MOVIE) {
411                                 sprintf(str, "%d %s%s", seq->len, seq->strip->dir, seq->strip->stripdata->name);
412                         }
413                 }
414
415
416                 strp= str;
417
418                 while( (len= BMF_GetStringWidth(G.font, strp)) > size) {
419                         if(len < 10) break;
420                         if(strp[1]==0) break;
421                         strp++;
422                 }
423
424                 mval[0]= (x1+x2-len+1)/2;
425                 mval[1]= 1;
426                 areamouseco_to_ipoco(G.v2d, mval, &x1, &x2);
427
428                 if(seq->flag & SELECT) cpack(0xFFFFFF);
429                 else cpack(0x0);
430                 glRasterPos3f(x1,  y1+0.2, 0.0);
431                 BMF_DrawString(G.font, strp);
432         }
433         
434
435         
436         if(seq->type < SEQ_EFFECT) {
437                 /* decoration: triangles */
438                 x1= seq->startdisp;
439                 x2= seq->enddisp;
440
441                 body+= 0x101010;
442                 dark= 0x202020;
443                 light= 0xB0B0B0;
444
445                 /* left triangle */
446                 if(seq->flag & SEQ_LEFTSEL) {
447                         cpack(body+0x20);
448                         if(G.moving) {
449                                 if(seq->flag & SEQ_OVERLAP) dark= light= 0x4040FF;
450                                 else dark= light= 0xFFFFFF;
451                         }
452                 } else {
453                         cpack(body);
454                 }
455         
456                 /*Tint the color for wave display to show through */
457                 if (seq->type == SEQ_SOUND) {
458                         glEnable( GL_BLEND );
459                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
460                         glGetFloatv(GL_CURRENT_COLOR, color_tint);
461                         glColor4f(color_tint[0], color_tint[1], color_tint[2], 0.7);
462                 }
463                 
464                 glBegin(GL_TRIANGLES);
465                         v1[0]= x1; glVertex2fv(v1);
466                         v2[0]= x1; glVertex2fv(v2);
467                         v2[0]+= seq->handsize; v2[1]= (y1+y2)/2.0; glVertex2fv(v2); v2[1]= y2;
468                 glEnd();
469
470                 cpack(light);
471                 glBegin(GL_LINE_STRIP);
472                         v1[0]= x1; glVertex2fv(v1);
473                         v2[0]= x1; glVertex2fv(v2);
474                         v2[0]+= seq->handsize; v2[1]= (y1+y2)/2.0; glVertex2fv(v2); v2[1]= y2;
475                         cpack(dark);
476                         glVertex2fv(v1);
477                 glEnd();
478         }
479
480
481                 /* right triangle */
482         if(seq->type < SEQ_EFFECT) {
483                 dark= 0x202020;
484                 light= 0xB0B0B0;
485
486                 if(seq->flag & SEQ_RIGHTSEL) {
487                         cpack(body+0x20);
488                         if(G.moving) {
489                                 if(seq->flag & SEQ_OVERLAP) dark= light= 0x4040FF;
490                                 else dark= light= 0xFFFFFF;
491                         }
492                 }
493                 else {
494                         cpack(body);
495                 }
496                 /*Tint the color for wave display to show through */
497                 if (seq->type == SEQ_SOUND) {
498                         glGetFloatv(GL_CURRENT_COLOR, color_tint);
499                         glColor4f(color_tint[0], color_tint[1], color_tint[2], 0.7);
500                 }
501                 
502                 glBegin(GL_TRIANGLES);
503                         v2[0]= x2; glVertex2fv(v2);
504                         v1[0]= x2; glVertex2fv(v1);
505                         v2[0]-= seq->handsize; v2[1]= (y1+y2)/2.0; glVertex2fv(v2); v2[1]= y2;
506                 glEnd();
507                 
508                 if (seq->type == SEQ_SOUND)
509                         glDisable( GL_BLEND );
510
511                 cpack(dark);
512                 glBegin(GL_LINE_STRIP);
513                         v2[0]= x2; glVertex2fv(v2);
514                         v1[0]= x2; glVertex2fv(v1);
515                         v1[0]-= seq->handsize; v1[1]= (y1+y2)/2.0; glVertex2fv(v1); v1[1]= y2;
516                         cpack(light);
517                         glVertex2fv(v2);
518                 glEnd();
519         }
520         
521         
522         if(G.moving || (seq->flag & SEQ_LEFTSEL)) {
523                 cpack(0xFFFFFF);
524                 glRasterPos3f(x1,  y1+0.2, 0.0);
525                 sprintf(str, "%d", seq->startdisp);
526                 BMF_DrawString(G.font, str);
527         }
528         
529         if(G.moving || (seq->flag & SEQ_RIGHTSEL)) {
530                 cpack(0xFFFFFF);
531                 glRasterPos3f(x2-seq->handsize/2,  y1+0.2, 0.0);
532                 sprintf(str, "%d", seq->enddisp-1);
533                 BMF_DrawString(G.font, str);
534         }
535 }
536
537 static Sequence *special_seq_update= 0;
538
539 void set_special_seq_update(int val)
540 {
541         int x;
542
543         /* if mouse over a sequence && LEFTMOUSE */
544         if(val) {
545                 special_seq_update= find_nearest_seq(&x);
546         }
547         else special_seq_update= 0;
548 }
549
550
551 static void draw_image_seq(ScrArea *sa)
552 {
553         SpaceSeq *sseq;
554         StripElem *se;
555         struct ImBuf *ibuf;
556         int x1, y1, rectx, recty;
557         float zoom;
558
559         glClearColor(0.0, 0.0, 0.0, 0.0);
560         glClear(GL_COLOR_BUFFER_BIT);
561         
562         rectx= (G.scene->r.size*G.scene->r.xsch)/100;
563         recty= (G.scene->r.size*G.scene->r.ysch)/100;
564         
565         ibuf= (ImBuf *)give_ibuf_seq(rectx, recty, (G.scene->r.cfra));
566
567         if(special_seq_update) {
568        se = special_seq_update->curelem;
569        if(se) {
570            if(se->ok==2) {
571                if(se->se1)
572                    ibuf= se->se1->ibuf;
573            }
574            else ibuf= se->ibuf;
575        }
576         }
577         if(ibuf==0 || ibuf->rect==0) return;
578
579         sseq= sa->spacedata.first;
580         if(sseq==0) return;
581
582         if (sseq->zoom > 0) zoom = sseq->zoom;
583         else zoom = -1.0/sseq->zoom;
584         /* calc location */
585         x1= (sa->winx-zoom*ibuf->x)/2;
586         y1= (sa->winy-zoom*ibuf->y)/2;
587
588         /* needed for gla draw */
589         glaDefine2DArea(&curarea->winrct);
590         glPixelZoom(zoom, zoom);
591         
592         glaDrawPixelsSafe(x1, y1, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
593         
594         glPixelZoom(1.0, 1.0);
595
596         sa->win_swap= WIN_BACK_OK;
597 }
598
599 static void draw_extra_seqinfo(void)
600 {
601         extern Sequence *last_seq;
602         StripElem *se, *last;
603         float xco, xfac;
604         int sta, end;
605         char str[256];
606
607         if(last_seq==0) return;
608
609         /* xfac: size of 1 pixel */
610         xfac= G.v2d->cur.xmax - G.v2d->cur.xmin;
611         xfac/= (float)(G.v2d->mask.xmax-G.v2d->mask.xmin);
612         xco= G.v2d->cur.xmin+40*xfac;
613
614         BIF_ThemeColor(TH_TEXT);
615
616         /* NAME */
617         glRasterPos3f(xco,  0.3, 0.0);
618         strncpy(str, give_seqname(last_seq), 255);
619         BMF_DrawString(G.font, str);
620         xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac;
621
622         if(last_seq->type==SEQ_SCENE && last_seq->scene) {
623                 glRasterPos3f(xco,  0.3, 0.0);
624                 BMF_DrawString(G.font, last_seq->scene->id.name+2);
625                 xco += xfac*BMF_GetStringWidth(G.font, last_seq->scene->id.name+2) +30.0*xfac;
626         }
627
628         /* LEN */
629         if(last_seq->type & SEQ_EFFECT)
630                 sprintf(str, "len: %d   From %d - %d", last_seq->len, last_seq->startdisp, last_seq->enddisp-1);
631         else
632                 sprintf(str, "len: %d (%d)", last_seq->enddisp-last_seq->startdisp, last_seq->len);
633
634         glRasterPos3f(xco,  0.3, 0.0);
635         BMF_DrawString(G.font, str);
636         xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac;
637
638         if(last_seq->type==SEQ_IMAGE) {
639
640                 /* CURRENT */
641                 se= (StripElem *)give_stripelem(last_seq,  (G.scene->r.cfra));
642                 if(se) {
643                         sprintf(str, "cur: %s", se->name);
644                         glRasterPos3f(xco,  0.3, 0.0);
645                         BMF_DrawString(G.font, str);
646                         xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac;
647                 }
648
649                 /* FIRST AND LAST */
650
651                 if(last_seq->strip) {
652                         se= last_seq->strip->stripdata;
653                         last= se+last_seq->len-1;
654                         if(last_seq->startofs) se+= last_seq->startofs;
655                         if(last_seq->endofs) last-= last_seq->endofs;
656
657                         sprintf(str, "First: %s at %d     Last: %s at %d", se->name, last_seq->startdisp, last->name, last_seq->enddisp-1);
658                         glRasterPos3f(xco,  0.3, 0.0);
659                         BMF_DrawString(G.font, str);
660                         xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac;
661
662                         /* orig size */
663                         sprintf(str, "OrigSize: %d x %d", last_seq->strip->orx, last_seq->strip->ory);
664                         glRasterPos3f(xco,  0.3, 0.0);
665                         BMF_DrawString(G.font, str);
666                         xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac;
667                 }
668         }
669         else if(last_seq->type==SEQ_MOVIE) {
670
671                 sta= last_seq->startofs;
672                 end= last_seq->len-1-last_seq->endofs;
673
674                 sprintf(str, "%s   %s%s  First: %d at %d     Last: %d at %d     Cur: %d",
675                                 last_seq->name+2, last_seq->strip->dir, last_seq->strip->stripdata->name,
676                                 sta, last_seq->startdisp, end, last_seq->enddisp-1,  (G.scene->r.cfra)-last_seq->startdisp);
677
678                 glRasterPos3f(xco,  0.3, 0.0);
679                 BMF_DrawString(G.font, str);
680         }
681         else if(last_seq->type==SEQ_SOUND) {
682
683                 sta= last_seq->startofs;
684                 end= last_seq->len-1-last_seq->endofs;
685
686                 sprintf(str, "%s   %s%s  First: %d at %d     Last: %d at %d     Cur: %d     Gain: %.2f dB     Pan: %.2f",
687                                 last_seq->name+2, last_seq->strip->dir, last_seq->strip->stripdata->name,
688                                 sta, last_seq->startdisp, end, last_seq->enddisp-1,  (G.scene->r.cfra)-last_seq->startdisp,
689                                 last_seq->level, last_seq->pan);
690
691                 glRasterPos3f(xco,  0.3, 0.0);
692                 BMF_DrawString(G.font, str);
693         }
694 }
695
696 #define SEQ_BUT_PLUGIN  1
697 #define SEQ_BUT_RELOAD  2
698 #define SEQ_BUT_EFFECT  3
699
700 void do_seqbuttons(short val)
701 {
702         extern Sequence *last_seq;
703
704         switch(val) {
705         case SEQ_BUT_PLUGIN:
706                 new_stripdata(last_seq);
707                 free_imbuf_effect_spec(CFRA);
708                 break;
709
710         case SEQ_BUT_RELOAD:
711                 free_imbuf_seq();       // frees all
712                 break;
713         case SEQ_BUT_EFFECT:
714                 new_stripdata(last_seq);
715                 calc_sequence(last_seq);
716                 break;
717         }
718
719         allqueue(REDRAWSEQ, 0);
720 }
721
722 static void seq_panel_properties(short cntrl)   // SEQ_HANDLER_PROPERTIES
723 {
724         extern Sequence *last_seq;
725         uiBlock *block;
726
727         block= uiNewBlock(&curarea->uiblocks, "seq_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
728         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
729         uiSetPanelHandler(SEQ_HANDLER_PROPERTIES);  // for close and esc
730         if(uiNewPanel(curarea, block, "Strip Properties", "Seq", 10, 230, 318, 204)==0) return;
731
732         if(last_seq==NULL) return;
733
734         if(last_seq->type==SEQ_PLUGIN) {
735                 PluginSeq *pis;
736                 VarStruct *varstr;
737                 int a, xco, yco;
738
739                 uiDefBut(block, LABEL, 0, "Type: Plugin", 10,50,70,20, 0, 0, 0, 0, 0, "");
740
741                 pis= last_seq->plugin;
742                 if(pis->vars==0) return;
743
744                 varstr= pis->varstr;
745                 if(varstr) {
746                         for(a=0; a<pis->vars; a++, varstr++) {
747                                 xco= 150*(a/6)+10;
748                                 yco= 125 - 20*(a % 6)+1;
749                                 uiDefBut(block, varstr->type, SEQ_BUT_PLUGIN, varstr->name, xco,yco,150,19, &(pis->data[a]), varstr->min, varstr->max, 100, 0, varstr->tip);
750
751                         }
752                 }
753         }
754         else if(last_seq->type==SEQ_IMAGE) {
755
756                 uiDefBut(block, LABEL, 0, "Type: Image", 10,140,150,20, 0, 0, 0, 0, 0, "");
757                 uiDefBut(block, TEX, B_NOP, "Name: ", 10,120,150,19, last_seq->name+2, 0.0, 21.0, 100, 0, "");
758
759                 uiDefButBitS(block, TOG, SEQ_MAKE_PREMUL, SEQ_BUT_RELOAD, "Convert to Premul", 10,90,150,19, &last_seq->flag, 0.0, 21.0, 100, 0, "Converts RGB values to become premultiplied with Alpha");
760                 uiDefButBitS(block, TOG, SEQ_FILTERY, SEQ_BUT_RELOAD, "FilterY",        10,70,150,19, &last_seq->flag, 0.0, 21.0, 100, 0, "For video movies to remove fields");
761                 uiDefButF(block, NUM, SEQ_BUT_RELOAD, "Mul:",                   10,50,150,19, &last_seq->mul, 0.001, 5.0, 100, 0, "Multiply colors");
762                 uiDefButS(block, TOG|BIT|7, SEQ_BUT_RELOAD, "Reverse Frames", 10,30,150,19, &last_seq->flag, 0.0, 21.0, 100, 0, "Reverse frame order");
763                 uiDefButF(block, NUM, SEQ_BUT_RELOAD, "Strobe:",                        10,10,150,19, &last_seq->strobe, 1.0, 30.0, 100, 0, "Only display every nth frame");
764         }
765         else if(last_seq->type==SEQ_META) {
766
767                 uiDefBut(block, LABEL, 0, "Type: Meta", 10,140,150,20, 0, 0, 0, 0, 0, "");
768                 uiDefBut(block, TEX, B_NOP, "Name: ", 10,120,150,19, last_seq->name+2, 0.0, 21.0, 100, 0, "");
769
770         }
771         else if(last_seq->type==SEQ_SCENE) {
772
773                 uiDefBut(block, LABEL, 0, "Type: Scene", 10,140,150,20, 0, 0, 0, 0, 0, "");
774                 uiDefBut(block, TEX, B_NOP, "Name: ", 10,120,150,19, last_seq->name+2, 0.0, 21.0, 100, 0, "");
775                 uiDefButS(block, TOG|BIT|7, SEQ_BUT_RELOAD, "Reverse Frames", 10,90,150,19, &last_seq->flag, 0.0, 21.0, 100, 0, "Reverse frame order");
776         }
777         else if(last_seq->type==SEQ_MOVIE) {
778
779                 if(last_seq->mul==0.0) last_seq->mul= 1.0;
780
781                 uiDefBut(block, LABEL, 0, "Type: Movie", 10,140,150,20, 0, 0, 0, 0, 0, "");
782                 uiDefBut(block, TEX, B_NOP, "Name: ", 10,120,150,19, last_seq->name+2, 0.0, 21.0, 100, 0, "");
783
784                 uiDefButBitS(block, TOG, SEQ_MAKE_PREMUL, SEQ_BUT_RELOAD, "Make Premul Alpha ", 10,90,150,19, &last_seq->flag, 0.0, 21.0, 100, 0, "Converts RGB values to become premultiplied with Alpha");
785                 uiDefButBitS(block, TOG, SEQ_FILTERY, SEQ_BUT_RELOAD, "FilterY ",       10,70,150,19, &last_seq->flag, 0.0, 21.0, 100, 0, "For video movies to remove fields");
786                 uiDefButF(block, NUM, SEQ_BUT_RELOAD, "Mul:",                   10,50,150,19, &last_seq->mul, 0.001, 5.0, 100, 0, "Multiply colors");
787                 
788                 uiDefButS(block, TOG|BIT|7, SEQ_BUT_RELOAD, "Reverse Frames", 10,30,150,19, &last_seq->flag, 0.0, 21.0, 100, 0, "Reverse frame order");
789                 uiDefButF(block, NUM, SEQ_BUT_RELOAD, "Strobe:",                        10,10,150,19, &last_seq->strobe, 1.0, 30.0, 100, 0, "Only display every nth frame");
790
791         }
792         else if(last_seq->type==SEQ_SOUND) {
793
794                 uiDefBut(block, LABEL, 0, "Type: Audio", 10,140,150,20, 0, 0, 0, 0, 0, "");
795                 uiDefBut(block, TEX, 0, "Name: ", 10,120,150,19, last_seq->name+2, 0.0, 21.0, 100, 0, "");
796
797                 uiDefButBitS(block, TOG, SEQ_MUTE, B_NOP, "Mute", 10,90,120,19, &last_seq->flag, 0.0, 21.0, 100, 0, "");
798                 uiDefButF(block, NUM, SEQ_BUT_RELOAD, "Gain (dB):", 10,70,150,19, &last_seq->level, -96.0, 6.0, 100, 0, "");
799                 uiDefButF(block, NUM, SEQ_BUT_RELOAD, "Pan:",   10,50,150,19, &last_seq->pan, -1.0, 1.0, 100, 0, "");
800         }
801         else if(last_seq->type>=SEQ_EFFECT) {
802                 uiDefBut(block, LABEL, 0, "Type: Effect", 10,140,150,20, 0, 0, 0, 0, 0, "");
803                 uiDefBut(block, TEX, B_NOP, "Name: ", 10,120,150,19, last_seq->name+2, 0.0, 21.0, 100, 0, "");
804
805                 if(last_seq->type==SEQ_WIPE){
806                         WipeVars *wipe = (WipeVars *)last_seq->effectdata;
807                         char formatstring[256];
808                         strncpy(formatstring, "Transition Type %t|Single Wipe%x0|Double Wipe %x1|Iris Wipe %x4|Clock Wipe %x5", 255);
809                         uiDefButS(block, MENU,SEQ_BUT_EFFECT, formatstring,     10,90,220,22, &wipe->wipetype, 0, 0, 0, 0, "What type of wipe should be performed");
810                         uiDefButF(block, NUM,SEQ_BUT_EFFECT,"Blur:",    10,65,220,22, &wipe->edgeWidth,0.0,1.0, 1, 2, "The percent width of the blur edge");
811                         switch(wipe->wipetype){ /*Skip Types that do not require angle*/
812                                 case DO_IRIS_WIPE:
813                                 case DO_CLOCK_WIPE:
814                                 break;
815                                 
816                                 default:
817                                         uiDefButF(block, NUM,SEQ_BUT_EFFECT,"Angle:",   10,40,220,22, &wipe->angle,-90.0,90.0, 1, 2, "The Angle of the Edge");
818                         }
819                         uiDefButS(block, TOG,SEQ_BUT_EFFECT,"Wipe In",  10,15,220,22, &wipe->forward,0,0, 0, 0, "Controls Primary Direction of Wipe");                          
820                 }
821                 else if(last_seq->type==SEQ_GLOW){
822                         GlowVars *glow = (GlowVars *)last_seq->effectdata;
823
824                         uiDefButF(block, NUM, SEQ_BUT_EFFECT, "Threshold:",     10,90,150,19, &glow->fMini, 0.0, 1.0, 0, 0, "Trigger Intensity");
825                         uiDefButF(block, NUM, SEQ_BUT_EFFECT, "Clamp:",         10,70,150,19, &glow->fClamp, 0.0, 1.0, 0, 0, "Brightness limit of intensity");
826                         uiDefButF(block, NUM, SEQ_BUT_EFFECT, "Boost factor:",  10,50,150,19, &glow->fBoost, 0.0, 10.0, 0, 0, "Brightness multiplier");
827                         uiDefButF(block, NUM, SEQ_BUT_EFFECT, "Blur distance:",         10,30,150,19, &glow->dDist, 0.5, 20.0, 0, 0, "Radius of glow effect");
828                         uiDefButI(block, NUM, B_NOP, "Quality:", 10,10,150,19, &glow->dQuality, 1.0, 5.0, 0, 0, "Accuracy of the blur effect");
829                         uiDefButI(block, TOG, B_NOP, "Only boost", 10,-10,150,19, &glow->bNoComp, 0.0, 0.0, 0, 0, "Show the glow buffer only");
830                 }
831
832         }
833
834
835 }
836
837 static void seq_blockhandlers(ScrArea *sa)
838 {
839         SpaceSeq *sseq= sa->spacedata.first;
840         short a;
841
842         /* warning; blocks need to be freed each time, handlers dont remove (for ipo moved to drawipospace) */
843         uiFreeBlocksWin(&sa->uiblocks, sa->win);
844
845         for(a=0; a<SPACE_MAXHANDLER; a+=2) {
846                 switch(sseq->blockhandler[a]) {
847
848                 case SEQ_HANDLER_PROPERTIES:
849                         seq_panel_properties(sseq->blockhandler[a+1]);
850                         break;
851
852                 }
853                 /* clear action value for event */
854                 sseq->blockhandler[a+1]= 0;
855         }
856         uiDrawBlocksPanels(sa, 0);
857
858 }
859
860 void drawseqspace(ScrArea *sa, void *spacedata)
861 {
862         SpaceSeq *sseq;
863         Editing *ed;
864         Sequence *seq;
865         float col[3];
866         int ofsx, ofsy;
867
868         ed= G.scene->ed;
869
870         sseq= curarea->spacedata.first;
871         if(sseq->mainb==1) {
872                 draw_image_seq(curarea);
873                 return;
874         }
875
876         bwin_clear_viewmat(sa->win);    /* clear buttons view */
877         glLoadIdentity();
878
879         BIF_GetThemeColor3fv(TH_BACK, col);
880         if(ed && ed->metastack.first) glClearColor(col[0], col[1], col[2]-0.1, 0.0);
881         else glClearColor(col[0], col[1], col[2], 0.0);
882
883         glClear(GL_COLOR_BUFFER_BIT);
884
885         calc_scrollrcts(sa, G.v2d, curarea->winx, curarea->winy);
886
887         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
888                 if(G.v2d->scroll) {
889                         ofsx= curarea->winrct.xmin;     /* because of mywin */
890                         ofsy= curarea->winrct.ymin;
891                         glViewport(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
892                         glScissor(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
893                 }
894         }
895
896
897         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
898
899         BIF_ThemeColorShade(TH_BACK, -20);
900         glRectf(G.v2d->cur.xmin,  0.0,  G.v2d->cur.xmax,  1.0);
901
902         boundbox_seq();
903         calc_ipogrid();
904         draw_ipogrid();
905         draw_cfra_seq();
906
907         /* sequences: first deselect */
908
909         if(ed) {
910                 seq= ed->seqbasep->first;
911                 while(seq) { /* bound box test, dont draw outside the view */
912                         if (seq->flag & SELECT ||
913                                         seq->start > G.v2d->cur.xmax ||
914                                         seq->start+seq->len < G.v2d->cur.xmin ||
915                                         seq->machine+1.0 < G.v2d->cur.ymin ||
916                                         seq->machine > G.v2d->cur.ymax)
917                         {
918                                 /* dont draw */
919                         } else {
920                                 drawseq(seq, sa);
921                         }
922                         seq= seq->next;
923                 }
924         }
925         ed= G.scene->ed;
926         if(ed) {
927                 seq= ed->seqbasep->first;
928                 while(seq) { /* bound box test, dont draw outside the view */
929                         if (!(seq->flag & SELECT) ||
930                                         seq->start > G.v2d->cur.xmax ||
931                                         seq->start+seq->len < G.v2d->cur.xmin ||
932                                         seq->machine+1.0 < G.v2d->cur.ymin ||
933                                         seq->machine > G.v2d->cur.ymax)
934                         {
935                                 /* dont draw */
936                         } else {
937                                 drawseq(seq, sa);
938                         }
939                         seq= seq->next;
940                 }
941         }
942
943         draw_extra_seqinfo();
944
945         /* restore viewport */
946         mywinset(curarea->win);
947
948         /* ortho at pixel level curarea */
949         myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
950
951         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
952                 if(G.v2d->scroll) {
953                         drawscroll(0);
954                 }
955         }
956
957         draw_area_emboss(sa);
958
959         if(sseq->mainb==0) {
960                 /* it is important to end a view in a transform compatible with buttons */
961                 bwin_scalematrix(sa->win, sseq->blockscale, sseq->blockscale, sseq->blockscale);
962                 seq_blockhandlers(sa);
963         }
964
965         curarea->win_swap= WIN_BACK_OK;
966 }
967
968