Remove most using declarations from header files.
[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 std;
35 using namespace ARDOUR;
36 using namespace PBD;
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         "LocateRollLocate",
46         "SetLoop",
47         "PunchIn",
48         "PunchOut",
49         "RangeStop",
50         "RangeLocate",
51         "Overwrite",
52         "SetSlaveSource",
53         "Audition",
54         "InputConfigurationChange",
55         "SetAudioRange",
56         "SetMusicRange",
57         "SetPlayRange",
58         "StopOnce",
59         "AutoLoop"
60 };
61
62 void
63 Session::add_event (nframes_t frame, Event::Type type, nframes_t target_frame)
64 {
65         Event* ev = new Event (type, Event::Add, frame, target_frame, 0);
66         queue_event (ev);
67 }
68
69 void
70 Session::remove_event (nframes_t frame, Event::Type type)
71 {
72         Event* ev = new Event (type, Event::Remove, frame, 0, 0);
73         queue_event (ev);
74 }
75
76 void
77 Session::replace_event (Event::Type type, nframes_t frame, nframes_t target)
78 {
79         Event* ev = new Event (type, Event::Replace, frame, target, 0);
80         queue_event (ev);
81 }
82
83 void
84 Session::clear_events (Event::Type type)
85 {
86         Event* ev = new Event (type, Event::Clear, 0, 0, 0);
87         queue_event (ev);
88 }
89
90
91 void
92 Session::dump_events () const
93 {
94         cerr << "EVENT DUMP" << endl;
95         for (Events::const_iterator i = events.begin(); i != events.end(); ++i) {
96                 cerr << "\tat " << (*i)->action_frame << ' ' << (*i)->type << " target = " << (*i)->target_frame << endl;
97         }
98         cerr << "Next event: ";
99
100         if ((Events::const_iterator) next_event == events.end()) {
101                 cerr << "none" << endl;
102         } else {
103                 cerr << "at " << (*next_event)->action_frame << ' ' 
104                      << (*next_event)->type << " target = " 
105                      << (*next_event)->target_frame << endl;
106         }
107         cerr << "Immediate events pending:\n";
108         for (Events::const_iterator i = immediate_events.begin(); i != immediate_events.end(); ++i) {
109                 cerr << "\tat " << (*i)->action_frame << ' ' << (*i)->type << " target = " << (*i)->target_frame << endl;
110         }
111         cerr << "END EVENT_DUMP" << endl;
112 }
113
114 void
115 Session::queue_event (Event* ev)
116 {
117         if (_state_of_the_state & Loading) {
118                 merge_event (ev);
119         } else {
120                 pending_events.write (&ev, 1);
121         }
122 }
123
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                 
310                 /* except locates, which we have the capability to handle */
311
312                 if (ev->type != Event::Locate) {
313                         immediate_events.insert (immediate_events.end(), ev);
314                         _remove_event (ev);
315                         return;
316                 }
317         }
318
319         //printf("Processing event: %s\n", event_names[ev->type]);
320
321         switch (ev->type) {
322         case Event::SetLoop:
323                 set_play_loop (ev->yes_or_no);
324                 break;
325
326         case Event::AutoLoop:
327                 if (play_loop) {
328                         start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
329                 }
330                 remove = false;
331                 del = false;
332                 break;
333
334         case Event::Locate:
335                 if (ev->yes_or_no) {
336                         // cerr << "forced locate to " << ev->target_frame << endl;
337                         locate (ev->target_frame, false, true, false);
338                 } else {
339                         // cerr << "soft locate to " << ev->target_frame << endl;
340                         start_locate (ev->target_frame, false, true, false);
341                 }
342                 _send_smpte_update = true;
343                 break;
344
345         case Event::LocateRoll:
346                 if (ev->yes_or_no) {
347                         // cerr << "forced locate to+roll " << ev->target_frame << endl;
348                         locate (ev->target_frame, true, true, false);
349                 } else {
350                         // cerr << "soft locate to+roll " << ev->target_frame << endl;
351                         start_locate (ev->target_frame, true, true, false);
352                 }
353                 _send_smpte_update = true;
354                 break;
355
356         case Event::LocateRollLocate:
357                 // locate is handled by ::request_roll_at_and_return()
358                 _requested_return_frame = ev->target_frame;
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 }