1 /*
2 TiMidity++ -- MIDI to WAVE converter and player
3 Copyright (C) 1999-2004 Masanao Izumo <iz@onicos.co.jp>
4 Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (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
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19
20 x_trace.c - Trace window drawing for X11 based systems
21 based on code by Yoshishige Arai <ryo2@on.rim.or.jp>
22 modified by Yair Kalvariski <cesium2@gmail.com>
23 */
24
25 #include "x_trace.h"
26 #include <stdlib.h>
27 #include "timer.h"
28
29 #ifdef HAVE_LIBXFT
30 #include <X11/Xft/Xft.h>
31 #endif
32
33 enum {
34 CL_C, /* column 0 = channel */
35 CL_VE, /* column 1 = velocity */
36 CL_VO, /* column 2 = volume */
37 CL_EX, /* column 3 = expression */
38 CL_PR, /* column 4 = program */
39 CL_PA, /* column 5 = panning */
40 CL_PI, /* column 6 = pitch bend */
41 CL_IN, /* column 7 = instrument name */
42 KEYBOARD,
43 TCOLUMN,
44 CL_BA = 4, /* column 5 = bank */
45 CL_BA_MSB, /* column 6 = bank_lsb */
46 CL_BA_LSB, /* column 7 = bank_msg */
47 CL_RE, /* column 8 = reverb */
48 CL_CH, /* column 9 = chorus */
49 KEYBOARD2,
50 T2COLUMN
51 };
52
53 #define MAX_GRADIENT_COLUMN CL_CH+1
54
55 typedef struct {
56 int y;
57 int l;
58 } KeyL;
59
60 typedef struct {
61 KeyL k[3];
62 int xofs;
63 Pixel col;
64 } ThreeL;
65
66 typedef struct {
67 const int col; /* column number */
68 const char **cap; /* caption strings array */
69 const int *w; /* column width array */
70 const int *ofs; /* column offset array */
71 } Tplane;
72
73 typedef struct {
74 GC gradient_gc[MAX_GRADIENT_COLUMN];
75 Pixmap gradient_pixmap[MAX_GRADIENT_COLUMN];
76 Boolean gradient_set[MAX_GRADIENT_COLUMN];
77 XColor x_boxcolor;
78 RGBInfo rgb;
79 } GradData;
80
81 typedef struct {
82 int is_drum[MAX_TRACE_CHANNELS];
83 int8 c_flags[MAX_TRACE_CHANNELS];
84 int8 v_flags[MAX_TRACE_CHANNELS];
85 int16 cnote[MAX_TRACE_CHANNELS];
86 int16 ctotal[MAX_TRACE_CHANNELS];
87 int16 cvel[MAX_TRACE_CHANNELS];
88 int16 reverb[MAX_TRACE_CHANNELS];
89 Channel channel[MAX_TRACE_CHANNELS];
90 char *inst_name[MAX_TRACE_CHANNELS];
91
92 unsigned int last_voice, tempo, timeratio, xaw_i_voices;
93 int pitch, poffset;
94 const char *key_cache;
95
96 Display *disp;
97 Window trace;
98 unsigned int depth, plane, multi_part, visible_channels, voices_width;
99 Pixel barcol[MAX_TRACE_CHANNELS];
100 Pixmap layer[2];
101 GC gcs, gct, gc_xcopy;
102 Boolean g_cursor_is_in;
103 tconfig *cfg;
104 const char *title;
105 GradData *grad;
106
107 #ifdef HAVE_LIBXFT
108 XftDraw *xft_trace, *xft_trace_foot, *xft_trace_inst;
109 XftFont *trfont, *ttfont;
110 XftColor xft_capcolor, xft_textcolor;
111 Pixmap xft_trace_foot_pixmap, xft_trace_inst_pixmap;
112 #else
113 int foot_width;
114 short title_font_ascent;
115 #endif /* HAVE_LIBXFT */
116 } PanelInfo;
117
118 #define gcs Panel->gcs
119 #define gct Panel->gct
120 #define gc_xcopy Panel->gc_xcopy
121 #define plane Panel->plane
122 #define layer Panel->layer
123 #define gradient_gc Panel->grad->gradient_gc
124 #define gradient_pixmap Panel->grad->gradient_pixmap
125 #define gradient_set Panel->grad->gradient_set
126 #define grgb Panel->grad->rgb
127 #define x_boxcolor Panel->grad->x_boxcolor
128
129 #ifdef HAVE_LIBXFT
130 #define trace_font Panel->trfont
131 #define ttitle_font Panel->ttfont
132
133 #define COPY_PIXEL(dest, src) do { \
134 XColor _x_; \
135 _x_.pixel = src; \
136 XQueryColor(disp, DefaultColormap(disp, 0), &_x_); \
137 dest.color.red = _x_.red; dest.color.green = _x_.green; \
138 dest.color.blue = _x_.blue; dest.color.alpha = 0xffff; dest.pixel = src; \
139 } while(0)
140
141 #ifdef X_HAVE_UTF8_STRING
142 #define TraceDrawStr(x,y,buf,len,color) do { \
143 XftColor xftcolor; \
144 COPY_PIXEL(xftcolor, color); \
145 XftDrawStringUtf8(Panel->xft_trace, &xftcolor, trace_font, \
146 x, y, (FcChar8 *)buf, len); \
147 } while(0)
148
149 #define TitleDrawStr(x,y,buf,len,color) do { \
150 XftColor xftcolor; \
151 COPY_PIXEL(xftcolor, color); \
152 XftDrawStringUtf8(Panel->xft_trace, &xftcolor, ttitle_font, \
153 x, y, (FcChar8 *)buf, len); \
154 } while(0)
155 #else
156 #define TraceDrawStr(x,y,buf,len,color) do { \
157 XftColor xftcolor; \
158 COPY_PIXEL(xftcolor, color); \
159 XftDrawString8(Panel->xft_trace, &xftcolor, trace_font, \
160 x, y, (FcChar8 *)buf, len);\
161 } while(0)
162
163 #define TitleDrawStr(x,y,buf,len,color) do { \
164 XftColor xftcolor; \
165 COPY_PIXEL(xftcolor, color); \
166 XftDrawString8(Panel->xft_trace, &xftcolor, ttitle_font, \
167 x, y, (FcChar8 *)buf, len); \
168 } while(0)
169 #endif /* X_HAVE_UTF8_STRING */
170
171 #else
172 #define trace_font Panel->cfg->c_trace_font
173 #define ttitle_font Panel->cfg->c_title_font
174
175 #define TraceDrawStr(x,y,buf,len,color) do { \
176 XSetForeground(disp, gct, color); \
177 XmbDrawString(disp, Panel->trace, trace_font, gct, x, y, buf, len); \
178 } while(0)
179
180 #define TitleDrawStr(x,y,buf,len,color) do { \
181 XSetForeground(disp, gct, color); \
182 XmbDrawString(disp, Panel->trace, ttitle_font, gct, x, y, buf, len); \
183 } while(0)
184 #endif /* HAVE_LIBXFT */
185
186 static PanelInfo *Panel;
187 static ThreeL *keyG = NULL;
188
189 static const char *caption[TCOLUMN] =
190 {"ch", " vel", " vol", "expr", "prog", "pan", "pit", " instrument",
191 " keyboard"};
192 static const char *caption2[T2COLUMN] =
193 {"ch", " vel", " vol", "expr", "bnk", "msb", "lsb", "reverb", "chorus",
194 " keyboard"};
195
196 static const int BARH_SPACE[TCOLUMN] = {22, 60, 40, 36, 36, 36, 30, 106, 304};
197 #define BARH_OFS0 (TRACE_HOFS)
198 #define BARH_OFS1 (BARH_OFS0+22)
199 #define BARH_OFS2 (BARH_OFS1+60)
200 #define BARH_OFS3 (BARH_OFS2+40)
201 #define BARH_OFS4 (BARH_OFS3+36)
202 #define BARH_OFS5 (BARH_OFS4+36)
203 #define BARH_OFS6 (BARH_OFS5+36)
204 #define BARH_OFS7 (BARH_OFS6+30)
205 #define BARH_OFS8 (BARH_OFS7+106)
206 static const int bar0ofs[TCOLUMN+1] = {BARH_OFS0, BARH_OFS1, BARH_OFS2, BARH_OFS3,
207 BARH_OFS4, BARH_OFS5, BARH_OFS6, BARH_OFS7, BARH_OFS8};
208
209 static const int BARH2_SPACE[T2COLUMN] = {22, 60, 40, 36, 36, 36, 36, 50,
210 50, 304};
211 #define BARH2_OFS0 (TRACE_HOFS)
212 #define BARH2_OFS1 (BARH2_OFS0+22)
213 #define BARH2_OFS2 (BARH2_OFS1+60)
214 #define BARH2_OFS3 (BARH2_OFS2+40)
215 #define BARH2_OFS4 (BARH2_OFS3+36)
216 #define BARH2_OFS5 (BARH2_OFS4+36)
217 #define BARH2_OFS6 (BARH2_OFS5+36)
218 #define BARH2_OFS7 (BARH2_OFS6+36)
219 #define BARH2_OFS8 (BARH2_OFS7+50)
220 #define BARH2_OFS9 (BARH2_OFS8+50)
221 static const int bar1ofs[T2COLUMN+1] = {BARH2_OFS0, BARH2_OFS1, BARH2_OFS2, BARH2_OFS3,
222 BARH2_OFS4, BARH2_OFS5, BARH2_OFS6, BARH2_OFS7, BARH2_OFS8, BARH2_OFS9};
223
224 static const Tplane pl[] = {
225 {TCOLUMN, caption, BARH_SPACE, bar0ofs},
226 {T2COLUMN, caption2, BARH2_SPACE, bar1ofs},
227 };
228
229 #define KEY_NUM 111
230 #define BARSCALE2 0.31111 /* velocity scale (60-4)/180 */
231 #define BARSCALE3 0.28125 /* volume scale (40-4)/128 */
232 #define BARSCALE4 0.25 /* expression scale (36-4)/128 */
233 #define BARSCALE5 0.359375 /* reverb scale (50-4)/128 */
234
235 #define FLAG_NOTE_OFF 1
236 #define FLAG_NOTE_ON 2
237 #define FLAG_BANK 1
238 #define FLAG_PROG 2
239 #define FLAG_PROG_ON 4
240 #define FLAG_PAN 8
241 #define FLAG_SUST 16
242 #define FLAG_BENDT 32
243
244 #define VISIBLE_CHANNELS Panel->visible_channels
245 #define VISLOW Panel->multi_part
246 #define XAWLIMIT(ch) ((VISLOW <= (ch)) && ((ch) < (VISLOW+VISIBLE_CHANNELS)))
247
248 #define disp Panel->disp
249
250 #define boxcolor Panel->cfg->box_color
251 #define capcolor Panel->cfg->caption_color
252 #define chocolor Panel->cfg->cho_color
253 #define expcolor Panel->cfg->expr_color
254 #define pancolor Panel->cfg->pan_color
255 #define playcolor Panel->cfg->play_color
256 #define revcolor Panel->cfg->rev_color
257 #define rimcolor Panel->cfg->rim_color
258 #define suscolor Panel->cfg->sus_color
259 #define textcolor Panel->cfg->common_fgcolor
260 #define textbgcolor Panel->cfg->text_bgcolor
261 #define tracecolor Panel->cfg->trace_bgcolor
262 #define volcolor Panel->cfg->volume_color
263
264 #define gradient_bar Panel->cfg->gradient_bar
265 #define black Panel->cfg->black_key_color
266 #define white Panel->cfg->white_key_color
267
268 #define trace_height_raw Panel->cfg->trace_height
269 #define trace_height_nf (Panel->cfg->trace_height - TRACE_FOOT)
270 #define trace_width Panel->cfg->trace_width
271
272 #define UNTITLED_STR Panel->cfg->untitled
273 /* Privates */
274
275 static int bitcount(int);
276 static void ctl_channel_note(int, int, int);
277 static void drawBar(int, int, int, int, Pixel);
278 static void drawKeyboardAll(Drawable, GC);
279 static void draw1Note(int, int, int);
280 static void drawProg(int, int, Boolean);
281 static void drawPan(int, int, Boolean);
282 static void draw1Chan(int, int, char);
283 static void drawVol(int, int);
284 static void drawExp(int, int);
285 static void drawPitch(int, int);
286 static void drawInstname(int, char *);
287 static void drawDrumPart(int, int);
288 static void drawBank(int, int, int, int);
289 static void drawReverb(int, int);
290 static void drawChorus(int, int);
291 static void drawFoot(Boolean);
292 static void drawVoices(void);
293 static void drawMute(int, int);
294 static int getdisplayinfo(RGBInfo *);
295 static int sftcount(int *);
296
bitcount(int d)297 static int bitcount(int d) {
298 int rt = 0;
299
300 while ((d & 0x01) == 0x01) {
301 d >>= 1;
302 rt++;
303 }
304 return rt;
305 }
306
sftcount(int * mask)307 static int sftcount(int *mask) {
308 int rt = 0;
309
310 while ((*mask & 0x01) == 0) {
311 (*mask) >>= 1;
312 rt++;
313 }
314 return rt;
315 }
316
getdisplayinfo(RGBInfo * rgb)317 static int getdisplayinfo(RGBInfo *rgb) {
318 XWindowAttributes xvi;
319 XGetWindowAttributes(disp, Panel->trace, &xvi);
320
321 if ((rgb != NULL) && (xvi.depth >= 16)) {
322 rgb->Red_depth = (xvi.visual)->red_mask;
323 rgb->Green_depth = (xvi.visual)->green_mask;
324 rgb->Blue_depth = (xvi.visual)->blue_mask;
325 rgb->Red_sft = sftcount(&(rgb->Red_depth));
326 rgb->Green_sft = sftcount(&(rgb->Green_depth));
327 rgb->Blue_sft = sftcount(&(rgb->Blue_depth));
328 rgb->Red_depth = bitcount(rgb->Red_depth);
329 rgb->Green_depth = bitcount(rgb->Green_depth);
330 rgb->Blue_depth = bitcount(rgb->Blue_depth);
331 }
332 return xvi.depth;
333 }
334
drawBar(int ch,int len,int xofs,int column,Pixel color)335 static void drawBar(int ch, int len, int xofs, int column, Pixel color) {
336 static Pixel column1color0 = 0;
337
338 XGCValues gv;
339 int col, i, screen;
340 XColor x_color;
341
342 ch -= VISLOW;
343 screen = DefaultScreen(disp);
344 if ((16 <= Panel->depth) && (gradient_bar)) {
345 gv.fill_style = FillTiled;
346 gv.fill_rule = WindingRule;
347
348 if (column < MAX_GRADIENT_COLUMN) {
349 col = column;
350 if (column == 1) {
351 if (gradient_set[0] == 0) {
352 column1color0 = color;
353 col = 0;
354 }
355 else if ((gradient_set[1] == 0) && (column1color0 != color)) {
356 col = 1;
357 }
358 else {
359 if (column1color0 == color) col = 0;
360 else col = 1;
361 }
362 }
363 if (gradient_set[col] == 0) {
364 unsigned long pxl;
365 int r, g, b;
366
367 gradient_pixmap[col] = XCreatePixmap(disp, Panel->trace,
368 BARH2_SPACE[column], 1, DefaultDepth(disp, screen));
369 x_color.pixel = color;
370 XQueryColor(disp, DefaultColormap(disp, 0), &x_color);
371 for (i=0;i<BARH2_SPACE[column];i++) {
372 r = x_boxcolor.red +
373 (x_color.red - x_boxcolor.red) * i / BARH2_SPACE[column];
374 g = x_boxcolor.green +
375 (x_color.green - x_boxcolor.green) * i / BARH2_SPACE[column];
376 b = x_boxcolor.blue +
377 (x_color.blue - x_boxcolor.blue) * i / BARH2_SPACE[column];
378 if (r<0) r = 0;
379 if (g<0) g = 0;
380 if (b<0) b = 0;
381 r >>= 8;
382 g >>= 8;
383 b >>= 8;
384 if (r>255) r = 255;
385 if (g>255) g = 255;
386 if (b>255) b = 255;
387 pxl = (r >> (8-grgb.Red_depth)) << grgb.Red_sft;
388 pxl |= (g >> (8-grgb.Green_depth)) << grgb.Green_sft;
389 pxl |= (b >> (8-grgb.Blue_depth)) << grgb.Blue_sft;
390 XSetForeground(disp, gct, pxl);
391 XDrawPoint(disp, gradient_pixmap[col], gct, i, 0);
392 }
393 gv.tile = gradient_pixmap[col];
394 gradient_gc[col] = XCreateGC(disp, Panel->trace,
395 GCFillStyle | GCFillRule | GCTile, &gv);
396 gradient_set[col] = 1;
397 }
398 XSetForeground(disp, gct, boxcolor);
399 XFillRectangle(disp, Panel->trace, gct,
400 xofs+len+2, CHANNEL_HEIGHT(ch)+2,
401 pl[plane].w[column] - len -4, BAR_HEIGHT);
402 gv.ts_x_origin = xofs + 2 - BARH2_SPACE[column] + len;
403 XChangeGC(disp, gradient_gc[col], GCTileStipXOrigin, &gv);
404 XFillRectangle(disp, Panel->trace, gradient_gc[col],
405 xofs+2, CHANNEL_HEIGHT(ch)+2,
406 len, BAR_HEIGHT);
407 }
408 }
409 else {
410 XSetForeground(disp, gct, boxcolor);
411 XFillRectangle(disp, Panel->trace, gct,
412 xofs+len+2, CHANNEL_HEIGHT(ch)+2,
413 pl[plane].w[column] - len - 4, BAR_HEIGHT);
414 XSetForeground(disp, gct, color);
415 XFillRectangle(disp, Panel->trace, gct,
416 xofs+2, CHANNEL_HEIGHT(ch)+2,
417 len, BAR_HEIGHT);
418 }
419 }
420
drawProg(int ch,int val,Boolean do_clean)421 static void drawProg(int ch, int val, Boolean do_clean) {
422 char s[4];
423
424 ch -= VISLOW;
425 if (do_clean == True) {
426 XSetForeground(disp, gct, boxcolor);
427 XFillRectangle(disp,Panel->trace,gct,
428 pl[plane].ofs[CL_PR]+2,CHANNEL_HEIGHT(ch)+2,
429 pl[plane].w[CL_PR]-4,BAR_HEIGHT);
430 }
431 snprintf(s, sizeof(s), "%3d", val);
432 TraceDrawStr(pl[plane].ofs[CL_PR]+5, CHANNEL_HEIGHT(ch)+BAR_HEIGHT-1,
433 s, 3, textcolor);
434 }
435
drawPan(int ch,int val,Boolean setcolor)436 static void drawPan(int ch, int val, Boolean setcolor) {
437 int ap, bp;
438 int x;
439 XPoint pp[3];
440
441 if (val < 0) return;
442
443 ch -= VISLOW;
444 if (setcolor == True) {
445 XSetForeground(disp, gct, boxcolor);
446 XFillRectangle(disp, Panel->trace, gct,
447 pl[plane].ofs[CL_PA]+2, CHANNEL_HEIGHT(ch)+2,
448 pl[plane].w[CL_PA]-4, BAR_HEIGHT);
449 XSetForeground(disp, gct, pancolor);
450 }
451 x = pl[plane].ofs[CL_PA] + 3;
452 ap = 31 * val/127;
453 bp = 31 - ap - 1;
454 pp[0].x = ap + x; pp[0].y = 12 + BAR_SPACE*(ch+1);
455 pp[1].x = bp + x; pp[1].y = 8 + BAR_SPACE*(ch+1);
456 pp[2].x = bp + x; pp[2].y = 16 + BAR_SPACE*(ch+1);
457 XFillPolygon(disp, Panel->trace, gct, pp, 3,
458 (int)Nonconvex, (int)CoordModeOrigin);
459 }
460
draw1Chan(int ch,int val,char cmd)461 static void draw1Chan(int ch, int val, char cmd) {
462 if ((cmd == '*') || (cmd == '&'))
463 drawBar(ch, (int)(val*BARSCALE2), pl[plane].ofs[CL_VE],
464 CL_VE, Panel->barcol[ch]);
465 }
466
drawVol(int ch,int val)467 static void drawVol(int ch, int val) {
468 drawBar(ch, (int)(val*BARSCALE3), pl[plane].ofs[CL_VO], CL_VO, volcolor);
469 }
470
drawExp(int ch,int val)471 static void drawExp(int ch, int val) {
472 drawBar(ch, (int)(val*BARSCALE4), pl[plane].ofs[CL_EX], CL_EX, expcolor);
473 }
474
drawReverb(int ch,int val)475 static void drawReverb(int ch, int val) {
476 drawBar(ch, (int)(val*BARSCALE5), pl[plane].ofs[CL_RE], CL_RE, revcolor);
477 }
478
drawChorus(int ch,int val)479 static void drawChorus(int ch, int val) {
480 drawBar(ch, (int)(val*BARSCALE5), pl[plane].ofs[CL_CH], CL_CH, chocolor);
481 }
482
drawPitch(int ch,int val)483 static void drawPitch(int ch, int val) {
484 char *s;
485
486 ch -= VISLOW;
487 XSetForeground(disp, gct, boxcolor);
488 XFillRectangle(disp,Panel->trace,gct,
489 pl[plane].ofs[CL_PI]+2,CHANNEL_HEIGHT(ch)+2,
490 pl[plane].w[CL_PI] -4,BAR_HEIGHT);
491 if (val != 0) {
492 if (val < 0) {
493 s = "=";
494 } else {
495 if (val == 0x2000) s = "*";
496 else if (val > 0x3000) s = ">>";
497 else if (val > 0x2000) s = ">";
498 else if (val > 0x1000) s = "<";
499 else s = "<<";
500 }
501 TraceDrawStr(pl[plane].ofs[CL_PI]+4, CHANNEL_HEIGHT(ch)+16, s, strlen(s),
502 Panel->barcol[9]);
503 }
504 }
505
drawDrumPart(int ch,int is_drum)506 static void drawDrumPart(int ch, int is_drum) {
507
508 if (plane != 0) return;
509 if (is_drum) Panel->barcol[ch] = Panel->cfg->drumvelocity_color;
510 else Panel->barcol[ch] = Panel->cfg->velocity_color;
511 }
512
draw1Note(int ch,int note,int flag)513 static void draw1Note(int ch, int note, int flag) {
514 int i, j;
515 XSegment dot[3];
516
517 j = note - 9;
518 if (j < 0) return;
519 ch -= VISLOW;
520 if (flag == '*') {
521 XSetForeground(disp, gct, playcolor);
522 } else if (flag == '&') {
523 XSetForeground(disp, gct,
524 ((keyG[j].col == black)?suscolor:Panel->barcol[0]));
525 } else {
526 XSetForeground(disp, gct, keyG[j].col);
527 }
528 for(i=0; i<3; i++) {
529 dot[i].x1 = keyG[j].xofs + i;
530 dot[i].y1 = CHANNEL_HEIGHT(ch) + keyG[j].k[i].y;
531 dot[i].x2 = dot[i].x1;
532 dot[i].y2 = dot[i].y1 + keyG[j].k[i].l;
533 }
534 XDrawSegments(disp, Panel->trace, gct, dot, 3);
535 }
536
ctl_channel_note(int ch,int note,int velocity)537 static void ctl_channel_note(int ch, int note, int velocity) {
538 if (velocity == 0) {
539 if (note == Panel->cnote[ch])
540 Panel->v_flags[ch] = FLAG_NOTE_OFF;
541 Panel->cvel[ch] = 0;
542 } else if (velocity > Panel->cvel[ch]) {
543 Panel->cvel[ch] = velocity;
544 Panel->cnote[ch] = note;
545 Panel->ctotal[ch] = velocity * Panel->channel[ch].volume *
546 Panel->channel[ch].expression / (127*127);
547 Panel->v_flags[ch] = FLAG_NOTE_ON;
548 }
549 }
550
drawKeyboardAll(Drawable pix,GC gc)551 static void drawKeyboardAll(Drawable pix, GC gc) {
552 int i, j;
553 XSegment dot[3];
554
555 XSetForeground(disp, gc, tracecolor);
556 XFillRectangle(disp, pix, gc, 0, 0, BARH_OFS8, BAR_SPACE);
557 XSetForeground(disp, gc, boxcolor);
558 XFillRectangle(disp, pix, gc, BARH_OFS8, 0,
559 trace_width-BARH_OFS8+1, BAR_SPACE);
560 for(i=0; i<KEY_NUM; i++) {
561 XSetForeground(disp, gc, keyG[i].col);
562 for(j=0; j<3; j++) {
563 dot[j].x1 = keyG[i].xofs + j;
564 dot[j].y1 = keyG[i].k[j].y;
565 dot[j].x2 = dot[j].x1;
566 dot[j].y2 = dot[j].y1 + keyG[i].k[j].l;
567 }
568 XDrawSegments(disp, pix, gc, dot, 3);
569 }
570 }
571
drawBank(int ch,int bank,int lsb,int msb)572 static void drawBank(int ch, int bank, int lsb, int msb) {
573 char s[4];
574
575 ch -= VISLOW;
576 XSetForeground(disp, gct, boxcolor);
577 XFillRectangle(disp, Panel->trace, gct,
578 pl[plane].ofs[CL_BA]+2, CHANNEL_HEIGHT(ch)+2,
579 pl[plane].w[CL_BA]-4, BAR_HEIGHT);
580 XFillRectangle(disp, Panel->trace, gct,
581 pl[plane].ofs[CL_BA_MSB]+2, CHANNEL_HEIGHT(ch)+2,
582 pl[plane].w[CL_BA_MSB]-4, BAR_HEIGHT);
583 XFillRectangle(disp, Panel->trace, gct,
584 pl[plane].ofs[CL_BA_LSB]+2, CHANNEL_HEIGHT(ch)+2,
585 pl[plane].w[CL_BA_LSB]-4, BAR_HEIGHT);
586 snprintf(s, sizeof(s), "%3d", bank);
587 TraceDrawStr(pl[plane].ofs[CL_BA]+6, CHANNEL_HEIGHT(ch)+BAR_HEIGHT-1,
588 s, strlen(s), textcolor);
589 snprintf(s, sizeof(s), "%3d", msb);
590 TraceDrawStr(pl[plane].ofs[CL_BA_MSB]+6, CHANNEL_HEIGHT(ch)+BAR_HEIGHT-1,
591 s, strlen(s), textcolor);
592 snprintf(s, sizeof(s), "%3d", lsb);
593 TraceDrawStr(pl[plane].ofs[CL_BA_LSB]+6, CHANNEL_HEIGHT(ch)+BAR_HEIGHT-1,
594 s, strlen(s), textcolor);
595 }
596
calcPitch(void)597 static const char * calcPitch(void)
598 {
599 int i, pitch;
600 static const char *keysig_name[] = {
601 "Cb", "Gb", "Db", "Ab", "Eb", "Bb", "F ", "C ",
602 "G ", "D ", "A ", "E ", "B ", "F#", "C#", "G#",
603 "D#", "A#"
604 };
605
606 pitch = Panel->pitch + ((Panel->pitch < 8) ? 7 : -6);
607 if (Panel->poffset > 0)
608 for (i = 0; i < Panel->poffset; i++)
609 pitch += (pitch > 10) ? -5 : 7;
610 else
611 for (i = 0; i < -Panel->poffset; i++)
612 pitch += (pitch < 7) ? 5 : -7;
613
614 return keysig_name[pitch];
615 }
616
617 #ifdef HAVE_LIBXFT
drawFoot(Boolean PitchChanged)618 static void drawFoot(Boolean PitchChanged) {
619 char *p, s[4096];
620 int l;
621
622 if (PitchChanged) Panel->key_cache = calcPitch();
623 if (Panel->pitch < 8) p = "Maj";
624 else p = "Min";
625 l = snprintf(s, sizeof(s),
626 "Voices %3d/%d Tempo %d/%3d%% Key %s %s (%+03d) %s",
627 Panel->last_voice, Panel->xaw_i_voices,
628 Panel->tempo*Panel->timeratio/100, Panel->timeratio,
629 Panel->key_cache, p, Panel->poffset, Panel->title);
630 if (l >= sizeof(s) || (l < 0)) l = sizeof(s) - 1;
631
632 /*
633 * In the Xft path we draw to a pixmap, and then copy that to screen.
634 * Reason is to avoid "flashing" in the footer, as it tends to change often
635 * (number of voices playing fluctuates) and Xft may be too slow otherwise.
636 */
637 XFillRectangle(disp, Panel->xft_trace_foot_pixmap, gcs, 0, 0,
638 trace_width, TRACE_FOOT-2);
639 #ifdef X_HAVE_UTF8_STRING
640 XftDrawStringUtf8(Panel->xft_trace_foot, &Panel->xft_capcolor, ttitle_font,
641 FOOT_HOFS, ttitle_font->ascent, (FcChar8 *)s, l);
642 #else
643 XftDrawString8(Panel->xft_trace_foot, &Panel->xft_capcolor, ttitle_font,
644 FOOT_HOFS, ttitle_font->ascent, (FcChar8 *)s, l);
645 #endif
646 XCopyArea(disp, (Drawable)Panel->xft_trace_foot_pixmap, (Drawable)Panel->trace,
647 gcs, 0, 0, trace_width, TRACE_FOOT-2, 0, trace_height_nf+2);
648 }
649
drawVoices(void)650 static void drawVoices(void) {
651 char s[20];
652 int l;
653 XGlyphInfo extents;
654
655 l = snprintf(s, sizeof(s), "Voices %3d/%d ",
656 Panel->last_voice, Panel->xaw_i_voices);
657 if ((l >= sizeof(s)) || (l < 0)) l = sizeof(s) - 1;
658 #ifdef X_HAVE_UTF8_STRING
659 XftTextExtentsUtf8(disp, ttitle_font, (FcChar8 *)s, l, &extents);
660 #else
661 XftTextExtents8(disp, ttitle_font, (FcChar8 *)s, l, &extents);
662 #endif
663 if (Panel->voices_width < extents.width) {
664 drawFoot(False);
665 } else {
666 XFillRectangle(disp, Panel->xft_trace_foot_pixmap, gcs, 0, 0,
667 Panel->voices_width, TRACE_FOOT-2);
668 #ifdef X_HAVE_UTF8_STRING
669 XftDrawStringUtf8(Panel->xft_trace_foot, &Panel->xft_capcolor,
670 ttitle_font, FOOT_HOFS, ttitle_font->ascent,
671 (FcChar8 *)s, l);
672 #else
673 XftDrawString8(Panel->xft_trace_foot, &Panel->xft_capcolor,
674 ttitle_font, FOOT_HOFS, ttitle_font->ascent,
675 (FcChar8 *)s, l);
676 #endif
677 XCopyArea(disp, (Drawable)Panel->xft_trace_foot_pixmap, (Drawable)Panel->trace,
678 gcs, 0, 0, Panel->voices_width, TRACE_FOOT-2, 0, trace_height_nf+2);
679 }
680 Panel->voices_width = extents.width;
681 }
682
drawInstname(int ch,char * name)683 static void drawInstname(int ch, char *name) {
684 int len;
685
686 ch -= VISLOW;
687 XSetForeground(disp, gct, boxcolor);
688 XFillRectangle(disp, Panel->xft_trace_inst_pixmap, gct,
689 0, 0, pl[plane].w[CL_IN]-4, BAR_HEIGHT);
690 len = strlen(name);
691 #ifdef X_HAVE_UTF8_STRING
692 XftDrawStringUtf8(Panel->xft_trace_inst, (Panel->is_drum[ch+VISLOW]) ?
693 &Panel->xft_capcolor : &Panel->xft_textcolor,
694 trace_font, 0, trace_font->ascent,
695 (FcChar8 *)name, len);
696 #else
697 XftDrawString8(Panel->xft_trace_inst, (Panel->is_drum[ch+VISLOW]) ?
698 &Panel->xft_capcolor : &Panel->xft_textcolor,
699 trace_font, 0, trace_font->ascent,
700 (FcChar8 *)name, len);
701 #endif
702 XCopyArea(disp, (Drawable)Panel->xft_trace_inst_pixmap,
703 (Drawable)Panel->trace, gct, 0, 0, pl[plane].w[CL_IN]-4,
704 BAR_HEIGHT, pl[plane].ofs[CL_IN]+2, CHANNEL_HEIGHT(ch)+2);
705 }
706
707 #else /* HAVE_LIBXFT */
708
drawFoot(Boolean PitchChanged)709 static void drawFoot(Boolean PitchChanged) {
710 char *p, s[4096];
711 int l, w;
712
713 if (PitchChanged) Panel->key_cache = calcPitch();
714 if (Panel->pitch < 8) p = "Maj";
715 else p = "Min";
716
717 l = snprintf(s, sizeof(s),
718 "Voices %3d/%d Tempo %d/%3d%% Key %s %s (%+03d) %s",
719 Panel->last_voice, Panel->xaw_i_voices,
720 Panel->tempo*Panel->timeratio/100, Panel->timeratio,
721 Panel->key_cache, p, Panel->poffset, Panel->title);
722 if (l >= sizeof(s) || (l < 0)) l = sizeof(s) - 1;
723
724 w = XmbTextEscapement(ttitle_font, s, l);
725 if (w < Panel->foot_width) {
726 XSetForeground(disp, gct, tracecolor);
727 /*
728 * w is reliable enough to detect changes in width used on screen,
729 * but can't be trusted enough to clear only w-Panel->foot_width width.
730 */
731 XFillRectangle(disp, Panel->trace, gct, 0,
732 trace_height_nf+2, trace_width,
733 TRACE_FOOT-2);
734 XmbDrawString(disp, Panel->trace, ttitle_font, gcs, 2,
735 trace_height_nf+Panel->title_font_ascent, s, l);
736 } else {
737 XmbDrawImageString(disp, Panel->trace, ttitle_font, gcs, 2,
738 trace_height_nf+Panel->title_font_ascent, s, l);
739 }
740 Panel->foot_width = w;
741 }
742
drawVoices(void)743 static void drawVoices(void) {
744 char s[20];
745 int l, w;
746
747 l = snprintf(s, sizeof(s), "Voices %3d/%d ",
748 Panel->last_voice, Panel->xaw_i_voices);
749 if ((l >= sizeof(s)) || (l < 0)) l = sizeof(s) - 1;
750 w = XmbTextEscapement(ttitle_font, s, l);
751 if (Panel->voices_width < w) {
752 drawFoot(False);
753 } else {
754 XmbDrawImageString(disp, Panel->trace, ttitle_font, gcs, 2,
755 trace_height_nf+Panel->title_font_ascent, s, l);
756 }
757 Panel->voices_width = w;
758 }
759
drawInstname(int ch,char * name)760 static void drawInstname(int ch, char *name) {
761 int len;
762
763 if (plane != 0) return;
764 ch -= VISLOW;
765 len = strlen(name);
766 XSetForeground(disp, gct, boxcolor);
767 XFillRectangle(disp, Panel->trace, gct,
768 pl[plane].ofs[CL_IN]+2, CHANNEL_HEIGHT(ch)+2,
769 pl[plane].w[CL_IN]-4, BAR_HEIGHT);
770 TraceDrawStr(pl[plane].ofs[CL_IN]+4, CHANNEL_HEIGHT(ch)+15,
771 name, len, (Panel->is_drum[ch+VISLOW])?capcolor:textcolor);
772 }
773 #endif /* HAVE_LIBXFT */
774
drawMute(int ch,int mute)775 static void drawMute(int ch, int mute) {
776 char s[16];
777
778 if (mute != 0) {
779 SET_CHANNELMASK(channel_mute, ch);
780 if (!XAWLIMIT(ch)) return;
781 /*
782 * If we drew the number using textbgcolor, it would only look clear in
783 * the non-Xft case, since AA may prevent the exact same pixels being used.
784 */
785 XSetForeground(disp, gct, textbgcolor);
786 XFillRectangle(disp, Panel->trace, gct, pl[plane].ofs[CL_C]+2,
787 CHANNEL_HEIGHT(ch-VISLOW)+2, pl[plane].w[CL_C]-4, BAR_HEIGHT);
788 } else {
789 UNSET_CHANNELMASK(channel_mute, ch);
790 if (!XAWLIMIT(ch)) return;
791 /* timidity internals counts from 0. timidity ui counts from 1 */
792 ch++;
793 snprintf(s, sizeof(s), "%2d", ch);
794 TraceDrawStr(pl[plane].ofs[CL_C]+2, CHANNEL_HEIGHT(ch-VISLOW)-5, s, 2, textcolor);
795 }
796 }
797
798 /* End of privates */
799
handleTraceinput(char * local_buf)800 int handleTraceinput(char *local_buf) {
801 char c;
802 int ch, i, n;
803
804 #define EXTRACT_CH(s,off) do { \
805 ch = atoi(s+off); \
806 local_buf = strchr(s, CH_END_TOKEN) - off; \
807 } while(0)
808
809 switch (local_buf[0]) {
810 case MT_NOTE:
811 {
812 int note;
813
814 EXTRACT_CH(local_buf, 1);
815 c = *(local_buf+2);
816 note = (*(local_buf+3) - '0') * 100 + (*(local_buf+4) - '0') * 10 +
817 *(local_buf+5) - '0';
818 n = atoi(local_buf+6);
819 if ((c == '*') || (c == '&')) {
820 Panel->c_flags[ch] |= FLAG_PROG_ON;
821 } else {
822 Panel->c_flags[ch] &= ~FLAG_PROG_ON; n = 0;
823 }
824 ctl_channel_note(ch, note, n);
825 if (!XAWLIMIT(ch)) break;
826 draw1Note(ch, note, c);
827 draw1Chan(ch, Panel->ctotal[ch], c);
828 }
829 break;
830 case MT_UPDATE_TIMER: /* update timer */
831 {
832 static double last_time = 0;
833 double d, t;
834 Bool need_flush;
835 double delta_time;
836
837 t = get_current_calender_time();
838 d = t - last_time;
839 if (d > 1) d = 1;
840 delta_time = d / TRACE_UPDATE_TIME;
841 last_time = t;
842 need_flush = False;
843 for(i=0; i<MAX_TRACE_CHANNELS; i++)
844 if (Panel->v_flags[i] != 0) {
845 if (Panel->v_flags[i] == FLAG_NOTE_OFF) {
846 Panel->ctotal[i] -= DELTA_VEL * delta_time;
847 if (Panel->ctotal[i] <= 0) {
848 Panel->ctotal[i] = 0;
849 Panel->v_flags[i] = 0;
850 }
851 if (XAWLIMIT(i)) draw1Chan(i, Panel->ctotal[i], '*');
852 need_flush = True;
853 } else {
854 Panel->v_flags[i] = 0;
855 }
856 }
857 if (need_flush) XFlush(disp);
858 }
859 break;
860 case MT_VOICES:
861 c = *(local_buf+1);
862 n = atoi(local_buf+2);
863 if (c == MTV_TOTAL_VOICES) {
864 if (Panel->xaw_i_voices != n) {
865 Panel->xaw_i_voices = n;
866 drawVoices();
867 }
868 }
869 else
870 if (Panel->last_voice != n) {
871 Panel->last_voice = n;
872 drawVoices();
873 }
874 break;
875 case MT_REDRAW_TRACE:
876 redrawTrace(True);
877 break;
878 case MT_MUTE:
879 EXTRACT_CH(local_buf, 1);
880 n = atoi(local_buf+2);
881 drawMute(ch, n);
882 break;
883 case MT_INST_NAME:
884 EXTRACT_CH(local_buf, 1);
885 strlcpy(Panel->inst_name[ch], (char *)&local_buf[2], INST_NAME_SIZE);
886 if (!XAWLIMIT(ch)) break;
887 drawInstname(ch, Panel->inst_name[ch]);
888 break;
889 case MT_IS_DRUM:
890 EXTRACT_CH(local_buf, 1);
891 Panel->is_drum[ch] = *(local_buf+2) - 'A';
892 if (!XAWLIMIT(ch)) break;
893 drawDrumPart(ch, Panel->is_drum[ch]);
894 break;
895 case MT_PANEL_INFO:
896 c = *(local_buf+1);
897 EXTRACT_CH(local_buf, 2);
898 n = atoi(local_buf+3);
899 switch(c) {
900 case MTP_PANNING:
901 Panel->channel[ch].panning = n;
902 Panel->c_flags[ch] |= FLAG_PAN;
903 if (plane || !XAWLIMIT(ch)) break;
904 drawPan(ch, n, True);
905 break;
906 case MTP_PITCH_BEND:
907 Panel->channel[ch].pitchbend = n;
908 Panel->c_flags[ch] |= FLAG_BENDT;
909 if (plane || !XAWLIMIT(ch)) break;
910 drawPitch(ch, n);
911 break;
912 case MTP_TONEBANK:
913 Panel->channel[ch].bank = n & 0xff;
914 Panel->channel[ch].bank_lsb = (n >> 8) & 0xff;
915 Panel->channel[ch].bank_msb = (n >> 16) & 0xff;
916 if (!plane || (!XAWLIMIT(ch))) break;
917 drawBank(ch, Panel->channel[ch].bank, Panel->channel[ch].bank_lsb,
918 Panel->channel[ch].bank_msb);
919 break;
920 case MTP_REVERB:
921 Panel->reverb[ch] = n;
922 if (!plane || !XAWLIMIT(ch)) break;
923 drawReverb(ch, n);
924 break;
925 case MTP_CHORUS:
926 Panel->channel[ch].chorus_level = n;
927 if (!plane || !XAWLIMIT(ch)) break;
928 drawChorus(ch, n);
929 break;
930 case MTP_SUSTAIN:
931 Panel->channel[ch].sustain = n;
932 Panel->c_flags[ch] |= FLAG_SUST;
933 break;
934 case MTP_PROGRAM:
935 Panel->channel[ch].program = n;
936 Panel->c_flags[ch] |= FLAG_PROG;
937 if (!XAWLIMIT(ch)) break;
938 drawProg(ch, n, True);
939 break;
940 case MTP_EXPRESSION:
941 Panel->channel[ch].expression = n;
942 ctl_channel_note(ch, Panel->cnote[ch], Panel->cvel[ch]);
943 if (!XAWLIMIT(ch)) break;
944 drawExp(ch, n);
945 break;
946 case MTP_VOLUME:
947 Panel->channel[ch].volume = n;
948 ctl_channel_note(ch, Panel->cnote[ch], Panel->cvel[ch]);
949 if (!XAWLIMIT(ch)) break;
950 drawVol(ch, n);
951 break;
952 }
953 break;
954 case MT_TEMPO:
955 i = atoi(local_buf+1);
956 n = (int) (500000/ (double)i * 120 + 0.5);
957 if (Panel->tempo != n) {
958 Panel->tempo = n;
959 drawFoot(False);
960 }
961 break;
962 case MT_RATIO:
963 n = atoi(local_buf+1);
964 if (Panel->timeratio != n) {
965 Panel->timeratio = n;
966 drawFoot(False);
967 }
968 break;
969 case MT_PITCH_OFFSET:
970 n = atoi(local_buf+1);
971 if (Panel->poffset != n) {
972 Panel->poffset = n;
973 drawFoot(True);
974 }
975 break;
976 case MT_PITCH:
977 n = atoi(local_buf+1);
978 if (Panel->pitch != n) {
979 Panel->pitch = n;
980 drawFoot(True);
981 }
982 break;
983 default:
984 return -1;
985 }
986 return 0;
987 }
988
redrawTrace(Boolean draw)989 void redrawTrace(Boolean draw) {
990 int i;
991 char s[3];
992
993 for(i=0; i<VISIBLE_CHANNELS; i++) {
994 XGCValues gv;
995
996 gv.tile = layer[plane];
997 gv.ts_x_origin = 0;
998 gv.ts_y_origin = CHANNEL_HEIGHT(i);
999 XChangeGC(disp, gc_xcopy, GCTile|GCTileStipXOrigin|GCTileStipYOrigin, &gv);
1000 XFillRectangle(disp, Panel->trace, gc_xcopy,
1001 0, CHANNEL_HEIGHT(i), trace_width, BAR_SPACE);
1002 }
1003 XSetForeground(disp, gct, capcolor);
1004 XDrawLine(disp, Panel->trace, gct, BARH_OFS0, trace_height_nf,
1005 trace_width-1, trace_height_nf);
1006
1007 for(i=VISLOW+1; i<VISLOW+VISIBLE_CHANNELS+1; i++) {
1008 snprintf(s, sizeof(s), "%2d", i);
1009 if (IS_SET_CHANNELMASK(channel_mute, i-1))
1010 TraceDrawStr(pl[plane].ofs[CL_C]+2, CHANNEL_HEIGHT(i-VISLOW)-5,
1011 s, 2, textbgcolor);
1012 else
1013 TraceDrawStr(pl[plane].ofs[CL_C]+2, CHANNEL_HEIGHT(i-VISLOW)-5,
1014 s, 2, textcolor);
1015 }
1016
1017 if (Panel->g_cursor_is_in) {
1018 XSetForeground(disp, gct, capcolor);
1019 XFillRectangle(disp, Panel->trace, gct, 0, 0, trace_width, TRACE_HEADER);
1020 }
1021 redrawCaption(Panel->g_cursor_is_in);
1022
1023 drawFoot(True);
1024 if (draw) {
1025 for(i=VISLOW; i<VISLOW+VISIBLE_CHANNELS; i++) {
1026 if ((Panel->ctotal[i] != 0) && (Panel->c_flags[i] & FLAG_PROG_ON))
1027 draw1Chan(i, Panel->ctotal[i], '*');
1028 drawProg(i, Panel->channel[i].program, False);
1029 drawVol(i, Panel->channel[i].volume);
1030 drawExp(i, Panel->channel[i].expression);
1031 if (plane) {
1032 drawBank(i, Panel->channel[i].bank, Panel->channel[i].bank_lsb,
1033 Panel->channel[i].bank_msb);
1034 drawReverb(i, Panel->reverb[i]);
1035 drawChorus(i, Panel->channel[i].chorus_level);
1036 } else {
1037 drawPitch(i, Panel->channel[i].pitchbend);
1038 drawInstname(i, Panel->inst_name[i]);
1039 }
1040 }
1041 if (!plane) {
1042 XSetForeground(disp, gct, pancolor);
1043 for(i=VISLOW; i<VISLOW+VISIBLE_CHANNELS; i++) {
1044 if (Panel->c_flags[i] & FLAG_PAN)
1045 drawPan(i, Panel->channel[i].panning, False);
1046 }
1047 XSetForeground(disp, gct, textcolor);
1048 }
1049 }
1050 }
1051
redrawCaption(Boolean cursor_is_in)1052 void redrawCaption(Boolean cursor_is_in) {
1053 const char *p;
1054 int i;
1055
1056 Panel->g_cursor_is_in = cursor_is_in;
1057 if (cursor_is_in) {
1058 XSetForeground(disp, gct, capcolor);
1059 XFillRectangle(disp, Panel->trace, gct, 0, 0, trace_width, TRACE_HEADER);
1060 XSetBackground(disp, gct, expcolor);
1061 for(i=0; i<pl[plane].col; i++) {
1062 p = pl[plane].cap[i];
1063 TitleDrawStr(pl[plane].ofs[i]+4, BAR_HEIGHT, p, strlen(p), tracecolor);
1064 }
1065 } else {
1066 XSetForeground(disp, gct, tracecolor);
1067 XFillRectangle(disp, Panel->trace, gct, 0, 0, trace_width, TRACE_HEADER);
1068 XSetBackground(disp, gct, tracecolor);
1069 for(i=0; i<pl[plane].col; i++) {
1070 p = pl[plane].cap[i];
1071 TitleDrawStr(pl[plane].ofs[i]+4, BAR_HEIGHT, p, strlen(p), capcolor);
1072 }
1073 }
1074 }
1075
initStatus(void)1076 void initStatus(void) {
1077 int i;
1078
1079 for(i=0; i<MAX_TRACE_CHANNELS; i++) {
1080 Panel->c_flags[i] = 0;
1081 Panel->channel[i].bank = 0;
1082 Panel->channel[i].chorus_level = 0;
1083 Panel->channel[i].expression = 0;
1084 Panel->channel[i].panning = -1;
1085 Panel->channel[i].pitchbend = 0;
1086 Panel->channel[i].program = 0;
1087 Panel->channel[i].sustain = 0;
1088 Panel->channel[i].volume = 0;
1089 Panel->cnote[i] = 0;
1090 Panel->cvel[i] = 0;
1091 Panel->ctotal[i] = 0;
1092 Panel->is_drum[i] = 0;
1093 *(Panel->inst_name[i]) = '\0';
1094 Panel->reverb[i] = 0;
1095 Panel->v_flags[i] = 0;
1096 }
1097 Panel->multi_part = 0;
1098 Panel->pitch = 0;
1099 Panel->poffset = 0;
1100 Panel->tempo = 100;
1101 Panel->timeratio = 100;
1102 Panel->last_voice = 0;
1103 }
1104
scrollTrace(int direction)1105 void scrollTrace(int direction) {
1106 if (direction > 0) {
1107 if (Panel->multi_part < (MAX_TRACE_CHANNELS - 2*VISIBLE_CHANNELS))
1108 Panel->multi_part += VISIBLE_CHANNELS;
1109 else if (Panel->multi_part < (MAX_TRACE_CHANNELS - VISIBLE_CHANNELS))
1110 Panel->multi_part = MAX_TRACE_CHANNELS - VISIBLE_CHANNELS;
1111 else
1112 Panel->multi_part = 0;
1113 } else {
1114 if (Panel->multi_part > VISIBLE_CHANNELS)
1115 Panel->multi_part -= VISIBLE_CHANNELS;
1116 else if (Panel->multi_part > 0)
1117 Panel->multi_part = 0;
1118 else
1119 Panel->multi_part = MAX_TRACE_CHANNELS - VISIBLE_CHANNELS;
1120 }
1121 redrawTrace(True);
1122 }
1123
toggleTracePlane(Boolean draw)1124 void toggleTracePlane(Boolean draw) {
1125 plane ^= 1;
1126 redrawTrace(draw);
1127 }
1128
getLowestVisibleChan(void)1129 int getLowestVisibleChan(void) {
1130 return Panel->multi_part;
1131 }
1132
getVisibleChanNum(void)1133 int getVisibleChanNum(void) {
1134 return Panel->visible_channels;
1135 }
1136
initTrace(Display * dsp,Window trace,char * title,tconfig * cfg)1137 void initTrace(Display *dsp, Window trace, char *title, tconfig *cfg) {
1138 #ifdef HAVE_LIBXFT
1139 char *font_name;
1140 #else
1141 char **ml;
1142 XFontStruct **fs_list;
1143 #endif
1144 int i, j, k, tmpi, w, screen;
1145 unsigned long gcmask;
1146 XGCValues gv;
1147
1148 Panel = (PanelInfo *)safe_malloc(sizeof(PanelInfo));
1149 Panel->trace = trace;
1150 if (!strcmp(title, "(null)")) Panel->title = (char *)UNTITLED_STR;
1151 else Panel->title = title;
1152 Panel->cfg = cfg;
1153 plane = 0;
1154 Panel->g_cursor_is_in = False;
1155 disp = dsp;
1156 screen = DefaultScreen(disp);
1157 Panel->key_cache = "C ";
1158 if (gradient_bar) {
1159 Panel->grad = (GradData *)safe_malloc(sizeof(GradData));
1160 Panel->depth = getdisplayinfo(&Panel->grad->rgb);
1161 for (i=0; i<MAX_GRADIENT_COLUMN; i++) gradient_set[i] = 0;
1162 x_boxcolor.pixel = boxcolor;
1163 XQueryColor(disp, DefaultColormap(disp, 0), &x_boxcolor);
1164 } else {
1165 Panel->grad = NULL;
1166 Panel->depth = getdisplayinfo(NULL);
1167 }
1168
1169 for(i=0; i<MAX_TRACE_CHANNELS; i++) {
1170 if (ISDRUMCHANNEL(i)) {
1171 Panel->is_drum[i] = 1;
1172 Panel->barcol[i] = cfg->drumvelocity_color;
1173 } else {
1174 Panel->barcol[i] = cfg->velocity_color;
1175 }
1176 Panel->inst_name[i] = (char *)safe_malloc(sizeof(char) * INST_NAME_SIZE);
1177 }
1178 initStatus();
1179 Panel->xaw_i_voices = 0;
1180 Panel->visible_channels = (cfg->trace_height - TRACE_HEADER - TRACE_FOOT) /
1181 BAR_SPACE;
1182 if (Panel->visible_channels > MAX_CHANNELS)
1183 Panel->visible_channels = MAX_CHANNELS;
1184 else if (Panel->visible_channels < 1)
1185 Panel->visible_channels = 1;
1186 /* This prevents empty space between the trace foot and the channel bars. */
1187 cfg->trace_height = Panel->visible_channels * BAR_SPACE +
1188 TRACE_HEADER + TRACE_FOOT;
1189
1190 Panel->voices_width = 0;
1191 #ifdef HAVE_LIBXFT
1192 if ((XftInit(NULL) != FcTrue) || (XftInitFtLibrary() != FcTrue)) {
1193 fprintf(stderr, "Xft can't init font library!\n");
1194 exit(1);
1195 }
1196
1197 font_name = XBaseFontNameListOfFontSet(Panel->cfg->c_title_font);
1198 ttitle_font = XftFontOpenXlfd(disp, screen, font_name);
1199 if (ttitle_font == NULL)
1200 ttitle_font = XftFontOpenName(disp, screen, font_name);
1201 if (ttitle_font == NULL) {
1202 fprintf(stderr, "can't load font %s\n", font_name);
1203 exit(1);
1204 }
1205
1206 font_name = XBaseFontNameListOfFontSet(Panel->cfg->c_trace_font);
1207 trace_font = XftFontOpenXlfd(disp, screen, font_name);
1208 if (trace_font == NULL)
1209 trace_font = XftFontOpenName(disp, screen, font_name);
1210 if (trace_font == NULL) {
1211 fprintf(stderr, "can't load font %s\n", font_name);
1212 exit(1);
1213 }
1214
1215 Panel->xft_trace = XftDrawCreate(disp, (Drawable)Panel->trace,
1216 DefaultVisual(disp, screen),
1217 DefaultColormap(disp, screen));
1218 Panel->xft_trace_foot_pixmap = XCreatePixmap (disp, (Drawable)Panel->trace,
1219 trace_width, TRACE_FOOT-2,
1220 Panel->depth);
1221 Panel->xft_trace_foot = XftDrawCreate(disp,
1222 (Drawable)Panel->xft_trace_foot_pixmap,
1223 DefaultVisual(disp, screen),
1224 DefaultColormap(disp, screen));
1225 Panel->xft_trace_inst_pixmap = XCreatePixmap (disp, (Drawable)Panel->trace,
1226 pl[plane].w[CL_IN]-4,
1227 BAR_HEIGHT, Panel->depth);
1228 Panel->xft_trace_inst = XftDrawCreate(disp,
1229 (Drawable)Panel->xft_trace_inst_pixmap,
1230 DefaultVisual(disp, screen),
1231 DefaultColormap(disp, screen));
1232
1233 COPY_PIXEL (Panel->xft_capcolor, capcolor);
1234 COPY_PIXEL (Panel->xft_textcolor, textcolor);
1235
1236 gcmask = GCForeground;
1237 gv.foreground = tracecolor;
1238 gcs = XCreateGC(disp, RootWindow(disp, screen), gcmask, &gv);
1239 #else
1240 Panel->foot_width = trace_width;
1241
1242 j = XFontsOfFontSet(ttitle_font, &fs_list, &ml);
1243 Panel->title_font_ascent = fs_list[0]->ascent;
1244 for (i=1; i<j; i++) {
1245 if (Panel->title_font_ascent < fs_list[i]->ascent)
1246 Panel->title_font_ascent = fs_list[i]->ascent;
1247 }
1248
1249 gcmask = GCForeground | GCBackground;
1250 gv.foreground = capcolor;
1251 gv.background = tracecolor;
1252 gv.plane_mask = 1;
1253 gcs = XCreateGC(disp, RootWindow(disp, screen), gcmask, &gv);
1254 #endif /* HAVE_LIBXFT */
1255
1256 gv.fill_style = FillTiled;
1257 gv.fill_rule = WindingRule;
1258 gc_xcopy = XCreateGC(disp, RootWindow(disp, screen),
1259 GCFillStyle | GCFillRule, &gv);
1260 gct = XCreateGC(disp, RootWindow(disp, screen), 0, NULL);
1261
1262 if (keyG == NULL) keyG = (ThreeL *)safe_malloc(sizeof(ThreeL) * KEY_NUM);
1263 for(i=0, j=BARH_OFS8+1; i<KEY_NUM; i++) {
1264 tmpi = i%12;
1265 switch (tmpi) {
1266 case 0:
1267 case 5:
1268 case 10:
1269 keyG[i].k[0].y = 11; keyG[i].k[0].l = 7;
1270 keyG[i].k[1].y = 2; keyG[i].k[1].l = 16;
1271 keyG[i].k[2].y = 11; keyG[i].k[2].l = 7;
1272 keyG[i].col = white;
1273 break;
1274 case 2:
1275 case 7:
1276 keyG[i].k[0].y = 11; keyG[i].k[0].l = 7;
1277 keyG[i].k[1].y = 2; keyG[i].k[1].l = 16;
1278 keyG[i].k[2].y = 2; keyG[i].k[2].l = 16;
1279 keyG[i].col = white;
1280 break;
1281 case 3:
1282 case 8:
1283 j += 2;
1284 keyG[i].k[0].y = 2; keyG[i].k[0].l = 16;
1285 keyG[i].k[1].y = 2; keyG[i].k[1].l = 16;
1286 keyG[i].k[2].y = 11; keyG[i].k[2].l = 7;
1287 keyG[i].col = white;
1288 break;
1289 default: /* black key */
1290 keyG[i].k[0].y = 2; keyG[i].k[0].l = 8;
1291 keyG[i].k[1].y = 2; keyG[i].k[1].l = 8;
1292 keyG[i].k[2].y = 2; keyG[i].k[2].l = 8;
1293 keyG[i].col = black;
1294 break;
1295 }
1296 keyG[i].xofs = j; j += 2;
1297 }
1298
1299 /* draw on template pixmaps that includes one channel row */
1300 for(i=0; i<2; i++) {
1301 layer[i] = XCreatePixmap(disp, Panel->trace, trace_width, BAR_SPACE,
1302 DefaultDepth(disp, screen));
1303 drawKeyboardAll(layer[i], gct);
1304 XSetForeground(disp, gct, capcolor);
1305 XDrawLine(disp, layer[i], gct, 0, 0, trace_width, 0);
1306 XDrawLine(disp, layer[i], gct, 0, 0, 0, BAR_SPACE);
1307 XDrawLine(disp, layer[i], gct, trace_width-1, 0, trace_width-1, BAR_SPACE);
1308
1309 for(j=0; j < pl[i].col-1; j++) {
1310 tmpi = TRACE_HOFS; w = pl[i].w[j];
1311 for(k=0; k<j; k++) tmpi += pl[i].w[k];
1312 tmpi = pl[i].ofs[j];
1313 XSetForeground(disp, gct, capcolor);
1314 XDrawLine(disp, layer[i], gct, tmpi+w, 0, tmpi+w, BAR_SPACE);
1315 XSetForeground(disp, gct, rimcolor);
1316 XDrawLine(disp, layer[i], gct, tmpi+w-2, 2, tmpi+w-2, BAR_HEIGHT+1);
1317 XDrawLine(disp, layer[i], gct, tmpi+2, BAR_HEIGHT+2, tmpi+w-2,
1318 BAR_HEIGHT+2);
1319 XSetForeground(disp, gct, j?boxcolor:textbgcolor);
1320 XFillRectangle(disp, layer[i], gct, tmpi+2, 2, w-4, BAR_HEIGHT);
1321 }
1322 }
1323 }
1324
uninitTrace(void)1325 void uninitTrace(void) {
1326 int i;
1327
1328 XFreePixmap(disp, layer[0]); XFreePixmap(disp, layer[1]);
1329 #ifdef HAVE_LIBXFT
1330 XftDrawDestroy(Panel->xft_trace);
1331 XftDrawDestroy(Panel->xft_trace_foot);
1332 XftDrawDestroy(Panel->xft_trace_inst);
1333 XFreePixmap(disp, Panel->xft_trace_foot_pixmap);
1334 XFreePixmap(disp, Panel->xft_trace_inst_pixmap);
1335 XftFontClose(disp, ttitle_font);
1336 XftFontClose(disp, trace_font);
1337 #endif
1338 if (Panel->grad != NULL) for (i=0; i<MAX_GRADIENT_COLUMN; i++) {
1339 if (gradient_set[i]) {
1340 XFreePixmap(disp, gradient_pixmap[i]);
1341 XFreeGC(disp, gradient_gc[i]);
1342 }
1343 }
1344 XFreeGC(disp, gcs); XFreeGC(disp, gct); XFreeGC(disp, gc_xcopy);
1345
1346 for (i=0; i<MAX_TRACE_CHANNELS; i++) free(Panel->inst_name[i]);
1347 free(Panel->grad); free(Panel); free(keyG);
1348 }
1349