Rough-in gtk-pianokeyboard C -> C++
This commit is contained in:
parent
7664f8fd29
commit
3f2f517291
|
@ -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
994
gtk2_ardour/gtk_pianokeyboard.cc
Normal file
994
gtk2_ardour/gtk_pianokeyboard.cc
Normal 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 ();
|
||||
}
|
|
@ -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__ */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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',
|
||||
|
|
Loading…
Reference in New Issue
Block a user