Optimize automation-event process splitting
[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
25 #include "ardour/selection.h"
26 #include "ardour/session.h"
27 #include "ardour/session_handle.h"
28
29 #include "axis_provider.h"
30 #include "gui_thread.h"
31 #include "mixer_strip.h"
32 #include "mixer_ui.h"
33 #include "route_processor_selection.h"
34 #include "route_ui.h"
35
36 #include "pbd/i18n.h"
37
38 using namespace std;
39 using namespace ARDOUR;
40 using namespace PBD;
41
42 RouteProcessorSelection::RouteProcessorSelection (SessionHandlePtr& s, AxisViewProvider& ap)
43         : shp (s), avp (ap)
44 {
45 }
46
47 bool
48 operator== (const RouteProcessorSelection& a, const RouteProcessorSelection& b)
49 {
50         // XXX MUST TEST PROCESSORS SOMEHOW
51         return a.axes == b.axes;
52 }
53
54 void
55 RouteProcessorSelection::clear ()
56 {
57         clear_processors ();
58         clear_routes ();
59 }
60
61 void
62 RouteProcessorSelection::clear_routes ()
63 {
64         if (shp.session()) {
65                 PresentationInfo::ChangeSuspender cs;
66                 shp.session()->selection().clear_stripables ();
67         }
68 }
69
70 std::list<AxisView*>
71 RouteProcessorSelection::add_grouped_tracks (AxisView* r) const
72 {
73         std::list<AxisView*> rv;
74
75         boost::shared_ptr<Route> route = boost::dynamic_pointer_cast<Route>(r->stripable());
76         if (route) {
77                 ARDOUR::RouteGroup* rg = route->route_group ();
78                 if (rg && rg->is_active() && rg->is_select ()) {
79
80                         boost::shared_ptr<RouteList> rl = rg->route_list ();
81                         for (RouteList::const_iterator i = rl->begin(); i != rl->end(); ++i) {
82                                 AxisView* av = avp.axis_view_by_stripable (*i);
83                                 rv.push_back (av);
84                         }
85                 }
86         }
87         return rv;
88 }
89
90 void
91 RouteProcessorSelection::presentation_info_changed (PropertyChange const & what_changed)
92 {
93         Session* s = shp.session();
94
95         if (!s) {
96                 /* too early ... session handle provider doesn't know about the
97                    session yet.
98                 */
99                 return;
100         }
101
102         PropertyChange pc;
103         pc.add (Properties::selected);
104
105         CoreSelection::StripableAutomationControls sc;
106         s->selection().get_stripables (sc);
107
108         for (AxisViewSelection::iterator a = axes.begin(); a != axes.end(); ++a) {
109                 (*a)->set_selected (false);
110         }
111
112         axes.clear ();
113
114         for (CoreSelection::StripableAutomationControls::const_iterator i = sc.begin(); i != sc.end(); ++i) {
115                 AxisView* av = avp.axis_view_by_stripable ((*i).stripable);
116                 if (av) {
117                         axes.insert (av);
118                         av->set_selected (true);
119                 }
120         }
121 }
122
123 void
124 RouteProcessorSelection::add (AxisView* r, bool with_groups)
125 {
126         if (!shp.session()) {
127                 return;
128         }
129
130         std::list<AxisView*> avl;
131         if (with_groups) {
132                 avl= add_grouped_tracks (r);
133         }
134         avl.push_back (r);
135
136         PresentationInfo::ChangeSuspender cs;
137         for (std::list<AxisView*>::const_iterator i = avl.begin (); i != avl.end (); ++i) {
138                 if (axes.insert (*i).second) {
139                         shp.session()->selection().add ((*i)->stripable(), boost::shared_ptr<AutomationControl>());
140                         MixerStrip* ms = dynamic_cast<MixerStrip*> (*i);
141                         if (ms) {
142                                 ms->CatchDeletion.connect (*this, invalidator (*this), boost::bind (&RouteProcessorSelection::remove, this, _1, false), gui_context());
143                         }
144                 }
145         }
146 }
147
148 void
149 RouteProcessorSelection::remove (AxisView* r, bool with_groups)
150 {
151         if (!shp.session()) {
152                 return;
153         }
154         ENSURE_GUI_THREAD (*this, &RouteProcessorSelection::remove, r);
155
156         std::list<AxisView*> avl;
157         if (with_groups) {
158                 avl= add_grouped_tracks (r);
159         }
160         avl.push_back (r);
161
162         PresentationInfo::ChangeSuspender cs;
163         for (std::list<AxisView*>::const_iterator i = avl.begin (); i != avl.end (); ++i) {
164                 shp.session()->selection().remove ((*i)->stripable(), boost::shared_ptr<AutomationControl>());
165         }
166 }
167
168 void
169 RouteProcessorSelection::set (AxisView* r)
170 {
171         if (!shp.session()) {
172                 return;
173         }
174         PresentationInfo::ChangeSuspender cs;
175         shp.session()->selection().clear_stripables ();
176         add (r, true);
177 }
178
179 bool
180 RouteProcessorSelection::selected (AxisView* r)
181 {
182         return find (axes.begin(), axes.end(), r) != axes.end();
183 }
184
185 bool
186 RouteProcessorSelection::empty ()
187 {
188         return processors.empty () && axes.empty ();
189 }