From 6b940afa36104e9d9d6c46828abb1182100689e3 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Tue, 23 Feb 2016 15:42:13 +0100 Subject: Lua Script Console Window --- gtk2_ardour/ardour.menus.in | 1 + gtk2_ardour/ardour_ui.cc | 3 + gtk2_ardour/ardour_ui.h | 13 ++- gtk2_ardour/ardour_ui_dependents.cc | 7 ++ gtk2_ardour/ardour_ui_dialogs.cc | 24 ++++ gtk2_ardour/ardour_ui_ed.cc | 16 +++ gtk2_ardour/luawindow.cc | 224 ++++++++++++++++++++++++++++++++++++ gtk2_ardour/luawindow.h | 78 +++++++++++++ gtk2_ardour/wscript | 1 + 9 files changed, 366 insertions(+), 1 deletion(-) create mode 100644 gtk2_ardour/luawindow.cc create mode 100644 gtk2_ardour/luawindow.h diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in index b05989fe7a..bf79009b56 100644 --- a/gtk2_ardour/ardour.menus.in +++ b/gtk2_ardour/ardour.menus.in @@ -528,6 +528,7 @@ + diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 9e48335ff7..da2323b80a 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -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; diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index 2d76d7eaad..88006a0820 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -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 */ @@ -661,6 +671,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr WM::Proxy route_params; WM::Proxy audio_midi_setup; WM::Proxy export_video_dialog; + WM::Proxy lua_script_window; /* Windows/Dialogs that require a creator method */ diff --git a/gtk2_ardour/ardour_ui_dependents.cc b/gtk2_ardour/ardour_ui_dependents.cc index 939c7d0eeb..b67b3a83bb 100644 --- a/gtk2_ardour/ardour_ui_dependents.cc +++ b/gtk2_ardour/ardour_ui_dependents.cc @@ -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")); diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc index 9618b4c5ca..25f8243ec9 100644 --- a/gtk2_ardour/ardour_ui_dialogs.cc +++ b/gtk2_ardour/ardour_ui_dialogs.cc @@ -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 () { diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index f091d070ca..d5e6968f89 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -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 index 0000000000..5fda4f2e24 --- /dev/null +++ b/gtk2_ardour/luawindow.cc @@ -0,0 +1,224 @@ +/* + Copyright (C) 2016 Robin Gareus + + 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 +#include +#include + +#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 (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(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 tb (outtext.get_buffer()); + tb->insert (tb->end(), s + "\n"); + scroll_to_bottom (); +} + +void +LuaWindow::clear_output () +{ + Glib::RefPtr tb (outtext.get_buffer()); + tb->set_text (""); +} diff --git a/gtk2_ardour/luawindow.h b/gtk2_ardour/luawindow.h new file mode 100644 index 0000000000..9a7f281f3e --- /dev/null +++ b/gtk2_ardour/luawindow.h @@ -0,0 +1,78 @@ +/* + Copyright (C) 2016 Robin Gareus + + 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 + +#include +#include +#include +#include + +#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 diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index 8d9a3362b4..de73078287 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -123,6 +123,7 @@ gtk2_ardour_sources = [ 'level_meter.cc', 'location_ui.cc', 'luainstance.cc', + 'luawindow.cc', 'main.cc', 'main_clock.cc', 'marker.cc', -- cgit v1.2.3