1 /*
2
3 This widget provides peak meters
4
5 (c) Fraser Stuart 2009
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 */
22
23 #include "stdlib.h"
24 #include "string.h"
25 #include "widgets.h"
26 #include "meter-peak.h"
27
28
29 static void inv_meter_class_init(InvMeterClass *klass);
30 static void inv_meter_init(InvMeter *meter);
31 static void inv_meter_size_request(GtkWidget *widget, GtkRequisition *requisition);
32 static void inv_meter_size_allocate(GtkWidget *widget, GtkAllocation *allocation);
33 static void inv_meter_realize(GtkWidget *widget);
34 static gboolean inv_meter_expose(GtkWidget *widget,GdkEventExpose *event);
35 static void inv_meter_paint(GtkWidget *widget, gint drawmode);
36 static void inv_meter_destroy(GtkObject *object);
37 static void inv_meter_colour_tozero(GtkWidget *widget, gint bypass, gint pos, gint on, struct colour *led);
38 static void inv_meter_colour_fromzero(GtkWidget *widget, gint bypass, gint pos, gint on, struct colour *led);
39 static void inv_meter_colour_bigtozero(GtkWidget *widget, gint bypass, gint pos, gint on, struct colour *led);
40
41
42 GtkType
inv_meter_get_type(void)43 inv_meter_get_type(void)
44 {
45 static GType inv_meter_type = 0;
46 char *name;
47 int i;
48
49
50 if (!inv_meter_type)
51 {
52 static const GTypeInfo type_info = {
53 sizeof(InvMeterClass),
54 NULL, /* base_init */
55 NULL, /* base_finalize */
56 (GClassInitFunc)inv_meter_class_init,
57 NULL, /* class_finalize */
58 NULL, /* class_data */
59 sizeof(InvMeter),
60 0, /* n_preallocs */
61 (GInstanceInitFunc)inv_meter_init
62 };
63 for (i = 0; ; i++) {
64 name = g_strdup_printf("InvMeter-%p-%d",inv_meter_class_init, i);
65 if (g_type_from_name(name)) {
66 free(name);
67 continue;
68 }
69 inv_meter_type = g_type_register_static(GTK_TYPE_WIDGET,name,&type_info,(GTypeFlags)0);
70 free(name);
71 break;
72 }
73 }
74 return inv_meter_type;
75 }
76
77 void
inv_meter_set_bypass(InvMeter * meter,gint num)78 inv_meter_set_bypass(InvMeter *meter, gint num)
79 {
80 if(meter->bypass != num) {
81 meter->bypass = num;
82 switch(meter->mode) {
83 case INV_METER_DRAW_MODE_TOZERO:
84 meter->LdB=-90;
85 meter->RdB=-90;
86 break;
87 case INV_METER_DRAW_MODE_FROMZERO:
88 meter->LdB=0;
89 meter->RdB=0;
90 break;
91 }
92 }
93 }
94
95 void
inv_meter_set_channels(InvMeter * meter,gint num)96 inv_meter_set_channels(InvMeter *meter, gint num)
97 {
98 meter->channels = num;
99 }
100
101 void
inv_meter_set_mode(InvMeter * meter,gint num)102 inv_meter_set_mode(InvMeter *meter, gint num)
103 {
104 meter->mode = num;
105 }
106
107 void
inv_meter_set_LdB(InvMeter * meter,float num)108 inv_meter_set_LdB(InvMeter *meter, float num)
109 {
110 meter->LdB = num;
111 if(GTK_WIDGET_REALIZED(meter))
112 inv_meter_paint(GTK_WIDGET(meter),INV_METER_DRAW_L);
113 }
114
115 void
inv_meter_set_RdB(InvMeter * meter,float num)116 inv_meter_set_RdB(InvMeter *meter, float num)
117 {
118 meter->RdB = num;
119 if(GTK_WIDGET_REALIZED(meter))
120 inv_meter_paint(GTK_WIDGET(meter),INV_METER_DRAW_R);
121 }
122
123
inv_meter_new()124 GtkWidget * inv_meter_new()
125 {
126 return GTK_WIDGET(gtk_type_new(inv_meter_get_type()));
127 }
128
129
130 static void
inv_meter_class_init(InvMeterClass * klass)131 inv_meter_class_init(InvMeterClass *klass)
132 {
133 GtkWidgetClass *widget_class;
134 GtkObjectClass *object_class;
135
136
137 widget_class = (GtkWidgetClass *) klass;
138 object_class = (GtkObjectClass *) klass;
139
140 widget_class->realize = inv_meter_realize;
141 widget_class->size_request = inv_meter_size_request;
142 widget_class->size_allocate = inv_meter_size_allocate;
143 widget_class->expose_event = inv_meter_expose;
144
145 object_class->destroy = inv_meter_destroy;
146 }
147
148
149 static void
inv_meter_init(InvMeter * meter)150 inv_meter_init(InvMeter *meter)
151 {
152 meter->bypass = INV_PLUGIN_ACTIVE;
153 meter->mode=INV_METER_DRAW_MODE_TOZERO;
154 meter->channels = 1;
155 meter->LdB = -90;
156 meter->RdB = -90;
157 meter->lastLpos = 1;
158 meter->lastRpos = 1;
159
160
161 meter->mOff60.R =0.1; meter->mOff60.G =0.1; meter->mOff60.B =0.4;
162 meter->mOn60.R =-0.1; meter->mOn60.G =-0.1; meter->mOn60.B =0.6;
163
164 meter->mOff12.R =0.2; meter->mOff12.G =0.3; meter->mOff12.B =0.4;
165 meter->mOn12.R =-0.1; meter->mOn12.G =0.3; meter->mOn12.B =0.6;
166
167 meter->mOff6.R =0.2; meter->mOff6.G =0.4; meter->mOff6.B =0.2;
168 meter->mOn6.R =0.1; meter->mOn6.G =0.6; meter->mOn6.B =-0.1;
169
170 meter->mOff0.R =0.5; meter->mOff0.G =0.5; meter->mOff0.B =0.0;
171 meter->mOn0.R =0.5; meter->mOn0.G =0.5; meter->mOn0.B =0.0;
172
173 meter->overOff.R=0.4; meter->overOff.G=0.2; meter->overOff.B=0.0;
174 meter->overOn.R =0.6; meter->overOn.G =0.0; meter->overOn.B =0.0;
175
176 meter->label_font_size=0;
177 meter->scale_font_size=0;
178
179 gtk_widget_set_tooltip_markup(GTK_WIDGET(meter),"<span size=\"8000\">Peak Meter.</span>");
180
181 }
182
183
184 static void
inv_meter_size_request(GtkWidget * widget,GtkRequisition * requisition)185 inv_meter_size_request(GtkWidget *widget,
186 GtkRequisition *requisition)
187 {
188 g_return_if_fail(widget != NULL);
189 g_return_if_fail(INV_IS_METER(widget));
190 g_return_if_fail(requisition != NULL);
191 switch(INV_METER(widget)->mode) {
192 case INV_METER_DRAW_MODE_TOZERO:
193 case INV_METER_DRAW_MODE_FROMZERO:
194 requisition->width = 149;
195 requisition->height = 37;
196 break;
197 case INV_METER_DRAW_MODE_BIGTOZERO:
198 requisition->width = 308;
199 requisition->height = 37;
200 break;
201 }
202
203 }
204
205
206 static void
inv_meter_size_allocate(GtkWidget * widget,GtkAllocation * allocation)207 inv_meter_size_allocate(GtkWidget *widget,
208 GtkAllocation *allocation)
209 {
210 g_return_if_fail(widget != NULL);
211 g_return_if_fail(INV_IS_METER(widget));
212 g_return_if_fail(allocation != NULL);
213
214 widget->allocation = *allocation;
215
216 if (GTK_WIDGET_REALIZED(widget)) {
217 gdk_window_move_resize(
218 widget->window,
219 allocation->x, allocation->y,
220 allocation->width, allocation->height
221 );
222 }
223 }
224
225
226 static void
inv_meter_realize(GtkWidget * widget)227 inv_meter_realize(GtkWidget *widget)
228 {
229 GdkWindowAttr attributes;
230 guint attributes_mask;
231
232 g_return_if_fail(widget != NULL);
233 g_return_if_fail(INV_IS_METER(widget));
234
235 GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
236
237 attributes.window_type = GDK_WINDOW_CHILD;
238 attributes.x = widget->allocation.x;
239 attributes.y = widget->allocation.y;
240
241 switch(INV_METER(widget)->mode) {
242 case INV_METER_DRAW_MODE_TOZERO:
243 case INV_METER_DRAW_MODE_FROMZERO:
244 attributes.width = 149;
245 attributes.height = 37;
246 break;
247 case INV_METER_DRAW_MODE_BIGTOZERO:
248 attributes.width = 308;
249 attributes.height = 37;
250 break;
251 }
252
253 attributes.wclass = GDK_INPUT_OUTPUT;
254 attributes.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK;
255
256 attributes_mask = GDK_WA_X | GDK_WA_Y;
257
258 widget->window = gdk_window_new(
259 gtk_widget_get_parent_window (widget),
260 & attributes, attributes_mask
261 );
262
263 gdk_window_set_user_data(widget->window, widget);
264
265 widget->style = gtk_style_attach(widget->style, widget->window);
266 gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL);
267 }
268
269
270 static gboolean
inv_meter_expose(GtkWidget * widget,GdkEventExpose * event)271 inv_meter_expose(GtkWidget *widget, GdkEventExpose *event)
272 {
273 g_return_val_if_fail(widget != NULL, FALSE);
274 g_return_val_if_fail(INV_IS_METER(widget), FALSE);
275 g_return_val_if_fail(event != NULL, FALSE);
276
277 inv_meter_paint(widget,INV_METER_DRAW_ALL);
278
279 return FALSE;
280 }
281
282
283 static void
inv_meter_paint(GtkWidget * widget,gint drawmode)284 inv_meter_paint(GtkWidget *widget, gint drawmode)
285 {
286 gint bypass;
287 gint mode;
288 gint channels;
289 gint Lpos=0;
290 gint Rpos=0;
291 gint lastLpos;
292 gint lastRpos;
293
294 cairo_t *cr;
295 gint Lon,Ron,min,max,i;
296 struct colour led;
297 GtkStyle *style;
298 char label[10];
299 cairo_text_extents_t extents;
300
301 style = gtk_widget_get_style(widget);
302 bypass = INV_METER(widget)->bypass;
303 mode = INV_METER(widget)->mode;
304 channels = INV_METER(widget)->channels;
305
306 switch(mode) {
307 case INV_METER_DRAW_MODE_TOZERO:
308 Lpos = bypass==INV_PLUGIN_ACTIVE ? (gint)(INV_METER(widget)->LdB+60.51) : 0 ; /* -60 to +6 db step 1db = 67 points*/
309 Rpos = bypass==INV_PLUGIN_ACTIVE ? (gint)(INV_METER(widget)->RdB+60.51) : 0 ;
310 break;
311 case INV_METER_DRAW_MODE_FROMZERO:
312 Lpos = bypass==INV_PLUGIN_ACTIVE ? (gint)(2*(INV_METER(widget)->LdB)+71.51): 72 ; /* -35.5 to 0 db step 0.5db = 71 points */
313 Rpos = bypass==INV_PLUGIN_ACTIVE ? (gint)(2*(INV_METER(widget)->RdB)+71.51): 72 ;
314 break;
315 case INV_METER_DRAW_MODE_BIGTOZERO:
316 Lpos = bypass==INV_PLUGIN_ACTIVE ? (gint)(2*(INV_METER(widget)->LdB)+120.51) : 0 ; /* -60 to +12 db step 0.5db = 145 points*/
317 Rpos = bypass==INV_PLUGIN_ACTIVE ? (gint)(2*(INV_METER(widget)->RdB)+120.51) : 0 ;
318 break;
319 }
320
321
322 lastLpos = INV_METER(widget)->lastLpos;
323 lastRpos = INV_METER(widget)->lastRpos;
324
325 cr = gdk_cairo_create(widget->window);
326
327 if(INV_METER(widget)->label_font_size==0) {
328 INV_METER(widget)->label_font_size=inv_choose_font_size(cr,"sans-serif",CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_NORMAL,99.0,6.1,"0");
329 }
330 if(INV_METER(widget)->scale_font_size==0) {
331 INV_METER(widget)->scale_font_size=inv_choose_font_size(cr,"sans-serif",CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_NORMAL,99.0,6.1,"0");
332 }
333
334
335 switch(drawmode) {
336 case INV_METER_DRAW_ALL:
337
338 gdk_cairo_set_source_color(cr,&style->bg[GTK_STATE_NORMAL]);
339 cairo_paint(cr);
340 switch(mode) {
341 case INV_METER_DRAW_MODE_TOZERO:
342 case INV_METER_DRAW_MODE_FROMZERO:
343 cairo_set_source_rgb(cr, 0, 0, 0);
344 cairo_rectangle(cr, 0, 0, 149, 24);
345 cairo_fill(cr);
346
347 cairo_new_path(cr);
348
349 cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
350 cairo_set_antialias (cr,CAIRO_ANTIALIAS_NONE);
351 cairo_set_line_width(cr,1);
352
353 gdk_cairo_set_source_color(cr,&style->dark[GTK_STATE_NORMAL]);
354 cairo_move_to(cr, 0, 23);
355 cairo_line_to(cr, 0, 0);
356 cairo_line_to(cr, 148, 0);
357 cairo_stroke(cr);
358
359 gdk_cairo_set_source_color(cr,&style->light[GTK_STATE_NORMAL]);
360 cairo_move_to(cr, 0, 23);
361 cairo_line_to(cr, 148, 23);
362 cairo_line_to(cr, 148, 0);
363 cairo_stroke(cr);
364 break;
365 case INV_METER_DRAW_MODE_BIGTOZERO:
366 cairo_set_source_rgb(cr, 0, 0, 0);
367 cairo_rectangle(cr, 0, 0, 303, 24);
368 cairo_fill(cr);
369
370 cairo_new_path(cr);
371
372 cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
373 cairo_set_antialias (cr,CAIRO_ANTIALIAS_NONE);
374 cairo_set_line_width(cr,1);
375
376 gdk_cairo_set_source_color(cr,&style->dark[GTK_STATE_NORMAL]);
377 cairo_move_to(cr, 0, 23);
378 cairo_line_to(cr, 0, 0);
379 cairo_line_to(cr, 302, 0);
380 cairo_stroke(cr);
381
382 gdk_cairo_set_source_color(cr,&style->light[GTK_STATE_NORMAL]);
383 cairo_move_to(cr, 0, 23);
384 cairo_line_to(cr, 302, 23);
385 cairo_line_to(cr, 302, 0);
386 cairo_stroke(cr);
387 break;
388 }
389
390
391 cairo_set_antialias (cr,CAIRO_ANTIALIAS_DEFAULT);
392 cairo_new_path(cr);
393
394 cairo_select_font_face(cr,"sans-serif",CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_NORMAL);
395 cairo_set_font_size(cr,INV_METER(widget)->scale_font_size);
396
397 switch(mode) {
398 case INV_METER_DRAW_MODE_TOZERO:
399 for(i=0;i<=5;i++) {
400 if(inv_choose_light_dark(&style->bg[GTK_STATE_NORMAL],&style->light[GTK_STATE_NORMAL],&style->dark[GTK_STATE_NORMAL])==1) {
401 gdk_cairo_set_source_color(cr,&style->light[GTK_STATE_NORMAL]);
402 } else {
403 gdk_cairo_set_source_color(cr,&style->dark[GTK_STATE_NORMAL]);
404 }
405 cairo_rectangle(cr, 10+(i*24), 25, 1, 2);
406 cairo_fill(cr);
407
408 if(bypass==INV_PLUGIN_BYPASS) {
409 gdk_cairo_set_source_color(cr,&style->fg[GTK_STATE_INSENSITIVE]);
410 } else {
411 gdk_cairo_set_source_color(cr,&style->fg[GTK_STATE_NORMAL]);
412 }
413 sprintf(label,"%i",(12*i)-60);
414 cairo_text_extents (cr,label,&extents);
415 cairo_move_to(cr,10+(i*24)-(extents.width/2),35);
416 cairo_show_text(cr,label);
417 }
418 break;
419
420 case INV_METER_DRAW_MODE_FROMZERO:
421 for(i=0;i<=5;i++) {
422 if(inv_choose_light_dark(&style->bg[GTK_STATE_NORMAL],&style->light[GTK_STATE_NORMAL],&style->dark[GTK_STATE_NORMAL])==1) {
423 gdk_cairo_set_source_color(cr,&style->light[GTK_STATE_NORMAL]);
424 } else {
425 gdk_cairo_set_source_color(cr,&style->dark[GTK_STATE_NORMAL]);
426 }
427 cairo_rectangle(cr, 24+(i*24), 25, 1, 2);
428 cairo_fill(cr);
429
430 if(bypass==INV_PLUGIN_BYPASS) {
431 gdk_cairo_set_source_color(cr,&style->fg[GTK_STATE_INSENSITIVE]);
432 } else {
433 gdk_cairo_set_source_color(cr,&style->fg[GTK_STATE_NORMAL]);
434 }
435 sprintf(label,"%i",30-(6*i));
436 cairo_text_extents (cr,label,&extents);
437 cairo_move_to(cr,24+(i*24)-(extents.width/2),35);
438 cairo_show_text(cr,label);
439 }
440 break;
441 case INV_METER_DRAW_MODE_BIGTOZERO:
442 for(i=0;i<=12;i++) {
443 if(inv_choose_light_dark(&style->bg[GTK_STATE_NORMAL],&style->light[GTK_STATE_NORMAL],&style->dark[GTK_STATE_NORMAL])==1) {
444 gdk_cairo_set_source_color(cr,&style->light[GTK_STATE_NORMAL]);
445 } else {
446 gdk_cairo_set_source_color(cr,&style->dark[GTK_STATE_NORMAL]);
447 }
448 cairo_rectangle(cr, 10+(i*24), 25, 1, 2);
449 cairo_fill(cr);
450
451 if(bypass==INV_PLUGIN_BYPASS) {
452 gdk_cairo_set_source_color(cr,&style->fg[GTK_STATE_INSENSITIVE]);
453 } else {
454 gdk_cairo_set_source_color(cr,&style->fg[GTK_STATE_NORMAL]);
455 }
456 if(i>10) {
457 sprintf(label,"+%i",(6*i)-60);
458 } else {
459 sprintf(label,"%i",(6*i)-60);
460 }
461 cairo_text_extents (cr,label,&extents);
462 cairo_move_to(cr,10+(i*24)-(extents.width/2),35);
463 cairo_show_text(cr,label);
464 }
465 break;
466 }
467
468 if(bypass==INV_PLUGIN_BYPASS) {
469 cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
470 } else {
471 cairo_set_source_rgb(cr, 1, 1, 1);
472 }
473 cairo_select_font_face(cr,"sans-serif",CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_NORMAL);
474 cairo_set_font_size(cr,INV_METER(widget)->label_font_size);
475
476 switch(mode) {
477 case INV_METER_DRAW_MODE_TOZERO:
478 switch(channels)
479 {
480 case 1:
481 cairo_move_to(cr,3,15);
482 cairo_show_text(cr,"M");
483 break;
484 case 2:
485 cairo_move_to(cr,3,10);
486 cairo_show_text(cr,"L");
487 cairo_move_to(cr,3,20);
488 cairo_show_text(cr,"R");
489 break;
490 }
491
492 for ( i = 1; i <= 67; i++)
493 {
494 switch(channels)
495 {
496 case 1:
497 Lon = i <= Lpos ? 1 : 0;
498
499 inv_meter_colour_tozero(widget, bypass, i, Lon, &led);
500 cairo_set_source_rgb(cr, led.R, led.G, led.B);
501 cairo_rectangle(cr, 10+(i*2), 3, 1, 18);
502 cairo_fill(cr);
503 break;
504 case 2:
505 Lon = i <= Lpos ? 1 : 0;
506 Ron = i <= Rpos ? 1 : 0;
507
508 inv_meter_colour_tozero(widget, bypass, i, Lon, &led);
509 cairo_set_source_rgb(cr, led.R, led.G, led.B);
510 cairo_rectangle(cr, 10+(i*2), 3, 1, 8);
511 cairo_fill(cr);
512
513 inv_meter_colour_tozero(widget, bypass, i, Ron, &led);
514 cairo_set_source_rgb(cr, led.R, led.G, led.B);
515 cairo_rectangle(cr, 10+(i*2), 13, 1, 8);
516 cairo_fill(cr);
517 break;
518 }
519 }
520 break;
521
522 case INV_METER_DRAW_MODE_FROMZERO:
523 for ( i = 1; i <= 71; i++)
524 {
525 switch(channels)
526 {
527 case 1:
528 Lon = i > Lpos ? 1 : 0;
529
530 inv_meter_colour_fromzero(widget, bypass, i, Lon, &led);
531 cairo_set_source_rgb(cr, led.R, led.G, led.B);
532 cairo_rectangle(cr, 2+(i*2), 3, 1, 18);
533 cairo_fill(cr);
534 break;
535 case 2:
536 Lon = i > Lpos ? 1 : 0;
537 Ron = i > Rpos ? 1 : 0;
538
539 inv_meter_colour_fromzero(widget, bypass, i, Lon, &led);
540 cairo_set_source_rgb(cr, led.R, led.G, led.B);
541 cairo_rectangle(cr, 2+(i*2), 3, 1, 8);
542 cairo_fill(cr);
543
544 inv_meter_colour_fromzero(widget, bypass, i, Ron, &led);
545 cairo_set_source_rgb(cr, led.R, led.G, led.B);
546 cairo_rectangle(cr, 2+(i*2), 13, 1, 8);
547 cairo_fill(cr);
548 break;
549 }
550 }
551 break;
552 case INV_METER_DRAW_MODE_BIGTOZERO:
553 switch(channels)
554 {
555 case 1:
556 cairo_move_to(cr,3,15);
557 cairo_show_text(cr,"M");
558 break;
559 case 2:
560 cairo_move_to(cr,3,10);
561 cairo_show_text(cr,"L");
562 cairo_move_to(cr,3,20);
563 cairo_show_text(cr,"R");
564 break;
565 }
566
567 for ( i = 1; i <= 144; i++)
568 {
569 switch(channels)
570 {
571 case 1:
572 Lon = i <= Lpos ? 1 : 0;
573
574 inv_meter_colour_bigtozero(widget, bypass, i, Lon, &led);
575 cairo_set_source_rgb(cr, led.R, led.G, led.B);
576 cairo_rectangle(cr, 10+(i*2), 3, 1, 18);
577 cairo_fill(cr);
578 break;
579 case 2:
580 Lon = i <= Lpos ? 1 : 0;
581 Ron = i <= Rpos ? 1 : 0;
582
583 inv_meter_colour_bigtozero(widget, bypass, i, Lon, &led);
584 cairo_set_source_rgb(cr, led.R, led.G, led.B);
585 cairo_rectangle(cr, 10+(i*2), 3, 1, 8);
586 cairo_fill(cr);
587
588 inv_meter_colour_bigtozero(widget, bypass, i, Ron, &led);
589 cairo_set_source_rgb(cr, led.R, led.G, led.B);
590 cairo_rectangle(cr, 10+(i*2), 13, 1, 8);
591 cairo_fill(cr);
592 break;
593 }
594 }
595 break;
596 }
597 INV_METER(widget)->lastLpos = Lpos;
598 INV_METER(widget)->lastRpos = Rpos;
599 break;
600
601 case INV_METER_DRAW_L:
602 switch(mode) {
603 case INV_METER_DRAW_MODE_TOZERO:
604 min = lastLpos < Lpos ? lastLpos : Lpos;
605 max = lastLpos > Lpos ? lastLpos : Lpos;
606 if(min<1) min=1;
607 if(max<1) max=1;
608 if(min>67) min=67;
609 if(max>67) max=67;
610 if(min != max || max == 1 ) {
611 for ( i = min ; i <= max; i++)
612 {
613 Lon = i <= Lpos ? 1 : 0;
614 inv_meter_colour_tozero(widget, bypass, i, Lon, &led);
615 cairo_set_source_rgb(cr, led.R, led.G, led.B);
616 switch(channels)
617 {
618 case 1:
619 cairo_rectangle(cr, 10+(i*2), 3, 1, 18);
620 break;
621 case 2:
622 cairo_rectangle(cr, 10+(i*2), 3, 1, 8);
623 break;
624 }
625 cairo_fill(cr);
626 }
627 }
628 break;
629 case INV_METER_DRAW_MODE_FROMZERO:
630 min = lastLpos < Lpos ? lastLpos : Lpos;
631 max = lastLpos > Lpos ? lastLpos : Lpos;
632 if(min<1) min=1;
633 if(max<1) max=1;
634 if(min>71) min=71;
635 if(max>71) max=71;
636 if(min != max || max == 1 ) {
637 for ( i = min ; i <= max; i++)
638 {
639 Lon = i > Lpos ? 1 : 0;
640 inv_meter_colour_fromzero(widget, bypass, i, Lon, &led);
641 cairo_set_source_rgb(cr, led.R, led.G, led.B);
642 switch(channels)
643 {
644 case 1:
645 cairo_rectangle(cr, 2+(i*2), 3, 1, 18);
646 break;
647 case 2:
648 cairo_rectangle(cr, 2+(i*2), 3, 1, 8);
649 break;
650 }
651 cairo_fill(cr);
652 }
653 }
654 break;
655 case INV_METER_DRAW_MODE_BIGTOZERO:
656 min = lastLpos < Lpos ? lastLpos : Lpos;
657 max = lastLpos > Lpos ? lastLpos : Lpos;
658 if(min<1) min=1;
659 if(max<1) max=1;
660 if(min>144) min=144;
661 if(max>144) max=144;
662 if(min != max || max == 1 ) {
663 for ( i = min ; i <= max; i++)
664 {
665 Lon = i <= Lpos ? 1 : 0;
666 inv_meter_colour_bigtozero(widget, bypass, i, Lon, &led);
667 cairo_set_source_rgb(cr, led.R, led.G, led.B);
668 switch(channels)
669 {
670 case 1:
671 cairo_rectangle(cr, 10+(i*2), 3, 1, 18);
672 break;
673 case 2:
674 cairo_rectangle(cr, 10+(i*2), 3, 1, 8);
675 break;
676 }
677 cairo_fill(cr);
678 }
679 }
680 break;
681 }
682 INV_METER(widget)->lastLpos = Lpos;
683 break;
684
685 case INV_METER_DRAW_R:
686 switch(mode) {
687 case INV_METER_DRAW_MODE_TOZERO:
688 min = lastRpos < Rpos ? lastRpos : Rpos;
689 max = lastRpos > Rpos ? lastRpos : Rpos;
690 if(min<1) min=1;
691 if(max<1) max=1;
692 if(min>67) min=67;
693 if(max>67) max=67;
694 if(min != max || max == 1 ) {
695 for ( i = min ; i <= max; i++)
696 {
697 Ron = i <= Rpos ? 1 : 0;
698 inv_meter_colour_tozero(widget, bypass, i, Ron, &led);
699 cairo_set_source_rgb(cr, led.R, led.G, led.B);
700 cairo_rectangle(cr, 10+(i*2), 13, 1, 8);
701 cairo_fill(cr);
702 }
703 }
704 break;
705 case INV_METER_DRAW_MODE_FROMZERO:
706 min = lastRpos < Rpos ? lastRpos : Rpos;
707 max = lastRpos > Rpos ? lastRpos : Rpos;
708 if(min<1) min=1;
709 if(max<1) max=1;
710 if(min>71) min=71;
711 if(max>71) max=71;
712 if(min != max || max == 1 ) {
713 for ( i = min ; i <= max; i++)
714 {
715 Ron = i > Rpos ? 1 : 0;
716 inv_meter_colour_fromzero(widget, bypass, i, Ron, &led);
717 cairo_set_source_rgb(cr, led.R, led.G, led.B);
718 cairo_rectangle(cr, 2+(i*2), 13, 1, 8);
719 cairo_fill(cr);
720 }
721 }
722 break;
723 case INV_METER_DRAW_MODE_BIGTOZERO:
724 min = lastRpos < Rpos ? lastRpos : Rpos;
725 max = lastRpos > Rpos ? lastRpos : Rpos;
726 if(min<1) min=1;
727 if(max<1) max=1;
728 if(min>144) min=144;
729 if(max>144) max=144;
730 if(min != max || max == 1 ) {
731 for ( i = min ; i <= max; i++)
732 {
733 Ron = i <= Rpos ? 1 : 0;
734 inv_meter_colour_bigtozero(widget, bypass, i, Ron, &led);
735 cairo_set_source_rgb(cr, led.R, led.G, led.B);
736 cairo_rectangle(cr, 10+(i*2), 13, 1, 8);
737 cairo_fill(cr);
738 }
739 }
740 break;
741 }
742 INV_METER(widget)->lastRpos = Rpos;
743 break;
744
745 }
746 cairo_destroy(cr);
747 }
748
749
750 static void
inv_meter_destroy(GtkObject * object)751 inv_meter_destroy(GtkObject *object)
752 {
753 InvMeter *meter;
754 InvMeterClass *klass;
755
756 g_return_if_fail(object != NULL);
757 g_return_if_fail(INV_IS_METER(object));
758
759 meter = INV_METER(object);
760
761 klass = gtk_type_class(gtk_widget_get_type());
762
763 if (GTK_OBJECT_CLASS(klass)->destroy) {
764 (* GTK_OBJECT_CLASS(klass)->destroy) (object);
765 }
766 }
767
768 static void
inv_meter_colour_tozero(GtkWidget * widget,gint bypass,gint pos,gint on,struct colour * led)769 inv_meter_colour_tozero(GtkWidget *widget, gint bypass, gint pos, gint on, struct colour *led)
770 {
771 float r1,r2;
772 struct colour mOff60 = INV_METER(widget)->mOff60;
773 struct colour mOn60 = INV_METER(widget)->mOn60;
774 struct colour mOff12 = INV_METER(widget)->mOff12;
775 struct colour mOn12 = INV_METER(widget)->mOn12;
776 struct colour mOff6 = INV_METER(widget)->mOff6;
777 struct colour mOn6 = INV_METER(widget)->mOn6;
778 struct colour mOff0 = INV_METER(widget)->mOff0;
779 struct colour mOn0 = INV_METER(widget)->mOn0;
780 struct colour overOff = INV_METER(widget)->overOff;
781 struct colour overOn = INV_METER(widget)->overOn;
782 /*
783 66 = +6dB
784 60 = 0dB
785 51 = -9dB
786 42 = -18dB
787 */
788 if(pos < 42)
789 {
790 r1=(42.0-(float)pos)/42.0;
791 r2=(float)pos/42.0;
792 led->R=(r1 * mOff60.R + (r2 * mOff12.R)) + (on * ((r1 * mOn60.R) + (r2 * mOn12.R))) ;
793 led->G=(r1 * mOff60.G + (r2 * mOff12.G)) + (on * ((r1 * mOn60.G) + (r2 * mOn12.G))) ;
794 led->B=(r1 * mOff60.B + (r2 * mOff12.B)) + (on * ((r1 * mOn60.B) + (r2 * mOn12.B))) ;
795 }
796
797 else if (pos < 51)
798 {
799 r1=(51.0-(float)pos)/9.0;
800 r2=((float)pos-42.0)/9.0;
801 led->R=(r1 * mOff12.R + (r2 * mOff6.R)) + (on * ((r1 * mOn12.R) + (r2 * mOn6.R))) ;
802 led->G=(r1 * mOff12.G + (r2 * mOff6.G)) + (on * ((r1 * mOn12.G) + (r2 * mOn6.G))) ;
803 led->B=(r1 * mOff12.B + (r2 * mOff6.B)) + (on * ((r1 * mOn12.B) + (r2 * mOn6.B))) ;
804 }
805
806 else if (pos < 60)
807 {
808 r1=(60.0-(float)pos)/9.0;
809 r2=((float)pos-51.0)/9.0;
810 led->R=(r1 * mOff6.R + (r2 * mOff0.R)) + (on * ((r1 * mOn6.R) + (r2 * mOn0.R))) ;
811 led->G=(r1 * mOff6.G + (r2 * mOff0.G)) + (on * ((r1 * mOn6.G) + (r2 * mOn0.G))) ;
812 led->B=(r1 * mOff6.B + (r2 * mOff0.B)) + (on * ((r1 * mOn6.B) + (r2 * mOn0.B))) ;
813 }
814 else
815 {
816 led->R=overOff.R + (on * overOn.R) ;
817 led->G=overOff.G + (on * overOn.G) ;
818 led->B=overOff.B + (on * overOn.B) ;
819 }
820
821 if(bypass==INV_PLUGIN_BYPASS) {
822 led->R=(led->R+led->G+led->B)/3;
823 led->G=led->R;
824 led->B=led->R;
825 }
826 }
827
828 static void
inv_meter_colour_fromzero(GtkWidget * widget,gint bypass,gint pos,gint on,struct colour * led)829 inv_meter_colour_fromzero(GtkWidget *widget, gint bypass, gint pos, gint on, struct colour *led)
830 {
831 float r1,r2;
832 struct colour mOff60 = INV_METER(widget)->mOff60;
833 struct colour mOn60 = INV_METER(widget)->mOn60;
834 struct colour mOff12 = INV_METER(widget)->mOff12;
835 struct colour mOn12 = INV_METER(widget)->mOn12;
836 struct colour mOff6 = INV_METER(widget)->mOff6;
837 struct colour mOn6 = INV_METER(widget)->mOn6;
838 struct colour mOff0 = INV_METER(widget)->mOff0;
839 struct colour mOn0 = INV_METER(widget)->mOn0;
840 struct colour overOff = INV_METER(widget)->overOff;
841 struct colour overOn = INV_METER(widget)->overOn;
842 /*
843 72 = 0dB
844 60 = -6dB
845 48 = -12dB
846 24 = -18dB
847 */
848 if(pos < 24)
849 {
850 r1=(24.0-(float)pos)/24.0;
851 r2=(float)pos/24.0;
852 led->R=(r1 * overOff.R + (r2 * mOff0.R)) + (on * ((r1 * overOn.R) + (r2 * mOn0.R))) ;
853 led->G=(r1 * overOff.G + (r2 * mOff0.G)) + (on * ((r1 * overOn.G) + (r2 * mOn0.G))) ;
854 led->B=(r1 * overOff.B + (r2 * mOff0.B)) + (on * ((r1 * overOn.B) + (r2 * mOn0.B))) ;
855 }
856
857 else if (pos < 48)
858 {
859 r1=(48.0-(float)pos)/24.0;
860 r2=((float)pos-24.0)/24.0;
861 led->R=(r1 * mOff0.R + (r2 * mOff6.R)) + (on * ((r1 * mOn0.R) + (r2 * mOn6.R))) ;
862 led->G=(r1 * mOff0.G + (r2 * mOff6.G)) + (on * ((r1 * mOn0.G) + (r2 * mOn6.G))) ;
863 led->B=(r1 * mOff0.B + (r2 * mOff6.B)) + (on * ((r1 * mOn0.B) + (r2 * mOn6.B))) ;
864 }
865
866 else if (pos < 60)
867 {
868 r1=(60.0-(float)pos)/12.0;
869 r2=((float)pos-48.0)/12.0;
870 led->R=(r1 * mOff6.R + (r2 * mOff12.R)) + (on * ((r1 * mOn6.R) + (r2 * mOn12.R))) ;
871 led->G=(r1 * mOff6.G + (r2 * mOff12.G)) + (on * ((r1 * mOn6.G) + (r2 * mOn12.G))) ;
872 led->B=(r1 * mOff6.B + (r2 * mOff12.B)) + (on * ((r1 * mOn6.B) + (r2 * mOn12.B))) ;
873 }
874 else if (pos < 72)
875 {
876 r1=(72.0-(float)pos)/12.0;
877 r2=((float)pos-60.0)/12.0;
878 led->R=(r1 * mOff12.R + (r2 * mOff60.R)) + (on * ((r1 * mOn12.R) + (r2 * mOn60.R))) ;
879 led->G=(r1 * mOff12.G + (r2 * mOff60.G)) + (on * ((r1 * mOn12.G) + (r2 * mOn60.G))) ;
880 led->B=(r1 * mOff12.B + (r2 * mOff60.B)) + (on * ((r1 * mOn12.B) + (r2 * mOn60.B))) ;
881 }
882 else
883 {
884 led->R=mOff60.R + (on * mOn60.R) ;
885 led->G=mOff60.G + (on * mOn60.G) ;
886 led->B=mOff60.B + (on * mOn60.B) ;
887 }
888 if(bypass==INV_PLUGIN_BYPASS) {
889 led->R=(led->R+led->G+led->B)/3;
890 led->G=led->R;
891 led->B=led->R;
892 }
893 }
894
895 static void
inv_meter_colour_bigtozero(GtkWidget * widget,gint bypass,gint pos,gint on,struct colour * led)896 inv_meter_colour_bigtozero(GtkWidget *widget, gint bypass, gint pos, gint on, struct colour *led)
897 {
898 float r1,r2;
899 struct colour mOff60 = INV_METER(widget)->mOff60;
900 struct colour mOn60 = INV_METER(widget)->mOn60;
901 struct colour mOff12 = INV_METER(widget)->mOff12;
902 struct colour mOn12 = INV_METER(widget)->mOn12;
903 struct colour mOff6 = INV_METER(widget)->mOff6;
904 struct colour mOn6 = INV_METER(widget)->mOn6;
905 struct colour mOff0 = INV_METER(widget)->mOff0;
906 struct colour mOn0 = INV_METER(widget)->mOn0;
907 struct colour overOff = INV_METER(widget)->overOff;
908 struct colour overOn = INV_METER(widget)->overOn;
909 /*
910 144 = +12dB
911 120 = 0dB
912 102 = -9dB
913 84 = -18dB
914 */
915 if(pos < 84)
916 {
917 r1=(84.0-(float)pos)/84.0;
918 r2=(float)pos/84.0;
919 led->R=(r1 * mOff60.R + (r2 * mOff12.R)) + (on * ((r1 * mOn60.R) + (r2 * mOn12.R))) ;
920 led->G=(r1 * mOff60.G + (r2 * mOff12.G)) + (on * ((r1 * mOn60.G) + (r2 * mOn12.G))) ;
921 led->B=(r1 * mOff60.B + (r2 * mOff12.B)) + (on * ((r1 * mOn60.B) + (r2 * mOn12.B))) ;
922 }
923
924 else if (pos < 102)
925 {
926 r1=(102.0-(float)pos)/18.0;
927 r2=((float)pos-84.0)/18.0;
928 led->R=(r1 * mOff12.R + (r2 * mOff6.R)) + (on * ((r1 * mOn12.R) + (r2 * mOn6.R))) ;
929 led->G=(r1 * mOff12.G + (r2 * mOff6.G)) + (on * ((r1 * mOn12.G) + (r2 * mOn6.G))) ;
930 led->B=(r1 * mOff12.B + (r2 * mOff6.B)) + (on * ((r1 * mOn12.B) + (r2 * mOn6.B))) ;
931 }
932
933 else if (pos < 120)
934 {
935 r1=(120.0-(float)pos)/18.0;
936 r2=((float)pos-102.0)/18.0;
937 led->R=(r1 * mOff6.R + (r2 * mOff0.R)) + (on * ((r1 * mOn6.R) + (r2 * mOn0.R))) ;
938 led->G=(r1 * mOff6.G + (r2 * mOff0.G)) + (on * ((r1 * mOn6.G) + (r2 * mOn0.G))) ;
939 led->B=(r1 * mOff6.B + (r2 * mOff0.B)) + (on * ((r1 * mOn6.B) + (r2 * mOn0.B))) ;
940 }
941 else
942 {
943 led->R=overOff.R + (on * overOn.R) ;
944 led->G=overOff.G + (on * overOn.G) ;
945 led->B=overOff.B + (on * overOn.B) ;
946 }
947
948 if(bypass==INV_PLUGIN_BYPASS) {
949 led->R=(led->R+led->G+led->B)/3;
950 led->G=led->R;
951 led->B=led->R;
952 }
953 }
954
955