summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-04-07 12:44:08 +0200
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-04-07 12:44:08 +0200
commitdc2363526761820ced55ff0735771dfb747b2921 (patch)
tree480d44db8ab8a8d2754210d9f9b9dc9e91af99d3 /plugins
parent79fccb4ac4c50f1d1f50ad379bc40e7ab3b52367 (diff)
parent823669afef8942b45960391f2f3d732ab1ad06e3 (diff)
Merge branch 'thesame' into devel
Diffstat (limited to 'plugins')
-rw-r--r--plugins/gtkui/Makefile.am3
-rwxr-xr-xplugins/gtkui/compile12
-rw-r--r--plugins/gtkui/eq.c33
-rw-r--r--plugins/gtkui/graphic.c1484
-rw-r--r--plugins/gtkui/graphic.h44
-rw-r--r--plugins/gtkui/graphic.vala737
-rw-r--r--plugins/gtkui/test.vala30
7 files changed, 2341 insertions, 2 deletions
diff --git a/plugins/gtkui/Makefile.am b/plugins/gtkui/Makefile.am
index 22e11995..02a2d5e4 100644
--- a/plugins/gtkui/Makefile.am
+++ b/plugins/gtkui/Makefile.am
@@ -17,7 +17,8 @@ gtkui_la_SOURCES = gtkui.c gtkui.h\
coverart.c coverart.h\
plcommon.c plcommon.h\
prefwin.c\
- eq.c eq.h
+ eq.c eq.h\
+ graphic.c graphic.h
gtkui_la_LDFLAGS = -module
diff --git a/plugins/gtkui/compile b/plugins/gtkui/compile
new file mode 100755
index 00000000..c608a7a1
--- /dev/null
+++ b/plugins/gtkui/compile
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+#gcc g.c ddb-equalizer.c -g -O0 `pkg-config --libs --cflags gtk+-2.0 gdk-2.0`
+
+valac -C -H graphic.h --library graphic graphic.vala --pkg=gtk+-2.0 &&
+#gcc --shared -o libgraphic.so `pkg-config --libs --cflags gtk+-2.0 gdk-2.0` graphic.c &&
+valac -C test.vala graphic.vapi --pkg=gtk+-2.0 &&
+gcc test.c graphic.c -I. -o test `pkg-config --libs --cflags gtk+-2.0 gdk-2.0`
+# gcc -shared graphic.c -o graphic.so `pkg-config --libs --cflags gtk+-2.0 gdk-2.0`
+#valac graphic.vala --pkg=gtk+-2.0
+#gcc *.c `pkg-config --libs --cflags gtk+-2.0`
+
diff --git a/plugins/gtkui/eq.c b/plugins/gtkui/eq.c
index a02b2bc0..1935cf6b 100644
--- a/plugins/gtkui/eq.c
+++ b/plugins/gtkui/eq.c
@@ -22,6 +22,7 @@
#include "gtkui.h"
#include "support.h"
#include "../supereq/supereq.h"
+#include "graphic.h"
static GtkWidget *eqwin;
static GtkWidget *sliders[18];
@@ -74,8 +75,29 @@ eq_init_widgets (GtkWidget *container) {
}
void
+graphic_value_changed (gpointer inst, double *values, gint count)
+{
+ DB_supereq_dsp_t *eq = NULL;
+ DB_dsp_t **plugs = deadbeef->plug_get_dsp_list ();
+
+ for (int i = 0; plugs[i]; i++)
+ {
+ if (plugs[i]->plugin.id && !strcmp (plugs[i]->plugin.id, "supereq"))
+ {
+ eq = (DB_supereq_dsp_t *)plugs[i];
+ for (int ii = 0; ii < count; ii++)
+ {
+ double val = db_to_amp (values[ii]);
+ eq->set_band (ii, val);
+ }
+ break;
+ }
+ }
+}
+
+void
eq_window_show (void) {
- if (!eqwin) {
+/* if (!eqwin) {
eqwin = gtk_hbox_new (FALSE, 0);
gtk_widget_set_size_request (eqwin, -1, 200);
eq_init_widgets (eqwin);
@@ -107,6 +129,15 @@ eq_window_show (void) {
gtk_range_set_value (GTK_RANGE (scale), val);
}
}
+ gtk_widget_show (eqwin);*/
+
+ if (!eqwin) {
+ eqwin = deadbeef_graphic_new();
+ g_signal_connect (eqwin, "on_changed", G_CALLBACK (graphic_value_changed), 0);
+ gtk_widget_set_size_request (eqwin, -1, 200);
+ GtkWidget *cont = lookup_widget (mainwin, "vbox1");
+ gtk_box_pack_start (GTK_BOX (cont), eqwin, FALSE, FALSE, 0);
+ }
gtk_widget_show (eqwin);
}
diff --git a/plugins/gtkui/graphic.c b/plugins/gtkui/graphic.c
new file mode 100644
index 00000000..3a899afb
--- /dev/null
+++ b/plugins/gtkui/graphic.c
@@ -0,0 +1,1484 @@
+/* graphic.c generated by valac, the Vala compiler
+ * generated from graphic.vala, do not modify */
+
+
+#include <glib.h>
+#include <glib-object.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <pango/pango.h>
+#include <float.h>
+#include <math.h>
+#include <cairo.h>
+#include <gobject/gvaluecollector.h>
+
+
+#define DEADBEEF_TYPE_GRAPHIC (deadbeef_graphic_get_type ())
+#define DEADBEEF_GRAPHIC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DEADBEEF_TYPE_GRAPHIC, DeadbeefGraphic))
+#define DEADBEEF_GRAPHIC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DEADBEEF_TYPE_GRAPHIC, DeadbeefGraphicClass))
+#define DEADBEEF_IS_GRAPHIC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DEADBEEF_TYPE_GRAPHIC))
+#define DEADBEEF_IS_GRAPHIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DEADBEEF_TYPE_GRAPHIC))
+#define DEADBEEF_GRAPHIC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DEADBEEF_TYPE_GRAPHIC, DeadbeefGraphicClass))
+
+typedef struct _DeadbeefGraphic DeadbeefGraphic;
+typedef struct _DeadbeefGraphicClass DeadbeefGraphicClass;
+typedef struct _DeadbeefGraphicPrivate DeadbeefGraphicPrivate;
+
+#define DEADBEEF_GRAPHIC_TYPE_POINT (deadbeef_graphic_point_get_type ())
+#define DEADBEEF_GRAPHIC_POINT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DEADBEEF_GRAPHIC_TYPE_POINT, DeadbeefGraphicPoint))
+#define DEADBEEF_GRAPHIC_POINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DEADBEEF_GRAPHIC_TYPE_POINT, DeadbeefGraphicPointClass))
+#define DEADBEEF_GRAPHIC_IS_POINT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DEADBEEF_GRAPHIC_TYPE_POINT))
+#define DEADBEEF_GRAPHIC_IS_POINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DEADBEEF_GRAPHIC_TYPE_POINT))
+#define DEADBEEF_GRAPHIC_POINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DEADBEEF_GRAPHIC_TYPE_POINT, DeadbeefGraphicPointClass))
+
+typedef struct _DeadbeefGraphicPoint DeadbeefGraphicPoint;
+typedef struct _DeadbeefGraphicPointClass DeadbeefGraphicPointClass;
+#define __g_list_free_deadbeef_graphic_point_unref0(var) ((var == NULL) ? NULL : (var = (_g_list_free_deadbeef_graphic_point_unref (var), NULL)))
+#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
+#define _pango_font_description_free0(var) ((var == NULL) ? NULL : (var = (pango_font_description_free (var), NULL)))
+#define _gdk_cursor_unref0(var) ((var == NULL) ? NULL : (var = (gdk_cursor_unref (var), NULL)))
+typedef struct _DeadbeefGraphicPointPrivate DeadbeefGraphicPointPrivate;
+#define _deadbeef_graphic_point_unref0(var) ((var == NULL) ? NULL : (var = (deadbeef_graphic_point_unref (var), NULL)))
+#define _g_free0(var) (var = (g_free (var), NULL))
+#define _cairo_destroy0(var) ((var == NULL) ? NULL : (var = (cairo_destroy (var), NULL)))
+#define __g_slist_free_g_object_unref0(var) ((var == NULL) ? NULL : (var = (_g_slist_free_g_object_unref (var), NULL)))
+typedef struct _DeadbeefGraphicParamSpecPoint DeadbeefGraphicParamSpecPoint;
+
+struct _DeadbeefGraphic {
+ GtkDrawingArea parent_instance;
+ DeadbeefGraphicPrivate * priv;
+};
+
+struct _DeadbeefGraphicClass {
+ GtkDrawingAreaClass parent_class;
+};
+
+struct _DeadbeefGraphicPrivate {
+ GList* points;
+ GList* current_point;
+ GdkColor back_color;
+ GdkColor fore_bright_color;
+ GdkColor fore_dark_color;
+ PangoContext* pango_ctx;
+ PangoFontDescription* font_desc;
+ double* values;
+ gint values_length1;
+ gint _values_size_;
+ double preamp;
+ gint mouse_y;
+ gboolean snap;
+ gboolean aa_mode;
+ gboolean curve_hook;
+ gboolean preamp_hook;
+ GtkMenu* menu;
+ GdkCursor* moving_cursor;
+ GdkCursor* updown_cursor;
+ GdkCursor* pointer_cursor;
+};
+
+struct _DeadbeefGraphicPoint {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ DeadbeefGraphicPointPrivate * priv;
+ double x;
+ double y;
+};
+
+struct _DeadbeefGraphicPointClass {
+ GTypeClass parent_class;
+ void (*finalize) (DeadbeefGraphicPoint *self);
+};
+
+struct _DeadbeefGraphicParamSpecPoint {
+ GParamSpec parent_instance;
+};
+
+
+extern gint btn_size;
+gint btn_size = 7;
+extern DeadbeefGraphic* deadbeef_graphic_inst;
+DeadbeefGraphic* deadbeef_graphic_inst = NULL;
+static gpointer deadbeef_graphic_point_parent_class = NULL;
+static gpointer deadbeef_graphic_parent_class = NULL;
+
+#define spot_size 3
+#define margin_left 35
+#define margin_bottom 10
+#define bands 18
+GType deadbeef_graphic_get_type (void);
+static gpointer deadbeef_graphic_point_ref (gpointer instance);
+static void deadbeef_graphic_point_unref (gpointer instance);
+static GParamSpec* deadbeef_graphic_param_spec_point (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) G_GNUC_UNUSED;
+static void deadbeef_graphic_value_set_point (GValue* value, gpointer v_object) G_GNUC_UNUSED;
+static void deadbeef_graphic_value_take_point (GValue* value, gpointer v_object) G_GNUC_UNUSED;
+static gpointer deadbeef_graphic_value_get_point (const GValue* value) G_GNUC_UNUSED;
+static GType deadbeef_graphic_point_get_type (void) G_GNUC_UNUSED;
+#define DEADBEEF_GRAPHIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DEADBEEF_TYPE_GRAPHIC, DeadbeefGraphicPrivate))
+enum {
+ DEADBEEF_GRAPHIC_DUMMY_PROPERTY
+};
+static void _g_list_free_deadbeef_graphic_point_unref (GList* self);
+void deadbeef_graphic_aa_mode_changed (DeadbeefGraphic* self, GtkCheckMenuItem* item);
+static void deadbeef_graphic_set_snap (DeadbeefGraphic* self, gboolean new_snap);
+void deadbeef_graphic_mode_changed (DeadbeefGraphic* self, GtkCheckMenuItem* item);
+static DeadbeefGraphicPoint* deadbeef_graphic_point_new (void);
+static DeadbeefGraphicPoint* deadbeef_graphic_point_construct (GType object_type);
+static void deadbeef_graphic_abs_to_screen (DeadbeefGraphic* self, double x, double y, GdkPoint* result);
+static void deadbeef_graphic_abs_to_screen_d (DeadbeefGraphic* self, double x, double y, double* sx, double* sy);
+static double deadbeef_graphic_cubic (DeadbeefGraphic* self, double y0, double y1, double y2, double y3, double mu);
+static inline double deadbeef_graphic_scale (DeadbeefGraphic* self, double val);
+static gboolean deadbeef_graphic_real_expose_event (GtkWidget* base, GdkEventExpose* event);
+static gboolean deadbeef_graphic_get_point_at (DeadbeefGraphic* self, double x, double y);
+static void deadbeef_graphic_recalc_values (DeadbeefGraphic* self);
+static void deadbeef_graphic_snap_move (DeadbeefGraphic* self, double x, double y);
+static void deadbeef_graphic_handle_curve_click (DeadbeefGraphic* self, GdkEventButton* event);
+static gboolean deadbeef_graphic_in_curve_area (DeadbeefGraphic* self, gint x, gint y);
+static gboolean deadbeef_graphic_real_button_press_event (GtkWidget* base, GdkEventButton* event);
+static gboolean deadbeef_graphic_real_button_release_event (GtkWidget* base, GdkEventButton* event);
+static gboolean deadbeef_graphic_real_leave_notify_event (GtkWidget* base, GdkEventCrossing* event);
+static gboolean deadbeef_graphic_real_motion_notify_event (GtkWidget* base, GdkEventMotion* event);
+DeadbeefGraphic* deadbeef_graphic_new (void);
+DeadbeefGraphic* deadbeef_graphic_construct (GType object_type);
+static void _deadbeef_graphic_aa_mode_changed_gtk_check_menu_item_toggled (GtkCheckMenuItem* _sender, gpointer self);
+static void _deadbeef_graphic_mode_changed_gtk_check_menu_item_toggled (GtkCheckMenuItem* _sender, gpointer self);
+static void _g_slist_free_g_object_unref (GSList* self);
+static GObject * deadbeef_graphic_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties);
+enum {
+ DEADBEEF_GRAPHIC_POINT_DUMMY_PROPERTY
+};
+static void deadbeef_graphic_point_finalize (DeadbeefGraphicPoint* obj);
+static void deadbeef_graphic_finalize (GObject* obj);
+
+const char* freqs[18] = {"32", "80", "110", "160", "220", "315", "450", "630", "900", "1.3k", "1.8k", "2.5k", "3.6k", "5k", "7k", "10k", "14k", "20k"};
+
+static void g_cclosure_user_marshal_VOID__POINTER_INT (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data);
+
+static void _g_list_free_deadbeef_graphic_point_unref (GList* self) {
+ g_list_foreach (self, (GFunc) deadbeef_graphic_point_unref, NULL);
+ g_list_free (self);
+}
+
+
+void deadbeef_graphic_aa_mode_changed (DeadbeefGraphic* self, GtkCheckMenuItem* item) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (item != NULL);
+ self->priv->aa_mode = gtk_check_menu_item_get_active (item);
+ gtk_widget_queue_draw ((GtkWidget*) self);
+}
+
+
+void deadbeef_graphic_mode_changed (DeadbeefGraphic* self, GtkCheckMenuItem* item) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (item != NULL);
+ deadbeef_graphic_set_snap (self, gtk_check_menu_item_get_active (item));
+}
+
+
+static gpointer _deadbeef_graphic_point_ref0 (gpointer self) {
+ return self ? deadbeef_graphic_point_ref (self) : NULL;
+}
+
+
+static void deadbeef_graphic_set_snap (DeadbeefGraphic* self, gboolean new_snap) {
+ g_return_if_fail (self != NULL);
+ self->priv->snap = new_snap;
+ if (self->priv->snap) {
+ double step;
+ step = 1.0 / ((double) (bands + 1));
+ if (g_list_length (self->priv->points) > 0) {
+ GList* iter;
+ iter = NULL;
+ {
+ gboolean _tmp0_;
+ iter = self->priv->points->next;
+ _tmp0_ = TRUE;
+ while (TRUE) {
+ if (!_tmp0_) {
+ iter = iter->next;
+ }
+ _tmp0_ = FALSE;
+ if (!(iter != NULL)) {
+ break;
+ }
+ self->priv->points = g_list_remove_link (self->priv->points, iter->prev);
+ }
+ }
+ self->priv->points = g_list_remove_link (self->priv->points, self->priv->points);
+ }
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp1_;
+ _tmp1_ = TRUE;
+ while (TRUE) {
+ DeadbeefGraphicPoint* point;
+ if (!_tmp1_) {
+ i++;
+ }
+ _tmp1_ = FALSE;
+ if (!(i < bands)) {
+ break;
+ }
+ point = deadbeef_graphic_point_new ();
+ point->x = (((double) i) + 1) * step;
+ point->y = self->priv->values[i];
+ self->priv->points = g_list_prepend (self->priv->points, _deadbeef_graphic_point_ref0 (point));
+ _deadbeef_graphic_point_unref0 (point);
+ }
+ }
+ }
+ self->priv->points = g_list_reverse (self->priv->points);
+ }
+}
+
+
+static void deadbeef_graphic_abs_to_screen (DeadbeefGraphic* self, double x, double y, GdkPoint* result) {
+ GdkPoint _tmp0_ = {0};
+ g_return_if_fail (self != NULL);
+ *result = (memset (&_tmp0_, 0, sizeof (GdkPoint)), _tmp0_.x = ((gint) (x * (((GtkWidget*) self)->allocation.width - margin_left))) + margin_left, _tmp0_.y = (gint) (y * (((GtkWidget*) self)->allocation.height - margin_bottom)), _tmp0_);
+ return;
+}
+
+
+static void deadbeef_graphic_abs_to_screen_d (DeadbeefGraphic* self, double x, double y, double* sx, double* sy) {
+ g_return_if_fail (self != NULL);
+ *sx = (double) (((gint) (x * (((GtkWidget*) self)->allocation.width - margin_left))) + margin_left);
+ *sy = (double) ((gint) (y * (((GtkWidget*) self)->allocation.height - margin_bottom)));
+}
+
+
+static double deadbeef_graphic_cubic (DeadbeefGraphic* self, double y0, double y1, double y2, double y3, double mu) {
+ double result = 0.0;
+ g_return_val_if_fail (self != NULL, 0.0);
+ result = 0.5 * ((((2 * y1) + (((-y0) + y2) * mu)) + ((((((2 * y0) - (5 * y1)) + (4 * y2)) - y3) * mu) * mu)) + (((((((-y0) + (3 * y1)) - (3 * y2)) + y3) * mu) * mu) * mu));
+ return result;
+}
+
+
+static gpointer _g_object_ref0 (gpointer self) {
+ return self ? g_object_ref (self) : NULL;
+}
+
+
+static gpointer _pango_font_description_copy0 (gpointer self) {
+ return self ? pango_font_description_copy (self) : NULL;
+}
+
+
+static gpointer _cairo_reference0 (gpointer self) {
+ return self ? cairo_reference (self) : NULL;
+}
+
+
+static gboolean deadbeef_graphic_real_expose_event (GtkWidget* base, GdkEventExpose* event) {
+ DeadbeefGraphic * self;
+ gboolean result = FALSE;
+ gint width;
+ gint height;
+ GdkPoint* _tmp1_;
+ gint _gpoints_size_;
+ gint gpoints_length1;
+ gint _tmp0_;
+ GdkPoint* gpoints;
+ GdkPoint _tmp2_ = {0};
+ gint i;
+ GdkPoint _tmp4_ = {0};
+ GdkDrawable* d;
+ GdkGCValues _tmp6_;
+ GdkGCValues _tmp5_ = {0};
+ GdkGC* gc;
+ double step;
+ double vstep;
+ PangoLayout* l;
+ PangoContext* ctx;
+ PangoFontDescription* fd;
+ gboolean _tmp10_ = FALSE;
+ char* tmp;
+ char* _tmp11_;
+ GdkRectangle _tmp13_;
+ GdkRectangle _tmp12_ = {0};
+ gint count;
+ GdkRectangle _tmp16_;
+ GdkRectangle _tmp15_ = {0};
+ gint bar_w;
+ GdkRectangle _tmp22_;
+ GdkRectangle _tmp21_ = {0};
+ GdkPoint gp = {0};
+ guint pcount;
+ double* _tmp23_;
+ gint _ys_size_;
+ gint ys_length1;
+ double* ys;
+ double* _tmp24_;
+ gint _xs_size_;
+ gint xs_length1;
+ double* xs;
+ cairo_t* _tmp26_;
+ cairo_t* cairo;
+ gint prev_x;
+ gint prev_y;
+ self = (DeadbeefGraphic*) base;
+ width = ((GtkWidget*) self)->allocation.width;
+ height = ((GtkWidget*) self)->allocation.height;
+ gpoints = (_tmp1_ = g_new0 (GdkPoint, _tmp0_ = g_list_length (self->priv->points) + 2), gpoints_length1 = _tmp0_, _gpoints_size_ = gpoints_length1, _tmp1_);
+ gpoints[0] = (_tmp2_.x = margin_left, _tmp2_.y = (height - margin_bottom) / 2, _tmp2_);
+ i = 1;
+ {
+ GList* p_collection;
+ GList* p_it;
+ p_collection = self->priv->points;
+ for (p_it = p_collection; p_it != NULL; p_it = p_it->next) {
+ DeadbeefGraphicPoint* p;
+ p = _deadbeef_graphic_point_ref0 ((DeadbeefGraphicPoint*) p_it->data);
+ {
+ GdkPoint _tmp3_ = {0};
+ gpoints[i] = (deadbeef_graphic_abs_to_screen (self, p->x, p->y, &_tmp3_), _tmp3_);
+ if (gpoints[i].x >= width) {
+ gpoints[i].x = width - 1;
+ }
+ i++;
+ _deadbeef_graphic_point_unref0 (p);
+ }
+ }
+ }
+ gpoints[i] = (_tmp4_.x = width - 1, _tmp4_.y = (height - margin_bottom) / 2, _tmp4_);
+ d = _g_object_ref0 ((GdkDrawable*) gtk_widget_get_window ((GtkWidget*) self));
+ gc = _g_object_ref0 (GDK_DRAWABLE_GET_CLASS (d)->create_gc (d, (_tmp6_ = (memset (&_tmp5_, 0, sizeof (GdkGCValues)), _tmp5_), &_tmp6_), 0));
+ gdk_gc_set_rgb_fg_color (gc, &self->priv->fore_dark_color);
+ step = ((double) (width - margin_left)) / ((double) (bands + 1));
+ {
+ gboolean _tmp7_;
+ i = 0;
+ _tmp7_ = TRUE;
+ while (TRUE) {
+ if (!_tmp7_) {
+ i++;
+ }
+ _tmp7_ = FALSE;
+ if (!(i < bands)) {
+ break;
+ }
+ gdk_draw_line (d, gc, ((gint) ((i + 1) * step)) + margin_left, 0, ((gint) ((i + 1) * step)) + margin_left, height - margin_bottom);
+ }
+ }
+ vstep = (double) (height - margin_bottom);
+ {
+ double di;
+ di = (double) 0;
+ {
+ gboolean _tmp8_;
+ _tmp8_ = TRUE;
+ while (TRUE) {
+ if (!_tmp8_) {
+ di = di + 0.25;
+ }
+ _tmp8_ = FALSE;
+ if (!(di < 2)) {
+ break;
+ }
+ gdk_draw_line (d, gc, margin_left, (gint) ((di - self->priv->preamp) * vstep), width, (gint) ((di - self->priv->preamp) * vstep));
+ }
+ }
+ }
+ gdk_gc_set_rgb_fg_color (gc, &self->priv->fore_bright_color);
+ l = gtk_widget_create_pango_layout ((GtkWidget*) self, NULL);
+ ctx = _g_object_ref0 (pango_layout_get_context (l));
+ fd = _pango_font_description_copy0 (pango_context_get_font_description (ctx));
+ pango_font_description_set_size (fd, 4);
+ pango_font_description_set_family_static (fd, "fixed");
+ pango_context_set_font_description (ctx, fd);
+ {
+ gboolean _tmp9_;
+ i = 0;
+ _tmp9_ = TRUE;
+ while (TRUE) {
+ if (!_tmp9_) {
+ i++;
+ }
+ _tmp9_ = FALSE;
+ if (!(i < bands)) {
+ break;
+ }
+ pango_layout_set_text (l, freqs[i], (gint) g_utf8_strlen (freqs[i], -1));
+ gdk_draw_layout (d, gc, ((gint) (((i + 1) * step) - 5)) + margin_left, (height - margin_bottom) + 2, l);
+ }
+ }
+ pango_layout_set_width (l, margin_left - 1);
+ pango_layout_set_alignment (l, PANGO_ALIGN_RIGHT);
+ if (self->priv->mouse_y != (-1)) {
+ _tmp10_ = self->priv->mouse_y < (height - margin_bottom);
+ } else {
+ _tmp10_ = FALSE;
+ }
+ if (_tmp10_) {
+ double db;
+ char* tmp;
+ db = deadbeef_graphic_scale (self, ((double) (self->priv->mouse_y - 1)) / ((double) ((height - margin_bottom) - 2)));
+ tmp = g_strdup_printf ("%.1f", db);
+ pango_layout_set_text (l, tmp, (gint) g_utf8_strlen (tmp, -1));
+ gdk_draw_layout (d, gc, margin_left - 1, self->priv->mouse_y - 3, l);
+ _g_free0 (tmp);
+ }
+ tmp = g_strdup_printf ("%.1f", deadbeef_graphic_scale (self, (double) 1));
+ pango_layout_set_text (l, tmp, (gint) g_utf8_strlen (tmp, -1));
+ gdk_draw_layout (d, gc, margin_left - 1, (height - margin_bottom) - 6, l);
+ tmp = (_tmp11_ = g_strdup_printf ("%.1f", deadbeef_graphic_scale (self, (double) 0)), _g_free0 (tmp), _tmp11_);
+ pango_layout_set_text (l, tmp, (gint) g_utf8_strlen (tmp, -1));
+ gdk_draw_layout (d, gc, margin_left - 1, 1, l);
+ pango_layout_set_text (l, "0db", 4);
+ gdk_draw_layout (d, gc, margin_left - 1, ((gint) ((1 - self->priv->preamp) * (height - margin_bottom))) - 3, l);
+ pango_layout_set_text (l, "preamp", 6);
+ pango_layout_set_alignment (l, PANGO_ALIGN_LEFT);
+ gdk_draw_layout (d, gc, 1, (height - margin_bottom) + 2, l);
+ gdk_draw_rectangle (d, gc, FALSE, margin_left, 0, (width - margin_left) - 1, (height - margin_bottom) - 1);
+ gdk_gc_set_line_attributes (gc, 2, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
+ gdk_gc_set_clip_rectangle (gc, (_tmp13_ = (_tmp12_.x = 0, _tmp12_.y = (gint) (self->priv->preamp * (height - margin_bottom)), _tmp12_.width = 11, _tmp12_.height = height, _tmp12_), &_tmp13_));
+ gdk_gc_set_rgb_fg_color (gc, &self->priv->fore_dark_color);
+ count = ((gint) ((height - margin_bottom) / 6)) + 1;
+ {
+ gint j;
+ j = 0;
+ {
+ gboolean _tmp14_;
+ _tmp14_ = TRUE;
+ while (TRUE) {
+ if (!_tmp14_) {
+ j++;
+ }
+ _tmp14_ = FALSE;
+ if (!(j < count)) {
+ break;
+ }
+ gdk_draw_rectangle (d, gc, TRUE, 1, ((height - margin_bottom) - (j * 6)) - 6, 11, 4);
+ }
+ }
+ }
+ gdk_gc_set_clip_rectangle (gc, (_tmp16_ = (_tmp15_.x = margin_left + 1, _tmp15_.y = 1, _tmp15_.width = (width - margin_left) - 2, _tmp15_.height = (height - margin_bottom) - 2, _tmp15_), &_tmp16_));
+ gdk_gc_set_rgb_fg_color (gc, &self->priv->fore_dark_color);
+ bar_w = 11;
+ if (step < bar_w) {
+ bar_w = ((gint) step) - 1;
+ }
+ {
+ gboolean _tmp17_;
+ i = 0;
+ _tmp17_ = TRUE;
+ while (TRUE) {
+ GdkRectangle _tmp19_;
+ GdkRectangle _tmp18_ = {0};
+ if (!_tmp17_) {
+ i++;
+ }
+ _tmp17_ = FALSE;
+ if (!(i < bands)) {
+ break;
+ }
+ gdk_gc_set_clip_rectangle (gc, (_tmp19_ = (_tmp18_.x = (((gint) ((i + 1) * step)) + margin_left) - (bar_w / 2), _tmp18_.y = (gint) (self->priv->values[i] * (height - margin_bottom)), _tmp18_.width = 11, _tmp18_.height = height, _tmp18_), &_tmp19_));
+ count = ((gint) (((height - margin_bottom) * (1 - self->priv->values[i])) / 6)) + 1;
+ {
+ gint j;
+ j = 0;
+ {
+ gboolean _tmp20_;
+ _tmp20_ = TRUE;
+ while (TRUE) {
+ if (!_tmp20_) {
+ j++;
+ }
+ _tmp20_ = FALSE;
+ if (!(j < count)) {
+ break;
+ }
+ gdk_draw_rectangle (d, gc, TRUE, (((gint) ((i + 1) * step)) + margin_left) - (bar_w / 2), ((height - margin_bottom) - (j * 6)) - 6, bar_w, 4);
+ }
+ }
+ }
+ }
+ }
+ gdk_gc_set_clip_rectangle (gc, (_tmp22_ = (_tmp21_.x = 0, _tmp21_.y = 0, _tmp21_.width = width, _tmp21_.height = height, _tmp21_), &_tmp22_));
+ gdk_gc_set_rgb_fg_color (gc, &self->priv->fore_bright_color);
+ pcount = g_list_length (self->priv->points);
+ ys = (_tmp23_ = g_new0 (double, pcount), ys_length1 = pcount, _ys_size_ = ys_length1, _tmp23_);
+ xs = (_tmp24_ = g_new0 (double, pcount), xs_length1 = pcount, _xs_size_ = xs_length1, _tmp24_);
+ i = 0;
+ {
+ GList* p_collection;
+ GList* p_it;
+ p_collection = self->priv->points;
+ for (p_it = p_collection; p_it != NULL; p_it = p_it->next) {
+ DeadbeefGraphicPoint* p;
+ p = _deadbeef_graphic_point_ref0 ((DeadbeefGraphicPoint*) p_it->data);
+ {
+ GdkPoint _tmp25_ = {0};
+ gp = (deadbeef_graphic_abs_to_screen (self, p->x, p->y, &_tmp25_), _tmp25_);
+ gdk_draw_rectangle (d, gc, TRUE, gp.x - spot_size, gp.y - spot_size, spot_size * 2, spot_size * 2);
+ xs[i] = p->x;
+ ys[i] = p->y;
+ i++;
+ _deadbeef_graphic_point_unref0 (p);
+ }
+ }
+ }
+ _tmp26_ = NULL;
+ if (self->priv->aa_mode) {
+ cairo_t* _tmp27_;
+ _tmp26_ = (_tmp27_ = gdk_cairo_create (d), _cairo_destroy0 (_tmp26_), _tmp27_);
+ } else {
+ cairo_t* _tmp28_;
+ _tmp26_ = (_tmp28_ = NULL, _cairo_destroy0 (_tmp26_), _tmp28_);
+ }
+ cairo = _cairo_reference0 (_tmp26_);
+ prev_x = 0;
+ prev_y = 0;
+ if (pcount > 0) {
+ GdkPoint _tmp29_ = {0};
+ gp = (deadbeef_graphic_abs_to_screen (self, xs[0], ys[0], &_tmp29_), _tmp29_);
+ if (self->priv->aa_mode) {
+ cairo_move_to (cairo, (double) margin_left, (double) gp.y);
+ } else {
+ gdk_draw_line (d, gc, margin_left, gp.y, gp.x, gp.y);
+ }
+ prev_x = gp.x;
+ prev_y = gp.y;
+ }
+ if (pcount >= 2) {
+ {
+ gboolean _tmp30_;
+ i = 0;
+ _tmp30_ = TRUE;
+ while (TRUE) {
+ double dx;
+ double dy;
+ gint pts;
+ if (!_tmp30_) {
+ i++;
+ }
+ _tmp30_ = FALSE;
+ if (!(i < (pcount - 1))) {
+ break;
+ }
+ if (((gint) ((xs[i + 1] - xs[i]) * width)) <= 5) {
+ GdkPoint _tmp31_ = {0};
+ GdkPoint gp2;
+ GdkPoint _tmp32_ = {0};
+ gp2 = (deadbeef_graphic_abs_to_screen (self, xs[i], ys[i], &_tmp31_), _tmp31_);
+ gp = (deadbeef_graphic_abs_to_screen (self, xs[i + 1], ys[i + 1], &_tmp32_), _tmp32_);
+ gdk_draw_line (d, gc, gp2.x, gp2.y, gp.x, gp.y);
+ prev_x = gp2.x;
+ prev_y = gp2.y;
+ continue;
+ }
+ dx = (xs[i + 1] - xs[i]) * width;
+ dy = (ys[i + 1] - ys[i]) * height;
+ pts = (gint) (sqrt ((dx * dx) + (dy * dy)) / 5.0);
+ step = ((double) (xs[i + 1] - xs[i])) / ((double) pts);
+ {
+ gint ii;
+ ii = 0;
+ {
+ gboolean _tmp33_;
+ _tmp33_ = TRUE;
+ while (TRUE) {
+ double y = 0.0;
+ gboolean _tmp34_ = FALSE;
+ if (!_tmp33_) {
+ ii++;
+ }
+ _tmp33_ = FALSE;
+ if (!(ii <= pts)) {
+ break;
+ }
+ if (i == 0) {
+ _tmp34_ = i == (pcount - 2);
+ } else {
+ _tmp34_ = FALSE;
+ }
+ if (_tmp34_) {
+ y = deadbeef_graphic_cubic (self, ys[0], ys[0], ys[1], ys[1], ((double) ii) / ((double) pts));
+ } else {
+ if (i == 0) {
+ y = deadbeef_graphic_cubic (self, ys[0], ys[0], ys[1], ys[2], ((double) ii) / ((double) pts));
+ } else {
+ if (i == (pcount - 2)) {
+ y = deadbeef_graphic_cubic (self, ys[i - 1], ys[i], ys[i + 1], ys[i + 1], ((double) ii) / ((double) pts));
+ } else {
+ y = deadbeef_graphic_cubic (self, ys[i - 1], ys[i], ys[i + 1], ys[i + 2], ((double) ii) / ((double) pts));
+ }
+ }
+ }
+ if (y < 0) {
+ y = (double) 0;
+ }
+ if (y > 1) {
+ y = (double) 1;
+ }
+ if (self->priv->aa_mode) {
+ double sx = 0.0;
+ double sy = 0.0;
+ deadbeef_graphic_abs_to_screen_d (self, (ii * step) + xs[i], y, &sx, &sy);
+ cairo_line_to (cairo, sx, sy);
+ } else {
+ GdkPoint _tmp35_ = {0};
+ gp = (deadbeef_graphic_abs_to_screen (self, (ii * step) + xs[i], y, &_tmp35_), _tmp35_);
+ if (gp.y < 2) {
+ gp.y = 2;
+ }
+ if (gp.y > ((height - margin_bottom) - 2)) {
+ gp.y = (height - margin_bottom) - 2;
+ }
+ gdk_draw_point (d, gc, gp.x, gp.y);
+ prev_x = gp.x;
+ prev_y = gp.y;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (pcount > 0) {
+ GdkPoint _tmp36_ = {0};
+ gp = (deadbeef_graphic_abs_to_screen (self, xs[pcount - 1], ys[pcount - 1], &_tmp36_), _tmp36_);
+ if (self->priv->aa_mode) {
+ cairo_line_to (cairo, (double) (width - 1), (double) gp.y);
+ } else {
+ gdk_draw_line (d, gc, gp.x, gp.y, width - 1, gp.y);
+ }
+ }
+ if (self->priv->aa_mode) {
+ cairo_set_source_rgb (cairo, ((double) self->priv->fore_bright_color.red) / ((double) 0xffff), ((double) self->priv->fore_bright_color.green) / ((double) 0xffff), ((double) self->priv->fore_bright_color.blue) / ((double) 0xffff));
+ cairo_stroke (cairo);
+ }
+ if (pcount == 0) {
+ gdk_draw_line (d, gc, margin_left, (height - margin_bottom) / 2, width - 1, (height - margin_bottom) / 2);
+ }
+ gdk_gc_set_line_attributes (gc, 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
+ gdk_draw_line (d, gc, margin_left + 1, self->priv->mouse_y, width, self->priv->mouse_y);
+ result = FALSE;
+ gpoints = (g_free (gpoints), NULL);
+ _g_object_unref0 (d);
+ _g_object_unref0 (gc);
+ _g_object_unref0 (l);
+ _g_object_unref0 (ctx);
+ _pango_font_description_free0 (fd);
+ _g_free0 (tmp);
+ ys = (g_free (ys), NULL);
+ xs = (g_free (xs), NULL);
+ _cairo_destroy0 (_tmp26_);
+ _cairo_destroy0 (cairo);
+ return result;
+}
+
+
+static gboolean deadbeef_graphic_get_point_at (DeadbeefGraphic* self, double x, double y) {
+ gboolean result = FALSE;
+ gboolean ret;
+ GList* iter;
+ double ss_x;
+ double ss_y;
+ g_return_val_if_fail (self != NULL, FALSE);
+ ret = FALSE;
+ iter = NULL;
+ ss_x = ((double) spot_size) / ((double) ((GtkWidget*) self)->allocation.width);
+ ss_y = ((double) spot_size) / ((double) ((GtkWidget*) self)->allocation.height);
+ {
+ gboolean _tmp0_;
+ iter = self->priv->points;
+ _tmp0_ = TRUE;
+ while (TRUE) {
+ gboolean _tmp1_ = FALSE;
+ if (!_tmp0_) {
+ iter = iter->next;
+ }
+ _tmp0_ = FALSE;
+ if (!(iter != NULL)) {
+ break;
+ }
+ if (fabs (((DeadbeefGraphicPoint*) iter->data)->x - x) <= ss_x) {
+ _tmp1_ = fabs (((DeadbeefGraphicPoint*) iter->data)->y - y) <= ss_y;
+ } else {
+ _tmp1_ = FALSE;
+ }
+ if (_tmp1_) {
+ self->priv->current_point = iter;
+ ret = TRUE;
+ break;
+ }
+ }
+ }
+ result = ret;
+ return result;
+}
+
+
+static inline double deadbeef_graphic_scale (DeadbeefGraphic* self, double val) {
+ double result = 0.0;
+ double k;
+ double d;
+ g_return_val_if_fail (self != NULL, 0.0);
+ k = (double) (-40);
+ d = (double) 20;
+ result = (((val + self->priv->preamp) - 0.5) * k) + d;
+ return result;
+}
+
+
+static void deadbeef_graphic_recalc_values (DeadbeefGraphic* self) {
+ guint pcount;
+ double* _tmp0_;
+ gint _ys_size_;
+ gint ys_length1;
+ double* ys;
+ double* _tmp1_;
+ gint _xs_size_;
+ gint xs_length1;
+ double* xs;
+ gint i;
+ double* _tmp7_;
+ gint _scaled_values_size_;
+ gint scaled_values_length1;
+ double* scaled_values;
+ g_return_if_fail (self != NULL);
+ pcount = g_list_length (self->priv->points);
+ ys = (_tmp0_ = g_new0 (double, pcount), ys_length1 = pcount, _ys_size_ = ys_length1, _tmp0_);
+ xs = (_tmp1_ = g_new0 (double, pcount), xs_length1 = pcount, _xs_size_ = xs_length1, _tmp1_);
+ i = 0;
+ {
+ GList* p_collection;
+ GList* p_it;
+ p_collection = self->priv->points;
+ for (p_it = p_collection; p_it != NULL; p_it = p_it->next) {
+ DeadbeefGraphicPoint* p;
+ p = _deadbeef_graphic_point_ref0 ((DeadbeefGraphicPoint*) p_it->data);
+ {
+ xs[i] = p->x;
+ ys[i] = p->y;
+ i++;
+ _deadbeef_graphic_point_unref0 (p);
+ }
+ }
+ }
+ if (pcount == 0) {
+ {
+ gboolean _tmp2_;
+ i = 0;
+ _tmp2_ = TRUE;
+ while (TRUE) {
+ if (!_tmp2_) {
+ i++;
+ }
+ _tmp2_ = FALSE;
+ if (!(i < bands)) {
+ break;
+ }
+ self->priv->values[i] = 0.5;
+ }
+ }
+ } else {
+ if (pcount == 1) {
+ {
+ gboolean _tmp3_;
+ i = 0;
+ _tmp3_ = TRUE;
+ while (TRUE) {
+ if (!_tmp3_) {
+ i++;
+ }
+ _tmp3_ = FALSE;
+ if (!(i < bands)) {
+ break;
+ }
+ self->priv->values[i] = ys[0];
+ }
+ }
+ } else {
+ gint pi;
+ pi = 0;
+ {
+ gboolean _tmp4_;
+ i = 0;
+ _tmp4_ = TRUE;
+ while (TRUE) {
+ double x;
+ double y;
+ gboolean _tmp5_ = FALSE;
+ gboolean _tmp6_ = FALSE;
+ if (!_tmp4_) {
+ i++;
+ }
+ _tmp4_ = FALSE;
+ if (!(i < bands)) {
+ break;
+ }
+ x = ((double) (i + 1)) / ((double) (bands + 1));
+ y = (double) 0;
+ if (xs[pi] > x) {
+ self->priv->values[i] = ys[pi];
+ continue;
+ }
+ if (xs[pi + 1] < x) {
+ _tmp5_ = pi < (pcount - 1);
+ } else {
+ _tmp5_ = FALSE;
+ }
+ if (_tmp5_) {
+ pi++;
+ }
+ if (pi == (pcount - 1)) {
+ self->priv->values[i] = ys[pcount - 1];
+ continue;
+ }
+ if (pi == 0) {
+ _tmp6_ = pi == (pcount - 2);
+ } else {
+ _tmp6_ = FALSE;
+ }
+ if (_tmp6_) {
+ y = deadbeef_graphic_cubic (self, ys[pi], ys[pi], ys[pi + 1], ys[pi + 1], (x - xs[pi]) / (xs[pi + 1] - xs[pi]));
+ } else {
+ if (pi == 0) {
+ y = deadbeef_graphic_cubic (self, ys[pi], ys[pi], ys[pi + 1], ys[pi + 2], (x - xs[pi]) / (xs[pi + 1] - xs[pi]));
+ } else {
+ if (pi == (pcount - 2)) {
+ y = deadbeef_graphic_cubic (self, ys[pi - 1], ys[pi], ys[pi + 1], ys[pi + 1], (x - xs[pi]) / (xs[pi + 1] - xs[pi]));
+ } else {
+ y = deadbeef_graphic_cubic (self, ys[pi - 1], ys[pi], ys[pi + 1], ys[pi + 2], (x - xs[pi]) / (xs[pi + 1] - xs[pi]));
+ }
+ }
+ }
+ if (y < 0) {
+ y = (double) 0;
+ }
+ if (y > 1) {
+ y = (double) 1;
+ }
+ self->priv->values[i] = y;
+ }
+ }
+ }
+ }
+ scaled_values = (_tmp7_ = g_new0 (double, bands), scaled_values_length1 = bands, _scaled_values_size_ = scaled_values_length1, _tmp7_);
+ {
+ gboolean _tmp8_;
+ i = 0;
+ _tmp8_ = TRUE;
+ while (TRUE) {
+ if (!_tmp8_) {
+ i++;
+ }
+ _tmp8_ = FALSE;
+ if (!(i < bands)) {
+ break;
+ }
+ scaled_values[i] = deadbeef_graphic_scale (self, self->priv->values[i]);
+ }
+ }
+ g_signal_emit_by_name (self, "on-changed", scaled_values, scaled_values_length1);
+ ys = (g_free (ys), NULL);
+ xs = (g_free (xs), NULL);
+ scaled_values = (g_free (scaled_values), NULL);
+}
+
+
+static void deadbeef_graphic_snap_move (DeadbeefGraphic* self, double x, double y) {
+ double step;
+ gint idx;
+ g_return_if_fail (self != NULL);
+ step = 1.0 / ((double) (bands + 1));
+ idx = (gint) ((x - (step / 2)) / step);
+ if (idx < bands) {
+ self->priv->current_point = g_list_nth (self->priv->points, (guint) idx);
+ ((DeadbeefGraphicPoint*) self->priv->current_point->data)->y = y;
+ }
+}
+
+
+static void deadbeef_graphic_handle_curve_click (DeadbeefGraphic* self, GdkEventButton* event) {
+ double x;
+ double y;
+ g_return_if_fail (self != NULL);
+ x = ((double) ((*event).x - margin_left)) / ((double) (((GtkWidget*) self)->allocation.width - margin_left));
+ y = (*event).y / ((double) (((GtkWidget*) self)->allocation.height - margin_bottom));
+ if ((*event).button == 1) {
+ if (self->priv->snap) {
+ deadbeef_graphic_snap_move (self, x, y);
+ } else {
+ if (!deadbeef_graphic_get_point_at (self, x, y)) {
+ DeadbeefGraphicPoint* point;
+ point = deadbeef_graphic_point_new ();
+ if (self->priv->points == NULL) {
+ self->priv->points = g_list_append (self->priv->points, _deadbeef_graphic_point_ref0 (point));
+ self->priv->current_point = self->priv->points;
+ } else {
+ if (((DeadbeefGraphicPoint*) self->priv->points->data)->x > x) {
+ self->priv->points = g_list_prepend (self->priv->points, _deadbeef_graphic_point_ref0 (point));
+ self->priv->current_point = self->priv->points;
+ } else {
+ gboolean found;
+ found = FALSE;
+ {
+ GList* i;
+ i = self->priv->points;
+ {
+ gboolean _tmp0_;
+ _tmp0_ = TRUE;
+ while (TRUE) {
+ gboolean _tmp1_ = FALSE;
+ if (!_tmp0_) {
+ i = i->next;
+ }
+ _tmp0_ = FALSE;
+ if (!(i->next != NULL)) {
+ break;
+ }
+ if (((DeadbeefGraphicPoint*) i->data)->x < x) {
+ _tmp1_ = ((DeadbeefGraphicPoint*) i->next->data)->x > x;
+ } else {
+ _tmp1_ = FALSE;
+ }
+ if (_tmp1_) {
+ self->priv->points = g_list_insert_before (self->priv->points, i->next, _deadbeef_graphic_point_ref0 (point));
+ self->priv->current_point = i->next;
+ found = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ if (!found) {
+ self->priv->points = g_list_append (self->priv->points, _deadbeef_graphic_point_ref0 (point));
+ self->priv->current_point = g_list_last (self->priv->points);
+ }
+ }
+ }
+ _deadbeef_graphic_point_unref0 (point);
+ }
+ ((DeadbeefGraphicPoint*) self->priv->current_point->data)->x = x;
+ ((DeadbeefGraphicPoint*) self->priv->current_point->data)->y = y;
+ }
+ deadbeef_graphic_recalc_values (self);
+ gdk_window_set_cursor (gtk_widget_get_window ((GtkWidget*) self), self->priv->moving_cursor);
+ gtk_widget_queue_draw ((GtkWidget*) self);
+ } else {
+ if ((*event).button == 3) {
+ if (self->priv->snap) {
+ return;
+ }
+ if (deadbeef_graphic_get_point_at (self, x, y)) {
+ self->priv->points = g_list_remove (self->priv->points, (DeadbeefGraphicPoint*) self->priv->current_point->data);
+ deadbeef_graphic_recalc_values (self);
+ gtk_widget_queue_draw ((GtkWidget*) self);
+ }
+ gtk_widget_queue_draw ((GtkWidget*) self);
+ }
+ }
+}
+
+
+static gboolean deadbeef_graphic_in_curve_area (DeadbeefGraphic* self, gint x, gint y) {
+ gboolean result = FALSE;
+ gboolean _tmp0_ = FALSE;
+ gboolean _tmp1_ = FALSE;
+ gboolean _tmp2_ = FALSE;
+ g_return_val_if_fail (self != NULL, FALSE);
+ if (x > margin_left) {
+ _tmp2_ = x < (((GtkWidget*) self)->allocation.width - 1);
+ } else {
+ _tmp2_ = FALSE;
+ }
+ if (_tmp2_) {
+ _tmp1_ = y > 1;
+ } else {
+ _tmp1_ = FALSE;
+ }
+ if (_tmp1_) {
+ _tmp0_ = y < (((GtkWidget*) self)->allocation.height - margin_bottom);
+ } else {
+ _tmp0_ = FALSE;
+ }
+ result = _tmp0_;
+ return result;
+}
+
+
+static gboolean deadbeef_graphic_real_button_press_event (GtkWidget* base, GdkEventButton* event) {
+ DeadbeefGraphic * self;
+ gboolean result = FALSE;
+ gboolean _tmp0_ = FALSE;
+ gboolean _tmp1_ = FALSE;
+ gboolean _tmp2_ = FALSE;
+ self = (DeadbeefGraphic*) base;
+ if (deadbeef_graphic_in_curve_area (self, (gint) (*event).x, (gint) (*event).y)) {
+ self->priv->curve_hook = TRUE;
+ deadbeef_graphic_handle_curve_click (self, event);
+ result = FALSE;
+ return result;
+ }
+ if ((*event).x <= 11) {
+ _tmp2_ = (*event).y > 1;
+ } else {
+ _tmp2_ = FALSE;
+ }
+ if (_tmp2_) {
+ _tmp1_ = (*event).y <= (((GtkWidget*) self)->allocation.height - margin_bottom);
+ } else {
+ _tmp1_ = FALSE;
+ }
+ if (_tmp1_) {
+ _tmp0_ = (*event).button == 1;
+ } else {
+ _tmp0_ = FALSE;
+ }
+ if (_tmp0_) {
+ self->priv->preamp = (*event).y / ((double) (((GtkWidget*) self)->allocation.height - margin_bottom));
+ self->priv->preamp_hook = TRUE;
+ }
+ if ((*event).button == 3) {
+ gtk_menu_popup (self->priv->menu, NULL, NULL, NULL, NULL, (*event).button, gtk_get_current_event_time ());
+ }
+ result = FALSE;
+ return result;
+}
+
+
+static gboolean deadbeef_graphic_real_button_release_event (GtkWidget* base, GdkEventButton* event) {
+ DeadbeefGraphic * self;
+ gboolean result = FALSE;
+ self = (DeadbeefGraphic*) base;
+ self->priv->curve_hook = FALSE;
+ self->priv->preamp_hook = FALSE;
+ gdk_window_set_cursor (gtk_widget_get_window ((GtkWidget*) self), self->priv->pointer_cursor);
+ result = FALSE;
+ return result;
+}
+
+
+static gboolean deadbeef_graphic_real_leave_notify_event (GtkWidget* base, GdkEventCrossing* event) {
+ DeadbeefGraphic * self;
+ gboolean result = FALSE;
+ self = (DeadbeefGraphic*) base;
+ self->priv->mouse_y = -1;
+ gtk_widget_queue_draw ((GtkWidget*) self);
+ result = FALSE;
+ return result;
+}
+
+
+static gboolean deadbeef_graphic_real_motion_notify_event (GtkWidget* base, GdkEventMotion* event) {
+ DeadbeefGraphic * self;
+ gboolean result = FALSE;
+ double x;
+ double y;
+ self = (DeadbeefGraphic*) base;
+ x = ((double) ((*event).x - margin_left)) / ((double) (((GtkWidget*) self)->allocation.width - margin_left));
+ y = (*event).y / ((double) (((GtkWidget*) self)->allocation.height - margin_bottom));
+ if (y < 0) {
+ y = (double) 0;
+ }
+ if (y > 1) {
+ y = (double) 1;
+ }
+ if (self->priv->preamp_hook) {
+ self->priv->preamp = y;
+ gtk_widget_queue_draw ((GtkWidget*) self);
+ result = FALSE;
+ return result;
+ }
+ if (!deadbeef_graphic_in_curve_area (self, (gint) (*event).x, (gint) (*event).y)) {
+ self->priv->mouse_y = -1;
+ } else {
+ self->priv->mouse_y = (gint) (*event).y;
+ }
+ if (self->priv->curve_hook) {
+ if (self->priv->snap) {
+ deadbeef_graphic_snap_move (self, x, y);
+ } else {
+ gboolean _tmp0_ = FALSE;
+ gboolean _tmp1_ = FALSE;
+ ((DeadbeefGraphicPoint*) self->priv->current_point->data)->x = x;
+ if (self->priv->current_point->prev != NULL) {
+ _tmp0_ = ((DeadbeefGraphicPoint*) self->priv->current_point->prev->data)->x > ((DeadbeefGraphicPoint*) self->priv->current_point->data)->x;
+ } else {
+ _tmp0_ = FALSE;
+ }
+ if (_tmp0_) {
+ ((DeadbeefGraphicPoint*) self->priv->current_point->data)->x = ((DeadbeefGraphicPoint*) self->priv->current_point->prev->data)->x;
+ }
+ if (self->priv->current_point->next != NULL) {
+ _tmp1_ = ((DeadbeefGraphicPoint*) self->priv->current_point->next->data)->x < ((DeadbeefGraphicPoint*) self->priv->current_point->data)->x;
+ } else {
+ _tmp1_ = FALSE;
+ }
+ if (_tmp1_) {
+ ((DeadbeefGraphicPoint*) self->priv->current_point->data)->x = ((DeadbeefGraphicPoint*) self->priv->current_point->next->data)->x;
+ }
+ ((DeadbeefGraphicPoint*) self->priv->current_point->data)->y = y;
+ if (((DeadbeefGraphicPoint*) self->priv->current_point->data)->x > 1) {
+ ((DeadbeefGraphicPoint*) self->priv->current_point->data)->x = (double) 1;
+ }
+ if (((DeadbeefGraphicPoint*) self->priv->current_point->data)->x < 0) {
+ ((DeadbeefGraphicPoint*) self->priv->current_point->data)->x = (double) 0;
+ }
+ }
+ deadbeef_graphic_recalc_values (self);
+ self->priv->mouse_y = (gint) (*event).y;
+ gtk_widget_queue_draw ((GtkWidget*) self);
+ } else {
+ if ((*event).x < 11) {
+ gdk_window_set_cursor (gtk_widget_get_window ((GtkWidget*) self), self->priv->updown_cursor);
+ } else {
+ if (!deadbeef_graphic_get_point_at (self, x, y)) {
+ gdk_window_set_cursor (gtk_widget_get_window ((GtkWidget*) self), self->priv->pointer_cursor);
+ } else {
+ gdk_window_set_cursor (gtk_widget_get_window ((GtkWidget*) self), self->priv->moving_cursor);
+ }
+ }
+ gtk_widget_queue_draw ((GtkWidget*) self);
+ }
+ result = FALSE;
+ return result;
+}
+
+
+DeadbeefGraphic* deadbeef_graphic_construct (GType object_type) {
+ DeadbeefGraphic * self;
+ self = g_object_newv (object_type, 0, NULL);
+ return self;
+}
+
+
+DeadbeefGraphic* deadbeef_graphic_new (void) {
+ return deadbeef_graphic_construct (DEADBEEF_TYPE_GRAPHIC);
+}
+
+
+static void _deadbeef_graphic_aa_mode_changed_gtk_check_menu_item_toggled (GtkCheckMenuItem* _sender, gpointer self) {
+ deadbeef_graphic_aa_mode_changed (self, _sender);
+}
+
+
+static void _deadbeef_graphic_mode_changed_gtk_check_menu_item_toggled (GtkCheckMenuItem* _sender, gpointer self) {
+ deadbeef_graphic_mode_changed (self, _sender);
+}
+
+
+static void _g_slist_free_g_object_unref (GSList* self) {
+ g_slist_foreach (self, (GFunc) g_object_unref, NULL);
+ g_slist_free (self);
+}
+
+
+static GObject * deadbeef_graphic_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties) {
+ GObject * obj;
+ GObjectClass * parent_class;
+ DeadbeefGraphic * self;
+ parent_class = G_OBJECT_CLASS (deadbeef_graphic_parent_class);
+ obj = parent_class->constructor (type, n_construct_properties, construct_properties);
+ self = DEADBEEF_GRAPHIC (obj);
+ {
+ PangoFontDescription* _tmp3_;
+ PangoContext* _tmp4_;
+ GtkMenu* _tmp5_;
+ GtkCheckMenuItem* checkitem;
+ GtkMenuItem* mode_item;
+ GtkMenu* mode_menu;
+ GSList* group;
+ GtkRadioMenuItem* thesame_item;
+ GtkRadioMenuItem* waker_item;
+ gtk_widget_add_events ((GtkWidget*) self, (gint) (((GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK) | GDK_LEAVE_NOTIFY_MASK) | GDK_POINTER_MOTION_MASK));
+ gtk_widget_modify_bg ((GtkWidget*) self, GTK_STATE_NORMAL, &self->priv->back_color);
+ self->priv->font_desc = (_tmp3_ = pango_font_description_from_string ("fixed 4"), _pango_font_description_free0 (self->priv->font_desc), _tmp3_);
+ self->priv->pango_ctx = (_tmp4_ = pango_context_new (), _g_object_unref0 (self->priv->pango_ctx), _tmp4_);
+ pango_context_set_font_description (self->priv->pango_ctx, self->priv->font_desc);
+ deadbeef_graphic_recalc_values (self);
+ self->priv->preamp = 0.5;
+ self->priv->menu = (_tmp5_ = g_object_ref_sink ((GtkMenu*) gtk_menu_new ()), _g_object_unref0 (self->priv->menu), _tmp5_);
+ checkitem = g_object_ref_sink ((GtkCheckMenuItem*) gtk_check_menu_item_new_with_label ("Antialiasing"));
+ gtk_widget_show ((GtkWidget*) checkitem);
+ g_signal_connect_object (checkitem, "toggled", (GCallback) _deadbeef_graphic_aa_mode_changed_gtk_check_menu_item_toggled, self, 0);
+ gtk_menu_shell_append ((GtkMenuShell*) self->priv->menu, (GtkWidget*) ((GtkMenuItem*) checkitem));
+ mode_item = g_object_ref_sink ((GtkMenuItem*) gtk_menu_item_new ());
+ gtk_widget_show ((GtkWidget*) mode_item);
+ gtk_menu_item_set_label (mode_item, "mode");
+ gtk_menu_shell_append ((GtkMenuShell*) self->priv->menu, (GtkWidget*) mode_item);
+ mode_menu = g_object_ref_sink ((GtkMenu*) gtk_menu_new ());
+ group = NULL;
+ thesame_item = g_object_ref_sink ((GtkRadioMenuItem*) gtk_radio_menu_item_new_with_label (group, "thesame"));
+ gtk_widget_show ((GtkWidget*) thesame_item);
+ gtk_menu_shell_append ((GtkMenuShell*) mode_menu, (GtkWidget*) ((GtkMenuItem*) thesame_item));
+ waker_item = g_object_ref_sink ((GtkRadioMenuItem*) gtk_radio_menu_item_new_with_label_from_widget (thesame_item, "waker"));
+ gtk_widget_show ((GtkWidget*) waker_item);
+ g_signal_connect_object ((GtkCheckMenuItem*) waker_item, "toggled", (GCallback) _deadbeef_graphic_mode_changed_gtk_check_menu_item_toggled, self, 0);
+ gtk_menu_shell_append ((GtkMenuShell*) mode_menu, (GtkWidget*) ((GtkMenuItem*) waker_item));
+ gtk_menu_item_set_submenu (mode_item, (GtkWidget*) mode_menu);
+ _g_object_unref0 (checkitem);
+ _g_object_unref0 (mode_item);
+ _g_object_unref0 (mode_menu);
+ __g_slist_free_g_object_unref0 (group);
+ _g_object_unref0 (thesame_item);
+ _g_object_unref0 (waker_item);
+ }
+ return obj;
+}
+
+
+static DeadbeefGraphicPoint* deadbeef_graphic_point_construct (GType object_type) {
+ DeadbeefGraphicPoint* self;
+ self = (DeadbeefGraphicPoint*) g_type_create_instance (object_type);
+ return self;
+}
+
+
+static DeadbeefGraphicPoint* deadbeef_graphic_point_new (void) {
+ return deadbeef_graphic_point_construct (DEADBEEF_GRAPHIC_TYPE_POINT);
+}
+
+
+static void deadbeef_graphic_value_point_init (GValue* value) {
+ value->data[0].v_pointer = NULL;
+}
+
+
+static void deadbeef_graphic_value_point_free_value (GValue* value) {
+ if (value->data[0].v_pointer) {
+ deadbeef_graphic_point_unref (value->data[0].v_pointer);
+ }
+}
+
+
+static void deadbeef_graphic_value_point_copy_value (const GValue* src_value, GValue* dest_value) {
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = deadbeef_graphic_point_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
+}
+
+
+static gpointer deadbeef_graphic_value_point_peek_pointer (const GValue* value) {
+ return value->data[0].v_pointer;
+}
+
+
+static gchar* deadbeef_graphic_value_point_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ if (collect_values[0].v_pointer) {
+ DeadbeefGraphicPoint* object;
+ object = collect_values[0].v_pointer;
+ if (object->parent_instance.g_class == NULL) {
+ return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
+ } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) {
+ return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
+ }
+ value->data[0].v_pointer = deadbeef_graphic_point_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
+}
+
+
+static gchar* deadbeef_graphic_value_point_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ DeadbeefGraphicPoint** object_p;
+ object_p = collect_values[0].v_pointer;
+ if (!object_p) {
+ return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
+ }
+ if (!value->data[0].v_pointer) {
+ *object_p = NULL;
+ } else if (collect_flags && G_VALUE_NOCOPY_CONTENTS) {
+ *object_p = value->data[0].v_pointer;
+ } else {
+ *object_p = deadbeef_graphic_point_ref (value->data[0].v_pointer);
+ }
+ return NULL;
+}
+
+
+static GParamSpec* deadbeef_graphic_param_spec_point (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
+ DeadbeefGraphicParamSpecPoint* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, DEADBEEF_GRAPHIC_TYPE_POINT), NULL);
+ spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
+ G_PARAM_SPEC (spec)->value_type = object_type;
+ return G_PARAM_SPEC (spec);
+}
+
+
+static gpointer deadbeef_graphic_value_get_point (const GValue* value) {
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, DEADBEEF_GRAPHIC_TYPE_POINT), NULL);
+ return value->data[0].v_pointer;
+}
+
+
+static void deadbeef_graphic_value_set_point (GValue* value, gpointer v_object) {
+ DeadbeefGraphicPoint* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, DEADBEEF_GRAPHIC_TYPE_POINT));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, DEADBEEF_GRAPHIC_TYPE_POINT));
+ g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
+ value->data[0].v_pointer = v_object;
+ deadbeef_graphic_point_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ deadbeef_graphic_point_unref (old);
+ }
+}
+
+
+static void deadbeef_graphic_value_take_point (GValue* value, gpointer v_object) {
+ DeadbeefGraphicPoint* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, DEADBEEF_GRAPHIC_TYPE_POINT));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, DEADBEEF_GRAPHIC_TYPE_POINT));
+ g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
+ value->data[0].v_pointer = v_object;
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ deadbeef_graphic_point_unref (old);
+ }
+}
+
+
+static void deadbeef_graphic_point_class_init (DeadbeefGraphicPointClass * klass) {
+ deadbeef_graphic_point_parent_class = g_type_class_peek_parent (klass);
+ DEADBEEF_GRAPHIC_POINT_CLASS (klass)->finalize = deadbeef_graphic_point_finalize;
+}
+
+
+static void deadbeef_graphic_point_instance_init (DeadbeefGraphicPoint * self) {
+ self->ref_count = 1;
+}
+
+
+static void deadbeef_graphic_point_finalize (DeadbeefGraphicPoint* obj) {
+ DeadbeefGraphicPoint * self;
+ self = DEADBEEF_GRAPHIC_POINT (obj);
+}
+
+
+static GType deadbeef_graphic_point_get_type (void) {
+ static volatile gsize deadbeef_graphic_point_type_id__volatile = 0;
+ if (g_once_init_enter (&deadbeef_graphic_point_type_id__volatile)) {
+ static const GTypeValueTable g_define_type_value_table = { deadbeef_graphic_value_point_init, deadbeef_graphic_value_point_free_value, deadbeef_graphic_value_point_copy_value, deadbeef_graphic_value_point_peek_pointer, "p", deadbeef_graphic_value_point_collect_value, "p", deadbeef_graphic_value_point_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (DeadbeefGraphicPointClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) deadbeef_graphic_point_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (DeadbeefGraphicPoint), 0, (GInstanceInitFunc) deadbeef_graphic_point_instance_init, &g_define_type_value_table };
+ static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };
+ GType deadbeef_graphic_point_type_id;
+ deadbeef_graphic_point_type_id = g_type_register_fundamental (g_type_fundamental_next (), "DeadbeefGraphicPoint", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ g_once_init_leave (&deadbeef_graphic_point_type_id__volatile, deadbeef_graphic_point_type_id);
+ }
+ return deadbeef_graphic_point_type_id__volatile;
+}
+
+
+static gpointer deadbeef_graphic_point_ref (gpointer instance) {
+ DeadbeefGraphicPoint* self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
+}
+
+
+static void deadbeef_graphic_point_unref (gpointer instance) {
+ DeadbeefGraphicPoint* self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ DEADBEEF_GRAPHIC_POINT_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
+}
+
+
+static void deadbeef_graphic_class_init (DeadbeefGraphicClass * klass) {
+ deadbeef_graphic_parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (DeadbeefGraphicPrivate));
+ GTK_WIDGET_CLASS (klass)->expose_event = deadbeef_graphic_real_expose_event;
+ GTK_WIDGET_CLASS (klass)->button_press_event = deadbeef_graphic_real_button_press_event;
+ GTK_WIDGET_CLASS (klass)->button_release_event = deadbeef_graphic_real_button_release_event;
+ GTK_WIDGET_CLASS (klass)->leave_notify_event = deadbeef_graphic_real_leave_notify_event;
+ GTK_WIDGET_CLASS (klass)->motion_notify_event = deadbeef_graphic_real_motion_notify_event;
+ G_OBJECT_CLASS (klass)->constructor = deadbeef_graphic_constructor;
+ G_OBJECT_CLASS (klass)->finalize = deadbeef_graphic_finalize;
+ g_signal_new ("on_changed", DEADBEEF_TYPE_GRAPHIC, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__POINTER_INT, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_INT);
+}
+
+
+static void deadbeef_graphic_instance_init (DeadbeefGraphic * self) {
+ GdkColor _tmp0_ = {0};
+ GdkColor _tmp1_ = {0};
+ GdkColor _tmp2_ = {0};
+ self->priv = DEADBEEF_GRAPHIC_GET_PRIVATE (self);
+ self->priv->points = NULL;
+ self->priv->current_point = NULL;
+ self->priv->back_color = (memset (&_tmp0_, 0, sizeof (GdkColor)), _tmp0_.red = (guint16) 0, _tmp0_.green = (guint16) 0, _tmp0_.blue = (guint16) 0, _tmp0_);
+ self->priv->fore_bright_color = (memset (&_tmp1_, 0, sizeof (GdkColor)), _tmp1_.red = (guint16) 0xffff, _tmp1_.green = (guint16) 0x7e00, _tmp1_.blue = (guint16) 0, _tmp1_);
+ self->priv->fore_dark_color = (memset (&_tmp2_, 0, sizeof (GdkColor)), _tmp2_.red = (guint16) 0x7800, _tmp2_.green = (guint16) 0x3b00, _tmp2_.blue = (guint16) 0, _tmp2_);
+ self->priv->values = g_new0 (double, bands);
+ self->priv->values_length1 = bands;
+ self->priv->_values_size_ = self->priv->values_length1;
+ self->priv->snap = FALSE;
+ self->priv->aa_mode = FALSE;
+ self->priv->curve_hook = FALSE;
+ self->priv->preamp_hook = FALSE;
+ self->priv->menu = NULL;
+ self->priv->moving_cursor = gdk_cursor_new (GDK_FLEUR);
+ self->priv->updown_cursor = gdk_cursor_new (GDK_DOUBLE_ARROW);
+ self->priv->pointer_cursor = gdk_cursor_new (GDK_LEFT_PTR);
+}
+
+
+static void deadbeef_graphic_finalize (GObject* obj) {
+ DeadbeefGraphic * self;
+ self = DEADBEEF_GRAPHIC (obj);
+ __g_list_free_deadbeef_graphic_point_unref0 (self->priv->points);
+ _g_object_unref0 (self->priv->pango_ctx);
+ _pango_font_description_free0 (self->priv->font_desc);
+ self->priv->values = (g_free (self->priv->values), NULL);
+ _g_object_unref0 (self->priv->menu);
+ _gdk_cursor_unref0 (self->priv->moving_cursor);
+ _gdk_cursor_unref0 (self->priv->updown_cursor);
+ _gdk_cursor_unref0 (self->priv->pointer_cursor);
+ G_OBJECT_CLASS (deadbeef_graphic_parent_class)->finalize (obj);
+}
+
+
+GType deadbeef_graphic_get_type (void) {
+ static volatile gsize deadbeef_graphic_type_id__volatile = 0;
+ if (g_once_init_enter (&deadbeef_graphic_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (DeadbeefGraphicClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) deadbeef_graphic_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (DeadbeefGraphic), 0, (GInstanceInitFunc) deadbeef_graphic_instance_init, NULL };
+ GType deadbeef_graphic_type_id;
+ deadbeef_graphic_type_id = g_type_register_static (GTK_TYPE_DRAWING_AREA, "DeadbeefGraphic", &g_define_type_info, 0);
+ g_once_init_leave (&deadbeef_graphic_type_id__volatile, deadbeef_graphic_type_id);
+ }
+ return deadbeef_graphic_type_id__volatile;
+}
+
+
+
+static void g_cclosure_user_marshal_VOID__POINTER_INT (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) {
+ typedef void (*GMarshalFunc_VOID__POINTER_INT) (gpointer data1, gpointer arg_1, gint arg_2, gpointer data2);
+ register GMarshalFunc_VOID__POINTER_INT callback;
+ register GCClosure * cc;
+ register gpointer data1, data2;
+ cc = (GCClosure *) closure;
+ g_return_if_fail (n_param_values == 3);
+ if (G_CCLOSURE_SWAP_DATA (closure)) {
+ data1 = closure->data;
+ data2 = param_values->data[0].v_pointer;
+ } else {
+ data1 = param_values->data[0].v_pointer;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__POINTER_INT) (marshal_data ? marshal_data : cc->callback);
+ callback (data1, g_value_get_pointer (param_values + 1), g_value_get_int (param_values + 2), data2);
+}
+
+
+
diff --git a/plugins/gtkui/graphic.h b/plugins/gtkui/graphic.h
new file mode 100644
index 00000000..6d588801
--- /dev/null
+++ b/plugins/gtkui/graphic.h
@@ -0,0 +1,44 @@
+/* graphic.h generated by valac, the Vala compiler, do not modify */
+
+
+#ifndef __GRAPHIC_H__
+#define __GRAPHIC_H__
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+
+#define DEADBEEF_TYPE_GRAPHIC (deadbeef_graphic_get_type ())
+#define DEADBEEF_GRAPHIC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DEADBEEF_TYPE_GRAPHIC, DeadbeefGraphic))
+#define DEADBEEF_GRAPHIC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DEADBEEF_TYPE_GRAPHIC, DeadbeefGraphicClass))
+#define DEADBEEF_IS_GRAPHIC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DEADBEEF_TYPE_GRAPHIC))
+#define DEADBEEF_IS_GRAPHIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DEADBEEF_TYPE_GRAPHIC))
+#define DEADBEEF_GRAPHIC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DEADBEEF_TYPE_GRAPHIC, DeadbeefGraphicClass))
+
+typedef struct _DeadbeefGraphic DeadbeefGraphic;
+typedef struct _DeadbeefGraphicClass DeadbeefGraphicClass;
+typedef struct _DeadbeefGraphicPrivate DeadbeefGraphicPrivate;
+
+struct _DeadbeefGraphic {
+ GtkDrawingArea parent_instance;
+ DeadbeefGraphicPrivate * priv;
+};
+
+struct _DeadbeefGraphicClass {
+ GtkDrawingAreaClass parent_class;
+};
+
+
+GType deadbeef_graphic_get_type (void);
+extern DeadbeefGraphic* deadbeef_graphic_inst;
+void deadbeef_graphic_aa_mode_changed (DeadbeefGraphic* self, GtkCheckMenuItem* item);
+void deadbeef_graphic_mode_changed (DeadbeefGraphic* self, GtkCheckMenuItem* item);
+DeadbeefGraphic* deadbeef_graphic_new (void);
+DeadbeefGraphic* deadbeef_graphic_construct (GType object_type);
+
+
+G_END_DECLS
+
+#endif
diff --git a/plugins/gtkui/graphic.vala b/plugins/gtkui/graphic.vala
new file mode 100644
index 00000000..d2cb1727
--- /dev/null
+++ b/plugins/gtkui/graphic.vala
@@ -0,0 +1,737 @@
+static const int spot_size = 3;
+static const int margin_left = 35;
+static const int margin_bottom = 10;
+static const int bands = 18;
+static int btn_size = 7;
+
+const string[] freqs = {
+ "32","80","110","160","220","315","450","630","900",
+ "1.3k","1.8k","2.5k","3.6k","5k","7k","10k","14k","20k"
+};
+
+namespace Deadbeef {
+ public class Graphic : Gtk.DrawingArea
+ {
+ public signal void on_changed (double[] values);
+
+ class Point
+ {
+ public double x;
+ public double y;
+ }
+
+ private List <Point> points = new List <Point> ();
+ private unowned List <Point> current_point = null;
+
+ private Gdk.Color back_color = Gdk.Color() {red = 0, green = 0, blue = 0};
+ private Gdk.Color fore_bright_color = Gdk.Color() {red = 0xffff, green = 0x7e00, blue = 0};
+ private Gdk.Color fore_dark_color = Gdk.Color() {red = 0x7800, green = 0x3b00, blue = 0};
+
+ private Pango.Context pango_ctx;
+ private Pango.FontDescription font_desc;
+
+ private double[] values = new double [bands];
+ private double preamp;
+
+ private int mouse_y;
+
+ private bool snap = false;
+ private bool aa_mode = false;
+
+ private bool curve_hook = false;
+ private bool preamp_hook = false;
+
+ private Gtk.Menu menu = null;
+
+ Gdk.Cursor moving_cursor = new Gdk.Cursor (Gdk.CursorType.FLEUR);
+ Gdk.Cursor updown_cursor = new Gdk.Cursor (Gdk.CursorType.DOUBLE_ARROW);
+ Gdk.Cursor pointer_cursor = new Gdk.Cursor (Gdk.CursorType.LEFT_PTR);
+
+ //public Graphic ()
+ construct
+ {
+ add_events (Gdk.EventMask.BUTTON_PRESS_MASK
+ | Gdk.EventMask.BUTTON_RELEASE_MASK
+ | Gdk.EventMask.LEAVE_NOTIFY_MASK
+ | Gdk.EventMask.POINTER_MOTION_MASK);
+
+ modify_bg (Gtk.StateType.NORMAL, back_color);
+
+ font_desc = Pango.FontDescription.from_string ("fixed 4");
+ pango_ctx = new Pango.Context();
+ pango_ctx.set_font_description (font_desc);
+ recalc_values();
+ preamp = 0.5;
+
+ menu = new Gtk.Menu ();
+
+ var checkitem = new Gtk.CheckMenuItem.with_label ("Antialiasing");
+ checkitem.show();
+ checkitem.toggled.connect (aa_mode_changed);
+ menu.append (checkitem);
+
+ var mode_item = new Gtk.MenuItem();
+ mode_item.show ();
+ mode_item.label = "mode";
+ menu.append (mode_item);
+
+ var mode_menu = new Gtk.Menu ();
+
+ var group = new GLib.SList <Gtk.RadioMenuItem> ();
+
+ var thesame_item = new Gtk.RadioMenuItem.with_label (group, "thesame");
+ thesame_item.show();
+ mode_menu.append (thesame_item);
+
+ var waker_item = new Gtk.RadioMenuItem.with_label_from_widget (thesame_item, "waker");
+ waker_item.show();
+ waker_item.toggled.connect (mode_changed);
+ mode_menu.append (waker_item);
+
+ mode_item.set_submenu (mode_menu);
+ }
+
+ public void
+ aa_mode_changed (Gtk.CheckMenuItem item)
+ {
+ aa_mode = item.active;
+ queue_draw ();
+ }
+
+ public void
+ mode_changed (Gtk.CheckMenuItem item)
+ {
+ set_snap (item.active);
+ }
+
+ private void
+ set_snap (bool new_snap)
+ {
+ snap = new_snap;
+
+ if (snap)
+ {
+ double step = 1.0 / (double)(bands+1);
+
+ if (points.length() > 0)
+ {
+ unowned List <Point> iter;
+ for (iter = points.next; iter != null; iter = iter.next)
+ points.remove_link (iter.prev);
+ points.remove_link (points);
+ }
+
+ for (int i = 0; i < bands; i++)
+ {
+ Point point = new Point ();
+ point.x = ((double)i+1)*step;
+ point.y = values[i];
+ points.prepend (point);
+ }
+ points.reverse ();
+ }
+ }
+
+ private Gdk.Point
+ abs_to_screen (double x, double y)
+ {
+ return Gdk.Point () {
+ x = (int)(x * (this.allocation.width-margin_left))+margin_left,
+ y = (int)(y * (this.allocation.height-margin_bottom))
+ };
+ }
+
+ private void
+ abs_to_screen_d (double x, double y, out double sx, out double sy)
+ {
+ sx = (int)(x * (this.allocation.width-margin_left))+margin_left;
+ sy = (int)(y * (this.allocation.height-margin_bottom));
+ }
+
+/* private double
+ cubic (double y0, double y1, double y2, double y3, double mu)
+ {
+ double a0,a1,a2,a3,mu2;
+
+ mu2 = mu*mu;
+ a0 = y3 - y2 - y0 + y1;
+ a1 = y0 - y1 - a0;
+ a2 = y2 - y0;
+ a3 = y1;
+
+ return (a0*mu*mu2+a1*mu2+a2*mu+a3);
+ }*/
+
+ private double
+ cubic (double y0, double y1, double y2, double y3, double mu)
+ {
+ return 0.5 *((2 * y1) +
+ (-y0 + y2) * mu +
+ (2*y0 - 5*y1 + 4*y2 - y3) * mu*mu +
+ (-y0 + 3*y1- 3*y2 + y3) * mu*mu*mu);
+ }
+
+ public override bool
+ expose_event (Gdk.EventExpose event)
+ {
+ int width = this.allocation.width;
+ int height = this.allocation.height;
+
+ Gdk.Point[] gpoints = new Gdk.Point [points.length()+2];
+ gpoints[0] = {margin_left, (height-margin_bottom) / 2};
+ int i = 1;
+ foreach (var p in this.points)
+ {
+ gpoints[i] = abs_to_screen (p.x, p.y);
+ if (gpoints[i].x >= width)
+ gpoints[i].x = width - 1;
+ i++;
+ }
+ gpoints[i] = {width-1, (height-margin_bottom) / 2};
+
+ Gdk.Drawable d = get_window();
+ var gc = d.create_gc (Gdk.GCValues(), 0);
+
+ gc.set_rgb_fg_color (fore_dark_color);
+ //drawing grid:
+ double step = (double)(width - margin_left) / (double)(bands+1);
+ for (i = 0; i < bands; i++)
+ {
+ //does anyone know why this method is static?
+ Gdk.draw_line (d, gc,
+ (int)((i+1)*step)+margin_left,
+ 0,
+ (int)((i+1)*step)+margin_left,
+ height - margin_bottom);
+ }
+
+ //double vstep = 1.0 / (double)(height-margin_bottom);
+ double vstep = (double)(height-margin_bottom);
+ for (double di=0; di < 2; di += 0.25)
+ {
+ Gdk.draw_line (d, gc,
+ margin_left,
+ (int)((di-preamp)*vstep),
+ width,
+ (int)((di-preamp)*vstep));
+ }
+
+ gc.set_rgb_fg_color (fore_bright_color);
+
+ //drawing freqs:
+ Pango.Layout l = create_pango_layout (null);
+ var ctx = l.get_context ();
+ var fd = ctx.get_font_description ();
+ fd.set_size (4);
+ fd.set_family_static ("fixed");
+ ctx.set_font_description (fd);
+ for (i = 0; i < bands; i++)
+ {
+ l.set_text (freqs[i], (int)freqs[i].len());
+ Gdk.draw_layout (d, gc, (int)((i+1)*step-5)+margin_left, height-margin_bottom+2, l);
+ }
+
+ //drawing db's:
+ l.set_width (margin_left-1);
+ l.set_alignment (Pango.Alignment.RIGHT);
+
+ if ((mouse_y != -1) && (mouse_y < height - margin_bottom))
+ {
+ double db = scale((double)(mouse_y-1) / (double)(height - margin_bottom - 2));
+ string tmp = "%.1f".printf (db);
+ l.set_text (tmp, (int)tmp.len());
+ Gdk.draw_layout (d, gc, margin_left-1, mouse_y-3, l);
+ }
+
+ string tmp = "%.1f".printf (scale (1));
+ l.set_text (tmp, (int)tmp.len());
+ Gdk.draw_layout (d, gc, margin_left-1, height-margin_bottom-6, l);
+
+ tmp = "%.1f".printf (scale (0));
+ l.set_text (tmp, (int)tmp.len());
+ Gdk.draw_layout (d, gc, margin_left-1, 1, l);
+
+ l.set_text ("0db", 4);
+ Gdk.draw_layout (d, gc, margin_left-1, (int)((1-preamp)*(height-margin_bottom))-3, l);
+
+ l.set_text ("preamp", 6);
+ l.set_alignment (Pango.Alignment.LEFT);
+ Gdk.draw_layout (d, gc, 1, height-margin_bottom+2, l);
+
+ d.draw_rectangle (gc, false, margin_left, 0, width-margin_left-1, height-margin_bottom-1);
+ gc.set_line_attributes (2, Gdk.LineStyle.SOLID, Gdk.CapStyle.NOT_LAST, Gdk.JoinStyle.MITER);
+
+ //draw preamp
+ gc.set_clip_rectangle ({0, (int)(preamp * (height-margin_bottom)), 11, height});
+
+ gc.set_rgb_fg_color (fore_dark_color);
+ int count = (int)((height-margin_bottom) / 6)+1;
+ for (int j = 0; j < count; j++)
+ d.draw_rectangle (
+ gc,
+ true,
+ 1,
+ height-margin_bottom-j*6 - 6,
+ 11,
+ 4);
+
+ gc.set_clip_rectangle ({margin_left+1, 1, width-margin_left-2, height-margin_bottom-2});
+
+ //drawing bars:
+ gc.set_rgb_fg_color (fore_dark_color);
+
+ int bar_w = 11;
+ if (step < bar_w)
+ bar_w = (int)step-1;
+
+
+ for (i = 0; i < bands; i++)
+ {
+ gc.set_clip_rectangle ({
+ (int)((i+1)*step)+margin_left - bar_w/2,
+ (int)(values[i] * (height-margin_bottom)),
+ 11,
+ height});
+ count = (int)((height-margin_bottom) * (1-values[i]) / 6)+1;
+ for (int j = 0; j < count; j++)
+ d.draw_rectangle (
+ gc,
+ true,
+ (int)((i+1)*step)+margin_left - bar_w/2,
+ height-margin_bottom-j*6 - 6,
+ bar_w,
+ 4);
+ }
+ gc.set_clip_rectangle ({0, 0, width, height});
+
+ //drawing curve:
+ gc.set_rgb_fg_color (fore_bright_color);
+ Gdk.Point gp;
+ uint pcount = points.length();
+ double[] ys = new double [pcount];
+ double[] xs = new double [pcount];
+ i=0;
+ foreach (var p in this.points)
+ {
+ gp = abs_to_screen (p.x, p.y);
+ d.draw_rectangle (gc, true, gp.x-spot_size, gp.y-spot_size, spot_size*2, spot_size*2);
+ xs[i] = p.x;
+ ys[i] = p.y;
+ i++;
+ }
+
+ Cairo.Context cairo = aa_mode ? Gdk.cairo_create (d) : null;
+
+ int prev_x = 0;
+ int prev_y = 0;
+
+ if (pcount > 0)
+ {
+ gp = abs_to_screen (xs[0], ys[0]);
+ if (aa_mode)
+ cairo.move_to (margin_left, gp.y);
+ else
+ Gdk.draw_line (d, gc, margin_left, gp.y, gp.x, gp.y);
+ prev_x = gp.x;
+ prev_y = gp.y;
+ }
+
+ if (pcount >= 2)
+ {
+ for (i = 0; i < pcount-1; i++)
+ {
+ //stdout.printf ("%d\n", (int)((xs[i+1]-xs[i])*width));
+ if ((int)((xs[i+1]-xs[i])*width) <= 5)
+ {
+ Gdk.Point gp2 = abs_to_screen (xs[i], ys[i]);
+ gp = abs_to_screen (xs[i+1], ys[i+1]);
+ Gdk.draw_line (d, gc, gp2.x, gp2.y, gp.x, gp.y);
+ prev_x = gp2.x;
+ prev_y = gp2.y;
+ continue;
+ }
+ //int pts = (int)((double)((xs[i+1] - xs[i]) * allocation.width) / 5.0);
+ //step = (double)(xs[i+1] - xs[i])/(double)pts;
+
+ double dx = (xs[i+1] - xs[i])*width;
+ double dy = (ys[i+1] - ys[i])*height;
+ int pts = (int)(GLib.Math.sqrt (dx*dx + dy*dy) / 5.0);
+ //stdout.printf ("%f %f %d\n", dx, dy, pts);
+ step = (double)(xs[i+1] - xs[i])/(double)pts;
+
+ for (int ii = 0; ii <= pts; ii++)
+ {
+ double y;
+
+ if (i == 0 && i == pcount-2) //case when we have only two points
+ y = cubic (ys[0], ys[0], ys[1], ys[1], (double)ii/(double)pts);
+
+ else if (i == 0)
+ y = cubic (ys[0], ys[0], ys[1], ys[2], (double)ii/(double)pts);
+
+ else if (i == pcount-2)
+ y = cubic (ys[i-1], ys[i], ys[i+1], ys[i+1], (double)ii/(double)pts);
+
+ else
+ y = cubic (ys[i-1], ys[i], ys[i+1], ys[i+2], (double)ii/(double)pts);
+ if (y < 0) y = 0;
+ if (y > 1) y = 1;
+
+ if (aa_mode)
+ {
+ double sx, sy;
+ abs_to_screen_d (ii*step+xs[i], y, out sx, out sy);
+ cairo.line_to (sx, sy);
+// prev_x = gp.x;
+// prev_y = gp.y;
+ }
+ else
+ {
+ gp = abs_to_screen (ii*step+xs[i], y);
+
+ if (gp.y < 2) gp.y = 2;
+ if (gp.y > height-margin_bottom-2) gp.y = height-margin_bottom-2;
+
+ Gdk.draw_point (d, gc, gp.x, gp.y);
+ //Gdk.draw_line (d, gc, prev_x, prev_y, gp.x, gp.y);
+ prev_x = gp.x;
+ prev_y = gp.y;
+ }
+ }
+ }
+ }
+ if (pcount > 0)
+ {
+// gp = abs_to_screen (xs[0], ys[0]);
+// cairo.move_to (margin_left, gp.y);
+// Gdk.draw_line (d, gc, margin_left, gp.y, gp.x, gp.y);
+
+ gp = abs_to_screen (xs[pcount-1], ys[pcount-1]);
+ if (aa_mode)
+ cairo.line_to (width-1, gp.y);
+ else
+ Gdk.draw_line (d, gc, gp.x, gp.y, width-1, gp.y);
+ }
+ if (aa_mode)
+ {
+ cairo.set_source_rgb (
+ (double)fore_bright_color.red / (double)0xffff,
+ (double)fore_bright_color.green / (double)0xffff,
+ (double)fore_bright_color.blue / (double)0xffff);
+ cairo.stroke();
+ }
+ if (pcount == 0)
+ {
+ Gdk.draw_line (d, gc, margin_left, (height-margin_bottom)/2, width-1, (height-margin_bottom)/2);
+ }
+
+ //drawing mouse coordinates:
+ gc.set_line_attributes (1, Gdk.LineStyle.ON_OFF_DASH, Gdk.CapStyle.NOT_LAST, Gdk.JoinStyle.MITER);
+ Gdk.draw_line (d, gc, margin_left+1, mouse_y, width, mouse_y);
+
+ return false;
+ }
+
+ //FIXME: I'm not sure returning value thru instance property is good
+ private bool
+ get_point_at (double x, double y)
+ {
+ bool ret = false;
+
+ unowned List <Point> iter;
+
+ double ss_x = (double)spot_size / (double)allocation.width;
+ double ss_y = (double)spot_size / (double)allocation.height;
+
+ for (iter = points; iter != null; iter = iter.next)
+ {
+ if (GLib.Math.fabs (iter.data.x - x) <= ss_x &&
+ GLib.Math.fabs (iter.data.y - y) <= ss_y)
+ {
+ current_point = iter;
+ ret = true;
+ break;
+ }
+ }
+ return ret;
+ }
+
+ private inline double
+ scale (double val)
+ {
+ double k = -40;
+ double d = 20;
+ return (val+preamp-0.5) * k + d;
+ }
+
+ private void
+ recalc_values ()
+ {
+ uint pcount = points.length();
+ double[] ys = new double [pcount];
+ double[] xs = new double [pcount];
+ int i=0;
+ foreach (var p in this.points)
+ {
+ xs[i] = p.x;
+ ys[i] = p.y;
+ i++;
+ }
+
+ if (pcount == 0)
+ {
+ for (i=0; i < bands; i++)
+ values[i] = 0.5;
+ }
+ else if (pcount == 1)
+ {
+ for (i=0; i < bands; i++)
+ values[i] = ys[0];
+ }
+ else
+ {
+ int pi = 0;
+ for (i = 0; i < bands; i++)
+ {
+ double x = (double)(i+1)/(double)(bands+1);
+ double y = 0;
+
+ if (xs[pi] > x) //before first point
+ {
+ values[i] = ys[pi];
+ continue;
+ }
+
+ if ((xs[pi+1] < x) && (pi < pcount-1)) //passed to next point
+ pi++;
+
+ if (pi == pcount-1) //after last point
+ {
+ values[i] = ys[pcount-1];
+ continue;
+ }
+
+ if (pi == 0 && pi == pcount-2) //two-points case
+ y = cubic (ys[pi], ys[pi], ys[pi+1], ys[pi+1],
+ (x - xs[pi])/(xs[pi+1] - xs[pi]));
+
+ else if (pi == 0)
+ y = cubic (ys[pi], ys[pi], ys[pi+1], ys[pi+2],
+ (x - xs[pi])/(xs[pi+1] - xs[pi]));
+
+ else if (pi == pcount-2)
+ y = cubic (ys[pi-1], ys[pi], ys[pi+1], ys[pi+1],
+ (x - xs[pi])/(xs[pi+1] - xs[pi]));
+
+ else
+ y = cubic (ys[pi-1], ys[pi], ys[pi+1], ys[pi+2],
+ (x - xs[pi])/(xs[pi+1] - xs[pi]));
+ if (y < 0) y = 0;
+ if (y > 1) y = 1;
+ values[i] = y;
+ }
+ }
+ double[] scaled_values = new double[bands];
+ for (i = 0; i < bands; i++)
+ scaled_values[i] = scale (values[i]);
+ on_changed (scaled_values);
+ }
+
+ private void
+ snap_move (double x, double y)
+ {
+ double step = 1.0 / (double)(bands+1);
+ int idx = (int)((x-step/2)/step);
+ if (idx < bands)
+ {
+ current_point = points.nth (idx);
+ current_point.data.y = y;
+ }
+ }
+
+ private void
+ handle_curve_click (Gdk.EventButton event)
+ {
+ double x = (double)(event.x - margin_left) / (double)(allocation.width - margin_left);
+ double y = event.y / (double)(allocation.height - margin_bottom);
+
+ if (event.button == 1)
+ {
+ /* Handling left button: moving points */
+ if (snap)
+ snap_move (x, y);
+ else
+ {
+ if (!get_point_at (x, y))
+ {
+ var point = new Point();
+ if (points == null)
+ {
+ points.append (point);
+ current_point = points;
+ }
+ else if (points.data.x > x)
+ {
+ points.prepend (point);
+ current_point = points;
+ }
+ else
+ {
+ var found = false;
+ for (unowned List <Point> i = points; i.next != null; i = i.next)
+ if (i.data.x < x && i.next.data.x > x)
+ {
+ points.insert_before (i.next, point);
+ current_point = i.next;
+ found = true;
+ break;
+ }
+ if (!found)
+ {
+ points.append (point);
+ current_point = points.last();
+ }
+ }
+ }
+ current_point.data.x = x;
+ current_point.data.y = y;
+ }
+ recalc_values();
+ get_window().set_cursor (moving_cursor);
+ queue_draw ();
+ }
+ else if (event.button == 3)
+ {
+ /* Handling right button: removing points */
+ if (snap)
+ return;
+ if (get_point_at (x, y))
+ {
+ points.remove (current_point.data);
+ recalc_values();
+ queue_draw ();
+ }
+ queue_draw();
+ }
+ }
+
+ private bool
+ in_curve_area (int x, int y)
+ {
+ return
+ x > margin_left &&
+ x < allocation.width-1 &&
+ y > 1 &&
+ y < allocation.height-margin_bottom;
+ }
+
+ /* Mouse button got pressed over widget */
+ public override bool
+ button_press_event (Gdk.EventButton event)
+ {
+ if (in_curve_area ((int)event.x, (int)event.y))
+ {
+ curve_hook = true;
+ handle_curve_click (event);
+ return false;
+ }
+
+ if (event.x <= 11 &&
+ event.y > 1 &&
+ event.y <= allocation.height-margin_bottom &&
+ event.button == 1
+ )
+ {
+ preamp = event.y / (double)(allocation.height - margin_bottom);
+ preamp_hook = true;
+ }
+
+ if (event.button == 3)
+ {
+ //stdout.printf ("");
+ menu.popup (null, null, null, event.button, Gtk.get_current_event_time());
+ }
+ return false;
+ }
+
+ /* Mouse button got released */
+ public override bool
+ button_release_event (Gdk.EventButton event)
+ {
+ curve_hook = false;
+ preamp_hook = false;
+ get_window().set_cursor (pointer_cursor);
+ return false;
+ }
+
+ public override bool
+ leave_notify_event (Gdk.EventCrossing event)
+ {
+ mouse_y = -1;
+ queue_draw();
+ return false;
+ }
+
+ /* Mouse pointer moved over widget */
+ public override bool
+ motion_notify_event (Gdk.EventMotion event)
+ {
+ double x = (double)(event.x - margin_left) / (double)(allocation.width - margin_left);
+ double y = event.y / (double)(allocation.height - margin_bottom);
+ if (y < 0) y = 0;
+ if (y > 1) y = 1;
+
+ if (preamp_hook)
+ {
+ preamp = y;
+ queue_draw();
+ return false;
+ }
+
+ if (!in_curve_area ((int)event.x, (int)event.y))
+ mouse_y = -1;
+ else
+ mouse_y = (int)event.y;
+
+ if (curve_hook)
+ {
+ if (snap)
+ snap_move (x, y);
+ else
+ {
+ current_point.data.x = x;
+
+ if ((current_point.prev != null) &&
+ current_point.prev.data.x > current_point.data.x)
+ current_point.data.x = current_point.prev.data.x;
+
+
+ if ((current_point.next != null) &&
+ current_point.next.data.x < current_point.data.x)
+ current_point.data.x = current_point.next.data.x;
+
+ current_point.data.y = y;
+
+ if (current_point.data.x > 1) current_point.data.x = 1;
+ if (current_point.data.x < 0) current_point.data.x = 0;
+ }
+
+ recalc_values();
+ mouse_y = (int)event.y;
+ queue_draw ();
+ }
+ else
+ {
+ if (!get_point_at (x, y))
+ get_window().set_cursor (pointer_cursor);
+ else
+ get_window().set_cursor (moving_cursor);
+ queue_draw ();
+ }
+ return false;
+ }
+
+ public static Graphic inst = null;
+
+ }
+}
diff --git a/plugins/gtkui/test.vala b/plugins/gtkui/test.vala
new file mode 100644
index 00000000..9a50c952
--- /dev/null
+++ b/plugins/gtkui/test.vala
@@ -0,0 +1,30 @@
+using Deadbeef;
+
+Graphic gr = null;
+
+public static bool
+redraw ()
+{
+ gr.queue_draw ();
+ return true;
+}
+
+public static int
+main (string[] args)
+{
+ Gtk.init (ref args);
+ var wnd = new Gtk.Window (Gtk.WindowType.TOPLEVEL);
+ wnd.destroy.connect (Gtk.main_quit);
+
+ gr = new Graphic ();
+ Graphic.inst = gr;
+ wnd.add (gr);
+ gr.show();
+ wnd.show();
+
+ Timeout.add (50, redraw);
+
+ Gtk.main();
+ return 0;
+}
+