Compare commits

...

8 Commits

10 changed files with 483 additions and 162 deletions

View File

@ -712,7 +712,7 @@ private:
gint really_remove_region_marker (ArdourMarker*); gint really_remove_region_marker (ArdourMarker*);
void goto_nth_marker (int nth); void goto_nth_marker (int nth);
void trigger_script (int nth); void trigger_script (int nth);
void trigger_script_by_name (const std::string script_name); void trigger_script_by_name (const std::string script_name, const std::string args = "");
void toggle_marker_lines (); void toggle_marker_lines ();
void set_marker_line_visibility (bool); void set_marker_line_visibility (bool);

View File

@ -873,7 +873,7 @@ static void _lua_print (std::string s) {
} }
void void
Editor::trigger_script_by_name (const std::string script_name) Editor::trigger_script_by_name (const std::string script_name, const std::string in_args)
{ {
string script_path; string script_path;
ARDOUR::LuaScriptList scr = LuaScripting::instance ().scripts(LuaScriptInfo::EditorAction); ARDOUR::LuaScriptList scr = LuaScripting::instance ().scripts(LuaScriptInfo::EditorAction);
@ -901,6 +901,8 @@ Editor::trigger_script_by_name (const std::string script_name)
lua.do_file (script_path); lua.do_file (script_path);
luabridge::LuaRef args (luabridge::newTable (L)); luabridge::LuaRef args (luabridge::newTable (L));
args[1] = in_args;
try { try {
luabridge::LuaRef fn = luabridge::getGlobal (L, "factory"); luabridge::LuaRef fn = luabridge::getGlobal (L, "factory");
if (fn.isFunction()) { if (fn.isFunction()) {

View File

@ -600,6 +600,9 @@ Dialog::Dialog (std::string const& title, luabridge::LuaRef lr)
if (!lr.isTable ()) { if (!lr.isTable ()) {
return; return;
} }
int row_count = 0;
for (luabridge::Iterator i (lr); !i.isNil (); ++i) { for (luabridge::Iterator i (lr); !i.isNil (); ++i) {
if (!i.key ().isNumber ()) { continue; } if (!i.key ().isNumber ()) { continue; }
if (!i.value ().isTable ()) { continue; } if (!i.value ().isTable ()) { continue; }
@ -755,6 +758,7 @@ Dialog::Dialog (std::string const& title, luabridge::LuaRef lr)
} }
_widgets.push_back(w); _widgets.push_back(w);
} }
row_count++;
} }
_ad.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); _ad.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
@ -763,14 +767,18 @@ Dialog::Dialog (std::string const& title, luabridge::LuaRef lr)
Gtk::Table* table = Gtk::manage (new Gtk::Table ()); Gtk::Table* table = Gtk::manage (new Gtk::Table ());
table->set_col_spacings (20); table->set_col_spacings (20);
table->set_row_spacings (8); table->set_row_spacings (8);
table->set_border_width (8);
table->signal_size_allocate ().connect (sigc::mem_fun (this, &Dialog::table_size_alloc)); table->signal_size_allocate ().connect (sigc::mem_fun (this, &Dialog::table_size_alloc));
_scroller.set_shadow_type(Gtk::SHADOW_NONE); if (row_count>16) {
_scroller.set_border_width(0); _scroller.set_shadow_type(Gtk::SHADOW_NONE);
_scroller.add (*table); _scroller.set_border_width(0);
_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER); _scroller.add (*table);
_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
_ad.get_vbox ()->pack_start (_scroller); _ad.get_vbox ()->pack_start (_scroller);
} else {
_ad.get_vbox ()->pack_start (*table);
}
int row = 0; int row = 0;
int last_end = -1; int last_end = -1;

View File

@ -26,5 +26,32 @@
<Binding key="Tertiary-l" action="Mixer/ToggleMixerList" group="Window Visibility"/> <Binding key="Tertiary-l" action="Mixer/ToggleMixerList" group="Window Visibility"/>
<Binding key="Tertiary-v" action="Mixer/ToggleVCAPane" group="Window Visibility"/> <Binding key="Tertiary-v" action="Mixer/ToggleVCAPane" group="Window Visibility"/>
<Binding key="Tertiary-m" action="Mixer/ToggleMonitorSection" group="Window Visibility"/> <Binding key="Tertiary-m" action="Mixer/ToggleMonitorSection" group="Window Visibility"/>
<Binding key="Primary-F1" action="Mixer/store-mixer-scene-1" group="Mixer Scenes"/>
<Binding key="Primary-F2" action="Mixer/store-mixer-scene-2" group="Mixer Scenes"/>
<Binding key="Primary-F3" action="Mixer/store-mixer-scene-3" group="Mixer Scenes"/>
<Binding key="Primary-F4" action="Mixer/store-mixer-scene-4" group="Mixer Scenes"/>
<Binding key="Primary-F5" action="Mixer/store-mixer-scene-5" group="Mixer Scenes"/>
<Binding key="Primary-F6" action="Mixer/store-mixer-scene-6" group="Mixer Scenes"/>
<Binding key="Primary-F7" action="Mixer/store-mixer-scene-7" group="Mixer Scenes"/>
<Binding key="Primary-F8" action="Mixer/store-mixer-scene-8" group="Mixer Scenes"/>
<Binding key="Primary-F9" action="Mixer/store-mixer-scene-9" group="Mixer Scenes"/>
<Binding key="Primary-F10" action="Mixer/store-mixer-scene-10" group="Mixer Scenes"/>
<Binding key="Primary-F11" action="Mixer/store-mixer-scene-11" group="Mixer Scenes"/>
<Binding key="Primary-F12" action="Mixer/store-mixer-scene-12" group="Mixer Scenes"/>
<Binding key="F1" action="Mixer/recall-mixer-scene-1" group="Mixer Scenes"/>
<Binding key="F2" action="Mixer/recall-mixer-scene-2" group="Mixer Scenes"/>
<Binding key="F3" action="Mixer/recall-mixer-scene-3" group="Mixer Scenes"/>
<Binding key="F4" action="Mixer/recall-mixer-scene-4" group="Mixer Scenes"/>
<Binding key="F5" action="Mixer/recall-mixer-scene-5" group="Mixer Scenes"/>
<Binding key="F6" action="Mixer/recall-mixer-scene-6" group="Mixer Scenes"/>
<Binding key="F7" action="Mixer/recall-mixer-scene-7" group="Mixer Scenes"/>
<Binding key="F8" action="Mixer/recall-mixer-scene-8" group="Mixer Scenes"/>
<Binding key="F9" action="Mixer/recall-mixer-scene-9" group="Mixer Scenes"/>
<Binding key="F10" action="Mixer/recall-mixer-scene-10" group="Mixer Scenes"/>
<Binding key="F11" action="Mixer/recall-mixer-scene-11" group="Mixer Scenes"/>
<Binding key="F12" action="Mixer/recall-mixer-scene-12" group="Mixer Scenes"/>
</Press> </Press>
</Bindings> </Bindings>

View File

@ -38,12 +38,15 @@
#include <glibmm/threads.h> #include <glibmm/threads.h>
#include <gtkmm/accelmap.h> #include <gtkmm/accelmap.h>
#include <gtkmm/menu.h>
#include <gtkmm/offscreenwindow.h> #include <gtkmm/offscreenwindow.h>
#include <gtkmm/stock.h> #include <gtkmm/stock.h>
#include "pbd/convert.h" #include "pbd/convert.h"
#include "pbd/unwind.h" #include "pbd/unwind.h"
#include "context_menu_helper.h"
#include "ardour/amp.h" #include "ardour/amp.h"
#include "ardour/debug.h" #include "ardour/debug.h"
#include "ardour/audio_port.h" #include "ardour/audio_port.h"
@ -65,7 +68,9 @@
#include "gtkmm2ext/window_title.h" #include "gtkmm2ext/window_title.h"
#include "gtkmm2ext/doi.h" #include "gtkmm2ext/doi.h"
#include "widgets/prompter.h"
#include "widgets/tearoff.h" #include "widgets/tearoff.h"
#include "widgets/tooltips.h"
#include "foldback_strip.h" #include "foldback_strip.h"
#include "keyboard.h" #include "keyboard.h"
@ -80,6 +85,7 @@
#include "route_sorter.h" #include "route_sorter.h"
#include "actions.h" #include "actions.h"
#include "gui_thread.h" #include "gui_thread.h"
#include "ardour_message.h"
#include "mixer_group_tabs.h" #include "mixer_group_tabs.h"
#include "plugin_utils.h" #include "plugin_utils.h"
#include "route_sorter.h" #include "route_sorter.h"
@ -92,6 +98,7 @@
#define PX_SCALE(px) std::max ((float)px, rintf ((float)px* UIConfiguration::instance ().get_ui_scale ())) #define PX_SCALE(px) std::max ((float)px, rintf ((float)px* UIConfiguration::instance ().get_ui_scale ()))
using namespace ARDOUR; using namespace ARDOUR;
using namespace ArdourWidgets;
using namespace ARDOUR_UI_UTILS; using namespace ARDOUR_UI_UTILS;
using namespace ARDOUR_PLUGIN_UTILS; using namespace ARDOUR_PLUGIN_UTILS;
using namespace PBD; using namespace PBD;
@ -280,6 +287,43 @@ Mixer_UI::Mixer_UI ()
favorite_plugins_vbox.pack_start (favorite_plugins_scroller, true, true); favorite_plugins_vbox.pack_start (favorite_plugins_scroller, true, true);
favorite_plugins_vbox.pack_start (favorite_plugins_search_hbox, false, false); favorite_plugins_vbox.pack_start (favorite_plugins_search_hbox, false, false);
Gtk::Label *l = manage (new Label (_("Mixer Scenes (F1...F8 to recall)")));
l->set_alignment(0, 0.5);
Gtk::Table *padder = manage (new Table ());
padder->set_border_width(4);
padder->attach (*l, 0,1,0,1, Gtk::FILL, Gtk::FILL);
_mixer_scene_vbox.pack_start(*padder, false, false);
_mixer_scene_table.set_border_width(4);
_mixer_scene_table.set_spacings(4);
_mixer_scene_table.set_homogeneous(false);
for (int column=0; column<1;column++) {
for (int row=0; row<8;row++) {
int col = column*2;
int scn_index = col*2+row;
ArdourButton* b = manage (new ArdourButton (ArdourButton::default_elements));
b->set_text(string_compose("%1", 1+ scn_index));
b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &Mixer_UI::scene_button_pressed), scn_index), false);
_mixer_scene_buttons.push_back(b);
Gtk::Label* l = manage (new Gtk::Label (""));
Gtk::EventBox* namebox = manage (new Gtk::EventBox ()); //must put the labe in a EventBox to capture double-click
namebox->add (*l);
namebox->add_events (Gdk::BUTTON_PRESS_MASK);
namebox->signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &Mixer_UI::scene_label_pressed), scn_index), false);
_mixer_scene_labels.push_back(l);
_mixer_scene_table.attach (*b, col, col+1, row, row+1, Gtk::FILL, Gtk::FILL); col++;
_mixer_scene_table.attach (*namebox, col, col+1, row, row+1, Gtk::FILL, Gtk::FILL); col++;
}
}
_mixer_scene_vbox.pack_start(_mixer_scene_table, false, false);
rhs_pane1.add (favorite_plugins_frame); rhs_pane1.add (favorite_plugins_frame);
rhs_pane1.add (track_display_frame); rhs_pane1.add (track_display_frame);
@ -288,6 +332,13 @@ Mixer_UI::Mixer_UI ()
list_vpacker.pack_start (rhs_pane2, true, true); list_vpacker.pack_start (rhs_pane2, true, true);
//add a spacer; this fills the area that is normally taken by the pane resizers
_mixer_scene_spacer.set_size_request (-1, 6);
list_vpacker.pack_start (_mixer_scene_spacer, false, false);
_mixer_scene_frame.add(_mixer_scene_vbox);
list_vpacker.pack_start (_mixer_scene_frame, false, false);
vca_label_bar.set_size_request (-1, 16 + 1); /* must match height in GroupTabs::set_size_request() + 1 border px*/ vca_label_bar.set_size_request (-1, 16 + 1); /* must match height in GroupTabs::set_size_request() + 1 border px*/
vca_vpacker.pack_start (vca_label_bar, false, false); vca_vpacker.pack_start (vca_label_bar, false, false);
@ -404,7 +455,6 @@ struct MixerStripSorter {
} }
}; };
void void
Mixer_UI::escape () Mixer_UI::escape ()
{ {
@ -1190,6 +1240,9 @@ Mixer_UI::set_session (Session* sess)
return; return;
} }
update_scene_buttons();
MixerScene::Change.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::update_scene_buttons, this), gui_context());
refill_favorite_plugins(); refill_favorite_plugins();
XMLNode* node = ARDOUR_UI::instance()->mixer_settings(); XMLNode* node = ARDOUR_UI::instance()->mixer_settings();
@ -3611,18 +3664,18 @@ Mixer_UI::register_actions ()
ActionManager::register_toggle_action (group, X_("toggle-input-monitor"), _("Toggle Input Monitoring"), sigc::bind (sigc::mem_fun (*this, &Mixer_UI::toggle_monitor_action), MonitorInput, false, false)); ActionManager::register_toggle_action (group, X_("toggle-input-monitor"), _("Toggle Input Monitoring"), sigc::bind (sigc::mem_fun (*this, &Mixer_UI::toggle_monitor_action), MonitorInput, false, false));
for (size_t i = 0; i < 12; ++i) { for (size_t i = 0; i < 12; ++i) {
std::string a = string_compose (X_("store-mixer-scene-%1"), i); std::string a = string_compose (X_("store-mixer-scene-%1"), i + 1);
std::string n = string_compose (_("Store Mixer Scene Slot #%1"), i + 1); std::string n = string_compose (_("Store Mixer Scene #%1"), i + 1);
ActionManager::register_action (group, a.c_str (), n.c_str (), ActionManager::register_action (group, a.c_str (), n.c_str (),
sigc::bind (sigc::mem_fun (*this, &Mixer_UI::store_mixer_scene), i)); sigc::bind (sigc::mem_fun (*this, &Mixer_UI::store_mixer_scene), i));
a = string_compose (X_("recall-mixer-scene-%1"), i); a = string_compose (X_("recall-mixer-scene-%1"), i + 1);
n = string_compose (_("Recall Mixer Scene Slot #%1"), i + 1); n = string_compose (_("Recall Mixer Scene #%1"), i + 1);
ActionManager::register_action (group, a.c_str (), n.c_str (), ActionManager::register_action (group, a.c_str (), n.c_str (),
sigc::bind (sigc::mem_fun (*this, &Mixer_UI::recall_mixer_scene), i)); sigc::bind (sigc::mem_fun (*this, &Mixer_UI::recall_mixer_scene), i));
a = string_compose (X_("clear-mixer-scene-%1"), i); a = string_compose (X_("clear-mixer-scene-%1"), i + 1);
n = string_compose (_("Clear Mixer Scene Slot #%1"), i + 1); n = string_compose (_("Clear Mixer Scene #%1"), i + 1);
ActionManager::register_action (group, a.c_str (), n.c_str (), ActionManager::register_action (group, a.c_str (), n.c_str (),
sigc::bind (sigc::mem_fun (*this, &Mixer_UI::clear_mixer_scene), i)); sigc::bind (sigc::mem_fun (*this, &Mixer_UI::clear_mixer_scene), i));
} }
@ -3837,15 +3890,103 @@ Mixer_UI::vca_unassign (boost::shared_ptr<VCA> vca)
void void
Mixer_UI::store_mixer_scene (size_t n) Mixer_UI::store_mixer_scene (size_t n)
{ {
if (_session) { if (!_session) {
_session->store_nth_mixer_scene (n); return;
}
std::string str;
/* if it already exists, prompt the user to overwrite an existing scene */
boost::shared_ptr<MixerScene> ms = _session->nth_mixer_scene (n, false);
if (ms && !ms->empty ()) {
ArdourMessageDialog md (_("Scene is already set. Overwrite it?"), false, MESSAGE_QUESTION, BUTTONS_YES_NO);
if (md.run () != RESPONSE_YES) {
return;
}
str = ms->name();
} else {
time_t now;
time (&now);
Glib::DateTime tm (Glib::DateTime::create_now_local (now));
str = Glib::DateTime::create_now_local().format ("%FT%H.%M.%S");
}
/* prompt the user for a scene name */
ArdourWidgets::Prompter name_prompter (true);
string result;
bool done = false;
name_prompter.set_title (_("Store Scene"));
name_prompter.set_prompt (_("Scene name:"));
name_prompter.set_initial_text (str);
name_prompter.add_button (_("Store"), Gtk::RESPONSE_ACCEPT);
name_prompter.show_all ();
while (!done) {
switch (name_prompter.run ()) {
case Gtk::RESPONSE_ACCEPT:
name_prompter.get_result (result);
name_prompter.hide ();
if (result.length()) {
_session->store_nth_mixer_scene (n);
boost::shared_ptr<MixerScene> ms = _session->nth_mixer_scene (n, false);
ms->set_name(result);
done = true;
} else {
/* nothing entered, just get out of here */
done = true;
}
break;
default:
done = true;
break;
}
} }
} }
void void
Mixer_UI::recall_mixer_scene (size_t n) Mixer_UI::recall_mixer_scene (size_t n)
{ {
if (_session) { if (!_session) {
return;
}
boost::shared_ptr<MixerScene> ms = _session->nth_mixer_scene (n, false);
if (!ms) {
return;
}
bool do_recall = true;
XMLNode* memory_warning_node = Config->instant_xml (X_("no-scene-warning"));
if (memory_warning_node == 0) {
ArdourMessageDialog msg (string_compose ( _("Recall mixer scene \"%1\"?\n"
"This will overwrite your mixer settings!\n"
"This operation cannot be undone."), ms->name()));
msg.add_button (_("Cancel"), Gtk::RESPONSE_NO);
msg.set_default_response (RESPONSE_OK);
VBox* vbox = msg.get_vbox();
HBox hbox;
CheckButton cb (_("Do not show this window again"));
hbox.pack_start (cb, true, false);
vbox->pack_start (hbox);
cb.show();
vbox->show();
hbox.show ();
if (msg.run () != Gtk::RESPONSE_OK) {
do_recall = false;
}
if (cb.get_active()) {
XMLNode node (X_("no-scene-warning"));
Config->add_instant_xml (node);
}
}
if (do_recall) {
_session->apply_nth_mixer_scene (n); _session->apply_nth_mixer_scene (n);
} }
} }
@ -3853,10 +3994,169 @@ Mixer_UI::recall_mixer_scene (size_t n)
void void
Mixer_UI::clear_mixer_scene (size_t n) Mixer_UI::clear_mixer_scene (size_t n)
{ {
if (_session) { if (!_session) {
boost::shared_ptr<MixerScene> ms = _session->nth_mixer_scene (n, false); return;
if (ms) { }
ms->clear ();
boost::shared_ptr<MixerScene> ms = _session->nth_mixer_scene (n, false);
if (!ms) {
return;
}
bool do_clear = false;
XMLNode* memory_warning_node = Config->instant_xml (X_("no-clear-warning"));
if (memory_warning_node == 0) {
ArdourMessageDialog msg (string_compose ( _("Clear mixer scene \"%1\"?\n"
"This operation cannot be undone."), ms->name()));
msg.add_button (_("Cancel"), Gtk::RESPONSE_NO);
msg.set_default_response (RESPONSE_OK);
VBox* vbox = msg.get_vbox();
HBox hbox;
CheckButton cb (_("Do not show this window again"));
hbox.pack_start (cb, true, false);
vbox->pack_start (hbox);
cb.show();
vbox->show();
hbox.show ();
if (msg.run () == Gtk::RESPONSE_OK) {
do_clear = true;
}
if (cb.get_active()) {
XMLNode node (X_("no-clear-warning"));
Config->add_instant_xml (node);
}
}
if (do_clear) {
ms->clear ();
}
}
void
Mixer_UI::rename_mixer_scene (size_t n)
{
if (!_session) {
return;
}
boost::shared_ptr<MixerScene> ms = _session->nth_mixer_scene (n, false);
if (!ms) {
return;
}
/* prompt the user for a scene name */
ArdourWidgets::Prompter name_prompter (true);
string result;
bool done = false;
name_prompter.set_title (_("Rename Scene"));
name_prompter.set_prompt (_("Scene name:"));
name_prompter.set_initial_text (ms->name());
name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
name_prompter.show_all ();
while (!done) {
switch (name_prompter.run ()) {
case Gtk::RESPONSE_ACCEPT:
name_prompter.get_result (result);
name_prompter.hide ();
if (result.length()) {
boost::shared_ptr<MixerScene> ms = _session->nth_mixer_scene (n, false);
ms->set_name(result);
done = true;
} else {
/* nothing entered, just get out of here */
done = true;
}
break;
default:
done = true;
break;
}
}
}
void
Mixer_UI::popup_scene_menu (GdkEventButton* ev, int scn_idx)
{
Gtk::Menu* menu = ARDOUR_UI_UTILS::shared_popup_menu ();
Gtk::Menu_Helpers::MenuList& items = menu->items();
items.push_back(Gtk::Menu_Helpers::MenuElem(_("Store"), sigc::bind(sigc::mem_fun(*this, &Mixer_UI::store_mixer_scene), scn_idx)));
boost::shared_ptr<MixerScene> ms = _session->nth_mixer_scene (scn_idx);
if(ms && !ms->empty()) {
items.push_back(Gtk::Menu_Helpers::MenuElem(_("Clear"), sigc::bind(sigc::mem_fun(*this, &Mixer_UI::clear_mixer_scene), scn_idx)));
items.push_back(Gtk::Menu_Helpers::MenuElem(_("Rename"), sigc::bind(sigc::mem_fun(*this, &Mixer_UI::rename_mixer_scene), scn_idx)));
}
menu->popup(1, ev->time);
}
bool
Mixer_UI::scene_button_pressed (GdkEventButton *ev, int idx)
{
if (!_session) {
return false;
}
boost::shared_ptr<MixerScene> scn = _session->nth_mixer_scene (idx);
if (ev->button == 1 && (scn && !scn->empty())) {
recall_mixer_scene(idx);
} else if (scn && (ev->button == 3) && Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::TertiaryModifier)) {
clear_mixer_scene(idx);
} else if (Keyboard::is_context_menu_event (ev)) {
popup_scene_menu (ev, idx);
}
return true;
}
bool
Mixer_UI::scene_label_pressed (GdkEventButton* ev, int idx)
{
boost::shared_ptr<MixerScene> scn = _session->nth_mixer_scene (idx);
if (!scn || scn->empty()) {
return false;
}
if ((ev->button == 1 && ev->type == GDK_2BUTTON_PRESS) || Keyboard::is_edit_event (ev)) {
rename_mixer_scene(idx);
return true;
}
return false;
}
void
Mixer_UI::update_scene_buttons ()
{
for (size_t idx=0; idx<12;idx++) {
if (!_mixer_scene_buttons.empty() && idx < _mixer_scene_buttons.size()) {
boost::shared_ptr<MixerScene> scn = _session->nth_mixer_scene (idx);
ArdourButton *b = _mixer_scene_buttons[idx];
if (scn && !scn->empty()) {
ArdourWidgets::set_tooltip (b, _("Click to recall this mixer scene\nRight-Click for context menu"));
}
Gtk::Label *l = _mixer_scene_labels[idx];
l->set_alignment(0, 0.5);
if (scn && !scn->empty()) {
l->set_text(scn->name());
} else {
if (idx==0 && scn->empty()) {
l->set_text(_("(Right-Click to Store)"));
} else {
l->set_text((""));
}
}
} }
} }
} }

View File

@ -126,6 +126,7 @@ public:
void store_mixer_scene (size_t); void store_mixer_scene (size_t);
void recall_mixer_scene (size_t); void recall_mixer_scene (size_t);
void clear_mixer_scene (size_t); void clear_mixer_scene (size_t);
void rename_mixer_scene (size_t n);
void do_vca_assign (boost::shared_ptr<ARDOUR::VCA>); void do_vca_assign (boost::shared_ptr<ARDOUR::VCA>);
void do_vca_unassign (boost::shared_ptr<ARDOUR::VCA>); void do_vca_unassign (boost::shared_ptr<ARDOUR::VCA>);
@ -207,6 +208,17 @@ private:
Gtk::HBox out_packer; Gtk::HBox out_packer;
ArdourWidgets::HPane list_hpane; ArdourWidgets::HPane list_hpane;
Gtk::EventBox _mixer_scene_spacer;
Gtk::Frame _mixer_scene_frame;
Gtk::Table _mixer_scene_table;
Gtk::VBox _mixer_scene_vbox;
std::vector<ArdourWidgets::ArdourButton *> _mixer_scene_buttons;
std::vector<Gtk::Label *> _mixer_scene_labels;
void popup_scene_menu (GdkEventButton* ev, int);
bool scene_button_pressed (GdkEventButton*, int);
bool scene_label_pressed (GdkEventButton* ev, int);
MixerGroupTabs* _group_tabs; MixerGroupTabs* _group_tabs;
bool on_scroll_event (GdkEventScroll*); bool on_scroll_event (GdkEventScroll*);
@ -228,6 +240,8 @@ private:
void add_stripables (ARDOUR::StripableList&); void add_stripables (ARDOUR::StripableList&);
void update_scene_buttons ();
void add_routes (ARDOUR::RouteList&); void add_routes (ARDOUR::RouteList&);
void remove_strip (MixerStrip *); void remove_strip (MixerStrip *);
void remove_foldback (FoldbackStrip *); void remove_foldback (FoldbackStrip *);

View File

@ -400,6 +400,8 @@ public:
virtual void set_video_timeline_height (const int h) = 0; virtual void set_video_timeline_height (const int h) = 0;
virtual void embed_audio_from_video (std::string, samplepos_t n = 0, bool lock_position_to_video = true) = 0; virtual void embed_audio_from_video (std::string, samplepos_t n = 0, bool lock_position_to_video = true) = 0;
virtual void trigger_script_by_name (const std::string script_name, const std::string args = "") = 0;
virtual bool track_selection_change_without_scroll () const = 0; virtual bool track_selection_change_without_scroll () const = 0;
virtual bool show_touched_automation () const = 0; virtual bool show_touched_automation () const = 0;

View File

@ -7525,10 +7525,12 @@ boost::shared_ptr<MixerScene>
Session::nth_mixer_scene (size_t nth, bool create_if_missing) Session::nth_mixer_scene (size_t nth, bool create_if_missing)
{ {
Glib::Threads::RWLock::ReaderLock lm (_mixer_scenes_lock); Glib::Threads::RWLock::ReaderLock lm (_mixer_scenes_lock);
if (create_if_missing && _mixer_scenes.size () <= nth) { if (create_if_missing && (!_mixer_scenes[nth] || _mixer_scenes.size() <= nth) ) {
lm.release (); lm.release ();
Glib::Threads::RWLock::WriterLock lw (_mixer_scenes_lock); Glib::Threads::RWLock::WriterLock lw (_mixer_scenes_lock);
_mixer_scenes.resize (nth + 1); if (_mixer_scenes.size() <= nth) {
_mixer_scenes.resize (nth + 1);
}
_mixer_scenes[nth] = boost::shared_ptr<MixerScene> (new MixerScene (*this)); _mixer_scenes[nth] = boost::shared_ptr<MixerScene> (new MixerScene (*this));
return _mixer_scenes[nth]; return _mixer_scenes[nth];
} }

View File

@ -3,7 +3,7 @@ ardour {
name = "Recall Mixer Settings", name = "Recall Mixer Settings",
author = "Mixbus Team", author = "Mixbus Team",
description = [[ description = [[
Recalls mixer settings outined by files Recalls mixer settings files
created by Store Mixer Settings. created by Store Mixer Settings.
Allows for some room to change Source Allows for some room to change Source
@ -11,15 +11,25 @@ ardour {
]] ]]
} }
function factory () function factory (params)
local acoraida_monicas_last_used_recall_file
return function () return function ()
local user_cfg = ARDOUR.user_config_directory(-1) local user_cfg = ARDOUR.user_config_directory(-1)
local local_path = ARDOUR.LuaAPI.build_filename(Session:path(), 'mixer_settings') local folder_path = ARDOUR.LuaAPI.build_filename(Session:path(), 'mixer_settings')
local global_path = ARDOUR.LuaAPI.build_filename(user_cfg, 'mixer_settings')
local p = params or {}
local args = p[1] or ""
if args=="global_path" then
folder_path = ARDOUR.LuaAPI.build_filename(user_cfg, 'mixer_settings')
end
local snap_num = 0
for test = 0, 12, 1 do
if string.find(args, string.format("Scene_%d", test)) then
snap_num = test
end
end
local invalidate = {} local invalidate = {}
@ -108,6 +118,7 @@ function factory ()
--print(i, l) --print(i, l)
local create_groups = dry_run["create_groups"] local create_groups = dry_run["create_groups"]
local set_names = dry_run["set_names"]
local skip_line = false local skip_line = false
local plugin, route, group = false, false, false local plugin, route, group = false, false, false
@ -171,6 +182,8 @@ function factory ()
if rt:isnil() then rt = Session:route_by_name(name) end if rt:isnil() then rt = Session:route_by_name(name) end
if rt:isnil() then goto nextline end if rt:isnil() then goto nextline end
if (set_names) then rt:set_name(name) end
if sends then if sends then
for i, data in pairs(sends) do for i, data in pairs(sends) do
i = i-1 i = i-1
@ -370,27 +383,27 @@ function factory ()
if do_route then if do_route then
local route_id = instance["route_id"] local route_id = instance["route_id"]
local route_name = instance["route_name"] local route_name = instance["route_name"]
local dlg_title = "" local src_name = string.format("%s", route_name)
local route_ptr = Session:route_by_id(PBD.ID(route_id)) local route_ptr = Session:route_by_id(PBD.ID(route_id))
if route_ptr:isnil() then -- if route_ptr:isnil() then
route_ptr = Session:route_by_name(route_name) -- route_ptr = Session:route_by_name(route_name)
if not(route_ptr:isnil()) then -- if not(route_ptr:isnil()) then
dlg_title = string.format("%s", route_ptr:name()) -- dlg_title = string.format("%s", route_ptr:name())
--action_title = "will use route settings" -- --action_title = "will use route settings"
else -- else
dlg_title = string.format("%s", route_name) -- dlg_title = string.format("%s", route_name)
--action_title = "will be ignored" -- --action_title = "will be ignored"
end -- end
else -- else
dlg_title = string.format("%s", route_ptr:name()) -- dlg_title = string.format("%s", route_ptr:name())
--action_title = "will use route settings" --action_title = "will use route settings"
end -- end
if route_ptr:isnil() then name = route_name else name = route_ptr:name() end if route_ptr:isnil() then name = route_name else name = route_ptr:name() end
table.insert(dry_table, { table.insert(dry_table, {
order=instance['pi_order']+pad, type = "label", align="right", key = "route-"..i , col = 0, colspan = 1, title = dlg_title order=instance['pi_order']+pad, type = "label", align="right", key = "route-"..i , col = 0, colspan = 1, title = src_name
}) })
table.insert(dry_table, { table.insert(dry_table, {
type = "dropdown", align="left", key = "destination-"..i, col = 1, colspan = 1, title = "", values = route_values, default = name or "----" type = "dropdown", align="left", key = "destination-"..i, col = 1, colspan = 1, title = "", values = route_values, default = name or "----"
@ -398,92 +411,50 @@ function factory ()
end end
i = i + 1 i = i + 1
end end
if (snap_num==0) then
table.insert(dry_table, {
type = "checkbox", col=0, colspan=2, align="left", key = "create_groups", default = true, title = "Create Groups if necessary?"
})
end
table.insert(dry_table, { table.insert(dry_table, {
type = "checkbox", col=0, colspan=2, align="left", key = "create_groups", default = true, title = "Create Groups if necessary?" type = "checkbox", col=0, colspan=2, align="left", key = "set_names", default = true, title = "Set Names from File"
}) })
return dry_table return dry_table
end end
local global_vs_local_dlg = {
{ type = "label", col=0, colspan=20, align="left", title = "" },
{
type = "radio", col=0, colspan=20, align="left", key = "recall-dir", title = "", values =
{
['Pick from Global Settings'] = 1, ['Pick from Local Settings'] = 2, ['Last Used Recall File'] = 3,
},
default = 'Last Used Recall File'
},
{ type = "label", col=0, colspan=20, align="left", title = ""},
}
local recall_options = { local recall_options = {
{ type = "label", col=0, colspan=10, align="left", title = "" }, { type = "label", col=0, colspan=10, align="left", title = "" },
{ type = "file", col=0, colspan=15, align="left", key = "file", title = "Select a Settings File", path = ARDOUR.LuaAPI.build_filename(Session:path(), "export", "params.lua") }, { type = "file", col=0, colspan=15, align="left", key = "file", title = "Select a Settings File", path = ARDOUR.LuaAPI.build_filename(Session:path(), "export", "params.lua") },
{ type = "label", col=0, colspan=10, align="left", title = "" }, { type = "label", col=0, colspan=10, align="left", title = "" },
} }
local gvld = LuaDialog.Dialog("Recall Mixer Settings:", global_vs_local_dlg):run() local default_path = ARDOUR.LuaAPI.build_filename(folder_path, 'asdf')
local file_name = "Scene_" .. snap_num
if not(gvld) then local file_path = ARDOUR.LuaAPI.build_filename(folder_path, string.format("%s-%s.lua", file_name, whoami()))
return if exists(folder_path) then
recall_options[2]['path'] = default_path
if (snap_num==0) then
local rv = LuaDialog.Dialog("Recall Mixer Settings:", recall_options):run()
if not(rv) then return end
file_name = rv['file']
file_path = rv['file']
print("About to load path " .. file_path)
end
local dry_return = LuaDialog.Dialog("Recall Mixer Settings:", dry_run(false, file_path)):run()
if dry_return then
recall(false, file_path, dry_return) --set first arg TRUE for debug
else
return
end
else else
if gvld['recall-dir'] == 1 then if (snap_num==0) then
local global_ok = isdir(global_path) LuaDialog.Message ("Recall Mixer Settings:",
local global_default_path = ARDOUR.LuaAPI.build_filename(global_path, string.format("FactoryDefault-%s.lua", whoami())) local_path .. 'does not exist!\nPlease run Store Mixer Settings first.',
print(global_default_path) LuaDialog.MessageType.Info, LuaDialog.ButtonType.Close):run()
if global_ok then else
recall_options[2]['path'] = global_default_path LuaDialog.Message ("Recall Mixer Settings:",
local rv = LuaDialog.Dialog("Recall Mixer Settings:", recall_options):run() "Mixer Snap " .. snap_num .. " does not exist yet.",
if not(rv) then return end LuaDialog.MessageType.Info, LuaDialog.ButtonType.Close):run()
local dry_return = LuaDialog.Dialog("Recall Mixer Settings:", dry_run(false, rv['file'])):run()
if dry_return then
acoraida_monicas_last_used_recall_file = rv['file']
recall(false, rv['file'], dry_return)
else
return
end
else
LuaDialog.Message ("Recall Mixer Settings:",
global_path .. ' does not exist!\nPlease run Store Mixer Settings first.',
LuaDialog.MessageType.Info, LuaDialog.ButtonType.Close):run()
end
end
if gvld['recall-dir'] == 2 then
local local_ok = isdir(local_path)
local local_default_path = ARDOUR.LuaAPI.build_filename(local_path, 'asdf')
print(local_default_path)
if local_ok then
recall_options[2]['path'] = local_default_path
local rv = LuaDialog.Dialog("Recall Mixer Settings:", recall_options):run()
if not(rv) then return end
local dry_return = LuaDialog.Dialog("Recall Mixer Settings:", dry_run(false, rv['file'])):run()
if dry_return then
acoraida_monicas_last_used_recall_file = rv['file']
recall(true, rv['file'], dry_return)
else
return
end
else
LuaDialog.Message ("Recall Mixer Settings:",
local_path .. 'does not exist!\nPlease run Store Mixer Settings first.',
LuaDialog.MessageType.Info, LuaDialog.ButtonType.Close):run()
end
end
if gvld['recall-dir'] == 3 then
if acoraida_monicas_last_used_recall_file then
local dry_return = LuaDialog.Dialog("Recall Mixer Settings:", dry_run(false, acoraida_monicas_last_used_recall_file)):run()
if dry_return then
recall(true, acoraida_monicas_last_used_recall_file, dry_return)
else
return
end
else
LuaDialog.Message ("Script has no record of last used file:",
'Please pick a recall file and then this option will be available',
LuaDialog.MessageType.Info, LuaDialog.ButtonType.Close):run()
end
end end
end end

View File

@ -5,7 +5,7 @@ ardour {
description = [[ description = [[
Stores the current Mixer state as a file Stores the current Mixer state as a file
that can be read and recalled arbitrarily that can be read and recalled arbitrarily
by it's companion script, Recall Mixer Settings. by its companion script, Recall Mixer Settings.
Supports: processor settings, grouping, Supports: processor settings, grouping,
mute, solo, gain, trim, pan and processor ordering, mute, solo, gain, trim, pan and processor ordering,
@ -13,11 +13,18 @@ ardour {
]] ]]
} }
function factory () return function () function factory (params)
return function ()
local user_cfg = ARDOUR.user_config_directory(-1) local user_cfg = ARDOUR.user_config_directory(-1)
local local_path = ARDOUR.LuaAPI.build_filename(Session:path(), 'mixer_settings') local folder_path = ARDOUR.LuaAPI.build_filename(Session:path(), 'mixer_settings')
local global_path = ARDOUR.LuaAPI.build_filename(user_cfg, 'mixer_settings')
local p = params or {}
local args = p[1] or ""
if args=="global_path" then
folder_path = ARDOUR.LuaAPI.build_filename(user_cfg, 'mixer_settings')
end
function exists(file) function exists(file)
local ok, err, code = os.rename(file, file) local ok, err, code = os.rename(file, file)
@ -46,25 +53,17 @@ function factory () return function ()
end end
function setup_paths() function setup_paths()
local global_ok, local_ok = false, false local local_ok = false
if not(isdir(global_path)) then if not(isdir(folder_path)) then
global_ok, _, _ = os.execute('mkdir '.. global_path) local_ok, _, _ = os.execute('mkdir '.. folder_path)
if global_ok == 0 then
global_ok = true
end
else
global_ok = true
end
if not(isdir(local_path)) then
local_ok, _, _ = os.execute('mkdir '.. local_path)
if local_ok == 0 then if local_ok == 0 then
local_ok = true local_ok = true
end end
else else
local_ok = true local_ok = true
end end
return global_ok, local_ok return local_ok
end end
function get_processor_by_name(track, name) function get_processor_by_name(track, name)
@ -351,42 +350,38 @@ function factory () return function ()
local store_options = { local store_options = {
{ type = "label", col=0, colspan=1, align="right", title = "Name:" }, { type = "label", col=0, colspan=1, align="right", title = "Name:" },
{ type = "entry", col=1, colspan=1, align="left" , key = "filename", default = Session:name(), title=""}, { type = "entry", col=1, colspan=1, align="left" , key = "filename", default = Session:name(), title=""},
{ type = "label", col=0, colspan=1, align="right", title = "Location:" },
{
type = "radio", col=1, colspan=3, align="left", key = "store-dir", title = "", values =
{
['Global (accessible from any session)'] = 1, ['Local (this session only)'] = 2
},
default = 'Locally (this session only)'
},
{ type = "hseparator", title="", col=0, colspan = 3}, { type = "hseparator", title="", col=0, colspan = 3},
{ type = "label", col=0, colspan=1, align="right", title = "Selected Tracks Only:" }, { type = "label", col=0, colspan=1, align="right", title = "Selected Tracks Only:" },
{ type = "checkbox", col=1, colspan=1, align="left", key = "selected", default = false, title = ""}, { type = "checkbox", col=1, colspan=1, align="left", key = "selected", default = false, title = ""},
--{ type = "label", col=0, colspan=2, align="left", title = ''}, --{ type = "label", col=0, colspan=2, align="left", title = ''},
--{ type = "label", col=0, colspan=2, align="left", title = "Global Path: " .. global_path}, --{ type = "label", col=0, colspan=2, align="left", title = "Global Path: " .. global_path},
--{ type = "label", col=0, colspan=2, align="left", title = "Local Path: " .. local_path}, --{ type = "label", col=0, colspan=2, align="left", title = "Local Path: " .. folder_path},
} }
local global_ok, local_ok = setup_paths() local snap_num = 0
for test = 0, 12, 1 do
if global_ok and local_ok then if string.find(args, string.format("Scene_%d", test)) then
local rv = LuaDialog.Dialog("Store Mixer Settings:", store_options):run() snap_num = test
if not(rv) then return end
local filename = rv['filename']
if rv['store-dir'] == 1 then
local store_path = ARDOUR.LuaAPI.build_filename(global_path, string.format("%s-%s.lua", filename, whoami()))
local selected = rv['selected']
mark_tracks(selected, store_path)
end
if rv['store-dir'] == 2 then
local store_path = ARDOUR.LuaAPI.build_filename(local_path, string.format("%s-%s.lua", filename, whoami()))
print(store_path)
local selected = rv['selected']
mark_tracks(selected, store_path)
end end
end end
local paths_ok = setup_paths()
local filename = "Scene_" .. snap_num
local selected = false --we store 'all' routes and let the user pick what to recall later
if paths_ok then
if (snap_num==0) then
local rv = LuaDialog.Dialog("Store Mixer Settings:", store_options):run()
if not(rv) then return end
filename = rv['filename']
selected = rv['selected']
end
local store_path = ARDOUR.LuaAPI.build_filename(folder_path, string.format("%s-%s.lua", filename, whoami()))
mark_tracks(selected, store_path)
if (snap_num ~= 0) then
LuaDialog.Message ("Mixer Scenes: Store", "Stored mixer settings to: " .. store_path,
LuaDialog.MessageType.Info, LuaDialog.ButtonType.Close):run()
end
end
end end end end