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