From 5bd64349b051e9b792ae484def50b9fac6b11c3f Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Fri, 22 Jun 2012 22:12:00 +0000 Subject: Intégrationd es GtkVuMEter faite. Mais c'est pas beau :P MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///var/svn/2012-violon-leds/trunk@28 6be1fa4d-33ac-4c33-becc-79fcb3794bb6 --- tests/test7/gtkvumeter.c | 305 +++++++++++++++++++++++++++++++++++++++++++++++ tests/test7/gtkvumeter.h | 39 ++++++ tests/test7/gui.glade | 78 ++---------- tests/test7/test7.c | 59 ++++++++- 4 files changed, 410 insertions(+), 71 deletions(-) create mode 100644 tests/test7/gtkvumeter.c create mode 100644 tests/test7/gtkvumeter.h (limited to 'tests/test7') diff --git a/tests/test7/gtkvumeter.c b/tests/test7/gtkvumeter.c new file mode 100644 index 0000000..34a2038 --- /dev/null +++ b/tests/test7/gtkvumeter.c @@ -0,0 +1,305 @@ +/* + Adapted From GtkVuMeter by Todd Goyen + Copyright 2003 Todd Goyen + wettoad@knighthoodofbuh.or + + Improved rendering performance (no individual drawline calls) + +*/ +#include +#include "gtkvumeter.h" + +#define MIN_HORIZONTAL_VUMETER_WIDTH 40 +#define HORIZONTAL_VUMETER_HEIGHT 20 +#define VERTICAL_VUMETER_WIDTH 20 +#define MIN_VERTICAL_VUMETER_HEIGHT 40 + +G_DEFINE_TYPE (GtkVuMeter, gtk_vu_meter, GTK_TYPE_DRAWING_AREA); + +static GdkColor default_f_gradient_keys[3] = {{0,65535,0,0},{0,65535,65535,0},{0,0,65535,0}}; +static GdkColor default_b_gradient_keys[3] = {{0,49151,0,0},{0,49151,49151,0},{0,0,49151,0}}; + +static gboolean gtk_vu_meter_expose (GtkWidget *vumeter, GdkEventExpose *event); +static void gtk_vu_meter_setup_colors (GtkVuMeter *vumeter); +static void gtk_vu_meter_free_colors (GtkVuMeter *vumeter); +static void free_drawbuf(guchar *pixels, gpointer data); +static void gtk_vu_meter_size_request (GtkWidget *widget, GtkRequisition *requisition); +static void gtk_vu_meter_size_allocate (GtkWidget *widget, GtkAllocation *allocation); +static gint gtk_vu_meter_sound_level_to_draw_level (GtkVuMeter *vumeter); +static void gtk_vu_meter_realize (GtkWidget *widget); + +static void gtk_vu_meter_class_init (GtkVuMeterClass *class) { + GtkWidgetClass *widget_class; + widget_class = GTK_WIDGET_CLASS (class); + widget_class->realize = gtk_vu_meter_realize; + widget_class->expose_event = gtk_vu_meter_expose; + widget_class->size_request = gtk_vu_meter_size_request; + widget_class->size_allocate = gtk_vu_meter_size_allocate; +} + +static void gtk_vu_meter_init (GtkVuMeter *vumeter) { + vumeter->vertical=TRUE; + gtk_vu_meter_set_gradient(vumeter, 3, default_f_gradient_keys, 3, default_b_gradient_keys); + gtk_vu_meter_setup_colors(vumeter); +} + +static void gtk_vu_meter_realize (GtkWidget *widget) +{ + GtkVuMeter *vumeter; + GdkWindowAttr attributes; + gint attributes_mask; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_VU_METER (widget)); + + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + vumeter = GTK_VU_METER (widget); + + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = widget->allocation.width; + attributes.height = widget->allocation.height; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask); + + widget->style = gtk_style_attach (widget->style, widget->window); + + gdk_window_set_user_data (widget->window, widget); + gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); + + gtk_vu_meter_setup_colors (vumeter); +} + +void gtk_vu_meter_set_gradient (GtkVuMeter *vumeter, gint f_gradient_key_count, GdkColor *f_gradient_keys, gint b_gradient_key_count, GdkColor *b_gradient_keys) { + //XXX : memdup is a bad idea ? + GdkColor *fgk = g_memdup(f_gradient_keys, f_gradient_key_count*sizeof(GdkColor)); + GdkColor *bgk = g_memdup(b_gradient_keys, b_gradient_key_count*sizeof(GdkColor)); + g_return_if_fail (fgk != NULL); + g_return_if_fail (bgk != NULL); + + vumeter->f_gradient_keys = fgk; + vumeter->f_gradient_key_count=f_gradient_key_count; + vumeter->b_gradient_keys = bgk; + vumeter->b_gradient_key_count=b_gradient_key_count; +} +static void gtk_vu_meter_free_colors (GtkVuMeter *vumeter) { + // TODO : free pixmaps +} + +static void gtk_vu_meter_setup_colors (GtkVuMeter *vumeter) { + + gint i,j; + guchar *f_drawbuf, *b_drawbuf, f_r, f_g, f_b, b_r, b_g, b_b; + gint f_key_len, b_key_len; + gint f_key_i, b_key_i; + gdouble f_key_pos, b_key_pos; + GdkColor *fgk, *bgk; + + gint h=GTK_WIDGET(vumeter)->allocation.height; + gint w=GTK_WIDGET(vumeter)->allocation.width; + + // Clean every previous colors and buffers + gtk_vu_meter_free_colors (vumeter); + + if (vumeter->vertical == TRUE) { + vumeter->colors = MAX(h, 0); + } else { + vumeter->colors = MAX(w, 0); + } + + // Allocate a memory buffers to hold the gradients + f_drawbuf=g_malloc(h*w*3); + b_drawbuf=g_malloc(h*w*3); + g_return_if_fail (f_drawbuf != NULL); + g_return_if_fail (b_drawbuf != NULL); + + // Compute some values before looping for gradient generation + f_key_len = vumeter->colors / (vumeter->f_gradient_key_count-1) + 1; + b_key_len = vumeter->colors / (vumeter->b_gradient_key_count-1) + 1; + fgk=vumeter->f_gradient_keys; + bgk=vumeter->b_gradient_keys; + + for (i=0; icolors; i++) { + // Compute the current position in the gradient keys + f_key_i=i/f_key_len; + f_key_pos=((gdouble) (i%f_key_len)/f_key_len); + b_key_i=i/f_key_len; + b_key_pos=((gdouble) (i%b_key_len)/b_key_len); + + /* Generate the Colours */ + /* foreground */ + f_r = ( fgk[f_key_i].red*(1.0-f_key_pos) + fgk[f_key_i+1].red*f_key_pos ) / 256; + f_g = ( fgk[f_key_i].green*(1.0-f_key_pos) + fgk[f_key_i+1].green*f_key_pos ) / 256; + f_b = ( fgk[f_key_i].blue*(1.0-f_key_pos) + fgk[f_key_i+1].blue*f_key_pos ) / 256; + /* background */ + b_r = ( bgk[b_key_i].red*(1.0-b_key_pos) + bgk[b_key_i+1].red*b_key_pos ) / 256; + b_g = ( bgk[b_key_i].green*(1.0-b_key_pos) + bgk[b_key_i+1].green*b_key_pos ) / 256; + b_b = ( bgk[b_key_i].blue*(1.0-b_key_pos) + bgk[b_key_i+1].blue*b_key_pos ) / 256; + + /* Apply the color in the drawbufs */ + if (vumeter->vertical == TRUE) { + // Vertical mode : draw directly the whole line of identical color + for (j=3*w*i; j<3*w*(i+1); ) { + f_drawbuf[j++]=f_r; + f_drawbuf[j++]=f_g; + f_drawbuf[j++]=f_b; + } + for (j=3*w*i; j<3*w*(i+1); ) { + b_drawbuf[j++]=b_r; + b_drawbuf[j++]=b_g; + b_drawbuf[j++]=b_b; + } + } else { + // Horiziontal mode : draw only the first line (color change at each pixel) + // Others line will be duplicated at the end + f_drawbuf[i]=f_r; + f_drawbuf[i+1]=f_g; + f_drawbuf[i+2]=f_b; + b_drawbuf[i]=b_r; + b_drawbuf[i+1]=b_g; + b_drawbuf[i+2]=b_b; + } + } + if (vumeter->vertical != TRUE) { + // Duplicate the first line over the others + for (j=1; jf_pixbuf = gdk_pixbuf_new_from_data(f_drawbuf, GDK_COLORSPACE_RGB, FALSE, 8, w, h, w*3, free_drawbuf, NULL); + vumeter->b_pixbuf = gdk_pixbuf_new_from_data(b_drawbuf, GDK_COLORSPACE_RGB, FALSE, 8, w, h, w*3, free_drawbuf, NULL); +} + +static void gtk_vu_meter_size_request (GtkWidget *widget, GtkRequisition *requisition) +{ + GtkVuMeter *vumeter; + + g_return_if_fail (GTK_IS_VU_METER (widget)); + g_return_if_fail (requisition != NULL); + + vumeter = GTK_VU_METER (widget); + + if (vumeter->vertical == TRUE) { + requisition->width = VERTICAL_VUMETER_WIDTH; + requisition->height = MIN_VERTICAL_VUMETER_HEIGHT; + } else { + requisition->width = MIN_HORIZONTAL_VUMETER_WIDTH; + requisition->height = HORIZONTAL_VUMETER_HEIGHT; + } +} + +static void gtk_vu_meter_size_allocate (GtkWidget *widget, GtkAllocation *allocation) +{ + GtkVuMeter *vumeter; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_VU_METER (widget)); + g_return_if_fail (allocation != NULL); + + widget->allocation = *allocation; + vumeter = GTK_VU_METER (widget); + + if (GTK_WIDGET_REALIZED (widget)) { + if (vumeter->vertical == TRUE) { /* veritcal */ + gdk_window_move_resize (widget->window, allocation->x, allocation->y, + VERTICAL_VUMETER_WIDTH, MAX(allocation->height, MIN_VERTICAL_VUMETER_HEIGHT)); + } else { /* horizontal */ + gdk_window_move_resize (widget->window, allocation->x, allocation->y, + MAX(allocation->width, MIN_HORIZONTAL_VUMETER_WIDTH), HORIZONTAL_VUMETER_HEIGHT); + } + /* Fix the colours */ + gtk_vu_meter_setup_colors (vumeter); + } +} + +static void free_drawbuf(guchar *pixels, gpointer data) { + g_free(pixels); +} + +static gboolean gtk_vu_meter_expose (GtkWidget *vumeter, GdkEventExpose *event) { + //gdk_pixbuf_render_to_drawable(pixbuf, dbuf_pixmap, app->style->fg_gc[GTK_STATE_NORMAL], 0, 0, 0, 0, WIDTH, HEIGHT, GDK_RGB_DITHER_NORMAL, 0, 0); + cairo_t *cr; + gint draw_level = gtk_vu_meter_sound_level_to_draw_level(GTK_VU_METER(vumeter)); + + cr = gdk_cairo_create (vumeter->window); + + // set a clip region for the expose event + cairo_rectangle (cr,event->area.x, event->area.y, event->area.width, event->area.height); + cairo_clip(cr); + + // Paint from the stored gradient + gdk_cairo_set_source_pixbuf(cr, GTK_VU_METER(vumeter)->b_pixbuf,0,0); + cairo_paint(cr); + + // set a clip region for the expose event + if (GTK_VU_METER(vumeter)->vertical==TRUE) { + cairo_rectangle (cr,event->area.x, event->area.y+draw_level, event->area.width, event->area.height-draw_level); + } else { + //TODO + cairo_rectangle (cr,event->area.x, event->area.y, event->area.width, 12/*event->area.height*/); + } + cairo_clip(cr); + + // Paint from the stored gradient + gdk_cairo_set_source_pixbuf(cr, GTK_VU_METER(vumeter)->f_pixbuf,0,0); + cairo_paint(cr); + + cairo_destroy(cr); + + return FALSE; +} + +static gint gtk_vu_meter_sound_level_to_draw_level (GtkVuMeter *vumeter) { + gint draw_level; + gdouble level, min, max, height; + + level = (gdouble)vumeter->level; + min = (gdouble)vumeter->min; + max = (gdouble)vumeter->max; + height = (gdouble)vumeter->colors; + + draw_level = (1.0 - (level - min)/(max - min)) * height; + + //printf("1.0 - (%lf - %lf)/(%lf - %lf)) * %lf => %i\n", level, min, max, min, height, draw_level); + + return draw_level; +} + +GtkWidget * gtk_vu_meter_new (gboolean vertical) { + GtkWidget *vumeter = g_object_new (GTK_TYPE_VU_METER, NULL); + GTK_VU_METER(vumeter)->vertical=vertical; + GTK_VU_METER(vumeter)->level=0; + GTK_VU_METER(vumeter)->min=-32767; + GTK_VU_METER(vumeter)->max=32767; + + return vumeter; +} + + +void gtk_vu_meter_set_min_max (GtkVuMeter *vumeter, gint min, gint max) +{ + g_return_if_fail (vumeter != NULL); + + vumeter->max = MAX(max, min); + vumeter->min = MIN(min, max); + if (vumeter->max == vumeter->min) { + vumeter->max++; + } + vumeter->level = CLAMP (vumeter->level, vumeter->min, vumeter->max); + gtk_widget_queue_draw (GTK_WIDGET(vumeter)); +} + +void gtk_vu_meter_set_level(GtkVuMeter *vumeter, gint level) +{ + g_return_if_fail (vumeter != NULL); + + vumeter->level = CLAMP (level, vumeter->min, vumeter->max); + gtk_widget_queue_draw (GTK_WIDGET(vumeter)); +} + diff --git a/tests/test7/gtkvumeter.h b/tests/test7/gtkvumeter.h new file mode 100644 index 0000000..07eb7c5 --- /dev/null +++ b/tests/test7/gtkvumeter.h @@ -0,0 +1,39 @@ +#ifndef GTKVUMETER_H +#define GTKVUMETER_H +#include + +#define GTK_TYPE_VU_METER (gtk_vu_meter_get_type ()) +#define GTK_VU_METER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_VU_METER, GtkVuMeter)) +#define GTK_VU_METER_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GTK_VU_METER, GtkVuMeterClass)) +#define GTK_IS_VU_METER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_VU_METER)) +#define GTK_IS_VU_METER_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GTK_TYPE_VU_METER)) +#define GTK_VU_METER_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_VU_METER, GtkVuMeterClass)) + +typedef struct _GtkVuMeter GtkVuMeter; +typedef struct _GtkVuMeterClass GtkVuMeterClass; + +struct _GtkVuMeter { + GtkDrawingArea parent; + + /* private */ + gboolean vertical; + gint level, min, max; + + gint f_gradient_key_count, b_gradient_key_count; + GdkColor *f_gradient_keys, *b_gradient_keys; + + gint colors; + GdkPixbuf *f_pixbuf, *b_pixbuf; +}; + +struct _GtkVuMeterClass { + GtkDrawingAreaClass parent_class; +}; + +GtkType gtk_vu_meter_get_type (void) G_GNUC_CONST; +GtkWidget * gtk_vu_meter_new (gboolean vertical); +void gtk_vu_meter_set_gradient (GtkVuMeter *vumeter, gint f_gradient_key_count, GdkColor *f_gradient_keys, gint b_gradient_key_count, GdkColor *b_gradient_keys); +void gtk_vu_meter_set_min_max (GtkVuMeter *vumeter, gint min, gint max); +void gtk_vu_meter_set_level(GtkVuMeter *vumeter, gint level); + +#endif /*GTKVUMETER_H*/ diff --git a/tests/test7/gui.glade b/tests/test7/gui.glade index f91b0d7..b6207b1 100644 --- a/tests/test7/gui.glade +++ b/tests/test7/gui.glade @@ -763,16 +763,12 @@ copy of the Program in return for a fee. 0 in - + True False 12 - - True - True - 1 - + @@ -900,44 +896,17 @@ copy of the Program in return for a fee. True False - + True False - - True - True - 1 - - - True - True - 0 - + - - True - True - 1 - - - True - True - 1 - + - - True - True - 1 - - - True - True - 2 - + @@ -947,44 +916,17 @@ copy of the Program in return for a fee. - + True False - - True - True - 1 - - - True - True - 0 - + - - True - True - 1 - - - True - True - 1 - + - - True - True - 1 - - - True - True - 2 - + diff --git a/tests/test7/test7.c b/tests/test7/test7.c index 7f557ca..52eb029 100644 --- a/tests/test7/test7.c +++ b/tests/test7/test7.c @@ -1,10 +1,14 @@ #include #include +#include "gtkvumeter.h" #define FUNC_COUNT 4 GtkBuilder *builder=NULL; GtkToggleButton *buttons[FUNC_COUNT]={NULL}; +GtkWidget *vumeter_sound, *vumeter_r, *vumeter_g, *vumeter_b, *vumeter_h, *vumeter_s, *vumeter_v; + +void add_custom_widgets(); // Applicative actions void switch_to_func(gint func_id) { @@ -42,8 +46,6 @@ void on_radbut_func_realize(GtkObject *object, gpointer user_data) { int main (int argc, char *argv[]) { GtkWidget *window; -// int res; - gtk_init(&argc, &argv); builder = gtk_builder_new(); @@ -52,7 +54,9 @@ int main (int argc, char *argv[]) { window = GTK_WIDGET(gtk_builder_get_object(builder, "win_main")); gtk_builder_connect_signals(builder, NULL); - gtk_widget_show(window); + + add_custom_widgets(); + gtk_widget_show_all(window); gtk_main(); @@ -60,3 +64,52 @@ int main (int argc, char *argv[]) { return 0; } +void add_custom_widgets() { + GtkContainer *c; + + GdkColor f_gradient_red[2] = {{0,65535,0,0},{0,32767,0,0}}; + GdkColor b_gradient_red[2] = {{0,49151,0,0},{0,24575,0,0}}; + GdkColor f_gradient_green[2] = {{0,0,65535,0},{0,0,32767,0}}; + GdkColor b_gradient_green[2] = {{0,0,49151,0},{0,0,24575,0}}; + GdkColor f_gradient_blue[2] = {{0,0,0,65535},{0,0,0,32767}}; + GdkColor b_gradient_blue[2] = {{0,0,0,49151},{0,0,0,24575}}; + GdkColor f_gradient_hue[7] = {{0,65535,0,0},{0,65535,0,65535},{0,0,0,65535},{0,0,65535,65535},{0,0,65535,0},{0,65535,65535,0},{0,65535,0,0}}; + GdkColor b_gradient_hue[7] = {{0,49151,0,0},{0,49151,0,49151},{0,0,0,49151},{0,0,49151,49151},{0,0,49151,0},{0,49151,49151,0},{0,49151,0,0}}; + GdkColor f_gradient_value[2] = {{0,65535,0,0},{0,32767,0,0}}; + GdkColor b_gradient_value[2] = {{0,49151,0,0},{0,24575,0,0}}; + GdkColor f_gradient_saturation[2] = {{0,32767,32767,32767},{0,32767,0,0}}; + GdkColor b_gradient_saturation[2] = {{0,24575,24575,24575},{0,24575,0,0}}; + + vumeter_sound = gtk_vu_meter_new(TRUE); + gtk_vu_meter_set_min_max(GTK_VU_METER(vumeter_sound), -50, 0); + c=GTK_CONTAINER(gtk_builder_get_object(builder, "a_in_sound")); + gtk_container_add(c,vumeter_sound); + + vumeter_h = gtk_vu_meter_new (TRUE); + gtk_vu_meter_set_min_max(GTK_VU_METER(vumeter_h), 0, 255); + gtk_vu_meter_set_gradient(GTK_VU_METER(vumeter_h), 7, f_gradient_hue, 7, b_gradient_hue); + vumeter_s = gtk_vu_meter_new (TRUE); + gtk_vu_meter_set_min_max(GTK_VU_METER(vumeter_s), 0, 255); + gtk_vu_meter_set_gradient(GTK_VU_METER(vumeter_s), 2, f_gradient_value, 2, b_gradient_value); + vumeter_v = gtk_vu_meter_new (TRUE); + gtk_vu_meter_set_min_max(GTK_VU_METER(vumeter_v), 0, 255); + gtk_vu_meter_set_gradient(GTK_VU_METER(vumeter_v), 2, f_gradient_saturation, 2, b_gradient_saturation); + c=GTK_CONTAINER(gtk_builder_get_object(builder, "hb_out_hsv")); + gtk_container_add(c,vumeter_h); + gtk_container_add(c,vumeter_s); + gtk_container_add(c,vumeter_v); + + vumeter_r = gtk_vu_meter_new (TRUE); + gtk_vu_meter_set_min_max(GTK_VU_METER(vumeter_r), 0, 255); + gtk_vu_meter_set_gradient(GTK_VU_METER(vumeter_r), 2, f_gradient_red, 2, b_gradient_red); + vumeter_g = gtk_vu_meter_new (TRUE); + gtk_vu_meter_set_min_max(GTK_VU_METER(vumeter_g), 0, 255); + gtk_vu_meter_set_gradient(GTK_VU_METER(vumeter_g), 2, f_gradient_green, 2, b_gradient_green); + vumeter_b = gtk_vu_meter_new (TRUE); + gtk_vu_meter_set_min_max(GTK_VU_METER(vumeter_b), 0, 255); + gtk_vu_meter_set_gradient(GTK_VU_METER(vumeter_b), 2, f_gradient_blue, 2, b_gradient_blue); + c=GTK_CONTAINER(gtk_builder_get_object(builder, "hb_out_rgb")); + gtk_container_add(c,vumeter_r); + gtk_container_add(c,vumeter_g); + gtk_container_add(c,vumeter_b); +} -- cgit v1.2.3