mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 14:54:56 +01:00
towards a proper lua script console UI
This commit is contained in:
parent
b7754af246
commit
dafdf87b79
3 changed files with 510 additions and 47 deletions
|
|
@ -17,24 +17,36 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef PLATFORM_WINDOWS
|
||||||
|
#define random() rand()
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WAF_BUILD
|
#ifdef WAF_BUILD
|
||||||
#include "gtk2ardour-config.h"
|
#include "gtk2ardour-config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <gtkmm2ext/gtk_ui.h>
|
#include <glibmm/fileutils.h>
|
||||||
#include <gtkmm2ext/utils.h>
|
#include <gtkmm/messagedialog.h>
|
||||||
#include <gtkmm2ext/window_title.h>
|
|
||||||
|
#include "pbd/basename.h"
|
||||||
|
#include "pbd/file_utils.h"
|
||||||
|
#include "pbd/md5.h"
|
||||||
|
|
||||||
|
#include "gtkmm2ext/gtk_ui.h"
|
||||||
|
#include "gtkmm2ext/utils.h"
|
||||||
|
#include "gtkmm2ext/window_title.h"
|
||||||
|
|
||||||
|
#include "ardour/luabindings.h"
|
||||||
|
#include "LuaBridge/LuaBridge.h"
|
||||||
|
|
||||||
#include "ardour_ui.h"
|
#include "ardour_ui.h"
|
||||||
#include "gui_thread.h"
|
#include "gui_thread.h"
|
||||||
#include "luainstance.h"
|
#include "luainstance.h"
|
||||||
#include "luawindow.h"
|
#include "luawindow.h"
|
||||||
#include "public_editor.h"
|
#include "public_editor.h"
|
||||||
|
#include "tooltips.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#include "ardour/luabindings.h"
|
|
||||||
#include "LuaBridge/LuaBridge.h"
|
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
@ -46,6 +58,18 @@ using namespace Gtkmm2ext;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
inline LuaWindow::BufferFlags operator| (const LuaWindow::BufferFlags& a, const LuaWindow::BufferFlags& b) {
|
||||||
|
return static_cast<LuaWindow::BufferFlags> (static_cast <int>(a) | static_cast<int> (b));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline LuaWindow::BufferFlags operator|= (LuaWindow::BufferFlags& a, const LuaWindow::BufferFlags& b) {
|
||||||
|
return a = static_cast<LuaWindow::BufferFlags> (static_cast <int>(a) | static_cast<int> (b));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline LuaWindow::BufferFlags operator&= (LuaWindow::BufferFlags& a, const LuaWindow::BufferFlags& b) {
|
||||||
|
return a = static_cast<LuaWindow::BufferFlags> (static_cast <int>(a) & static_cast<int> (b));
|
||||||
|
}
|
||||||
|
|
||||||
LuaWindow* LuaWindow::_instance = 0;
|
LuaWindow* LuaWindow::_instance = 0;
|
||||||
|
|
||||||
LuaWindow*
|
LuaWindow*
|
||||||
|
|
@ -62,54 +86,86 @@ LuaWindow::LuaWindow ()
|
||||||
: Window (Gtk::WINDOW_TOPLEVEL)
|
: Window (Gtk::WINDOW_TOPLEVEL)
|
||||||
, VisibilityTracker (*((Gtk::Window*) this))
|
, VisibilityTracker (*((Gtk::Window*) this))
|
||||||
, _visible (false)
|
, _visible (false)
|
||||||
|
, _menu_scratch (0)
|
||||||
|
, _menu_snippet (0)
|
||||||
|
, _menu_actions (0)
|
||||||
|
, _btn_run (_("Run"))
|
||||||
|
, _btn_clear (_("Clear Outtput"))
|
||||||
|
, _btn_open (_("Import"))
|
||||||
|
, _btn_save (_("Save"))
|
||||||
|
, _btn_delete (_("Delete"))
|
||||||
|
, _current_buffer (0)
|
||||||
{
|
{
|
||||||
set_name ("Lua");
|
set_name ("Lua");
|
||||||
|
|
||||||
update_title ();
|
update_title ();
|
||||||
set_wmclass (X_("ardour_mixer"), PROGRAM_NAME);
|
set_wmclass (X_("ardour_mixer"), PROGRAM_NAME);
|
||||||
|
|
||||||
|
script_select.disable_scrolling ();
|
||||||
|
|
||||||
set_border_width (0);
|
set_border_width (0);
|
||||||
|
|
||||||
outtext.set_editable (false);
|
outtext.set_editable (false);
|
||||||
outtext.set_wrap_mode (Gtk::WRAP_WORD);
|
outtext.set_wrap_mode (Gtk::WRAP_WORD);
|
||||||
|
outtext.set_cursor_visible (false);
|
||||||
|
|
||||||
signal_delete_event().connect (sigc::mem_fun (*this, &LuaWindow::hide_window));
|
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));
|
signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
|
||||||
|
|
||||||
scrollwin.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_ALWAYS);
|
_btn_run.signal_clicked.connect (sigc::mem_fun(*this, &LuaWindow::run_script));
|
||||||
scrollwin.add (outtext);
|
_btn_clear.signal_clicked.connect (sigc::mem_fun(*this, &LuaWindow::clear_output));
|
||||||
|
_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));
|
||||||
|
|
||||||
Gtk::Button *btn_clr = manage (new Button ("Clear"));
|
_btn_open.set_sensitive (false); // TODO
|
||||||
btn_clr->signal_clicked().connect (sigc::mem_fun(*this, &LuaWindow::clear_output));
|
_btn_save.set_sensitive (false);
|
||||||
|
_btn_delete.set_sensitive (false); // TODO
|
||||||
|
|
||||||
|
// layout
|
||||||
|
|
||||||
|
Gtk::ScrolledWindow *scrollin = manage (new Gtk::ScrolledWindow);
|
||||||
|
scrollin->set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
|
||||||
|
scrollin->add (entry);
|
||||||
|
scrollout.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_ALWAYS);
|
||||||
|
scrollout.add (outtext);
|
||||||
|
|
||||||
Gtk::HBox *hbox = manage (new HBox());
|
Gtk::HBox *hbox = manage (new HBox());
|
||||||
|
|
||||||
hbox->pack_start (entry, true, true, 2);
|
hbox->pack_start (_btn_run, false, false, 2);
|
||||||
hbox->pack_start (*btn_clr, false, false, 0);
|
hbox->pack_start (_btn_clear, 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 (script_select, false, false, 2);
|
||||||
|
|
||||||
Gtk::VBox *vbox = manage (new VBox());
|
Gtk::VBox *vbox = manage (new VBox());
|
||||||
vbox->pack_start (scrollwin, true, true, 0);
|
vbox->pack_start (*scrollin, true, true, 0);
|
||||||
vbox->pack_start (*hbox, false, false, 2);
|
vbox->pack_start (*hbox, false, false, 2);
|
||||||
|
|
||||||
entry.signal_activate().connect (sigc::mem_fun (*this, &LuaWindow::entry_activated));
|
Gtk::VPaned *vpane = manage (new Gtk::VPaned ());
|
||||||
|
vpane->pack1 (*vbox, true, false);
|
||||||
|
vpane->pack2 (scrollout, false, true);
|
||||||
|
|
||||||
|
vpane->show_all ();
|
||||||
|
add (*vpane);
|
||||||
|
set_size_request (640, 480); // XXX
|
||||||
|
|
||||||
lua.Print.connect (sigc::mem_fun (*this, &LuaWindow::append_text));
|
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();
|
lua_State* L = lua.getState();
|
||||||
|
LuaInstance::register_classes (L);
|
||||||
luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
|
luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
|
||||||
lua_setglobal (L, "Editor");
|
lua_setglobal (L, "Editor");
|
||||||
// TODO
|
|
||||||
// - allow to load files
|
ARDOUR_UI_UTILS::set_tooltip (script_select, _("Select Editor Buffer"));
|
||||||
// - allow to run files directly
|
|
||||||
// - history buffer
|
setup_buffers ();
|
||||||
// - multi-line input ??
|
LuaScripting::instance().scripts_changed.connect (*this, invalidator (*this), boost::bind (&LuaWindow::refresh_scriptlist, this), gui_context());
|
||||||
|
|
||||||
|
Glib::RefPtr<Gtk::TextBuffer> tb (entry.get_buffer());
|
||||||
|
|
||||||
|
_script_changed_connection = tb->signal_changed().connect (sigc::mem_fun(*this, &LuaWindow::script_changed));
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaWindow::~LuaWindow ()
|
LuaWindow::~LuaWindow ()
|
||||||
|
|
@ -193,18 +249,44 @@ void
|
||||||
LuaWindow::scroll_to_bottom ()
|
LuaWindow::scroll_to_bottom ()
|
||||||
{
|
{
|
||||||
Gtk::Adjustment *adj;
|
Gtk::Adjustment *adj;
|
||||||
adj = scrollwin.get_vadjustment();
|
adj = scrollout.get_vadjustment();
|
||||||
adj->set_value (MAX(0,(adj->get_upper() - adj->get_page_size())));
|
adj->set_value (MAX(0,(adj->get_upper() - adj->get_page_size())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LuaWindow::entry_activated ()
|
LuaWindow::run_script ()
|
||||||
{
|
{
|
||||||
std::string cmd = entry.get_text();
|
Glib::RefPtr<Gtk::TextBuffer> tb (entry.get_buffer());
|
||||||
append_text ("> " + cmd);
|
std::string script = tb->get_text();
|
||||||
|
const std::string& bytecode = LuaScripting::get_factory_bytecode (script);
|
||||||
|
if (bytecode.empty()) {
|
||||||
|
// plain script or faulty script -- run directly
|
||||||
|
try {
|
||||||
|
lua.do_command ("function ardour () end");
|
||||||
|
if (0 == lua.do_command (script)) {
|
||||||
|
append_text ("> OK");
|
||||||
|
}
|
||||||
|
} catch (luabridge::LuaException const& e) {
|
||||||
|
append_text (string_compose (_("LuaException: %1"), e.what()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// script with factory method
|
||||||
|
try {
|
||||||
|
lua_State* L = lua.getState();
|
||||||
|
lua.do_command ("function ardour () end");
|
||||||
|
|
||||||
if (0 == lua.do_command (cmd)) {
|
LuaScriptParamList args = LuaScriptParams::script_params (script, "action_param", false);
|
||||||
entry.set_text("");
|
luabridge::LuaRef tbl_arg (luabridge::newTable(L));
|
||||||
|
LuaScriptParams::params_to_ref (&tbl_arg, args);
|
||||||
|
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;");
|
||||||
|
} catch (luabridge::LuaException const& e) {
|
||||||
|
append_text (string_compose (_("LuaException: %1"), e.what()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -222,3 +304,319 @@ LuaWindow::clear_output ()
|
||||||
Glib::RefPtr<Gtk::TextBuffer> tb (outtext.get_buffer());
|
Glib::RefPtr<Gtk::TextBuffer> tb (outtext.get_buffer());
|
||||||
tb->set_text ("");
|
tb->set_text ("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LuaWindow::new_script ()
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
Glib::RefPtr<Gtk::TextBuffer> tb (entry.get_buffer());
|
||||||
|
tb->set_text ("");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LuaWindow::delete_script ()
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
Glib::RefPtr<Gtk::TextBuffer> tb (entry.get_buffer());
|
||||||
|
tb->set_text ("");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LuaWindow::import_script ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LuaWindow::save_script ()
|
||||||
|
{
|
||||||
|
Glib::RefPtr<Gtk::TextBuffer> tb (entry.get_buffer());
|
||||||
|
std::string script = tb->get_text();
|
||||||
|
std::string msg = "Unknown error";
|
||||||
|
|
||||||
|
std::string path;
|
||||||
|
LuaScriptInfoPtr lsi = LuaScripting::script_info (script);
|
||||||
|
ScriptBuffer & sb (*_current_buffer);
|
||||||
|
|
||||||
|
assert (sb.flags & Buffer_Dirty);
|
||||||
|
|
||||||
|
// 1) check if it has a valid header and factory
|
||||||
|
const std::string& bytecode = LuaScripting::get_factory_bytecode (script);
|
||||||
|
if (bytecode.empty()) {
|
||||||
|
msg = _("Missing script header.\nThe script requires an '{ardour}' info table and a 'factory' function.");
|
||||||
|
goto errorout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!LuaScripting::try_compile (script, LuaScriptParams::script_params (script, "action_param", false))) {
|
||||||
|
msg = _("Script fails to compile.");
|
||||||
|
goto errorout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) check script name & type
|
||||||
|
lsi = LuaScripting::script_info (script);
|
||||||
|
if (!lsi) {
|
||||||
|
msg = _("Invalid or missing script-name or script-type.");
|
||||||
|
goto errorout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lsi->type != LuaScriptInfo::Snippet && lsi->type != LuaScriptInfo::EditorAction) {
|
||||||
|
msg = _("Invalid script-type.\nValid types are 'EditorAction' and 'Snippet'.");
|
||||||
|
goto errorout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) if there's already a writable file,...
|
||||||
|
if ((sb.flags & Buffer_HasFile) && !(sb.flags & Buffer_ReadOnly)) {
|
||||||
|
try {
|
||||||
|
Glib::file_set_contents (sb.path, script);
|
||||||
|
sb.flags &= BufferFlags(~Buffer_Dirty);
|
||||||
|
update_gui_state (); // XXX here?
|
||||||
|
append_text (X_("> ") + string_compose (_("Saved as %1"), sb.path));
|
||||||
|
return; // OK
|
||||||
|
} catch (Glib::FileError e) {
|
||||||
|
msg = string_compose (_("Error saving file: %1"), e.what());
|
||||||
|
goto errorout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4) check if the name is unique for the given type; locally at least
|
||||||
|
if (true /*sb.flags & Buffer_HasFile*/) {
|
||||||
|
LuaScriptList& lsl (LuaScripting::instance ().scripts (lsi->type));
|
||||||
|
for (LuaScriptList::const_iterator s = lsl.begin(); s != lsl.end(); ++s) {
|
||||||
|
if ((*s)->name == lsi->name) {
|
||||||
|
msg = string_compose (_("Script with given name '%1' already exists.\nUse a different name in the descriptor."), lsi->name);
|
||||||
|
goto errorout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5) construct filename -- TODO ask user for name, ask to replace file.
|
||||||
|
do {
|
||||||
|
char buf[80];
|
||||||
|
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?
|
||||||
|
MD5 md5;
|
||||||
|
std::string fn = md5.digestString (buf);
|
||||||
|
|
||||||
|
switch (lsi->type) {
|
||||||
|
case LuaScriptInfo::EditorAction:
|
||||||
|
fn = "a_" + fn;
|
||||||
|
break;
|
||||||
|
case LuaScriptInfo::Snippet:
|
||||||
|
fn = "s_" + fn;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
path = Glib::build_filename (LuaScripting::user_script_dir (), fn.substr(0, 11) + ".lua");
|
||||||
|
} while (Glib::file_test (path, Glib::FILE_TEST_EXISTS));
|
||||||
|
|
||||||
|
try {
|
||||||
|
Glib::file_set_contents (path, script);
|
||||||
|
sb.path = path;
|
||||||
|
sb.flags |= Buffer_HasFile;
|
||||||
|
sb.flags &= BufferFlags(~Buffer_Dirty);
|
||||||
|
update_gui_state (); // XXX here?
|
||||||
|
LuaScripting::instance().refresh (true);
|
||||||
|
append_text (X_("> ") + string_compose (_("Saved as %1"), path));
|
||||||
|
return; // OK
|
||||||
|
} catch (Glib::FileError e) {
|
||||||
|
msg = string_compose (_("Error saving file: %1"), e.what());
|
||||||
|
goto errorout;
|
||||||
|
}
|
||||||
|
|
||||||
|
errorout:
|
||||||
|
MessageDialog am (msg);
|
||||||
|
am.run ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LuaWindow::setup_buffers ()
|
||||||
|
{
|
||||||
|
if (script_buffers.size() > 0) {
|
||||||
|
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();
|
||||||
|
|
||||||
|
refresh_scriptlist ();
|
||||||
|
update_gui_state ();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
LuaWindow::count_scratch_buffers () const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LuaWindow::refresh_scriptlist ()
|
||||||
|
{
|
||||||
|
for (ScriptBufferList::iterator i = script_buffers.begin (); i != script_buffers.end ();) {
|
||||||
|
if ((*i)->flags & Buffer_Scratch) {
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
i = script_buffers.erase (i);
|
||||||
|
}
|
||||||
|
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)));
|
||||||
|
}
|
||||||
|
|
||||||
|
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)));
|
||||||
|
}
|
||||||
|
rebuild_menu ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LuaWindow::rebuild_menu ()
|
||||||
|
{
|
||||||
|
using namespace Menu_Helpers;
|
||||||
|
|
||||||
|
_menu_scratch = manage (new Menu);
|
||||||
|
_menu_snippet = manage (new Menu);
|
||||||
|
_menu_actions = manage (new Menu);
|
||||||
|
|
||||||
|
MenuList& items_scratch (_menu_scratch->items());
|
||||||
|
MenuList& items_snippet (_menu_snippet->items());
|
||||||
|
MenuList& items_actions (_menu_actions->items());
|
||||||
|
|
||||||
|
{
|
||||||
|
Menu_Helpers::MenuElem elem = Gtk::Menu_Helpers::MenuElem(_("New"),
|
||||||
|
sigc::mem_fun(*this, &LuaWindow::new_script));
|
||||||
|
items_scratch.push_back(elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)));
|
||||||
|
|
||||||
|
if ((*i)->flags & Buffer_Scratch) {
|
||||||
|
items_scratch.push_back(elem);
|
||||||
|
}
|
||||||
|
else if ((*i)->type == LuaScriptInfo::EditorAction) {
|
||||||
|
items_actions.push_back(elem);
|
||||||
|
}
|
||||||
|
else if ((*i)->type == LuaScriptInfo::Snippet) {
|
||||||
|
items_snippet.push_back(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
script_select.clear_items ();
|
||||||
|
script_select.AddMenuElem (Menu_Helpers::MenuElem ("Scratch", *_menu_scratch));
|
||||||
|
script_select.AddMenuElem (Menu_Helpers::MenuElem ("Snippets", *_menu_snippet));
|
||||||
|
script_select.AddMenuElem (Menu_Helpers::MenuElem ("Actions", *_menu_actions));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LuaWindow::script_selection_changed (ScriptBufferPtr n)
|
||||||
|
{
|
||||||
|
if (n == _current_buffer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Glib::RefPtr<Gtk::TextBuffer> tb (entry.get_buffer());
|
||||||
|
_current_buffer->script = tb->get_text();
|
||||||
|
|
||||||
|
if (!(n->flags & Buffer_Valid)) {
|
||||||
|
if (!n->load()) {
|
||||||
|
append_text ("! Failed to load buffer.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n->flags & Buffer_Valid) {
|
||||||
|
_current_buffer = n;
|
||||||
|
_script_changed_connection.block ();
|
||||||
|
tb->set_text (n->script);
|
||||||
|
_script_changed_connection.unblock ();
|
||||||
|
} else {
|
||||||
|
append_text ("! Failed to switch buffer.");
|
||||||
|
}
|
||||||
|
update_gui_state ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LuaWindow::update_gui_state ()
|
||||||
|
{
|
||||||
|
const ScriptBuffer & sb (*_current_buffer);
|
||||||
|
std::string name;
|
||||||
|
if (sb.flags & Buffer_Scratch) {
|
||||||
|
name = string_compose (_("Scratch Buffer %1"), sb.name);
|
||||||
|
} else if (sb.type == LuaScriptInfo::EditorAction) {
|
||||||
|
name = string_compose (_("Action: '%1'"), sb.name);
|
||||||
|
} else if (sb.type == LuaScriptInfo::Snippet) {
|
||||||
|
name = string_compose (_("Snippet: %1"), sb.name);
|
||||||
|
} else {
|
||||||
|
cerr << "Invalid Script type\n";
|
||||||
|
assert (0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sb.flags & Buffer_Dirty) {
|
||||||
|
name += " *";
|
||||||
|
}
|
||||||
|
script_select.set_text(name);
|
||||||
|
|
||||||
|
_btn_save.set_sensitive (sb.flags & Buffer_Dirty);
|
||||||
|
_btn_delete.set_sensitive (sb.flags & Buffer_Scratch); // TODO allow to remove user-scripts
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LuaWindow::script_changed () {
|
||||||
|
if (_current_buffer->flags & Buffer_Dirty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_current_buffer->flags |= Buffer_Dirty;
|
||||||
|
update_gui_state ();
|
||||||
|
}
|
||||||
|
|
||||||
|
LuaWindow::ScriptBuffer::ScriptBuffer (const std::string& n)
|
||||||
|
: name (n)
|
||||||
|
, flags (Buffer_Scratch | Buffer_Valid)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
LuaWindow::ScriptBuffer::ScriptBuffer (LuaScriptInfoPtr p)
|
||||||
|
: name (p->name)
|
||||||
|
, path (p->path)
|
||||||
|
, flags (Buffer_HasFile)
|
||||||
|
, type (p->type)
|
||||||
|
{
|
||||||
|
if (!PBD::exists_and_writable (path)) {
|
||||||
|
flags |= Buffer_ReadOnly;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
LuaWindow::ScriptBuffer::ScriptBuffer (const ScriptBuffer& other)
|
||||||
|
: script (other.script)
|
||||||
|
, name (other.name)
|
||||||
|
, path (other.path)
|
||||||
|
, flags (other.flags)
|
||||||
|
, type (other.type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LuaWindow::ScriptBuffer::~ScriptBuffer ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
LuaWindow::ScriptBuffer::load ()
|
||||||
|
{
|
||||||
|
if (!(flags & Buffer_HasFile)) return false;
|
||||||
|
if (flags & Buffer_Valid) return true;
|
||||||
|
try {
|
||||||
|
script = Glib::file_get_contents (path);
|
||||||
|
flags |= Buffer_Valid;
|
||||||
|
} catch (Glib::FileError e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,17 +26,21 @@
|
||||||
#include <gtkmm/label.h>
|
#include <gtkmm/label.h>
|
||||||
#include <gtkmm/window.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 "pbd/signals.h"
|
||||||
|
#include "pbd/stateful.h"
|
||||||
|
|
||||||
|
#include "ardour/ardour.h"
|
||||||
|
#include "ardour/luascripting.h"
|
||||||
|
#include "ardour/session_handle.h"
|
||||||
|
#include "ardour/types.h"
|
||||||
|
|
||||||
#include "gtkmm2ext/visibility_tracker.h"
|
#include "gtkmm2ext/visibility_tracker.h"
|
||||||
|
|
||||||
#include "lua/luastate.h"
|
#include "lua/luastate.h"
|
||||||
|
|
||||||
|
#include "ardour_button.h"
|
||||||
|
#include "ardour_dropdown.h"
|
||||||
|
|
||||||
class LuaWindow :
|
class LuaWindow :
|
||||||
public Gtk::Window,
|
public Gtk::Window,
|
||||||
public PBD::ScopedConnectionList,
|
public PBD::ScopedConnectionList,
|
||||||
|
|
@ -52,27 +56,85 @@ class LuaWindow :
|
||||||
|
|
||||||
void set_session (ARDOUR::Session* s);
|
void set_session (ARDOUR::Session* s);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
Buffer_NOFLAG = 0x00,
|
||||||
|
Buffer_Valid = 0x01, ///< script is loaded
|
||||||
|
Buffer_HasFile = 0x02,
|
||||||
|
Buffer_ReadOnly = 0x04,
|
||||||
|
Buffer_Dirty = 0x08,
|
||||||
|
Buffer_Scratch = 0x10,
|
||||||
|
} BufferFlags;
|
||||||
|
|
||||||
|
class ScriptBuffer {
|
||||||
|
public:
|
||||||
|
ScriptBuffer (const std::string&);
|
||||||
|
ScriptBuffer (ARDOUR::LuaScriptInfoPtr);
|
||||||
|
//ScriptBuffer (const ScriptBuffer& other);
|
||||||
|
~ScriptBuffer ();
|
||||||
|
|
||||||
|
bool load ();
|
||||||
|
|
||||||
|
std::string script;
|
||||||
|
std::string name;
|
||||||
|
std::string path;
|
||||||
|
BufferFlags flags;
|
||||||
|
ARDOUR::LuaScriptInfo::ScriptType type;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LuaWindow ();
|
LuaWindow ();
|
||||||
static LuaWindow* _instance;
|
static LuaWindow* _instance;
|
||||||
|
|
||||||
|
LuaState lua;
|
||||||
bool _visible;
|
bool _visible;
|
||||||
Gtk::VBox global_vpacker;
|
|
||||||
|
Gtk::Menu* _menu_scratch;
|
||||||
|
Gtk::Menu* _menu_snippet;
|
||||||
|
Gtk::Menu* _menu_actions;
|
||||||
|
|
||||||
|
sigc::connection _script_changed_connection;
|
||||||
|
|
||||||
|
Gtk::TextView entry;
|
||||||
|
Gtk::TextView outtext;
|
||||||
|
Gtk::ScrolledWindow scrollout;
|
||||||
|
|
||||||
|
ArdourButton _btn_run;
|
||||||
|
ArdourButton _btn_clear;
|
||||||
|
ArdourButton _btn_open;
|
||||||
|
ArdourButton _btn_save;
|
||||||
|
ArdourButton _btn_delete;
|
||||||
|
|
||||||
|
ArdourDropdown script_select;
|
||||||
|
|
||||||
|
typedef boost::shared_ptr<ScriptBuffer> ScriptBufferPtr;
|
||||||
|
typedef std::vector<ScriptBufferPtr> ScriptBufferList;
|
||||||
|
|
||||||
|
ScriptBufferList script_buffers;
|
||||||
|
ScriptBufferPtr _current_buffer;
|
||||||
|
|
||||||
void session_going_away ();
|
void session_going_away ();
|
||||||
void update_title ();
|
void update_title ();
|
||||||
|
|
||||||
Gtk::Entry entry;
|
void setup_buffers ();
|
||||||
Gtk::TextView outtext;
|
void refresh_scriptlist ();
|
||||||
Gtk::ScrolledWindow scrollwin;
|
void rebuild_menu ();
|
||||||
|
uint32_t count_scratch_buffers () const;
|
||||||
|
|
||||||
|
void script_changed ();
|
||||||
|
void script_selection_changed (ScriptBufferPtr n);
|
||||||
|
void update_gui_state ();
|
||||||
|
|
||||||
void append_text (std::string s);
|
void append_text (std::string s);
|
||||||
void scroll_to_bottom ();
|
void scroll_to_bottom ();
|
||||||
void clear_output ();
|
void clear_output ();
|
||||||
|
|
||||||
void entry_activated ();
|
void run_script ();
|
||||||
|
|
||||||
LuaState lua;
|
void new_script ();
|
||||||
|
void delete_script ();
|
||||||
|
void import_script ();
|
||||||
|
void save_script ();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,7 @@ ScriptSelector::script_combo_changed ()
|
||||||
void
|
void
|
||||||
ScriptSelector::refresh ()
|
ScriptSelector::refresh ()
|
||||||
{
|
{
|
||||||
|
LuaScripting::instance ().refresh ();
|
||||||
_scripts = LuaScripting::instance ().scripts (_script_type);
|
_scripts = LuaScripting::instance ().scripts (_script_type);
|
||||||
setup_list ();
|
setup_list ();
|
||||||
}
|
}
|
||||||
|
|
@ -166,10 +167,12 @@ ScriptParameterDialog::ScriptParameterDialog (std::string title,
|
||||||
t->attach (_name_entry, 1, 2, ty, ty+1);
|
t->attach (_name_entry, 1, 2, ty, ty+1);
|
||||||
++ty;
|
++ty;
|
||||||
|
|
||||||
l = manage (new Label (_("<b>Parameters:</b>"), Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER, false));
|
if (_lsp.size () > 0) {
|
||||||
l->set_use_markup ();
|
l = manage (new Label (_("<b>Instance Parameters</b>"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||||
t->attach (_name_entry, 0, 2, ty, ty+1);
|
l->set_use_markup ();
|
||||||
++ty;
|
t->attach (*l, 0, 2, ty, ty+1);
|
||||||
|
++ty;
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < _lsp.size (); ++i) {
|
for (size_t i = 0; i < _lsp.size (); ++i) {
|
||||||
CheckButton* c = manage (new CheckButton (_lsp[i]->title));
|
CheckButton* c = manage (new CheckButton (_lsp[i]->title));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue