Optimize plugin-processing for non-automated params
[ardour.git] / libs / ardour / ardour / midi_source.h
1 /*
2     Copyright (C) 2006 Paul Davis
3     Author: David Robillard
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #ifndef __ardour_midi_source_h__
21 #define __ardour_midi_source_h__
22
23 #include <string>
24 #include <time.h>
25 #include <glibmm/threads.h>
26 #include <boost/enable_shared_from_this.hpp>
27 #include "pbd/stateful.h"
28 #include "pbd/xml++.h"
29 #include "evoral/Sequence.hpp"
30 #include "evoral/Range.hpp"
31 #include "ardour/ardour.h"
32 #include "ardour/buffer.h"
33 #include "ardour/midi_cursor.h"
34 #include "ardour/source.h"
35 #include "ardour/beats_samples_converter.h"
36
37 namespace ARDOUR {
38
39 class MidiChannelFilter;
40 class MidiModel;
41 class MidiStateTracker;
42
43 template<typename T> class MidiRingBuffer;
44
45 /** Source for MIDI data */
46 class LIBARDOUR_API MidiSource : virtual public Source, public boost::enable_shared_from_this<MidiSource>
47 {
48   public:
49         typedef Temporal::Beats TimeType;
50
51         MidiSource (Session& session, std::string name, Source::Flag flags = Source::Flag(0));
52         MidiSource (Session& session, const XMLNode&);
53         virtual ~MidiSource ();
54
55         /** Write the data in the given time range to another MidiSource
56          * \param newsrc MidiSource to which data will be written. Should be a
57          *        new, empty source. If it already has contents, the results are
58          *        undefined. Source must be writable.
59          * \param begin time of earliest event that can be written.
60          * \param end time of latest event that can be written.
61          * \return zero on success, non-zero if the write failed for any reason.
62          */
63         int write_to (const Lock&                   lock,
64                       boost::shared_ptr<MidiSource> newsrc,
65                       Temporal::Beats               begin = Temporal::Beats(),
66                       Temporal::Beats               end   = std::numeric_limits<Temporal::Beats>::max());
67
68         /** Export the midi data in the given time range to another MidiSource
69          * \param newsrc MidiSource to which data will be written. Should be a
70          *        new, empty source. If it already has contents, the results are
71          *        undefined. Source must be writable.
72          * \param begin time of earliest event that can be written.
73          * \param end time of latest event that can be written.
74          * \return zero on success, non-zero if the write failed for any reason.
75          */
76         int export_write_to (const Lock&                   lock,
77                              boost::shared_ptr<MidiSource> newsrc,
78                              Temporal::Beats               begin,
79                              Temporal::Beats               end);
80
81         /** Read the data in a given time range from the MIDI source.
82          * All time stamps in parameters are in audio samples (even if the source has tempo time).
83          * \param dst Ring buffer where read events are written.
84          * \param source_start Start position of the SOURCE in this read context.
85          * \param start Start of range to be read.
86          * \param cnt Length of range to be read (in audio samples).
87          * \param loop_range If non-null, all event times will be mapped into this loop range.
88          * \param tracker an optional pointer to MidiStateTracker object, for note on/off tracking.
89          * \param filtered Parameters whose MIDI messages will not be returned.
90          */
91         virtual samplecnt_t midi_read (const Lock&                        lock,
92                                       Evoral::EventSink<samplepos_t>&     dst,
93                                       samplepos_t                         source_start,
94                                       samplepos_t                         start,
95                                       samplecnt_t                         cnt,
96                                       Evoral::Range<samplepos_t>*         loop_range,
97                                       MidiCursor&                        cursor,
98                                       MidiStateTracker*                  tracker,
99                                       MidiChannelFilter*                 filter,
100                                       const std::set<Evoral::Parameter>& filtered,
101                                       const double                       pulse,
102                                       const double                       start_beats) const;
103
104         /** Write data from a MidiRingBuffer to this source.
105          *  @param source Source to read from.
106          *  @param source_start This source's start position in session samples.
107          *  @param cnt The length of time to write.
108          */
109         virtual samplecnt_t midi_write (const Lock&                 lock,
110                                        MidiRingBuffer<samplepos_t>& src,
111                                        samplepos_t                  source_start,
112                                        samplecnt_t                  cnt);
113
114         /** Append a single event with a timestamp in beats.
115          *
116          * Caller must ensure that the event is later than the last written event.
117          */
118         virtual void append_event_beats(const Lock&                         lock,
119                                         const Evoral::Event<Temporal::Beats>& ev) = 0;
120
121         /** Append a single event with a timestamp in samples.
122          *
123          * Caller must ensure that the event is later than the last written event.
124          */
125         virtual void append_event_samples(const Lock&                      lock,
126                                          const Evoral::Event<samplepos_t>& ev,
127                                          samplepos_t                       source_start) = 0;
128
129         virtual bool       empty () const;
130         virtual samplecnt_t length (samplepos_t pos) const;
131         virtual void       update_length (samplecnt_t);
132
133         virtual void mark_streaming_midi_write_started (const Lock& lock, NoteMode mode);
134         virtual void mark_streaming_write_started (const Lock& lock);
135         virtual void mark_streaming_write_completed (const Lock& lock);
136
137         /** Mark write starting with the given time parameters.
138          *
139          * This is called by MidiDiskStream::process before writing to the capture
140          * buffer which will be later read by midi_read().
141          *
142          * @param position The timeline position the source now starts at.
143          * @param capture_length The current length of the capture, which may not
144          * be zero if record is armed while rolling.
145          * @param loop_length The loop length if looping, otherwise zero.
146          */
147         void mark_write_starting_now (samplecnt_t position,
148                                       samplecnt_t capture_length,
149                                       samplecnt_t loop_length);
150
151         /* like ::mark_streaming_write_completed() but with more arguments to
152          * allow control over MIDI-specific behaviour. Expected to be used only
153          * when recording actual MIDI input, rather then when importing files
154          * etc.
155          */
156         virtual void mark_midi_streaming_write_completed (
157                 const Lock&                                      lock,
158                 Evoral::Sequence<Temporal::Beats>::StuckNoteOption stuck_option,
159                 Temporal::Beats                                  when = Temporal::Beats());
160
161         virtual void session_saved();
162
163         std::string captured_for() const               { return _captured_for; }
164         void        set_captured_for (std::string str) { _captured_for = str; }
165
166         XMLNode& get_state ();
167         int set_state (const XMLNode&, int version);
168
169         bool length_mutable() const { return true; }
170
171         void     set_length_beats(TimeType l) { _length_beats = l; }
172         TimeType length_beats() const         { return _length_beats; }
173
174         virtual void load_model(const Glib::Threads::Mutex::Lock& lock, bool force_reload=false) = 0;
175         virtual void destroy_model(const Glib::Threads::Mutex::Lock& lock) = 0;
176
177         /** Reset cached information (like iterators) when things have changed.
178          * @param lock Source lock, which must be held by caller.
179          */
180         void invalidate(const Glib::Threads::Mutex::Lock& lock);
181
182         /** Thou shalt not emit this directly, use invalidate() instead. */
183         mutable PBD::Signal1<void, bool> Invalidated;
184
185         void set_note_mode(const Glib::Threads::Mutex::Lock& lock, NoteMode mode);
186
187         boost::shared_ptr<MidiModel> model() { return _model; }
188         void set_model(const Glib::Threads::Mutex::Lock& lock, boost::shared_ptr<MidiModel>);
189         void drop_model(const Glib::Threads::Mutex::Lock& lock);
190
191         Evoral::ControlList::InterpolationStyle interpolation_of (Evoral::Parameter) const;
192         void set_interpolation_of (Evoral::Parameter, Evoral::ControlList::InterpolationStyle);
193         void copy_interpolation_from (boost::shared_ptr<MidiSource>);
194         void copy_interpolation_from (MidiSource *);
195
196         AutoState automation_state_of (Evoral::Parameter) const;
197         void set_automation_state_of (Evoral::Parameter, AutoState);
198         void copy_automation_state_from (boost::shared_ptr<MidiSource>);
199         void copy_automation_state_from (MidiSource *);
200
201         /** Emitted when a different MidiModel is set */
202         PBD::Signal0<void> ModelChanged;
203         /** Emitted when a parameter's interpolation style is changed */
204         PBD::Signal2<void, Evoral::Parameter, Evoral::ControlList::InterpolationStyle> InterpolationChanged;
205         /** Emitted when a parameter's automation state is changed */
206         PBD::Signal2<void, Evoral::Parameter, AutoState> AutomationStateChanged;
207
208   protected:
209         virtual void flush_midi(const Lock& lock) = 0;
210
211         virtual samplecnt_t read_unlocked (const Lock&                    lock,
212                                           Evoral::EventSink<samplepos_t>& dst,
213                                           samplepos_t                     position,
214                                           samplepos_t                     start,
215                                           samplecnt_t                     cnt,
216                                           Evoral::Range<samplepos_t>*     loop_range,
217                                           MidiStateTracker*              tracker,
218                                           MidiChannelFilter*             filter) const = 0;
219
220         /** Write data to this source from a MidiRingBuffer.
221          *  @param source Buffer to read from.
222          *  @param position This source's start position in session samples.
223          *  @param cnt The duration of this block to write for.
224          */
225         virtual samplecnt_t write_unlocked (const Lock&                 lock,
226                                            MidiRingBuffer<samplepos_t>& source,
227                                            samplepos_t                  position,
228                                            samplecnt_t                  cnt) = 0;
229
230         std::string _captured_for;
231
232         boost::shared_ptr<MidiModel> _model;
233         bool                         _writing;
234
235         Temporal::Beats _length_beats;
236
237         /** The total duration of the current capture. */
238         samplepos_t _capture_length;
239
240         /** Length of transport loop during current capture, or zero. */
241         samplepos_t _capture_loop_length;
242
243         /** Map of interpolation styles to use for Parameters; if they are not in this map,
244          *  the correct interpolation style can be obtained from EventTypeMap::interpolation_of ()
245          */
246         typedef std::map<Evoral::Parameter, Evoral::ControlList::InterpolationStyle> InterpolationStyleMap;
247         InterpolationStyleMap _interpolation_style;
248
249         /** Map of automation states to use for Parameters; if they are not in this map,
250          *  the correct automation state is Off.
251          */
252         typedef std::map<Evoral::Parameter, AutoState> AutomationStateMap;
253         AutomationStateMap  _automation_state;
254 };
255
256 }
257
258 #endif /* __ardour_midi_source_h__ */