Super basic Virtual-Keyboard UI
authorRobin Gareus <robin@gareus.org>
Fri, 18 Oct 2019 01:50:52 +0000 (03:50 +0200)
committerRobin Gareus <robin@gareus.org>
Fri, 18 Oct 2019 01:50:52 +0000 (03:50 +0200)
gtk2_ardour/ardour.menus.in
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui.h
gtk2_ardour/ardour_ui_dialogs.cc
gtk2_ardour/port_group.cc
gtk2_ardour/virtual_keyboard_window.cc [new file with mode: 0644]
gtk2_ardour/virtual_keyboard_window.h [new file with mode: 0644]
gtk2_ardour/wscript

index f04cbd6539180d94498eb6fda7162223b599b3a7..f0bcaa197743fea56839595e63c6dc168c6503c2 100644 (file)
       <menuitem action='ManageTemplates'/>
       <menuitem action='toggle-key-editor'/>
       <separator/>
+      <menuitem action='toggle-virtual-keyboard'/>
       <menuitem action='NewMIDITracer'/>
       <menuitem action='toggle-log-window'/>
       <separator/>
index 0f077c9baa8fa4de3d813f02945c149f9363e104..708528e067495c59fa866b5d8bf3dc7a6f5cdbfe 100644 (file)
@@ -205,6 +205,7 @@ typedef uint64_t microseconds_t;
 #include "utils.h"
 #include "utils_videotl.h"
 #include "video_server_dialog.h"
+#include "virtual_keyboard_window.h"
 #include "add_video_dialog.h"
 #include "transcode_video_dialog.h"
 
@@ -337,6 +338,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        , bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this))
        , big_clock_window (X_("big-clock"), _("Big Clock"), boost::bind (&ARDOUR_UI::create_big_clock_window, this))
        , big_transport_window (X_("big-transport"), _("Transport Controls"), boost::bind (&ARDOUR_UI::create_big_transport_window, this))
+       , virtual_keyboard_window (X_("virtual-keyboard"), _("Virtual Keyboard"), boost::bind (&ARDOUR_UI::create_virtual_keyboard_window, this))
        , audio_port_matrix (X_("audio-connection-manager"), _("Audio Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::AUDIO))
        , midi_port_matrix (X_("midi-connection-manager"), _("MIDI Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::MIDI))
        , key_editor (X_("key-editor"), _("Keyboard Shortcuts"), boost::bind (&ARDOUR_UI::create_key_editor, this))
@@ -494,6 +496,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
                location_ui.set_state (*ui_xml, 0);
                big_clock_window.set_state (*ui_xml, 0);
                big_transport_window.set_state (*ui_xml, 0);
+               virtual_keyboard_window.set_state (*ui_xml, 0);
                audio_port_matrix.set_state (*ui_xml, 0);
                midi_port_matrix.set_state (*ui_xml, 0);
                export_video_dialog.set_state (*ui_xml, 0);
@@ -519,6 +522,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        WM::Manager::instance().register_window (&location_ui);
        WM::Manager::instance().register_window (&big_clock_window);
        WM::Manager::instance().register_window (&big_transport_window);
+       WM::Manager::instance().register_window (&virtual_keyboard_window);
        WM::Manager::instance().register_window (&audio_port_matrix);
        WM::Manager::instance().register_window (&midi_port_matrix);
        WM::Manager::instance().register_window (&idleometer);
index 8e733760102cbdeee07a1c2c979237b290f72657..611fefb823ad44ceb2268a0347edfd7d858a93ae 100644 (file)
 #include "session_option_editor.h"
 #include "speaker_dialog.h"
 #include "transport_masters_dialog.h"
+#include "virtual_keyboard_window.h"
 #else
 class About;
 class AddRouteDialog;
@@ -137,6 +138,7 @@ class GlobalPortMatrixWindow;
 class IdleOMeter;
 class PluginDSPLoadWindow;
 class TransportMastersWindow;
+class VirtualKeyboardWindow;
 #endif
 
 class VideoTimeLine;
@@ -720,6 +722,7 @@ private:
        WM::ProxyWithConstructor<BundleManager> bundle_manager;
        WM::ProxyWithConstructor<BigClockWindow> big_clock_window;
        WM::ProxyWithConstructor<BigTransportWindow> big_transport_window;
+       WM::ProxyWithConstructor<VirtualKeyboardWindow> virtual_keyboard_window;
        WM::ProxyWithConstructor<GlobalPortMatrixWindow> audio_port_matrix;
        WM::ProxyWithConstructor<GlobalPortMatrixWindow> midi_port_matrix;
        WM::ProxyWithConstructor<KeyEditor> key_editor;
@@ -731,6 +734,7 @@ private:
        AddVideoDialog*         create_add_video_dialog ();
        BigClockWindow*         create_big_clock_window();
        BigTransportWindow*     create_big_transport_window();
+       VirtualKeyboardWindow*  create_virtual_keyboard_window();
        GlobalPortMatrixWindow* create_global_port_matrix (ARDOUR::DataType);
        KeyEditor*              create_key_editor ();
 
index f56f4c6adce831fddfe1b3260bb2f32a54976340..8625b92210b56710045700325ac15c2a7640b15b 100644 (file)
@@ -82,6 +82,7 @@
 #include "time_info_box.h"
 #include "timers.h"
 #include "transport_masters_dialog.h"
+#include "virtual_keyboard_window.h"
 
 #include "pbd/i18n.h"
 
@@ -103,6 +104,10 @@ ARDOUR_UI::set_session (Session *s)
                big_transport_window->set_session (s);
        }
 
+       if (virtual_keyboard_window) {
+               virtual_keyboard_window->set_session (s);
+       }
+
        if (!_session) {
                WM::Manager::instance().set_session (s);
                /* Session option editor cannot exist across change-of-session */
@@ -887,6 +892,14 @@ ARDOUR_UI::create_big_transport_window ()
        return btw;
 }
 
+VirtualKeyboardWindow*
+ARDOUR_UI::create_virtual_keyboard_window ()
+{
+       VirtualKeyboardWindow* vkbd = new VirtualKeyboardWindow ();
+       vkbd->set_session (_session);
+       return vkbd;
+}
+
 void
 ARDOUR_UI::handle_locations_change (Location *)
 {
@@ -912,6 +925,9 @@ ARDOUR_UI::tabbed_window_state_event_handler (GdkEventWindowState* ev, void* obj
                        if (big_transport_window) {
                                big_transport_window->set_transient_for (*editor->own_window());
                        }
+                       if (virtual_keyboard_window) {
+                               virtual_keyboard_window->set_transient_for (*editor->own_window());
+                       }
                }
 
        } else if (object == mixer) {
@@ -924,6 +940,9 @@ ARDOUR_UI::tabbed_window_state_event_handler (GdkEventWindowState* ev, void* obj
                        if (big_transport_window) {
                                big_transport_window->set_transient_for (*mixer->own_window());
                        }
+                       if (virtual_keyboard_window) {
+                               virtual_keyboard_window->set_transient_for (*mixer->own_window());
+                       }
                }
        }
 
index 7604a29eb83ff7d574b4e99a0208e97158d6b0ca..ca3a73643b6a30a2e80f47a5243ac60f9a2a31f2 100644 (file)
@@ -489,6 +489,18 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
                }
        }
 
+       /* virtual keyboard */
+       if ((type == DataType::MIDI || type == DataType::NIL)) {
+               AudioEngine* ae = AudioEngine::instance();
+               if (!inputs) {
+                       boost::shared_ptr<Bundle> vm (new Bundle (_("Virtual MIDI"), inputs));
+                       vm->add_channel (
+                               _("Virtual Keyboard"), DataType::MIDI, ae->make_port_name_non_relative (session->vkbd_output_port()->name())
+                               );
+                       program->add_bundle (vm);
+               }
+       }
+
        /* our sync ports */
 
        if ((type == DataType::MIDI || type == DataType::NIL)) {
diff --git a/gtk2_ardour/virtual_keyboard_window.cc b/gtk2_ardour/virtual_keyboard_window.cc
new file mode 100644 (file)
index 0000000..65efd08
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2019 Robin Gareus <robin@gareus.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gtkmm/box.h>
+
+#include "ardour/async_midi_port.h"
+
+#include "ardour_ui.h"
+#include "virtual_keyboard_window.h"
+#include "utils.h"
+
+#include "pbd/i18n.h"
+
+using namespace Glib;
+using namespace Gtk;
+
+VirtualKeyboardWindow::VirtualKeyboardWindow ()
+       : ArdourWindow (_("Virtual Keyboard"))
+       , _piano_velocity (*manage (new Adjustment (100, 1, 127, 1, 16)))
+       , _piano_channel (*manage (new Adjustment (0, 1, 16, 1, 1)))
+{
+       _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);
+
+       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_keyboard_set_keyboard_layout (_piano, "QWERTY");
+
+       HBox* box = manage (new HBox);
+       box->pack_start (*manage (new Label (_("Channel:"))), false, false);
+       box->pack_start (_piano_channel, false, false);
+       box->pack_start (*manage (new Label (_("Velocity:"))), false, false);
+       box->pack_start (_piano_velocity, false, false);
+
+       Box* box2 = manage (new HBox ());
+       box2->pack_start (*box, true, false);
+
+       VBox* vbox = manage (new VBox);
+       vbox->pack_start (*box2, false, false, 4);
+       vbox->pack_start (*_pianomm, true, true);
+       add (*vbox);
+
+       set_keep_above (true);
+       vbox->show_all();
+}
+
+VirtualKeyboardWindow::~VirtualKeyboardWindow ()
+{
+       delete _pianomm;
+}
+
+void
+VirtualKeyboardWindow::on_unmap ()
+{
+       ArdourWindow::on_unmap ();
+       ARDOUR_UI::instance()->reset_focus (this);
+}
+
+bool
+VirtualKeyboardWindow::on_key_press_event (GdkEventKey* ev)
+{
+       return ARDOUR_UI_UTILS::relay_key_press (ev, this);
+}
+
+void
+VirtualKeyboardWindow::note_on_event_handler (int note)
+{
+       _pianomm->grab_focus ();
+       if (!_session) {
+               return;
+       }
+       uint8_t channel = _piano_channel.get_value_as_int () - 1;
+       uint8_t ev[3];
+       ev[0] = (MIDI_CMD_NOTE_ON | channel);
+       ev[1] = note;
+       ev[2] = _piano_velocity.get_value_as_int ();
+       boost::dynamic_pointer_cast<ARDOUR::AsyncMIDIPort>(_session->vkbd_output_port())->write (ev, 3, 0);
+}
+
+void
+VirtualKeyboardWindow::note_off_event_handler (int note)
+{
+       if (!_session) {
+               return;
+       }
+
+       uint8_t channel = _piano_channel.get_value_as_int () - 1;
+       uint8_t ev[3];
+       ev[0] = (MIDI_CMD_NOTE_OFF | channel);
+       ev[1] = note;
+       ev[2] = 0;
+       boost::dynamic_pointer_cast<ARDOUR::AsyncMIDIPort>(_session->vkbd_output_port())->write (ev, 3, 0);
+}
diff --git a/gtk2_ardour/virtual_keyboard_window.h b/gtk2_ardour/virtual_keyboard_window.h
new file mode 100644 (file)
index 0000000..af09f74
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2019 Robin Gareus <robin@gareus.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _virtual_keyboard_window_h_
+#define _virtual_keyboard_window_h_
+
+#include "ardour_window.h"
+#include "gtk_pianokeyboard.h"
+
+namespace ARDOUR {
+       class Session;
+}
+
+class VirtualKeyboardWindow : public ArdourWindow
+{
+public:
+       VirtualKeyboardWindow ();
+       ~VirtualKeyboardWindow ();
+
+protected:
+       void on_unmap ();
+       bool on_key_press_event (GdkEventKey*);
+
+private:
+       static void _note_on_event_handler (GtkWidget*, int note, gpointer arg)
+       {
+               static_cast<VirtualKeyboardWindow*>(arg)->note_on_event_handler(note);
+       }
+
+       static void _note_off_event_handler (GtkWidget*, int note, gpointer arg) 
+       {
+               static_cast<VirtualKeyboardWindow*>(arg)->note_off_event_handler(note);
+       }
+
+       void note_on_event_handler  (int);
+       void note_off_event_handler (int);
+
+       PianoKeyboard*  _piano;
+       Gtk::Widget*    _pianomm;
+       Gtk::SpinButton _piano_velocity;
+       Gtk::SpinButton _piano_channel;
+};
+
+#endif
index e80e5da4fcd7bda8532d828e7a7c849a01b77359..0845013f7571edd7fd1c304f0039de0c4320aee7 100644 (file)
@@ -284,6 +284,7 @@ gtk2_ardour_sources = [
         'utils.cc',
         'vca_master_strip.cc',
         'verbose_cursor.cc',
+        'virtual_keyboard_window.cc',
         'visibility_group.cc',
         'window_manager.cc',
 # video-timeline related sources: