X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fport_group.cc;h=f68a00dd8faaeef1351b97bd6a5f868afda88e64;hb=2dc3c8b3650266eba09cf7fe53c39c6728d4d5b6;hp=213c818b0bae05b0a25a0f356479bd1af401e29d;hpb=664e715a002450ac0f079411f6f051c122a4322a;p=ardour.git diff --git a/gtk2_ardour/port_group.cc b/gtk2_ardour/port_group.cc index 213c818b0b..f68a00dd8f 100644 --- a/gtk2_ardour/port_group.cc +++ b/gtk2_ardour/port_group.cc @@ -30,9 +30,12 @@ #include "ardour/io_processor.h" #include "ardour/midi_port.h" #include "ardour/midiport_manager.h" +#include "ardour/plugin_insert.h" +#include "ardour/port.h" +#include "ardour/profile.h" #include "ardour/session.h" +#include "ardour/sidechain.h" #include "ardour/user_bundle.h" -#include "ardour/port.h" #include "control_protocol/control_protocol.h" @@ -42,7 +45,7 @@ #include "time_axis_view.h" #include "public_editor.h" -#include "i18n.h" +#include "pbd/i18n.h" using namespace std; using namespace Gtk; @@ -315,7 +318,7 @@ struct RouteIOs { class RouteIOsComparator { public: bool operator() (RouteIOs const & a, RouteIOs const & b) { - return a.route->order_key () < b.route->order_key (); + return a.route->presentation_info ().order() < b.route->presentation_info().order(); } }; @@ -336,8 +339,9 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp boost::shared_ptr bus (new PortGroup (string_compose (_("%1 Busses"), PROGRAM_NAME))); boost::shared_ptr track (new PortGroup (string_compose (_("%1 Tracks"), PROGRAM_NAME))); + boost::shared_ptr sidechain (new PortGroup (string_compose (_("%1 Sidechains"), PROGRAM_NAME))); boost::shared_ptr system (new PortGroup (_("Hardware"))); - boost::shared_ptr ardour (new PortGroup (string_compose (_("%1 Misc"), PROGRAM_NAME))); + boost::shared_ptr program (new PortGroup (string_compose (_("%1 Misc"), PROGRAM_NAME))); boost::shared_ptr other (new PortGroup (_("Other"))); /* Find the IOs which have bundles for routes and their processors. We store @@ -350,11 +354,11 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp for (RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) { - /* we never show the monitor bus inputs */ + /* we never show the monitor bus inputs */ - if (inputs && (*i)->is_monitor()) { - continue; - } + if (inputs && (*i)->is_monitor()) { + continue; + } /* keep track of IOs that we have taken bundles from, so that we can avoid taking the same IO from both @@ -374,13 +378,10 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp /* Sort RouteIOs by the routes' editor order keys */ route_ios.sort (RouteIOsComparator ()); - /* Now put the bundles that belong to these sorted RouteIOs into the PortGroup. - Note that if the RouteIO's bundles are multi-type, we may make new Bundles - with only the ports of one type. - */ + /* Now put the bundles that belong to these sorted RouteIOs into the PortGroup. */ for (list::iterator i = route_ios.begin(); i != route_ios.end(); ++i) { - TimeAxisView* tv = PublicEditor::instance().axis_view_from_route (i->route); + TimeAxisView* tv = PublicEditor::instance().time_axis_view_from_stripable (i->route); /* Work out which group to put these IOs' bundles in */ boost::shared_ptr g; @@ -391,10 +392,33 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp } for (list >::iterator j = i->ios.begin(); j != i->ios.end(); ++j) { - if (tv) { - g->add_bundle ((*j)->bundle(), *j, tv->color ()); - } else { - g->add_bundle ((*j)->bundle(), *j); + /* Only add the bundle if there is at least one port + * with a type that's been asked for */ + if (type == DataType::NIL || (*j)->bundle()->nchannels().n(type) > 0) { + if (tv) { + g->add_bundle ((*j)->bundle(), *j, tv->color ()); + } else { + g->add_bundle ((*j)->bundle(), *j); + } + } + } + + /* When on input side, let's look for sidechains in the route's plugins + to display them right next to their route */ + for (uint32_t n = 0; inputs; ++n) { + boost::shared_ptr p = (i->route)->nth_plugin (n); + if (!p) { + break; + } + boost::shared_ptr sc = boost::static_pointer_cast (p)->sidechain (); + + if (sc) { + boost::shared_ptr io = sc->input(); + if (tv) { + sidechain->add_bundle (io->bundle(), io, tv->color ()); + } else { + sidechain->add_bundle (io->bundle(), io); + } } } } @@ -420,54 +444,62 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp } } - /* Ardour stuff */ + /* miscellany */ - if (!inputs) { - ardour->add_bundle (session->the_auditioner()->output()->bundle()); - ardour->add_bundle (session->click_io()->bundle()); - /* Note: the LTC ports do not have the usual ":audio_out 1" postfix, so - * ardour->add_bundle (session->ltc_output_io()->bundle()); - * won't work - */ - boost::shared_ptr ltc (new Bundle (_("LTC Out"), inputs)); - ltc->add_channel (_("LTC Out"), DataType::AUDIO, session->engine().make_port_name_non_relative (session->ltc_output_port()->name())); - ardour->add_bundle (ltc); - } else { - boost::shared_ptr ltc (new Bundle (_("LTC In"), inputs)); - ltc->add_channel (_("LTC In"), DataType::AUDIO, session->engine().make_port_name_non_relative (session->ltc_input_port()->name())); - ardour->add_bundle (ltc); + if (type == DataType::AUDIO || type == DataType::NIL) { + if (!inputs) { + program->add_bundle (session->the_auditioner()->output()->bundle()); + program->add_bundle (session->click_io()->bundle()); + /* Note: the LTC ports do not have the usual ":audio_out 1" postfix, so + * program->add_bundle (session->ltc_output_io()->bundle()); + * won't work + */ + boost::shared_ptr ltc (new Bundle (_("LTC Out"), inputs)); + ltc->add_channel (_("LTC Out"), DataType::AUDIO, session->engine().make_port_name_non_relative (session->ltc_output_port()->name())); + program->add_bundle (ltc); + } else { + // XXX TRANSPORTMASTERS + //boost::shared_ptr ltc (new Bundle (_("LTC In"), inputs)); + // ltc->add_channel (_("LTC In"), DataType::AUDIO, session->engine().make_port_name_non_relative (session->ltc_input_port()->name())); + // program->add_bundle (ltc); + } } - /* Ardour's surfaces */ + /* our control surfaces */ + + /* XXX assume for now that all control protocols with ports use + * MIDI. If anyone created a control protocol that used audio ports, + * this will break. + */ - ControlProtocolManager& m = ControlProtocolManager::instance (); - for (list::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) { - if ((*i)->protocol) { - list > b = (*i)->protocol->bundles (); - for (list >::iterator j = b.begin(); j != b.end(); ++j) { - if ((*j)->ports_are_inputs() == inputs) { - ardour->add_bundle (*j); + if ((type == DataType::MIDI || type == DataType::NIL)) { + ControlProtocolManager& m = ControlProtocolManager::instance (); + for (list::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) { + if ((*i)->protocol) { + list > b = (*i)->protocol->bundles (); + for (list >::iterator j = b.begin(); j != b.end(); ++j) { + if ((*j)->ports_are_inputs() == inputs) { + program->add_bundle (*j); + } } } } } - /* Ardour's sync ports */ + /* our sync ports */ if ((type == DataType::MIDI || type == DataType::NIL)) { boost::shared_ptr sync (new Bundle (_("Sync"), inputs)); AudioEngine* ae = AudioEngine::instance(); if (inputs) { - sync->add_channel ( - _("MTC in"), DataType::MIDI, ae->make_port_name_non_relative (session->mtc_input_port()->name()) - ); - sync->add_channel ( - _("MIDI control in"), DataType::MIDI, ae->make_port_name_non_relative (session->midi_input_port()->name()) - ); - sync->add_channel ( - _("MIDI clock in"), DataType::MIDI, ae->make_port_name_non_relative (session->midi_clock_input_port()->name()) - ); + // XXX TRANSPORTMASTER + // sync->add_channel ( + // _("MTC in"), DataType::MIDI, ae->make_port_name_non_relative (session->mtc_input_port()->name()) + // ); + // sync->add_channel ( + // _("MIDI clock in"), DataType::MIDI, ae->make_port_name_non_relative (session->midi_clock_input_port()->name()) + //); sync->add_channel ( _("MMC in"), DataType::MIDI, ae->make_port_name_non_relative (session->mmc_input_port()->name()) ); @@ -475,9 +507,6 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp sync->add_channel ( _("MTC out"), DataType::MIDI, ae->make_port_name_non_relative (session->mtc_output_port()->name()) ); - sync->add_channel ( - _("MIDI control out"), DataType::MIDI, ae->make_port_name_non_relative (session->midi_output_port()->name()) - ); sync->add_channel ( _("MIDI clock out"), DataType::MIDI, ae->make_port_name_non_relative (session->midi_clock_output_port()->name()) ); @@ -486,21 +515,33 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp ); } - ardour->add_bundle (sync); + program->add_bundle (sync); } /* Now find all other ports that we haven't thought of yet */ std::vector extra_system[DataType::num_types]; + std::vector extra_program[DataType::num_types]; std::vector extra_other[DataType::num_types]; - string lpn (PROGRAM_NAME); - boost::to_lower (lpn); - string lpnc = lpn; - lpnc += ':'; + string lpn (PROGRAM_NAME); + boost::to_lower (lpn); + string lpnc = lpn; + lpnc += ':'; vector ports; - if (AudioEngine::instance()->get_ports ("", type, inputs ? IsInput : IsOutput, ports) > 0) { + if (type == DataType::NIL) { + vector p1; + AudioEngine::instance()->get_ports ("", DataType::AUDIO, inputs ? IsInput : IsOutput, ports); + AudioEngine::instance()->get_ports ("", DataType::MIDI, inputs ? IsInput : IsOutput, p1); + for (vector::const_iterator s = p1.begin(); s != p1.end(); ++s) { + ports.push_back (*s); + } + } else { + AudioEngine::instance()->get_ports ("", type, inputs ? IsInput : IsOutput, ports); + } + + if (ports.size () > 0) { for (vector::const_iterator s = ports.begin(); s != ports.end(); ) { @@ -509,45 +550,74 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp if (!system->has_port(p) && !bus->has_port(p) && !track->has_port(p) && - !ardour->has_port(p) && + !sidechain->has_port(p) && + !program->has_port(p) && !other->has_port(p)) { - /* special hack: ignore MIDI ports labelled Midi-Through. these - are basically useless and mess things up for default - connections. - */ + /* special hack: ignore MIDI ports labelled Midi-Through. these + are basically useless and mess things up for default + connections. + */ + + if (p.find ("Midi-Through") != string::npos || p.find ("Midi Through") != string::npos) { + ++s; + continue; + } - if (p.find ("Midi-Through") != string::npos) { - ++s; - continue; - } + /* special hack: ignore our monitor inputs (which show up here because + we excluded them earlier. + */ - /* special hack: ignore our monitor inputs (which show up here because - we excluded them earlier. - */ + string lp = p; + string monitor = _("Monitor"); - string lp = p; - boost::to_lower (lp); + boost::to_lower (lp); + boost::to_lower (monitor); - if ((lp.find (N_(":monitor")) != string::npos) && - (lp.find (lpn) != string::npos)) { - ++s; - continue; - } + if ((lp.find (monitor) != string::npos) && + (lp.find (lpn) != string::npos)) { + ++s; + continue; + } - /* can't use the audio engine for this as we are looking at non-Ardour ports */ + /* can't use the audio engine for this as we + * are looking at ports not owned by the + * application, and the audio engine/port + * manager doesn't seem them. + */ PortEngine::PortHandle ph = AudioEngine::instance()->port_engine().get_port_by_name (p); - if (ph) { - DataType t (AudioEngine::instance()->port_engine().port_data_type (ph)); - if (t != DataType::NIL) { - if (port_has_prefix (p, N_("system:")) || - port_has_prefix (p, N_("alsa_pcm")) || - port_has_prefix (p, lpnc)) { - extra_system[t].push_back (p); - } else { - extra_other[t].push_back (p); + + if (!ph) { + continue; + } + + DataType t (AudioEngine::instance()->port_engine().port_data_type (ph)); + + if (t != DataType::NIL) { + + PortFlags flags (AudioEngine::instance()->port_engine().get_port_flags (ph)); + + if (port_has_prefix (p, lpnc)) { + + /* we own this port (named after the program) */ + + /* Hide scene ports from non-Tracks Live builds */ + if (!ARDOUR::Profile->get_trx()) { + if (p.find (_("Scene ")) != string::npos) { + ++s; + continue; + } } + + extra_program[t].push_back (p); + + } else if (flags & IsPhysical) { + + extra_system[t].push_back (p); + + } else { + extra_other[t].push_back (p); } } } @@ -563,6 +633,14 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp } } + for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) { + if (!extra_program[*i].empty()) { + /* used program name as bundle name */ + boost::shared_ptr b = make_bundle_from_ports (extra_program[*i], *i, inputs, lpn); + program->add_bundle (b); + } + } + for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) { if (extra_other[*i].empty()) continue; std::string cp; @@ -589,28 +667,36 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp } add_group_if_not_empty (other); - if (type != DataType::MIDI) { - add_group_if_not_empty (bus); - } + add_group_if_not_empty (bus); add_group_if_not_empty (track); - add_group_if_not_empty (ardour); + add_group_if_not_empty (sidechain); + add_group_if_not_empty (program); add_group_if_not_empty (system); emit_changed (); } boost::shared_ptr -PortGroupList::make_bundle_from_ports (std::vector const & p, ARDOUR::DataType type, bool inputs) const +PortGroupList::make_bundle_from_ports (std::vector const & p, ARDOUR::DataType type, bool inputs, std::string const& bundle_name) const { boost::shared_ptr b (new Bundle ("", inputs)); - std::string const pre = common_prefix (p); - if (!pre.empty()) { - b->set_name (pre.substr (0, pre.length() - 1)); + + if (!bundle_name.empty()) { + b->set_name (bundle_name); + } else { + if (!pre.empty()) { + b->set_name (pre.substr (0, pre.length() - 1)); + } } for (uint32_t j = 0; j < p.size(); ++j) { - b->add_channel (p[j].substr (pre.length()), type); + std::string n = p[j].substr (pre.length()); + std::string pn = AudioEngine::instance()->get_pretty_name_by_name (p[j]); + if (!pn.empty()) { + n = pn; + } + b->add_channel (n, type); b->set_port (j, p[j]); } @@ -791,4 +877,3 @@ PortGroupList::empty () const { return _groups.empty (); } -