2 * Dictix / DixSpectrograph - dix-spectrograph.c
4 * Copyright (C) Martin Blanchard 2011 <tinram@gmx.fr>
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.
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.
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 Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
29 #include <glib/gi18n.h>
32 #include "dix-spectrograph.h"
40 struct _DixSpectrographPrivate
49 #define DIX_SPECTROGRAPH_GET_PRIVATE(obj) \
50 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), DIX_TYPE_SPECTROGRAPH, DixSpectrographPrivate))
52 #define DIX_SPECTROGRAPH_BANDS 8
53 #define DIX_SPECTROGRAPH_THRESHOLD -70.0f
54 #define DIX_SPECTROGRAPH_HEIGHT 35
55 #define DIX_SPECTROGRAPH_HEIGHT_D 35.0
56 #define DIX_SPECTROGRAPH_LED_WIDTH 8
57 #define DIX_SPECTROGRAPH_LED_WIDTH_D 8.0
58 #define DIX_SPECTROGRAPH_LED_HEIGHT 5
59 #define DIX_SPECTROGRAPH_LED_HEIGHT_D 5.0
60 #define DIX_SPECTROGRAPH_LED_PADDING 1
61 #define DIX_SPECTROGRAPH_LED_PADDING_D 1.0
63 G_DEFINE_TYPE (DixSpectrograph
, dix_spectrograph
, GTK_TYPE_WIDGET
)
65 static guint
dix_spectrograph_log_scale (gfloat db
);
68 dix_spectrograph_set_property (GObject
* object
, guint prop_id
, const GValue
* value
, GParamSpec
* pspec
)
70 DixSpectrograph
* spec
= (DixSpectrograph
*) object
;
71 DixSpectrographPrivate
* priv
= spec
->priv
;
76 active
= g_value_get_boolean (value
);
78 if (priv
->active
!= active
) {
79 priv
->active
= active
;
81 if (priv
->active
== TRUE
) {
82 gtk_widget_set_state_flags (GTK_WIDGET (spec
),
83 GTK_STATE_FLAG_ACTIVE
, FALSE
);
85 gtk_widget_unset_state_flags (GTK_WIDGET (spec
),
86 GTK_STATE_FLAG_ACTIVE
);
89 g_object_notify (G_OBJECT (spec
), "active");
94 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
103 dix_spectrograph_get_property (GObject
* object
, guint prop_id
, GValue
* value
, GParamSpec
* pspec
)
105 DixSpectrograph
* spec
= (DixSpectrograph
*) object
;
106 DixSpectrographPrivate
* priv
= spec
->priv
;
110 g_value_set_boolean (value
, priv
->active
);
114 g_value_set_uint (value
, priv
->bands
);
118 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
126 dix_spectrograph_finalize (GObject
*object
)
128 DixSpectrograph
* spec
= (DixSpectrograph
*) object
;
129 DixSpectrographPrivate
* priv
= spec
->priv
;
131 G_OBJECT_CLASS (dix_spectrograph_parent_class
)->finalize (object
);
135 dix_spectrograph_realize (GtkWidget
* widget
)
137 GdkWindow
*window
= NULL
;
138 GtkAllocation allocation
;
139 GdkWindowAttr attributes
;
140 gint attributes_mask
;
142 gtk_widget_get_allocation (widget
, &allocation
);
144 gtk_widget_set_realized (widget
, TRUE
);
146 attributes
.wclass
= GDK_INPUT_OUTPUT
;
147 attributes
.window_type
= GDK_WINDOW_CHILD
;
148 attributes
.x
= allocation
.x
;
149 attributes
.y
= allocation
.y
;
150 attributes
.width
= allocation
.width
;
151 attributes
.height
= allocation
.height
;
152 attributes
.visual
= gtk_widget_get_visual (widget
);
153 attributes
.event_mask
= gtk_widget_get_events (widget
) | GDK_EXPOSURE_MASK
;
155 attributes_mask
= GDK_WA_X
| GDK_WA_Y
| GDK_WA_VISUAL
;
157 window
= gdk_window_new (gtk_widget_get_parent_window (widget
),
158 &attributes
, attributes_mask
);
159 gtk_widget_set_window (widget
, window
);
160 gdk_window_set_user_data (window
, widget
);
165 dix_spectrograph_get_preferred_width (GtkWidget
*widget
, gint
*minimal
, gint
*natural
)
167 DixSpectrograph
* spec
= (DixSpectrograph
*) widget
;
168 DixSpectrographPrivate
* priv
= spec
->priv
;
171 width
= (priv
->bands
* DIX_SPECTROGRAPH_LED_WIDTH
)
172 + ((priv
->bands
- 1) * DIX_SPECTROGRAPH_LED_PADDING
);
174 *minimal
= *natural
= width
;
178 dix_spectrograph_get_preferred_height (GtkWidget
*widget
, gint
*minimal
, gint
*natural
)
182 height
= DIX_SPECTROGRAPH_HEIGHT
;
184 *minimal
= *natural
= height
;
188 dix_spectrograph_draw (GtkWidget
*widget
, cairo_t
*cr
)
190 DixSpectrograph
* spec
= (DixSpectrograph
*) widget
;
191 DixSpectrographPrivate
* priv
= spec
->priv
;
192 GtkStyleContext
* context
= NULL
;
198 context
= gtk_widget_get_style_context (widget
);
199 state
= gtk_widget_get_state_flags (widget
);
200 if (G_LIKELY (context
!= NULL
)) {
201 gtk_style_context_set_state (context
, state
);
204 height
= gtk_widget_get_allocated_height (widget
);
206 for (i
= 0; i
< priv
->bands
; i
++) {
207 level
= dix_spectrograph_log_scale (priv
->magnitudes
[i
]);
208 if (G_UNLIKELY (level
> 6)) {
214 (gdouble
) i
* DIX_SPECTROGRAPH_LED_WIDTH_D
215 + (gdouble
) i
* DIX_SPECTROGRAPH_LED_PADDING_D
,
216 (gdouble
) height
- 1.0,
217 DIX_SPECTROGRAPH_LED_WIDTH_D
,
219 cairo_set_source_rgb (cr
, 0.00, 0.00, 0.00);
223 for (j
= level
; j
> 0 ; j
--) {
225 (gdouble
) i
* DIX_SPECTROGRAPH_LED_WIDTH_D
226 + (gdouble
) i
* DIX_SPECTROGRAPH_LED_PADDING_D
,
228 - (gdouble
) level
* DIX_SPECTROGRAPH_LED_HEIGHT_D
229 - (gdouble
) (level
- 1) * DIX_SPECTROGRAPH_LED_PADDING_D
,
230 DIX_SPECTROGRAPH_LED_WIDTH_D
,
231 DIX_SPECTROGRAPH_LED_HEIGHT_D
);
232 cairo_set_source_rgb (cr
, 0.00, 0.00, 0.00);
244 dix_spectrograph_class_init (DixSpectrographClass
* klass
)
246 GObjectClass
* gobject_class
= (GObjectClass
*) klass
;
247 GtkWidgetClass
* widget_class
= (GtkWidgetClass
*) klass
;
249 gobject_class
->set_property
= dix_spectrograph_set_property
;
250 gobject_class
->get_property
= dix_spectrograph_get_property
;
251 gobject_class
->finalize
= dix_spectrograph_finalize
;
253 widget_class
->realize
= dix_spectrograph_realize
;
254 widget_class
->get_preferred_width
= dix_spectrograph_get_preferred_width
;
255 widget_class
->get_preferred_height
= dix_spectrograph_get_preferred_height
;
256 widget_class
->draw
= dix_spectrograph_draw
;
258 g_object_class_install_property (gobject_class
,
260 g_param_spec_boolean ("active",
262 "Whether the spectrograph is active",
266 g_object_class_install_property (gobject_class
,
268 g_param_spec_uint ("bands",
270 "Number of frequency bands.",
271 6, 12, DIX_SPECTROGRAPH_BANDS
,
274 g_type_class_add_private (gobject_class
, sizeof (DixSpectrographPrivate
));
278 dix_spectrograph_init (DixSpectrograph
* spec
)
280 DixSpectrographPrivate
* priv
= DIX_SPECTROGRAPH_GET_PRIVATE (spec
);
284 priv
->active
= FALSE
;
285 gtk_widget_unset_state_flags (GTK_WIDGET (spec
),
286 GTK_STATE_FLAG_ACTIVE
);
288 priv
->bands
= DIX_SPECTROGRAPH_BANDS
;
290 priv
->magnitudes
= g_malloc (priv
->bands
* sizeof (gfloat
));
291 for (i
= 0; i
< priv
->bands
; i
++) {
292 priv
->magnitudes
[i
] = DIX_SPECTROGRAPH_THRESHOLD
;
294 /*priv->magnitudes[0] = -70.0f;*/
295 /*priv->magnitudes[1] = -40.0f;*/
296 /*priv->magnitudes[2] = -30.0f;*/
297 /*priv->magnitudes[3] = -20.0f;*/
298 /*priv->magnitudes[4] = -15.0f;*/
299 /*priv->magnitudes[5] = -3.0f;*/
300 /*priv->magnitudes[6] = -1.0f;*/
301 /*priv->magnitudes[7] = -80.0f;*/
305 dix_spectrograph_new ()
307 return GTK_WIDGET (g_object_new (DIX_TYPE_SPECTROGRAPH
, NULL
));
311 dix_spectrograph_set_magnitudes (DixSpectrograph
* spec
, guint bands
, gfloat
* magnitudes
)
313 g_return_if_fail (DIX_IS_SPECTROGRAPH (spec
));
314 g_return_if_fail (bands
== DIX_SPECTROGRAPH_BANDS
);
315 g_return_if_fail (magnitudes
!= NULL
);
316 DixSpectrographPrivate
* priv
= spec
->priv
;
319 if (G_UNLIKELY (bands
!= priv
->bands
)) {
323 for (i
= 0; i
< priv
->bands
; i
++) {
324 if (G_UNLIKELY (magnitudes
[i
] == priv
->magnitudes
[i
])) {
325 printf ("Improbable !\n");
329 if (magnitudes
[i
] < DIX_SPECTROGRAPH_THRESHOLD
) {
330 priv
->magnitudes
[i
] = DIX_SPECTROGRAPH_THRESHOLD
;
331 } else if (magnitudes
[i
] > priv
->magnitudes
[i
]) {
332 if (magnitudes
[i
] > 6.0f
) {
333 priv
->magnitudes
[i
] = 6.0f
;
335 priv
->magnitudes
[i
] = magnitudes
[i
];
337 } else if (magnitudes
[i
] < priv
->magnitudes
[i
]) {
338 priv
->magnitudes
[i
] -= 0.75f
; /* Ballistic coefficient */
342 gtk_widget_queue_draw (GTK_WIDGET (spec
));
346 dix_spectrograph_log_scale (gfloat db
)
352 } else if (db
< -37.2f
) {
354 } else if (db
< -25.8f
) {
356 } else if (db
< -17.0f
) {
358 } else if (db
< -9.4f
) {
360 } else if (db
< -1.7f
) {