+void
+RouteGroup::make_subgroup (bool aux, Placement placement)
+{
+ RouteList rl;
+ uint32_t nin = 0;
+
+ /* since we don't do MIDI Busses yet, check quickly ... */
+
+ for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
+ if ((*i)->output()->n_ports().n_midi() != 0) {
+ PBD::warning << _("You cannot subgroup MIDI tracks at this time") << endmsg;
+ return;
+ }
+ }
+
+ for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
+ if (!aux && nin != 0 && nin != (*i)->output()->n_ports().n_audio()) {
+ PBD::warning << _("You cannot subgroup tracks with different number of outputs at this time.") << endmsg;
+ return;
+ }
+ nin = max (nin, (*i)->output()->n_ports().n_audio());
+ }
+
+ try {
+ /* use master bus etc. to determine default nouts.
+ *
+ * (since tracks can't have fewer outs than ins,
+ * "nin" currently defines the number of outpus if nin > 2)
+ */
+ rl = _session.new_audio_route (nin, 2, 0, 1, string(), PresentationInfo::AudioBus, PresentationInfo::max_order);
+ } catch (...) {
+ return;
+ }
+
+ subgroup_bus = rl.front();
+ subgroup_bus->set_name (_name);
+
+ if (aux) {
+
+ _session.add_internal_sends (subgroup_bus, placement, routes);
+
+ } else {
+
+ boost::shared_ptr<Bundle> bundle = subgroup_bus->input()->bundle ();
+
+ for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
+ (*i)->output()->disconnect (this);
+ (*i)->output()->connect_ports_to_bundle (bundle, false, this);
+ }
+ }
+}
+
+void
+RouteGroup::destroy_subgroup ()
+{
+ if (!subgroup_bus) {
+ return;
+ }
+
+ for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
+ (*i)->output()->disconnect (this);
+ /* XXX find a new bundle to connect to */
+ }
+
+ _session.remove_route (subgroup_bus);
+ subgroup_bus.reset ();
+}
+
+bool
+RouteGroup::has_subgroup() const
+{
+ return subgroup_bus != 0;
+}
+
+bool
+RouteGroup::enabled_property (PBD::PropertyID prop)
+{
+ OwnedPropertyList::iterator i = _properties->find (prop);
+ if (i == _properties->end()) {
+ return false;
+ }
+
+ return dynamic_cast<const PropertyTemplate<bool>* > (i->second)->val ();
+}
+
+void
+RouteGroup::post_set (PBD::PropertyChange const &)
+{
+ push_to_groups ();
+}
+
+void
+RouteGroup::push_to_groups ()
+{
+ if (is_relative()) {
+ _gain_group->set_mode (ControlGroup::Mode (_gain_group->mode()|ControlGroup::Relative));
+ } else {
+ _gain_group->set_mode (ControlGroup::Mode (_gain_group->mode()&~ControlGroup::Relative));
+ }
+
+ if (_active) {
+ _gain_group->set_active (is_gain());
+ _solo_group->set_active (is_solo());
+ _mute_group->set_active (is_mute());
+ _rec_enable_group->set_active (is_recenable());
+ _monitoring_group->set_active (is_monitoring());
+ } else {
+ _gain_group->set_active (false);
+ _solo_group->set_active (false);
+ _mute_group->set_active (false);
+
+ _rec_enable_group->set_active (false);
+ _monitoring_group->set_active (false);
+ }
+}
+
+void
+RouteGroup::assign_master (boost::shared_ptr<VCA> master)
+{
+ if (!routes || routes->empty()) {
+ return;
+ }
+
+ boost::shared_ptr<Route> front = routes->front ();
+
+ if (front->slaved_to (master)) {
+ return;
+ }
+
+ for (RouteList::iterator r = routes->begin(); r != routes->end(); ++r) {
+ (*r)->assign (master, false);
+ }
+
+ bool used_to_share_gain = false;
+
+ if (is_gain()) {
+ used_to_share_gain = true;
+ }
+
+ group_master = master;
+ _group_master_number = master->number();
+ _gain_group->set_active (false);
+
+ if (used_to_share_gain) {
+ send_change (PropertyChange (Properties::group_gain));
+ }
+}
+
+void
+RouteGroup::unassign_master (boost::shared_ptr<VCA> master)
+{
+ if (!routes || routes->empty()) {
+ return;
+ }
+
+ boost::shared_ptr<Route> front = routes->front ();
+
+ if (!front->slaved_to (master)) {
+ return;
+ }
+
+ for (RouteList::iterator r = routes->begin(); r != routes->end(); ++r) {
+ (*r)->unassign (master);
+ }
+
+ group_master.reset ();
+ _group_master_number = -1;
+
+ /* this is slightly tricky: is_gain() will return whether or not
+ the group is supposed to be sharing gain adjustment, and now that
+ we've reset _group_master_number to -1, it will reflect the user's
+ intentions correctly. Since there was a master before, and now there
+ is not, we are going to reactivate gain sharing ... and then tell
+ the world about it.
+ */
+ if (is_gain()) {
+ _gain_group->set_active (true);
+ send_change (PropertyChange (Properties::group_gain));
+ }
+}
+
+bool
+RouteGroup::slaved () const
+{
+ if (!routes || routes->empty()) {
+ return false;
+ }
+
+ return routes->front()->slaved ();
+}
+
+bool
+RouteGroup::has_control_master() const
+{
+ return group_master.lock() != 0;
+}