13
0

Rough-in gtk-pianokeyboard C -> C++

This commit is contained in:
Robin Gareus 2019-10-24 19:43:46 +02:00
parent 7664f8fd29
commit 3f2f517291
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
14 changed files with 1190 additions and 1347 deletions

View File

@ -88,7 +88,6 @@ GenericPluginUI::GenericPluginUI (boost::shared_ptr<PluginInsert> pi, bool scrol
, is_scrollable(scrollable)
, _plugin_pianokeyboard_expander (_("MIDI Keyboard"))
, _piano (0)
, _pianomm (0)
, _piano_velocity (*manage (new Adjustment (100, 1, 127, 1, 16)))
, _piano_channel (*manage (new Adjustment (0, 1, 16, 1, 1)))
{
@ -140,13 +139,11 @@ GenericPluginUI::GenericPluginUI (boost::shared_ptr<PluginInsert> pi, bool scrol
VBox* v1_box = manage (new VBox);
VBox* v2_box = manage (new VBox);
if (pi->is_instrument ()) {
_piano = (PianoKeyboard*)piano_keyboard_new();
_pianomm = Glib::wrap((GtkWidget*)_piano);
_pianomm->set_flags(Gtk::CAN_FOCUS);
_pianomm->add_events(Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
_piano = new PianoKeyboard ();
_piano->set_flags(Gtk::CAN_FOCUS);
g_signal_connect (G_OBJECT (_piano), "note-on", G_CALLBACK (GenericPluginUI::_note_on_event_handler), this);
g_signal_connect (G_OBJECT (_piano), "note-off", G_CALLBACK (GenericPluginUI::_note_off_event_handler), this);
_piano->NoteOn.connect (sigc::mem_fun (*this, &GenericPluginUI::note_on_event_handler));
_piano->NoteOff.connect (sigc::mem_fun (*this, &GenericPluginUI::note_off_event_handler));
HBox* box = manage (new HBox);
box->pack_start (*manage (new Label (_("Channel:"))), false, false);
@ -159,7 +156,7 @@ GenericPluginUI::GenericPluginUI (boost::shared_ptr<PluginInsert> pi, bool scrol
_pianobox.set_spacing (4);
_pianobox.pack_start (*box2, true, true);
_pianobox.pack_start (*_pianomm, true, true);
_pianobox.pack_start (*_piano, true, true);
_plugin_pianokeyboard_expander.set_expanded(false);
_plugin_pianokeyboard_expander.property_expanded().signal_changed().connect( sigc::mem_fun(*this, &GenericPluginUI::toggle_pianokeyboard));
@ -236,7 +233,7 @@ GenericPluginUI::~GenericPluginUI ()
screen_update_connection.disconnect();
}
delete automation_menu;
delete _pianomm;
delete _piano;
}
void
@ -1392,22 +1389,10 @@ GenericPluginUI::toggle_pianokeyboard ()
}
void
GenericPluginUI::_note_on_event_handler(GtkWidget*, int note, int, gpointer arg)
{
((GenericPluginUI*)arg)->note_on_event_handler(note);
}
void
GenericPluginUI::_note_off_event_handler(GtkWidget*, int note, gpointer arg)
{
((GenericPluginUI*)arg)->note_off_event_handler(note);
}
void
GenericPluginUI::note_on_event_handler (int note)
GenericPluginUI::note_on_event_handler (int note, int)
{
MidiTrack* mt = dynamic_cast<MidiTrack*> (insert->owner());
_pianomm->grab_focus ();
_piano->grab_focus ();
uint8_t channel = _piano_channel.get_value_as_int () - 1;
uint8_t event[3];
event[0] = (MIDI_CMD_NOTE_ON | channel);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,994 @@
/*-
* Copyright (c) 2007, 2008 Edward Tomasz Napierała <trasz@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* This is piano_keyboard, piano keyboard-like GTK+ widget. It contains
* no MIDI-specific code.
*
* For questions and comments, contact Edward Tomasz Napierala <trasz@FreeBSD.org>.
*/
#include <assert.h>
#include <math.h>
#include <stdint.h>
#include <string.h>
#include <cairo/cairo.h>
#include <pango/pango.h>
#include <pango/pangocairo.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include "gtk_pianokeyboard.h"
#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
#ifndef MIN
# define MIN(A, B) ((A) < (B)) ? (A) : (B)
#endif
#ifndef MAX
# define MAX(A, B) ((A) > (B)) ? (A) : (B)
#endif
#define PIANO_KEYBOARD_DEFAULT_WIDTH 730
#define PIANO_KEYBOARD_DEFAULT_HEIGHT 70
void
PianoKeyboard::draw_keyboard_cue (cairo_t* cr, int note)
{
#if 0
int w = _notes[0].w;
int h = _notes[0].h;
int first_note_in_lower_row = (_octave + 1) * 12;
int last_note_in_lower_row = (_octave + 2) * 12 - 1;
int first_note_in_higher_row = (_octave + 2) * 12;
int last_note_in_higher_row = (_octave + 3) * 12 + 4;
first_note_in_lower_row = MIN (127, MAX (0, first_note_in_lower_row));
last_note_in_lower_row = MIN (127, MAX (0, last_note_in_lower_row));
first_note_in_higher_row = MIN (127, MAX (0, first_note_in_higher_row));
last_note_in_higher_row = MIN (127, MAX (0, last_note_in_higher_row));
cairo_set_source_rgb (cr, 1.0f, 0.0f, 0.0f);
cairo_move_to (cr, _notes[first_note_in_lower_row].x + 3, h - 6);
cairo_line_to (cr, _notes[last_note_in_lower_row].x + w - 3, h - 6);
cairo_stroke (cr);
cairo_set_source_rgb (cr, 0.0f, 0.0f, 1.0f);
cairo_move_to (cr, _notes[first_note_in_higher_row].x + 3, h - 9);
cairo_line_to (cr, _notes[last_note_in_higher_row].x + w - 3, h - 9);
cairo_stroke (cr);
#endif
int nkey = note - _octave * 12;
if (nkey < 0 || nkey >= NNOTES) {
return;
}
if (_note_bindings.find (nkey) == _note_bindings.end()) {
return;
}
// TODO Cache PangoFontDescription for each expose call.
// TODO display above note/octave label if both are visible
int is_white = _notes[note].white;
int x = _notes[note].x;
int w = _notes[note].w;
int h = _notes[note].h;
int tw, th;
char buf[32];
sprintf (buf, "ArdourMono %dpx", MAX (8, MIN (20, w / 2 + 3)));
PangoFontDescription* font = pango_font_description_from_string (buf);
snprintf(buf, 16, "%lc", gdk_keyval_to_unicode (gdk_keyval_to_upper (gdk_keyval_from_name (_note_bindings[nkey].c_str()))));
PangoLayout* pl = pango_cairo_create_layout (cr);
pango_layout_set_font_description (pl, font);
pango_layout_set_text (pl, buf, -1);
pango_layout_set_alignment (pl, PANGO_ALIGN_LEFT);
pango_layout_get_pixel_size (pl, &tw, &th);
if (is_white) {
cairo_set_source_rgba (cr, 0.0, 0.0, 0.5, 1.0);
} else {
cairo_set_source_rgba (cr, 1.0, 1.0, 0.5, 1.0);
}
if (tw < w) {
cairo_save (cr);
cairo_move_to (cr, x + (w - tw) / 2, h - th - 5);
pango_cairo_show_layout (cr, pl);
cairo_restore (cr);
}
g_object_unref (pl);
pango_font_description_free (font);
}
void
PianoKeyboard::queue_note_draw (int note)
{
Gdk::Rectangle rect;
Glib::RefPtr<Gdk::Window> win = get_window();
rect.set_x (_notes[note].x);
rect.set_y (0);
rect.set_width (_notes[note].w);
rect.set_height (_notes[note].h);
win->invalidate_rect(rect, true); // -> queue_draw_area ()
}
void
PianoKeyboard::draw_note (cairo_t* cr, int note)
{
if (note < _min_note || note > _max_note) {
return;
}
int is_white = _notes[note].white;
int x = _notes[note].x;
int w = _notes[note].w;
int h = _notes[note].h;
if (_notes[note].pressed || _notes[note].sustained) {
if (is_white) {
cairo_set_source_rgb (cr, 0.7, 0.5, 0.5);
} else {
cairo_set_source_rgb (cr, 0.6, 0.4, 0.4);
}
} else if (_highlight_grand_piano_range && (note < PIANO_MIN_NOTE || note > PIANO_MAX_NOTE)) {
if (is_white) {
cairo_set_source_rgb (cr, 0.7, 0.7, 0.7);
} else {
cairo_set_source_rgb (cr, 0.3, 0.3, 0.3);
}
} else {
if (is_white) {
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
} else {
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
}
}
cairo_set_line_width (cr, 1.0);
cairo_rectangle (cr, x, 0, w, h);
cairo_fill (cr);
cairo_set_source_rgb (cr, 0.0f, 0.0f, 0.0f); /* black outline */
cairo_rectangle (cr, x, 0, w, h);
cairo_stroke (cr);
if (_enable_keyboard_cue) {
draw_keyboard_cue (cr, note);
}
else if (_print_note_label && (note % 12) == 0) {
int tw, th;
char buf[32];
sprintf (buf, "ArdourMono %dpx", MAX (10, MIN (20, MIN (w / 2 + 3, h / 7))));
PangoFontDescription* font = pango_font_description_from_string (buf);
sprintf (buf, "C%2d", (note / 12) - 1);
PangoLayout* pl = pango_cairo_create_layout (cr);
pango_layout_set_font_description (pl, font);
pango_layout_set_text (pl, buf, -1);
pango_layout_set_alignment (pl, PANGO_ALIGN_LEFT);
pango_layout_get_pixel_size (pl, &tw, &th);
if (th < w && tw < h * .3) {
cairo_save (cr);
cairo_move_to (cr, x + (w - th) / 2, h - 3);
cairo_rotate (cr, M_PI / -2.0);
cairo_set_source_rgba (cr, .0, .0, .0, 1.0);
pango_cairo_show_layout (cr, pl);
cairo_restore (cr);
}
g_object_unref (pl);
pango_font_description_free (font);
}
/* We need to redraw black keys that partially obscure the white one. */
if (note < NNOTES - 2 && !_notes[note + 1].white) {
draw_note (cr, note + 1);
}
if (note > 0 && !_notes[note - 1].white) {
draw_note (cr, note - 1);
}
}
int
PianoKeyboard::press_key (int key, int vel)
{
assert (key >= 0);
assert (key < NNOTES);
_maybe_stop_sustained_notes = false;
/* This is for keyboard autorepeat protection. */
if (_notes[key].pressed)
return 0;
if (_sustain_new_notes) {
_notes[key].sustained = 1;
} else {
_notes[key].sustained = 0;
}
if (_monophonic && _last_key != key) {
_notes[_last_key].pressed = 0;
_notes[_last_key].sustained = 0;
queue_note_draw (_last_key);
}
_last_key = key;
_notes[key].pressed = 1;
NoteOn (key, vel); /* EMIT SIGNAL */
queue_note_draw (key);
return 1;
}
int
PianoKeyboard::release_key (int key)
{
assert (key >= 0);
assert (key < NNOTES);
_maybe_stop_sustained_notes = false;
if (!_notes[key].pressed)
return 0;
if (_sustain_new_notes) {
_notes[key].sustained = 1;
}
_notes[key].pressed = 0;
if (_notes[key].sustained)
return 0;
NoteOff (key); /* EMIT SIGNAL */
queue_note_draw (key);
return 1;
}
void
PianoKeyboard::stop_unsustained_notes ()
{
int i;
for (i = 0; i < NNOTES; ++i) {
if (_notes[i].pressed && !_notes[i].sustained) {
_notes[i].pressed = 0;
NoteOff (i); /* EMIT SIGNAL */
queue_note_draw (i);
}
}
}
void
PianoKeyboard::stop_sustained_notes ()
{
int i;
for (i = 0; i < NNOTES; ++i) {
if (_notes[i].sustained) {
_notes[i].pressed = 0;
_notes[i].sustained = 0;
NoteOff (i); /* EMIT SIGNAL */
queue_note_draw (i);
}
}
}
int
PianoKeyboard::key_binding (const char* key)
{
if (_key_bindings.find (key) != _key_bindings.end()) {
return _key_bindings.at (key);
}
return -1;
}
void
PianoKeyboard::bind_key (const char* key, int note)
{
_key_bindings[key] = note;
_note_bindings[note] = key;
}
void
PianoKeyboard::clear_notes ()
{
_key_bindings.clear ();
_note_bindings.clear ();
}
void
PianoKeyboard::bind_keys_qwerty ()
{
clear_notes ();
bind_key ("space", 128);
/* Lower keyboard row - "zxcvbnm". */
bind_key ("z", 12); /* C0 */
bind_key ("s", 13);
bind_key ("x", 14);
bind_key ("d", 15);
bind_key ("c", 16);
bind_key ("v", 17);
bind_key ("g", 18);
bind_key ("b", 19);
bind_key ("h", 20);
bind_key ("n", 21);
bind_key ("j", 22);
bind_key ("m", 23);
/* Upper keyboard row, first octave - "qwertyu". */
bind_key ("q", 24);
bind_key ("2", 25);
bind_key ("w", 26);
bind_key ("3", 27);
bind_key ("e", 28);
bind_key ("r", 29);
bind_key ("5", 30);
bind_key ("t", 31);
bind_key ("6", 32);
bind_key ("y", 33);
bind_key ("7", 34);
bind_key ("u", 35);
/* Upper keyboard row, the rest - "iop". */
bind_key ("i", 36);
bind_key ("9", 37);
bind_key ("o", 38);
bind_key ("0", 39);
bind_key ("p", 40);
}
void
PianoKeyboard::bind_keys_qwertz ()
{
bind_keys_qwerty ();
/* The only difference between QWERTY and QWERTZ is that the "y" and "z" are swapped together. */
bind_key ("y", 12);
bind_key ("z", 33);
}
void
PianoKeyboard::bind_keys_azerty ()
{
clear_notes ();
bind_key ("space", 128);
/* Lower keyboard row - "wxcvbn,". */
bind_key ("w", 12); /* C0 */
bind_key ("s", 13);
bind_key ("x", 14);
bind_key ("d", 15);
bind_key ("c", 16);
bind_key ("v", 17);
bind_key ("g", 18);
bind_key ("b", 19);
bind_key ("h", 20);
bind_key ("n", 21);
bind_key ("j", 22);
bind_key ("comma", 23);
/* Upper keyboard row, first octave - "azertyu". */
bind_key ("a", 24);
bind_key ("eacute", 25);
bind_key ("z", 26);
bind_key ("quotedbl", 27);
bind_key ("e", 28);
bind_key ("r", 29);
bind_key ("parenleft", 30);
bind_key ("t", 31);
bind_key ("minus", 32);
bind_key ("y", 33);
bind_key ("egrave", 34);
bind_key ("u", 35);
/* Upper keyboard row, the rest - "iop". */
bind_key ("i", 36);
bind_key ("ccedilla", 37);
bind_key ("o", 38);
bind_key ("agrave", 39);
bind_key ("p", 40);
}
void
PianoKeyboard::bind_keys_dvorak ()
{
clear_notes ();
bind_key ("space", 128);
/* Lower keyboard row - ";qjkxbm". */
bind_key ("semicolon", 12); /* C0 */
bind_key ("o", 13);
bind_key ("q", 14);
bind_key ("e", 15);
bind_key ("j", 16);
bind_key ("k", 17);
bind_key ("i", 18);
bind_key ("x", 19);
bind_key ("d", 20);
bind_key ("b", 21);
bind_key ("h", 22);
bind_key ("m", 23);
bind_key ("w", 24); /* overlaps with upper row */
bind_key ("n", 25);
bind_key ("v", 26);
bind_key ("s", 27);
bind_key ("z", 28);
/* Upper keyboard row, first octave - "',.pyfg". */
bind_key ("apostrophe", 24);
bind_key ("2", 25);
bind_key ("comma", 26);
bind_key ("3", 27);
bind_key ("period", 28);
bind_key ("p", 29);
bind_key ("5", 30);
bind_key ("y", 31);
bind_key ("6", 32);
bind_key ("f", 33);
bind_key ("7", 34);
bind_key ("g", 35);
/* Upper keyboard row, the rest - "crl". */
bind_key ("c", 36);
bind_key ("9", 37);
bind_key ("r", 38);
bind_key ("0", 39);
bind_key ("l", 40);
#if 0
bind_key("slash", 41); /* extra F */
bind_key("bracketright", 42);
bind_key("equal", 43);
#endif
}
bool
PianoKeyboard::on_key_press_event (GdkEventKey* event)
{
int note;
char* key;
guint keyval;
GdkKeymapKey kk;
/* We're not using event->keyval, because we need keyval with level set to 0.
E.g. if user holds Shift and presses '7', we want to get a '7', not '&'. */
kk.keycode = event->hardware_keycode;
kk.level = 0;
kk.group = 0;
keyval = gdk_keymap_lookup_key (NULL, &kk);
key = gdk_keyval_name (gdk_keyval_to_lower (keyval));
if (key == NULL) {
g_message ("gtk_keyval_name() returned NULL; please report this.");
return false;
}
note = key_binding (key);
if (note < 0) {
return false;
}
if (note == 128) {
if (event->type == GDK_KEY_RELEASE) {
Rest (); /* EMIT SIGNAL */
}
return true;
}
note += _octave * 12;
assert (note >= 0);
assert (note < NNOTES);
if (event->type == GDK_KEY_PRESS) {
press_key (note, _key_velocity);
} else if (event->type == GDK_KEY_RELEASE) {
release_key (note);
}
return true;
}
bool
PianoKeyboard::on_key_release_event (GdkEventKey* event)
{
return on_key_press_event (event);
}
int
PianoKeyboard::get_note_for_xy (int x, int y) const
{
int height = get_height ();
int note;
if (y <= ((height * 2) / 3)) { /* might be a black key */
for (note = 0; note <= _max_note; ++note) {
if (_notes[note].white) {
continue;
}
if (x >= _notes[note].x && x <= _notes[note].x + _notes[note].w) {
return note;
}
}
}
for (note = 0; note <= _max_note; ++note) {
if (!_notes[note].white) {
continue;
}
if (x >= _notes[note].x && x <= _notes[note].x + _notes[note].w) {
return note;
}
}
return -1;
}
int
PianoKeyboard::get_velocity_for_note_at_y (int note, int y) const
{
if (note < 0) {
return 0;
}
int vel = _min_velocity + (_max_velocity - _min_velocity) * y / _notes[note].h;
if (vel < 1) {
return 1;
} else if (vel > 127) {
return 127;
}
return vel;
}
bool
PianoKeyboard::on_button_press_event (GdkEventButton* event)
{
int x = event->x;
int y = event->y;
int note = get_note_for_xy (x, y);
if (event->button != 1)
return true;
if (event->type == GDK_BUTTON_PRESS) {
if (note < 0) {
return true;
}
if (_note_being_pressed_using_mouse >= 0) {
release_key (_note_being_pressed_using_mouse);
}
press_key (note, get_velocity_for_note_at_y ( note, y));
_note_being_pressed_using_mouse = note;
} else if (event->type == GDK_BUTTON_RELEASE) {
if (note >= 0) {
release_key (note);
} else {
if (_note_being_pressed_using_mouse >= 0) {
release_key (_note_being_pressed_using_mouse);
}
}
_note_being_pressed_using_mouse = -1;
}
return true;
}
bool
PianoKeyboard::on_button_release_event (GdkEventButton* event)
{
return on_button_press_event (event);
}
bool
PianoKeyboard::on_motion_notify_event (GdkEventMotion* event)
{
int note;
if ((event->state & GDK_BUTTON1_MASK) == 0)
return true;
int x = event->x;
int y = event->y;
note = get_note_for_xy (x, y);
if (note != _note_being_pressed_using_mouse && note >= 0) {
if (_note_being_pressed_using_mouse >= 0) {
release_key (_note_being_pressed_using_mouse);
}
press_key (note, get_velocity_for_note_at_y (note, y));
_note_being_pressed_using_mouse = note;
}
return true;
}
bool
PianoKeyboard::on_expose_event (GdkEventExpose* event)
{
cairo_t* cr = gdk_cairo_create (GDK_DRAWABLE (get_window ()->gobj ()));
cairo_rectangle (cr, event->area.x, event->area.y, event->area.width, event->area.height);
cairo_clip (cr);
for (int i = 0; i < NNOTES; ++i) {
GdkRectangle r;
r.x = _notes[i].x;
r.y = 0;
r.width = _notes[i].w;
r.height = _notes[i].h;
switch (gdk_region_rect_in (event->region, &r)) {
case GDK_OVERLAP_RECTANGLE_PART:
case GDK_OVERLAP_RECTANGLE_IN:
draw_note (cr, i);
break;
default:
break;
}
}
cairo_destroy (cr);
return true;
}
void
PianoKeyboard::on_size_request (Gtk::Requisition* requisition)
{
requisition->width = PIANO_KEYBOARD_DEFAULT_WIDTH;
requisition->height = PIANO_KEYBOARD_DEFAULT_HEIGHT;
}
int
PianoKeyboard::is_black (int key) const
{
int note_in_octave = key % 12;
switch (note_in_octave) {
case 1:
case 3:
case 6:
case 8:
case 10:
return 1;
default:
return 0;
}
return 0;
}
double
PianoKeyboard::black_key_left_shift (int key) const
{
int note_in_octave = key % 12;
switch (note_in_octave) {
case 1:
return 2.0 / 3.0;
case 3:
return 1.0 / 3.0;
case 6:
return 2.0 / 3.0;
case 8:
return 0.5;
case 10:
return 1.0 / 3.0;
default:
return 0;
}
return 0;
}
void
PianoKeyboard::recompute_dimensions ()
{
int note;
int number_of_white_keys = 0;
int skipped_white_keys = 0;
for (note = _min_note; note <= _max_note; ++note) {
if (!is_black (note)) {
++number_of_white_keys;
}
}
for (note = 0; note < _min_note; ++note) {
if (!is_black (note)) {
++skipped_white_keys;
}
}
int width = get_width ();
int height = get_height ();
int key_width = width / number_of_white_keys;
int black_key_width = key_width * 0.8;
int useful_width = number_of_white_keys * key_width;
int widget_margin = (width - useful_width) / 2;
int white_key;
for (note = 0, white_key = -skipped_white_keys; note < NNOTES; ++note) {
if (is_black (note)) {
/* This note is black key. */
_notes[note].x = widget_margin +
(white_key * key_width) -
(black_key_width * black_key_left_shift (note));
_notes[note].w = black_key_width;
_notes[note].h = (height * 2) / 3;
_notes[note].white = 0;
continue;
}
/* This note is white key. */
_notes[note].x = widget_margin + white_key * key_width;
_notes[note].w = key_width;
_notes[note].h = height;
_notes[note].white = 1;
white_key++;
}
}
void
PianoKeyboard::on_size_allocate (Gtk::Allocation& allocation)
{
DrawingArea::on_size_allocate (allocation);
recompute_dimensions ();
}
PianoKeyboard::PianoKeyboard ()
{
using namespace Gdk;
add_events (KEY_PRESS_MASK|KEY_RELEASE_MASK|BUTTON_PRESS_MASK|BUTTON_RELEASE_MASK|POINTER_MOTION_MASK|POINTER_MOTION_HINT_MASK);
_maybe_stop_sustained_notes = false;
_sustain_new_notes = false;
_enable_keyboard_cue = false;
_highlight_grand_piano_range = false;
_print_note_label = false;
_octave = 4;
_octave_range = 7;
_note_being_pressed_using_mouse = -1;
_min_note = 0;
_max_note = 127;
_last_key = 0;
_monophonic = false;
_min_velocity = 1;
_max_velocity = 127;
_key_velocity = 100;
bind_keys_qwerty ();
}
PianoKeyboard::~PianoKeyboard ()
{
}
void
PianoKeyboard::set_keyboard_cue (bool enabled)
{
_enable_keyboard_cue = enabled;
queue_draw ();
}
void
PianoKeyboard::set_grand_piano_highlight (bool enabled)
{
_highlight_grand_piano_range = enabled;
queue_draw ();
}
void
PianoKeyboard::show_note_label (bool enabled)
{
_print_note_label = enabled;
queue_draw ();
}
void
PianoKeyboard::set_monophonic (bool monophonic)
{
_monophonic = monophonic;
}
void
PianoKeyboard::set_velocities (int min_vel, int max_vel, int key_vel)
{
if (min_vel <= max_vel && min_vel > 0 && max_vel < 128) {
_min_velocity = min_vel;
_max_velocity = max_vel;
}
if (key_vel > 0 && key_vel < 128) {
_key_velocity = key_vel;
}
}
void
PianoKeyboard::sustain_press ()
{
if (!_sustain_new_notes) {
_sustain_new_notes = true;
_maybe_stop_sustained_notes = true;
}
}
void
PianoKeyboard::sustain_release ()
{
if (_maybe_stop_sustained_notes) {
stop_sustained_notes ();
}
_sustain_new_notes = false;
}
void
PianoKeyboard::set_note_on (int note)
{
if (_notes[note].pressed == 0) {
_notes[note].pressed = 1;
queue_note_draw (note);
}
}
void
PianoKeyboard::set_note_off (int note)
{
if (_notes[note].pressed || _notes[note].sustained) {
_notes[note].pressed = 0;
_notes[note].sustained = 0;
queue_note_draw (note);
}
}
void
PianoKeyboard::set_octave (int octave)
{
stop_unsustained_notes ();
if (octave < -1) {
octave = -1;
} else if (octave > 7) {
octave = 7;
}
_octave = octave;
set_octave_range (_octave_range);
}
void
PianoKeyboard::set_octave_range (int octave_range)
{
stop_unsustained_notes ();
if (octave_range < 2) {
octave_range = 2;
}
if (octave_range > 11) {
octave_range = 11;
}
_octave_range = octave_range;
/* -1 <= _octave <= 7
* key-bindings are at offset 12 .. 40
* default piano range: _octave = 4, range = 7 -> note 21..108
*/
switch (_octave_range) {
default:
assert (0);
break;
case 2:
case 3:
_min_note = (_octave + 1) * 12;
break;
case 4:
case 5:
_min_note = (_octave + 0) * 12;
break;
case 6:
_min_note = (_octave - 1) * 12;
break;
case 7:
case 8:
_min_note = (_octave - 2) * 12;
break;
case 9:
case 10:
_min_note = (_octave - 3) * 12;
break;
case 11:
_min_note = (_octave - 4) * 12;
break;
}
int upper_offset = 0;
if (_min_note < 3) {
upper_offset = 0;
_min_note = 0;
} else if (_octave_range > 5) {
/* extend down to A */
upper_offset = 3;
_min_note -= 3;
}
_max_note = MIN (127, upper_offset + _min_note + _octave_range * 12);
if (_max_note == 127) {
_min_note = MAX (0, _max_note - _octave_range * 12);
}
recompute_dimensions ();
queue_draw ();
}
void
PianoKeyboard::set_keyboard_layout (Layout layout)
{
switch (layout) {
case QWERTY:
bind_keys_qwerty ();
break;
case QWERTZ:
bind_keys_qwertz ();
break;
case AZERTY:
bind_keys_azerty ();
break;
case DVORAK:
bind_keys_dvorak ();
break;
}
queue_draw ();
}

View File

@ -20,20 +20,10 @@
#ifndef __PIANO_KEYBOARD_H__
#define __PIANO_KEYBOARD_H__
#include <map>
#include <glib.h>
#include <gtk/gtkdrawingarea.h>
G_BEGIN_DECLS
#define TYPE_PIANO_KEYBOARD (piano_keyboard_get_type ())
#define PIANO_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PIANO_KEYBOARD, PianoKeyboard))
#define PIANO_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PIANO_KEYBOARD, PianoKeyboardClass))
#define IS_PIANO_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PIANO_KEYBOARD))
#define IS_PIANO_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PIANO_KEYBOARD))
#define PIANO_KEYBOARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PIANO_KEYBOARD, PianoKeyboardClass))
typedef struct _PianoKeyboard PianoKeyboard;
typedef struct _PianoKeyboardClass PianoKeyboardClass;
#include <gtkmm/drawingarea.h>
#define NNOTES (128)
#define PIANO_MIN_NOTE 21
@ -42,59 +32,111 @@ typedef struct _PianoKeyboardClass PianoKeyboardClass;
#define OCTAVE_MIN (-1)
#define OCTAVE_MAX (7)
struct PKNote {
int pressed; /* 1 if key is in pressed down state. */
int sustained; /* 1 if note is sustained. */
int x; /* Distance between the left edge of the key
* and the left edge of the widget, in pixels. */
int w; /* Width of the key, in pixels. */
int h; /* Height of the key, in pixels. */
int white; /* 1 if key is white; 0 otherwise. */
class PianoKeyboard : public Gtk::DrawingArea
{
public:
PianoKeyboard ();
~PianoKeyboard ();
sigc::signal<void, int, int> NoteOn;
sigc::signal<void, int> NoteOff;
sigc::signal<void > Rest;
enum Layout {
QWERTY,
QWERTZ,
AZERTY,
DVORAK
};
void sustain_press ();
void sustain_release ();
void set_note_on (int note);
void set_note_off (int note);
void set_keyboard_cue (bool enabled);
void set_grand_piano_highlight (bool enabled);
void show_note_label (bool enabled);
void set_monophonic (bool monophonic);
void set_octave (int octave);
void set_octave_range (int octave_range);
void set_keyboard_layout (Layout layout);
void set_velocities (int min_vel, int max_vel, int key_vel);
protected:
bool on_key_press_event (GdkEventKey *);
bool on_key_release_event (GdkEventKey *);
bool on_button_press_event (GdkEventButton*);
bool on_button_release_event (GdkEventButton*);
bool on_motion_notify_event (GdkEventMotion*);
bool on_expose_event (GdkEventExpose*);
void on_size_request (Gtk::Requisition*);
void on_size_allocate (Gtk::Allocation&);
private:
void draw_keyboard_cue (cairo_t* cr, int note);
void queue_note_draw (int note);
void draw_note (cairo_t* cr, int note);
int press_key (int key, int vel);
int release_key (int key);
void release_key ();
void stop_unsustained_notes ();
void stop_sustained_notes ();
int key_binding (const char* key);
void bind_key (const char* key, int note);
void clear_notes ();
void bind_keys_qwerty ();
void bind_keys_qwertz ();
void bind_keys_azerty ();
void bind_keys_dvorak ();
int get_note_for_xy (int x, int y) const;
int get_velocity_for_note_at_y (int note, int y) const;
int is_black (int key) const;
double black_key_left_shift (int key) const;
void recompute_dimensions ();
struct PKNote {
PKNote ()
: pressed (false)
, sustained (false)
, white (false)
, x (0)
, w (0)
, h (0)
{}
bool pressed; /* 1 if key is in pressed down state. */
bool sustained; /* 1 if note is sustained. */
bool white; /* 1 if key is white; 0 otherwise. */
int x; /* Distance between the left edge of the key * and the left edge of the widget, in pixels. */
int w; /* Width of the key, in pixels. */
int h; /* Height of the key, in pixels. */
};
bool _maybe_stop_sustained_notes;
bool _sustain_new_notes;
bool _enable_keyboard_cue;
bool _highlight_grand_piano_range;
bool _print_note_label;
int _octave;
int _octave_range;
int _note_being_pressed_using_mouse;
int _min_note;
int _max_note;
int _last_key;
bool _monophonic;
int _min_velocity;
int _max_velocity;
int _key_velocity;
PKNote _notes[NNOTES];
std::map<std::string, int> _key_bindings; /**< Table used to translate from PC keyboard character to MIDI note number. */
std::map<int, std::string> _note_bindings; /**< Table to translate from MIDI note number to PC keyboard character. */
};
struct _PianoKeyboard {
GtkDrawingArea da;
int maybe_stop_sustained_notes;
int sustain_new_notes;
gboolean enable_keyboard_cue;
gboolean highlight_grand_piano_range;
gboolean print_note_label;
int octave;
int octave_range;
int widget_margin;
int note_being_pressed_using_mouse;
int min_note;
int max_note;
int last_key;
gboolean monophonic;
struct PKNote notes[NNOTES];
GHashTable* key_bindings; /**< Table used to translate from PC keyboard character to MIDI note number. */
char* note_bindings[NNOTES]; /**< Table to translate from MIDI note number to PC keyboard character. */
int min_velocity;
int max_velocity;
int key_velocity;
};
struct _PianoKeyboardClass {
GtkDrawingAreaClass parent_class;
};
GType piano_keyboard_get_type (void) G_GNUC_CONST;
GtkWidget* piano_keyboard_new (void);
void piano_keyboard_sustain_press (PianoKeyboard* pk);
void piano_keyboard_sustain_release (PianoKeyboard* pk);
void piano_keyboard_set_note_on (PianoKeyboard* pk, int note);
void piano_keyboard_set_note_off (PianoKeyboard* pk, int note);
void piano_keyboard_set_keyboard_cue (PianoKeyboard* pk, gboolean enabled);
void piano_keyboard_set_grand_piano_highlight (PianoKeyboard* pk, gboolean enabled);
void piano_keyboard_show_note_label (PianoKeyboard* pk, gboolean enabled);
void piano_keyboard_set_monophonic (PianoKeyboard* pk, gboolean monophonic);
void piano_keyboard_set_octave (PianoKeyboard* pk, int octave);
void piano_keyboard_set_octave_range (PianoKeyboard* pk, int octave_range);
void piano_keyboard_set_keyboard_layout (PianoKeyboard* pk, const char* layout);
void piano_keyboard_set_velocities (PianoKeyboard* pk, int min_vel, int max_vel, int key_vel);
G_END_DECLS
#endif /* __PIANO_KEYBOARD_H__ */

View File

@ -23,33 +23,26 @@
#include "pbd/i18n.h"
static void
_note_on_event_handler(GtkWidget* /*widget*/, int note, int, gpointer arg)
{
((NoteSelectDialog*)arg)->note_on_event_handler(note);
}
NoteSelectDialog::NoteSelectDialog()
NoteSelectDialog::NoteSelectDialog ()
: ArdourDialog (_("Select Note"))
, _piano((PianoKeyboard*)piano_keyboard_new())
, _pianomm(Glib::wrap((GtkWidget*)_piano))
, _note_number(60)
{
_pianomm->set_flags(Gtk::CAN_FOCUS);
_pianomm->show();
g_signal_connect(G_OBJECT(_piano), "note-on", G_CALLBACK(_note_on_event_handler), this);
piano_keyboard_set_monophonic(_piano, TRUE);
piano_keyboard_sustain_press(_piano);
_piano.set_flags(Gtk::CAN_FOCUS);
_piano.show();
_piano.NoteOn.connect (sigc::mem_fun (*this, &NoteSelectDialog::note_on_event_handler));
_piano.set_monophonic (true);
_piano.sustain_press ();
get_vbox()->pack_start(_piano);
get_vbox()->pack_start(*_pianomm);
add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
add_button(Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
set_default_response(Gtk::RESPONSE_ACCEPT);
}
void
NoteSelectDialog::note_on_event_handler(int note)
NoteSelectDialog::note_on_event_handler(int note, int)
{
printf("NOTE: %d\n", note);
_note_number = note;
}

View File

@ -31,12 +31,11 @@ public:
uint8_t note_number() const { return _note_number; }
void note_on_event_handler(int note);
private:
PianoKeyboard* _piano;
Gtk::Widget* _pianomm;
uint8_t _note_number;
PianoKeyboard _piano;
uint8_t _note_number;
void note_on_event_handler(int, int);
};
#endif /* __gtk2_ardour_note_select_dialog_h__ */

View File

@ -57,8 +57,6 @@ PatchChangeWidget::PatchChangeWidget (boost::shared_ptr<ARDOUR::Route> r)
, _audition_end_spin (*manage (new Adjustment (60, 0, 127, 1, 16)))
, _audition_velocity (*manage (new Adjustment (100, 1, 127, 1, 16)))
, _audition_note_on (false)
, _piano ((PianoKeyboard*)piano_keyboard_new())
, _pianomm (Glib::wrap((GtkWidget*)_piano))
{
Box* box;
box = manage (new HBox ());
@ -114,11 +112,12 @@ PatchChangeWidget::PatchChangeWidget (boost::shared_ptr<ARDOUR::Route> r)
_channel_select.AddMenuElem (MenuElemNoMnemonic (buf, sigc::bind (sigc::mem_fun (*this, &PatchChangeWidget::select_channel), chn)));
}
piano_keyboard_set_monophonic (_piano, TRUE);
g_signal_connect (G_OBJECT (_piano), "note-on", G_CALLBACK (PatchChangeWidget::_note_on_event_handler), this);
g_signal_connect (G_OBJECT (_piano), "note-off", G_CALLBACK (PatchChangeWidget::_note_off_event_handler), this);
_pianomm->set_flags(Gtk::CAN_FOCUS);
pack_start (*_pianomm, false, false);
_piano.set_monophonic (true);
_piano.NoteOn.connect (sigc::mem_fun (*this, &PatchChangeWidget::_note_on_event_handler));
_piano.NoteOff.connect (sigc::mem_fun (*this, &PatchChangeWidget::note_off_event_handler));
_piano.set_flags(Gtk::CAN_FOCUS);
pack_start (_piano, false, false);
_audition_start_spin.set_sensitive (false);
_audition_end_spin.set_sensitive (false);
@ -145,7 +144,6 @@ PatchChangeWidget::PatchChangeWidget (boost::shared_ptr<ARDOUR::Route> r)
PatchChangeWidget::~PatchChangeWidget ()
{
cancel_audition ();
delete _pianomm;
}
void
@ -434,7 +432,7 @@ PatchChangeWidget::cancel_audition ()
if (_audition_note_on) {
note_off_event_handler (_audition_note_num);
piano_keyboard_set_note_off (_piano, _audition_note_num);
_piano.set_note_off (_audition_note_num);
}
}
@ -467,25 +465,19 @@ PatchChangeWidget::audition_next ()
{
if (_audition_note_on) {
note_off_event_handler (_audition_note_num);
piano_keyboard_set_note_off (_piano, _audition_note_num);
_piano.set_note_off (_audition_note_num);
return ++_audition_note_num <= _audition_end_spin.get_value_as_int() && _audition_enable.get_active ();
} else {
note_on_event_handler (_audition_note_num, true);
piano_keyboard_set_note_on (_piano, _audition_note_num);
_piano.set_note_on (_audition_note_num);
return true;
}
}
void
PatchChangeWidget::_note_on_event_handler(GtkWidget*, int note, int, gpointer arg)
PatchChangeWidget::_note_on_event_handler (int note, int)
{
((PatchChangeWidget*)arg)->note_on_event_handler(note, false);
}
void
PatchChangeWidget::_note_off_event_handler(GtkWidget*, int note, gpointer arg)
{
((PatchChangeWidget*)arg)->note_off_event_handler(note);
note_on_event_handler(note, false);
}
void
@ -493,7 +485,7 @@ PatchChangeWidget::note_on_event_handler (int note, bool for_audition)
{
if (!for_audition) {
cancel_audition ();
_pianomm->grab_focus ();
_piano.grab_focus ();
}
uint8_t event[3];
event[0] = (MIDI_CMD_NOTE_ON | _channel);

View File

@ -99,11 +99,9 @@ private:
uint8_t _audition_note_num;
bool _audition_note_on;
PianoKeyboard* _piano;
Gtk::Widget* _pianomm;
PianoKeyboard _piano;
static void _note_on_event_handler (GtkWidget*, int, int, gpointer);
static void _note_off_event_handler (GtkWidget*, int, gpointer);
void _note_on_event_handler (int, int);
void note_on_event_handler (int, bool for_audition);
void note_off_event_handler (int);
};

View File

@ -319,14 +319,11 @@ private:
Gtk::Expander _plugin_pianokeyboard_expander;
PianoKeyboard* _piano;
Gtk::Widget* _pianomm;
Gtk::VBox _pianobox;
Gtk::SpinButton _piano_velocity;
Gtk::SpinButton _piano_channel;
static void _note_on_event_handler (GtkWidget*, int, int, gpointer);
static void _note_off_event_handler (GtkWidget*, int, gpointer);
void note_on_event_handler (int);
void note_on_event_handler (int, int);
void note_off_event_handler (int);
void toggle_pianokeyboard ();

View File

@ -50,18 +50,6 @@ using namespace ArdourWidgets;
Gtkmm2ext::Bindings* StepEntry::bindings = 0;
StepEntry* StepEntry::_instance = 0;
static void
_note_off_event_handler (GtkWidget* /*widget*/, int note, gpointer arg)
{
((StepEntry*)arg)->note_off_event_handler (note);
}
static void
_rest_event_handler (GtkWidget* /*widget*/, gpointer arg)
{
((StepEntry*)arg)->rest_event_handler ();
}
StepEntry&
StepEntry::instance()
{
@ -99,8 +87,6 @@ StepEntry::StepEntry ()
, program_adjustment (0, 0.0, 127.0, 1.0, 4.0)
, program_spinner (program_adjustment)
, program_button (_("+"))
, _piano (0)
, piano (0)
, se (0)
{
set_data ("ardour-bindings", bindings);
@ -436,13 +422,10 @@ StepEntry::StepEntry ()
length_divisor_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &StepEntry::length_value_change));
dot_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &StepEntry::dot_value_change));
_piano = (PianoKeyboard*) piano_keyboard_new ();
piano = wrap ((GtkWidget*) _piano);
_piano.set_flags (Gtk::CAN_FOCUS);
piano->set_flags (Gtk::CAN_FOCUS);
g_signal_connect(G_OBJECT(_piano), "note-off", G_CALLBACK(_note_off_event_handler), this);
g_signal_connect(G_OBJECT(_piano), "rest", G_CALLBACK(_rest_event_handler), this);
_piano.NoteOff.connect (sigc::mem_fun (*this, &StepEntry::note_off_event_handler));
_piano.Rest.connect (sigc::mem_fun (*this, &StepEntry::rest_event_handler));
program_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::program_click));
bank_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::bank_click));
@ -453,7 +436,7 @@ StepEntry::StepEntry ()
packer.set_spacing (6);
packer.pack_start (upper_box, false, false);
packer.pack_start (*piano, false, false);
packer.pack_start (_piano, false, false);
packer.show_all ();
add (packer);
@ -592,7 +575,7 @@ void
StepEntry::on_show ()
{
ArdourWindow::on_show ();
//piano->grab_focus ();
//_piano->grab_focus ();
}
void

View File

@ -51,9 +51,6 @@ class StepEntry : public ArdourWindow
void set_step_editor (StepEditor*);
void note_off_event_handler (int note);
void rest_event_handler ();
Temporal::Beats note_length();
uint8_t note_velocity() const;
uint8_t note_channel() const;
@ -66,6 +63,9 @@ class StepEntry : public ArdourWindow
static StepEntry* _instance;
StepEntry ();
void note_off_event_handler (int note);
void rest_event_handler ();
Temporal::Beats _current_note_length;
uint8_t _current_note_velocity;
@ -140,8 +140,8 @@ class StepEntry : public ArdourWindow
void velocity_value_change ();
void length_value_change ();
PianoKeyboard* _piano;
Gtk::Widget* piano;
PianoKeyboard _piano;
StepEditor* se;
void bank_click ();

View File

@ -57,12 +57,10 @@ VirtualKeyboardWindow::VirtualKeyboardWindow ()
, _piano_octave_range (*manage (new Adjustment (7, 2, 11, 1, 1)))
, _pitch_adjustment (8192, 0, 16383, 1, 256)
{
_piano = (PianoKeyboard*)piano_keyboard_new ();
_pianomm = Glib::wrap ((GtkWidget*)_piano);
_pianomm->set_flags (Gtk::CAN_FOCUS);
_pianomm->add_events (Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK);
piano_keyboard_set_keyboard_layout (_piano, "QWERTY");
piano_keyboard_show_note_label (_piano, true);
_piano.set_flags (Gtk::CAN_FOCUS);
_piano.set_keyboard_layout(PianoKeyboard::QWERTY);
_piano.show_note_label (true);
using namespace Menu_Helpers;
_keyboard_layout.AddMenuElem (MenuElem ("QWERTY",
@ -218,7 +216,7 @@ VirtualKeyboardWindow::VirtualKeyboardWindow ()
vbox->pack_start (*box1, false, false, 4);
vbox->pack_start (*_pgm_box, false, false, 4);
vbox->pack_start (*_cfg_box, false, false, 4);
vbox->pack_start (*_pianomm, true, true);
vbox->pack_start (_piano, true, true);
add (*vbox);
_bank_msb.signal_value_changed ().connect (sigc::mem_fun (*this, &VirtualKeyboardWindow::bank_patch));
@ -240,8 +238,9 @@ VirtualKeyboardWindow::VirtualKeyboardWindow ()
_show_note_label.signal_button_release_event ().connect (sigc::mem_fun (*this, &VirtualKeyboardWindow::toggle_note_label), false);
_send_panic.signal_button_release_event ().connect (sigc::mem_fun (*this, &VirtualKeyboardWindow::send_panic_message), false);
g_signal_connect (G_OBJECT (_piano), "note-on", G_CALLBACK (VirtualKeyboardWindow::_note_on_event_handler), this);
g_signal_connect (G_OBJECT (_piano), "note-off", G_CALLBACK (VirtualKeyboardWindow::_note_off_event_handler), this);
_piano.NoteOn.connect (sigc::mem_fun (*this, &VirtualKeyboardWindow::note_on_event_handler));
_piano.NoteOff.connect (sigc::mem_fun (*this, &VirtualKeyboardWindow::note_off_event_handler));
update_velocity_settings (0);
update_octave_range ();
@ -252,7 +251,6 @@ VirtualKeyboardWindow::VirtualKeyboardWindow ()
VirtualKeyboardWindow::~VirtualKeyboardWindow ()
{
delete _pianomm;
delete _pitch_slider_tooltip;
}
@ -306,8 +304,7 @@ VirtualKeyboardWindow::set_state (const XMLNode& root)
std::string layout;
if (node->get_property (X_("Layout"), layout)) {
piano_keyboard_set_keyboard_layout (_piano, layout.c_str ());
_keyboard_layout.set_active (layout);
select_keyboard_layout (layout);
}
for (int i = 0; i < VKBD_NCTRLS; ++i) {
@ -325,15 +322,15 @@ VirtualKeyboardWindow::set_state (const XMLNode& root)
}
if (node->get_property (X_("HighlightGrandPiano"), a)) {
_highlight_grand_piano.set_active (a);
piano_keyboard_set_grand_piano_highlight (_piano, a);
_piano.set_grand_piano_highlight (a);
}
if (node->get_property (X_("HighlightKeyRange"), a)) {
_highlight_key_range.set_active (a);
piano_keyboard_set_keyboard_cue (_piano, a);
_piano.set_keyboard_cue (a);
}
if (node->get_property (X_("ShowNoteLabel"), a)) {
_show_note_label.set_active (a);
piano_keyboard_show_note_label (_piano, a);
_piano.show_note_label (a);
}
int v;
@ -367,7 +364,7 @@ VirtualKeyboardWindow::set_state (const XMLNode& root)
bool
VirtualKeyboardWindow::on_focus_in_event (GdkEventFocus *ev)
{
_pianomm->grab_focus ();
_piano.grab_focus ();
return ArdourWindow::on_focus_in_event(ev);
}
@ -381,15 +378,22 @@ VirtualKeyboardWindow::on_unmap ()
bool
VirtualKeyboardWindow::on_key_press_event (GdkEventKey* ev)
{
_pianomm->grab_focus ();
_piano.grab_focus ();
return ARDOUR_UI_UTILS::relay_key_press (ev, this);
}
void
VirtualKeyboardWindow::select_keyboard_layout (std::string const& l)
{
piano_keyboard_set_keyboard_layout (_piano, l.c_str ());
_keyboard_layout.set_active (l);
if (l == "QWERTY") {
_piano.set_keyboard_layout (PianoKeyboard::QWERTY);
} else if (l == "QWERTZ") {
_piano.set_keyboard_layout (PianoKeyboard::QWERTZ);
} else if (l == "AZERTY") {
_piano.set_keyboard_layout (PianoKeyboard::AZERTY);
} else if (l == "DVORAK") {
_piano.set_keyboard_layout (PianoKeyboard::DVORAK);
}
}
bool
@ -421,15 +425,15 @@ VirtualKeyboardWindow::toggle_bankpatch (GdkEventButton*)
void
VirtualKeyboardWindow::update_octave_key ()
{
piano_keyboard_set_octave (_piano, _piano_octave_key.get_value_as_int ());
_pianomm->grab_focus ();
_piano.set_octave (_piano_octave_key.get_value_as_int ());
_piano.grab_focus ();
}
void
VirtualKeyboardWindow::update_octave_range ()
{
piano_keyboard_set_octave_range (_piano, _piano_octave_range.get_value_as_int ());
_pianomm->grab_focus ();
_piano.set_octave_range (_piano_octave_range.get_value_as_int ());
_piano.grab_focus ();
}
bool
@ -445,7 +449,7 @@ VirtualKeyboardWindow::toggle_highlight_piano (GdkEventButton*)
{
bool a = !_highlight_grand_piano.get_active ();
_highlight_grand_piano.set_active (a);
piano_keyboard_set_grand_piano_highlight (_piano, a);
_piano.set_grand_piano_highlight (a);
return false;
}
@ -454,7 +458,7 @@ VirtualKeyboardWindow::toggle_highlight_key (GdkEventButton*)
{
bool a = !_highlight_key_range.get_active ();
_highlight_key_range.set_active (a);
piano_keyboard_set_keyboard_cue (_piano, a);
_piano.set_keyboard_cue (a);
return false;
}
@ -463,7 +467,7 @@ VirtualKeyboardWindow::toggle_note_label (GdkEventButton*)
{
bool a = !_show_note_label.get_active ();
_show_note_label.set_active (a);
piano_keyboard_show_note_label (_piano, a);
_piano.show_note_label (a);
return false;
}
@ -518,15 +522,13 @@ VirtualKeyboardWindow::update_velocity_settings (int ctrl)
}
if (_yaxis_velocity.get_active ()) {
piano_keyboard_set_velocities (_piano,
_piano_min_velocity.get_value_as_int (),
_piano_max_velocity.get_value_as_int (),
_piano_key_velocity.get_value_as_int ());
_piano.set_velocities (_piano_min_velocity.get_value_as_int (),
_piano_max_velocity.get_value_as_int (),
_piano_key_velocity.get_value_as_int ());
} else {
piano_keyboard_set_velocities (_piano,
_piano_key_velocity.get_value_as_int (),
_piano_key_velocity.get_value_as_int (),
_piano_key_velocity.get_value_as_int ());
_piano.set_velocities (_piano_key_velocity.get_value_as_int (),
_piano_key_velocity.get_value_as_int (),
_piano_key_velocity.get_value_as_int ());
}
update_sensitivity ();
}
@ -537,7 +539,7 @@ VirtualKeyboardWindow::update_sensitivity ()
bool c = _yaxis_velocity.get_active ();
_piano_min_velocity.set_sensitive (c);
_piano_max_velocity.set_sensitive (c);
_pianomm->grab_focus ();
_piano.grab_focus ();
}
void
@ -552,7 +554,7 @@ VirtualKeyboardWindow::pitch_slider_adjusted ()
void
VirtualKeyboardWindow::note_on_event_handler (int note, int velocity)
{
_pianomm->grab_focus ();
_piano.grab_focus ();
if (!_session) {
return;
}

View File

@ -96,16 +96,6 @@ protected:
bool on_focus_in_event (GdkEventFocus*);
private:
static void _note_on_event_handler (GtkWidget*, int note, int vel, gpointer arg)
{
static_cast<VirtualKeyboardWindow*> (arg)->note_on_event_handler (note, vel);
}
static void _note_off_event_handler (GtkWidget*, int note, gpointer arg)
{
static_cast<VirtualKeyboardWindow*> (arg)->note_off_event_handler (note);
}
void on_unmap ();
bool on_key_press_event (GdkEventKey*);
@ -129,8 +119,7 @@ private:
bool toggle_note_label (GdkEventButton*);
bool send_panic_message (GdkEventButton*);
PianoKeyboard* _piano;
Gtk::Widget* _pianomm;
PianoKeyboard _piano;
Gtk::SpinButton _piano_channel;
Gtk::SpinButton _transpose_output;

View File

@ -125,7 +125,7 @@ gtk2_ardour_sources = [
'ghostregion.cc',
'global_port_matrix.cc',
'group_tabs.cc',
'gtk_pianokeyboard.c',
'gtk_pianokeyboard.cc',
'gui_object.cc',
'idleometer.cc',
'insert_remove_time_dialog.cc',