ardour
midi_model.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2007 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 
21 #ifndef __ardour_midi_model_h__
22 #define __ardour_midi_model_h__
23 
24 #include <deque>
25 #include <queue>
26 #include <utility>
27 
28 #include <boost/utility.hpp>
29 #include <glibmm/threads.h>
30 
31 #include "pbd/command.h"
32 
36 #include "ardour/types.h"
37 #include "ardour/types.h"
38 #include "ardour/variant.h"
39 
40 #include "evoral/Note.hpp"
41 #include "evoral/Sequence.hpp"
42 
43 namespace ARDOUR {
44 
45 class Session;
46 class MidiSource;
47 
55 class LIBARDOUR_API MidiModel : public AutomatableSequence<Evoral::Beats> {
56 public:
58 
60 
61  NoteMode note_mode() const { return (percussive() ? Percussive : Sustained); }
62  void set_note_mode(NoteMode mode) { set_percussive(mode == Percussive); };
63 
65  public:
66 
67  DiffCommand (boost::shared_ptr<MidiModel> m, const std::string& name);
68 
69  const std::string& name () const { return _name; }
70 
71  virtual void operator() () = 0;
72  virtual void undo () = 0;
73 
74  virtual int set_state (const XMLNode&, int version) = 0;
75  virtual XMLNode & get_state () = 0;
76 
77  boost::shared_ptr<MidiModel> model() const { return _model; }
78 
79  protected:
81  const std::string _name;
82 
83  };
84 
86  public:
87 
88  NoteDiffCommand (boost::shared_ptr<MidiModel> m, const std::string& name) : DiffCommand (m, name) {}
90 
91  enum Property {
96  Channel
97  };
98 
99  void operator() ();
100  void undo ();
101 
102  int set_state (const XMLNode&, int version);
103  XMLNode & get_state ();
104 
105  void add (const NotePtr note);
106  void remove (const NotePtr note);
107  void side_effect_remove (const NotePtr note);
108 
109  void change (const NotePtr note, Property prop, uint8_t new_value) {
110  change(note, prop, Variant(new_value));
111  }
112 
113  void change (const NotePtr note, Property prop, TimeType new_time) {
114  change(note, prop, Variant(new_time));
115  }
116 
117  void change (const NotePtr note, Property prop, const Variant& new_value);
118 
119  bool adds_or_removes() const {
120  return !_added_notes.empty() || !_removed_notes.empty();
121  }
122 
123  NoteDiffCommand& operator+= (const NoteDiffCommand& other);
124 
125  static Variant get_value (const NotePtr note, Property prop);
126 
127  static Variant::Type value_type (Property prop);
128 
129  struct NoteChange {
131  NotePtr note;
132  uint32_t note_id;
135  };
136 
137  typedef std::list<NoteChange> ChangeList;
138  typedef std::list< boost::shared_ptr< Evoral::Note<TimeType> > > NoteList;
139 
140  const ChangeList& changes() const { return _changes; }
141  const NoteList& added_notes() const { return _added_notes; }
142  const NoteList& removed_notes() const { return _removed_notes; }
143 
144  private:
145  ChangeList _changes;
146  NoteList _added_notes;
147  NoteList _removed_notes;
148 
149  std::set<NotePtr> side_effect_removals;
150 
151  XMLNode &marshal_change(const NoteChange&);
152  NoteChange unmarshal_change(XMLNode *xml_note);
153 
154  XMLNode &marshal_note(const NotePtr note);
155  NotePtr unmarshal_note(XMLNode *xml_note);
156  };
157 
158  /* Currently this class only supports changes of sys-ex time, but could be expanded */
160  public:
162 
163  enum Property {
165  };
166 
167  int set_state (const XMLNode&, int version);
168  XMLNode & get_state ();
169 
170  void remove (SysExPtr sysex);
171  void operator() ();
172  void undo ();
173 
174  void change (boost::shared_ptr<Evoral::Event<TimeType> >, TimeType);
175 
176  private:
177  struct Change {
179  gint sysex_id;
181  TimeType old_time;
182  TimeType new_time;
183  };
184 
185  typedef std::list<Change> ChangeList;
186  ChangeList _changes;
187 
188  std::list<SysExPtr> _removed;
189 
190  XMLNode & marshal_change (const Change &);
191  Change unmarshal_change (XMLNode *);
192  };
193 
195  public:
198 
199  int set_state (const XMLNode &, int version);
200  XMLNode & get_state ();
201 
202  void operator() ();
203  void undo ();
204 
205  void add (PatchChangePtr);
206  void remove (PatchChangePtr);
207  void change_time (PatchChangePtr, TimeType);
208  void change_channel (PatchChangePtr, uint8_t);
209  void change_program (PatchChangePtr, uint8_t);
210  void change_bank (PatchChangePtr, int);
211 
212  enum Property {
216  Bank
217  };
218 
219  private:
220  struct Change {
223  gint patch_id;
224  TimeType old_time;
225  union {
226  uint8_t old_channel;
227  int old_bank;
228  uint8_t old_program;
229  };
230  TimeType new_time;
231  union {
232  uint8_t new_channel;
233  uint8_t new_program;
234  int new_bank;
235  };
236 
237  Change() : patch_id (-1) {}
238  };
239 
240  typedef std::list<Change> ChangeList;
241  ChangeList _changes;
242 
243  std::list<PatchChangePtr> _added;
244  std::list<PatchChangePtr> _removed;
245 
246  XMLNode & marshal_change (const Change &);
247  Change unmarshal_change (XMLNode *);
248 
249  XMLNode & marshal_patch_change (constPatchChangePtr);
250  PatchChangePtr unmarshal_patch_change (XMLNode *);
251  };
252 
253  MidiModel::NoteDiffCommand* new_note_diff_command (const std::string name = "midi edit");
254  MidiModel::SysExDiffCommand* new_sysex_diff_command (const std::string name = "midi edit");
255  MidiModel::PatchChangeDiffCommand* new_patch_change_diff_command (const std::string name = "midi edit");
256  void apply_command (Session& session, Command* cmd);
257  void apply_command_as_subcommand (Session& session, Command* cmd);
258 
259  bool sync_to_source (const Glib::Threads::Mutex::Lock& source_lock);
260 
261  bool write_to(boost::shared_ptr<MidiSource> source,
262  const Glib::Threads::Mutex::Lock& source_lock);
263 
264  bool write_section_to(boost::shared_ptr<MidiSource> source,
265  const Glib::Threads::Mutex::Lock& source_lock,
268 
269  // MidiModel doesn't use the normal AutomationList serialisation code
270  // since controller data is stored in the .mid
271  XMLNode& get_state();
272  int set_state(const XMLNode&) { return 0; }
273 
274  PBD::Signal0<void> ContentsChanged;
275 
277  void set_midi_source (boost::shared_ptr<MidiSource>);
278 
280  PatchChangePtr find_patch_change (Evoral::event_id_t);
281  boost::shared_ptr<Evoral::Note<TimeType> > find_note (gint note_id);
282  boost::shared_ptr<Evoral::Event<TimeType> > find_sysex (gint);
283 
284  InsertMergePolicy insert_merge_policy () const;
285  void set_insert_merge_policy (InsertMergePolicy);
286 
287  boost::shared_ptr<Evoral::Control> control_factory(const Evoral::Parameter& id);
288 
289  void insert_silence_at_start (TimeType);
290  void transpose (TimeType, TimeType, int);
291 
292  std::set<WeakNotePtr>& active_notes() { return _active_notes; }
293 
294 protected:
295  int resolve_overlaps_unlocked (const NotePtr, void* arg = 0);
296 
297 private:
299  WriteLockImpl(Glib::Threads::Mutex::Lock* slock, Glib::Threads::RWLock& s, Glib::Threads::Mutex& c)
300  : AutomatableSequence<TimeType>::WriteLockImpl(s, c)
301  , source_lock (slock)
302  {}
304  delete source_lock;
305  }
307  };
308 
309 public:
310  WriteLock edit_lock();
311 
312 private:
313  friend class DeltaCommand;
314 
315  void source_interpolation_changed (Evoral::Parameter, Evoral::ControlList::InterpolationStyle);
316  void source_automation_state_changed (Evoral::Parameter, AutoState);
317  void control_list_interpolation_changed (Evoral::Parameter, Evoral::ControlList::InterpolationStyle);
318  void automation_list_automation_state_changed (Evoral::Parameter, AutoState);
319 
320  void control_list_marked_dirty ();
321 
323 
324  // We cannot use a boost::shared_ptr here to avoid a retain cycle
327 
328  std::set<WeakNotePtr> _active_notes;
329 };
330 
331 } /* namespace ARDOUR */
332 
333 #endif /* __ardour_midi_model_h__ */
334 
std::list< SysExPtr > _removed
Definition: midi_model.h:188
NoteMode note_mode() const
Definition: midi_model.h:61
SysExDiffCommand::Property property
Definition: midi_model.h:180
const NoteList & removed_notes() const
Definition: midi_model.h:142
PBD::ScopedConnectionList _midi_source_connections
Definition: midi_model.h:322
void change(const NotePtr note, Property prop, TimeType new_time)
Definition: midi_model.h:113
int32_t event_id_t
Definition: types.hpp:40
std::list< boost::shared_ptr< Evoral::Note< TimeType > > > NoteList
Definition: midi_model.h:138
const NoteList & added_notes() const
Definition: midi_model.h:141
InsertMergePolicy
Definition: types.h:110
NoteMode
Definition: types.h:204
LIBEVORAL_API const Beats MaxBeats
Definition: types.cpp:26
boost::shared_ptr< MidiModel > _model
Definition: midi_model.h:80
InsertMergePolicy _insert_merge_policy
Definition: midi_model.h:326
std::list< NoteChange > ChangeList
Definition: midi_model.h:137
void set_note_mode(NoteMode mode)
Definition: midi_model.h:62
NoteDiffCommand(boost::shared_ptr< MidiModel > m, const std::string &name)
Definition: midi_model.h:88
const std::string _name
Definition: midi_model.h:81
LIBEVORAL_API const Beats MinBeats
Definition: types.cpp:27
PBD::Signal0< void > ContentsChanged
Definition: midi_model.h:274
boost::shared_ptr< MidiModel > model() const
Definition: midi_model.h:77
const ChangeList & changes() const
Definition: midi_model.h:140
std::list< Change > ChangeList
Definition: midi_model.h:185
Definition: amp.h:29
boost::shared_ptr< Evoral::Event< TimeType > > sysex
Definition: midi_model.h:178
void change(const NotePtr note, Property prop, uint8_t new_value)
Definition: midi_model.h:109
std::list< PatchChangePtr > _added
Definition: midi_model.h:243
Glib::Threads::Mutex::Lock * source_lock
Definition: midi_model.h:306
Evoral::Beats TimeType
Definition: midi_model.h:57
#define LIBARDOUR_API
const char * name
WriteLockImpl(Glib::Threads::Mutex::Lock *slock, Glib::Threads::RWLock &s, Glib::Threads::Mutex &c)
Definition: midi_model.h:299
Definition: xml++.h:95
std::set< NotePtr > side_effect_removals
Definition: midi_model.h:149
std::list< PatchChangePtr > _removed
Definition: midi_model.h:244
int set_state(const XMLNode &)
Definition: midi_model.h:272
static LilvNode * get_value(LilvWorld *world, const LilvNode *subject, const LilvNode *predicate)
Definition: lv2_plugin.cc:971
std::set< WeakNotePtr > & active_notes()
Definition: midi_model.h:292
const std::string & name() const
Definition: midi_model.h:69
std::set< WeakNotePtr > _active_notes
Definition: midi_model.h:328
boost::weak_ptr< MidiSource > _midi_source
Definition: midi_model.h:325
AutoState
Definition: types.h:145