--- gigedit/trunk/src/gigedit/regionchooser.cpp 2008/02/02 08:52:48 1658 +++ gigedit/trunk/src/gigedit/regionchooser.cpp 2008/02/03 14:10:47 1661 @@ -24,9 +24,13 @@ #include #include #include +#include #include "global.h" +#define REGION_BLOCK_HEIGHT 20 +#define KEYBOARD_HEIGHT 40 + void SortedRegions::update(gig::Instrument* instrument) { // Usually, the regions in a gig file are ordered after their key // range, but there are files where they are not. The @@ -54,7 +58,9 @@ -RegionChooser::RegionChooser() +RegionChooser::RegionChooser() : + m_VirtKeybModeChoice(_("Virtual Keyboard Mode")), + currentActiveKey(-1) { Glib::RefPtr colormap = get_default_colormap(); @@ -74,7 +80,30 @@ resize.active = false; move.active = false; cursor_is_resize = false; - h1 = 20; + h1 = REGION_BLOCK_HEIGHT; + + // properties of the virtual keyboard + { + const char* choices[] = { "normal", "chord", NULL }; + static const virt_keyboard_mode_t values[] = { + VIRT_KEYBOARD_MODE_NORMAL, + VIRT_KEYBOARD_MODE_CHORD + }; + m_VirtKeybModeChoice.set_choices(choices, values); + m_VirtKeybModeChoice.set_value(VIRT_KEYBOARD_MODE_NORMAL); + } + m_VirtKeybVelocityLabelDescr.set_text(_("Note-On Velocity:")); + m_VirtKeybVelocityLabel.set_text("-"); + m_VirtKeybOffVelocityLabelDescr.set_text(_("Note-Off Velocity:")); + m_VirtKeybOffVelocityLabel.set_text("-"); + m_VirtKeybPropsBox.pack_start(m_VirtKeybModeChoice.label, Gtk::PACK_SHRINK); + m_VirtKeybPropsBox.pack_start(m_VirtKeybModeChoice.widget, Gtk::PACK_SHRINK); + m_VirtKeybPropsBox.pack_start(m_VirtKeybVelocityLabelDescr, Gtk::PACK_SHRINK); + m_VirtKeybPropsBox.pack_start(m_VirtKeybVelocityLabel, Gtk::PACK_SHRINK); + m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabelDescr, Gtk::PACK_SHRINK); + m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabel, Gtk::PACK_SHRINK); + m_VirtKeybPropsBox.set_spacing(10); + m_VirtKeybPropsBox.show(); actionGroup = Gtk::ActionGroup::create(); actionGroup->add(Gtk::Action::create("Properties", @@ -122,14 +151,27 @@ sigc::mem_fun(*this, &RegionChooser::on_dimension_manager_changed) ) ); + keyboard_key_hit_signal.connect( + sigc::mem_fun(*this, &RegionChooser::on_note_on_event) + ); + keyboard_key_released_signal.connect( + sigc::mem_fun(*this, &RegionChooser::on_note_off_event) + ); } RegionChooser::~RegionChooser() { } +template inline std::string ToString(T o) { + std::stringstream ss; + ss << o; + return ss.str(); +} + void RegionChooser::on_note_on_event(int key, int velocity) { draw_region(key, key+1, activeKeyColor); + m_VirtKeybVelocityLabel.set_text(ToString(velocity)); } void RegionChooser::on_note_off_event(int key, int velocity) { @@ -137,6 +179,7 @@ draw_region(key, key+1, black); else draw_region(key, key+1, white); + m_VirtKeybOffVelocityLabel.set_text(ToString(velocity)); } void RegionChooser::on_realize() @@ -154,7 +197,7 @@ { Glib::RefPtr window = get_window(); window->clear(); - const int h = 40; + const int h = KEYBOARD_HEIGHT; const int w = get_width() - 1; const int bh = int(h * 0.55); @@ -224,7 +267,7 @@ void RegionChooser::on_size_request(GtkRequisition* requisition) { *requisition = GtkRequisition(); - requisition->height = 40 + 20; + requisition->height = KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT; requisition->width = 500; } @@ -234,7 +277,7 @@ } void RegionChooser::draw_digit(int key) { - const int h = 40; + const int h = KEYBOARD_HEIGHT; const int w = get_width() - 1; Glib::RefPtr layout = Pango::Layout::create(get_pango_context()); char buf[30]; @@ -250,7 +293,7 @@ void RegionChooser::draw_region(int from, int to, const Gdk::Color& color) { - const int h = 40; + const int h = KEYBOARD_HEIGHT; const int w = get_width() - 1; const int bh = int(h * 0.55); @@ -296,6 +339,28 @@ bool RegionChooser::on_button_release_event(GdkEventButton* event) { + const int k = int(event->x / (get_width() - 1) * 128.0); + + // handle-note off on virtual keyboard + if (event->type == GDK_BUTTON_RELEASE) { + int velocity = (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 : + int(float(event->y - REGION_BLOCK_HEIGHT) / float(KEYBOARD_HEIGHT) * 128.0f) + 1; + if (velocity <= 0) velocity = 1; + switch (m_VirtKeybModeChoice.get_value()) { + case VIRT_KEYBOARD_MODE_CHORD: + if (event->y >= REGION_BLOCK_HEIGHT) + keyboard_key_released_signal.emit(k, velocity); + break; + case VIRT_KEYBOARD_MODE_NORMAL: + default: + if (currentActiveKey >= 0 && currentActiveKey <= 127) { + keyboard_key_released_signal.emit(currentActiveKey, velocity); + currentActiveKey = -1; + } + break; + } + } + if (resize.active) { get_window()->pointer_ungrab(event->time); resize.active = false; @@ -355,8 +420,18 @@ { if (!instrument) return true; - int k = int(event->x / (get_width() - 1) * 128.0); + const int k = int(event->x / (get_width() - 1) * 128.0); + if (event->type == GDK_BUTTON_PRESS) { + if (event->y >= REGION_BLOCK_HEIGHT) { + int velocity = (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 : + int(float(event->y - REGION_BLOCK_HEIGHT) / float(KEYBOARD_HEIGHT) * 128.0f) + 1; + currentActiveKey = k; + keyboard_key_hit_signal.emit(k, velocity); + } + } + + if (event->y >= REGION_BLOCK_HEIGHT) return true; if (event->type == GDK_BUTTON_PRESS && event->button == 3) { gig::Region* r = get_region(k); if (r) { @@ -592,6 +667,21 @@ Gdk::ModifierType state = Gdk::ModifierType(0); window->get_pointer(x, y, state); + // handle virtual MIDI keyboard + if (m_VirtKeybModeChoice.get_value() != VIRT_KEYBOARD_MODE_CHORD && + currentActiveKey > 0 && + event->y >= REGION_BLOCK_HEIGHT && + event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT) + { + const int k = int(event->x / (get_width() - 1) * 128.0); + int velocity = (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 : + int(float(event->y - REGION_BLOCK_HEIGHT) / float(KEYBOARD_HEIGHT) * 128.0f) + 1; + if (velocity <= 0) velocity = 1; + keyboard_key_released_signal.emit(currentActiveKey, velocity); + currentActiveKey = k; + keyboard_key_hit_signal.emit(k, velocity); + } + if (resize.active) { motion_resize_region(x, y); } else if (move.active) { @@ -751,3 +841,11 @@ sigc::signal& RegionChooser::signal_region_changed_signal() { return region_changed_signal; } + +sigc::signal& RegionChooser::signal_keyboard_key_hit() { + return keyboard_key_hit_signal; +} + +sigc::signal& RegionChooser::signal_keyboard_key_released() { + return keyboard_key_released_signal; +}