+ class PatchChangeDiffCommand : public DiffCommand {
+ public:
+ PatchChangeDiffCommand (boost::shared_ptr<MidiModel>, const std::string &);
+ PatchChangeDiffCommand (boost::shared_ptr<MidiModel>, const XMLNode &);
+
+ int set_state (const XMLNode &, int version);
+ XMLNode & get_state ();
+
+ void operator() ();
+ void undo ();
+
+ void add (PatchChangePtr);
+ void remove (PatchChangePtr);
+ void change_time (PatchChangePtr, TimeType);
+ void change_channel (PatchChangePtr, uint8_t);
+ void change_program (PatchChangePtr, uint8_t);
+ void change_bank (PatchChangePtr, int);
+
+ enum Property {
+ Time,
+ Channel,
+ Program,
+ Bank
+ };
+
+ private:
+ struct Change {
+ PatchChangePtr patch;
+ Property property;
+ union {
+ TimeType old_time;
+ uint8_t old_channel;
+ int old_bank;
+ uint8_t old_program;
+ };
+ union {
+ uint8_t new_channel;
+ TimeType new_time;
+ uint8_t new_program;
+ int new_bank;
+ };
+ };
+
+ typedef std::list<Change> ChangeList;
+ ChangeList _changes;
+
+ std::list<PatchChangePtr> _added;
+ std::list<PatchChangePtr> _removed;
+
+ XMLNode & marshal_change (const Change &);
+ Change unmarshal_change (XMLNode *);
+
+ XMLNode & marshal_patch_change (constPatchChangePtr);
+ PatchChangePtr unmarshal_patch_change (XMLNode *);
+ };
+
+ MidiModel::NoteDiffCommand* new_note_diff_command (const std::string name = "midi edit");
+ MidiModel::SysExDiffCommand* new_sysex_diff_command (const std::string name = "midi edit");
+ MidiModel::PatchChangeDiffCommand* new_patch_change_diff_command (const std::string name = "midi edit");
+ void apply_command (Session& session, Command* cmd);
+ void apply_command_as_subcommand (Session& session, Command* cmd);
+
+ bool sync_to_source ();
+ bool write_to(boost::shared_ptr<MidiSource> source);
+ bool write_section_to (boost::shared_ptr<MidiSource> source, Evoral::MusicalTime begin = Evoral::MinMusicalTime,
+ Evoral::MusicalTime end = Evoral::MaxMusicalTime);
+
+ // MidiModel doesn't use the normal AutomationList serialisation code
+ // since controller data is stored in the .mid
+ XMLNode& get_state();
+ int set_state(const XMLNode&) { return 0; }
+
+ PBD::Signal0<void> ContentsChanged;
+
+ boost::shared_ptr<const MidiSource> midi_source ();
+ void set_midi_source (boost::shared_ptr<MidiSource>);
+
+ boost::shared_ptr<Evoral::Note<TimeType> > find_note (NotePtr);
+ PatchChangePtr find_patch_change (Evoral::event_id_t);
+ boost::shared_ptr<Evoral::Note<TimeType> > find_note (gint note_id);
+ boost::shared_ptr<Evoral::Event<TimeType> > find_sysex (gint);
+
+ InsertMergePolicy insert_merge_policy () const;
+ void set_insert_merge_policy (InsertMergePolicy);
+
+ boost::shared_ptr<Evoral::Control> control_factory(const Evoral::Parameter& id);
+
+ void insert_silence_at_start (TimeType);
+ void transpose (TimeType, TimeType, int);
+
+protected:
+ int resolve_overlaps_unlocked (const NotePtr, void* arg = 0);
+
+private:
+ struct WriteLockImpl : public AutomatableSequence<TimeType>::WriteLockImpl {
+ WriteLockImpl(Glib::Mutex::Lock* source_lock, Glib::RWLock& s, Glib::Mutex& c)
+ : AutomatableSequence<TimeType>::WriteLockImpl(s, c)
+ , source_lock(source_lock)
+ {}
+ ~WriteLockImpl() {
+ delete source_lock;
+ }
+ Glib::Mutex::Lock* source_lock;
+ };
+
+public:
+ WriteLock edit_lock();
+ WriteLock write_lock();