globally remove all trailing whitespace from ardour code base.
[ardour.git] / libs / ardour / session_rtevents.cc
1 /*
2     Copyright (C) 1999-2009 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 #include <boost/bind.hpp>
20
21 #include "pbd/error.h"
22 #include "pbd/compose.h"
23
24 #include "ardour/session.h"
25 #include "ardour/route.h"
26 #include "ardour/track.h"
27
28 #include "i18n.h"
29
30 using namespace std;
31 using namespace PBD;
32 using namespace ARDOUR;
33 using namespace Glib;
34
35 void
36 Session::set_monitoring (boost::shared_ptr<RouteList> rl, MonitorChoice mc, SessionEvent::RTeventCallback after, bool group_override)
37 {
38         queue_event (get_rt_event (rl, mc, after, group_override, &Session::rt_set_monitoring));
39 }
40
41 void
42 Session::rt_set_monitoring (boost::shared_ptr<RouteList> rl, MonitorChoice mc, bool /* group_override */)
43 {
44         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
45                 if (!(*i)->is_auditioner()) {
46                         boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*i);
47                         if (t) {
48                                 t->set_monitoring (mc);
49                         }
50                 }
51         }
52
53         set_dirty();
54 }
55
56 void
57 Session::set_solo (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
58 {
59         queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_solo));
60 }
61
62 void
63 Session::rt_set_solo (boost::shared_ptr<RouteList> rl, bool yn, bool /* group_override */)
64 {
65         solo_update_disabled = true;
66         
67         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
68                 if (!(*i)->is_auditioner()) {
69                         (*i)->set_solo (yn, this);
70                 }
71         }
72
73         solo_update_disabled = false;
74         routes_solo_changed (rl);
75
76         set_dirty();
77 }
78
79 void
80 Session::cancel_solo_after_disconnect (boost::shared_ptr<Route> r, bool upstream, SessionEvent::RTeventCallback after)
81 {
82         boost::shared_ptr<RouteList> rl (new RouteList);
83         rl->push_back (r);
84
85         queue_event (get_rt_event (rl, upstream, after, false, &Session::rt_cancel_solo_after_disconnect));
86 }
87
88 void
89 Session::rt_cancel_solo_after_disconnect (boost::shared_ptr<RouteList> rl, bool upstream, bool /* group_override */)
90 {
91         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
92                 if (!(*i)->is_auditioner()) {
93                         (*i)->cancel_solo_after_disconnect (upstream);
94                 }
95         }
96         /* no need to call set-dirty - the disconnect will already have done that */
97 }
98
99 void
100 Session::set_just_one_solo (boost::shared_ptr<Route> r, bool yn, SessionEvent::RTeventCallback after)
101 {
102         /* its a bit silly to have to do this, but it keeps the API for this public method sane (we're
103            only going to solo one route) and keeps our ability to use get_rt_event() for the internal
104            private method.
105         */
106
107         boost::shared_ptr<RouteList> rl (new RouteList);
108         rl->push_back (r);
109
110         queue_event (get_rt_event (rl, yn, after, false, &Session::rt_set_just_one_solo));
111 }
112
113 void
114 Session::rt_set_just_one_solo (boost::shared_ptr<RouteList> just_one, bool yn, bool /*ignored*/)
115 {
116         boost::shared_ptr<RouteList> rl = routes.reader ();
117         boost::shared_ptr<Route> r = just_one->front();
118
119         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
120                 if (!(*i)->is_auditioner() && r != *i) {
121                         (*i)->set_solo (!yn, (*i)->route_group());
122                 }
123         }
124
125         r->set_solo (yn, r->route_group());
126
127         set_dirty();
128 }
129
130 void
131 Session::set_listen (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
132 {
133         queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_listen));
134 }
135
136 void
137 Session::rt_set_listen (boost::shared_ptr<RouteList> rl, bool yn, bool /*group_override*/ )
138 {
139         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
140                 if (!(*i)->is_auditioner()) {
141                         (*i)->set_listen (yn, this);
142                 }
143         }
144
145         set_dirty();
146 }
147
148 void
149 Session::set_mute (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
150 {
151         /* Set superficial value of mute controls for automation. */
152         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
153                 boost::shared_ptr<Route::MuteControllable> mc = (*i)->mute_control();
154                 mc->set_superficial_value(yn);
155         }
156
157         queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_mute));
158 }
159
160 void
161 Session::rt_set_mute (boost::shared_ptr<RouteList> rl, bool yn, bool /*group_override*/)
162 {
163         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
164                 if (!(*i)->is_monitor() && !(*i)->is_auditioner()) {
165                         (*i)->set_mute (yn, this);
166                 }
167         }
168
169         set_dirty();
170 }
171
172 void
173 Session::set_solo_isolated (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
174 {
175         queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_solo_isolated));
176 }
177
178 void
179 Session::rt_set_solo_isolated (boost::shared_ptr<RouteList> rl, bool yn, bool /*group_override*/)
180 {
181         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
182                 if (!(*i)->is_master() && !(*i)->is_monitor() && !(*i)->is_auditioner()) {
183                         (*i)->set_solo_isolated (yn, this);
184                 }
185         }
186
187         set_dirty();
188 }
189
190 void
191 Session::set_record_enabled (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
192 {
193         if (!writable()) {
194                 return;
195         }
196
197         /* do the non-RT part of rec-enabling first - the RT part will be done
198          * on the next process cycle. This does mean that theoretically we are
199          * doing things provisionally on the assumption that the rec-enable
200          * change will work, but this had better be a solid assumption for
201          * other reasons.
202          */
203
204         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
205                 if ((*i)->is_auditioner() || (*i)->record_safe ()) {
206                         continue;
207                 }
208
209                 boost::shared_ptr<Track> t;
210
211                 if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
212                         t->prep_record_enabled (yn, (group_override ? (void*) t->route_group() : (void *) this));
213                 }
214         }
215
216         queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_record_enabled));
217 }
218
219 void
220 Session::rt_set_record_enabled (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
221 {
222         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
223                 if ((*i)->is_auditioner() || (*i)->record_safe ()) {
224                         continue;
225                 }
226
227                 boost::shared_ptr<Track> t;
228
229                 if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
230                         t->set_record_enabled (yn, (group_override ? (void*) t->route_group() : (void *) this));
231                 }
232         }
233
234         set_dirty ();
235 }
236
237
238 void
239 Session::set_record_safe (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
240 {
241         set_record_enabled (rl, false, after, group_override);
242         queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_record_safe));
243 }
244
245 void
246 Session::rt_set_record_safe (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
247 {
248         for (RouteList::iterator i = rl->begin (); i != rl->end (); ++i) {
249                 if ((*i)->is_auditioner ()) { // REQUIRES REVIEW Can audiotioner be in Record Safe mode?
250                         continue;
251                 }
252         
253                 boost::shared_ptr<Track> t;
254         
255                 if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
256                         t->set_record_safe (yn, (group_override ? (void*) t->route_group () : (void *) this));
257                 }
258         }
259         
260         set_dirty ();
261 }
262
263 void
264 Session::process_rtop (SessionEvent* ev)
265 {
266         ev->rt_slot ();
267
268         if (ev->event_loop) {
269                 ev->event_loop->call_slot (MISSING_INVALIDATOR, boost::bind (ev->rt_return, ev));
270         } else {
271                 warning << string_compose ("programming error: %1", X_("Session RT event queued from thread without a UI - cleanup in RT thread!")) << endmsg;
272                 ev->rt_return (ev);
273         }
274 }