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.h"
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 class ThawList;
61 
62 template<typename T> class MidiRingBuffer;
63 
64 class LIBARDOUR_API MidiRegion : public Region
65 {
66   public:
67 	static void make_property_quarks ();
68 
69 	~MidiRegion();
70 
71 	bool do_export (std::string path) const;
72 
73 	boost::shared_ptr<MidiRegion> clone (std::string path = std::string()) const;
74 	boost::shared_ptr<MidiRegion> clone (boost::shared_ptr<MidiSource>, ThawList* tl = 0) const;
75 
76 	boost::shared_ptr<MidiSource> midi_source (uint32_t n=0) const;
77 
78 	/* Stub Readable interface */
read(Sample *,samplepos_t,samplecnt_t,int)79 	virtual samplecnt_t read (Sample*, samplepos_t /*pos*/, samplecnt_t /*cnt*/, int /*channel*/) const { return 0; }
readable_length()80 	virtual samplecnt_t readable_length() const { return length(); }
81 
82 	samplecnt_t read_at (Evoral::EventSink<samplepos_t>& dst,
83 	                    samplepos_t position,
84 	                    samplecnt_t dur,
85 	                    Evoral::Range<samplepos_t>* loop_range,
86 	                    MidiCursor& cursor,
87 	                    uint32_t  chan_n = 0,
88 	                    NoteMode  mode = Sustained,
89 	                    MidiStateTracker* tracker = 0,
90 	                    MidiChannelFilter* filter = 0) const;
91 
92 	samplecnt_t master_read_at (MidiRingBuffer<samplepos_t>& dst,
93 	                           samplepos_t position,
94 	                           samplecnt_t dur,
95 	                           Evoral::Range<samplepos_t>* loop_range,
96 	                           MidiCursor& cursor,
97 	                           uint32_t  chan_n = 0,
98 	                           NoteMode  mode = Sustained) const;
99 
100 	XMLNode& state ();
101 	int      set_state (const XMLNode&, int version);
102 
103 	int separate_by_channel (std::vector< boost::shared_ptr<Region> >&) const;
104 
105 	/* automation */
106 
107 	boost::shared_ptr<Evoral::Control> control(const Evoral::Parameter& id, bool create=false);
108 
109 	virtual boost::shared_ptr<const Evoral::Control> control(const Evoral::Parameter& id) const;
110 
111 	/* export */
112 
113 	boost::shared_ptr<MidiModel> model();
114 	boost::shared_ptr<const MidiModel> model() const;
115 
116 	void fix_negative_start ();
start_beats()117 	double start_beats () const {return _start_beats; }
length_beats()118 	double length_beats () const {return _length_beats; }
119 
120 	void clobber_sources (boost::shared_ptr<MidiSource> source);
121 
122 	int render (Evoral::EventSink<samplepos_t>& dst,
123 	            uint32_t                        chan_n,
124 	            NoteMode                        mode,
125 	            MidiChannelFilter*              filter) const;
126 
127   protected:
128 
can_trim_start_before_source_start()129 	virtual bool can_trim_start_before_source_start () const {
130 		return true;
131 	}
132 
133   private:
134 	friend class RegionFactory;
135 	PBD::Property<double> _start_beats;
136 	PBD::Property<double> _length_beats;
137 
138 	MidiRegion (const SourceList&);
139 	MidiRegion (boost::shared_ptr<const MidiRegion>);
140 	MidiRegion (boost::shared_ptr<const MidiRegion>, ARDOUR::MusicSample offset);
141 
142 	samplecnt_t _read_at (const SourceList&, Evoral::EventSink<samplepos_t>& dst,
143 	                     samplepos_t position,
144 	                     samplecnt_t dur,
145 	                     Evoral::Range<samplepos_t>* loop_range,
146 	                     MidiCursor& cursor,
147 	                     uint32_t chan_n = 0,
148 	                     NoteMode mode = Sustained,
149 	                     MidiStateTracker* tracker = 0,
150 	                     MidiChannelFilter* filter = 0) const;
151 
152 	void register_properties ();
153 	void post_set (const PBD::PropertyChange&);
154 
155 	void recompute_at_start ();
156 	void recompute_at_end ();
157 
158 	bool set_name (const std::string & str);
159 
160 	void set_position_internal (samplepos_t pos, bool allow_bbt_recompute, const int32_t sub_num);
161 	void set_position_music_internal (double qn);
162 	void set_length_internal (samplecnt_t len, const int32_t sub_num);
163 	void set_start_internal (samplecnt_t, const int32_t sub_num);
164 	void trim_to_internal (samplepos_t position, samplecnt_t length, const int32_t sub_num);
165 	void update_length_beats (const int32_t sub_num);
166 
167 	void model_changed ();
168 	void model_contents_changed ();
169 	void model_shifted (double qn_distance);
170 	void model_automation_state_changed (Evoral::Parameter const &);
171 
172 	void set_start_beats_from_start_samples ();
173 	void update_after_tempo_map_change (bool send_change = true);
174 
175 	std::set<Evoral::Parameter> _filtered_parameters; ///< parameters that we ask our source not to return when reading
176 	PBD::ScopedConnection _model_connection;
177 	PBD::ScopedConnection _model_shift_connection;
178 	PBD::ScopedConnection _model_changed_connection;
179 	PBD::ScopedConnection _source_connection;
180 	PBD::ScopedConnection _model_contents_connection;
181 	bool _ignore_shift;
182 };
183 
184 } /* namespace ARDOUR */
185 
186 
187 #endif /* __ardour_midi_region_h__ */
188