summaryrefslogtreecommitdiff
path: root/gtk2_ardour/foldback_strip.cc
diff options
context:
space:
mode:
authorLen Ovens <len@ovenwerks.net>2019-08-21 20:55:51 -0700
committerLen Ovens <len@ovenwerks.net>2019-08-26 17:48:22 -0700
commita2de8bd88143b6092e102aded0b4669b44a2ea40 (patch)
tree5fc1337b7ca9609ef6146156ce4c4bd3d88e686b /gtk2_ardour/foldback_strip.cc
parentfe1442dec9eed5779f15448c36e432670d434a90 (diff)
Add send controls to foldback GUI
Diffstat (limited to 'gtk2_ardour/foldback_strip.cc')
-rw-r--r--gtk2_ardour/foldback_strip.cc375
1 files changed, 245 insertions, 130 deletions
diff --git a/gtk2_ardour/foldback_strip.cc b/gtk2_ardour/foldback_strip.cc
index b3332d2a17..e1d0e4753f 100644
--- a/gtk2_ardour/foldback_strip.cc
+++ b/gtk2_ardour/foldback_strip.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2000-2006 Paul Davis
+ Copyright (C) 2018-2019 Len Ovens
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -32,7 +32,9 @@
#include "ardour/amp.h"
#include "ardour/audioengine.h"
#include "ardour/internal_send.h"
+#include "ardour/internal_return.h"
#include "ardour/io.h"
+#include "ardour/io_processor.h"
#include "ardour/pannable.h"
#include "ardour/panner.h"
#include "ardour/panner_shell.h"
@@ -44,6 +46,7 @@
#include "ardour/session.h"
#include "ardour/types.h"
#include "ardour/user_bundle.h"
+#include "ardour/value_as_string.h"
#include "gtkmm2ext/gtk_ui.h"
#include "gtkmm2ext/menu_elems.h"
@@ -73,6 +76,154 @@ using namespace Gtk;
using namespace Gtkmm2ext;
using namespace std;
+#define PX_SCALE(px) std::max((float)px, rintf((float)px * UIConfiguration::instance().get_ui_scale()))
+
+FoldbackSend::FoldbackSend (boost::shared_ptr<Send> snd, \
+ boost::shared_ptr<ARDOUR::Route> sr, boost::shared_ptr<ARDOUR::Route> fr)
+ : _button (ArdourButton::led_default_elements)
+ , _send (snd)
+ , _send_route (sr)
+ , _foldback_route (fr)
+ , _send_proc (snd)
+ , _send_del (snd)
+ , pan_control (ArdourKnob::default_elements, ArdourKnob::Flags (ArdourKnob::Detent | ArdourKnob::ArcToZero))
+ , _adjustment (gain_to_slider_position_with_max (1.0, Config->get_max_gain()), 0, 1, 0.01, 0.1)
+ , _slider (&_adjustment, boost::shared_ptr<PBD::Controllable>(), 0, max(13.f, rintf(13.f * UIConfiguration::instance().get_ui_scale())))
+ , _ignore_ui_adjustment (true)
+ , _slider_persistant_tooltip (&_slider)
+
+{
+
+ //Gtk::HBox * snd_but_pan = new Gtk::HBox ();
+ HBox * snd_but_pan = new HBox ();
+
+ _button.set_distinct_led_click (true);
+ _button.set_fallthrough_to_parent(true);
+ _button.set_led_left (true);
+ _button.signal_led_clicked.connect (sigc::mem_fun (*this, &FoldbackSend::led_clicked));
+ _button.set_name ("processor prefader");
+ _button.set_text (_send_route->name());
+ snd_but_pan->pack_start (_button, true, true);
+ _button.set_active (_send_proc->enabled ());
+ _button.show ();
+
+ if (_foldback_route->input()->n_ports().n_audio() == 2) {
+ boost::shared_ptr<Pannable> pannable = _send_del->panner()->pannable();
+ boost::shared_ptr<AutomationControl> ac;
+ ac = pannable->pan_azimuth_control;
+ pan_control.set_size_request (PX_SCALE(19), PX_SCALE(19));
+ pan_control.set_tooltip_prefix (_("Pan: "));
+ pan_control.set_name ("trim knob");
+ pan_control.set_no_show_all (true);
+ snd_but_pan->pack_start (pan_control, false, false);
+ pan_control.show ();
+ pan_control.set_controllable (ac);
+ }
+ boost::shared_ptr<AutomationControl> lc;
+ lc = _send->gain_control();
+ _slider.set_controllable (lc);
+ _slider.set_name ("ProcessorControlSlider");
+ _slider.set_text (_("Level"));
+
+
+
+ pack_start (*snd_but_pan, Gtk::PACK_SHRINK);
+ snd_but_pan->show();
+ pack_start (_slider, true, true);
+ _slider.show ();
+ level_changed ();
+ _adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &FoldbackSend::level_adjusted));
+ lc->Changed.connect (_connections, invalidator (*this), boost::bind (&FoldbackSend::level_changed, this), gui_context ());
+ _send_proc->ActiveChanged.connect (_connections, invalidator (*this), boost::bind (&FoldbackSend::send_state_changed, this), gui_context ());
+
+ show ();
+
+
+}
+
+FoldbackSend::~FoldbackSend ()
+{
+ _send = boost::shared_ptr<Send> ();
+ _send_route = boost::shared_ptr<Route> ();
+ _foldback_route = boost::shared_ptr<Route> ();
+ _send_proc = boost::shared_ptr<Processor> ();
+ _send_del = boost::shared_ptr<Delivery> ();
+ _connections.drop_connections();
+ pan_control.set_controllable (boost::shared_ptr<AutomationControl> ());
+ _slider.set_controllable (boost::shared_ptr<AutomationControl> ());
+
+}
+
+void
+FoldbackSend::led_clicked(GdkEventButton *ev)
+{
+ if (_send_proc) {
+ if (_button.get_active ()) {
+ _send_proc->enable (false);
+
+ } else {
+ _send_proc->enable (true);
+ }
+ }
+}
+
+void
+FoldbackSend::send_state_changed ()
+{
+ _button.set_active (_send_proc->enabled ());
+
+}
+
+void
+FoldbackSend::level_adjusted ()
+{
+ if (_ignore_ui_adjustment) {
+ return;
+ }
+ boost::shared_ptr<AutomationControl> lc = _send->gain_control();
+
+ if (!lc) {
+ return;
+ }
+
+ lc->set_value ( lc->interface_to_internal(_adjustment.get_value ()) , Controllable::NoGroup);
+ set_tooltip ();
+}
+
+void
+FoldbackSend::level_changed ()
+{
+ boost::shared_ptr<AutomationControl> lc = _send->gain_control();
+ if (!lc) {
+ return;
+ }
+
+ _ignore_ui_adjustment = true;
+
+ const double nval = lc->internal_to_interface (lc->get_value ());
+ if (_adjustment.get_value() != nval) {
+ _adjustment.set_value (nval);
+ set_tooltip ();
+ }
+
+ _ignore_ui_adjustment = false;
+}
+
+void
+FoldbackSend::set_tooltip ()
+{
+ boost::shared_ptr<AutomationControl> lc = _send->gain_control();
+
+ if (!lc) {
+ return;
+ }
+ std::string tt = ARDOUR::value_as_string (lc->desc(), lc->get_value ());
+ string sm = Gtkmm2ext::markup_escape_text (tt);
+ _slider_persistant_tooltip.set_tip (sm);
+ ArdourWidgets::set_tooltip (_button, Gtkmm2ext::markup_escape_text (sm));
+}
+
+
FoldbackStrip* FoldbackStrip::_entered_foldback_strip;
PBD::Signal1<void,FoldbackStrip*> FoldbackStrip::CatchDeletion;
@@ -83,13 +234,11 @@ FoldbackStrip::FoldbackStrip (Mixer_UI& mx, Session* sess, boost::shared_ptr<Rou
, _mixer_owned (true)
, _pr_selection ()
, panners (sess)
- , button_size_group (Gtk::SizeGroup::create (Gtk::SIZE_GROUP_HORIZONTAL))
, mute_solo_table (1, 2)
, bottom_button_table (1, 1)
, _plugin_insert_cnt (0)
, _comment_button (_("Comments"))
, fb_level_control (0)
-// , _visibility (X_("mixer-element-visibility"))
{
_session = sess;
init ();
@@ -110,38 +259,35 @@ FoldbackStrip::init ()
/* the length of this string determines the width of the mixer strip when it is set to `wide' */
longest_label = "longest label";
-
output_button.set_text (_("Output"));
output_button.set_name ("mixer strip button");
-// send_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
-// send_scroller.add (send_display);
+
+ send_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
+ send_scroller.add (send_display);
send_display.set_flags (CAN_FOCUS);
- send_display.set_name ("ProcessorList");
- send_display.set_data ("sendbox", this);
- send_display.set_size_request (48, -1);
- send_display.set_spacing (0);
+ //send_display.set_name ("ProcessorList");
+ send_display.set_name ("AudioBusStripBase");
+ send_display.set_spacing (4);
insert_box = new ProcessorBox (0, boost::bind (&FoldbackStrip::plugin_selector, this), _pr_selection, 0);
insert_box->set_no_show_all ();
insert_box->show ();
insert_box->set_session (_session);
-// send_scroller.show ();
+ send_scroller.show ();
send_display.show ();
- // TODO implement ArdourKnob::on_size_request properly
fb_level_control = new ArdourKnob (ArdourKnob::default_elements, ArdourKnob::Detent);
-
-#define PX_SCALE(px) std::max((float)px, rintf((float)px * UIConfiguration::instance().get_ui_scale()))
fb_level_control->set_size_request (PX_SCALE(65), PX_SCALE(65));
-#undef PX_SCALE
fb_level_control->set_tooltip_prefix (_("Level: "));
fb_level_control->set_name ("monitor section knob");
fb_level_control->set_no_show_all (true);
bottom_button_table.attach (*fb_level_control, 0, 1, 0, 1,FILL,FILL,20,20); //EXPAND
-
+ bottom_button_table.set_spacings (20);
+ bottom_button_table.set_row_spacings (20);
+ bottom_button_table.set_homogeneous (true);
mute_solo_table.set_homogeneous (true);
mute_solo_table.set_spacings (2);
@@ -151,14 +297,11 @@ FoldbackStrip::init ()
show_sends_box.pack_start (*show_sends_button, true, true);
show_sends_button->show();
- bottom_button_table.set_spacings (20);
- bottom_button_table.set_row_spacings (20);
- bottom_button_table.set_homogeneous (true);
- name_button.set_name ("monitor section button");
+ name_button.set_name ("mixer strip button");
name_button.set_text_ellipsize (Pango::ELLIPSIZE_END);
- _select_button.set_name ("monitor section button");
+ _select_button.set_name ("mixer strip button");
_select_button.set_text (_("Select Foldback Bus"));
_comment_button.set_name (X_("mixer strip button"));
@@ -166,13 +309,13 @@ FoldbackStrip::init ()
_comment_button.signal_clicked.connect (sigc::mem_fun (*this, &RouteUI::toggle_comment_editor));
global_vpacker.set_border_width (1);
-
global_vpacker.set_spacing (4);
+
global_vpacker.pack_start (_select_button, Gtk::PACK_SHRINK);
global_vpacker.pack_start (name_button, Gtk::PACK_SHRINK);
global_vpacker.pack_start (_invert_button_box, Gtk::PACK_SHRINK);
global_vpacker.pack_start (show_sends_box, Gtk::PACK_SHRINK);
-
+ global_vpacker.pack_start (send_scroller, true, true);
#ifndef MIXBUS
//add a spacer underneath the foldback bus;
//this fills the area that is taken up by the scrollbar on the tracks;
@@ -192,11 +335,10 @@ FoldbackStrip::init ()
#endif
global_vpacker.pack_end (_comment_button, Gtk::PACK_SHRINK);
global_vpacker.pack_end (output_button, Gtk::PACK_SHRINK);
+ global_vpacker.pack_end (*insert_box, Gtk::PACK_SHRINK);
+ global_vpacker.pack_end (bottom_button_table, Gtk::PACK_SHRINK);
global_vpacker.pack_end (mute_solo_table, Gtk::PACK_SHRINK);
global_vpacker.pack_end (panners, Gtk::PACK_SHRINK);
- global_vpacker.pack_end (bottom_button_table, Gtk::PACK_SHRINK);
-// global_vpacker.pack_end (*insert_box, true, true);
- global_vpacker.pack_end (*insert_box, Gtk::PACK_SHRINK);
global_frame.add (global_vpacker);
global_frame.set_shadow_type (Gtk::SHADOW_IN);
@@ -208,7 +350,6 @@ FoldbackStrip::init ()
_selected = true;
set_selected (false);
-
_packed = false;
_embedded = false;
@@ -216,23 +357,14 @@ FoldbackStrip::init ()
_session->engine().Running.connect (*this, invalidator (*this), boost::bind (&FoldbackStrip::engine_running, this), gui_context());
output_button.set_text_ellipsize (Pango::ELLIPSIZE_MIDDLE);
-
output_button.signal_button_press_event().connect (sigc::mem_fun(*this, &FoldbackStrip::output_press), false);
output_button.signal_button_release_event().connect (sigc::mem_fun(*this, &FoldbackStrip::output_release), false);
-
name_button.signal_button_press_event().connect (sigc::mem_fun(*this, &FoldbackStrip::name_button_button_press), false);
_select_button.signal_button_press_event().connect (sigc::mem_fun (*this, &FoldbackStrip::select_button_button_press), false);
_width = Wide;
-
- /* start off as a passthru strip. we'll correct this, if necessary,
- in update_diskstream_display().
- */
-
-
-
add_events (Gdk::BUTTON_RELEASE_MASK|
Gdk::ENTER_NOTIFY_MASK|
Gdk::LEAVE_NOTIFY_MASK|
@@ -245,19 +377,6 @@ FoldbackStrip::init ()
*this, invalidator (*this), boost::bind (&FoldbackStrip::port_connected_or_disconnected, this, _1, _3), gui_context ()
);
- /* Add the widgets under visibility control to the VisibilityGroup; the names used here
- must be the same as those used in RCOptionEditor so that the configuration changes
- are recognised when they occur.
- */
-/* _visibility.add (&_invert_button_box, X_("PhaseInvert"), _("Phase Invert"), false);
- _visibility.add (&output_button, X_("Output"), _("Output"), false);
- _visibility.add (&_comment_button, X_("Comments"), _("Comments"), false);
-
- parameter_changed (X_("mixer-element-visibility"));
- UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &FoldbackStrip::parameter_changed));
- Config->ParameterChanged.connect (_config_connection, MISSING_INVALIDATOR, boost::bind (&FoldbackStrip::parameter_changed, this, _1), gui_context());
- _session->config.ParameterChanged.connect (_config_connection, MISSING_INVALIDATOR, boost::bind (&FoldbackStrip::parameter_changed, this, _1), gui_context());
-*/
//watch for mouse enter/exit so we can do some stuff
signal_enter_notify_event().connect (sigc::mem_fun(*this, &FoldbackStrip::mixer_strip_enter_event ));
signal_leave_notify_event().connect (sigc::mem_fun(*this, &FoldbackStrip::mixer_strip_leave_event ));
@@ -269,6 +388,8 @@ FoldbackStrip::~FoldbackStrip ()
CatchDeletion (this);
delete fb_level_control;
fb_level_control = 0;
+ _connections.drop_connections();
+ clear_send_box ();
if (this ==_entered_foldback_strip)
_entered_foldback_strip = NULL;
@@ -319,28 +440,16 @@ FoldbackStrip::set_route (boost::shared_ptr<Route> rt)
{
/// FIX NO route
if (!rt) {
+ clear_send_box ();
RouteUI::self_delete ();
return;
}
- if (show_sends_button->get_parent()) {
- show_sends_box.remove (*show_sends_button);
- }
RouteUI::set_route (rt);
- /* ProcessorBox needs access to _route so that it can read
- GUI object state.
- */
-// processor_box.set_route (rt);
- insert_box->set_route (rt);
-
+ insert_box->set_route (_route);
revert_to_default_display ();
-
-
-// mute_solo_table.attach (gpm.gain_display,0,1,1,2, EXPAND|FILL, EXPAND);
-// mute_solo_table.attach (gpm.peak_display,1,2,1,2, EXPAND|FILL, EXPAND);
-
if (solo_button->get_parent()) {
mute_solo_table.remove (*solo_button);
}
@@ -354,23 +463,18 @@ FoldbackStrip::set_route (boost::shared_ptr<Route> rt)
mute_button->show ();
solo_button->show ();
show_sends_box.show ();
-
spacer.show();
-
update_fb_level_control();
- show_sends_box.pack_start (*show_sends_button, true, true);
+ BusSendDisplayChanged (boost::shared_ptr<Route> ());
show_sends_button->show();
-
delete route_ops_menu;
route_ops_menu = 0;
-
delete route_select_menu;
route_select_menu = 0;
_route->output()->changed.connect (*this, invalidator (*this), boost::bind (&FoldbackStrip::update_output_display, this), gui_context());
-
_route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&FoldbackStrip::io_changed_proxy, this), gui_context ());
if (_route->panner_shell()) {
@@ -382,55 +486,22 @@ FoldbackStrip::set_route (boost::shared_ptr<Route> rt)
set_stuff_from_route ();
+ _session->DirtyChanged.connect (route_connections, invalidator (*this), boost::bind (&FoldbackStrip::update_send_box, this), gui_context());
/* now force an update of all the various elements */
update_mute_display ();
update_solo_display ();
name_changed ();
comment_changed ();
-
connect_to_pan ();
panners.setup_pan ();
panners.show_all ();
-
update_output_display ();
add_events (Gdk::BUTTON_RELEASE_MASK);
insert_box->show ();
-
- Route::FedBy fed_by = _route->fed_by();
- for (Route::FedBy::iterator i = fed_by.begin(); i != fed_by.end(); ++i) {
- if (i->sends_only) {
- boost::shared_ptr<Route> s_rt (i->r.lock());
- boost::shared_ptr<Send> snd = s_rt->internal_send_for (_route);
- //s_rt->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&FoldbackStrip::fill_sendbox, this), this);
- boost::shared_ptr<Processor> processor (snd);
- //boost::shared_ptr<PluginInsert> plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (processor);
-// Ok we have the info... now we need widgets to put it in... I suspect I need a class or three
-// this doesn't work... and I need to clear it out and rebuild each time.
- ArdourWidgets::ArdourButton _button;
- _button.set_distinct_led_click (true);
- _button.set_fallthrough_to_parent(true);
- _button.set_led_left (true);
-// _button.signal_led_clicked.connect (sigc::mem_fun (*this, &FoldbackStrip::led_clicked));
- _button.set_text (s_rt->name ());
-
- //Gtk::VBox snd_entry = NULL;
- Gtk::VBox snd_entry;
- snd_entry.set_border_width (1);
- snd_entry.set_spacing (4);
- snd_entry.pack_start (_button, true, true);
- send_display.pack_start (snd_entry, true, true);
- _button.show ();
- snd_entry.show ();
-
-
- }
- }
-
-
-
+ update_send_box ();
global_frame.show();
global_vpacker.show();
mute_solo_table.show();
@@ -449,6 +520,70 @@ FoldbackStrip::set_route (boost::shared_ptr<Route> rt)
}
void
+FoldbackStrip::update_send_box ()
+{
+ std::cout << "update_send_box\n";
+ clear_send_box ();
+ if (!_route) {
+ return;
+ }
+ std::cout << "update_send_box get fedby\n";
+ Route::FedBy fed_by = _route->fed_by();
+ std::cout << "update_send_box got fedby\n";
+ for (Route::FedBy::iterator i = fed_by.begin(); i != fed_by.end(); ++i) {
+ std::cout << "update_send_box route: " << i->r.lock()->name() << " \n";
+ if (i->sends_only) {
+ boost::shared_ptr<Route> s_rt (i->r.lock());
+ std::cout << "update_send_box sends only for " << s_rt->name() << " \n";
+ boost::shared_ptr<Send> snd = s_rt->internal_send_for (_route);
+ if (snd) {
+ std::cout << "update_send_box got send\n";
+ FoldbackSend * fb_s = new FoldbackSend (snd, s_rt, _route);
+ std::cout << "update_send_box started new FoldbackSend\n";
+ send_display.pack_start (*fb_s, Gtk::PACK_SHRINK);
+ std::cout << "update_send_box FbS packed\n";
+ fb_s->show ();
+ std::cout << "update_send_box FbS shown\n";
+ s_rt->processors_changed.connect (_connections, invalidator (*this), boost::bind (&FoldbackStrip::processors_changed, this, _1), gui_context ());
+ std::cout << "update_send_box sending route changed connected\n";
+ }
+ }
+ }
+ std::cout << "update_send_box finished\n";
+}
+
+void
+FoldbackStrip::update_send_box_2 (IOProcessor*,uint32_t)
+{
+ std::cout << "update_send_box_2\n";
+ update_send_box ();
+}
+
+void
+FoldbackStrip::clear_send_box ()
+{
+ std::cout << "clear_send_box\n";
+ std::vector< Widget* > snd_list = send_display.get_children ();
+ _connections.drop_connections ();
+ for (uint32_t i = 0; i < snd_list.size(); i++) {
+ std::cout << "clear_send_box for " << i << "\n";
+ send_display.remove (*(snd_list[i]));
+ delete snd_list[i];
+ std::cout << "clear_send_box deleted " << i << "\n";
+ }
+ std::cout << "clear_send_box for finished\n";
+ snd_list.clear();
+ std::cout << "clear_send_box list cleared\n";
+}
+
+void
+FoldbackStrip::processors_changed (RouteProcessorChange)
+{
+ std::cout << "processors_changed\n";
+ update_send_box ();
+}
+
+void
FoldbackStrip::set_stuff_from_route ()
{
/* if width is not set, it will be set by the MixerUI or editor */
@@ -1176,26 +1311,8 @@ FoldbackStrip::name_changed ()
set_tooltip (name_button, Gtkmm2ext::markup_escape_text(_route->name()));
}
-/*
-void
-FoldbackStrip::output_button_resized (Gtk::Allocation& alloc)
-{
- //output_button.set_layout_ellipsize_width (alloc.get_width() * PANGO_SCALE);
-}
void
-FoldbackStrip::name_button_resized (Gtk::Allocation& alloc)
-{
- //name_button.set_layout_ellipsize_width (20);
-}
-
-void
-FoldbackStrip::comment_button_resized (Gtk::Allocation& alloc)
-{
- //_comment_button.set_layout_ellipsize_width (alloc.get_width() * PANGO_SCALE);
-}
-*/
-void
FoldbackStrip::set_embedded (bool yn)
{
_embedded = yn;
@@ -1224,7 +1341,6 @@ FoldbackStrip::hide_processor_editor (boost::weak_ptr<Processor> p)
return;
}
-// Gtk::Window* w = processor_box.get_processor_ui (processor);
Gtk::Window* w = insert_box->get_processor_ui (processor);
if (w) {
@@ -1436,15 +1552,10 @@ FoldbackStrip::color () const
return route_color ();
}
-/*bool
-FoldbackStrip::marked_for_display () const
-{
- return !_route->presentation_info().hidden();
-}*/
-
void
FoldbackStrip::remove_current_fb ()
{
+ clear_send_box ();
StripableList slist;
boost::shared_ptr<Route> next = boost::shared_ptr<Route> ();
boost::shared_ptr<Route> old_route = _route;
@@ -1459,8 +1570,12 @@ FoldbackStrip::remove_current_fb ()
}
if (next) {
set_route (next);
+ _session->remove_route (old_route);
+ } else {
+ //_session->remove_route (old_route);
+ clear_send_box ();
+ RouteUI::self_delete ();
}
- _session->remove_route (old_route);
}