[SCM] calf/master: Move knob code to separate files.

js at users.alioth.debian.org js at users.alioth.debian.org
Tue May 7 15:41:15 UTC 2013


The following commit has been merged in the master branch:
commit a2ddd8f8b9752d88c28045ec9b88c4cf6f9bced4
Author: Krzysztof Foltman <wdev at foltman.com>
Date:   Wed Sep 26 22:37:14 2012 +0100

    Move knob code to separate files.

diff --git a/src/Makefile.am b/src/Makefile.am
index cc238f2..321932d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -51,7 +51,7 @@ if USE_LV2_GUI
 
 noinst_LTLIBRARIES += calflv2gui.la
 
-calflv2gui_la_SOURCES = gui.cpp gui_config.cpp gui_controls.cpp ctl_curve.cpp ctl_keyboard.cpp ctl_led.cpp ctl_tube.cpp ctl_vumeter.cpp custom_ctl.cpp metadata.cpp giface.cpp plugin_gui_window.cpp preset.cpp preset_gui.cpp lv2gui.cpp osctl.cpp utils.cpp
+calflv2gui_la_SOURCES = gui.cpp gui_config.cpp gui_controls.cpp ctl_curve.cpp ctl_keyboard.cpp ctl_knob.cpp ctl_led.cpp ctl_tube.cpp ctl_vumeter.cpp custom_ctl.cpp metadata.cpp giface.cpp plugin_gui_window.cpp preset.cpp preset_gui.cpp lv2gui.cpp osctl.cpp utils.cpp
 
 if USE_DEBUG
 calflv2gui_la_LDFLAGS = -rpath $(lv2dir) -avoid-version -module -lexpat $(GUI_DEPS_LIBS) -disable-static
@@ -62,7 +62,7 @@ endif
 endif
 
 if USE_GUI
-libcalfgui_la_SOURCES = ctl_curve.cpp ctl_keyboard.cpp ctl_led.cpp ctl_tube.cpp ctl_vumeter.cpp custom_ctl.cpp gui.cpp gui_config.cpp gui_controls.cpp osctl.cpp plugin_gui_window.cpp preset_gui.cpp utils.cpp
+libcalfgui_la_SOURCES = ctl_curve.cpp ctl_keyboard.cpp ctl_knob.cpp ctl_led.cpp ctl_tube.cpp ctl_vumeter.cpp custom_ctl.cpp gui.cpp gui_config.cpp gui_controls.cpp osctl.cpp plugin_gui_window.cpp preset_gui.cpp utils.cpp
 libcalfgui_la_LDFLAGS = -static -disable-shared -lexpat
 endif
 
diff --git a/src/calf/Makefile.am b/src/calf/Makefile.am
index cbc466a..9078b57 100644
--- a/src/calf/Makefile.am
+++ b/src/calf/Makefile.am
@@ -1,5 +1,5 @@
 noinst_HEADERS = audio_fx.h benchmark.h biquad.h buffer.h custom_ctl.h \
-    ctl_curve.h ctl_keyboard.h ctl_led.h ctl_tube.h ctl_vumeter.h \
+    ctl_curve.h ctl_keyboard.h ctl_knob.h ctl_led.h ctl_tube.h ctl_vumeter.h \
     delay.h envelope.h fft.h fixed_point.h giface.h gtk_session_env.h gtk_main_win.h \
     gui.h gui_config.h gui_controls.h inertia.h jackhost.h \
     host_session.h loudness.h \
diff --git a/src/calf/ctl_knob.h b/src/calf/ctl_knob.h
new file mode 100644
index 0000000..77938a4
--- /dev/null
+++ b/src/calf/ctl_knob.h
@@ -0,0 +1,57 @@
+/* Calf DSP Library
+ * A knob (dial) widget.
+ *
+ * Copyright (C) 2008-2010 Krzysztof Foltman, Torben Hohn, Markus
+ * Schmidt and others
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CALF_CTL_KNOB_H
+#define CALF_CTL_KNOB_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CALF_TYPE_KNOB          (calf_knob_get_type())
+#define CALF_KNOB(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALF_TYPE_KNOB, CalfKnob))
+#define CALF_IS_KNOB(obj)       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALF_TYPE_KNOB))
+#define CALF_KNOB_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST ((klass),  CALF_TYPE_KNOB, CalfKnobClass))
+#define CALF_IS_KNOB_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass),  CALF_TYPE_KNOB))
+
+struct CalfKnob
+{
+    GtkRange parent;
+    int knob_type;
+    int knob_size;
+    double start_x, start_y, last_y, start_value;
+};
+
+struct CalfKnobClass
+{
+    GtkRangeClass parent_class;
+    GdkPixbuf *knob_image[5];
+};
+
+extern GtkWidget *calf_knob_new();
+extern GtkWidget *calf_knob_new_with_adjustment(GtkAdjustment *_adjustment);
+
+extern GType calf_knob_get_type();
+
+G_END_DECLS
+
+#endif
diff --git a/src/calf/custom_ctl.h b/src/calf/custom_ctl.h
index ade88f3..359a27e 100644
--- a/src/calf/custom_ctl.h
+++ b/src/calf/custom_ctl.h
@@ -108,31 +108,6 @@ extern GtkWidget *calf_phase_graph_new();
 
 extern GType calf_phase_graph_get_type();
 
-#define CALF_TYPE_KNOB          (calf_knob_get_type())
-#define CALF_KNOB(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALF_TYPE_KNOB, CalfKnob))
-#define CALF_IS_KNOB(obj)       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALF_TYPE_KNOB))
-#define CALF_KNOB_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST ((klass),  CALF_TYPE_KNOB, CalfKnobClass))
-#define CALF_IS_KNOB_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass),  CALF_TYPE_KNOB))
-
-struct CalfKnob
-{
-    GtkRange parent;
-    int knob_type;
-    int knob_size;
-    double start_x, start_y, last_y, start_value;
-};
-
-struct CalfKnobClass
-{
-    GtkRangeClass parent_class;
-    GdkPixbuf *knob_image[5];
-};
-
-extern GtkWidget *calf_knob_new();
-extern GtkWidget *calf_knob_new_with_adjustment(GtkAdjustment *_adjustment);
-
-extern GType calf_knob_get_type();
-
 #define CALF_TYPE_TOGGLE          (calf_toggle_get_type())
 #define CALF_TOGGLE(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALF_TYPE_TOGGLE, CalfToggle))
 #define CALF_IS_TOGGLE(obj)       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALF_TYPE_TOGGLE))
diff --git a/src/ctl_knob.cpp b/src/ctl_knob.cpp
new file mode 100644
index 0000000..84935ea
--- /dev/null
+++ b/src/ctl_knob.cpp
@@ -0,0 +1,344 @@
+/* Calf DSP Library
+ * Knob control.
+ * Copyright (C) 2007-2010 Krzysztof Foltman, Torben Hohn, Markus Schmidt
+ * and others
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+#include "config.h"
+#include <calf/ctl_knob.h>
+#include <gdk/gdkkeysyms.h>
+#include <cairo/cairo.h>
+#include <malloc.h>
+#include <math.h>
+#include <gdk/gdk.h>
+
+///////////////////////////////////////// knob ///////////////////////////////////////////////
+
+static gboolean
+calf_knob_expose (GtkWidget *widget, GdkEventExpose *event)
+{
+    g_assert(CALF_IS_KNOB(widget));
+    
+    CalfKnob *self = CALF_KNOB(widget);
+    GdkWindow *window = widget->window;
+    GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget));
+     
+    // printf("adjustment = %p value = %f\n", adj, adj->value);
+    int ox = widget->allocation.x, oy = widget->allocation.y;
+    ox += (widget->allocation.width - self->knob_size * 20) / 2;
+    oy += (widget->allocation.height - self->knob_size * 20) / 2;
+
+    int phase = (int)((adj->value - adj->lower) * 64 / (adj->upper - adj->lower));
+    // skip middle phase except for true middle value
+    if (self->knob_type == 1 && phase == 32) {
+        double pt = (adj->value - adj->lower) * 2.0 / (adj->upper - adj->lower) - 1.0;
+        if (pt < 0)
+            phase = 31;
+        if (pt > 0)
+            phase = 33;
+    }
+    // endless knob: skip 90deg highlights unless the value is really a multiple of 90deg
+    if (self->knob_type == 3 && !(phase % 16)) {
+        if (phase == 64)
+            phase = 0;
+        double nom = adj->lower + phase * (adj->upper - adj->lower) / 64.0;
+        double diff = (adj->value - nom) / (adj->upper - adj->lower);
+        if (diff > 0.0001)
+            phase = (phase + 1) % 64;
+        if (diff < -0.0001)
+            phase = (phase + 63) % 64;
+    }
+    gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], CALF_KNOB_CLASS(GTK_OBJECT_GET_CLASS(widget))->knob_image[self->knob_size - 1], phase * self->knob_size * 20, self->knob_type * self->knob_size * 20, ox, oy, self->knob_size * 20, self->knob_size * 20, GDK_RGB_DITHER_NORMAL, 0, 0);
+    // printf("exposed %p %d+%d\n", widget->window, widget->allocation.x, widget->allocation.y);
+    if (gtk_widget_is_focus(widget))
+    {
+        gtk_paint_focus(widget->style, window, GTK_STATE_NORMAL, NULL, widget, NULL, ox, oy, self->knob_size * 20, self->knob_size * 20);
+    }
+
+    return TRUE;
+}
+
+static void
+calf_knob_size_request (GtkWidget *widget,
+                           GtkRequisition *requisition)
+{
+    g_assert(CALF_IS_KNOB(widget));
+
+    CalfKnob *self = CALF_KNOB(widget);
+
+    // width/height is hardwired at 40px now
+    // is now chooseable by "size" value in XML (1-4)
+    requisition->width  = 20 * self->knob_size;
+    requisition->height = 20 * self->knob_size;
+}
+
+static void
+calf_knob_incr (GtkWidget *widget, int dir_down)
+{
+    g_assert(CALF_IS_KNOB(widget));
+    CalfKnob *self = CALF_KNOB(widget);
+    GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget));
+
+    int oldstep = (int)(0.5f + (adj->value - adj->lower) / adj->step_increment);
+    int step;
+    int nsteps = (int)(0.5f + (adj->upper - adj->lower) / adj->step_increment); // less 1 actually
+    if (dir_down)
+        step = oldstep - 1;
+    else
+        step = oldstep + 1;
+    if (self->knob_type == 3 && step >= nsteps)
+        step %= nsteps;
+    if (self->knob_type == 3 && step < 0)
+        step = nsteps - (nsteps - step) % nsteps;
+
+    // trying to reduce error cumulation here, by counting from lowest or from highest
+    float value = adj->lower + step * double(adj->upper - adj->lower) / nsteps;
+    gtk_range_set_value(GTK_RANGE(widget), value);
+    // printf("step %d:%d nsteps %d value %f:%f\n", oldstep, step, nsteps, oldvalue, value);
+}
+
+static gboolean
+calf_knob_key_press (GtkWidget *widget, GdkEventKey *event)
+{
+    g_assert(CALF_IS_KNOB(widget));
+    CalfKnob *self = CALF_KNOB(widget);
+    GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget));
+
+    switch(event->keyval)
+    {
+        case GDK_Home:
+            gtk_range_set_value(GTK_RANGE(widget), adj->lower);
+            return TRUE;
+
+        case GDK_End:
+            gtk_range_set_value(GTK_RANGE(widget), adj->upper);
+            return TRUE;
+
+        case GDK_Up:
+            calf_knob_incr(widget, 0);
+            return TRUE;
+
+        case GDK_Down:
+            calf_knob_incr(widget, 1);
+            return TRUE;
+            
+        case GDK_Shift_L:
+        case GDK_Shift_R:
+            self->start_value = gtk_range_get_value(GTK_RANGE(widget));
+            self->start_y = self->last_y;
+            return TRUE;
+    }
+
+    return FALSE;
+}
+
+static gboolean
+calf_knob_key_release (GtkWidget *widget, GdkEventKey *event)
+{
+    g_assert(CALF_IS_KNOB(widget));
+    CalfKnob *self = CALF_KNOB(widget);
+
+    if(event->keyval == GDK_Shift_L || event->keyval == GDK_Shift_R)
+    {
+        self->start_value = gtk_range_get_value(GTK_RANGE(widget));
+        self->start_y = self->last_y;
+        return TRUE;
+    }
+    
+    return FALSE;
+}
+
+static gboolean
+calf_knob_button_press (GtkWidget *widget, GdkEventButton *event)
+{
+    g_assert(CALF_IS_KNOB(widget));
+    CalfKnob *self = CALF_KNOB(widget);
+
+    // CalfKnob *lg = CALF_KNOB(widget);
+    gtk_widget_grab_focus(widget);
+    gtk_grab_add(widget);
+    self->start_x = event->x;
+    self->last_y = self->start_y = event->y;
+    self->start_value = gtk_range_get_value(GTK_RANGE(widget));
+    
+    return TRUE;
+}
+
+static gboolean
+calf_knob_button_release (GtkWidget *widget, GdkEventButton *event)
+{
+    g_assert(CALF_IS_KNOB(widget));
+
+    if (GTK_WIDGET_HAS_GRAB(widget))
+        gtk_grab_remove(widget);
+    return FALSE;
+}
+
+static inline float endless(float value)
+{
+    if (value >= 0)
+        return fmod(value, 1.f);
+    else
+        return fmod(1.f - fmod(1.f - value, 1.f), 1.f);
+}
+
+static inline float deadzone(GtkWidget *widget, float value, float incr)
+{
+    // map to dead zone
+    float ov = value;
+    if (ov > 0.5)
+        ov = 0.1 + ov;
+    if (ov < 0.5)
+        ov = ov - 0.1;
+    
+    float nv = ov + incr;
+    
+    if (nv > 0.6)
+        return nv - 0.1;
+    if (nv < 0.4)
+        return nv + 0.1;
+    return 0.5;
+}
+
+static gboolean
+calf_knob_pointer_motion (GtkWidget *widget, GdkEventMotion *event)
+{
+    g_assert(CALF_IS_KNOB(widget));
+    CalfKnob *self = CALF_KNOB(widget);
+
+    float scale = (event->state & GDK_SHIFT_MASK) ? 1000 : 100;
+    gboolean moved = FALSE;
+    
+    if (GTK_WIDGET_HAS_GRAB(widget)) 
+    {
+        if (self->knob_type == 3)
+        {
+            gtk_range_set_value(GTK_RANGE(widget), endless(self->start_value - (event->y - self->start_y) / scale));
+        }
+        else
+        if (self->knob_type == 1)
+        {
+            gtk_range_set_value(GTK_RANGE(widget), deadzone(GTK_WIDGET(widget), self->start_value, -(event->y - self->start_y) / scale));
+        }
+        else
+        {
+            gtk_range_set_value(GTK_RANGE(widget), self->start_value - (event->y - self->start_y) / scale);
+        }
+        moved = TRUE;
+    }
+    self->last_y = event->y;
+    return moved;
+}
+
+static gboolean
+calf_knob_scroll (GtkWidget *widget, GdkEventScroll *event)
+{
+    calf_knob_incr(widget, event->direction);
+    return TRUE;
+}
+
+static void
+calf_knob_class_init (CalfKnobClass *klass)
+{
+    // GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+    GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+    widget_class->expose_event = calf_knob_expose;
+    widget_class->size_request = calf_knob_size_request;
+    widget_class->button_press_event = calf_knob_button_press;
+    widget_class->button_release_event = calf_knob_button_release;
+    widget_class->motion_notify_event = calf_knob_pointer_motion;
+    widget_class->key_press_event = calf_knob_key_press;
+    widget_class->key_release_event = calf_knob_key_release;
+    widget_class->scroll_event = calf_knob_scroll;
+    GError *error = NULL;
+    klass->knob_image[0] = gdk_pixbuf_new_from_file(PKGLIBDIR "/knob1.png", &error);
+    klass->knob_image[1] = gdk_pixbuf_new_from_file(PKGLIBDIR "/knob2.png", &error);
+    klass->knob_image[2] = gdk_pixbuf_new_from_file(PKGLIBDIR "/knob3.png", &error);
+    klass->knob_image[3] = gdk_pixbuf_new_from_file(PKGLIBDIR "/knob4.png", &error);
+    klass->knob_image[4] = gdk_pixbuf_new_from_file(PKGLIBDIR "/knob5.png", &error);
+    g_assert(klass->knob_image != NULL);
+}
+
+static void
+calf_knob_init (CalfKnob *self)
+{
+    GtkWidget *widget = GTK_WIDGET(self);
+    GTK_WIDGET_SET_FLAGS (GTK_WIDGET(self), GTK_CAN_FOCUS);
+    widget->requisition.width = 40;
+    widget->requisition.height = 40;
+}
+
+GtkWidget *
+calf_knob_new()
+{
+    GtkAdjustment *adj = (GtkAdjustment *)gtk_adjustment_new(0, 0, 1, 0.01, 0.5, 0);
+    return calf_knob_new_with_adjustment(adj);
+}
+
+static gboolean calf_knob_value_changed(gpointer obj)
+{
+    GtkWidget *widget = (GtkWidget *)obj;
+    gtk_widget_queue_draw(widget);
+    return FALSE;
+}
+
+GtkWidget *calf_knob_new_with_adjustment(GtkAdjustment *_adjustment)
+{
+    GtkWidget *widget = GTK_WIDGET( g_object_new (CALF_TYPE_KNOB, NULL ));
+    if (widget) {
+        gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment);
+        gtk_signal_connect(GTK_OBJECT(widget), "value-changed", G_CALLBACK(calf_knob_value_changed), widget);
+    }
+    return widget;
+}
+
+GType
+calf_knob_get_type (void)
+{
+    static GType type = 0;
+    if (!type) {
+        
+        static const GTypeInfo type_info = {
+            sizeof(CalfKnobClass),
+            NULL, /* base_init */
+            NULL, /* base_finalize */
+            (GClassInitFunc)calf_knob_class_init,
+            NULL, /* class_finalize */
+            NULL, /* class_data */
+            sizeof(CalfKnob),
+            0,    /* n_preallocs */
+            (GInstanceInitFunc)calf_knob_init
+        };
+        
+        for (int i = 0; ; i++) {
+            char *name = g_strdup_printf("CalfKnob%u%d", 
+                ((unsigned int)(intptr_t)calf_knob_class_init) >> 16, i);
+            if (g_type_from_name(name)) {
+                free(name);
+                continue;
+            }
+            type = g_type_register_static(GTK_TYPE_RANGE,
+                                          name,
+                                          &type_info,
+                                          (GTypeFlags)0);
+            free(name);
+            break;
+        }
+    }
+    return type;
+}
+
diff --git a/src/custom_ctl.cpp b/src/custom_ctl.cpp
index 4183487..61e67bc 100644
--- a/src/custom_ctl.cpp
+++ b/src/custom_ctl.cpp
@@ -909,322 +909,6 @@ calf_phase_graph_get_type (void)
 }
 
 
-///////////////////////////////////////// knob ///////////////////////////////////////////////
-
-static gboolean
-calf_knob_expose (GtkWidget *widget, GdkEventExpose *event)
-{
-    g_assert(CALF_IS_KNOB(widget));
-    
-    CalfKnob *self = CALF_KNOB(widget);
-    GdkWindow *window = widget->window;
-    GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget));
-     
-    // printf("adjustment = %p value = %f\n", adj, adj->value);
-    int ox = widget->allocation.x, oy = widget->allocation.y;
-    ox += (widget->allocation.width - self->knob_size * 20) / 2;
-    oy += (widget->allocation.height - self->knob_size * 20) / 2;
-
-    int phase = (int)((adj->value - adj->lower) * 64 / (adj->upper - adj->lower));
-    // skip middle phase except for true middle value
-    if (self->knob_type == 1 && phase == 32) {
-        double pt = (adj->value - adj->lower) * 2.0 / (adj->upper - adj->lower) - 1.0;
-        if (pt < 0)
-            phase = 31;
-        if (pt > 0)
-            phase = 33;
-    }
-    // endless knob: skip 90deg highlights unless the value is really a multiple of 90deg
-    if (self->knob_type == 3 && !(phase % 16)) {
-        if (phase == 64)
-            phase = 0;
-        double nom = adj->lower + phase * (adj->upper - adj->lower) / 64.0;
-        double diff = (adj->value - nom) / (adj->upper - adj->lower);
-        if (diff > 0.0001)
-            phase = (phase + 1) % 64;
-        if (diff < -0.0001)
-            phase = (phase + 63) % 64;
-    }
-    gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], CALF_KNOB_CLASS(GTK_OBJECT_GET_CLASS(widget))->knob_image[self->knob_size - 1], phase * self->knob_size * 20, self->knob_type * self->knob_size * 20, ox, oy, self->knob_size * 20, self->knob_size * 20, GDK_RGB_DITHER_NORMAL, 0, 0);
-    // printf("exposed %p %d+%d\n", widget->window, widget->allocation.x, widget->allocation.y);
-    if (gtk_widget_is_focus(widget))
-    {
-        gtk_paint_focus(widget->style, window, GTK_STATE_NORMAL, NULL, widget, NULL, ox, oy, self->knob_size * 20, self->knob_size * 20);
-    }
-
-    return TRUE;
-}
-
-static void
-calf_knob_size_request (GtkWidget *widget,
-                           GtkRequisition *requisition)
-{
-    g_assert(CALF_IS_KNOB(widget));
-
-    CalfKnob *self = CALF_KNOB(widget);
-
-    // width/height is hardwired at 40px now
-    // is now chooseable by "size" value in XML (1-4)
-    requisition->width  = 20 * self->knob_size;
-    requisition->height = 20 * self->knob_size;
-}
-
-static void
-calf_knob_incr (GtkWidget *widget, int dir_down)
-{
-    g_assert(CALF_IS_KNOB(widget));
-    CalfKnob *self = CALF_KNOB(widget);
-    GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget));
-
-    int oldstep = (int)(0.5f + (adj->value - adj->lower) / adj->step_increment);
-    int step;
-    int nsteps = (int)(0.5f + (adj->upper - adj->lower) / adj->step_increment); // less 1 actually
-    if (dir_down)
-        step = oldstep - 1;
-    else
-        step = oldstep + 1;
-    if (self->knob_type == 3 && step >= nsteps)
-        step %= nsteps;
-    if (self->knob_type == 3 && step < 0)
-        step = nsteps - (nsteps - step) % nsteps;
-
-    // trying to reduce error cumulation here, by counting from lowest or from highest
-    float value = adj->lower + step * double(adj->upper - adj->lower) / nsteps;
-    gtk_range_set_value(GTK_RANGE(widget), value);
-    // printf("step %d:%d nsteps %d value %f:%f\n", oldstep, step, nsteps, oldvalue, value);
-}
-
-static gboolean
-calf_knob_key_press (GtkWidget *widget, GdkEventKey *event)
-{
-    g_assert(CALF_IS_KNOB(widget));
-    CalfKnob *self = CALF_KNOB(widget);
-    GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget));
-
-    switch(event->keyval)
-    {
-        case GDK_Home:
-            gtk_range_set_value(GTK_RANGE(widget), adj->lower);
-            return TRUE;
-
-        case GDK_End:
-            gtk_range_set_value(GTK_RANGE(widget), adj->upper);
-            return TRUE;
-
-        case GDK_Up:
-            calf_knob_incr(widget, 0);
-            return TRUE;
-
-        case GDK_Down:
-            calf_knob_incr(widget, 1);
-            return TRUE;
-            
-        case GDK_Shift_L:
-        case GDK_Shift_R:
-            self->start_value = gtk_range_get_value(GTK_RANGE(widget));
-            self->start_y = self->last_y;
-            return TRUE;
-    }
-
-    return FALSE;
-}
-
-static gboolean
-calf_knob_key_release (GtkWidget *widget, GdkEventKey *event)
-{
-    g_assert(CALF_IS_KNOB(widget));
-    CalfKnob *self = CALF_KNOB(widget);
-
-    if(event->keyval == GDK_Shift_L || event->keyval == GDK_Shift_R)
-    {
-        self->start_value = gtk_range_get_value(GTK_RANGE(widget));
-        self->start_y = self->last_y;
-        return TRUE;
-    }
-    
-    return FALSE;
-}
-
-static gboolean
-calf_knob_button_press (GtkWidget *widget, GdkEventButton *event)
-{
-    g_assert(CALF_IS_KNOB(widget));
-    CalfKnob *self = CALF_KNOB(widget);
-
-    // CalfKnob *lg = CALF_KNOB(widget);
-    gtk_widget_grab_focus(widget);
-    gtk_grab_add(widget);
-    self->start_x = event->x;
-    self->last_y = self->start_y = event->y;
-    self->start_value = gtk_range_get_value(GTK_RANGE(widget));
-    
-    return TRUE;
-}
-
-static gboolean
-calf_knob_button_release (GtkWidget *widget, GdkEventButton *event)
-{
-    g_assert(CALF_IS_KNOB(widget));
-
-    if (GTK_WIDGET_HAS_GRAB(widget))
-        gtk_grab_remove(widget);
-    return FALSE;
-}
-
-static inline float endless(float value)
-{
-    if (value >= 0)
-        return fmod(value, 1.f);
-    else
-        return fmod(1.f - fmod(1.f - value, 1.f), 1.f);
-}
-
-static inline float deadzone(GtkWidget *widget, float value, float incr)
-{
-    // map to dead zone
-    float ov = value;
-    if (ov > 0.5)
-        ov = 0.1 + ov;
-    if (ov < 0.5)
-        ov = ov - 0.1;
-    
-    float nv = ov + incr;
-    
-    if (nv > 0.6)
-        return nv - 0.1;
-    if (nv < 0.4)
-        return nv + 0.1;
-    return 0.5;
-}
-
-static gboolean
-calf_knob_pointer_motion (GtkWidget *widget, GdkEventMotion *event)
-{
-    g_assert(CALF_IS_KNOB(widget));
-    CalfKnob *self = CALF_KNOB(widget);
-
-    float scale = (event->state & GDK_SHIFT_MASK) ? 1000 : 100;
-    gboolean moved = FALSE;
-    
-    if (GTK_WIDGET_HAS_GRAB(widget)) 
-    {
-        if (self->knob_type == 3)
-        {
-            gtk_range_set_value(GTK_RANGE(widget), endless(self->start_value - (event->y - self->start_y) / scale));
-        }
-        else
-        if (self->knob_type == 1)
-        {
-            gtk_range_set_value(GTK_RANGE(widget), deadzone(GTK_WIDGET(widget), self->start_value, -(event->y - self->start_y) / scale));
-        }
-        else
-        {
-            gtk_range_set_value(GTK_RANGE(widget), self->start_value - (event->y - self->start_y) / scale);
-        }
-        moved = TRUE;
-    }
-    self->last_y = event->y;
-    return moved;
-}
-
-static gboolean
-calf_knob_scroll (GtkWidget *widget, GdkEventScroll *event)
-{
-    calf_knob_incr(widget, event->direction);
-    return TRUE;
-}
-
-static void
-calf_knob_class_init (CalfKnobClass *klass)
-{
-    // GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
-    GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
-    widget_class->expose_event = calf_knob_expose;
-    widget_class->size_request = calf_knob_size_request;
-    widget_class->button_press_event = calf_knob_button_press;
-    widget_class->button_release_event = calf_knob_button_release;
-    widget_class->motion_notify_event = calf_knob_pointer_motion;
-    widget_class->key_press_event = calf_knob_key_press;
-    widget_class->key_release_event = calf_knob_key_release;
-    widget_class->scroll_event = calf_knob_scroll;
-    GError *error = NULL;
-    klass->knob_image[0] = gdk_pixbuf_new_from_file(PKGLIBDIR "/knob1.png", &error);
-    klass->knob_image[1] = gdk_pixbuf_new_from_file(PKGLIBDIR "/knob2.png", &error);
-    klass->knob_image[2] = gdk_pixbuf_new_from_file(PKGLIBDIR "/knob3.png", &error);
-    klass->knob_image[3] = gdk_pixbuf_new_from_file(PKGLIBDIR "/knob4.png", &error);
-    klass->knob_image[4] = gdk_pixbuf_new_from_file(PKGLIBDIR "/knob5.png", &error);
-    g_assert(klass->knob_image != NULL);
-}
-
-static void
-calf_knob_init (CalfKnob *self)
-{
-    GtkWidget *widget = GTK_WIDGET(self);
-    GTK_WIDGET_SET_FLAGS (GTK_WIDGET(self), GTK_CAN_FOCUS);
-    widget->requisition.width = 40;
-    widget->requisition.height = 40;
-}
-
-GtkWidget *
-calf_knob_new()
-{
-    GtkAdjustment *adj = (GtkAdjustment *)gtk_adjustment_new(0, 0, 1, 0.01, 0.5, 0);
-    return calf_knob_new_with_adjustment(adj);
-}
-
-static gboolean calf_knob_value_changed(gpointer obj)
-{
-    GtkWidget *widget = (GtkWidget *)obj;
-    gtk_widget_queue_draw(widget);
-    return FALSE;
-}
-
-GtkWidget *calf_knob_new_with_adjustment(GtkAdjustment *_adjustment)
-{
-    GtkWidget *widget = GTK_WIDGET( g_object_new (CALF_TYPE_KNOB, NULL ));
-    if (widget) {
-        gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment);
-        gtk_signal_connect(GTK_OBJECT(widget), "value-changed", G_CALLBACK(calf_knob_value_changed), widget);
-    }
-    return widget;
-}
-
-GType
-calf_knob_get_type (void)
-{
-    static GType type = 0;
-    if (!type) {
-        
-        static const GTypeInfo type_info = {
-            sizeof(CalfKnobClass),
-            NULL, /* base_init */
-            NULL, /* base_finalize */
-            (GClassInitFunc)calf_knob_class_init,
-            NULL, /* class_finalize */
-            NULL, /* class_data */
-            sizeof(CalfKnob),
-            0,    /* n_preallocs */
-            (GInstanceInitFunc)calf_knob_init
-        };
-        
-        for (int i = 0; ; i++) {
-            char *name = g_strdup_printf("CalfKnob%u%d", 
-                ((unsigned int)(intptr_t)calf_knob_class_init) >> 16, i);
-            if (g_type_from_name(name)) {
-                free(name);
-                continue;
-            }
-            type = g_type_register_static(GTK_TYPE_RANGE,
-                                          name,
-                                          &type_info,
-                                          (GTypeFlags)0);
-            free(name);
-            break;
-        }
-    }
-    return type;
-}
-
 ///////////////////////////////////////// toggle ///////////////////////////////////////////////
 
 static gboolean
diff --git a/src/gui_controls.cpp b/src/gui_controls.cpp
index cc60a82..5a33651 100644
--- a/src/gui_controls.cpp
+++ b/src/gui_controls.cpp
@@ -22,6 +22,7 @@
 #include <assert.h>
 #include <calf/ctl_curve.h>
 #include <calf/ctl_keyboard.h>
+#include <calf/ctl_knob.h>
 #include <calf/ctl_led.h>
 #include <calf/ctl_tube.h>
 #include <calf/ctl_vumeter.h>

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list