#include "gtk2ardour-config.h"
#endif
+#include "pbd/gstdio_compat.h"
#include <glibmm/fileutils.h>
#include <gtkmm/messagedialog.h>
#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"
#include "utils.h"
#include "utils_videotl.h"
-#include "i18n.h"
+#include "pbd/i18n.h"
using namespace ARDOUR;
using namespace ARDOUR_UI_UTILS;
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);
_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);
+ _btn_revert.set_sensitive (false);
// layout
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);
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 <PublicEditor *> (L, &PublicEditor::instance());
- lua_setglobal (L, "Editor");
-
ARDOUR_UI_UTILS::set_tooltip (script_select, _("Select Editor Buffer"));
setup_buffers ();
LuaWindow::~LuaWindow ()
{
+ delete lua;
}
void
return just_hide_it (ev, static_cast<Gtk::Window *>(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 <PublicEditor *> (L, &PublicEditor::instance());
+ lua_setglobal (L, "Editor");
+}
+
void LuaWindow::set_session (Session* s)
{
SessionHandlePtr::set_session (s);
update_title ();
_session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&LuaWindow::update_title, this), gui_context());
- lua_State* L = lua.getState();
+ lua_State* L = lua->getState();
LuaBindings::set_session (L, _session);
}
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);
}
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) {
} 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()));
}
Glib::RefPtr<Gtk::TextBuffer> tb (outtext.get_buffer());
tb->insert (tb->end(), s + "\n");
scroll_to_bottom ();
+ Gtkmm2ext::UI::instance()->flush_pending (0.05);
}
void
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 ()
{
void
LuaWindow::delete_script ()
{
- assert (_current_buffer->flags & Buffer_Scratch);
+ 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);
for (ScriptBufferList::const_iterator i = script_buffers.begin (); i != script_buffers.end (); ++i) {
if ((*i)->flags & Buffer_Scratch) {
script_selection_changed (*i);
- return;
+ neednew = false;
}
}
- new_script ();
+ 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
// TODO convert a few URL (eg. pastebin) to raw.
#if 0
char *url = "http://pastebin.com/raw/3UMkZ6nV";
- char *rv = a3_curl_http_get (url, 0);
+ char *rv = ArdourCurl::http_get (url, 0);
if (rv) {
new_script ();
Glib::RefPtr<Gtk::TextBuffer> tb (entry.get_buffer());
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));
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
script_buffers.push_back (ScriptBufferPtr (new LuaWindow::ScriptBuffer("#1")));
_current_buffer = script_buffers.front();
+ Glib::RefPtr<Gtk::TextBuffer> tb (entry.get_buffer());
+ tb->set_text (_current_buffer->script);
+
refresh_scriptlist ();
update_gui_state ();
}
}
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 ();
}
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);
}
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<Gtk::TextBuffer> 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()) {
}
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
: 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)
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
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;
}