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__
25 #include <boost/utility.hpp>
26 #include <glibmm/thread.h>
27 #include <pbd/command.h>
28 #include <ardour/types.h>
29 #include <ardour/midi_buffer.h>
30 #include <ardour/midi_ring_buffer.h>
38 /** This is a slightly higher level (than MidiBuffer) model of MIDI note data.
39 * Currently it only represents note data, which is represented as complete
40 * note events (ie with a start time and a duration) rather than separate
41 * note on and off events (controller data is not here since it's represented
42 * as an AutomationList)
44 class MidiModel : public boost::noncopyable {
47 Note(double time=0, double dur=0, uint8_t note=0, uint8_t vel=0x40);
48 Note(const Note& copy);
50 const MidiModel::Note& operator=(const MidiModel::Note& copy);
52 inline bool operator==(const Note& other)
53 { return time() == other.time() && note() == other.note(); }
55 inline double time() const { return _on_event.time(); }
56 inline double end_time() const { return _off_event.time(); }
57 inline uint8_t note() const { return _on_event.note(); }
58 inline uint8_t velocity() const { return _on_event.velocity(); }
59 inline double duration() const { return _off_event.time() - _on_event.time(); }
61 inline void set_time(double t) { _off_event.time() = t + duration(); _on_event.time() = t; }
62 inline void set_note(uint8_t n) { _on_event.buffer()[1] = n; _off_event.buffer()[1] = n; }
63 inline void set_velocity(uint8_t n) { _on_event.buffer()[2] = n; }
64 inline void set_duration(double d) { _off_event.time() = _on_event.time() + d; }
66 inline MidiEvent& on_event() { return _on_event; }
67 inline MidiEvent& off_event() { return _off_event; }
69 inline const MidiEvent& on_event() const { return _on_event; }
70 inline const MidiEvent& off_event() const { return _off_event; }
73 // Event buffers are self-contained
78 MidiModel(Session& s, size_t size=0);
80 void clear() { _notes.clear(); }
82 NoteMode note_mode() const { return _note_mode; }
83 void set_note_mode(NoteMode mode) { _note_mode = mode; }
86 bool currently_writing() const { return _writing; }
87 void end_write(bool delete_stuck=false);
89 size_t read (MidiRingBuffer& dst, nframes_t start, nframes_t nframes, nframes_t stamp_offset) const;
91 /** Resizes vector if necessary (NOT realtime safe) */
92 void append(const MidiBuffer& data);
94 /** Resizes vector if necessary (NOT realtime safe) */
95 void append(double time, size_t size, const Byte* in_buffer);
97 inline const Note& note_at(unsigned i) const { return _notes[i]; }
99 inline size_t n_notes() const { return _notes.size(); }
101 typedef std::vector<Note> Notes;
103 inline static bool note_time_comparator (const Note& a, const Note& b) {
104 return a.time() < b.time();
107 struct LaterNoteEndComparator {
108 typedef const Note* value_type;
109 inline bool operator()(const Note* const a, const Note* const b) {
110 return a->end_time() > b->end_time();
114 inline Notes& notes() { return _notes; }
115 inline const Notes& notes() const { return _notes; }
117 /** Add/Remove notes.
118 * Technically all operations can be implemented as one of these.
120 class DeltaCommand : public Command
123 DeltaCommand (MidiModel& m, const std::string& name)
124 : Command(name), _model(m), _name(name) {}
125 //DeltaCommand (MidiModel&, const XMLNode& node);
127 const std::string& name() const { return _name; }
132 /*int set_state (const XMLNode&);
133 XMLNode& get_state ();*/
135 void add(const Note& note);
136 void remove(const Note& note);
141 std::list<Note> _added_notes;
142 std::list<Note> _removed_notes;
145 MidiModel::DeltaCommand* new_delta_command(const std::string name="midi edit");
146 void apply_command(Command* cmd);
148 bool edited() const { return _edited; }
149 bool write_to(boost::shared_ptr<MidiSource> source);
151 sigc::signal<void> ContentsChanged;
154 friend class DeltaCommand;
155 void add_note_unlocked(const Note& note);
156 void remove_note_unlocked(const Note& note);
158 bool is_sorted() const;
160 void append_note_on(double time, uint8_t note, uint8_t velocity);
161 void append_note_off(double time, uint8_t note);
170 typedef std::vector<size_t> WriteNotes;
171 WriteNotes _write_notes;
175 // note state for read():
177 typedef std::priority_queue<const Note*,std::vector<const Note*>,
178 LaterNoteEndComparator> ActiveNotes;
180 mutable ActiveNotes _active_notes;
183 } /* namespace ARDOUR */
185 #endif /* __ardour_midi_model_h__ */