X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fluawindow.cc;h=90fa41a166a3f2512f58055c383063915de33c02;hb=3c25d26e91d4703ba76c90d5175aa94e4ddd850b;hp=98846275f477e1586641a7bedd42aed7a20d929d;hpb=28b707061b0edd72760e2e46bc15999e8a8c73b8;p=ardour.git diff --git a/gtk2_ardour/luawindow.cc b/gtk2_ardour/luawindow.cc index 98846275f4..90fa41a166 100644 --- a/gtk2_ardour/luawindow.cc +++ b/gtk2_ardour/luawindow.cc @@ -25,6 +25,7 @@ #include "gtk2ardour-config.h" #endif +#include "pbd/gstdio_compat.h" #include #include @@ -33,9 +34,11 @@ #include "pbd/md5.h" #include "gtkmm2ext/gtk_ui.h" +#include "gtkmm2ext/pane.h" #include "gtkmm2ext/utils.h" #include "gtkmm2ext/window_title.h" +#include "ardour/filesystem_paths.h" #include "ardour/luabindings.h" #include "LuaBridge/LuaBridge.h" @@ -46,8 +49,9 @@ #include "public_editor.h" #include "tooltips.h" #include "utils.h" +#include "utils_videotl.h" -#include "i18n.h" +#include "pbd/i18n.h" using namespace ARDOUR; using namespace ARDOUR_UI_UTILS; @@ -85,19 +89,22 @@ LuaWindow::instance () LuaWindow::LuaWindow () : Window (Gtk::WINDOW_TOPLEVEL) , VisibilityTracker (*((Gtk::Window*) this)) + , lua (0) , _visible (false) , _menu_scratch (0) , _menu_snippet (0) , _menu_actions (0) , _btn_run (_("Run")) - , _btn_clear (_("Clear Outtput")) + , _btn_clear (_("Clear Output")) , _btn_open (_("Import")) , _btn_save (_("Save")) , _btn_delete (_("Delete")) + , _btn_revert (_("Revert")) , _current_buffer () { set_name ("Lua"); + reinit_lua (); update_title (); set_wmclass (X_("ardour_mixer"), PROGRAM_NAME); @@ -117,10 +124,12 @@ LuaWindow::LuaWindow () _btn_open.signal_clicked.connect (sigc::mem_fun(*this, &LuaWindow::import_script)); _btn_save.signal_clicked.connect (sigc::mem_fun(*this, &LuaWindow::save_script)); _btn_delete.signal_clicked.connect (sigc::mem_fun(*this, &LuaWindow::delete_script)); + _btn_revert.signal_clicked.connect (sigc::mem_fun(*this, &LuaWindow::revert_script)); _btn_open.set_sensitive (false); // TODO _btn_save.set_sensitive (false); - _btn_delete.set_sensitive (false); // TODO + _btn_delete.set_sensitive (false); + _btn_revert.set_sensitive (false); // layout @@ -130,6 +139,9 @@ LuaWindow::LuaWindow () scrollout.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_ALWAYS); scrollout.add (outtext); + entry.set_name ("ArdourLuaEntry"); + outtext.set_name ("ArdourLuaEntry"); + Gtk::HBox *hbox = manage (new HBox()); hbox->pack_start (_btn_run, false, false, 2); @@ -137,39 +149,33 @@ LuaWindow::LuaWindow () hbox->pack_start (_btn_open, false, false, 2); hbox->pack_start (_btn_save, false, false, 2); hbox->pack_start (_btn_delete, false, false, 2); + hbox->pack_start (_btn_revert, false, false, 2); hbox->pack_start (script_select, false, false, 2); Gtk::VBox *vbox = manage (new VBox()); vbox->pack_start (*scrollin, true, true, 0); vbox->pack_start (*hbox, false, false, 2); - Gtk::VPaned *vpane = manage (new Gtk::VPaned ()); - vpane->pack1 (*vbox, true, false); - vpane->pack2 (scrollout, false, true); + Gtkmm2ext::VPane *vpane = manage (new Gtkmm2ext::VPane ()); + vpane->add (*vbox); + vpane->add (scrollout); + vpane->set_divider (0, 0.75); vpane->show_all (); add (*vpane); set_size_request (640, 480); // XXX - - lua.Print.connect (sigc::mem_fun (*this, &LuaWindow::append_text)); - - lua_State* L = lua.getState(); - LuaInstance::register_classes (L); - luabridge::push (L, &PublicEditor::instance()); - lua_setglobal (L, "Editor"); - ARDOUR_UI_UTILS::set_tooltip (script_select, _("Select Editor Buffer")); setup_buffers (); LuaScripting::instance().scripts_changed.connect (*this, invalidator (*this), boost::bind (&LuaWindow::refresh_scriptlist, this), gui_context()); Glib::RefPtr tb (entry.get_buffer()); - _script_changed_connection = tb->signal_changed().connect (sigc::mem_fun(*this, &LuaWindow::script_changed)); } LuaWindow::~LuaWindow () { + delete lua; } void @@ -187,6 +193,19 @@ LuaWindow::hide_window (GdkEventAny *ev) return just_hide_it (ev, static_cast(this)); } +void LuaWindow::reinit_lua () +{ + ENSURE_GUI_THREAD (*this, &LuaWindow::session_going_away); + delete lua; + lua = new LuaState(); + lua->Print.connect (sigc::mem_fun (*this, &LuaWindow::append_text)); + + lua_State* L = lua->getState(); + LuaInstance::register_classes (L); + luabridge::push (L, &PublicEditor::instance()); + lua_setglobal (L, "Editor"); +} + void LuaWindow::set_session (Session* s) { SessionHandlePtr::set_session (s); @@ -197,8 +216,7 @@ void LuaWindow::set_session (Session* s) 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(); + lua_State* L = lua->getState(); LuaBindings::set_session (L, _session); } @@ -206,14 +224,13 @@ 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) ?? + reinit_lua (); // drop state (all variables, session references) SessionHandlePtr::session_going_away (); _session = 0; update_title (); - lua_State* L = lua.getState(); + lua_State* L = lua->getState(); LuaBindings::set_session (L, _session); } @@ -262,8 +279,8 @@ LuaWindow::run_script () if (bytecode.empty()) { // plain script or faulty script -- run directly try { - lua.do_command ("function ardour () end"); - if (0 == lua.do_command (script)) { + lua->do_command ("function ardour () end"); + if (0 == lua->do_command (script)) { append_text ("> OK"); } } catch (luabridge::LuaException const& e) { @@ -272,18 +289,18 @@ LuaWindow::run_script () } else { // script with factory method try { - lua_State* L = lua.getState(); - lua.do_command ("function ardour () end"); + lua_State* L = lua->getState(); + lua->do_command ("function ardour () end"); LuaScriptParamList args = LuaScriptParams::script_params (script, "action_param", false); luabridge::LuaRef tbl_arg (luabridge::newTable(L)); LuaScriptParams::params_to_ref (&tbl_arg, args); - lua.do_command (script); // register "factory" + lua->do_command (script); // register "factory" luabridge::LuaRef lua_factory = luabridge::getGlobal (L, "factory"); if (lua_factory.isFunction()) { lua_factory(tbl_arg)(); } - lua.do_command ("factory = nil;"); + lua->do_command ("factory = nil;"); } catch (luabridge::LuaException const& e) { append_text (string_compose (_("LuaException: %1"), e.what())); } @@ -296,6 +313,7 @@ LuaWindow::append_text (std::string s) Glib::RefPtr tb (outtext.get_buffer()); tb->insert (tb->end(), s + "\n"); scroll_to_bottom (); + Gtkmm2ext::UI::instance()->flush_pending (0.05); } void @@ -305,27 +323,86 @@ LuaWindow::clear_output () tb->set_text (""); } +void +LuaWindow::edit_script (const std::string& name, const std::string& script) +{ + ScriptBuffer* sb = new LuaWindow::ScriptBuffer (name); + sb->script = script; + script_buffers.push_back (ScriptBufferPtr (sb)); + script_selection_changed (script_buffers.back ()); + refresh_scriptlist (); + show_window (); +} + void LuaWindow::new_script () { -#if 0 - Glib::RefPtr tb (entry.get_buffer()); - tb->set_text (""); -#endif + char buf[32]; + snprintf (buf, sizeof (buf), "#%d", count_scratch_buffers () + 1); + script_buffers.push_back (ScriptBufferPtr (new LuaWindow::ScriptBuffer (buf))); + script_selection_changed (script_buffers.back ()); + refresh_scriptlist (); } void LuaWindow::delete_script () { -#if 0 - Glib::RefPtr tb (entry.get_buffer()); - tb->set_text (""); -#endif + assert ((_current_buffer->flags & Buffer_Scratch) || !(_current_buffer->flags & Buffer_ReadOnly)); + bool refresh = false; + bool neednew = true; + if (_current_buffer->flags & Buffer_HasFile) { + if (0 == ::g_unlink (_current_buffer->path.c_str())) { + append_text (X_("> ") + string_compose (_("Deleted %1"), _current_buffer->path)); + refresh = true; + } else { + append_text (X_("> ") + string_compose (_("Failed to delete %1"), _current_buffer->path)); + } + } + for (ScriptBufferList::iterator i = script_buffers.begin (); i != script_buffers.end (); ++i) { + if ((*i) == _current_buffer) { + script_buffers.erase (i); + break; + } + } + + for (ScriptBufferList::const_iterator i = script_buffers.begin (); i != script_buffers.end (); ++i) { + if ((*i)->flags & Buffer_Scratch) { + script_selection_changed (*i); + neednew = false; + } + } + if (neednew) { + new_script (); + } + if (refresh) { + LuaScripting::instance ().refresh (true); + } +} + +void +LuaWindow::revert_script () +{ + _current_buffer->flags &= BufferFlags(~Buffer_Valid); + script_selection_changed (_current_buffer, true); } void LuaWindow::import_script () { + // TODO: dialog to select file or enter URL + // TODO convert a few URL (eg. pastebin) to raw. +#if 0 + char *url = "http://pastebin.com/raw/3UMkZ6nV"; + char *rv = ArdourCurl::http_get (url, 0); + if (rv) { + new_script (); + Glib::RefPtr tb (entry.get_buffer()); + tb->set_text (rv); + _current_buffer->flags &= BufferFlags(~Buffer_Dirty); + update_gui_state (); + } + free (rv); +#endif } void @@ -369,6 +446,7 @@ LuaWindow::save_script () if ((sb.flags & Buffer_HasFile) && !(sb.flags & Buffer_ReadOnly)) { try { Glib::file_set_contents (sb.path, script); + sb.name = lsi->name; sb.flags &= BufferFlags(~Buffer_Dirty); update_gui_state (); // XXX here? append_text (X_("> ") + string_compose (_("Saved as %1"), sb.path)); @@ -396,7 +474,7 @@ LuaWindow::save_script () time_t t = time(0); struct tm * timeinfo = localtime (&t); strftime (buf, sizeof(buf), "%s%d", timeinfo); - sprintf (buf, "%s%d", buf, random ()); // is this valid? + sprintf (buf, "%s%ld", buf, random ()); // is this valid? MD5 md5; std::string fn = md5.digestString (buf); @@ -416,9 +494,11 @@ LuaWindow::save_script () try { Glib::file_set_contents (path, script); sb.path = path; + sb.name = lsi->name; sb.flags |= Buffer_HasFile; sb.flags &= BufferFlags(~Buffer_Dirty); - update_gui_state (); // XXX here? + sb.flags &= BufferFlags(~Buffer_ReadOnly); + update_gui_state (); // XXX here? .refresh (true) may trigger this, too LuaScripting::instance().refresh (true); append_text (X_("> ") + string_compose (_("Saved as %1"), path)); return; // OK @@ -439,9 +519,11 @@ LuaWindow::setup_buffers () return; } script_buffers.push_back (ScriptBufferPtr (new LuaWindow::ScriptBuffer("#1"))); - script_buffers.push_back (ScriptBufferPtr (new LuaWindow::ScriptBuffer("#2"))); // XXX _current_buffer = script_buffers.front(); + Glib::RefPtr tb (entry.get_buffer()); + tb->set_text (_current_buffer->script); + refresh_scriptlist (); update_gui_state (); } @@ -449,7 +531,13 @@ LuaWindow::setup_buffers () uint32_t LuaWindow::count_scratch_buffers () const { - return 0; + uint32_t n = 0; + for (ScriptBufferList::const_iterator i = script_buffers.begin (); i != script_buffers.end (); ++i) { + if ((*i)->flags & Buffer_Scratch) { + ++n; + } + } + return n; } void @@ -464,12 +552,12 @@ LuaWindow::refresh_scriptlist () } LuaScriptList& lsa (LuaScripting::instance ().scripts (LuaScriptInfo::EditorAction)); for (LuaScriptList::const_iterator s = lsa.begin(); s != lsa.end(); ++s) { - script_buffers.push_back (ScriptBufferPtr ( new LuaWindow::ScriptBuffer(*s))); + script_buffers.push_back (ScriptBufferPtr (new LuaWindow::ScriptBuffer(*s))); } LuaScriptList& lss (LuaScripting::instance ().scripts (LuaScriptInfo::Snippet)); for (LuaScriptList::const_iterator s = lss.begin(); s != lss.end(); ++s) { - script_buffers.push_back (ScriptBufferPtr ( new LuaWindow::ScriptBuffer(*s))); + script_buffers.push_back (ScriptBufferPtr (new LuaWindow::ScriptBuffer(*s))); } rebuild_menu (); } @@ -493,9 +581,17 @@ LuaWindow::rebuild_menu () items_scratch.push_back(elem); } + items_scratch.push_back(SeparatorElem()); + for (ScriptBufferList::const_iterator i = script_buffers.begin (); i != script_buffers.end (); ++i) { - Menu_Helpers::MenuElem elem = Gtk::Menu_Helpers::MenuElem((*i)->name, - sigc::bind(sigc::mem_fun(*this, &LuaWindow::script_selection_changed), (*i))); + std::string name; + if ((*i)->flags & Buffer_ReadOnly) { + name = "[R] " + (*i)->name; + } else { + name = (*i)->name; + } + Menu_Helpers::MenuElem elem = Gtk::Menu_Helpers::MenuElem(name, + sigc::bind(sigc::mem_fun(*this, &LuaWindow::script_selection_changed), (*i), false)); if ((*i)->flags & Buffer_Scratch) { items_scratch.push_back(elem); @@ -515,14 +611,17 @@ LuaWindow::rebuild_menu () } void -LuaWindow::script_selection_changed (ScriptBufferPtr n) +LuaWindow::script_selection_changed (ScriptBufferPtr n, bool force) { - if (n == _current_buffer) { + if (n == _current_buffer && !force) { return; } Glib::RefPtr tb (entry.get_buffer()); - _current_buffer->script = tb->get_text(); + + if (_current_buffer->flags & Buffer_Valid) { + _current_buffer->script = tb->get_text(); + } if (!(n->flags & Buffer_Valid)) { if (!n->load()) { @@ -562,8 +661,14 @@ LuaWindow::update_gui_state () } script_select.set_text(name); + if (sb.flags & Buffer_ReadOnly) { + _btn_save.set_text (_("Save as")); + } else { + _btn_save.set_text (_("Save")); + } _btn_save.set_sensitive (sb.flags & Buffer_Dirty); - _btn_delete.set_sensitive (sb.flags & Buffer_Scratch); // TODO allow to remove user-scripts + _btn_delete.set_sensitive (sb.flags & Buffer_Scratch || ((sb.flags & (Buffer_ReadOnly | Buffer_HasFile)) == Buffer_HasFile)); + _btn_revert.set_sensitive ((sb.flags & Buffer_Dirty) && (sb.flags & Buffer_HasFile)); } void @@ -579,6 +684,10 @@ LuaWindow::ScriptBuffer::ScriptBuffer (const std::string& n) : name (n) , flags (Buffer_Scratch | Buffer_Valid) { + script = + "---- this header is (only) required to save the script\n" + "-- ardour { [\"type\"] = \"Snippet\", name = \"\" }\n" + "-- function factory () return function () -- -- end end\n"; } LuaWindow::ScriptBuffer::ScriptBuffer (LuaScriptInfoPtr p) @@ -590,6 +699,10 @@ LuaWindow::ScriptBuffer::ScriptBuffer (LuaScriptInfoPtr p) if (!PBD::exists_and_writable (path)) { flags |= Buffer_ReadOnly; } + if (path.find (user_config_directory ()) != 0) { + // mark non-user scripts as read-only + flags |= Buffer_ReadOnly; + } } #if 0 @@ -610,11 +723,12 @@ LuaWindow::ScriptBuffer::~ScriptBuffer () bool LuaWindow::ScriptBuffer::load () { + assert (!(flags & Buffer_Valid)); if (!(flags & Buffer_HasFile)) return false; - if (flags & Buffer_Valid) return true; try { script = Glib::file_get_contents (path); flags |= Buffer_Valid; + flags &= BufferFlags(~Buffer_Dirty); } catch (Glib::FileError e) { return false; }