Committed filthy mess of a working copy solely for moving between machines.
[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     $Id$
19 */
20
21 #include <cmath>
22 #include <unistd.h>
23
24 #include <ardour/timestamps.h>
25
26 #include <pbd/error.h>
27 #include <pbd/lockmonitor.h>
28
29 #include <ardour/ardour.h>
30 #include <ardour/session.h>
31 #include <ardour/diskstream.h>
32
33 #include "i18n.h"
34
35 using namespace ARDOUR;
36 //using namespace sigc;
37
38 MultiAllocSingleReleasePool Session::Event::pool ("event", sizeof (Session::Event), 512);
39
40 static const char* event_names[] = {
41         "SetTransportSpeed",
42         "SetDiskstreamSpeed",
43         "Locate",
44         "LocateRoll",
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 (jack_nframes_t frame, Event::Type type, jack_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 (jack_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, jack_nframes_t frame, jack_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 /* [DR] Always called from audio thread? */
124 void
125 Session::merge_event (Event* ev)
126 {
127         switch (ev->action) {
128         case Event::Remove:
129                 _remove_event (ev);
130                 delete ev;
131                 return;
132
133         case Event::Replace:
134                 _replace_event (ev);
135                 return;
136
137         case Event::Clear:
138                 _clear_event_type (ev->type);
139                 delete ev;
140                 return;
141                 
142         case Event::Add:
143                 break;
144         }
145
146         /* try to handle immediate events right here */
147
148         if (ev->action_frame == 0) {
149                 process_event (ev);
150                 return;
151         }
152         
153         switch (ev->type) {
154         case Event::AutoLoop:
155         case Event::StopOnce:
156                 _clear_event_type (ev->type);
157                 break;
158
159         default:
160                 for (Events::iterator i = events.begin(); i != events.end(); ++i) {
161                         if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
162                           error << string_compose(_("Session: cannot have two events of type %1 at the same frame (%2)."), 
163                                                  event_names[ev->type], ev->action_frame) << endmsg;
164                                 return;
165                         }
166                 }
167         }
168
169         events.insert (events.begin(), ev);
170         events.sort (Event::compare);
171         next_event = events.begin();
172         set_next_event ();
173 }
174
175 /** @return true when @a ev is deleted. */
176 bool
177 Session::_replace_event (Event* ev)
178 {
179         bool ret = false;
180         Events::iterator i;
181
182         /* private, used only for events that can only exist once in the queue */
183
184         for (i = events.begin(); i != events.end(); ++i) {
185                 if ((*i)->type == ev->type) {
186                         (*i)->action_frame = ev->action_frame;
187                         (*i)->target_frame = ev->target_frame;
188                         if ((*i) == ev) {
189                                 ret = true;
190                         }
191                         delete ev;
192                         break;
193                 }
194         }
195
196         if (i == events.end()) {
197                 events.insert (events.begin(), ev);
198         }
199
200         events.sort (Event::compare);
201         next_event = events.end();
202         set_next_event ();
203
204         return ret;
205 }
206
207 /** @return true when @a ev is deleted. */
208 bool
209 Session::_remove_event (Session::Event* ev)
210 {
211         bool ret = false;
212         Events::iterator i;
213         
214         for (i = events.begin(); i != events.end(); ++i) {
215                 if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
216                         if ((*i) == ev) {
217                                 ret = true;
218                         }
219
220                         delete *i;
221                         if (i == next_event) {
222                                 ++next_event;
223                         }
224                         events.erase (i);
225                         break;
226                 }
227         }
228
229         if (i != events.end()) {
230                 set_next_event ();
231         }
232
233         return ret;
234 }
235
236 void
237 Session::_clear_event_type (Event::Type type)
238 {
239         Events::iterator i, tmp;
240         
241         for (i = events.begin(); i != events.end(); ) {
242
243                 tmp = i;
244                 ++tmp;
245
246                 if ((*i)->type == type) {
247                         delete *i;
248                         if (i == next_event) {
249                                 ++next_event;
250                         }
251                         events.erase (i);
252                 }
253
254                 i = tmp;
255         }
256
257         for (i = immediate_events.begin(); i != immediate_events.end(); ) {
258
259                 tmp = i;
260                 ++tmp;
261
262                 if ((*i)->type == type) {
263                         delete *i;
264                         immediate_events.erase (i);
265                 }
266
267                 i = tmp;
268         }
269
270         set_next_event ();
271 }
272
273 void
274 Session::set_next_event ()
275 {
276         if (events.empty()) {
277                 next_event = events.end();
278                 return;
279         } 
280
281         if (next_event == events.end()) {
282                 next_event = events.begin();
283         }
284
285         if ((*next_event)->action_frame > _transport_frame) {
286                 next_event = events.begin();
287         }
288
289         for (; next_event != events.end(); ++next_event) {
290                 if ((*next_event)->action_frame >= _transport_frame) {
291                         break;
292                 }
293         }
294 }
295
296 void
297 Session::process_event (Event* ev)
298 {
299         bool remove = true;
300         bool del = true;
301
302         /* if we're in the middle of a state change (i.e. waiting
303            for the butler thread to complete the non-realtime
304            part of the change), we'll just have to queue this
305            event for a time when the change is complete.
306         */
307
308         if (non_realtime_work_pending()) {
309                 immediate_events.insert (immediate_events.end(), ev);
310                 _remove_event (ev);
311                 return;
312         }
313
314         // FIXME [DR]
315         printf("Processing event: %s\n", event_names[ev->type]);
316
317         switch (ev->type) {
318         case Event::SetLoop:
319                 set_auto_loop (ev->yes_or_no);
320                 break;
321
322         case Event::Locate:
323                 if (ev->yes_or_no) {
324                         // cerr << "forced locate to " << ev->target_frame << endl;
325                         locate (ev->target_frame, false, true, false);
326                 } else {
327                         // cerr << "soft locate to " << ev->target_frame << endl;
328                         start_locate (ev->target_frame, false, true, false);
329                 }
330                 _send_smpte_update = true;
331                 break;
332
333         case Event::LocateRoll:
334                 if (ev->yes_or_no) {
335                         // cerr << "forced locate to+roll " << ev->target_frame << endl;
336                         locate (ev->target_frame, true, true, false);
337                 } else {
338                         // cerr << "soft locate to+roll " << ev->target_frame << endl;
339                         start_locate (ev->target_frame, true, true, false);
340                 }
341                 _send_smpte_update = true;
342                 break;
343
344         case Event::SetTransportSpeed:
345                 set_transport_speed (ev->speed, ev->yes_or_no);
346                 break;
347                 
348         case Event::PunchIn:
349                 // cerr << "PunchIN at " << transport_frame() << endl;
350                 if (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 (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::AutoLoop:
390                 if (auto_loop) {
391                         start_locate (ev->target_frame, true, false, seamless_loop);
392                 }
393                 remove = false;
394                 del = false;
395                 break;
396
397         case Event::Overwrite:
398                 overwrite_some_buffers (static_cast<DiskStream*>(ev->ptr));
399                 break;
400
401         case Event::SetDiskstreamSpeed:
402                 set_diskstream_speed (static_cast<DiskStream*> (ev->ptr), ev->speed);
403                 break;
404
405         case Event::SetSlaveSource:
406                 set_slave_source (ev->slave, ev->target_frame);
407                 break;
408
409         case Event::Audition:
410                 set_audition (static_cast<AudioRegion*> (ev->ptr));
411                 break;
412
413         case Event::InputConfigurationChange:
414                 post_transport_work = PostTransportWork (post_transport_work | PostTransportInputChange);
415                 schedule_butler_transport_work ();
416                 break;
417
418         case Event::SetAudioRange:
419                 current_audio_range = ev->audio_range;
420                 setup_auto_play ();
421                 break;
422
423         case Event::SetPlayRange:
424                 set_play_range (ev->yes_or_no);
425                 break;
426
427         default:
428           fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
429                 /*NOTREACHED*/
430                 break;
431         };
432
433         if (remove) {
434                 del = del && !_remove_event (ev);
435         }
436
437         if (del) {
438                 delete ev;
439         }
440 }