1 /* 2 * Copyright (C) 2009-2018 Paul Davis <paul@linuxaudiosystems.com> 3 * Copyright (C) 2010-2012 Carl Hetherington <carl@carlh.net> 4 * Copyright (C) 2010-2012 David Robillard <d@drobilla.net> 5 * Copyright (C) 2015-2018 Robin Gareus <robin@gareus.org> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 */ 21 22 #ifndef __ardour_session_event_h__ 23 #define __ardour_session_event_h__ 24 25 #include <list> 26 #include <boost/function.hpp> 27 #include <boost/shared_ptr.hpp> 28 #include <boost/weak_ptr.hpp> 29 30 #include "pbd/pool.h" 31 #include "pbd/ringbuffer.h" 32 #include "pbd/event_loop.h" 33 34 #include "ardour/libardour_visibility.h" 35 #include "ardour/types.h" 36 37 namespace ARDOUR { 38 39 class TransportMaster; 40 class Region; 41 class Track; 42 43 class LIBARDOUR_API SessionEvent { 44 public: 45 enum Type { 46 SetTransportSpeed, 47 Locate, 48 LocateRoll, 49 LocateRollLocate, 50 SetLoop, 51 PunchIn, 52 PunchOut, 53 RangeStop, 54 RangeLocate, 55 Overwrite, 56 OverwriteAll, 57 Audition, 58 SetPlayAudioRange, 59 CancelPlayAudioRange, 60 RealTimeOperation, 61 AdjustPlaybackBuffering, 62 AdjustCaptureBuffering, 63 SetTimecodeTransmission, 64 Skip, 65 SetTransportMaster, 66 StartRoll, 67 EndRoll, 68 69 /* only one of each of these events can be queued at any one time */ 70 71 AutoLoop, 72 }; 73 74 enum Action { 75 Add, 76 Remove, 77 Replace, 78 Clear 79 }; 80 81 Type type; 82 Action action; 83 samplepos_t action_sample; 84 samplepos_t target_sample; 85 double speed; 86 87 union { 88 bool yes_or_no; 89 samplepos_t target2_sample; 90 OverwriteReason overwrite; 91 }; 92 93 boost::weak_ptr<Track> track; 94 95 union { 96 bool second_yes_or_no; 97 double control_value; 98 LocateTransportDisposition locate_transport_disposition; 99 }; 100 101 union { 102 bool third_yes_or_no; 103 }; 104 105 /* 5 members to handle a multi-group event handled in RT context */ 106 107 typedef boost::function<void (SessionEvent*)> RTeventCallback; 108 109 boost::shared_ptr<ControlList> controls; /* apply to */ 110 boost::shared_ptr<RouteList> routes; /* apply to */ 111 boost::function<void (void)> rt_slot; /* what to call in RT context */ 112 RTeventCallback rt_return; /* called after rt_slot, with this event as an argument */ 113 PBD::EventLoop* event_loop; 114 115 std::list<AudioRange> audio_range; 116 std::list<MusicRange> music_range; 117 118 boost::shared_ptr<Region> region; 119 boost::shared_ptr<TransportMaster> transport_master; 120 121 SessionEvent (Type t, Action a, samplepos_t when, samplepos_t where, double spd, bool yn = false, bool yn2 = false, bool yn3 = false); 122 set_track(boost::shared_ptr<Track> t)123 void set_track (boost::shared_ptr<Track> t) { 124 track = t; 125 } 126 before(const SessionEvent & other)127 bool before (const SessionEvent& other) const { 128 return action_sample < other.action_sample; 129 } 130 after(const SessionEvent & other)131 bool after (const SessionEvent& other) const { 132 return action_sample > other.action_sample; 133 } 134 compare(const SessionEvent * e1,const SessionEvent * e2)135 static bool compare (const SessionEvent *e1, const SessionEvent *e2) { 136 return e1->before (*e2); 137 } 138 139 void* operator new (size_t); 140 void operator delete (void *ptr, size_t /*size*/); 141 142 static const samplepos_t Immediate = -1; 143 144 static bool has_per_thread_pool (); 145 static void create_per_thread_pool (const std::string& n, uint32_t nitems); 146 static void init_event_pool (); 147 event_pool()148 CrossThreadPool* event_pool() const { return own_pool; } 149 150 private: 151 static PerThreadPool* pool; 152 CrossThreadPool* own_pool; 153 154 friend class Butler; 155 }; 156 157 class SessionEventManager { 158 public: SessionEventManager()159 SessionEventManager () : pending_events (2048), 160 auto_loop_event(0), punch_out_event(0), punch_in_event(0) {} ~SessionEventManager()161 virtual ~SessionEventManager() {} 162 163 virtual void queue_event (SessionEvent *ev) = 0; 164 void clear_events (SessionEvent::Type type); 165 void clear_events (SessionEvent::Type type, boost::function<void (void)> after); 166 167 protected: 168 PBD::RingBuffer<SessionEvent*> pending_events; 169 typedef std::list<SessionEvent *> Events; 170 Events events; 171 Events immediate_events; 172 Events::iterator next_event; 173 174 Glib::Threads::Mutex rb_write_lock; 175 176 /* there can only ever be one of each of these */ 177 178 SessionEvent *auto_loop_event; 179 SessionEvent *punch_out_event; 180 SessionEvent *punch_in_event; 181 182 void dump_events () const; 183 void merge_event (SessionEvent*); 184 void replace_event (SessionEvent::Type, samplepos_t action_sample, samplepos_t target = 0); 185 bool _replace_event (SessionEvent*); 186 bool _remove_event (SessionEvent *); 187 void _clear_event_type (SessionEvent::Type); 188 189 void add_event (samplepos_t action_sample, SessionEvent::Type type, samplepos_t target_sample = 0); 190 void remove_event (samplepos_t sample, SessionEvent::Type type); 191 192 virtual void process_event(SessionEvent*) = 0; 193 virtual void set_next_event () = 0; 194 }; 195 196 } /* namespace */ 197 198 #endif /* __ardour_session_event_h__ */ 199