Lua Script Console Window
authorRobin Gareus <robin@gareus.org>
Tue, 23 Feb 2016 14:42:13 +0000 (15:42 +0100)
committerRobin Gareus <robin@gareus.org>
Tue, 23 Feb 2016 14:42:13 +0000 (15:42 +0100)
gtk2_ardour/ardour.menus.in
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui.h
gtk2_ardour/ardour_ui_dependents.cc
gtk2_ardour/ardour_ui_dialogs.cc
gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/luawindow.cc [new file with mode: 0644]
gtk2_ardour/luawindow.h [new file with mode: 0644]
gtk2_ardour/wscript

index b05989fe7aa97120db6d3b4d38816251500085f3..bf79009b56681e8363b2959804e0439f338353e7 100644 (file)
           <menuitem action='detach-preferences'/>
       </menu>
       <menuitem action='toggle-meterbridge'/>
+      <menuitem action='toggle-luawindow'/>
       <separator/>
       <menuitem action='toggle-inspector'/>
       <menuitem action='toggle-locations'/>
index 9e48335ff7959b86191bbc69140da3b572104ec3..da2323b80a277d55b4fc96f3d359294f49a27370 100644 (file)
@@ -124,6 +124,7 @@ typedef uint64_t microseconds_t;
 #include "keyboard.h"
 #include "keyeditor.h"
 #include "location_ui.h"
+#include "luawindow.h"
 #include "main_clock.h"
 #include "missing_file_dialog.h"
 #include "missing_plugin_dialog.h"
@@ -263,6 +264,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        , last_key_press_time (0)
        , save_as_dialog (0)
        , meterbridge (0)
+       , luawindow (0)
        , rc_option_editor (0)
        , speaker_config_window (X_("speaker-config"), _("Speaker Configuration"))
        , add_route_dialog (X_("add-routes"), _("Add Tracks/Busses"))
@@ -654,6 +656,7 @@ ARDOUR_UI::~ARDOUR_UI ()
                delete secondary_clock;
                delete _process_thread;
                delete meterbridge;
+               delete luawindow;
                delete editor;
                delete mixer;
                delete nsm;
index 2d76d7eaad580d8bdf0977e921bc972e6775d32a..88006a082076d850322bd59be3176db63718b4e0 100644 (file)
@@ -126,6 +126,8 @@ class ShuttleControl;
 class Splash;
 class TimeInfoBox;
 class Meterbridge;
+class LuaWindow;
+class LuaScriptManager;
 class MidiTracer;
 class NSM_Client;
 class LevelMeterHBox;
@@ -208,6 +210,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
        void toggle_monitor_section_visibility ();
        void toggle_keep_tearoffs();
 
+       void lua_script_manager();
+
        static PublicEditor* _instance;
 
        /** Emitted frequently with the audible frame, false, and the edit point as
@@ -256,6 +260,9 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
 
        void start_duplicate_routes ();
 
+       void add_lua_script ();
+       void remove_lua_script ();
+
        void add_video (Gtk::Window* float_window);
        void remove_video ();
        void start_video_server_menu (Gtk::Window* float_window);
@@ -383,6 +390,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
        void tabbable_state_change (Gtkmm2ext::Tabbable&);
 
        void toggle_meterbridge ();
+       void toggle_luawindow ();
 
        int  setup_windows ();
        void setup_transport ();
@@ -645,9 +653,11 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
 
        int         create_mixer ();
        int         create_editor ();
+       int         create_meterbridge ();
+       int         create_luawindow ();
 
        Meterbridge  *meterbridge;
-       int         create_meterbridge ();
+       LuaWindow    *luawindow;
 
         /* Dialogs that can be created via new<T> */
 
@@ -661,6 +671,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
         WM::Proxy<RouteParams_UI> route_params;
         WM::Proxy<EngineControl> audio_midi_setup;
         WM::Proxy<ExportVideoDialog> export_video_dialog;
+        WM::Proxy<LuaScriptManager> lua_script_window;
 
         /* Windows/Dialogs that require a creator method */
 
index 939c7d0eebd125956facfbf44b7ac8ec92a40c79..b67b3a83bb70a4e6d71216a780877d408d67052d 100644 (file)
@@ -37,6 +37,7 @@
 #include "ardour_ui.h"
 #include "public_editor.h"
 #include "meterbridge.h"
+#include "luawindow.h"
 #include "mixer_ui.h"
 #include "keyboard.h"
 #include "splash.h"
@@ -119,6 +120,7 @@ ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s)
        BootMessage (_("Setup Mixer"));
        mixer->set_session (s);
        meterbridge->set_session (s);
+       luawindow->set_session (s);
 
        /* its safe to do this now */
 
@@ -257,6 +259,11 @@ ARDOUR_UI::setup_windows ()
                return -1;
        }
 
+       if (create_luawindow ()) {
+               error << _("UI: cannot setup luawindow") << endmsg;
+               return -1;
+       }
+
        /* order of addition affects order seen in initial window display */
 
        rc_option_editor->add_to_notebook (_tabs, _("Preferences"));
index 9618b4c5caec83792be331eb236ec4f8dadcdbc6..25f8243ec9e3d6d06b607dda98080fdd98291382 100644 (file)
@@ -49,6 +49,7 @@
 #include "gui_thread.h"
 #include "keyeditor.h"
 #include "location_ui.h"
+#include "luawindow.h"
 #include "main_clock.h"
 #include "meterbridge.h"
 #include "meter_patterns.h"
@@ -666,6 +667,29 @@ ARDOUR_UI::toggle_meterbridge ()
        }
 }
 
+void
+ARDOUR_UI::toggle_luawindow ()
+{
+       assert (editor && luawindow);
+
+       bool show = false;
+       bool obscuring = false;
+
+       if (luawindow->not_visible ()) {
+               show = true;
+       }
+       // TODO check overlap
+
+       if (show) {
+               luawindow->show_window ();
+               luawindow->present ();
+               luawindow->raise ();
+       } else {
+               luawindow->hide_window (NULL);
+       }
+}
+
+
 void
 ARDOUR_UI::new_midi_tracer_window ()
 {
index f091d070ca56dcbc4eca2eaf72a7b03a5d055370..d5e6968f89784e592de14275c61d8a375e97172e 100644 (file)
@@ -51,6 +51,7 @@
 #include "editor.h"
 #include "actions.h"
 #include "meterbridge.h"
+#include "luawindow.h"
 #include "mixer_ui.h"
 #include "startup.h"
 #include "window_manager.h"
@@ -93,6 +94,20 @@ ARDOUR_UI::create_editor ()
        return 0;
 }
 
+int
+ARDOUR_UI::create_luawindow ()
+
+{
+       try {
+               luawindow = LuaWindow::instance ();
+       }
+       catch (failed_constructor& err) {
+               return -1;
+       }
+
+       return 0;
+}
+
 void
 ARDOUR_UI::install_actions ()
 {
@@ -273,6 +288,7 @@ ARDOUR_UI::install_actions ()
                global_actions.register_action (common_actions, X_("show-ui-prefs"), _("Show more UI preferences"), sigc::mem_fun (*this, &ARDOUR_UI::show_ui_prefs));
        }
 
+       global_actions.register_action (common_actions, X_("toggle-luawindow"), S_("Window|Scripting"),  sigc::mem_fun(*this, &ARDOUR_UI::toggle_luawindow));
        global_actions.register_action (common_actions, X_("toggle-meterbridge"), S_("Window|Meterbridge"),  sigc::mem_fun(*this, &ARDOUR_UI::toggle_meterbridge));
 
        act = global_actions.register_action (common_actions, X_("NewMIDITracer"), _("MIDI Tracer"), sigc::mem_fun(*this, &ARDOUR_UI::new_midi_tracer_window));
diff --git a/gtk2_ardour/luawindow.cc b/gtk2_ardour/luawindow.cc
new file mode 100644 (file)
index 0000000..5fda4f2
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+    Copyright (C) 2016 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifdef WAF_BUILD
+#include "gtk2ardour-config.h"
+#endif
+
+#include <gtkmm2ext/gtk_ui.h>
+#include <gtkmm2ext/utils.h>
+#include <gtkmm2ext/window_title.h>
+
+#include "ardour_ui.h"
+#include "gui_thread.h"
+#include "luainstance.h"
+#include "luawindow.h"
+#include "public_editor.h"
+#include "utils.h"
+
+#include "ardour/luabindings.h"
+#include "LuaBridge/LuaBridge.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace ARDOUR_UI_UTILS;
+using namespace PBD;
+using namespace Gtk;
+using namespace Glib;
+using namespace Gtkmm2ext;
+using namespace std;
+
+
+LuaWindow* LuaWindow::_instance = 0;
+
+LuaWindow*
+LuaWindow::instance ()
+{
+       if (!_instance) {
+               _instance  = new LuaWindow;
+       }
+
+       return _instance;
+}
+
+LuaWindow::LuaWindow ()
+       : Window (Gtk::WINDOW_TOPLEVEL)
+       , VisibilityTracker (*((Gtk::Window*) this))
+       , _visible (false)
+{
+       set_name ("Lua");
+
+       update_title ();
+       set_wmclass (X_("ardour_mixer"), PROGRAM_NAME);
+
+       set_border_width (0);
+
+       outtext.set_editable (false);
+       outtext.set_wrap_mode (Gtk::WRAP_WORD);
+
+       signal_delete_event().connect (sigc::mem_fun (*this, &LuaWindow::hide_window));
+       signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
+
+       scrollwin.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_ALWAYS);
+       scrollwin.add (outtext);
+
+       Gtk::Button *btn_clr = manage (new Button ("Clear"));
+       btn_clr->signal_clicked().connect (sigc::mem_fun(*this, &LuaWindow::clear_output));
+
+       Gtk::HBox *hbox = manage (new HBox());
+
+       hbox->pack_start (entry, true, true, 2);
+       hbox->pack_start (*btn_clr, false, false, 0);
+
+       Gtk::VBox *vbox = manage (new VBox());
+       vbox->pack_start (scrollwin, true, true, 0);
+       vbox->pack_start (*hbox, false, false, 2);
+
+       entry.signal_activate().connect (sigc::mem_fun (*this, &LuaWindow::entry_activated));
+
+       lua.Print.connect (sigc::mem_fun (*this, &LuaWindow::append_text));
+
+       vbox->show_all ();
+       add (*vbox);
+       set_size_request (640, 480); // XXX
+
+       LuaInstance::register_classes (lua.getState());
+       // TODO register some callback functions.
+
+       lua_State* L = lua.getState();
+       luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
+       lua_setglobal (L, "Editor");
+       // TODO
+       // - allow to load files
+       // - allow to run files directly
+       // - history buffer
+       // - multi-line input ??
+}
+
+LuaWindow::~LuaWindow ()
+{
+}
+
+void
+LuaWindow::show_window ()
+{
+       present();
+       _visible = true;
+}
+
+bool
+LuaWindow::hide_window (GdkEventAny *ev)
+{
+       if (!_visible) return 0;
+       _visible = false;
+       return just_hide_it (ev, static_cast<Gtk::Window *>(this));
+}
+
+void LuaWindow::set_session (Session* s)
+{
+       SessionHandlePtr::set_session (s);
+       if (!_session) {
+               return;
+       }
+
+       update_title ();
+       _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&LuaWindow::update_title, this), gui_context());
+
+       // expose "Session" point directly
+       lua_State* L = lua.getState();
+       LuaBindings::set_session (L, _session);
+}
+
+void
+LuaWindow::session_going_away ()
+{
+       ENSURE_GUI_THREAD (*this, &LuaWindow::session_going_away);
+       lua.do_command ("collectgarbage();");
+       //TODO: re-init lua-engine (drop all references) ??
+
+       SessionHandlePtr::session_going_away ();
+       _session = 0;
+       update_title ();
+
+       lua_State* L = lua.getState();
+       LuaBindings::set_session (L, _session);
+}
+
+void
+LuaWindow::update_title ()
+{
+       if (_session) {
+               string n;
+
+               if (_session->snap_name() != _session->name()) {
+                       n = _session->snap_name ();
+               } else {
+                       n = _session->name ();
+               }
+
+               if (_session->dirty ()) {
+                       n = "*" + n;
+               }
+
+               WindowTitle title (n);
+               title += S_("Window|Lua");
+               title += Glib::get_application_name ();
+               set_title (title.get_string());
+
+       } else {
+               WindowTitle title (S_("Window|Lua"));
+               title += Glib::get_application_name ();
+               set_title (title.get_string());
+       }
+}
+
+void
+LuaWindow::scroll_to_bottom ()
+{
+       Gtk::Adjustment *adj;
+       adj = scrollwin.get_vadjustment();
+       adj->set_value (MAX(0,(adj->get_upper() - adj->get_page_size())));
+}
+
+void
+LuaWindow::entry_activated ()
+{
+       std::string cmd = entry.get_text();
+       append_text ("> " + cmd);
+
+       if (0 == lua.do_command (cmd)) {
+               entry.set_text("");
+       }
+}
+
+void
+LuaWindow::append_text (std::string s)
+{
+       Glib::RefPtr<Gtk::TextBuffer> tb (outtext.get_buffer());
+       tb->insert (tb->end(), s + "\n");
+       scroll_to_bottom ();
+}
+
+void
+LuaWindow::clear_output ()
+{
+       Glib::RefPtr<Gtk::TextBuffer> tb (outtext.get_buffer());
+       tb->set_text ("");
+}
diff --git a/gtk2_ardour/luawindow.h b/gtk2_ardour/luawindow.h
new file mode 100644 (file)
index 0000000..9a7f281
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+    Copyright (C) 2016 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+#ifndef __ardour_luawindow_h__
+#define __ardour_luawindow_h__
+
+#include <glibmm/thread.h>
+
+#include <gtkmm/box.h>
+#include <gtkmm/scrolledwindow.h>
+#include <gtkmm/label.h>
+#include <gtkmm/window.h>
+
+#include "ardour/ardour.h"
+#include "ardour/types.h"
+#include "ardour/session_handle.h"
+
+#include "pbd/stateful.h"
+#include "pbd/signals.h"
+
+#include "gtkmm2ext/visibility_tracker.h"
+
+#include "lua/luastate.h"
+
+class LuaWindow :
+       public Gtk::Window,
+       public PBD::ScopedConnectionList,
+       public ARDOUR::SessionHandlePtr,
+       public Gtkmm2ext::VisibilityTracker
+{
+  public:
+       static LuaWindow* instance();
+       ~LuaWindow();
+
+       void show_window ();
+       bool hide_window (GdkEventAny *ev);
+
+       void set_session (ARDOUR::Session* s);
+
+  private:
+       LuaWindow ();
+       static LuaWindow* _instance;
+
+       bool _visible;
+       Gtk::VBox global_vpacker;
+
+       void session_going_away ();
+       void update_title ();
+
+       Gtk::Entry entry;
+       Gtk::TextView outtext;
+       Gtk::ScrolledWindow scrollwin;
+
+       void append_text (std::string s);
+       void scroll_to_bottom ();
+       void clear_output ();
+
+       void entry_activated ();
+
+       LuaState lua;
+};
+
+#endif
index 8d9a3362b4aac517ee068b0797a3a414682e2d97..de73078287ea3351662927abfdef921cdd0e4142 100644 (file)
@@ -123,6 +123,7 @@ gtk2_ardour_sources = [
         'level_meter.cc',
         'location_ui.cc',
         'luainstance.cc',
+        'luawindow.cc',
         'main.cc',
         'main_clock.cc',
         'marker.cc',