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