change MidiPlaylist::dump() into ::render(); change type of initial argument
[ardour.git] / libs / ardour / ardour / midi_region.h
1 /*
2  * Copyright (C) 2006-2016 David Robillard <d@drobilla.net>
3  * Copyright (C) 2007-2017 Paul Davis <paul@linuxaudiosystems.com>
4  * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
5  * Copyright (C) 2016-2017 Nick Mainsbridge <mainsbridge@gmail.com>
6  * Copyright (C) 2016-2017 Robin Gareus <robin@gareus.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #ifndef __ardour_midi_region_h__
24 #define __ardour_midi_region_h__
25
26 #include <vector>
27
28 #include "temporal/beats.h"
29 #include "evoral/Range.hpp"
30
31 #include "pbd/string_convert.h"
32
33 #include "ardour/ardour.h"
34 #include "ardour/midi_cursor.h"
35 #include "ardour/region.h"
36
37 class XMLNode;
38
39 namespace ARDOUR {
40         namespace Properties {
41                 LIBARDOUR_API extern PBD::PropertyDescriptor<double> start_beats;
42                 LIBARDOUR_API extern PBD::PropertyDescriptor<double> length_beats;
43         }
44 }
45
46 namespace Evoral {
47 template<typename Time> class EventSink;
48 }
49
50 namespace ARDOUR {
51
52 class MidiChannelFilter;
53 class MidiFilter;
54 class MidiModel;
55 class MidiSource;
56 class MidiStateTracker;
57 class Playlist;
58 class Route;
59 class Session;
60
61 template<typename T> class MidiRingBuffer;
62
63 class LIBARDOUR_API MidiRegion : public Region
64 {
65   public:
66         static void make_property_quarks ();
67
68         ~MidiRegion();
69
70         bool do_export (std::string path) const;
71
72         boost::shared_ptr<MidiRegion> clone (std::string path = std::string()) const;
73         boost::shared_ptr<MidiRegion> clone (boost::shared_ptr<MidiSource>) const;
74
75         boost::shared_ptr<MidiSource> midi_source (uint32_t n=0) const;
76
77         /* Stub Readable interface */
78         virtual samplecnt_t read (Sample*, samplepos_t /*pos*/, samplecnt_t /*cnt*/, int /*channel*/) const { return 0; }
79         virtual samplecnt_t readable_length() const { return length(); }
80
81         samplecnt_t read_at (Evoral::EventSink<samplepos_t>& dst,
82                             samplepos_t position,
83                             samplecnt_t dur,
84                             Evoral::Range<samplepos_t>* loop_range,
85                             MidiCursor& cursor,
86                             uint32_t  chan_n = 0,
87                             NoteMode  mode = Sustained,
88                             MidiStateTracker* tracker = 0,
89                             MidiChannelFilter* filter = 0) const;
90
91         samplecnt_t master_read_at (MidiRingBuffer<samplepos_t>& dst,
92                                    samplepos_t position,
93                                    samplecnt_t dur,
94                                    Evoral::Range<samplepos_t>* loop_range,
95                                    MidiCursor& cursor,
96                                    uint32_t  chan_n = 0,
97                                    NoteMode  mode = Sustained) const;
98
99         XMLNode& state ();
100         int      set_state (const XMLNode&, int version);
101
102         int separate_by_channel (std::vector< boost::shared_ptr<Region> >&) const;
103
104         /* automation */
105
106         boost::shared_ptr<Evoral::Control> control(const Evoral::Parameter& id, bool create=false);
107
108         virtual boost::shared_ptr<const Evoral::Control> control(const Evoral::Parameter& id) const;
109
110         /* export */
111
112         boost::shared_ptr<MidiModel> model();
113         boost::shared_ptr<const MidiModel> model() const;
114
115         void fix_negative_start ();
116         double start_beats () const {return _start_beats; }
117         double length_beats () const {return _length_beats; }
118
119         void clobber_sources (boost::shared_ptr<MidiSource> source);
120
121         int render (Evoral::EventSink<samplepos_t>& dst,
122                     uint32_t                        chan_n,
123                     NoteMode                        mode,
124                     MidiChannelFilter*              filter) const;
125
126   protected:
127
128         virtual bool can_trim_start_before_source_start () const {
129                 return true;
130         }
131
132   private:
133         friend class RegionFactory;
134         PBD::Property<double> _start_beats;
135         PBD::Property<double> _length_beats;
136
137         MidiRegion (const SourceList&);
138         MidiRegion (boost::shared_ptr<const MidiRegion>);
139         MidiRegion (boost::shared_ptr<const MidiRegion>, ARDOUR::MusicSample offset);
140
141         samplecnt_t _read_at (const SourceList&, Evoral::EventSink<samplepos_t>& dst,
142                              samplepos_t position,
143                              samplecnt_t dur,
144                              Evoral::Range<samplepos_t>* loop_range,
145                              MidiCursor& cursor,
146                              uint32_t chan_n = 0,
147                              NoteMode mode = Sustained,
148                              MidiStateTracker* tracker = 0,
149                              MidiChannelFilter* filter = 0) const;
150
151         void register_properties ();
152         void post_set (const PBD::PropertyChange&);
153
154         void recompute_at_start ();
155         void recompute_at_end ();
156
157         void set_position_internal (samplepos_t pos, bool allow_bbt_recompute, const int32_t sub_num);
158         void set_position_music_internal (double qn);
159         void set_length_internal (samplecnt_t len, const int32_t sub_num);
160         void set_start_internal (samplecnt_t, const int32_t sub_num);
161         void trim_to_internal (samplepos_t position, samplecnt_t length, const int32_t sub_num);
162         void update_length_beats (const int32_t sub_num);
163
164         void model_changed ();
165         void model_shifted (double qn_distance);
166         void model_automation_state_changed (Evoral::Parameter const &);
167
168         void set_start_beats_from_start_samples ();
169         void update_after_tempo_map_change (bool send_change = true);
170
171         std::set<Evoral::Parameter> _filtered_parameters; ///< parameters that we ask our source not to return when reading
172         PBD::ScopedConnection _model_connection;
173         PBD::ScopedConnection _model_shift_connection;
174         PBD::ScopedConnection _source_connection;
175         PBD::ScopedConnection _model_contents_connection;
176         bool _ignore_shift;
177 };
178
179 } /* namespace ARDOUR */
180
181
182 #endif /* __ardour_midi_region_h__ */