/*
- Copyright (C) 2000-2006 Paul Davis
-
- 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ * Copyright (C) 2005-2006 Nick Mainsbridge <mainsbridge@gmail.com>
+ * Copyright (C) 2005-2006 Taybin Rutkin <taybin@taybin.com>
+ * Copyright (C) 2005-2007 Doug McLain <doug@nostar.net>
+ * Copyright (C) 2005-2017 Paul Davis <paul@linuxaudiosystems.com>
+ * Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
+ * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
+ * Copyright (C) 2008 Hans Baier <hansfbaier@googlemail.com>
+ * Copyright (C) 2009-2010 Sakari Bergen <sakari.bergen@beatwaves.net>
+ * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
+ * Copyright (C) 2013-2016 John Emmas <john@creativepost.co.uk>
+ * Copyright (C) 2014-2018 Ben Loftis <ben@harrisonconsoles.com>
+ * Copyright (C) 2015-2016 Tim Mayberry <mojofunk@gmail.com>
+ * Copyright (C) 2016-2017 Julien "_FrnchFrgg_" RIVAUD <frnchfrgg@free.fr>
+ * Copyright (C) 2018 Len Ovens <len@ovenwerks.net>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
#include <cmath>
#include <list>
#include "pbd/enumwriter.h"
#include "pbd/replace_all.h"
#include "pbd/stacktrace.h"
+#include "pbd/unwind.h"
#include "ardour/amp.h"
#include "ardour/audio_track.h"
#include "widgets/tooltips.h"
#include "ardour_window.h"
+#include "context_menu_helper.h"
#include "enums_convert.h"
#include "mixer_strip.h"
#include "mixer_ui.h"
, _comment_button (_("Comments"))
, trim_control (ArdourKnob::default_elements, ArdourKnob::Flags (ArdourKnob::Detent | ArdourKnob::ArcToZero))
, _visibility (X_("mixer-element-visibility"))
+ , _suspend_menu_callbacks (false)
, control_slave_ui (sess)
{
init ();
, _comment_button (_("Comments"))
, trim_control (ArdourKnob::default_elements, ArdourKnob::Flags (ArdourKnob::Detent | ArdourKnob::ArcToZero))
, _visibility (X_("mixer-element-visibility"))
+ , _suspend_menu_callbacks (false)
, control_slave_ui (sess)
{
init ();
hide_button.set_tweaks (ArdourButton::Square);
set_tooltip (width_button, t);
- hide_button.set_icon (ArdourIcon::CloseCross);
+ hide_button.set_icon (ArdourIcon::HideEye);
hide_button.set_tweaks (ArdourButton::Square);
set_tooltip (&hide_button, _("Hide this mixer strip"));
solo_iso_table.set_homogeneous (true);
solo_iso_table.set_spacings (2);
- if (!ARDOUR::Profile->get_trx()) {
- solo_iso_table.attach (*solo_isolated_led, 0, 1, 0, 1);
- solo_iso_table.attach (*solo_safe_led, 1, 2, 0, 1);
- }
+ solo_iso_table.attach (*solo_isolated_led, 0, 1, 0, 1);
+ solo_iso_table.attach (*solo_safe_led, 1, 2, 0, 1);
solo_iso_table.show ();
rec_mon_table.set_homogeneous (true);
rec_mon_table.resize (1, 3);
rec_mon_table.attach (*monitor_input_button, 1, 2, 0, 1);
rec_mon_table.attach (*monitor_disk_button, 2, 3, 0, 1);
- } else if (!ARDOUR::Profile->get_trx()) {
- rec_mon_table.attach (*monitor_input_button, 1, 2, 0, 1);
- rec_mon_table.attach (*monitor_disk_button, 1, 2, 1, 2);
}
rec_mon_table.show ();
number_label.set_tweaks (ArdourButton::OccasionalText);
global_vpacker.set_spacing (2);
- if (!ARDOUR::Profile->get_trx()) {
- global_vpacker.pack_start (width_hide_box, Gtk::PACK_SHRINK);
- global_vpacker.pack_start (name_button, Gtk::PACK_SHRINK);
- global_vpacker.pack_start (input_button_box, Gtk::PACK_SHRINK);
- global_vpacker.pack_start (_invert_button_box, Gtk::PACK_SHRINK);
- global_vpacker.pack_start (processor_box, true, true);
- }
+ global_vpacker.pack_start (width_hide_box, Gtk::PACK_SHRINK);
+ global_vpacker.pack_start (name_button, Gtk::PACK_SHRINK);
+ global_vpacker.pack_start (input_button_box, Gtk::PACK_SHRINK);
+ global_vpacker.pack_start (_invert_button_box, Gtk::PACK_SHRINK);
+ global_vpacker.pack_start (processor_box, true, true);
global_vpacker.pack_start (panners, Gtk::PACK_SHRINK);
global_vpacker.pack_start (rec_mon_table, Gtk::PACK_SHRINK);
global_vpacker.pack_start (solo_iso_table, Gtk::PACK_SHRINK);
global_vpacker.pack_start (gpm, Gtk::PACK_SHRINK);
global_vpacker.pack_start (control_slave_ui, Gtk::PACK_SHRINK);
global_vpacker.pack_start (bottom_button_table, Gtk::PACK_SHRINK);
- if (!ARDOUR::Profile->get_trx()) {
- global_vpacker.pack_start (output_button, Gtk::PACK_SHRINK);
- global_vpacker.pack_start (_comment_button, Gtk::PACK_SHRINK);
- } else {
- global_vpacker.pack_start (name_button, Gtk::PACK_SHRINK);
- }
+ global_vpacker.pack_start (output_button, Gtk::PACK_SHRINK);
+ global_vpacker.pack_start (_comment_button, Gtk::PACK_SHRINK);
#ifndef MIXBUS
//add a spacer underneath the master bus;
_packed = false;
_embedded = false;
- _session->engine().Stopped.connect (*this, invalidator (*this), boost::bind (&MixerStrip::engine_stopped, this), gui_context());
- _session->engine().Running.connect (*this, invalidator (*this), boost::bind (&MixerStrip::engine_running, this), gui_context());
-
input_button.signal_button_press_event().connect (sigc::mem_fun(*this, &MixerStrip::input_press), false);
input_button.signal_button_release_event().connect (sigc::mem_fun(*this, &MixerStrip::input_release), false);
input_button.signal_size_allocate().connect (sigc::mem_fun (*this, &MixerStrip::input_button_resized));
{
assert (_route && _session);
if (route()->trim() && route()->trim()->active() && route()->n_inputs().n_audio() > 0) {
- route()->trim()->gain_control ()->start_touch (_session->transport_frame());
+ route()->trim()->gain_control ()->start_touch (_session->transport_sample());
}
}
{
assert (_route && _session);
if (route()->trim() && route()->trim()->active() && route()->n_inputs().n_audio() > 0) {
- route()->trim()->gain_control ()->stop_touch (_session->transport_frame());
+ route()->trim()->gain_control ()->stop_touch (_session->transport_sample());
}
}
gpm.gain_display.get_parent()->remove (gpm.gain_display);
}
- gpm.set_type (rt->meter_type());
-
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);
solo_iso_table.set_sensitive(false);
control_slave_ui.set_sensitive(false);
if (monitor_section_button == 0) {
- Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMonitorSection");
+ Glib::RefPtr<Action> act = ActionManager::get_action ("Mixer", "ToggleMonitorSection");
_session->MonitorChanged.connect (route_connections, invalidator (*this), boost::bind (&MixerStrip::monitor_changed, this), gui_context());
+ _session->MonitorBusAddedOrRemoved.connect (route_connections, invalidator (*this), boost::bind (&MixerStrip::monitor_section_added_or_removed, this), gui_context());
monitor_section_button = manage (new ArdourButton);
monitor_changed ();
mute_solo_table.attach (*monitor_section_button, 1, 2, 0, 1);
monitor_section_button->show();
monitor_section_button->unset_flags (Gtk::CAN_FOCUS);
+ monitor_section_added_or_removed ();
}
- parameter_changed ("use-monitor-bus");
} else {
bottom_button_table.attach (group_button, 1, 2, 0, 1);
mute_solo_table.attach (*mute_button, 0, 1, 0, 1);
control_slave_ui.set_sensitive(true);
}
- if (_mixer_owned && route()->is_master() ) {
- spacer.show();
- } else {
- spacer.hide();
- }
+ hide_master_spacer (false);
if (is_track()) {
monitor_input_button->show ();
if (ARDOUR::Profile->get_mixbus()) {
rec_mon_table.attach (*monitor_input_button, 1, 2, 0, 1);
rec_mon_table.attach (*monitor_disk_button, 2, 3, 0, 1);
- } else if (ARDOUR::Profile->get_trx()) {
- rec_mon_table.attach (*monitor_input_button, 1, 2, 0, 2);
} else {
rec_mon_table.attach (*monitor_input_button, 1, 2, 0, 1);
rec_mon_table.attach (*monitor_disk_button, 1, 2, 1, 2);
_route->panner_shell()->Changed.connect (route_connections, invalidator (*this), boost::bind (&MixerStrip::connect_to_pan, this), gui_context());
}
- if (is_audio_track()) {
- audio_track()->DiskstreamChanged.connect (route_connections, invalidator (*this), boost::bind (&MixerStrip::diskstream_changed, this), gui_context());
- }
-
_route->comment_changed.connect (route_connections, invalidator (*this), boost::bind (&MixerStrip::setup_comment_button, this), gui_context());
set_stuff_from_route ();
const float scale = std::max(1.f, UIConfiguration::instance().get_ui_scale());
+ gpm.gain_automation_state_button.set_text (GainMeterBase::short_astate_string (gain_automation->automation_state()));
+
+ if (_route->panner()) {
+ ((Gtk::Label*)panners.pan_automation_state_button.get_child())->set_text (GainMeterBase::short_astate_string (_route->panner()->automation_state()));
+ }
+
switch (w) {
case Wide:
show_sends_button->set_text (_("Aux"));
}
- gpm.gain_automation_state_button.set_text (
- gpm.astate_string(gain_automation->automation_state()));
-
- if (_route->panner()) {
- ((Gtk::Label*)panners.pan_automation_state_button.get_child())->set_text (
- panners.astate_string(_route->panner()->automation_state()));
- }
-
{
// panners expect an even number of horiz. pixels
int width = rintf (max (110.f * scale, gpm.get_gm_width() + 10.f * scale)) + 1;
show_sends_button->set_text (_("Snd"));
}
- gpm.gain_automation_state_button.set_text (
- gpm.short_astate_string(gain_automation->automation_state()));
gain_meter().setup_meters (); // recalc meter width
- if (_route->panner()) {
- ((Gtk::Label*)panners.pan_automation_state_button.get_child())->set_text (
- panners.short_astate_string(_route->panner()->automation_state()));
- }
-
{
// panners expect an even number of horiz. pixels
int width = rintf (max (60.f * scale, gpm.get_gm_width() + 10.f * scale)) + 1;
MixerStrip::output_press (GdkEventButton *ev)
{
using namespace Menu_Helpers;
- if (!_session->engine().connected()) {
- MessageDialog msg (_("Not connected to audio engine - no I/O changes are possible"));
- msg.run ();
+ if (!ARDOUR_UI_UTILS::engine_is_running ()) {
return true;
}
}
/* then other routes inputs */
- boost::shared_ptr<ARDOUR::RouteList> routes = _session->get_routes ();
- RouteList copy = *routes;
+ RouteList copy = _session->get_routelist ();
copy.sort (RouteCompareByName ());
for (ARDOUR::RouteList::const_iterator i = copy.begin(); i != copy.end(); ++i) {
maybe_add_bundle_to_output_menu ((*i)->input()->bundle(), current, intended_type);
citems.pop_back ();
}
- if (!ARDOUR::Profile->get_mixbus()) {
- citems.push_back (SeparatorElem());
+ citems.push_back (SeparatorElem());
+ if (!ARDOUR::Profile->get_mixbus()) {
+ bool need_separator = false;
for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) {
+ if (!_route->output()->can_add_port (*i)) {
+ continue;
+ }
+ need_separator = true;
citems.push_back (
MenuElem (
string_compose (_("Add %1 port"), (*i).to_i18n_string()),
)
);
}
+ if (need_separator) {
+ citems.push_back (SeparatorElem());
+ }
}
- citems.push_back (SeparatorElem());
citems.push_back (MenuElem (_("Routing Grid"), sigc::mem_fun (*(static_cast<RouteUI*>(this)), &RouteUI::edit_output_configuration)));
Gtkmm2ext::anchored_menu_popup(&output_menu, &output_button, "",
input_menu.set_name ("ArdourContextMenu");
citems.clear();
- if (!_session->engine().connected()) {
- MessageDialog msg (_("Not connected to audio engine - no I/O changes are possible"));
- msg.run ();
+ if (!ARDOUR_UI_UTILS::engine_is_running ()) {
return true;
}
}
citems.push_back (SeparatorElem());
+
+ bool need_separator = false;
for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) {
+ if (!_route->input()->can_add_port (*i)) {
+ continue;
+ }
+ need_separator = true;
citems.push_back (
MenuElem (
string_compose (_("Add %1 port"), (*i).to_i18n_string()),
)
);
}
+ if (need_separator) {
+ citems.push_back (SeparatorElem());
+ }
- citems.push_back (SeparatorElem());
citems.push_back (MenuElem (_("Routing Grid"), sigc::mem_fun (*(static_cast<RouteUI*>(this)), &RouteUI::edit_input_configuration)));
Gtkmm2ext::anchored_menu_popup(&input_menu, &input_button, "",
return;
}
- ARDOUR::BundleList current = _route->input()->bundles_connected ();
-
- if (std::find (current.begin(), current.end(), c) == current.end()) {
- _route->input()->connect_ports_to_bundle (c, true, this);
- } else {
- _route->input()->disconnect_ports_from_bundle (c, this);
- }
+ _route->input()->connect_ports_to_bundle (c, true, this);
}
void
return;
}
- ARDOUR::BundleList current = _route->output()->bundles_connected ();
-
- if (std::find (current.begin(), current.end(), c) == current.end()) {
- _route->output()->connect_ports_to_bundle (c, true, this);
- } else {
- _route->output()->disconnect_ports_from_bundle (c, this);
- }
+ _route->output()->connect_ports_to_bundle (c, true, true, this);
}
void
/*
* Output port labelling
- * =====================
*
* Case 1: Each output has one connection, all connections are to system:playback_%i
* out 1 -> system:playback_1
* Default case (unusual routing):
* Display as: *number of connections*
*
+ *
* Tooltips
- * ========
+ *
* .-----------------------------------------------.
* | Mixdown |
* | out 1 -> ardour:master/in 1, jamin:input/in 1 |
void
MixerStrip::update_io_button (bool for_input)
{
- vector<string> port_connections;
-
- uint32_t total_connection_count = 0;
- uint32_t io_connection_count = 0;
- uint32_t ardour_connection_count = 0;
- uint32_t system_connection_count = 0;
- uint32_t other_connection_count = 0;
- uint32_t typed_connection_count = 0;
-
+ ostringstream tooltip;
ostringstream label;
-
bool have_label = false;
- bool each_io_has_one_connection = true;
-
- string connection_name;
- string ardour_track_name;
- string other_connection_type;
- string system_ports;
- string system_port;
- ostringstream tooltip;
- char * tooltip_cstr;
+ uint32_t total_connection_count = 0;
+ uint32_t typed_connection_count = 0;
+ bool each_typed_port_has_one_connection = true;
DataType dt = guess_main_type(for_input);
+ boost::shared_ptr<IO> io = for_input ? _route->input() : _route->output();
- if ( dt == DataType::MIDI ) {
- tooltip << _("MIDI ");
- }
-
+ /* Fill in the tooltip. Also count:
+ * - The total number of connections.
+ * - The number of main-typed connections.
+ * - Whether each main-typed port has exactly one connection. */
if (for_input) {
- tooltip << string_compose (_("<b>INPUT</b> to %1"), Gtkmm2ext::markup_escape_text (_route->name()));
+ tooltip << string_compose (_("<b>INPUT</b> to %1"),
+ Gtkmm2ext::markup_escape_text (_route->name()));
} else {
- tooltip << string_compose (_("<b>OUTPUT</b> from %1"), Gtkmm2ext::markup_escape_text (_route->name()));
+ tooltip << string_compose (_("<b>OUTPUT</b> from %1"),
+ Gtkmm2ext::markup_escape_text (_route->name()));
}
- boost::shared_ptr<IO> io = for_input ? _route->input() : _route->output();
- for (PortSet::iterator port = io->ports().begin(); port != io->ports().end(); ++port) {
- port_connections.clear ();
+ string arrow = Gtkmm2ext::markup_escape_text(for_input ? " <- " : " -> ");
+ vector<string> port_connections;
+ for (PortSet::iterator port = io->ports().begin();
+ port != io->ports().end();
+ ++port) {
+ port_connections.clear();
port->get_connections(port_connections);
- //ignore any port connections that don't match our DataType
- if (port->type() != dt) {
- if (!port_connections.empty()) {
- ++typed_connection_count;
- }
- continue;
- }
-
- io_connection_count = 0;
-
- if (!port_connections.empty()) {
- for (vector<string>::iterator i = port_connections.begin(); i != port_connections.end(); ++i) {
- string pn = "";
- string& connection_name (*i);
-
- if (connection_name.find("system:") == 0) {
- pn = AudioEngine::instance()->get_pretty_name_by_name (connection_name);
- }
-
- if (io_connection_count == 0) {
- tooltip << endl << Gtkmm2ext::markup_escape_text (port->name().substr(port->name().find("/") + 1))
- << " -> "
- << Gtkmm2ext::markup_escape_text ( pn.empty() ? connection_name : pn );
- } else {
- tooltip << ", "
- << Gtkmm2ext::markup_escape_text ( pn.empty() ? connection_name : pn );
- }
-
- if (connection_name.find(RouteUI::program_port_prefix) == 0) {
- if (ardour_track_name.empty()) {
- // "ardour:Master/in 1" -> "ardour:Master/"
- string::size_type slash = connection_name.find("/");
- if (slash != string::npos) {
- ardour_track_name = connection_name.substr(0, slash + 1);
- }
- }
-
- if (connection_name.find(ardour_track_name) == 0) {
- ++ardour_connection_count;
- }
- } else if (!pn.empty()) {
- if (system_ports.empty()) {
- system_ports += pn;
- } else {
- system_ports += "/" + pn;
- }
- if (connection_name.find("system:") == 0) {
- ++system_connection_count;
- }
- } else if (connection_name.find("system:midi_") == 0) {
- if (for_input) {
- // "system:midi_capture_123" -> "123"
- system_port = "M " + connection_name.substr(20);
- } else {
- // "system:midi_playback_123" -> "123"
- system_port = "M " + connection_name.substr(21);
- }
-
- if (system_ports.empty()) {
- system_ports += system_port;
- } else {
- system_ports += "/" + system_port;
- }
-
- ++system_connection_count;
+ uint32_t port_connection_count = 0;
- } else if (connection_name.find("system:") == 0) {
- if (for_input) {
- // "system:capture_123" -> "123"
- system_port = connection_name.substr(15);
- } else {
- // "system:playback_123" -> "123"
- system_port = connection_name.substr(16);
- }
-
- if (system_ports.empty()) {
- system_ports += system_port;
- } else {
- system_ports += "/" + system_port;
- }
-
- ++system_connection_count;
- } else {
- if (other_connection_type.empty()) {
- // "jamin:in 1" -> "jamin:"
- other_connection_type = connection_name.substr(0, connection_name.find(":") + 1);
- }
+ for (vector<string>::iterator i = port_connections.begin();
+ i != port_connections.end();
+ ++i) {
+ ++port_connection_count;
- if (connection_name.find(other_connection_type) == 0) {
- ++other_connection_count;
- }
- }
-
- ++total_connection_count;
- ++io_connection_count;
+ if (port_connection_count == 1) {
+ tooltip << endl << Gtkmm2ext::markup_escape_text (
+ port->name().substr(port->name().find("/") + 1));
+ tooltip << arrow;
+ } else {
+ tooltip << ", ";
}
+
+ tooltip << Gtkmm2ext::markup_escape_text(*i);
}
- if (io_connection_count != 1) {
- each_io_has_one_connection = false;
+ total_connection_count += port_connection_count;
+ if (port->type() == dt) {
+ typed_connection_count += port_connection_count;
+ each_typed_port_has_one_connection &= (port_connection_count == 1);
}
+
}
if (total_connection_count == 0) {
tooltip << endl << _("Disconnected");
}
- tooltip_cstr = new char[tooltip.str().size() + 1];
- strcpy(tooltip_cstr, tooltip.str().c_str());
-
- if (for_input) {
- set_tooltip (&input_button, tooltip_cstr);
- } else {
- set_tooltip (&output_button, tooltip_cstr);
+ if (typed_connection_count == 0) {
+ label << "-";
+ have_label = true;
}
- delete [] tooltip_cstr;
+ /* Are all main-typed channels connected to the same route ? */
+ if (!have_label) {
+ boost::shared_ptr<ARDOUR::RouteList> routes = _session->get_routes ();
+ for (ARDOUR::RouteList::const_iterator route = routes->begin();
+ route != routes->end();
+ ++route) {
+ boost::shared_ptr<IO> dest_io =
+ for_input ? (*route)->output() : (*route)->input();
+ if (io->bundle()->connected_to(dest_io->bundle(),
+ _session->engine(),
+ dt, true)) {
+ label << Gtkmm2ext::markup_escape_text ((*route)->name());
+ have_label = true;
+ break;
+ }
+ }
+ }
- if (each_io_has_one_connection) {
- if (total_connection_count == ardour_connection_count) {
- // all connections are to the same track in ardour
- // "ardour:Master/" -> "Master"
- string::size_type slash = ardour_track_name.find("/");
- if (slash != string::npos) {
- const size_t ppps = RouteUI::program_port_prefix.size (); // "ardour:"
- label << ardour_track_name.substr (ppps, slash - ppps);
+ /* Are all main-typed channels connected to the same (user) bundle ? */
+ if (!have_label) {
+ boost::shared_ptr<ARDOUR::BundleList> bundles = _session->bundles ();
+ for (ARDOUR::BundleList::iterator bundle = bundles->begin();
+ bundle != bundles->end();
+ ++bundle) {
+ if (boost::dynamic_pointer_cast<UserBundle> (*bundle) == 0)
+ continue;
+ if (io->bundle()->connected_to(*bundle, _session->engine(),
+ dt, true)) {
+ label << Gtkmm2ext::markup_escape_text ((*bundle)->name());
have_label = true;
+ break;
}
}
- else if (total_connection_count == system_connection_count) {
- // all connections are to system ports
- label << system_ports;
- have_label = true;
+ }
+
+ /* Is each main-typed channel only connected to a physical output ? */
+ if (!have_label && each_typed_port_has_one_connection) {
+ ostringstream temp_label;
+ vector<string> phys;
+ string playorcapture;
+ if (for_input) {
+ _session->engine().get_physical_inputs(dt, phys);
+ playorcapture = "capture_";
+ } else {
+ _session->engine().get_physical_outputs(dt, phys);
+ playorcapture = "playback_";
}
- else if (total_connection_count == other_connection_count) {
- // all connections are to the same external program eg jamin
- // "jamin:" -> "jamin"
- label << other_connection_type.substr(0, other_connection_type.size() - 1);
+ for (PortSet::iterator port = io->ports().begin(dt);
+ port != io->ports().end(dt);
+ ++port) {
+ string pn = "";
+ for (vector<string>::iterator s = phys.begin();
+ s != phys.end();
+ ++s) {
+ if (!port->connected_to(*s))
+ continue;
+ pn = AudioEngine::instance()->get_pretty_name_by_name(*s);
+ if (pn.empty()) {
+ string::size_type start = (*s).find(playorcapture);
+ if (start != string::npos) {
+ pn = (*s).substr(start + playorcapture.size());
+ }
+ }
+ break;
+ }
+ if (pn.empty()) {
+ temp_label.str(""); /* erase the failed attempt */
+ break;
+ }
+ if (port != io->ports().begin(dt))
+ temp_label << "/";
+ temp_label << pn;
+ }
+
+ if (!temp_label.str().empty()) {
+ label << temp_label.str();
have_label = true;
}
}
- if (!have_label) {
- if (total_connection_count == 0) {
- // Disconnected
- label << "-";
- } else {
- // Odd configuration
- label << "*" << total_connection_count << "*";
+ /* Is each main-typed channel connected to a single and different port with
+ * the same client name (e.g. another JACK client) ? */
+ if (!have_label && each_typed_port_has_one_connection) {
+ string maybe_client = "";
+ vector<string> connections;
+ for (PortSet::iterator port = io->ports().begin(dt);
+ port != io->ports().end(dt);
+ ++port) {
+ port_connections.clear();
+ port->get_connections(port_connections);
+ string connection = port_connections.front();
+
+ vector<string>::iterator i = connections.begin();
+ while (i != connections.end() && *i != connection) {
+ ++i;
+ }
+ if (i != connections.end())
+ break; /* duplicate connection */
+ connections.push_back(connection);
+
+ connection = connection.substr(0, connection.find(":"));
+ if (maybe_client.empty())
+ maybe_client = connection;
+ if (maybe_client != connection)
+ break;
}
- if (typed_connection_count > 0) {
- label << "\u2295"; // circled plus
+ if (connections.size() == io->n_ports().n(dt)) {
+ label << maybe_client;
+ have_label = true;
}
}
+ /* Odd configuration */
+ if (!have_label) {
+ label << "*" << total_connection_count << "*";
+ }
+
+ if (total_connection_count > typed_connection_count) {
+ label << "\u2295"; /* circled plus */
+ }
+
+ /* Actually set the properties of the button */
+ char * cstr = new char[tooltip.str().size() + 1];
+ strcpy(cstr, tooltip.str().c_str());
+
if (for_input) {
input_button.set_text (label.str());
+ set_tooltip (&input_button, cstr);
} else {
output_button.set_text (label.str());
+ set_tooltip (&output_button, cstr);
}
+
+ delete [] cstr;
}
void
i->signal_activate().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*_route, &Route::set_strict_io), !_route->strict_io())));
}
+ if (is_track()) {
+ items.push_back (SeparatorElem());
+
+ Gtk::Menu* dio_menu = new Menu;
+ MenuList& dio_items = dio_menu->items();
+ dio_items.push_back (MenuElem (_("Record Pre-Fader"), sigc::bind (sigc::mem_fun (*this, &RouteUI::set_disk_io_point), DiskIOPreFader)));
+ dio_items.push_back (MenuElem (_("Record Post-Fader"), sigc::bind (sigc::mem_fun (*this, &RouteUI::set_disk_io_point), DiskIOPostFader)));
+ dio_items.push_back (MenuElem (_("Custom Record+Playback Positions"), sigc::bind (sigc::mem_fun (*this, &RouteUI::set_disk_io_point), DiskIOCustom)));
+
+ items.push_back (MenuElem (_("Disk I/O..."), *dio_menu));
+ }
+
_plugin_insert_cnt = 0;
_route->foreach_processor (sigc::mem_fun (*this, &MixerStrip::help_count_plugins));
if (_plugin_insert_cnt > 0) {
items.push_back (MenuElem (_("Pin Connections..."), sigc::mem_fun (*this, &RouteUI::manage_pins)));
}
+ if (boost::dynamic_pointer_cast<MidiTrack>(_route) || _route->the_instrument ()) {
+ items.push_back (MenuElem (_("Patch Selector..."),
+ sigc::mem_fun(*this, &RouteUI::select_midi_patch)));
+ }
+
if (_route->the_instrument () && _route->the_instrument ()->output_streams().n_audio() > 2) {
// TODO ..->n_audio() > 1 && separate_output_groups) hard to check here every time.
items.push_back (MenuElem (_("Fan out to Busses"), sigc::bind (sigc::mem_fun (*this, &RouteUI::fan_out), true, true)));
items.push_back (MenuElem (_("Fan out to Tracks"), sigc::bind (sigc::mem_fun (*this, &RouteUI::fan_out), false, true)));
}
- items.push_back (SeparatorElem());
- items.push_back (MenuElem (_("Adjust Latency..."), sigc::mem_fun (*this, &RouteUI::adjust_latency)));
-
items.push_back (SeparatorElem());
items.push_back (CheckMenuElem (_("Protect Against Denormals"), sigc::mem_fun (*this, &RouteUI::toggle_denormal_protection)));
denormal_menu_item = dynamic_cast<Gtk::CheckMenuItem *> (&items.back());
break;
}
- set_tooltip (name_button, _route->name());
+ set_tooltip (name_button, Gtkmm2ext::markup_escape_text(_route->name()));
if (_session->config.get_track_name_number()) {
const int64_t track_number = _route->track_number ();
}
-void
-MixerStrip::engine_stopped ()
-{
-}
-
-void
-MixerStrip::engine_running ()
-{
-}
-
string
MixerStrip::meter_point_string (MeterPoint mp)
{
}
}
+void
+MixerStrip::monitor_section_added_or_removed ()
+{
+ assert (monitor_section_button);
+ if (mute_button->get_parent()) {
+ mute_button->get_parent()->remove(*mute_button);
+ }
+ if (monitor_section_button->get_parent()) {
+ monitor_section_button->get_parent()->remove(*monitor_section_button);
+ }
+ if (_session && _session->monitor_out ()) {
+ mute_solo_table.attach (*mute_button, 0, 1, 0, 1);
+ mute_solo_table.attach (*monitor_section_button, 1, 2, 0, 1);
+ mute_button->show();
+ monitor_section_button->show();
+ } else {
+ mute_solo_table.attach (*mute_button, 0, 2, 0, 1);
+ mute_button->show();
+ }
+}
+
/** Called when the metering point has changed */
void
MixerStrip::meter_changed ()
monitor_input_button->set_sensitive (true);
monitor_disk_button->set_sensitive (true);
_comment_button.set_sensitive (true);
+ trim_control.set_sensitive (true);
+ if (midi_input_enable_button) {
+ midi_input_enable_button->set_sensitive (true);
+ }
+ control_slave_ui.set_sensitive (true);
RouteUI::check_rec_enable_sensitivity ();
set_button_names (); // update solo button visual state
}
set_current_delivery (send);
- send->meter()->set_type(_route->shared_peak_meter()->get_type());
+ send->meter()->set_meter_type (_route->meter_type ());
send->set_metering (true);
_current_delivery->DropReferences.connect (send_gone_connection, invalidator (*this), boost::bind (&MixerStrip::revert_to_default_display, this), gui_context());
monitor_input_button->set_sensitive (false);
monitor_disk_button->set_sensitive (false);
_comment_button.set_sensitive (false);
+ trim_control.set_sensitive (false);
+ if (midi_input_enable_button) {
+ midi_input_enable_button->set_sensitive (false);
+ }
+ control_slave_ui.set_sensitive (false);
if (boost::dynamic_pointer_cast<InternalSend>(send)) {
output_button.set_sensitive (false);
_visibility.set_state (UIConfiguration::instance().get_mixer_strip_visibility ());
} else if (p == "track-name-number") {
name_changed ();
- } else if (p == "use-monitor-bus") {
- if (monitor_section_button) {
- if (mute_button->get_parent()) {
- mute_button->get_parent()->remove(*mute_button);
- }
- if (monitor_section_button->get_parent()) {
- monitor_section_button->get_parent()->remove(*monitor_section_button);
- }
- if (Config->get_use_monitor_bus ()) {
- mute_solo_table.attach (*mute_button, 0, 1, 0, 1);
- mute_solo_table.attach (*monitor_section_button, 1, 2, 0, 1);
- mute_button->show();
- monitor_section_button->show();
- } else {
- mute_solo_table.attach (*mute_button, 0, 2, 0, 1);
- mute_button->show();
- }
- }
- } else if (p == "track-name-number") {
update_track_number_visibility();
}
}
{
using namespace Gtk::Menu_Helpers;
- Gtk::Menu* m = manage (new Menu);
+ Gtk::Menu* m = ARDOUR_UI_UTILS::shared_popup_menu ();
MenuList& items = m->items ();
RadioMenuItem::Group group;
- _suspend_menu_callbacks = true;
+ PBD::Unwinder<bool> uw (_suspend_menu_callbacks, true);
add_level_meter_item_point (items, group, _("Input"), MeterInput);
add_level_meter_item_point (items, group, _("Pre Fader"), MeterPreFader);
add_level_meter_item_point (items, group, _("Post Fader"), MeterPostFader);
if (gpm.meter_channels().n_audio() == 0) {
m->popup (ev->button, ev->time);
- _suspend_menu_callbacks = false;
return;
}
sigc::bind (SetMeterTypeMulti, _strip_type, _route->route_group(), cmt)));
m->popup (ev->button, ev->time);
- _suspend_menu_callbacks = false;
}
void
MixerStrip::set_meter_type (MeterType t)
{
if (_suspend_menu_callbacks) return;
- gpm.set_type (t);
+ _route->set_meter_type (t);
}
void
{
return RouteUI::mark_hidden (!yn);
}
+
+void
+MixerStrip::hide_master_spacer (bool yn)
+{
+ if (_mixer_owned && route()->is_master() && !yn) {
+ spacer.show();
+ } else {
+ spacer.hide();
+ }
+}