Honor groups for mixer selection
[ardour.git] / gtk2_ardour / route_processor_selection.cc
1 /*
2     Copyright (C) 2002 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <algorithm>
21 #include <sigc++/bind.h>
22
23 #include "pbd/error.h"
24 #include "pbd/i18n.h"
25
26 #include "ardour/selection.h"
27 #include "ardour/session.h"
28 #include "ardour/session_handle.h"
29
30 #include "axis_provider.h"
31 #include "gui_thread.h"
32 #include "mixer_strip.h"
33 #include "mixer_ui.h"
34 #include "route_processor_selection.h"
35 #include "route_ui.h"
36
37 using namespace std;
38 using namespace ARDOUR;
39 using namespace PBD;
40
41 RouteProcessorSelection::RouteProcessorSelection (SessionHandlePtr& s, AxisViewProvider& ap)
42         : shp (s), avp (ap)
43 {
44 }
45
46 RouteProcessorSelection&
47 RouteProcessorSelection::operator= (const RouteProcessorSelection& other)
48 {
49         if (&other != this) {
50                 (*((ProcessorSelection*) this)) = (*((ProcessorSelection const *) &other));
51                 axes = other.axes;
52         }
53         return *this;
54 }
55
56 bool
57 operator== (const RouteProcessorSelection& a, const RouteProcessorSelection& b)
58 {
59         // XXX MUST TEST PROCESSORS SOMEHOW
60         return a.axes == b.axes;
61 }
62
63 void
64 RouteProcessorSelection::clear ()
65 {
66         clear_processors ();
67         clear_routes ();
68 }
69
70 void
71 RouteProcessorSelection::clear_routes ()
72 {
73         if (shp.session()) {
74                 PresentationInfo::ChangeSuspender cs;
75                 shp.session()->selection().clear_stripables ();
76         }
77 }
78
79 std::list<AxisView*>
80 RouteProcessorSelection::add_grouped_tracks (AxisView* r) const
81 {
82         std::list<AxisView*> rv;
83
84         boost::shared_ptr<Route> route = boost::dynamic_pointer_cast<Route>(r->stripable());
85         if (route) {
86                 ARDOUR::RouteGroup* rg = route->route_group ();
87                 if (rg && rg->is_active() && rg->is_select ()) {
88
89                         boost::shared_ptr<RouteList> rl = rg->route_list ();
90                         for (RouteList::const_iterator i = rl->begin(); i != rl->end(); ++i) {
91                                 AxisView* av = avp.axis_view_by_stripable (*i);
92                                 rv.push_back (av);
93                         }
94                 }
95         }
96         return rv;
97 }
98
99 void
100 RouteProcessorSelection::presentation_info_changed (PropertyChange const & what_changed)
101 {
102         Session* s = shp.session();
103
104         if (!s) {
105                 /* too early ... session handle provider doesn't know about the
106                    session yet.
107                 */
108                 return;
109         }
110
111         PropertyChange pc;
112         pc.add (Properties::selected);
113
114         CoreSelection::StripableAutomationControls sc;
115         s->selection().get_stripables (sc);
116
117         for (AxisViewSelection::iterator a = axes.begin(); a != axes.end(); ++a) {
118                 (*a)->set_selected (false);
119         }
120
121         axes.clear ();
122
123         for (CoreSelection::StripableAutomationControls::const_iterator i = sc.begin(); i != sc.end(); ++i) {
124                 AxisView* av = avp.axis_view_by_stripable ((*i).stripable);
125                 if (av) {
126                         axes.insert (av);
127                         av->set_selected (true);
128                 }
129         }
130 }
131
132 void
133 RouteProcessorSelection::add (AxisView* r, bool with_groups)
134 {
135         if (!shp.session()) {
136                 return;
137         }
138
139         std::list<AxisView*> avl;
140         if (with_groups) {
141                 avl= add_grouped_tracks (r);
142         }
143         avl.push_back (r);
144
145         PresentationInfo::ChangeSuspender cs;
146         for (std::list<AxisView*>::const_iterator i = avl.begin (); i != avl.end (); ++i) {
147                 if (axes.insert (*i).second) {
148                         shp.session()->selection().add ((*i)->stripable(), boost::shared_ptr<AutomationControl>());
149                         MixerStrip* ms = dynamic_cast<MixerStrip*> (*i);
150                         if (ms) {
151                                 ms->CatchDeletion.connect (*this, invalidator (*this), boost::bind (&RouteProcessorSelection::remove, this, _1, false), gui_context());
152                         }
153                 }
154         }
155 }
156
157 void
158 RouteProcessorSelection::remove (AxisView* r, bool with_groups)
159 {
160         if (!shp.session()) {
161                 return;
162         }
163         ENSURE_GUI_THREAD (*this, &RouteProcessorSelection::remove, r);
164
165         std::list<AxisView*> avl;
166         if (with_groups) {
167                 avl= add_grouped_tracks (r);
168         }
169         avl.push_back (r);
170
171         PresentationInfo::ChangeSuspender cs;
172         for (std::list<AxisView*>::const_iterator i = avl.begin (); i != avl.end (); ++i) {
173                 shp.session()->selection().remove ((*i)->stripable(), boost::shared_ptr<AutomationControl>());
174         }
175 }
176
177 void
178 RouteProcessorSelection::set (AxisView* r)
179 {
180         if (!shp.session()) {
181                 return;
182         }
183         shp.session()->selection().clear_stripables ();
184         add (r, true);
185 }
186
187 bool
188 RouteProcessorSelection::selected (AxisView* r)
189 {
190         return find (axes.begin(), axes.end(), r) != axes.end();
191 }
192
193 bool
194 RouteProcessorSelection::empty ()
195 {
196         return processors.empty () && axes.empty ();
197 }