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