Ardour  8.12
midi_model.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007-2016 David Robillard <d@drobilla.net>
3  * Copyright (C) 2008-2012 Hans Baier <hansfbaier@googlemail.com>
4  * Copyright (C) 2008-2017 Paul Davis <paul@linuxaudiosystems.com>
5  * Copyright (C) 2009-2011 Carl Hetherington <carl@carlh.net>
6  * Copyright (C) 2015 AndrĂ© Nusser <andre.nusser@googlemail.com>
7  * Copyright (C) 2016 Robin Gareus <robin@gareus.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 #ifndef __ardour_midi_model_h__
25 #define __ardour_midi_model_h__
26 
27 #include <deque>
28 #include <map>
29 #include <queue>
30 #include <utility>
31 
32 #include <glibmm/threads.h>
33 
34 #include "pbd/command.h"
35 
37 #include "ardour/automation_list.h"
39 #include "ardour/source.h"
40 #include "ardour/types.h"
41 #include "ardour/types.h"
42 #include "ardour/variant.h"
43 
44 #include "evoral/Note.h"
45 #include "evoral/Sequence.h"
46 
47 namespace ARDOUR {
48 
49 class Session;
50 class MidiSource;
51 
59 class LIBARDOUR_API MidiModel : public AutomatableSequence<Temporal::Beats> {
60 public:
62 
64 
66  public:
67 
68  DiffCommand (std::shared_ptr<MidiModel> m, const std::string& name);
69 
70  const std::string& name () const { return _name; }
71 
72  virtual void operator() () = 0;
73  virtual void undo () = 0;
74 
75  virtual int set_state (const XMLNode&, int version) = 0;
76  virtual XMLNode & get_state () const = 0;
77 
78  std::shared_ptr<MidiModel> model() const { return _model; }
79 
80  protected:
81  std::shared_ptr<MidiModel> _model;
82  const std::string _name;
83 
84  };
85 
87  public:
88 
89  NoteDiffCommand (std::shared_ptr<MidiModel> m, const std::string& name) : DiffCommand (m, name) {}
90  NoteDiffCommand (std::shared_ptr<MidiModel> m, const XMLNode& node);
91 
92  enum Property {
97  Channel
98  };
99 
100  void operator() ();
101  void undo ();
102 
103  int set_state (const XMLNode&, int version);
104  XMLNode & get_state () const;
105 
106  void add (const NotePtr note);
107  void remove (const NotePtr note);
108  void side_effect_remove (const NotePtr note);
109 
110  void change (const NotePtr note, Property prop, uint8_t new_value) {
111  change(note, prop, Variant(new_value));
112  }
113 
114  void change (const NotePtr note, Property prop, TimeType new_time) {
115  change(note, prop, Variant(new_time));
116  }
117 
118  void change (const NotePtr note, Property prop, const Variant& new_value);
119 
120  bool adds_or_removes() const {
121  return !_added_notes.empty() || !_removed_notes.empty();
122  }
123 
124  NoteDiffCommand& operator+= (const NoteDiffCommand& other);
125 
126  static Variant get_value (const NotePtr note, Property prop);
127 
129 
130  struct NoteChange {
133  uint32_t note_id;
136  };
137 
138  typedef std::list<NoteChange> ChangeList;
139  typedef std::list< std::shared_ptr< Evoral::Note<TimeType> > > NoteList;
140 
141  const ChangeList& changes() const { return _changes; }
142  const NoteList& added_notes() const { return _added_notes; }
143  const NoteList& removed_notes() const { return _removed_notes; }
144 
145  private:
149 
150  std::set<NotePtr> side_effect_removals;
151 
154 
155  XMLNode &marshal_note(const NotePtr note) const;
157  };
158 
159  /* Currently this class only supports changes of sys-ex time, but could be expanded */
161  public:
162  SysExDiffCommand (std::shared_ptr<MidiModel> m, const std::string& name) : DiffCommand (m, name) {}
163  SysExDiffCommand (std::shared_ptr<MidiModel> m, const XMLNode& node);
164 
165  enum Property {
167  };
168 
169  int set_state (const XMLNode&, int version);
170  XMLNode & get_state () const;
171 
173  void operator() ();
174  void undo ();
175 
176  void change (std::shared_ptr<Evoral::Event<TimeType> >, TimeType);
177 
178  private:
179  struct Change {
180  Change () : sysex_id (0) {}
181  std::shared_ptr<Evoral::Event<TimeType> > sysex;
182  gint sysex_id;
186  };
187 
188  typedef std::list<Change> ChangeList;
190 
191  std::list<SysExPtr> _removed;
192 
193  XMLNode & marshal_change (const Change &) const;
195  };
196 
198  public:
199  PatchChangeDiffCommand (std::shared_ptr<MidiModel>, const std::string &);
200  PatchChangeDiffCommand (std::shared_ptr<MidiModel>, const XMLNode &);
201 
202  int set_state (const XMLNode &, int version);
203  XMLNode & get_state () const;
204 
205  void operator() ();
206  void undo ();
207 
214 
215  enum Property {
219  Bank
220  };
221 
222  private:
223  struct Change {
226  gint patch_id;
228  union {
229  uint8_t old_channel;
230  int old_bank;
231  uint8_t old_program;
232  };
234  union {
235  uint8_t new_channel;
236  uint8_t new_program;
237  int new_bank;
238  };
239 
240  Change() : patch_id (-1) {}
241  };
242 
243  typedef std::list<Change> ChangeList;
245 
246  std::list<PatchChangePtr> _added;
247  std::list<PatchChangePtr> _removed;
248 
249  XMLNode & marshal_change (const Change &) const;
251 
254  };
255 
256  void create_mapping_stash (Temporal::Beats const & offset);
258 
265  MidiModel::NoteDiffCommand* new_note_diff_command (const std::string& name = "midi edit");
267  MidiModel::SysExDiffCommand* new_sysex_diff_command (const std::string& name = "midi edit");
268 
271 
279 
281 
288 
294 
295  bool sync_to_source (const Source::WriterLock& source_lock);
296 
297  bool write_to(std::shared_ptr<MidiSource> source,
298  const Source::WriterLock& source_lock);
299 
300  bool write_section_to(std::shared_ptr<MidiSource> source,
301  const Source::WriterLock& source_lock,
304  bool offset_events = false);
305 
306  // MidiModel doesn't use the normal AutomationList serialisation code
307  // since controller data is stored in the .mid
308  XMLNode& get_state() const;
309  int set_state(const XMLNode&) { return 0; }
310 
311  PBD::Signal0<void> ContentsChanged;
312  PBD::Signal1<void, Temporal::timecnt_t> ContentsShifted;
313 
314  std::shared_ptr<Evoral::Note<TimeType> > find_note (NotePtr);
316  std::shared_ptr<Evoral::Note<TimeType> > find_note (Evoral::event_id_t);
317  std::shared_ptr<Evoral::Event<TimeType> > find_sysex (Evoral::event_id_t);
318 
321 
322  std::shared_ptr<Evoral::Control> control_factory(const Evoral::Parameter& id);
323 
325  void transpose (NoteDiffCommand *, const NotePtr, int);
326 
327  protected:
328  int resolve_overlaps_unlocked (const NotePtr, void* arg = 0);
329 
330  protected:
331  friend class NoteDiffCommand;
332  friend class SysExDiffCommand;
334 
335  MidiSource& midi_source() const { return _midi_source; }
336 
337  private:
339  WriteLockImpl(Source::WriterLock* slock, Glib::Threads::RWLock& s, Glib::Threads::Mutex& c)
341  , source_lock (slock)
342  {}
344  delete source_lock;
345  }
347  };
348 
349 public:
351 
352 private:
353  friend class DeltaCommand;
354 
359 
361 
363 
366 
367  typedef std::map<void*,superclock_t> TempoMappingStash;
369 
370 };
371 
372 } /* namespace ARDOUR */
373 
374 #endif /* __ardour_midi_model_h__ */
375 
DiffCommand(std::shared_ptr< MidiModel > m, const std::string &name)
std::shared_ptr< MidiModel > _model
Definition: midi_model.h:81
const std::string _name
Definition: midi_model.h:82
std::shared_ptr< MidiModel > model() const
Definition: midi_model.h:78
const std::string & name() const
Definition: midi_model.h:70
virtual XMLNode & get_state() const =0
virtual int set_state(const XMLNode &, int version)=0
std::list< std::shared_ptr< Evoral::Note< TimeType > > > NoteList
Definition: midi_model.h:139
static Variant get_value(const NotePtr note, Property prop)
void side_effect_remove(const NotePtr note)
XMLNode & marshal_note(const NotePtr note) const
XMLNode & marshal_change(const NoteChange &) const
void add(const NotePtr note)
int set_state(const XMLNode &, int version)
void change(const NotePtr note, Property prop, const Variant &new_value)
NoteDiffCommand(std::shared_ptr< MidiModel > m, const std::string &name)
Definition: midi_model.h:89
void remove(const NotePtr note)
const NoteList & removed_notes() const
Definition: midi_model.h:143
std::list< NoteChange > ChangeList
Definition: midi_model.h:138
NoteChange unmarshal_change(XMLNode *xml_note)
NoteDiffCommand(std::shared_ptr< MidiModel > m, const XMLNode &node)
const ChangeList & changes() const
Definition: midi_model.h:141
std::set< NotePtr > side_effect_removals
Definition: midi_model.h:150
NotePtr unmarshal_note(XMLNode *xml_note)
void change(const NotePtr note, Property prop, TimeType new_time)
Definition: midi_model.h:114
void change(const NotePtr note, Property prop, uint8_t new_value)
Definition: midi_model.h:110
const NoteList & added_notes() const
Definition: midi_model.h:142
static Variant::Type value_type(Property prop)
PatchChangeDiffCommand(std::shared_ptr< MidiModel >, const std::string &)
int set_state(const XMLNode &, int version)
std::list< PatchChangePtr > _removed
Definition: midi_model.h:247
std::list< PatchChangePtr > _added
Definition: midi_model.h:246
void change_channel(PatchChangePtr, uint8_t)
void change_bank(PatchChangePtr, int)
void change_program(PatchChangePtr, uint8_t)
void change_time(PatchChangePtr, TimeType)
XMLNode & marshal_patch_change(constPatchChangePtr) const
XMLNode & marshal_change(const Change &) const
PatchChangePtr unmarshal_patch_change(XMLNode *)
PatchChangeDiffCommand(std::shared_ptr< MidiModel >, const XMLNode &)
std::list< Change > ChangeList
Definition: midi_model.h:188
int set_state(const XMLNode &, int version)
std::list< SysExPtr > _removed
Definition: midi_model.h:191
SysExDiffCommand(std::shared_ptr< MidiModel > m, const std::string &name)
Definition: midi_model.h:162
void change(std::shared_ptr< Evoral::Event< TimeType > >, TimeType)
XMLNode & marshal_change(const Change &) const
SysExDiffCommand(std::shared_ptr< MidiModel > m, const XMLNode &node)
void source_interpolation_changed(Evoral::Parameter const &, AutomationList::InterpolationStyle)
InsertMergePolicy insert_merge_policy() const
std::map< void *, superclock_t > TempoMappingStash
Definition: midi_model.h:367
void apply_diff_command_as_commit(Session *session, PBD::Command *cmd)
Definition: midi_model.h:280
bool write_section_to(std::shared_ptr< MidiSource > source, const Source::WriterLock &source_lock, Temporal::Beats begin=Temporal::Beats(), Temporal::Beats end=std::numeric_limits< Temporal::Beats >::max(), bool offset_events=false)
TempoMappingStash tempo_mapping_stash
Definition: midi_model.h:368
PBD::ScopedConnectionList _midi_source_connections
Definition: midi_model.h:362
std::shared_ptr< Evoral::Control > control_factory(const Evoral::Parameter &id)
void rebuild_from_mapping_stash(Temporal::Beats const &offset)
MidiSource & midi_source() const
Definition: midi_model.h:335
MidiModel::PatchChangeDiffCommand * new_patch_change_diff_command(const std::string &name="midi edit")
void source_automation_state_changed(Evoral::Parameter const &, AutoState)
void control_list_marked_dirty()
void set_insert_merge_policy(InsertMergePolicy)
int resolve_overlaps_unlocked(const NotePtr, void *arg=0)
void apply_diff_command_as_subcommand(Session &session, PBD::Command *cmd)
void apply_diff_command_as_commit(Session &session, PBD::Command *cmd)
int set_state(const XMLNode &)
Definition: midi_model.h:309
void apply_diff_command_only(Session &session, PBD::Command *cmd)
void create_mapping_stash(Temporal::Beats const &offset)
InsertMergePolicy _insert_merge_policy
Definition: midi_model.h:365
WriteLock edit_lock()
Temporal::Beats TimeType
Definition: midi_model.h:61
PatchChangePtr find_patch_change(Evoral::event_id_t)
bool write_to(std::shared_ptr< MidiSource > source, const Source::WriterLock &source_lock)
MidiModel::NoteDiffCommand * new_note_diff_command(const std::string &name="midi edit")
void control_list_interpolation_changed(Evoral::Parameter const &, AutomationList::InterpolationStyle)
std::shared_ptr< Evoral::Event< TimeType > > find_sysex(Evoral::event_id_t)
void insert_silence_at_start(TimeType)
void automation_list_automation_state_changed(Evoral::Parameter const &, AutoState)
MidiModel::SysExDiffCommand * new_sysex_diff_command(const std::string &name="midi edit")
MidiModel(MidiSource &)
bool sync_to_source(const Source::WriterLock &source_lock)
std::shared_ptr< Evoral::Note< TimeType > > find_note(NotePtr)
MidiSource & _midi_source
Definition: midi_model.h:364
std::shared_ptr< Evoral::Note< TimeType > > find_note(Evoral::event_id_t)
PBD::Signal0< void > ContentsChanged
Definition: midi_model.h:311
void transpose(NoteDiffCommand *, const NotePtr, int)
PBD::Signal1< void, Temporal::timecnt_t > ContentsShifted
Definition: midi_model.h:312
XMLNode & get_state() const
Glib::Threads::RWLock::WriterLock WriterLock
std::shared_ptr< PatchChange< Temporal::Beats > > PatchChangePtr
Definition: Sequence.h:205
std::shared_ptr< const PatchChange< Temporal::Beats > > constPatchChangePtr
Definition: Sequence.h:206
std::shared_ptr< Event< Temporal::Beats > > SysExPtr
Definition: Sequence.h:192
std::shared_ptr< Evoral::Note< Temporal::Beats > > NotePtr
Definition: Sequence.h:89
std::shared_ptr< WriteLockImpl > WriteLock
Definition: Sequence.h:95
Definition: xml++.h:114
GtkImageIconNameData name
Definition: gtkimage.h:6
#define LIBARDOUR_API
void session(lua_State *L)
int32_t event_id_t
SysExDiffCommand::Property property
Definition: midi_model.h:183
std::shared_ptr< Evoral::Event< TimeType > > sysex
Definition: midi_model.h:181
WriteLockImpl(Source::WriterLock *slock, Glib::Threads::RWLock &s, Glib::Threads::Mutex &c)
Definition: midi_model.h:339
Source::WriterLock * source_lock
Definition: midi_model.h:346
static Temporal::Beats max()
Definition: beats.h:300