/*
- 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));
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);
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, "",
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());
}
-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);
} else if (p == "track-name-number") {
name_changed ();
update_track_number_visibility();
- } 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();
- }
- }
}
}
{
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();
+ }
+}