change input/output button context menus for mixer strip to be non-additive: when...
[ardour.git] / libs / ardour / ardour / session_event.h
1 #ifndef __ardour_session_event_h__
2 #define __ardour_session_event_h__
3
4 #include <list>
5 #include <boost/function.hpp>
6 #include <boost/shared_ptr.hpp>
7
8 #include "pbd/pool.h"
9 #include "pbd/ringbuffer.h"
10 #include "pbd/event_loop.h"
11
12 #include "ardour/types.h"
13
14 namespace ARDOUR {
15
16 class Slave;
17 class Region;
18
19 class SessionEvent {
20 public:
21         enum Type {
22                 SetTransportSpeed,
23                 SetTrackSpeed,
24                 Locate,
25                 LocateRoll,
26                 LocateRollLocate,
27                 SetLoop,
28                 PunchIn,
29                 PunchOut,
30                 RangeStop,
31                 RangeLocate,
32                 Overwrite,
33                 SetSyncSource,
34                 Audition,
35                 InputConfigurationChange,
36                 SetPlayAudioRange,
37                 RealTimeOperation,
38                 AdjustPlaybackBuffering,
39                 AdjustCaptureBuffering,
40                 SetTimecodeTransmission,
41
42                 /* only one of each of these events can be queued at any one time */
43
44                 StopOnce,
45                 AutoLoop,
46                 AutoLoopDeclick,
47         };
48
49         enum Action {
50                 Add,
51                 Remove,
52                 Replace,
53                 Clear
54         };
55
56         Type       type;
57         Action     action;
58         framepos_t action_frame;
59         framepos_t target_frame;
60         double     speed;
61
62         union {
63                 void*        ptr;
64                 bool         yes_or_no;
65                 framepos_t  target2_frame;
66                 Slave*       slave;
67                 Route*       route;
68         };
69
70         union {
71                 bool second_yes_or_no;
72         };
73
74         union {
75                 bool third_yes_or_no;
76         };
77
78         /* 4 members to handle a multi-group event handled in RT context */
79
80         typedef boost::function<void (SessionEvent*)> RTeventCallback;
81
82         boost::shared_ptr<RouteList> routes;    /* apply to */
83         boost::function<void (void)> rt_slot;   /* what to call in RT context */
84         RTeventCallback              rt_return; /* called after rt_slot, with this event as an argument */
85         PBD::EventLoop*              event_loop;
86
87         std::list<AudioRange> audio_range;
88         std::list<MusicRange> music_range;
89
90         boost::shared_ptr<Region> region;
91
92     SessionEvent (Type t, Action a, framepos_t when, framepos_t where, double spd, bool yn = false, bool yn2 = false, bool yn3 = false)
93                 : type (t)
94                 , action (a)
95                 , action_frame (when)
96                 , target_frame (where)
97                 , speed (spd)
98                 , yes_or_no (yn)
99                 , second_yes_or_no (yn2)
100                 , third_yes_or_no (yn3)
101                 , event_loop (0) {}
102
103         void set_ptr (void* p) {
104                 ptr = p;
105         }
106
107         bool before (const SessionEvent& other) const {
108                 return action_frame < other.action_frame;
109         }
110
111         bool after (const SessionEvent& other) const {
112                 return action_frame > other.action_frame;
113         }
114
115         static bool compare (const SessionEvent *e1, const SessionEvent *e2) {
116                 return e1->before (*e2);
117         }
118
119         void* operator new (size_t);
120         void  operator delete (void *ptr, size_t /*size*/);
121
122         static const framepos_t Immediate = 0;
123
124         static void create_per_thread_pool (const std::string& n, uint32_t nitems);
125         static void init_event_pool ();
126
127 private:
128         static PerThreadPool* pool;
129         CrossThreadPool* own_pool;
130
131         friend class Butler;
132 };
133
134 class SessionEventManager {
135 public:
136         SessionEventManager () : pending_events (2048),
137                                  auto_loop_event(0), punch_out_event(0), punch_in_event(0) {}
138         virtual ~SessionEventManager() {}
139
140         virtual void queue_event (SessionEvent *ev) = 0;
141         void clear_events (SessionEvent::Type type);
142
143 protected:
144         RingBuffer<SessionEvent*> pending_events;
145         typedef std::list<SessionEvent *> Events;
146         Events           events;
147         Events           immediate_events;
148         Events::iterator next_event;
149
150         /* there can only ever be one of each of these */
151
152         SessionEvent *auto_loop_event;
153         SessionEvent *punch_out_event;
154         SessionEvent *punch_in_event;
155
156         void dump_events () const;
157         void merge_event (SessionEvent*);
158         void replace_event (SessionEvent::Type, framepos_t action_frame, framepos_t target = 0);
159         bool _replace_event (SessionEvent*);
160         bool _remove_event (SessionEvent *);
161         void _clear_event_type (SessionEvent::Type);
162
163         void add_event (framepos_t action_frame, SessionEvent::Type type, framepos_t target_frame = 0);
164         void remove_event (framepos_t frame, SessionEvent::Type type);
165
166         virtual void process_event(SessionEvent*) = 0;
167         virtual void set_next_event () = 0;
168 };
169
170 } /* namespace */
171
172 #endif /* __ardour_session_event_h__ */