NOOP, remove trailing tabs/whitespace.
[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         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
66                 if (!(*i)->is_auditioner()) {
67                         (*i)->set_solo (yn, this);
68                 }
69         }
70
71         set_dirty();
72         /* XXX boost::shared_ptr<RouteList>  goes out of scope here and is likley free()ed in RT context
73          * because boost's shared_ptr does reference counting and free/delete in the dtor.
74          * (this also applies to other rt_  methods here)
75          */
76 }
77
78 void
79 Session::cancel_solo_after_disconnect (boost::shared_ptr<Route> r, bool upstream, SessionEvent::RTeventCallback after)
80 {
81         boost::shared_ptr<RouteList> rl (new RouteList);
82         rl->push_back (r);
83
84         queue_event (get_rt_event (rl, upstream, after, false, &Session::rt_cancel_solo_after_disconnect));
85 }
86
87 void
88 Session::rt_cancel_solo_after_disconnect (boost::shared_ptr<RouteList> rl, bool upstream, bool /* group_override */)
89 {
90         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
91                 if (!(*i)->is_auditioner()) {
92                         (*i)->cancel_solo_after_disconnect (upstream);
93                 }
94         }
95         /* no need to call set-dirty - the disconnect will already have done that */
96 }
97
98 void
99 Session::set_just_one_solo (boost::shared_ptr<Route> r, bool yn, SessionEvent::RTeventCallback after)
100 {
101         /* its a bit silly to have to do this, but it keeps the API for this public method sane (we're
102            only going to solo one route) and keeps our ability to use get_rt_event() for the internal
103            private method.
104         */
105
106         boost::shared_ptr<RouteList> rl (new RouteList);
107         rl->push_back (r);
108
109         queue_event (get_rt_event (rl, yn, after, false, &Session::rt_set_just_one_solo));
110 }
111
112 void
113 Session::rt_set_just_one_solo (boost::shared_ptr<RouteList> just_one, bool yn, bool /*ignored*/)
114 {
115         boost::shared_ptr<RouteList> rl = routes.reader ();
116         boost::shared_ptr<Route> r = just_one->front();
117
118         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
119                 if (!(*i)->is_auditioner() && r != *i) {
120                         (*i)->set_solo (!yn, (*i)->route_group());
121                 }
122         }
123
124         r->set_solo (yn, r->route_group());
125
126         set_dirty();
127 }
128
129 void
130 Session::set_listen (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
131 {
132         queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_listen));
133 }
134
135 void
136 Session::rt_set_listen (boost::shared_ptr<RouteList> rl, bool yn, bool /*group_override*/ )
137 {
138         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
139                 if (!(*i)->is_auditioner()) {
140                         (*i)->set_listen (yn, this);
141                 }
142         }
143
144         set_dirty();
145 }
146
147 void
148 Session::set_mute (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
149 {
150         /* Set superficial value of mute controls for automation. */
151         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
152                 boost::shared_ptr<Route::MuteControllable> mc = (*i)->mute_control();
153                 mc->set_superficial_value(yn);
154         }
155
156         queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_mute));
157 }
158
159 void
160 Session::rt_set_mute (boost::shared_ptr<RouteList> rl, bool yn, bool /*group_override*/)
161 {
162         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
163                 if (!(*i)->is_monitor() && !(*i)->is_auditioner()) {
164                         (*i)->set_mute (yn, this);
165                 }
166         }
167
168         set_dirty();
169 }
170
171 void
172 Session::set_solo_isolated (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
173 {
174         queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_solo_isolated));
175 }
176
177 void
178 Session::rt_set_solo_isolated (boost::shared_ptr<RouteList> rl, bool yn, bool /*group_override*/)
179 {
180         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
181                 if (!(*i)->is_master() && !(*i)->is_monitor() && !(*i)->is_auditioner()) {
182                         (*i)->set_solo_isolated (yn, this);
183                 }
184         }
185
186         set_dirty();
187 }
188
189 void
190 Session::set_record_enabled (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
191 {
192         if (!writable()) {
193                 return;
194         }
195
196         /* do the non-RT part of rec-enabling first - the RT part will be done
197          * on the next process cycle. This does mean that theoretically we are
198          * doing things provisionally on the assumption that the rec-enable
199          * change will work, but this had better be a solid assumption for
200          * other reasons.
201          */
202
203         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
204                 if ((*i)->is_auditioner() || (*i)->record_safe ()) {
205                         continue;
206                 }
207
208                 boost::shared_ptr<Track> t;
209
210                 if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
211                         t->prep_record_enabled (yn, (group_override ? (void*) t->route_group() : (void *) this));
212                 }
213         }
214
215         queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_record_enabled));
216 }
217
218 void
219 Session::rt_set_record_enabled (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
220 {
221         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
222                 if ((*i)->is_auditioner() || (*i)->record_safe ()) {
223                         continue;
224                 }
225
226                 boost::shared_ptr<Track> t;
227
228                 if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
229                         t->set_record_enabled (yn, (group_override ? (void*) t->route_group() : (void *) this));
230                 }
231         }
232
233         set_dirty ();
234 }
235
236
237 void
238 Session::set_record_safe (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
239 {
240         set_record_enabled (rl, false, after, group_override);
241         queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_record_safe));
242 }
243
244 void
245 Session::rt_set_record_safe (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
246 {
247         for (RouteList::iterator i = rl->begin (); i != rl->end (); ++i) {
248                 if ((*i)->is_auditioner ()) { // REQUIRES REVIEW Can audiotioner be in Record Safe mode?
249                         continue;
250                 }
251
252                 boost::shared_ptr<Track> t;
253
254                 if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
255                         t->set_record_safe (yn, (group_override ? (void*) t->route_group () : (void *) this));
256                 }
257         }
258
259         set_dirty ();
260 }
261
262 void
263 Session::process_rtop (SessionEvent* ev)
264 {
265         ev->rt_slot ();
266
267         if (ev->event_loop) {
268                 ev->event_loop->call_slot (MISSING_INVALIDATOR, boost::bind (ev->rt_return, ev));
269         } else {
270                 warning << string_compose ("programming error: %1", X_("Session RT event queued from thread without a UI - cleanup in RT thread!")) << endmsg;
271                 ev->rt_return (ev);
272         }
273 }