add new API to ARDOUR_UI to allow dynamic add/remove of keyboard bindings to key...
[ardour.git] / gtk2_ardour / luawindow.cc
1 /*
2     Copyright (C) 2016 Robin Gareus <robin@gareus.org>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifdef WAF_BUILD
21 #include "gtk2ardour-config.h"
22 #endif
23
24 #include <gtkmm2ext/gtk_ui.h>
25 #include <gtkmm2ext/utils.h>
26 #include <gtkmm2ext/window_title.h>
27
28 #include "ardour_ui.h"
29 #include "gui_thread.h"
30 #include "luainstance.h"
31 #include "luawindow.h"
32 #include "public_editor.h"
33 #include "utils.h"
34
35 #include "ardour/luabindings.h"
36 #include "LuaBridge/LuaBridge.h"
37
38 #include "i18n.h"
39
40 using namespace ARDOUR;
41 using namespace ARDOUR_UI_UTILS;
42 using namespace PBD;
43 using namespace Gtk;
44 using namespace Glib;
45 using namespace Gtkmm2ext;
46 using namespace std;
47
48
49 LuaWindow* LuaWindow::_instance = 0;
50
51 LuaWindow*
52 LuaWindow::instance ()
53 {
54         if (!_instance) {
55                 _instance  = new LuaWindow;
56         }
57
58         return _instance;
59 }
60
61 LuaWindow::LuaWindow ()
62         : Window (Gtk::WINDOW_TOPLEVEL)
63         , VisibilityTracker (*((Gtk::Window*) this))
64         , _visible (false)
65 {
66         set_name ("Lua");
67
68         update_title ();
69         set_wmclass (X_("ardour_mixer"), PROGRAM_NAME);
70
71         set_border_width (0);
72
73         outtext.set_editable (false);
74         outtext.set_wrap_mode (Gtk::WRAP_WORD);
75
76         signal_delete_event().connect (sigc::mem_fun (*this, &LuaWindow::hide_window));
77         signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
78
79         scrollwin.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_ALWAYS);
80         scrollwin.add (outtext);
81
82         Gtk::Button *btn_clr = manage (new Button ("Clear"));
83         btn_clr->signal_clicked().connect (sigc::mem_fun(*this, &LuaWindow::clear_output));
84
85         Gtk::HBox *hbox = manage (new HBox());
86
87         hbox->pack_start (entry, true, true, 2);
88         hbox->pack_start (*btn_clr, false, false, 0);
89
90         Gtk::VBox *vbox = manage (new VBox());
91         vbox->pack_start (scrollwin, true, true, 0);
92         vbox->pack_start (*hbox, false, false, 2);
93
94         entry.signal_activate().connect (sigc::mem_fun (*this, &LuaWindow::entry_activated));
95
96         lua.Print.connect (sigc::mem_fun (*this, &LuaWindow::append_text));
97
98         vbox->show_all ();
99         add (*vbox);
100         set_size_request (640, 480); // XXX
101
102         LuaInstance::register_classes (lua.getState());
103         // TODO register some callback functions.
104
105         lua_State* L = lua.getState();
106         luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
107         lua_setglobal (L, "Editor");
108         // TODO
109         // - allow to load files
110         // - allow to run files directly
111         // - history buffer
112         // - multi-line input ??
113 }
114
115 LuaWindow::~LuaWindow ()
116 {
117 }
118
119 void
120 LuaWindow::show_window ()
121 {
122         present();
123         _visible = true;
124 }
125
126 bool
127 LuaWindow::hide_window (GdkEventAny *ev)
128 {
129         if (!_visible) return 0;
130         _visible = false;
131         return just_hide_it (ev, static_cast<Gtk::Window *>(this));
132 }
133
134 void LuaWindow::set_session (Session* s)
135 {
136         SessionHandlePtr::set_session (s);
137         if (!_session) {
138                 return;
139         }
140
141         update_title ();
142         _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&LuaWindow::update_title, this), gui_context());
143
144         // expose "Session" point directly
145         lua_State* L = lua.getState();
146         LuaBindings::set_session (L, _session);
147 }
148
149 void
150 LuaWindow::session_going_away ()
151 {
152         ENSURE_GUI_THREAD (*this, &LuaWindow::session_going_away);
153         lua.do_command ("collectgarbage();");
154         //TODO: re-init lua-engine (drop all references) ??
155
156         SessionHandlePtr::session_going_away ();
157         _session = 0;
158         update_title ();
159
160         lua_State* L = lua.getState();
161         LuaBindings::set_session (L, _session);
162 }
163
164 void
165 LuaWindow::update_title ()
166 {
167         if (_session) {
168                 string n;
169
170                 if (_session->snap_name() != _session->name()) {
171                         n = _session->snap_name ();
172                 } else {
173                         n = _session->name ();
174                 }
175
176                 if (_session->dirty ()) {
177                         n = "*" + n;
178                 }
179
180                 WindowTitle title (n);
181                 title += S_("Window|Lua");
182                 title += Glib::get_application_name ();
183                 set_title (title.get_string());
184
185         } else {
186                 WindowTitle title (S_("Window|Lua"));
187                 title += Glib::get_application_name ();
188                 set_title (title.get_string());
189         }
190 }
191
192 void
193 LuaWindow::scroll_to_bottom ()
194 {
195         Gtk::Adjustment *adj;
196         adj = scrollwin.get_vadjustment();
197         adj->set_value (MAX(0,(adj->get_upper() - adj->get_page_size())));
198 }
199
200 void
201 LuaWindow::entry_activated ()
202 {
203         std::string cmd = entry.get_text();
204         append_text ("> " + cmd);
205
206         if (0 == lua.do_command (cmd)) {
207                 entry.set_text("");
208         }
209 }
210
211 void
212 LuaWindow::append_text (std::string s)
213 {
214         Glib::RefPtr<Gtk::TextBuffer> tb (outtext.get_buffer());
215         tb->insert (tb->end(), s + "\n");
216         scroll_to_bottom ();
217 }
218
219 void
220 LuaWindow::clear_output ()
221 {
222         Glib::RefPtr<Gtk::TextBuffer> tb (outtext.get_buffer());
223         tb->set_text ("");
224 }