summaryrefslogtreecommitdiff
path: root/libs/ardour/ardour/session_event.h
blob: 79acec3bcf9990b532e95b25033c2836e3fe5527 (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
192
193
194
195
196
/*
 * Copyright (C) 2009-2018 Paul Davis <paul@linuxaudiosystems.com>
 * Copyright (C) 2010-2012 Carl Hetherington <carl@carlh.net>
 * Copyright (C) 2010-2012 David Robillard <d@drobilla.net>
 * Copyright (C) 2015-2018 Robin Gareus <robin@gareus.org>
 *
 * 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef __ardour_session_event_h__
#define __ardour_session_event_h__

#include <list>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_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 TransportMaster;
class Region;
class Track;

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

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

		AutoLoop,
	};

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

	Type       type;
	Action     action;
	samplepos_t action_sample;
	samplepos_t target_sample;
	double     speed;

	union {
		bool             yes_or_no;
		samplepos_t      target2_sample;
		OverwriteReason  overwrite;
	};

	boost::weak_ptr<Track> track;

	union {
		bool second_yes_or_no;
		double control_value;
		LocateTransportDisposition locate_transport_disposition;
	};

	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;
	boost::shared_ptr<TransportMaster> transport_master;

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

	void set_track (boost::shared_ptr<Track> t) {
		track = t;
	}

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

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

	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 samplepos_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:
	PBD::RingBuffer<SessionEvent*> pending_events;
	typedef std::list<SessionEvent *> Events;
	Events           events;
	Events           immediate_events;
	Events::iterator next_event;

	Glib::Threads::Mutex rb_write_lock;

	/* 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, samplepos_t action_sample, samplepos_t target = 0);
	bool _replace_event (SessionEvent*);
	bool _remove_event (SessionEvent *);
	void _clear_event_type (SessionEvent::Type);

	void add_event (samplepos_t action_sample, SessionEvent::Type type, samplepos_t target_sample = 0);
	void remove_event (samplepos_t sample, SessionEvent::Type type);

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

} /* namespace */

#endif /* __ardour_session_event_h__ */