add slave,transport and event debugging traces
[ardour.git] / libs / ardour / session_events.cc
1 /*
2     Copyright (C) 1999-2004 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 <cmath>
21 #include <unistd.h>
22
23 #include "ardour/timestamps.h"
24
25 #include "pbd/error.h"
26 #include "pbd/enumwriter.h"
27 #include <glibmm/thread.h>
28
29 #include "ardour/ardour.h"
30 #include "ardour/audio_diskstream.h"
31 #include "ardour/butler.h"
32 #include "ardour/debug.h"
33 #include "ardour/session.h"
34
35 #include "i18n.h"
36
37 using namespace std;
38 using namespace ARDOUR;
39 using namespace PBD;
40
41 MultiAllocSingleReleasePool Session::Event::pool ("event", sizeof (Session::Event), 512);
42
43 void
44 Session::add_event (nframes_t frame, Event::Type type, nframes_t target_frame)
45 {
46         Event* ev = new Event (type, Event::Add, frame, target_frame, 0);
47         queue_event (ev);
48 }
49
50 void
51 Session::remove_event (nframes_t frame, Event::Type type)
52 {
53         Event* ev = new Event (type, Event::Remove, frame, 0, 0);
54         queue_event (ev);
55 }
56
57 void
58 Session::replace_event (Event::Type type, nframes_t frame, nframes_t target)
59 {
60         Event* ev = new Event (type, Event::Replace, frame, target, 0);
61         queue_event (ev);
62 }
63
64 void
65 Session::clear_events (Event::Type type)
66 {
67         Event* ev = new Event (type, Event::Clear, 0, 0, 0);
68         queue_event (ev);
69 }
70
71
72 void
73 Session::dump_events () const
74 {
75         cerr << "EVENT DUMP" << endl;
76         for (Events::const_iterator i = events.begin(); i != events.end(); ++i) {
77                 cerr << "\tat " << (*i)->action_frame << ' ' << (*i)->type << " target = " << (*i)->target_frame << endl;
78         }
79         cerr << "Next event: ";
80
81         if ((Events::const_iterator) next_event == events.end()) {
82                 cerr << "none" << endl;
83         } else {
84                 cerr << "at " << (*next_event)->action_frame << ' '
85                      << (*next_event)->type << " target = "
86                      << (*next_event)->target_frame << endl;
87         }
88         cerr << "Immediate events pending:\n";
89         for (Events::const_iterator i = immediate_events.begin(); i != immediate_events.end(); ++i) {
90                 cerr << "\tat " << (*i)->action_frame << ' ' << (*i)->type << " target = " << (*i)->target_frame << endl;
91         }
92         cerr << "END EVENT_DUMP" << endl;
93 }
94
95 void
96 Session::queue_event (Event* ev)
97 {
98         if (_state_of_the_state & Loading) {
99                 merge_event (ev);
100         } else {
101                 pending_events.write (&ev, 1);
102         }
103 }
104
105 void
106 Session::merge_event (Event* ev)
107 {
108         switch (ev->action) {
109         case Event::Remove:
110                 _remove_event (ev);
111                 delete ev;
112                 return;
113
114         case Event::Replace:
115                 _replace_event (ev);
116                 return;
117
118         case Event::Clear:
119                 _clear_event_type (ev->type);
120                 delete ev;
121                 return;
122
123         case Event::Add:
124                 break;
125         }
126
127         /* try to handle immediate events right here */
128
129         if (ev->action_frame == 0) {
130                 process_event (ev);
131                 return;
132         }
133
134         switch (ev->type) {
135         case Event::AutoLoop:
136         case Event::StopOnce:
137                 _clear_event_type (ev->type);
138                 break;
139
140         default:
141                 for (Events::iterator i = events.begin(); i != events.end(); ++i) {
142                         if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
143                           error << string_compose(_("Session: cannot have two events of type %1 at the same frame (%2)."),
144                                                   enum_2_string (ev->type), ev->action_frame) << endmsg;
145                                 return;
146                         }
147                 }
148         }
149
150         events.insert (events.begin(), ev);
151         events.sort (Event::compare);
152         next_event = events.begin();
153         set_next_event ();
154 }
155
156 /** @return true when @a ev is deleted. */
157 bool
158 Session::_replace_event (Event* ev)
159 {
160         bool ret = false;
161         Events::iterator i;
162
163         /* private, used only for events that can only exist once in the queue */
164
165         for (i = events.begin(); i != events.end(); ++i) {
166                 if ((*i)->type == ev->type) {
167                         (*i)->action_frame = ev->action_frame;
168                         (*i)->target_frame = ev->target_frame;
169                         if ((*i) == ev) {
170                                 ret = true;
171                         }
172                         delete ev;
173                         break;
174                 }
175         }
176
177         if (i == events.end()) {
178                 events.insert (events.begin(), ev);
179         }
180
181         events.sort (Event::compare);
182         next_event = events.end();
183         set_next_event ();
184
185         return ret;
186 }
187
188 /** @return true when @a ev is deleted. */
189 bool
190 Session::_remove_event (Session::Event* ev)
191 {
192         bool ret = false;
193         Events::iterator i;
194
195         for (i = events.begin(); i != events.end(); ++i) {
196                 if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
197                         if ((*i) == ev) {
198                                 ret = true;
199                         }
200
201                         delete *i;
202                         if (i == next_event) {
203                                 ++next_event;
204                         }
205                         events.erase (i);
206                         break;
207                 }
208         }
209
210         if (i != events.end()) {
211                 set_next_event ();
212         }
213
214         return ret;
215 }
216
217 void
218 Session::_clear_event_type (Event::Type type)
219 {
220         Events::iterator i, tmp;
221
222         for (i = events.begin(); i != events.end(); ) {
223
224                 tmp = i;
225                 ++tmp;
226
227                 if ((*i)->type == type) {
228                         delete *i;
229                         if (i == next_event) {
230                                 ++next_event;
231                         }
232                         events.erase (i);
233                 }
234
235                 i = tmp;
236         }
237
238         for (i = immediate_events.begin(); i != immediate_events.end(); ) {
239
240                 tmp = i;
241                 ++tmp;
242
243                 if ((*i)->type == type) {
244                         delete *i;
245                         immediate_events.erase (i);
246                 }
247
248                 i = tmp;
249         }
250
251         set_next_event ();
252 }
253
254 void
255 Session::set_next_event ()
256 {
257         if (events.empty()) {
258                 next_event = events.end();
259                 return;
260         }
261
262         if (next_event == events.end()) {
263                 next_event = events.begin();
264         }
265
266         if ((*next_event)->action_frame > _transport_frame) {
267                 next_event = events.begin();
268         }
269
270         for (; next_event != events.end(); ++next_event) {
271                 if ((*next_event)->action_frame >= _transport_frame) {
272                         break;
273                 }
274         }
275 }
276
277 void
278 Session::process_event (Event* ev)
279 {
280         bool remove = true;
281         bool del = true;
282
283         /* if we're in the middle of a state change (i.e. waiting
284            for the butler thread to complete the non-realtime
285            part of the change), we'll just have to queue this
286            event for a time when the change is complete.
287         */
288
289         if (non_realtime_work_pending()) {
290
291                 /* except locates, which we have the capability to handle */
292
293                 if (ev->type != Event::Locate) {
294                         immediate_events.insert (immediate_events.end(), ev);
295                         _remove_event (ev);
296                         return;
297                 }
298         }
299
300         DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
301
302         switch (ev->type) {
303         case Event::SetLoop:
304                 set_play_loop (ev->yes_or_no);
305                 break;
306
307         case Event::AutoLoop:
308                 if (play_loop) {
309                         start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
310                 }
311                 remove = false;
312                 del = false;
313                 break;
314
315         case Event::Locate:
316                 if (ev->yes_or_no) {
317                         // cerr << "forced locate to " << ev->target_frame << endl;
318                         locate (ev->target_frame, false, true, false);
319                 } else {
320                         // cerr << "soft locate to " << ev->target_frame << endl;
321                         start_locate (ev->target_frame, false, true, false);
322                 }
323                 _send_timecode_update = true;
324                 break;
325
326         case Event::LocateRoll:
327                 if (ev->yes_or_no) {
328                         // cerr << "forced locate to+roll " << ev->target_frame << endl;
329                         locate (ev->target_frame, true, true, false);
330                 } else {
331                         // cerr << "soft locate to+roll " << ev->target_frame << endl;
332                         start_locate (ev->target_frame, true, true, false);
333                 }
334                 _send_timecode_update = true;
335                 break;
336
337         case Event::LocateRollLocate:
338                 // locate is handled by ::request_roll_at_and_return()
339                 _requested_return_frame = ev->target_frame;
340                 request_locate (ev->target2_frame, true);
341                 break;
342
343
344         case Event::SetTransportSpeed:
345                 set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
346                 break;
347
348         case Event::PunchIn:
349                 // cerr << "PunchIN at " << transport_frame() << endl;
350                 if (config.get_punch_in() && record_status() == Enabled) {
351                         enable_record ();
352                 }
353                 remove = false;
354                 del = false;
355                 break;
356
357         case Event::PunchOut:
358                 // cerr << "PunchOUT at " << transport_frame() << endl;
359                 if (config.get_punch_out()) {
360                         step_back_from_record ();
361                 }
362                 remove = false;
363                 del = false;
364                 break;
365
366         case Event::StopOnce:
367                 if (!non_realtime_work_pending()) {
368                         stop_transport (ev->yes_or_no);
369                         _clear_event_type (Event::StopOnce);
370                 }
371                 remove = false;
372                 del = false;
373                 break;
374
375         case Event::RangeStop:
376                 if (!non_realtime_work_pending()) {
377                         stop_transport (ev->yes_or_no);
378                 }
379                 remove = false;
380                 del = false;
381                 break;
382
383         case Event::RangeLocate:
384                 start_locate (ev->target_frame, true, true, false);
385                 remove = false;
386                 del = false;
387                 break;
388
389         case Event::Overwrite:
390                 overwrite_some_buffers (static_cast<Diskstream*>(ev->ptr));
391                 break;
392
393         case Event::SetDiskstreamSpeed:
394                 set_diskstream_speed (static_cast<Diskstream*> (ev->ptr), ev->speed);
395                 break;
396
397         case Event::SetSyncSource:
398                 use_sync_source (ev->sync_source);
399                 break;
400
401         case Event::Audition:
402                 set_audition (ev->region);
403                 // drop reference to region
404                 ev->region.reset ();
405                 break;
406
407         case Event::InputConfigurationChange:
408                 add_post_transport_work (PostTransportInputChange);
409                 _butler->schedule_transport_work ();
410                 break;
411
412         case Event::SetPlayAudioRange:
413                 set_play_range (ev->audio_range, (ev->speed == 1.0f));
414                 break;
415
416         default:
417           fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
418                 /*NOTREACHED*/
419                 break;
420         };
421
422         if (remove) {
423                 del = del && !_remove_event (ev);
424         }
425
426         if (del) {
427                 delete ev;
428         }
429 }