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