[SCM] calf/master: + Curve: added (quite primitive) cursor feedback, added object destructor + Keyboard: added callbacks for changing key colour and drawing overlays on keys
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:37:26 UTC 2013
The following commit has been merged in the master branch:
commit 6055b82305a9d406201c558d44f9a08394c4da08
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date: Thu Jul 31 20:36:09 2008 +0000
+ Curve: added (quite primitive) cursor feedback, added object destructor
+ Keyboard: added callbacks for changing key colour and drawing overlays on keys
git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@242 78b06b96-2940-0410-b7fc-879d825d01d8
diff --git a/src/calf/ctl_curve.h b/src/calf/ctl_curve.h
index 5a31c19..0c53d4f 100644
--- a/src/calf/ctl_curve.h
+++ b/src/calf/ctl_curve.h
@@ -48,7 +48,7 @@ struct CalfCurve
virtual void curve_changed(const point_vector &data) {}
};
- struct EventTester: public EventSink
+ struct EventTester: public EventAdapter
{
virtual void curve_changed(const point_vector &data) {
for(size_t i = 0; i < data.size(); i++)
@@ -62,37 +62,11 @@ struct CalfCurve
int cur_pt;
bool hide_current;
EventSink *sink;
-
- void log2phys(float &x, float &y) {
- x = (x - x0) / (x1 - x0) * (parent.allocation.width - 2) + 1;
- y = (y - y0) / (y1 - y0) * (parent.allocation.height - 2) + 1;
- }
- void phys2log(float &x, float &y) {
- x = x0 + (x - 1) * (x1 - x0) / (parent.allocation.width - 2);
- y = y0 + (y - 1) * (y1 - y0) / (parent.allocation.height - 2);
- }
- void clip(int pt, float &x, float &y, bool &hide)
- {
- float ymin = std::min(y0, y1), ymax = std::max(y0, y1);
- float yamp = ymax - ymin;
- hide = false;
- if (pt != 0 && pt != (int)(points->size() - 1))
- {
- if (y < ymin - yamp || y > ymax + yamp)
- hide = true;
- }
- if (x < x0) x = x0;
- if (y < ymin) y = ymin;
- if (x > x1) x = x1;
- if (y > ymax) y = ymax;
- if (pt == 0) x = 0;
- if (pt == (int)(points->size() - 1))
- x = (*points)[pt].first;
- if (pt > 0 && x < (*points)[pt - 1].first)
- x = (*points)[pt - 1].first;
- if (pt < (int)(points->size() - 1) && x > (*points)[pt + 1].first)
- x = (*points)[pt + 1].first;
- }
+ GdkCursor *hand_cursor, *pencil_cursor;
+
+ void log2phys(float &x, float &y);
+ void phys2log(float &x, float &y);
+ void clip(int pt, float &x, float &y, bool &hide);
};
struct CalfCurveClass
@@ -101,8 +75,8 @@ struct CalfCurveClass
};
extern GtkWidget *calf_curve_new();
-
extern GType calf_curve_get_type();
+extern void calf_curve_set_points(GtkWidget *widget, const CalfCurve::point_vector &src);
G_END_DECLS
diff --git a/src/calf/ctl_keyboard.h b/src/calf/ctl_keyboard.h
index 7e47051..f94262e 100644
--- a/src/calf/ctl_keyboard.h
+++ b/src/calf/ctl_keyboard.h
@@ -35,20 +35,49 @@ G_BEGIN_DECLS
struct CalfKeyboard
{
+ struct KeyInfo
+ {
+ double x, y, width, height;
+ int note;
+ bool black;
+ };
+
struct EventSink
{
+ virtual void set_instance(CalfKeyboard *kb)=0;
+ virtual bool pre_draw(cairo_t *c, KeyInfo &ki)=0;
+ virtual bool pre_draw_outline(cairo_t *c, KeyInfo &ki)=0;
+ virtual void post_draw(cairo_t *c, KeyInfo &ki)=0;
+ virtual void post_all(cairo_t *c)=0;
virtual void note_on(int note, int vel) = 0;
virtual void note_off(int note) = 0;
};
struct EventAdapter: public EventSink
{
+ CalfKeyboard *kb;
+ virtual void set_instance(CalfKeyboard *_kb) { kb = _kb; }
+ virtual bool pre_draw(cairo_t *c, KeyInfo &ki) { return false; }
+ virtual bool pre_draw_outline(cairo_t *c, KeyInfo &ki) { return false; }
+ virtual void post_draw(cairo_t *c, KeyInfo &ki) {}
+ virtual void post_all(cairo_t *c) {}
virtual void note_on(int note, int vel) {}
virtual void note_off(int note) {}
};
- struct EventTester: public EventSink
+ struct EventTester: public EventAdapter
{
+ virtual bool pre_draw(cairo_t *c, KeyInfo &ki) { if (ki.note == 60) cairo_set_source_rgb(c, 1.0, 1.0, 0.5); return false; }
+ virtual void post_draw(cairo_t *c, KeyInfo &ki) {
+ if (ki.note % 12 != 0 && ki.note % 12 != 3 && ki.note % 12 != 7)
+ return;
+ cairo_rectangle(c, ki.x + ki.width / 2 - 2, ki.y + ki.height - 8, 4, 4);
+ if (ki.black)
+ cairo_set_source_rgb(c, 1.0, 1.0, 1.0);
+ else
+ cairo_set_source_rgb(c, 0.0, 0.0, 0.0);
+ cairo_fill(c);
+ }
virtual void note_on(int note, int vel) { g_message("note on %d %d", note, vel); }
virtual void note_off(int note) { g_message("note off %d", note); }
};
@@ -57,6 +86,7 @@ struct CalfKeyboard
int nkeys;
EventSink *sink;
int last_key;
+ bool interactive;
};
struct CalfKeyboardClass
diff --git a/src/ctl_curve.cpp b/src/ctl_curve.cpp
index 21a4afd..5c554b3 100644
--- a/src/ctl_curve.cpp
+++ b/src/ctl_curve.cpp
@@ -24,6 +24,8 @@
#include <stdint.h>
#include <math.h>
+static gpointer parent_class = NULL;
+
GtkWidget *
calf_curve_new()
{
@@ -83,7 +85,8 @@ calf_curve_realize(GtkWidget *widget)
GdkWindowAttr attributes;
attributes.event_mask = GDK_EXPOSURE_MASK | GDK_BUTTON1_MOTION_MASK |
GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
- GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK;
+ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK;
attributes.x = widget->allocation.x;
attributes.y = widget->allocation.y;
attributes.width = widget->allocation.width;
@@ -119,27 +122,34 @@ calf_curve_size_allocate (GtkWidget *widget,
gdk_window_move_resize(widget->window, allocation->x, allocation->y, allocation->width, allocation->height );
}
-static gboolean
-calf_curve_button_press (GtkWidget *widget, GdkEventButton *event)
+static int
+find_nearest(CalfCurve *self, int ex, int ey, int &insert_pt)
{
- g_assert(CALF_IS_CURVE(widget));
- CalfCurve *self = CALF_CURVE(widget);
float dist = 5;
- int found_pt = -1, insert_pt = -1;
- int i;
- for (i = 0; i < (int)self->points->size(); i++)
+ int found_pt = -1;
+ for (int i = 0; i < (int)self->points->size(); i++)
{
float x = (*self->points)[i].first, y = (*self->points)[i].second;
self->log2phys(x, y);
- float thisdist = std::max(fabs(event->x - x), fabs(event->y - y));
+ float thisdist = std::max(fabs(ex - x), fabs(ey - y));
if (thisdist < dist)
{
dist = thisdist;
found_pt = i;
}
- if (event->x > x)
+ if (ex > x)
insert_pt = i + 1;
}
+ return found_pt;
+}
+
+static gboolean
+calf_curve_button_press (GtkWidget *widget, GdkEventButton *event)
+{
+ g_assert(CALF_IS_CURVE(widget));
+ CalfCurve *self = CALF_CURVE(widget);
+ int found_pt, insert_pt = -1;
+ found_pt = find_nearest(self, event->x, event->y, insert_pt);
if (found_pt == -1 && insert_pt != -1)
{
float x = event->x, y = event->y;
@@ -161,6 +171,7 @@ calf_curve_button_press (GtkWidget *widget, GdkEventButton *event)
gtk_widget_queue_draw(widget);
if (self->sink)
self->sink->curve_changed(*self->points);
+ gdk_window_set_cursor(widget->window, self->hand_cursor);
return TRUE;
}
@@ -176,6 +187,7 @@ calf_curve_button_release (GtkWidget *widget, GdkEventButton *event)
if (self->sink)
self->sink->curve_changed(*self->points);
gtk_widget_queue_draw(widget);
+ gdk_window_set_cursor(widget->window, self->pencil_cursor);
return FALSE;
}
@@ -183,6 +195,8 @@ static gboolean
calf_curve_pointer_motion (GtkWidget *widget, GdkEventMotion *event)
{
g_assert(CALF_IS_CURVE(widget));
+ if (event->is_hint)
+ gdk_event_request_motions(event);
CalfCurve *self = CALF_CURVE(widget);
if (self->cur_pt != -1)
{
@@ -194,12 +208,34 @@ calf_curve_pointer_motion (GtkWidget *widget, GdkEventMotion *event)
self->sink->curve_changed(*self->points);
gtk_widget_queue_draw(widget);
}
+ else
+ {
+ int insert_pt = -1;
+ if (find_nearest(self, event->x, event->y, insert_pt) == -1)
+ gdk_window_set_cursor(widget->window, self->pencil_cursor);
+ else
+ gdk_window_set_cursor(widget->window, self->hand_cursor);
+ }
return FALSE;
}
static void
+calf_curve_finalize (GObject *obj)
+{
+ g_assert(CALF_IS_CURVE(obj));
+ CalfCurve *self = CALF_CURVE(obj);
+
+ delete self->points;
+ self->points = NULL;
+
+ G_OBJECT_CLASS(parent_class)->finalize(obj);
+}
+
+static void
calf_curve_class_init (CalfCurveClass *klass)
{
+ parent_class = g_type_class_peek_parent (klass);
+
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
widget_class->realize = calf_curve_realize;
widget_class->expose_event = calf_curve_expose;
@@ -210,17 +246,18 @@ calf_curve_class_init (CalfCurveClass *klass)
widget_class->motion_notify_event = calf_curve_pointer_motion;
// widget_class->key_press_event = calf_curve_key_press;
// widget_class->scroll_event = calf_curve_scroll;
+
+ G_OBJECT_CLASS(klass)->finalize = calf_curve_finalize;
}
static void
calf_curve_init (CalfCurve *self)
{
GtkWidget *widget = GTK_WIDGET(self);
- GTK_WIDGET_SET_FLAGS (GTK_WIDGET(self), GTK_CAN_FOCUS);
+ GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
self->points = new CalfCurve::point_vector;
// XXXKF: destructor
- self->points->push_back(CalfCurve::point(0.f, 0.f));
- self->points->push_back(CalfCurve::point(0.5f, 0.25f));
+ self->points->push_back(CalfCurve::point(0.f, 1.f));
self->points->push_back(CalfCurve::point(1.f, 1.f));
self->x0 = 0.f;
self->x1 = 1.f;
@@ -228,6 +265,52 @@ calf_curve_init (CalfCurve *self)
self->y1 = 0.f;
self->cur_pt = -1;
self->hide_current = false;
+ self->pencil_cursor = gdk_cursor_new(GDK_PENCIL);
+ self->hand_cursor = gdk_cursor_new(GDK_FLEUR);
+}
+
+void CalfCurve::log2phys(float &x, float &y) {
+ x = (x - x0) / (x1 - x0) * (parent.allocation.width - 2) + 1;
+ y = (y - y0) / (y1 - y0) * (parent.allocation.height - 2) + 1;
+}
+
+void CalfCurve::phys2log(float &x, float &y) {
+ x = x0 + (x - 1) * (x1 - x0) / (parent.allocation.width - 2);
+ y = y0 + (y - 1) * (y1 - y0) / (parent.allocation.height - 2);
+}
+
+void CalfCurve::clip(int pt, float &x, float &y, bool &hide)
+{
+ float ymin = std::min(y0, y1), ymax = std::max(y0, y1);
+ float yamp = ymax - ymin;
+ hide = false;
+ if (pt != 0 && pt != (int)(points->size() - 1))
+ {
+ if (y < ymin - yamp || y > ymax + yamp)
+ hide = true;
+ }
+ if (x < x0) x = x0;
+ if (y < ymin) y = ymin;
+ if (x > x1) x = x1;
+ if (y > ymax) y = ymax;
+ if (pt == 0) x = 0;
+ if (pt == (int)(points->size() - 1))
+ x = (*points)[pt].first;
+ if (pt > 0 && x < (*points)[pt - 1].first)
+ x = (*points)[pt - 1].first;
+ if (pt < (int)(points->size() - 1) && x > (*points)[pt + 1].first)
+ x = (*points)[pt + 1].first;
+}
+
+void calf_curve_set_points(GtkWidget *widget, const CalfCurve::point_vector &src)
+{
+ g_assert(CALF_IS_CURVE(widget));
+ CalfCurve *self = CALF_CURVE(widget);
+ if (self->points->size() != src.size())
+ self->cur_pt = -1;
+ *self->points = src;
+
+ gtk_widget_queue_draw(widget);
}
GType
diff --git a/src/ctl_keyboard.cpp b/src/ctl_keyboard.cpp
index 3edd427..3eb8808 100644
--- a/src/ctl_keyboard.cpp
+++ b/src/ctl_keyboard.cpp
@@ -24,6 +24,10 @@
#include <stdint.h>
#include <malloc.h>
+static const int semitones_b[] = { 1, 3, -1, 6, 8, 10, -1 };
+static const int semitones_w[] = { 0, 2, 4, 5, 7, 9, 11 };
+
+
GtkWidget *
calf_keyboard_new()
{
@@ -48,23 +52,40 @@ calf_keyboard_expose (GtkWidget *widget, GdkEventExpose *event)
for (int i = 0; i < self->nkeys; i++)
{
- cairo_rectangle(c, 0.5 + 12 * i, 0.5, 12, sy);
+ CalfKeyboard::KeyInfo ki = { 0.5 + 12 * i, 0.5, 12, sy, 12 * (i / 7) + semitones_w[i % 7], false };
+ cairo_new_path(c);
gdk_cairo_set_source_color(c, &scWhiteKey);
- cairo_fill_preserve(c);
- gdk_cairo_set_source_color(c, &scOutline);
- cairo_stroke(c);
+ if (!self->sink->pre_draw(c, ki))
+ {
+ cairo_rectangle(c, ki.x, ki.y, ki.width, ki.height);
+ cairo_fill_preserve(c);
+ gdk_cairo_set_source_color(c, &scOutline);
+ if (!self->sink->pre_draw_outline(c, ki))
+ cairo_stroke(c);
+ else
+ cairo_new_path(c);
+ self->sink->post_draw(c, ki);
+ }
}
for (int i = 0; i < self->nkeys - 1; i++)
{
if ((1 << (i % 7)) & 59)
{
- cairo_rectangle(c, 8 + 12 * i, 0, 8, sy * 3 / 5);
+ CalfKeyboard::KeyInfo ki = { 8.5 + 12 * i, 0.5, 8, sy * 3 / 5, 12 * (i / 7) + semitones_b[i % 7], true };
+ cairo_new_path(c);
+ cairo_rectangle(c, ki.x, ki.y, ki.width, ki.height);
gdk_cairo_set_source_color(c, &scBlackKey);
- cairo_fill(c);
+ if (!self->sink->pre_draw(c, ki))
+ {
+ cairo_fill(c);
+ self->sink->post_draw(c, ki);
+ }
}
}
+ self->sink->post_all(c);
+
cairo_destroy(c);
return TRUE;
@@ -128,7 +149,7 @@ calf_keyboard_key_press (GtkWidget *widget, GdkEventKey *event)
return FALSE;
}
-static int
+int
calf_keyboard_pos_to_note (CalfKeyboard *kb, int x, int y, int *vel = NULL)
{
// first try black keys
@@ -137,15 +158,13 @@ calf_keyboard_pos_to_note (CalfKeyboard *kb, int x, int y, int *vel = NULL)
int blackkey = (x - 8) / 12;
if (blackkey < kb->nkeys && (59 & (1 << (blackkey % 7))))
{
- static const int semitones[] = { 1, 3, -1, 6, 8, 10, -1 };
- return semitones[blackkey % 7] + 12 * (blackkey / 7);
+ return semitones_b[blackkey % 7] + 12 * (blackkey / 7);
}
}
// if not a black key, then which white one?
- static const int semitones[] = { 0, 2, 4, 5, 7, 9, 11 };
int whitekey = x / 12;
// semitones within octave + 12 semitones per octave
- return semitones[whitekey % 7] + 12 * (whitekey / 7);
+ return semitones_w[whitekey % 7] + 12 * (whitekey / 7);
}
static gboolean
@@ -153,7 +172,7 @@ calf_keyboard_button_press (GtkWidget *widget, GdkEventButton *event)
{
g_assert(CALF_IS_KEYBOARD(widget));
CalfKeyboard *self = CALF_KEYBOARD(widget);
- if (!self->sink)
+ if (!self->interactive)
return FALSE;
gtk_widget_grab_focus(widget);
int vel = 127;
@@ -168,7 +187,7 @@ calf_keyboard_button_release (GtkWidget *widget, GdkEventButton *event)
{
g_assert(CALF_IS_KEYBOARD(widget));
CalfKeyboard *self = CALF_KEYBOARD(widget);
- if (!self->sink)
+ if (!self->interactive)
return FALSE;
if (self->last_key != -1)
self->sink->note_off(self->last_key);
@@ -180,7 +199,7 @@ calf_keyboard_pointer_motion (GtkWidget *widget, GdkEventMotion *event)
{
g_assert(CALF_IS_KEYBOARD(widget));
CalfKeyboard *self = CALF_KEYBOARD(widget);
- if (!self->sink)
+ if (!self->interactive)
return FALSE;
int vel = 127;
int key = calf_keyboard_pos_to_note(self, event->x, event->y, &vel);
@@ -213,11 +232,12 @@ calf_keyboard_class_init (CalfKeyboardClass *klass)
static void
calf_keyboard_init (CalfKeyboard *self)
{
+ static CalfKeyboard::EventAdapter default_sink;
GtkWidget *widget = GTK_WIDGET(self);
g_assert(CALF_IS_KEYBOARD(widget));
GTK_WIDGET_SET_FLAGS (GTK_WIDGET(self), GTK_CAN_FOCUS);
self->nkeys = 7 * 3 + 1;
- self->sink = NULL;
+ self->sink = &default_sink;
self->last_key = -1;
}
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list