summaryrefslogtreecommitdiff
path: root/libs/ardour/ardour/session_event.h
blob: 2ce2d5225ad4fde75fba90fef8bda7212fe36999 (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
#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/types.h"

namespace ARDOUR {

class Slave;
class Region;

struct SessionEvent {
    enum Type {
	    SetTransportSpeed,
	    SetDiskstreamSpeed,
	    Locate,
	    LocateRoll,
	    LocateRollLocate,
	    SetLoop,
	    PunchIn,
	    PunchOut,
	    RangeStop,
	    RangeLocate,
	    Overwrite,
	    SetSyncSource,
	    Audition,
	    InputConfigurationChange,
	    SetPlayAudioRange,
	    RealTimeOperation,

	    /* only one of each of these events can be queued at any one time */
	    
	    StopOnce,
	    AutoLoop
    };
    
    enum Action {
	    Add,
	    Remove,
	    Replace,
	    Clear
    };
    
    Type             type;
    Action           action;
    nframes64_t      action_frame;
    nframes64_t      target_frame;
    double           speed;
    
    union {
	void*        ptr;
	bool         yes_or_no;
	nframes64_t  target2_frame;
	Slave*       slave;
	Route*       route;
    };
    
    union {
	bool second_yes_or_no;
    };

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

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

    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, nframes_t when, nframes_t where, double spd, bool yn = false, bool yn2 = false)
	    : type (t)
	    , action (a)
	    , action_frame (when)
	    , target_frame (where)
	    , speed (spd)
	    , yes_or_no (yn)
	    , second_yes_or_no (yn2)
	    , event_loop (0) {}

    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 nframes_t Immediate = 0;
    
    static void create_per_thread_pool (const std::string& n, unsigned long nitems);
    static void init_event_pool ();

private:
    static PerThreadPool* pool;
    CrossThreadPool* own_pool;
};

class SessionEventManager {
   public:
        SessionEventManager () : pending_events (2048){}
        virtual ~SessionEventManager() {}

        virtual void queue_event (SessionEvent *ev) = 0; 
	void clear_events (SessionEvent::Type type);
        
  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, nframes64_t action_frame, nframes64_t target = 0);
	bool _replace_event (SessionEvent*);
	bool _remove_event (SessionEvent *);
	void _clear_event_type (SessionEvent::Type);

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

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

} /* namespace */

#endif /* __ardour_session_event_h__ */