75% (?) of the way towards making mixer strips control bus sends. lots more to do

git-svn-id: svn://localhost/ardour2/branches/3.0@5090 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2009-05-17 02:08:13 +00:00
parent 091bd8a778
commit 7deb14773b
15 changed files with 276 additions and 73 deletions

View File

@ -165,7 +165,13 @@ GainMeterBase::set_io (boost::shared_ptr<IO> io)
_io = io;
level_meter->set_meter (_io->peak_meter());
if (!_io) {
level_meter->set_meter (0);
gain_slider->set_controllable (boost::shared_ptr<PBD::Controllable>());
return;
}
level_meter->set_meter (&_io->peak_meter());
gain_slider->set_controllable (_io->gain_control());
boost::shared_ptr<Route> r;
@ -836,6 +842,14 @@ GainMeter::set_io (boost::shared_ptr<IO> io)
if (!r->is_hidden()) {
fader_vbox->pack_start (gain_automation_state_button, false, false, 0);
}
} else {
/* we're managing a non-Route IO (e.g. Send) */
gain_display_box.pack_end (peak_display, true, true);
hbox.pack_end (*level_meter, true, true);
fader_vbox->pack_start (gain_automation_state_button, false, false, 0);
}
}

View File

@ -80,12 +80,14 @@ LevelMeter::~LevelMeter ()
}
void
LevelMeter::set_meter (PeakMeter& meter)
LevelMeter::set_meter (PeakMeter* meter)
{
_configuration_connection.disconnect();
_meter = &meter;
_configuration_connection = _meter->ConfigurationChanged.connect(
_meter = meter;
if (_meter) {
_configuration_connection = _meter->ConfigurationChanged.connect(
mem_fun(*this, &LevelMeter::configuration_changed));
}
}
float
@ -94,6 +96,10 @@ LevelMeter::update_meters ()
vector<MeterInfo>::iterator i;
uint32_t n;
float peak, mpeak;
if (!_meter) {
return 0.0f;
}
for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) {
if ((*i).packed) {
@ -149,8 +155,10 @@ LevelMeter::hide_all_meters ()
void
LevelMeter::setup_meters (int len, int initial_width)
{
hide_all_meters ();
if (!_meter) {
return; /* do it later */
return; /* do it later or never */
}
int32_t nmidi = _meter->input_streams().n_midi();
@ -160,8 +168,6 @@ LevelMeter::setup_meters (int len, int initial_width)
guint16 width;
hide_all_meters ();
if (nmeters == 0) {
return;
}

View File

@ -55,7 +55,7 @@ class LevelMeter : public Gtk::HBox
LevelMeter (ARDOUR::Session&);
~LevelMeter ();
virtual void set_meter (ARDOUR::PeakMeter& meter);
virtual void set_meter (ARDOUR::PeakMeter* meter);
void update_gain_sensitive ();

View File

@ -67,6 +67,8 @@ using namespace Gtk;
using namespace Gtkmm2ext;
using namespace std;
sigc::signal<void,boost::shared_ptr<Route> > MixerStrip::SwitchIO;
int MixerStrip::scrollbar_height = 0;
#ifdef VARISPEED_IN_MIXER_STRIP
@ -88,8 +90,8 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, bool in_mixer)
, RouteUI (sess, _("Mute"), _("Solo"), _("Record"))
,_mixer(mx)
, _mixer_owned (in_mixer)
, pre_processor_box (PreFader, sess, mx.plugin_selector(), mx.selection(), in_mixer)
, post_processor_box (PostFader, sess, mx.plugin_selector(), mx.selection(), in_mixer)
, pre_processor_box (PreFader, sess, mx.plugin_selector(), mx.selection(), this, in_mixer)
, post_processor_box (PostFader, sess, mx.plugin_selector(), mx.selection(), this, in_mixer)
, gpm (sess)
, panners (sess)
, button_table (3, 2)
@ -117,8 +119,8 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
, RouteUI (sess, _("Mute"), _("Solo"), _("Record"))
,_mixer(mx)
, _mixer_owned (in_mixer)
, pre_processor_box (PreFader, sess, mx.plugin_selector(), mx.selection(), in_mixer)
, post_processor_box (PostFader, sess, mx.plugin_selector(), mx.selection(), in_mixer)
, pre_processor_box (PreFader, sess, mx.plugin_selector(), mx.selection(), this, in_mixer)
, post_processor_box (PostFader, sess, mx.plugin_selector(), mx.selection(), this, in_mixer)
, gpm (sess)
, panners (sess)
, button_table (3, 2)
@ -290,6 +292,12 @@ MixerStrip::init ()
rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press), false);
rec_enable_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::rec_enable_release));
/* ditto for this button and busses */
show_sends_button->set_name ("MixerRecordEnableButton");
show_sends_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::show_sends_press), false);
show_sends_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::show_sends_release));
name_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::name_button_button_press), false);
group_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::select_mix_group), false);
@ -309,6 +317,9 @@ MixerStrip::init ()
set_name ("AudioTrackStripBase");
add_events (Gdk::BUTTON_RELEASE_MASK);
SwitchIO.connect (mem_fun (*this, &MixerStrip::switch_io));
}
MixerStrip::~MixerStrip ()
@ -326,6 +337,10 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
button_table.remove (*rec_enable_button);
}
if (show_sends_button->get_parent()) {
button_table.remove (*show_sends_button);
}
#ifdef VARISPEED_IN_MIXER_STRIP
if (speed_frame->get_parent()) {
button_table.remove (*speed_frame);
@ -384,6 +399,12 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
button_table.attach (*rec_enable_button, 0, 2, 2, 3);
rec_enable_button->show();
} else if (!is_track()) {
/* bus */
button_table.attach (*show_sends_button, 0, 2, 2, 3);
show_sends_button->show();
}
if (_route->phase_invert()) {
@ -562,6 +583,9 @@ MixerStrip::set_width (Width w, void* owner)
if (rec_enable_button) {
((Gtk::Label*)rec_enable_button->get_child())->set_text (_("Record"));
}
if (show_sends_button) {
((Gtk::Label*)show_sends_button->get_child())->set_text (_("Sends"));
}
((Gtk::Label*)mute_button->get_child())->set_text (_("Mute"));
((Gtk::Label*)solo_button->get_child())->set_text (_("Solo"));
@ -593,6 +617,9 @@ MixerStrip::set_width (Width w, void* owner)
if (rec_enable_button) {
((Gtk::Label*)rec_enable_button->get_child())->set_text (_("Rec"));
}
if (show_sends_button) {
((Gtk::Label*)show_sends_button->get_child())->set_text (_("Snd"));
}
((Gtk::Label*)mute_button->get_child())->set_text (_("M"));
((Gtk::Label*)solo_button->get_child())->set_text (_("S"));
@ -1462,3 +1489,24 @@ MixerStrip::meter_changed (void *src)
set_width(_width, this);
}
void
MixerStrip::switch_io (boost::shared_ptr<Route> target)
{
boost::shared_ptr<IO> to_display;
if (_route == target) {
/* don't change the display for the target */
return;
}
if (!target) {
to_display = _route;
} else {
to_display = _route->send_io_for (target);
}
gain_meter().set_io (to_display);
gain_meter().setup_meters ();
panner_ui().set_io (to_display);
panner_ui().setup_pan ();
}

View File

@ -88,6 +88,9 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
Width get_width() const { return _width; }
void* width_owner() const { return _width_owner; }
GainMeter& gain_meter() { return gpm; }
PannerUI& panner_ui() { return panners; }
void fast_update ();
void set_embedded (bool);
@ -98,6 +101,8 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
sigc::signal<void> WidthChanged;
#endif
static sigc::signal<void,boost::shared_ptr<ARDOUR::Route> > SwitchIO;
protected:
friend class Mixer_UI;
void set_packed (bool yn);
@ -257,6 +262,8 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
void engine_running();
void engine_stopped();
void switch_io (boost::shared_ptr<ARDOUR::Route>);
static int scrollbar_height;
};

View File

@ -133,7 +133,7 @@ PannerUI::PannerUI (Session& s)
void
PannerUI::set_io (boost::shared_ptr<IO> io)
{
if (!io->panner()) {
if (io && !io->panner()) {
cerr << "PannerUI::set_io IO has no panners" << endl;
return;
}
@ -148,15 +148,16 @@ PannerUI::set_io (boost::shared_ptr<IO> io)
_io = io;
connections.push_back (_io->panner()->Changed.connect (
mem_fun(*this, &PannerUI::panner_changed)));
connections.push_back (_io->panner()->LinkStateChanged.connect (
mem_fun(*this, &PannerUI::update_pan_linkage)));
connections.push_back (_io->panner()->StateChanged.connect (
mem_fun(*this, &PannerUI::update_pan_state)));
delete panner;
panner = 0;
if (!_io) {
return;
}
connections.push_back (_io->panner()->Changed.connect (mem_fun(*this, &PannerUI::panner_changed)));
connections.push_back (_io->panner()->LinkStateChanged.connect (mem_fun(*this, &PannerUI::update_pan_linkage)));
connections.push_back (_io->panner()->StateChanged.connect (mem_fun(*this, &PannerUI::update_pan_state)));
setup_pan ();
@ -338,7 +339,7 @@ PannerUI::update_pan_state ()
void
PannerUI::setup_pan ()
{
if (!_io->panner()) {
if (!_io || !_io->panner()) {
return;
}

View File

@ -59,6 +59,7 @@
#include "io_selector.h"
#include "keyboard.h"
#include "mixer_ui.h"
#include "mixer_strip.h"
#include "plugin_selector.h"
#include "plugin_ui.h"
#include "processor_box.h"
@ -89,8 +90,9 @@ Gdk::Color* ProcessorBox::active_processor_color;
Gdk::Color* ProcessorBox::inactive_processor_color;
ProcessorBox::ProcessorBox (Placement pcmnt, Session& sess, PluginSelector &plugsel,
RouteRedirectSelection & rsel, bool owner_is_mixer)
RouteRedirectSelection & rsel, MixerStrip* parent, bool owner_is_mixer)
: _session(sess)
, _parent_strip (parent)
, _owner_is_mixer (owner_is_mixer)
, _placement(pcmnt)
, _plugin_selector(plugsel)
@ -1193,12 +1195,10 @@ ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
return;
}
boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (processor);
#ifdef OLD_SEND_EDITING
SendUIWindow *send_ui;
if (send->get_gui() == 0) {
send_ui = new SendUIWindow (send, _session);
WindowTitle title(Glib::get_application_name());
@ -1212,6 +1212,12 @@ ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
}
gidget = send_ui;
#else
if (_parent_strip) {
_parent_strip->gain_meter().set_io (send->io());
_parent_strip->panner_ui().set_io (send->io());
}
#endif
} else if ((retrn = boost::dynamic_pointer_cast<Return> (processor)) != 0) {

View File

@ -52,6 +52,7 @@ class MotionController;
class PluginSelector;
class PluginUIWindow;
class RouteRedirectSelection;
class MixerStrip;
namespace ARDOUR {
class Connection;
@ -68,7 +69,7 @@ namespace ARDOUR {
class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
{
public:
ProcessorBox (ARDOUR::Placement, ARDOUR::Session&, PluginSelector &, RouteRedirectSelection &, bool owner_is_mixer = false);
ProcessorBox (ARDOUR::Placement, ARDOUR::Session&, PluginSelector &, RouteRedirectSelection &, MixerStrip* parent, bool owner_is_mixer = false);
~ProcessorBox ();
void set_route (boost::shared_ptr<ARDOUR::Route>);
@ -90,6 +91,7 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
private:
boost::shared_ptr<ARDOUR::Route> _route;
ARDOUR::Session & _session;
MixerStrip* _parent_strip; // null if in RouteParamsUI
bool _owner_is_mixer;
bool ab_direction;
std::vector<sigc::connection> connections;

View File

@ -231,8 +231,8 @@ RouteParams_UI::setup_processor_boxes()
cleanup_processor_boxes();
// construct new redirect boxes
pre_insert_box = new ProcessorBox(PreFader, *session, *_plugin_selector, _rr_selection);
post_insert_box = new ProcessorBox(PostFader, *session, *_plugin_selector, _rr_selection);
pre_insert_box = new ProcessorBox(PreFader, *session, *_plugin_selector, _rr_selection, 0);
post_insert_box = new ProcessorBox(PostFader, *session, *_plugin_selector, _rr_selection, 0);
pre_insert_box->set_route (_route);
post_insert_box->set_route (_route);

View File

@ -38,6 +38,7 @@
#include "gui_thread.h"
#include "ardour_dialog.h"
#include "latency_gui.h"
#include "mixer_strip.h"
#include "automation_time_axis.h"
#include "ardour/route.h"
@ -84,6 +85,7 @@ RouteUI::~RouteUI()
delete solo_menu;
delete mute_menu;
delete remote_control_menu;
delete sends_menu;
}
void
@ -94,6 +96,7 @@ RouteUI::init ()
mute_menu = 0;
solo_menu = 0;
remote_control_menu = 0;
sends_menu = 0;
ignore_toggle = false;
wait_for_release = false;
route_active_menu_item = 0;
@ -118,6 +121,11 @@ RouteUI::init ()
rec_enable_button->set_self_managed (true);
UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
show_sends_button = manage (new BindableToggleButton (""));
show_sends_button->set_name ("ShowSendsButton");
show_sends_button->set_self_managed (true);
UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
_session.SoloChanged.connect (mem_fun(*this, &RouteUI::solo_changed_so_update_mute));
}
@ -497,6 +505,83 @@ RouteUI::rec_enable_release (GdkEventButton* ev)
return true;
}
void
RouteUI::build_sends_menu ()
{
using namespace Menu_Helpers;
sends_menu = new Menu;
sends_menu->set_name ("ArdourContextMenu");
MenuList& items = sends_menu->items();
items.push_back (MenuElem(_("Copy track gains to sends"), mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
items.push_back (MenuElem(_("Set sends gain to -inf"), mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
items.push_back (MenuElem(_("Set sends gain to 0dB"), mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
}
void
RouteUI::set_sends_gain_from_track ()
{
}
void
RouteUI::set_sends_gain_to_zero ()
{
}
void
RouteUI::set_sends_gain_to_unity ()
{
}
bool
RouteUI::show_sends_press(GdkEventButton* ev)
{
if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
return true;
}
if (!ignore_toggle && !is_track() && show_sends_button) {
if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
// do nothing on midi bind event
return false;
} else if (Keyboard::is_context_menu_event (ev)) {
if (sends_menu == 0) {
build_sends_menu ();
}
sends_menu->popup (0, ev->time);
} else {
/* change button state */
show_sends_button->set_active (!show_sends_button->get_active());
if (show_sends_button->get_active()) {
/* show sends to this bus */
MixerStrip::SwitchIO (_route);
} else {
/* everybody back to normal */
MixerStrip::SwitchIO (boost::shared_ptr<Route>());
}
}
}
return true;
}
bool
RouteUI::show_sends_release (GdkEventButton* ev)
{
return true;
}
void
RouteUI::solo_changed(void* src)
{

View File

@ -81,7 +81,8 @@ class RouteUI : public virtual AxisView
BindableToggleButton* mute_button;
BindableToggleButton* solo_button;
BindableToggleButton* rec_enable_button;
BindableToggleButton* rec_enable_button; /* audio tracks */
BindableToggleButton* show_sends_button; /* busses */
virtual std::string solo_button_name () const { return "SoloButton"; }
virtual std::string safe_solo_button_name () const { return "SafeSoloButton"; }
@ -89,6 +90,7 @@ class RouteUI : public virtual AxisView
Gtk::Menu* mute_menu;
Gtk::Menu* solo_menu;
Gtk::Menu* remote_control_menu;
Gtk::Menu* sends_menu;
XMLNode *xml_node;
void ensure_xml_node ();
@ -101,6 +103,13 @@ class RouteUI : public virtual AxisView
bool solo_release(GdkEventButton*);
bool rec_enable_press(GdkEventButton*);
bool rec_enable_release(GdkEventButton*);
bool show_sends_press(GdkEventButton*);
bool show_sends_release(GdkEventButton*);
void build_sends_menu ();
void set_sends_gain_from_track ();
void set_sends_gain_to_zero ();
void set_sends_gain_to_unity ();
void solo_changed(void*);
void solo_changed_so_update_mute ();

View File

@ -141,6 +141,8 @@ class IO : public SessionObject, public AutomatableControls, public Latent
int disconnect_inputs (void *src);
int disconnect_outputs (void *src);
bool connected_to (boost::shared_ptr<const IO>) const;
nframes_t signal_latency() const { return _own_latency; }
nframes_t output_latency() const;
nframes_t input_latency() const;

View File

@ -91,7 +91,6 @@ class Route : public IO
/* these are the core of the API of a Route. see the protected sections as well */
virtual int roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
int declick, bool can_record, bool rec_monitors_input);
@ -181,6 +180,8 @@ class Route : public IO
boost::shared_ptr<Delivery> control_outs() const { return _control_outs; }
boost::shared_ptr<Delivery> main_outs() const { return _main_outs; }
boost::shared_ptr<IO> send_io_for (boost::shared_ptr<const IO> target) const;
/** A record of the stream configuration at some point in the processor list.
* Used to return where and why an processor list configuration request failed.
@ -248,7 +249,7 @@ class Route : public IO
int listen_via (boost::shared_ptr<IO>, const std::string& name);
void drop_listen (boost::shared_ptr<IO>);
bool feeds (boost::shared_ptr<Route>);
bool feeds (boost::shared_ptr<IO>);
std::set<boost::shared_ptr<Route> > fed_by;
struct ToggleControllable : public PBD::Controllable {
@ -314,7 +315,7 @@ class Route : public IO
nframes_t _initial_delay;
nframes_t _roll_delay;
ProcessorList _processors;
Glib::RWLock _processor_lock;
mutable Glib::RWLock _processor_lock;
boost::shared_ptr<Delivery> _main_outs;
boost::shared_ptr<Delivery> _control_outs; // XXX to be removed/generalized by listen points
RouteGroup *_edit_group;

View File

@ -1596,25 +1596,28 @@ IO::get_port_counts (const XMLNode& node, ChanCount& in, ChanCount& out,
int
IO::create_ports (const XMLNode& node)
{
ChanCount in;
ChanCount out;
boost::shared_ptr<Bundle> ic;
boost::shared_ptr<Bundle> oc;
if (pending_state_node) {
no_panner_reset = true;
get_port_counts (*pending_state_node, in, out, ic, oc);
if (ensure_io (in, out, true, this)) {
error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
return -1;
ChanCount in;
ChanCount out;
boost::shared_ptr<Bundle> ic;
boost::shared_ptr<Bundle> oc;
no_panner_reset = true;
get_port_counts (*pending_state_node, in, out, ic, oc);
if (ensure_io (in, out, true, this)) {
error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
return -1;
}
/* XXX use ic and oc if relevant */
no_panner_reset = false;
}
/* XXX use ic and oc if relevant */
no_panner_reset = false;
set_deferred_state ();
return 0;
}
@ -2663,3 +2666,22 @@ IO::increment_output_offset (nframes_t n)
_output_offset += n;
}
bool
IO::connected_to (boost::shared_ptr<const IO> other) const
{
uint32_t i, j;
uint32_t no = n_outputs().n_total();
uint32_t ni = other->n_inputs ().n_total();
for (i = 0; i < no; ++i) {
for (j = 0; j < ni; ++j) {
if (output(i)->connected_to (other->input(j)->name())) {
return true;
}
}
}
return false;
}

View File

@ -2112,39 +2112,21 @@ Route::set_comment (string cmt, void *src)
}
bool
Route::feeds (boost::shared_ptr<Route> other)
Route::feeds (boost::shared_ptr<IO> other)
{
uint32_t i, j;
IO& self = *this;
uint32_t no = self.n_outputs().n_total();
uint32_t ni = other->n_inputs ().n_total();
for (i = 0; i < no; ++i) {
for (j = 0; j < ni; ++j) {
if (self.output(i)->connected_to (other->input(j)->name())) {
return true;
}
}
if (connected_to (other)) {
return true;
}
/* check IOProcessors which may also interconnect Routes */
for (ProcessorList::iterator r = _processors.begin(); r != _processors.end(); r++) {
boost::shared_ptr<IOProcessor> proc = boost::dynamic_pointer_cast<IOProcessor>(*r);
if (!proc) {
continue;
}
no = proc->io()->n_outputs().n_total();
for (i = 0; i < no; ++i) {
for (j = 0; j < ni; ++j) {
if (proc->io()->output(i)->connected_to (other->input (j)->name())) {
return true;
}
boost::shared_ptr<IOProcessor> proc;
if ((proc = boost::dynamic_pointer_cast<IOProcessor>(*r)) != 0) {
if (proc->io()->connected_to (other)) {
return true;
}
}
}
@ -2700,3 +2682,21 @@ Route::set_name (const string& str)
return ret;
}
boost::shared_ptr<IO>
Route::send_io_for (boost::shared_ptr<const IO> target) const
{
Glib::RWLock::ReaderLock lm (_processor_lock);
for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
boost::shared_ptr<Send> send;
if ((send = boost::dynamic_pointer_cast<Send>(*i)) != 0) {
if (send->io()->connected_to (target)) {
return send->io();
}
}
}
return boost::shared_ptr<IO>();
}