add an plugin API to query generic-gui grid-layout
[ardour.git] / libs / ardour / ardour / midi_model.h
index d1fba0a8ea3570535bb63be391ba8a728f19d003..254d6100770a25ee05e2087f1cf668e524543a49 100644 (file)
 #ifndef __ardour_midi_model_h__
 #define __ardour_midi_model_h__
 
-#include <queue>
 #include <deque>
+#include <queue>
 #include <utility>
+
 #include <boost/utility.hpp>
-#include <glibmm/thread.h>
+#include <glibmm/threads.h>
+
 #include "pbd/command.h"
-#include "ardour/types.h"
-#include "ardour/midi_buffer.h"
-#include "ardour/midi_ring_buffer.h"
+
 #include "ardour/automatable_sequence.h"
+#include "ardour/libardour_visibility.h"
+#include "ardour/libardour_visibility.h"
+#include "ardour/types.h"
 #include "ardour/types.h"
+#include "ardour/variant.h"
+
 #include "evoral/Note.hpp"
 #include "evoral/Sequence.hpp"
 
@@ -47,16 +52,16 @@ class MidiSource;
  * Because of this MIDI controllers and automatable controllers/widgets/etc
  * are easily interchangeable.
  */
-class MidiModel : public AutomatableSequence<Evoral::MusicalTime> {
+class LIBARDOUR_API MidiModel : public AutomatableSequence<Evoral::Beats> {
 public:
-       typedef Evoral::MusicalTime TimeType;
+       typedef Evoral::Beats TimeType;
 
        MidiModel (boost::shared_ptr<MidiSource>);
 
        NoteMode note_mode() const { return (percussive() ? Percussive : Sustained); }
        void set_note_mode(NoteMode mode) { set_percussive(mode == Percussive); };
 
-       class DiffCommand : public Command {
+       class LIBARDOUR_API DiffCommand : public Command {
        public:
 
                DiffCommand (boost::shared_ptr<MidiModel> m, const std::string& name);
@@ -77,7 +82,7 @@ public:
 
        };
 
-       class NoteDiffCommand : public DiffCommand {
+       class LIBARDOUR_API NoteDiffCommand : public DiffCommand {
        public:
 
                NoteDiffCommand (boost::shared_ptr<MidiModel> m, const std::string& name) : DiffCommand (m, name) {}
@@ -101,8 +106,15 @@ public:
                void 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);
+               void change (const NotePtr note, Property prop, uint8_t new_value) {
+                       change(note, prop, Variant(new_value));
+               }
+
+               void change (const NotePtr note, Property prop, TimeType new_time) {
+                       change(note, prop, Variant(new_time));
+               }
+
+               void change (const NotePtr note, Property prop, const Variant& new_value);
 
                bool adds_or_removes() const {
                        return !_added_notes.empty() || !_removed_notes.empty();
@@ -110,26 +122,29 @@ public:
 
                NoteDiffCommand& operator+= (const NoteDiffCommand& other);
 
-       private:
+               static Variant get_value (const NotePtr note, Property prop);
+
+               static Variant::Type value_type (Property prop);
+
                struct NoteChange {
                        NoteDiffCommand::Property property;
                        NotePtr note;
-                       union {
-                               uint8_t  old_value;
-                               TimeType old_time;
-                       };
-                       union {
-                               uint8_t  new_value;
-                               TimeType new_time;
-                       };
+                       uint32_t note_id;
+                       Variant old_value;
+                       Variant new_value;
                };
 
-               typedef std::list<NoteChange> ChangeList;
-               ChangeList _changes;
-
+               typedef std::list<NoteChange>                                    ChangeList;
                typedef std::list< boost::shared_ptr< Evoral::Note<TimeType> > > NoteList;
-               NoteList _added_notes;
-               NoteList _removed_notes;
+
+               const ChangeList& changes()       const { return _changes; }
+               const NoteList&   added_notes()   const { return _added_notes; }
+               const NoteList&   removed_notes() const { return _removed_notes; }
+
+       private:
+               ChangeList _changes;
+               NoteList   _added_notes;
+               NoteList   _removed_notes;
 
                std::set<NotePtr> side_effect_removals;
 
@@ -141,7 +156,7 @@ public:
        };
 
        /* Currently this class only supports changes of sys-ex time, but could be expanded */
-       class SysExDiffCommand : public DiffCommand {
+       class LIBARDOUR_API SysExDiffCommand : public DiffCommand {
        public:
                SysExDiffCommand (boost::shared_ptr<MidiModel> m, const XMLNode& node);
 
@@ -152,6 +167,7 @@ public:
                int set_state (const XMLNode&, int version);
                XMLNode & get_state ();
 
+               void remove (SysExPtr sysex);
                void operator() ();
                void undo ();
 
@@ -159,7 +175,9 @@ public:
 
        private:
                struct Change {
+                       Change () : sysex_id (0) {}
                        boost::shared_ptr<Evoral::Event<TimeType> > sysex;
+                       gint sysex_id;
                        SysExDiffCommand::Property property;
                        TimeType old_time;
                        TimeType new_time;
@@ -168,11 +186,13 @@ public:
                typedef std::list<Change> ChangeList;
                ChangeList _changes;
 
+               std::list<SysExPtr> _removed;
+
                XMLNode & marshal_change (const Change &);
                Change unmarshal_change (XMLNode *);
        };
 
-       class PatchChangeDiffCommand : public DiffCommand {
+       class LIBARDOUR_API PatchChangeDiffCommand : public DiffCommand {
        public:
                PatchChangeDiffCommand (boost::shared_ptr<MidiModel>, const std::string &);
                PatchChangeDiffCommand (boost::shared_ptr<MidiModel>, const XMLNode &);
@@ -201,18 +221,21 @@ public:
                struct Change {
                        PatchChangePtr patch;
                        Property       property;
+                       gint           patch_id;
+                       TimeType       old_time;
                        union {
-                               TimeType   old_time;
                                uint8_t    old_channel;
                                int        old_bank;
                                uint8_t    old_program;
                        };
+                       TimeType       new_time;
                        union {
                                uint8_t    new_channel;
-                               TimeType   new_time;
                                uint8_t    new_program;
                                int        new_bank;
                        };
+
+                   Change() : patch_id (-1) {}
                };
 
                typedef std::list<Change> ChangeList;
@@ -234,10 +257,15 @@ public:
        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);
+       bool sync_to_source (const Glib::Threads::Mutex::Lock& source_lock);
+
+       bool write_to(boost::shared_ptr<MidiSource>     source,
+                     const Glib::Threads::Mutex::Lock& source_lock);
+
+       bool write_section_to(boost::shared_ptr<MidiSource>     source,
+                             const Glib::Threads::Mutex::Lock& source_lock,
+                             Evoral::Beats                     begin = Evoral::MinBeats,
+                             Evoral::Beats                     end   = Evoral::MaxBeats);
 
        // MidiModel doesn't use the normal AutomationList serialisation code
        // since controller data is stored in the .mid
@@ -260,26 +288,27 @@ public:
        boost::shared_ptr<Evoral::Control> control_factory(const Evoral::Parameter& id);
 
        void insert_silence_at_start (TimeType);
-       void transpose (TimeType, TimeType, int);
+       void transpose (NoteDiffCommand *, const NotePtr, int);
+
+       std::set<WeakNotePtr>& active_notes() { return _active_notes; }
 
 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)
+               WriteLockImpl(Glib::Threads::Mutex::Lock* slock, Glib::Threads::RWLock& s, Glib::Threads::Mutex& c)
                        : AutomatableSequence<TimeType>::WriteLockImpl(s, c)
-                       , source_lock(source_lock)
+                       , source_lock (slock)
                {}
                ~WriteLockImpl() {
                        delete source_lock;
                }
-               Glib::Mutex::Lock* source_lock;
+               Glib::Threads::Mutex::Lock* source_lock;
        };
 
 public:
-       virtual WriteLock edit_lock();
-       virtual WriteLock write_lock();
+       WriteLock edit_lock();
 
 private:
        friend class DeltaCommand;
@@ -289,16 +318,18 @@ private:
        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
        boost::weak_ptr<MidiSource> _midi_source;
        InsertMergePolicy _insert_merge_policy;
+
+       std::set<WeakNotePtr> _active_notes;
 };
 
 } /* 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__ */