summaryrefslogtreecommitdiff
path: root/libs/ardour/ardour/session_event.h
blob: 8bb160b90e2abde07b308d7f9334028790043557 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/*
    Copyright (C) 2012 Paul Davis

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#ifndef __ardour_session_event_h__
#define __ardour_session_event_h__

#include <list>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>

#include "pbd/pool.h"
#include "pbd/ringbuffer.h"
#include "pbd/event_loop.h"

#include "ardour/libardour_visibility.h"
#include "ardour/types.h"

namespace ARDOUR {

class Slave;
class Region;

class LIBARDOUR_API SessionEvent {
public:
	enum Type {
		SetTransportSpeed,
		SetTrackSpeed,
		Locate,
		LocateRoll,
		LocateRollLocate,
		SetLoop,
		PunchIn,
		PunchOut,
		RangeStop,
		RangeLocate,
		Overwrite,
		SetSyncSource,
		Audition,
		InputConfigurationChange,
		SetPlayAudioRange,
		CancelPlayAudioRange,
		RealTimeOperation,
		AdjustPlaybackBuffering,
		AdjustCaptureBuffering,
		SetTimecodeTransmission,
		Skip,

		/* only one of each of these events can be queued at any one time */

		StopOnce,
		AutoLoop,
		AutoLoopDeclick,
	};

	enum Action {
		Add,
		Remove,
		Replace,
		Clear
	};

	Type       type;
	Action     action;
	framepos_t action_frame;
	framepos_t target_frame;
	double     speed;

	union {
		void*        ptr;
		bool         yes_or_no;
		framepos_t   target2_frame;
		Slave*       slave;
		Route*       route;
	};

	union {
		bool second_yes_or_no;
		double control_value;
	};

	union {
		bool third_yes_or_no;
	};

	/* 5 members to handle a multi-group event handled in RT context */

	typedef boost::function<void (SessionEvent*)> RTeventCallback;

	boost::shared_ptr<ControlList> controls; /* apply to */
	boost::shared_ptr<RouteList> routes;     /* apply to */
	boost::function<void (void)> rt_slot;    /* what to call in RT context */
	RTeventCallback              rt_return;  /* called after rt_slot, with this event as an argument */
	PBD::EventLoop*              event_loop;

	std::list<AudioRange> audio_range;
	std::list<MusicRange> music_range;

	boost::shared_ptr<Region> region;

	SessionEvent (Type t, Action a, framepos_t when, framepos_t where, double spd, bool yn = false, bool yn2 = false, bool yn3 = false);

	void set_ptr (void* p) {
		ptr = p;
	}

	bool before (const SessionEvent& other) const {
		return action_frame < other.action_frame;
	}

	bool after (const SessionEvent& other) const {
		return action_frame > other.action_frame;
	}

	static bool compare (const SessionEvent *e1, const SessionEvent *e2) {
		return e1->before (*e2);
	}

	void* operator new (size_t);
	void  operator delete (void *ptr, size_t /*size*/);

	static const framepos_t Immediate = -1;

	static bool has_per_thread_pool ();
	static void create_per_thread_pool (const std::string& n, uint32_t nitems);
	static void init_event_pool ();

	CrossThreadPool* event_pool() const { return own_pool; }

private:
	static PerThreadPool* pool;
	CrossThreadPool* own_pool;

	friend class Butler;
};

class SessionEventManager {
public:
	SessionEventManager () : pending_events (2048),
	                         auto_loop_event(0), punch_out_event(0), punch_in_event(0) {}
	virtual ~SessionEventManager() {}

	virtual void queue_event (SessionEvent *ev) = 0;
	void clear_events (SessionEvent::Type type);
	void clear_events (SessionEvent::Type type, boost::function<void (void)> after);

protected:
	RingBuffer<SessionEvent*> pending_events;
	typedef std::list<SessionEvent *> Events;
	Events           events;
	Events           immediate_events;
	Events::iterator next_event;

	/* there can only ever be one of each of these */

	SessionEvent *auto_loop_event;
	SessionEvent *punch_out_event;
	SessionEvent *punch_in_event;

	void dump_events () const;
	void merge_event (SessionEvent*);
	void replace_event (SessionEvent::Type, framepos_t action_frame, framepos_t target = 0);
	bool _replace_event (SessionEvent*);
	bool _remove_event (SessionEvent *);
	void _clear_event_type (SessionEvent::Type);

	void add_event (framepos_t action_frame, SessionEvent::Type type, framepos_t target_frame = 0);
	void remove_event (framepos_t frame, SessionEvent::Type type);

	virtual void process_event(SessionEvent*) = 0;
	virtual void set_next_event () = 0;
};

} /* namespace */

#endif /* __ardour_session_event_h__ */