2 Copyright (C) 2007 Paul Davis
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.
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.
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.
21 #ifndef __ardour_midi_model_h__
22 #define __ardour_midi_model_h__
27 #include <boost/utility.hpp>
28 #include <glibmm/thread.h>
29 #include "pbd/command.h"
30 #include "ardour/types.h"
31 #include "ardour/midi_buffer.h"
32 #include "ardour/midi_ring_buffer.h"
33 #include "ardour/automatable_sequence.h"
34 #include "ardour/types.h"
35 #include "evoral/Note.hpp"
36 #include "evoral/Sequence.hpp"
43 /** This is a higher level (than MidiBuffer) model of MIDI data, with separate
44 * representations for notes (instead of just unassociated note on/off events)
45 * and controller data. Controller data is represented as part of the
46 * Automatable base (i.e. in a map of AutomationList, keyed by Parameter).
47 * Because of this MIDI controllers and automatable controllers/widgets/etc
48 * are easily interchangeable.
50 class MidiModel
: public AutomatableSequence
<Evoral::MusicalTime
> {
52 typedef Evoral::MusicalTime TimeType
;
54 MidiModel(MidiSource
* s
);
56 NoteMode
note_mode() const { return (percussive() ? Percussive
: Sustained
); }
57 void set_note_mode(NoteMode mode
) { set_percussive(mode
== Percussive
); };
59 class DiffCommand
: public Command
{
69 DiffCommand (boost::shared_ptr
<MidiModel
> m
, const std::string
& name
);
70 DiffCommand (boost::shared_ptr
<MidiModel
> m
, const XMLNode
& node
);
72 const std::string
& name() const { return _name
; }
77 int set_state (const XMLNode
&, int version
);
78 XMLNode
& get_state ();
80 void add (const NotePtr note
);
81 void remove (const NotePtr note
);
82 void side_effect_remove (const NotePtr note
);
84 void change (const NotePtr note
, Property prop
, uint8_t new_value
);
85 void change (const NotePtr note
, Property prop
, TimeType new_time
);
87 bool adds_or_removes() const {
88 return !_added_notes
.empty() || !_removed_notes
.empty();
91 DiffCommand
& operator+= (const DiffCommand
& other
);
92 boost::shared_ptr
<MidiModel
> model() const { return _model
; }
95 boost::shared_ptr
<MidiModel
> _model
;
96 const std::string _name
;
99 DiffCommand::Property property
;
111 typedef std::list
<NoteChange
> ChangeList
;
114 typedef std::list
< boost::shared_ptr
< Evoral::Note
<TimeType
> > > NoteList
;
115 NoteList _added_notes
;
116 NoteList _removed_notes
;
118 std::set
<NotePtr
> side_effect_removals
;
120 XMLNode
&marshal_change(const NoteChange
&);
121 NoteChange
unmarshal_change(XMLNode
*xml_note
);
123 XMLNode
&marshal_note(const NotePtr note
);
124 NotePtr
unmarshal_note(XMLNode
*xml_note
);
127 MidiModel::DiffCommand
* new_diff_command(const std::string name
="midi edit");
128 void apply_command(Session
& session
, Command
* cmd
);
129 void apply_command_as_subcommand(Session
& session
, Command
* cmd
);
131 bool sync_to_source ();
132 bool write_to(boost::shared_ptr
<MidiSource
> source
);
133 bool write_section_to (boost::shared_ptr
<MidiSource
> source
, Evoral::MusicalTime begin
= Evoral::MinMusicalTime
,
134 Evoral::MusicalTime end
= Evoral::MaxMusicalTime
);
136 // MidiModel doesn't use the normal AutomationList serialisation code
137 // since controller data is stored in the .mid
138 XMLNode
& get_state();
139 int set_state(const XMLNode
&) { return 0; }
141 PBD::Signal0
<void> ContentsChanged
;
143 const MidiSource
* midi_source() const { return _midi_source
; }
144 void set_midi_source (MidiSource
*);
146 boost::shared_ptr
<Evoral::Note
<TimeType
> > find_note (NotePtr
);
147 boost::shared_ptr
<Evoral::Note
<TimeType
> > find_note (gint note_id
);
149 InsertMergePolicy
insert_merge_policy () const;
150 void set_insert_merge_policy (InsertMergePolicy
);
152 boost::shared_ptr
<Evoral::Control
> control_factory(const Evoral::Parameter
& id
);
155 int resolve_overlaps_unlocked (const NotePtr
, void* arg
= 0);
158 struct WriteLockImpl
: public AutomatableSequence
<TimeType
>::WriteLockImpl
{
159 WriteLockImpl(Glib::Mutex::Lock
* source_lock
, Glib::RWLock
& s
, Glib::Mutex
& c
)
160 : AutomatableSequence
<TimeType
>::WriteLockImpl(s
, c
)
161 , source_lock(source_lock
)
166 Glib::Mutex::Lock
* source_lock
;
170 virtual WriteLock
edit_lock();
171 virtual WriteLock
write_lock();
174 friend class DeltaCommand
;
176 void source_interpolation_changed (Evoral::Parameter
, Evoral::ControlList::InterpolationStyle
);
177 void control_list_interpolation_changed (Evoral::Parameter
, Evoral::ControlList::InterpolationStyle
);
179 PBD::ScopedConnectionList _midi_source_connections
;
181 // We cannot use a boost::shared_ptr here to avoid a retain cycle
182 MidiSource
* _midi_source
;
183 InsertMergePolicy _insert_merge_policy
;
186 } /* namespace ARDOUR */
188 #endif /* __ardour_midi_model_h__ */