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