#include "ardour/audio_track.h"
#include "ardour/audioengine.h"
#include "ardour/internal_send.h"
+#include "ardour/io.h"
#include "ardour/meter.h"
#include "ardour/midi_track.h"
#include "ardour/pannable.h"
#include "tooltips.h"
#include "ui_config.h"
-#include "i18n.h"
+#include "pbd/i18n.h"
using namespace ARDOUR;
using namespace ARDOUR_UI_UTILS;
number_label.signal_button_press_event().connect (sigc::mem_fun(*this, &MixerStrip::number_button_button_press), false);
name_button.signal_button_press_event().connect (sigc::mem_fun(*this, &MixerStrip::name_button_button_press), false);
- name_button.signal_button_release_event().connect (sigc::mem_fun(*this, &MixerStrip::name_button_button_release), false);
group_button.signal_button_press_event().connect (sigc::mem_fun(*this, &MixerStrip::select_route_group), false);
return string();
}
+void
+MixerStrip::update_trim_control ()
+{
+ if (route()->trim() && route()->trim()->active() &&
+ route()->n_inputs().n_audio() > 0) {
+ trim_control.show ();
+ trim_control.set_controllable (route()->trim()->gain_control());
+ } else {
+ trim_control.hide ();
+ boost::shared_ptr<Controllable> none;
+ trim_control.set_controllable (none);
+ }
+}
+
void
MixerStrip::set_route (boost::shared_ptr<Route> rt)
{
monitor_disk_button->hide ();
}
- if (route()->trim() && route()->trim()->active()) {
- trim_control.show ();
- trim_control.set_controllable (route()->trim()->gain_control());
- } else {
- trim_control.hide ();
- boost::shared_ptr<Controllable> none;
- trim_control.set_controllable (none);
- }
+ update_trim_control();
if (is_midi_track()) {
if (midi_input_enable_button == 0) {
citems.push_back (SeparatorElem());
citems.push_back (MenuElem (_("Routing Grid"), sigc::mem_fun (*(static_cast<RouteUI*>(this)), &RouteUI::edit_output_configuration)));
- output_menu.popup (1, ev->time);
+ Gtkmm2ext::anchored_menu_popup(&output_menu, &output_button, "",
+ 1, ev->time);
+
break;
}
citems.push_back (SeparatorElem());
citems.push_back (MenuElem (_("Routing Grid"), sigc::mem_fun (*(static_cast<RouteUI*>(this)), &RouteUI::edit_input_configuration)));
- input_menu.popup (1, ev->time);
+ Gtkmm2ext::anchored_menu_popup(&input_menu, &input_button, "",
+ 1, ev->time);
break;
}
{
uint32_t io_count;
uint32_t io_index;
+ boost::shared_ptr<IO> io;
boost::shared_ptr<Port> port;
vector<string> port_connections;
ostringstream tooltip;
char * tooltip_cstr;
- //to avoid confusion, the button caption should only show connections that match the datatype of the track
+ /* To avoid confusion, the button caption only shows connections that match the expected datatype
+ *
+ * First of all, if the user made only connections to a given type, we should use that one since
+ * it is very probably what the user expects. If there are several connections types, then show
+ * audio ones as primary, which matches expectations for both audio tracks with midi control and
+ * synthesisers. This first heuristic can be expressed with these two rules:
+ * A) If there are connected audio ports, consider audio as primary type.
+ * B) Else, if there are connected midi ports, consider midi as primary type.
+ *
+ * If there are no connected ports, then we choose the primary type based on the type of existing
+ * but unconnected ports. Again:
+ * C) If there are audio ports, consider audio as primary type.
+ * D) Else, if there are midi ports, consider midi as primary type. */
+
DataType dt = DataType::AUDIO;
- if ( boost::dynamic_pointer_cast<MidiTrack>(route) != 0 ) {
- dt = DataType::MIDI;
- // avoid further confusion with Midi-tracks that have a synth.
- // Audio-ports may be connected, but button says "Disconnected"
+ bool match = false;
+
+ if (for_input) {
+ io = route->input();
+ } else {
+ io = route->output();
+ }
+
+ io_count = io->n_ports().n_total();
+ for (io_index = 0; io_index < io_count; ++io_index) {
+ port = io->nth (io_index);
+ if (port->connected()) {
+ match = true;
+ if (port->type() == DataType::AUDIO) {
+ /* Rule A) applies no matter the remaining ports */
+ dt = DataType::AUDIO;
+ break;
+ }
+ if (port->type() == DataType::MIDI) {
+ /* Rule B) is a good candidate... */
+ dt = DataType::MIDI;
+ /* ...but continue the loop to check remaining ports for rule A) */
+ }
+ }
+ }
+
+ if (!match) {
+ /* Neither rule A) nor rule B) matched */
+ if ( io->n_ports().n_audio() > 0 ) {
+ /* Rule C */
+ dt = DataType::AUDIO;
+ } else if ( io->n_ports().n_midi() > 0 ) {
+ /* Rule D */
+ dt = DataType::MIDI;
+ }
+ }
+
+ if ( dt == DataType::MIDI ) {
tooltip << _("MIDI ");
}
if (for_input) {
- io_count = route->n_inputs().n_total();
tooltip << string_compose (_("<b>INPUT</b> to %1"), Gtkmm2ext::markup_escape_text (route->name()));
} else {
- io_count = route->n_outputs().n_total();
tooltip << string_compose (_("<b>OUTPUT</b> from %1"), Gtkmm2ext::markup_escape_text (route->name()));
}
-
for (io_index = 0; io_index < io_count; ++io_index) {
- if (for_input) {
- port = route->input()->nth (io_index);
- } else {
- port = route->output()->nth (io_index);
- }
+ port = io->nth (io_index);
port_connections.clear ();
port->get_connections(port_connections);
MixerStrip::io_changed_proxy ()
{
Glib::signal_idle().connect_once (sigc::mem_fun (*this, &MixerStrip::update_panner_choices));
+ Glib::signal_idle().connect_once (sigc::mem_fun (*this, &MixerStrip::update_trim_control));
}
void
WeakRouteList r;
r.push_back (route ());
group_menu->build (r);
- group_menu->menu()->popup (1, ev->time);
+
+ RouteGroup *rg = _route->route_group();
+
+ Gtkmm2ext::anchored_menu_popup(group_menu->menu(), &group_button,
+ rg ? rg->name() : _("No Group"),
+ 1, ev->time);
}
return true;
if (!processor || !processor->display_to_user()) {
return;
}
- if (boost::dynamic_pointer_cast<PluginInsert> (processor)) {
+ boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (processor);
+#ifdef MIXBUS
+ if (pi && pi->is_channelstrip ()) {
+ return;
+ }
+#endif
+ if (pi) {
++_plugin_insert_cnt;
}
}
items.push_back (MenuElem (_("Pin Connections..."), sigc::mem_fun (*this, &RouteUI::manage_pins)));
}
+ 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)));
gboolean
MixerStrip::name_button_button_press (GdkEventButton* ev)
{
- if (ev->button == 3) {
+ if (ev->button == 1 || ev->button == 3) {
list_route_operations ();
/* do not allow rename if the track is record-enabled */
rename_menu_item->set_sensitive (!is_track() || !track()->rec_enable_control()->get_value());
- route_ops_menu->popup (1, ev->time);
+ if (ev->button == 1) {
+ Gtkmm2ext::anchored_menu_popup(route_ops_menu, &name_button, "",
+ 1, ev->time);
+ } else {
+ route_ops_menu->popup (3, ev->time);
+ }
return true;
}
return false;
}
-gboolean
-MixerStrip::name_button_button_release (GdkEventButton* ev)
-{
- if (ev->button == 1) {
- list_route_operations ();
-
- /* do not allow rename if the track is record-enabled */
- rename_menu_item->set_sensitive (!is_track() || !track()->rec_enable_control()->get_value());
- route_ops_menu->popup (1, ev->time);
- }
-
- return false;
-}
-
gboolean
MixerStrip::number_button_button_press (GdkEventButton* ev)
{
}
void
-MixerStrip::show_selected ()
+MixerStrip::set_selected (bool yn)
{
+ AxisView::set_selected (yn);
+
if (selected()) {
global_frame.set_shadow_type (Gtk::SHADOW_ETCHED_OUT);
global_frame.set_name ("MixerStripSelectedFrame");