1 /*
2 
3     This widget provides phase 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-phase.h"
27 
28 
29 static void 	inv_phase_meter_class_init(InvPhaseMeterClass *klass);
30 static void 	inv_phase_meter_init(InvPhaseMeter *meter);
31 static void 	inv_phase_meter_size_request(GtkWidget *widget, GtkRequisition *requisition);
32 static void 	inv_phase_meter_size_allocate(GtkWidget *widget, GtkAllocation *allocation);
33 static void 	inv_phase_meter_realize(GtkWidget *widget);
34 static gboolean inv_phase_meter_expose(GtkWidget *widget,GdkEventExpose *event);
35 static void 	inv_phase_meter_paint(GtkWidget *widget, gint mode);
36 static void	inv_phase_meter_destroy(GtkObject *object);
37 static void	inv_phase_meter_colour(GtkWidget *widget, gint bypass, gint pos, gint on, struct colour *led);
38 
39 
40 GtkType
inv_phase_meter_get_type(void)41 inv_phase_meter_get_type(void)
42 {
43 	static GType inv_phase_meter_type = 0;
44 	char *name;
45 	int i;
46 
47 
48 	if (!inv_phase_meter_type)
49 	{
50 		static const GTypeInfo type_info = {
51 			sizeof(InvPhaseMeterClass),
52 			NULL, /* base_init */
53 			NULL, /* base_finalize */
54 			(GClassInitFunc)inv_phase_meter_class_init,
55 			NULL, /* class_finalize */
56 			NULL, /* class_data */
57 			sizeof(InvPhaseMeter),
58 			0,    /* n_preallocs */
59 			(GInstanceInitFunc)inv_phase_meter_init
60 		};
61 		for (i = 0; ; i++) {
62 			name = g_strdup_printf("InvPhaseMeter-%p-%d",inv_phase_meter_class_init, i);
63 			if (g_type_from_name(name)) {
64 				free(name);
65 				continue;
66 			}
67 			inv_phase_meter_type = g_type_register_static(GTK_TYPE_WIDGET,name,&type_info,(GTypeFlags)0);
68 			free(name);
69 			break;
70 		}
71 	}
72 	return inv_phase_meter_type;
73 }
74 
75 void
inv_phase_meter_set_bypass(InvPhaseMeter * meter,gint num)76 inv_phase_meter_set_bypass(InvPhaseMeter *meter, gint num)
77 {
78 	if(meter->bypass != num) {
79 		meter->bypass = num;
80 		meter->phase=0;
81 	}
82 }
83 
84 void
inv_phase_meter_set_phase(InvPhaseMeter * meter,float num)85 inv_phase_meter_set_phase(InvPhaseMeter *meter, float num)
86 {
87 	meter->phase = num;
88 	if(GTK_WIDGET_REALIZED(meter))
89 		inv_phase_meter_paint(GTK_WIDGET(meter),INV_PHASE_METER_DRAW_DATA);
90 }
91 
inv_phase_meter_new()92 GtkWidget * inv_phase_meter_new()
93 {
94 	return GTK_WIDGET(gtk_type_new(inv_phase_meter_get_type()));
95 }
96 
97 
98 static void
inv_phase_meter_class_init(InvPhaseMeterClass * klass)99 inv_phase_meter_class_init(InvPhaseMeterClass *klass)
100 {
101 	GtkWidgetClass *widget_class;
102 	GtkObjectClass *object_class;
103 
104 
105 	widget_class = (GtkWidgetClass *) klass;
106 	object_class = (GtkObjectClass *) klass;
107 
108 	widget_class->realize = inv_phase_meter_realize;
109 	widget_class->size_request = inv_phase_meter_size_request;
110 	widget_class->size_allocate = inv_phase_meter_size_allocate;
111 	widget_class->expose_event = inv_phase_meter_expose;
112 
113 	object_class->destroy = inv_phase_meter_destroy;
114 }
115 
116 
117 static void
inv_phase_meter_init(InvPhaseMeter * meter)118 inv_phase_meter_init(InvPhaseMeter *meter)
119 {
120 	meter->bypass = INV_PLUGIN_ACTIVE;
121 	meter->phase = 0;
122 
123 	meter->mOff0.R =0.1;	meter->mOff0.G =0.1;	meter->mOff0.B =0.4;
124 	meter->mOn0.R  =-0.1;	meter->mOn0.G  =-0.1;	meter->mOn0.B  =0.6;
125 
126 	meter->mOff30.R =0.2; 	meter->mOff30.G =0.3;	meter->mOff30.B =0.4;
127 	meter->mOn30.R  =-0.1;	meter->mOn30.G  =0.3;	meter->mOn30.B  =0.6;
128 
129 	meter->mOff45.R =0.2; 	meter->mOff45.G =0.4;	meter->mOff45.B =0.2;
130 	meter->mOn45.R  =0.1;	meter->mOn45.G  =0.6;	meter->mOn45.B  =-0.1;
131 
132 	meter->mOff60.R  =0.5;	meter->mOff60.G  =0.5;	meter->mOff60.B  =0.0;
133 	meter->mOn60.R   =0.5;	meter->mOn60.G   =0.5;	meter->mOn60.B   =0.0;
134 
135 	meter->mOff90.R=0.4;	meter->mOff90.G=0.2;	meter->mOff90.B=0.0;
136 	meter->mOn90.R =0.6;	meter->mOn90.G =0.0;	meter->mOn90.B =0.0;
137 
138 	meter->font_size=0;
139 
140 	gtk_widget_set_tooltip_markup(GTK_WIDGET(meter),"<span size=\"8000\">Phase Meter.</span>");
141 }
142 
143 
144 static void
inv_phase_meter_size_request(GtkWidget * widget,GtkRequisition * requisition)145 inv_phase_meter_size_request(GtkWidget *widget,
146     GtkRequisition *requisition)
147 {
148 	g_return_if_fail(widget != NULL);
149 	g_return_if_fail(INV_IS_PHASE_METER(widget));
150 	g_return_if_fail(requisition != NULL);
151 
152 	requisition->width = 388;
153 	requisition->height = 36;
154 }
155 
156 
157 static void
inv_phase_meter_size_allocate(GtkWidget * widget,GtkAllocation * allocation)158 inv_phase_meter_size_allocate(GtkWidget *widget,
159     GtkAllocation *allocation)
160 {
161 	g_return_if_fail(widget != NULL);
162 	g_return_if_fail(INV_IS_PHASE_METER(widget));
163 	g_return_if_fail(allocation != NULL);
164 
165 	widget->allocation = *allocation;
166 
167 	if (GTK_WIDGET_REALIZED(widget)) {
168 		gdk_window_move_resize(
169 		   widget->window,
170 		   allocation->x, allocation->y,
171 		   allocation->width, allocation->height
172 		);
173 	}
174 }
175 
176 
177 static void
inv_phase_meter_realize(GtkWidget * widget)178 inv_phase_meter_realize(GtkWidget *widget)
179 {
180 	GdkWindowAttr attributes;
181 	guint attributes_mask;
182 
183 	g_return_if_fail(widget != NULL);
184 	g_return_if_fail(INV_IS_PHASE_METER(widget));
185 
186 	GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
187 
188 	attributes.window_type = GDK_WINDOW_CHILD;
189 	attributes.x = widget->allocation.x;
190 	attributes.y = widget->allocation.y;
191 	attributes.width = 388;
192 	attributes.height = 36;
193 
194 	attributes.wclass = GDK_INPUT_OUTPUT;
195 	attributes.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK;
196 
197 	attributes_mask = GDK_WA_X | GDK_WA_Y;
198 
199 	widget->window = gdk_window_new(
200 	  gtk_widget_get_parent_window (widget),
201 	  & attributes, attributes_mask
202 	);
203 
204 	gdk_window_set_user_data(widget->window, widget);
205 
206 	widget->style = gtk_style_attach(widget->style, widget->window);
207 	gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL);
208 }
209 
210 
211 static gboolean
inv_phase_meter_expose(GtkWidget * widget,GdkEventExpose * event)212 inv_phase_meter_expose(GtkWidget *widget, GdkEventExpose *event)
213 {
214 	g_return_val_if_fail(widget != NULL, FALSE);
215 	g_return_val_if_fail(INV_IS_PHASE_METER(widget), FALSE);
216 	g_return_val_if_fail(event != NULL, FALSE);
217 
218 	inv_phase_meter_paint(widget,INV_PHASE_METER_DRAW_ALL);
219 
220 	return FALSE;
221 }
222 
223 
224 static void
inv_phase_meter_paint(GtkWidget * widget,gint mode)225 inv_phase_meter_paint(GtkWidget *widget, gint mode)
226 {
227 	gint 			phase;
228 	gint 			bypass;
229 
230 	gint 			i;
231 	cairo_t 		*cr;
232 	float 			Pon;
233 	GtkStyle		*style;
234 
235 	char 			label[10];
236 	struct colour		led;
237 	cairo_text_extents_t 	extents;
238 
239 	style   = gtk_widget_get_style(widget);
240 	bypass = INV_PHASE_METER(widget)->bypass;
241 	phase  = (gint)((INV_PHASE_METER(widget)->phase*57.295779506)+0.2);
242 
243 	cr = gdk_cairo_create(widget->window);
244 
245 	if(INV_PHASE_METER(widget)->font_size==0) {
246 		INV_PHASE_METER(widget)->font_size=inv_choose_font_size(cr,"sans-serif",CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_NORMAL,99.0,6.1,"0");
247 	}
248 
249 	if(mode==INV_PHASE_METER_DRAW_ALL) {
250 		cairo_set_source_rgb(cr, 0, 0, 0);
251 		cairo_paint(cr);
252 
253 		cairo_new_path(cr);
254 
255 		cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
256 		cairo_set_antialias (cr,CAIRO_ANTIALIAS_NONE);
257 		cairo_set_line_width(cr,1);
258 
259 		gdk_cairo_set_source_color(cr,&style->dark[GTK_STATE_NORMAL]);
260 		cairo_move_to(cr, 0, 35);
261 		cairo_line_to(cr, 0, 0);
262 		cairo_line_to(cr, 387, 0);
263 		cairo_stroke(cr);
264 
265 		gdk_cairo_set_source_color(cr,&style->light[GTK_STATE_NORMAL]);
266 		cairo_move_to(cr, 0, 35);
267 		cairo_line_to(cr, 387, 35);
268 		cairo_line_to(cr, 387, 0);
269 		cairo_stroke(cr);
270 
271 		cairo_set_antialias (cr,CAIRO_ANTIALIAS_DEFAULT);
272 		cairo_new_path(cr);
273 
274 		if(bypass==INV_PLUGIN_BYPASS) {
275 			cairo_set_source_rgb(cr, 0.3, 0.3, 0.3);
276 		} else {
277 			cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
278 		}
279 
280 		cairo_rectangle(cr, 14, 21, 1, 2);
281 		cairo_fill(cr);
282 
283 		cairo_rectangle(cr, 104, 21, 1, 2);
284 		cairo_fill(cr);
285 
286 		cairo_rectangle(cr, 194, 21, 1, 2);
287 		cairo_fill(cr);
288 
289 		cairo_rectangle(cr, 284, 21, 1, 2);
290 		cairo_fill(cr);
291 
292 		cairo_rectangle(cr, 374, 21, 1, 2);
293 		cairo_fill(cr);
294 
295 
296 		if(bypass==INV_PLUGIN_BYPASS) {
297 			cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
298 		} else {
299 			cairo_set_source_rgb(cr, 1, 1, 1);
300 		}
301 
302 		cairo_select_font_face(cr,"sans-serif",CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_NORMAL);
303 		cairo_set_font_size(cr,INV_PHASE_METER(widget)->font_size);
304 
305 		strcpy(label,"-90");
306 		cairo_text_extents (cr,label,&extents);
307 		cairo_move_to(cr,13-(extents.width/2),31);
308 		cairo_show_text(cr,label);
309 
310 		strcpy(label,"-45");
311 		cairo_text_extents (cr,label,&extents);
312 		cairo_move_to(cr,103-(extents.width/2),31);
313 		cairo_show_text(cr,label);
314 
315 		strcpy(label,"0");
316 		cairo_text_extents (cr,label,&extents);
317 		cairo_move_to(cr,194-(extents.width/2),31);
318 
319 		cairo_show_text(cr,label);
320 
321 		strcpy(label,"45");
322 		cairo_text_extents (cr,label,&extents);
323 		cairo_move_to(cr,284-(extents.width/2),31);
324 		cairo_show_text(cr,label);
325 
326 		strcpy(label,"90");
327 		cairo_text_extents (cr,label,&extents);
328 		cairo_move_to(cr,374-(extents.width/2),31);
329 		cairo_show_text(cr,label);
330 
331 
332 	}
333 
334 
335 	inv_phase_meter_colour(widget, bypass, 0, 1, &led);
336 	cairo_set_source_rgb(cr, led.R, led.G, led.B);
337 	cairo_rectangle(cr, 194, 5, 1, 14);
338 
339 	for ( i = 1; i <= 90; i++)
340 	{
341 		Pon = i <= phase ? 1 : 0;
342 
343 		inv_phase_meter_colour(widget, bypass, i, Pon, &led);
344 		cairo_set_source_rgb(cr, led.R, led.G, led.B);
345 		cairo_rectangle(cr, 194+(i*2), 5, 1, 14);
346 		cairo_fill(cr);
347 		cairo_rectangle(cr, 194-(i*2), 5, 1, 14);
348 		cairo_fill(cr);
349 	}
350   	cairo_destroy(cr);
351 }
352 
353 
354 static void
inv_phase_meter_destroy(GtkObject * object)355 inv_phase_meter_destroy(GtkObject *object)
356 {
357 	InvPhaseMeter *meter;
358 	InvPhaseMeterClass *klass;
359 
360 	g_return_if_fail(object != NULL);
361 	g_return_if_fail(INV_IS_PHASE_METER(object));
362 
363 	meter = INV_PHASE_METER(object);
364 
365 	klass = gtk_type_class(gtk_widget_get_type());
366 
367 	if (GTK_OBJECT_CLASS(klass)->destroy) {
368 		(* GTK_OBJECT_CLASS(klass)->destroy) (object);
369 	}
370 }
371 
372 static void
inv_phase_meter_colour(GtkWidget * widget,gint bypass,gint pos,gint on,struct colour * led)373 inv_phase_meter_colour(GtkWidget *widget, gint bypass, gint pos, gint on, struct colour *led)
374 {
375 	float r1,r2;
376 
377 	struct colour  mOff0  = INV_PHASE_METER(widget)->mOff0;
378 	struct colour  mOn0   = INV_PHASE_METER(widget)->mOn0;
379 	struct colour  mOff30 = INV_PHASE_METER(widget)->mOff30;
380 	struct colour  mOn30  = INV_PHASE_METER(widget)->mOn30;
381 	struct colour  mOff45 = INV_PHASE_METER(widget)->mOff45;
382 	struct colour  mOn45  = INV_PHASE_METER(widget)->mOn45;
383 	struct colour  mOff60 = INV_PHASE_METER(widget)->mOff60;
384 	struct colour  mOn60  = INV_PHASE_METER(widget)->mOn60;
385 	struct colour  mOff90 = INV_PHASE_METER(widget)->mOff90;
386 	struct colour  mOn90  = INV_PHASE_METER(widget)->mOn90;
387 
388 
389 	if(pos < 30)
390 	{
391 		r1=(30.0-(float)pos)/30.0;
392 		r2=(float)pos/30.0;
393 		led->R=(r1 * mOff0.R + (r2 * mOff30.R))  + (on * ((r1 * mOn0.R) + (r2 * mOn30.R))) ;
394 		led->G=(r1 * mOff0.G + (r2 * mOff30.G))  + (on * ((r1 * mOn0.G) + (r2 * mOn30.G))) ;
395 		led->B=(r1 * mOff0.B + (r2 * mOff30.B))  + (on * ((r1 * mOn0.B) + (r2 * mOn30.B))) ;
396 	}
397 
398 	else if (pos < 45)
399 	{
400 		r1=(45.0-(float)pos)/15.0;
401 		r2=((float)pos-30.0)/15.0;
402 		led->R=(r1 * mOff30.R + (r2 * mOff45.R))  + (on * ((r1 * mOn30.R) + (r2 * mOn45.R))) ;
403 		led->G=(r1 * mOff30.G + (r2 * mOff45.G))  + (on * ((r1 * mOn30.G) + (r2 * mOn45.G))) ;
404 		led->B=(r1 * mOff30.B + (r2 * mOff45.B))  + (on * ((r1 * mOn30.B) + (r2 * mOn45.B))) ;
405 	}
406 
407 	else if (pos < 60)
408 	{
409 		r1=(60.0-(float)pos)/15.0;
410 		r2=((float)pos-45.0)/15.0;
411 		led->R=(r1 * mOff45.R + (r2 * mOff60.R))  + (on * ((r1 * mOn45.R) + (r2 * mOn60.R))) ;
412 		led->G=(r1 * mOff45.G + (r2 * mOff60.G))  + (on * ((r1 * mOn45.G) + (r2 * mOn60.G))) ;
413 		led->B=(r1 * mOff45.B + (r2 * mOff60.B))  + (on * ((r1 * mOn45.B) + (r2 * mOn60.B))) ;
414 	}
415 	else
416 	{
417 		r1=(90.0-(float)pos)/30.0;
418 		r2=((float)pos-60.0)/30.0;
419 		led->R=(r1 * mOff60.R + (r2 * mOff90.R))  + (on * ((r1 * mOn60.R) + (r2 * mOn90.R))) ;
420 		led->G=(r1 * mOff60.G + (r2 * mOff90.G))  + (on * ((r1 * mOn60.G) + (r2 * mOn90.G))) ;
421 		led->B=(r1 * mOff60.B + (r2 * mOff90.B))  + (on * ((r1 * mOn60.B) + (r2 * mOn90.B))) ;
422 	}
423 
424 	if(bypass==INV_PLUGIN_BYPASS) {
425 		led->R=(led->R+led->G+led->B)/3;
426 		led->G=led->R;
427 		led->B=led->R;
428 	}
429 }
430 
431