X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Froute_group.cc;h=e1d43f4cd6a72401d2ac8eccddc943cb3b34db2c;hb=7d96960b162d25da87c388a3083775e8770bba56;hp=13b90474ccbc3d230f564e37eb9383951c12f1dc;hpb=99904735e066804358f1d0bd138a84f1e9ecda91;p=ardour.git diff --git a/libs/ardour/route_group.cc b/libs/ardour/route_group.cc index 13b90474cc..e1d43f4cd6 100644 --- a/libs/ardour/route_group.cc +++ b/libs/ardour/route_group.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2000-2002 Paul Davis + Copyright (C) 2000-2009 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 @@ -22,25 +22,44 @@ #include -#include -#include -#include +#include "pbd/error.h" +#include "pbd/enumwriter.h" +#include "pbd/strsplit.h" -#include -#include -#include -#include +#include "ardour/amp.h" +#include "ardour/route_group.h" +#include "ardour/audio_track.h" +#include "ardour/audio_diskstream.h" +#include "ardour/configuration.h" +#include "ardour/session.h" + +#include "i18n.h" using namespace ARDOUR; -using namespace sigc; using namespace std; -RouteGroup::RouteGroup (Session& s, const string &n, Flag f) - : _session (s), _name (n), _flags (f) +RouteGroup::RouteGroup (Session& s, const string &n, Flag f, Property p) + : _session (s) + , routes (new RouteList) + , _name (n) + , _flags (f) + , _properties (Property (p)) { } +RouteGroup::~RouteGroup () +{ + for (RouteList::iterator i = routes->begin(); i != routes->end();) { + RouteList::iterator tmp = i; + ++tmp; + + (*i)->leave_route_group (); + + i = tmp; + } +} + void RouteGroup::set_name (string str) { @@ -49,33 +68,51 @@ RouteGroup::set_name (string str) FlagsChanged (0); /* EMIT SIGNAL */ } +/** Add a route to a group. Adding a route which is already in the group is allowed; nothing will happen. + * @param r Route to add. + */ int -RouteGroup::add (Route *r) +RouteGroup::add (boost::shared_ptr r) { - routes.push_back (r); - r->GoingAway.connect (sigc::bind (mem_fun (*this, &RouteGroup::remove_when_going_away), r)); + if (find (routes->begin(), routes->end(), r) != routes->end()) { + return 0; + } + + r->leave_route_group (); + + routes->push_back (r); + + r->join_route_group (this); + r->DropReferences.connect_same_thread (*this, boost::bind (&RouteGroup::remove_when_going_away, this, boost::weak_ptr (r))); + _session.set_dirty (); changed (); /* EMIT SIGNAL */ return 0; } void -RouteGroup::remove_when_going_away (Route *r) +RouteGroup::remove_when_going_away (boost::weak_ptr wr) { - remove (r); + boost::shared_ptr r (wr.lock()); + + if (r) { + remove (r); + } } - + int -RouteGroup::remove (Route *r) +RouteGroup::remove (boost::shared_ptr r) { - list::iterator i; + RouteList::iterator i; - if ((i = find (routes.begin(), routes.end(), r)) != routes.end()) { - routes.erase (i); + if ((i = find (routes->begin(), routes->end(), r)) != routes->end()) { + r->leave_route_group (); + routes->erase (i); _session.set_dirty (); changed (); /* EMIT SIGNAL */ return 0; } + return -1; } @@ -84,18 +121,18 @@ gain_t RouteGroup::get_min_factor(gain_t factor) { gain_t g; - - for (list::iterator i = routes.begin(); i != routes.end(); i++) { - g = (*i)->gain(); + + for (RouteList::iterator i = routes->begin(); i != routes->end(); i++) { + g = (*i)->amp()->gain(); if ( (g+g*factor) >= 0.0f) continue; if ( g <= 0.0000003f ) return 0.0f; - + factor = 0.0000003f/g - 1.0f; - } + } return factor; } @@ -103,14 +140,14 @@ gain_t RouteGroup::get_max_factor(gain_t factor) { gain_t g; - - for (list::iterator i = routes.begin(); i != routes.end(); i++) { - g = (*i)->gain(); - + + for (RouteList::iterator i = routes->begin(); i != routes->end(); i++) { + g = (*i)->amp()->gain(); + // if the current factor woulnd't raise this route above maximum - if ( (g+g*factor) <= 1.99526231f) + if ( (g+g*factor) <= 1.99526231f) continue; - + // if route gain is already at peak, return 0.0f factor if (g>=1.99526231f) return 0.0f; @@ -128,12 +165,28 @@ RouteGroup::get_state (void) XMLNode *node = new XMLNode ("RouteGroup"); node->add_property ("name", _name); node->add_property ("flags", enum_2_string (_flags)); + node->add_property ("properties", enum_2_string (_properties)); + + if (!routes->empty()) { + stringstream str; + + for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) { + str << (*i)->id () << ' '; + } + + node->add_property ("routes", str.str()); + } + return *node; } -int -RouteGroup::set_state (const XMLNode& node) +int +RouteGroup::set_state (const XMLNode& node, int version) { + if (version < 3000) { + return set_state_2X (node, version); + } + const XMLProperty *prop; if ((prop = node.property ("name")) != 0) { @@ -144,12 +197,52 @@ RouteGroup::set_state (const XMLNode& node) _flags = Flag (string_2_enum (prop->value(), _flags)); } + if ((prop = node.property ("properties")) != 0) { + _properties = Property (string_2_enum (prop->value(), _properties)); + } + + if ((prop = node.property ("routes")) != 0) { + stringstream str (prop->value()); + vector ids; + split (str.str(), ids, ' '); + + for (vector::iterator i = ids.begin(); i != ids.end(); ++i) { + PBD::ID id (*i); + boost::shared_ptr r = _session.route_by_id (id); + + if (r) { + add (r); + } + } + } + + return 0; +} + +int +RouteGroup::set_state_2X (const XMLNode& node, int /*version*/) +{ + XMLProperty const * prop; + + if ((prop = node.property ("name")) != 0) { + _name = prop->value(); + } + + if ((prop = node.property ("flags")) != 0) { + _flags = Flag (string_2_enum (prop->value(), _flags)); + } + + if (node.name() == "MixGroup") { + _properties = Property (Gain | Mute | Solo | RecEnable); + } else if (node.name() == "EditGroup") { + _properties = Property (Select | Edit); + } + return 0; } void RouteGroup::set_active (bool yn, void *src) - { if (is_active() == yn) { return; @@ -192,7 +285,7 @@ RouteGroup::set_hidden (bool yn, void *src) _flags = Flag (_flags & ~Active); } } else { - _flags = Flag (_flags & ~Hidden); + _flags = Flag (_flags & ~Hidden); if (Config->get_hiding_groups_deactivates_groups()) { _flags = Flag (_flags | Active); } @@ -202,13 +295,65 @@ RouteGroup::set_hidden (bool yn, void *src) } void -RouteGroup::audio_track_group (set& ats) -{ - for (list::iterator i = routes.begin(); i != routes.end(); ++i) { - AudioTrack* at = dynamic_cast(*i); +RouteGroup::audio_track_group (set >& ats) +{ + for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) { + boost::shared_ptr at = boost::dynamic_pointer_cast(*i); if (at) { ats.insert (at); } } } +void +RouteGroup::make_subgroup () +{ + 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::info << _("You cannot subgroup MIDI tracks at this time") << endmsg; + return; + } + } + + for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) { + nin = max (nin, (*i)->output()->n_ports().n_audio()); + } + + try { + /* use master bus etc. to determine default nouts */ + rl = _session.new_audio_route (false, nin, 2, 0, 1); + } catch (...) { + return; + } + + subgroup_bus = rl.front(); + subgroup_bus->set_name (_name); + + boost::shared_ptr 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, 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 (); +}