[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