X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fardour%2Fmidi_model.h;h=d0a05e131d5a83fd04f64a84fc1bf9fc6dcd0380;hb=494635b99b9cdac42fd7a14e80c78ce437d6f606;hp=e91d6484ea6e923fe6d643e24b5f5f44b7069ad0;hpb=bf91ed99ec2b1231c7150bde7f12c8ca573f0834;p=ardour.git diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h index e91d6484ea..d0a05e131d 100644 --- a/libs/ardour/ardour/midi_model.h +++ b/libs/ardour/ardour/midi_model.h @@ -1,6 +1,6 @@ /* Copyright (C) 2007 Paul Davis - Author: Dave Robillard + Author: David Robillard This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -51,13 +51,38 @@ class MidiModel : public AutomatableSequence { public: typedef Evoral::MusicalTime TimeType; - MidiModel(MidiSource* s); + MidiModel (boost::shared_ptr); NoteMode note_mode() const { return (percussive() ? Percussive : Sustained); } void set_note_mode(NoteMode mode) { set_percussive(mode == Percussive); }; class DiffCommand : public Command { public: + + DiffCommand (boost::shared_ptr m, const std::string& name); + + const std::string& name () const { return _name; } + + virtual void operator() () = 0; + virtual void undo () = 0; + + virtual int set_state (const XMLNode&, int version) = 0; + virtual XMLNode & get_state () = 0; + + boost::shared_ptr model() const { return _model; } + + protected: + boost::shared_ptr _model; + const std::string _name; + + }; + + class NoteDiffCommand : public DiffCommand { + public: + + NoteDiffCommand (boost::shared_ptr m, const std::string& name) : DiffCommand (m, name) {} + NoteDiffCommand (boost::shared_ptr m, const XMLNode& node); + enum Property { NoteNumber, Velocity, @@ -66,37 +91,28 @@ public: Channel }; - DiffCommand (boost::shared_ptr m, const std::string& name); - DiffCommand (boost::shared_ptr m, const XMLNode& node); - - const std::string& name() const { return _name; } - - void operator()(); - void undo(); + void operator() (); + void undo (); int set_state (const XMLNode&, int version); - XMLNode& get_state (); + XMLNode & get_state (); void add (const NotePtr note); void remove (const NotePtr note); - void side_effect_remove (const NotePtr note); + void side_effect_remove (const NotePtr note); void change (const NotePtr note, Property prop, uint8_t new_value); void change (const NotePtr note, Property prop, TimeType new_time); - bool adds_or_removes() const { - return !_added_notes.empty() || !_removed_notes.empty(); - } - - DiffCommand& operator+= (const DiffCommand& other); - boost::shared_ptr model() const { return _model; } + bool adds_or_removes() const { + return !_added_notes.empty() || !_removed_notes.empty(); + } - private: - boost::shared_ptr _model; - const std::string _name; + NoteDiffCommand& operator+= (const NoteDiffCommand& other); + private: struct NoteChange { - DiffCommand::Property property; + NoteDiffCommand::Property property; NotePtr note; union { uint8_t old_value; @@ -115,7 +131,7 @@ public: NoteList _added_notes; NoteList _removed_notes; - std::set side_effect_removals; + std::set side_effect_removals; XMLNode &marshal_change(const NoteChange&); NoteChange unmarshal_change(XMLNode *xml_note); @@ -124,14 +140,104 @@ public: NotePtr unmarshal_note(XMLNode *xml_note); }; - MidiModel::DiffCommand* new_diff_command(const std::string name="midi edit"); - void apply_command(Session& session, Command* cmd); - void apply_command_as_subcommand(Session& session, Command* cmd); + /* Currently this class only supports changes of sys-ex time, but could be expanded */ + class SysExDiffCommand : public DiffCommand { + public: + SysExDiffCommand (boost::shared_ptr m, const XMLNode& node); + + enum Property { + Time, + }; + + int set_state (const XMLNode&, int version); + XMLNode & get_state (); + + void operator() (); + void undo (); + + void change (boost::shared_ptr >, TimeType); + + private: + struct Change { + boost::shared_ptr > sysex; + SysExDiffCommand::Property property; + TimeType old_time; + TimeType new_time; + }; + + typedef std::list ChangeList; + ChangeList _changes; + + XMLNode & marshal_change (const Change &); + Change unmarshal_change (XMLNode *); + }; + + class PatchChangeDiffCommand : public DiffCommand { + public: + PatchChangeDiffCommand (boost::shared_ptr, const std::string &); + PatchChangeDiffCommand (boost::shared_ptr, 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 ChangeList; + ChangeList _changes; + + std::list _added; + std::list _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 source); bool write_section_to (boost::shared_ptr source, Evoral::MusicalTime begin = Evoral::MinMusicalTime, - Evoral::MusicalTime end = Evoral::MaxMusicalTime); + Evoral::MusicalTime end = Evoral::MaxMusicalTime); // MidiModel doesn't use the normal AutomationList serialisation code // since controller data is stored in the .mid @@ -140,19 +246,24 @@ public: PBD::Signal0 ContentsChanged; - const MidiSource* midi_source() const { return _midi_source; } - void set_midi_source (MidiSource *); + boost::shared_ptr midi_source (); + void set_midi_source (boost::shared_ptr); boost::shared_ptr > find_note (NotePtr); + PatchChangePtr find_patch_change (Evoral::event_id_t); boost::shared_ptr > find_note (gint note_id); + boost::shared_ptr > find_sysex (gint); - InsertMergePolicy insert_merge_policy () const; - void set_insert_merge_policy (InsertMergePolicy); + InsertMergePolicy insert_merge_policy () const; + void set_insert_merge_policy (InsertMergePolicy); boost::shared_ptr 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); + int resolve_overlaps_unlocked (const NotePtr, void* arg = 0); private: struct WriteLockImpl : public AutomatableSequence::WriteLockImpl { @@ -167,23 +278,29 @@ private: }; public: - virtual WriteLock edit_lock(); - virtual WriteLock write_lock(); + WriteLock edit_lock(); + WriteLock write_lock(); private: friend class DeltaCommand; void source_interpolation_changed (Evoral::Parameter, Evoral::ControlList::InterpolationStyle); + void source_automation_state_changed (Evoral::Parameter, AutoState); void control_list_interpolation_changed (Evoral::Parameter, Evoral::ControlList::InterpolationStyle); - + void automation_list_automation_state_changed (Evoral::Parameter, AutoState); + + void control_list_marked_dirty (); + PBD::ScopedConnectionList _midi_source_connections; // We cannot use a boost::shared_ptr here to avoid a retain cycle - MidiSource* _midi_source; - InsertMergePolicy _insert_merge_policy; + boost::weak_ptr _midi_source; + InsertMergePolicy _insert_merge_policy; }; } /* namespace ARDOUR */ +/* This is a very long comment and stuff oh my god it's so long what are we going to do oh no oh no*/ + #endif /* __ardour_midi_model_h__ */