+ Line graph: added dot support
[calfwidgets.git] / src / vumeter.cpp
blob3808cd46b6fe3a50d4aee2378ddbb2bbb1e0fced
1 /* Calf DSP Library
2 * A LED-line-style volume meter widget
3 * Copyright (C) 2007-2008 Krzysztof Foltman
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 #include <calfwidgets/vumeter.h>
21 #include <cairo/cairo.h>
22 #include <math.h>
23 #include <stdint.h>
24 #include <malloc.h>
26 ///////////////////////////////////////// vu meter ///////////////////////////////////////////////
28 static gboolean
29 calf_vu_meter_expose (GtkWidget *widget, GdkEventExpose *event)
31 g_assert(CALF_IS_VU_METER(widget));
33 CalfVUMeter *vu = CALF_VU_METER(widget);
34 int ox = widget->allocation.x + 1, oy = widget->allocation.y + 1;
35 int sx = widget->allocation.width - 2, sy = widget->allocation.height - 2;
37 cairo_t *c = gdk_cairo_create(GDK_DRAWABLE(widget->window));
39 GdkColor sc = { 0, 0, 0, 0 };
40 gdk_cairo_set_source_color(c, &sc);
41 cairo_rectangle(c, ox, oy, sx, sy);
42 cairo_fill(c);
43 cairo_set_line_width(c, 1);
45 CalfVUMeterMode mode = vu->mode;
47 for (int x = ox; x <= ox + sx; x += 3)
49 float ts = (x - ox) * 1.0 / sx;
50 float r = 0.f, g = 0.f, b = 0.f;
51 switch(mode)
53 case CALF_VU_METER_MODE_STANDARD:
54 default:
55 if (ts < 0.75)
56 r = ts / 0.75, g = 1, b = 0;
57 else
58 r = 1, g = 1 - (ts - 0.75) / 0.25, b = 0;
59 if (vu->value < ts || vu->value <= 0)
60 r *= 0.5, g *= 0.5, b *= 0.5;
61 break;
62 case CALF_VU_METER_MODE_MONOCHROME_REVERSE:
63 r = 1, g = 1, b = 0;
64 if (!(vu->value < ts || vu->value <= 0))
65 r *= 0.5, g *= 0.5, b *= 0.5;
66 break;
67 case CALF_VU_METER_MODE_MONOCHROME:
68 r = 1, g = 1, b = 0;
69 if (vu->value < ts || vu->value <= 0)
70 r *= 0.5, g *= 0.5, b *= 0.5;
71 break;
73 GdkColor sc2 = { 0, (guint16)(65535 * r), (guint16)(65535 * g), (guint16)(65535 * b) };
74 gdk_cairo_set_source_color(c, &sc2);
75 cairo_move_to(c, x, oy);
76 cairo_line_to(c, x, oy + sy + 1);
77 cairo_move_to(c, x, oy + sy);
78 cairo_line_to(c, x, oy );
79 cairo_stroke(c);
82 cairo_destroy(c);
84 gtk_paint_shadow(widget->style, widget->window, GTK_STATE_NORMAL, GTK_SHADOW_IN, NULL, widget, NULL, ox - 1, oy - 1, sx + 2, sy + 2);
85 // printf("exposed %p %d+%d\n", widget->window, widget->allocation.x, widget->allocation.y);
87 return TRUE;
90 static void
91 calf_vu_meter_size_request (GtkWidget *widget,
92 GtkRequisition *requisition)
94 g_assert(CALF_IS_VU_METER(widget));
96 requisition->width = 50;
97 requisition->height = 14;
100 static void
101 calf_vu_meter_size_allocate (GtkWidget *widget,
102 GtkAllocation *allocation)
104 g_assert(CALF_IS_VU_METER(widget));
106 widget->allocation = *allocation;
109 static void
110 calf_vu_meter_class_init (CalfVUMeterClass *klass)
112 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
113 widget_class->expose_event = calf_vu_meter_expose;
114 widget_class->size_request = calf_vu_meter_size_request;
115 widget_class->size_allocate = calf_vu_meter_size_allocate;
118 static void
119 calf_vu_meter_init (CalfVUMeter *self)
121 GtkWidget *widget = GTK_WIDGET(self);
122 GTK_WIDGET_SET_FLAGS (widget, GTK_NO_WINDOW);
123 widget->requisition.width = 40;
124 widget->requisition.height = 40;
125 self->value = 0;
128 GtkWidget *
129 calf_vu_meter_new()
131 return GTK_WIDGET( g_object_new (CALF_TYPE_VU_METER, NULL ));
134 GType
135 calf_vu_meter_get_type (void)
137 static GType type = 0;
138 if (!type) {
139 static const GTypeInfo type_info = {
140 sizeof(CalfVUMeterClass),
141 NULL, /* base_init */
142 NULL, /* base_finalize */
143 (GClassInitFunc)calf_vu_meter_class_init,
144 NULL, /* class_finalize */
145 NULL, /* class_data */
146 sizeof(CalfVUMeter),
147 0, /* n_preallocs */
148 (GInstanceInitFunc)calf_vu_meter_init
151 GTypeInfo *type_info_copy = new GTypeInfo(type_info);
153 for (int i = 0; ; i++) {
154 char *name = g_strdup_printf("CalfVUMeter%u%d", ((unsigned int)(intptr_t)calf_vu_meter_class_init) >> 16, i);
155 if (g_type_from_name(name)) {
156 free(name);
157 continue;
159 type = g_type_register_static( GTK_TYPE_WIDGET,
160 name,
161 type_info_copy,
162 (GTypeFlags)0);
163 free(name);
164 break;
167 return type;
170 extern void calf_vu_meter_set_value(CalfVUMeter *meter, float value)
172 if (value != meter->value)
174 meter->value = value;
175 gtk_widget_queue_draw(GTK_WIDGET(meter));
179 extern float calf_vu_meter_get_value(CalfVUMeter *meter)
181 return meter->value;
184 extern void calf_vu_meter_set_mode(CalfVUMeter *meter, CalfVUMeterMode mode)
186 if (mode != meter->mode)
188 meter->mode = mode;
189 gtk_widget_queue_draw(GTK_WIDGET(meter));
193 extern CalfVUMeterMode calf_vu_meter_get_mode(CalfVUMeter *meter)
195 return meter->mode;