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 <pbd/command.h>
27 #include <ardour/types.h>
28 #include <ardour/midi_buffer.h>
29 #include <ardour/midi_ring_buffer.h>
36 /** This is a slightly higher level (than MidiBuffer) model of MIDI note data.
37 * Currently it only represents note data, which is represented as complete
38 * note events (ie with a start time and a duration) rather than separate
39 * note on and off events (controller data is not here since it's represented
40 * as an AutomationList)
42 class MidiModel : public boost::noncopyable {
45 Note(double time=0, double dur=0, uint8_t note=0, uint8_t vel=0x40);
46 Note(const Note& copy);
48 const MidiModel::Note& operator=(const MidiModel::Note& copy);
50 inline bool operator==(const Note& other)
51 { return time() == other.time() && note() == other.note(); }
53 inline double time() const { return _on_event.time(); }
54 inline double end_time() const { return _off_event.time(); }
55 inline uint8_t note() const { return _on_event.note(); }
56 inline uint8_t velocity() const { return _on_event.velocity(); }
57 inline double duration() const { return _off_event.time() - _on_event.time(); }
59 inline void set_time(double t) { _off_event.time() = t + duration(); _on_event.time() = t; }
60 inline void set_note(uint8_t n) { _on_event.buffer()[1] = n; _off_event.buffer()[1] = n; }
61 inline void set_velocity(uint8_t n) { _on_event.buffer()[2] = n; }
62 inline void set_duration(double d) { _off_event.time() = _on_event.time() + d; }
64 inline MidiEvent& on_event() { return _on_event; }
65 inline MidiEvent& off_event() { return _off_event; }
67 inline const MidiEvent& on_event() const { return _on_event; }
68 inline const MidiEvent& off_event() const { return _off_event; }
71 // Event buffers are self-contained
76 MidiModel(Session& s, size_t size=0);
78 void clear() { _notes.clear(); }
80 NoteMode note_mode() const { return _note_mode; }
81 void set_note_mode(NoteMode mode) { _note_mode = mode; }
84 bool currently_writing() const { return _writing; }
85 void end_write(bool delete_stuck=false);
87 size_t read (MidiRingBuffer& dst, nframes_t start, nframes_t nframes, nframes_t stamp_offset) const;
89 /** Resizes vector if necessary (NOT realtime safe) */
90 void append(const MidiBuffer& data);
92 /** Resizes vector if necessary (NOT realtime safe) */
93 void append(double time, size_t size, const Byte* in_buffer);
95 inline const Note& note_at(unsigned i) const { return _notes[i]; }
97 inline size_t n_notes() const { return _notes.size(); }
99 typedef std::vector<Note> Notes;
101 inline static bool note_time_comparator (const Note& a, const Note& b) {
102 return a.time() < b.time();
105 struct LaterNoteEndComparator {
106 typedef const Note* value_type;
107 inline bool operator()(const Note* const a, const Note* const b) {
108 return a->end_time() > b->end_time();
112 inline Notes& notes() { return _notes; }
113 inline const Notes& notes() const { return _notes; }
115 /** Add/Remove notes.
116 * Technically all operations can be implemented as one of these.
118 class DeltaCommand : public Command
121 DeltaCommand (MidiModel& m, const std::string& name)
122 : Command(name), _model(m), _name(name) {}
123 //DeltaCommand (MidiModel&, const XMLNode& node);
125 const std::string& name() const { return _name; }
130 /*int set_state (const XMLNode&);
131 XMLNode& get_state ();*/
133 void add(const Note& note);
134 void remove(const Note& note);
139 std::list<Note> _added_notes;
140 std::list<Note> _removed_notes;
143 MidiModel::DeltaCommand* new_delta_command(const std::string name="midi edit");
144 void apply_command(Command* cmd);
146 bool write_new_source(const std::string& path);
148 sigc::signal<void> ContentsChanged;
151 friend class DeltaCommand;
152 void add_note(const Note& note);
153 void remove_note(const Note& note);
155 bool is_sorted() const;
157 void append_note_on(double time, uint8_t note, uint8_t velocity);
158 void append_note_off(double time, uint8_t note);
165 typedef std::vector<size_t> WriteNotes;
166 WriteNotes _write_notes;
169 // note state for read():
171 typedef std::priority_queue<const Note*,std::vector<const Note*>,
172 LaterNoteEndComparator> ActiveNotes;
174 mutable ActiveNotes _active_notes;
177 } /* namespace ARDOUR */
179 #endif /* __ardour_midi_model_h__ */