diff options
author | David Robillard <d@drobilla.net> | 2009-02-02 02:36:05 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2009-02-02 02:36:05 +0000 |
commit | 166ef64e3db4ab72b7b1e7455234e2b9ceddf6d8 (patch) | |
tree | 0f28067a301556c5c0a67091c691c82960db57c1 | |
parent | ead5dd45689be089d79a4a5daad88da737ca4cd9 (diff) |
Make (MIDI) event time stamp type a template parameter.
git-svn-id: svn://localhost/ardour2/branches/3.0@4473 d708f5d6-7413-0410-9779-e7cbd77b26cf
54 files changed, 534 insertions, 424 deletions
diff --git a/gtk2_ardour/canvas-hit.h b/gtk2_ardour/canvas-hit.h index fa90075a0c..c4578b3530 100644 --- a/gtk2_ardour/canvas-hit.h +++ b/gtk2_ardour/canvas-hit.h @@ -29,11 +29,13 @@ namespace Canvas { class CanvasHit : public Diamond, public CanvasNoteEvent { public: + typedef Evoral::Note<double> NoteType; + CanvasHit( - MidiRegionView& region, - Group& group, - double size, - const boost::shared_ptr<Evoral::Note> note = boost::shared_ptr<Evoral::Note>()) + MidiRegionView& region, + Group& group, + double size, + const boost::shared_ptr<NoteType> note = boost::shared_ptr<NoteType>()) : Diamond(group, size), CanvasNoteEvent(region, this, note) { diff --git a/gtk2_ardour/canvas-note-event.cc b/gtk2_ardour/canvas-note-event.cc index 326d502104..aa296d1fb2 100644 --- a/gtk2_ardour/canvas-note-event.cc +++ b/gtk2_ardour/canvas-note-event.cc @@ -39,7 +39,7 @@ const uint32_t CanvasNoteEvent::midi_channel_colors[16] = { }; CanvasNoteEvent::CanvasNoteEvent(MidiRegionView& region, Item* item, - const boost::shared_ptr<Evoral::Note> note) + const boost::shared_ptr<NoteType> note) : _region(region) , _item(item) , _text(0) diff --git a/gtk2_ardour/canvas-note-event.h b/gtk2_ardour/canvas-note-event.h index ee22e00dac..1f22a5b797 100644 --- a/gtk2_ardour/canvas-note-event.h +++ b/gtk2_ardour/canvas-note-event.h @@ -32,7 +32,7 @@ class Editor; class MidiRegionView; -namespace Evoral { class Note; } +namespace Evoral { template<typename T> class Note; } namespace Gnome { namespace Canvas { @@ -51,10 +51,11 @@ namespace Canvas { */ class CanvasNoteEvent : public sigc::trackable, public InteractiveItem { public: + typedef Evoral::Note<double> NoteType; CanvasNoteEvent( - MidiRegionView& region, - Item* item, - const boost::shared_ptr<Evoral::Note> note = boost::shared_ptr<Evoral::Note>()); + MidiRegionView& region, + Item* item, + const boost::shared_ptr<NoteType> note = boost::shared_ptr<NoteType>()); virtual ~CanvasNoteEvent(); @@ -87,7 +88,7 @@ public: virtual double x2() = 0; virtual double y2() = 0; - const boost::shared_ptr<Evoral::Note> note() const { return _note; } + const boost::shared_ptr<NoteType> note() const { return _note; } inline static uint32_t meter_style_fill_color(uint8_t vel) { @@ -116,14 +117,14 @@ public: protected: enum State { None, Pressed, Dragging }; - MidiRegionView& _region; - Item* const _item; - InteractiveText* _text; - Widget* _channel_selector_widget; - State _state; - const boost::shared_ptr<Evoral::Note> _note; - bool _own_note; - bool _selected; + MidiRegionView& _region; + Item* const _item; + InteractiveText* _text; + Widget* _channel_selector_widget; + State _state; + const boost::shared_ptr<NoteType> _note; + bool _own_note; + bool _selected; }; } // namespace Gnome diff --git a/gtk2_ardour/canvas-note.h b/gtk2_ardour/canvas-note.h index 30cbad6c25..0f5d428ef1 100644 --- a/gtk2_ardour/canvas-note.h +++ b/gtk2_ardour/canvas-note.h @@ -31,6 +31,8 @@ namespace Canvas { class CanvasNote : public SimpleRect, public CanvasNoteEvent { public: + typedef Evoral::Note<double> NoteType; + double x1() { return property_x1(); } double y1() { return property_y1(); } double x2() { return property_x2(); } @@ -53,9 +55,9 @@ public: }; CanvasNote( - MidiRegionView& region, - Group& group, - const boost::shared_ptr<Evoral::Note> note = boost::shared_ptr<Evoral::Note>()) + MidiRegionView& region, + Group& group, + const boost::shared_ptr<NoteType> note = boost::shared_ptr<NoteType>()) : SimpleRect(group), CanvasNoteEvent(region, this, note), _note_state(None) { diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index b00a4a5550..a090c1e566 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -456,7 +456,7 @@ MidiRegionView::create_note_at(double x, double y, double length) new_note_length = snap_to_frame(new_note_time_position_relative + new_note_length) + _region->start() - new_note_time; - const boost::shared_ptr<Evoral::Note> new_note(new Evoral::Note( + const boost::shared_ptr<NoteType> new_note(new NoteType( 0, new_note_time, new_note_length, (uint8_t)note, 0x40)); view->update_note_range(new_note->note()); @@ -504,7 +504,7 @@ MidiRegionView::start_delta_command(string name) } void -MidiRegionView::command_add_note(const boost::shared_ptr<Evoral::Note> note, bool selected) +MidiRegionView::command_add_note(const boost::shared_ptr<NoteType> note, bool selected) { if (_delta_command) _delta_command->add(note); @@ -889,7 +889,7 @@ MidiRegionView::extend_active_notes() } void -MidiRegionView::play_midi_note(boost::shared_ptr<Evoral::Note> note) +MidiRegionView::play_midi_note(boost::shared_ptr<NoteType> note) { if (!trackview.editor().sound_notes()) { return; @@ -907,7 +907,7 @@ MidiRegionView::play_midi_note(boost::shared_ptr<Evoral::Note> note) } bool -MidiRegionView::play_midi_note_off(boost::shared_ptr<Evoral::Note> note) +MidiRegionView::play_midi_note_off(boost::shared_ptr<NoteType> note) { RouteUI* route_ui = dynamic_cast<RouteUI*> (&trackview); assert(route_ui); @@ -925,7 +925,7 @@ MidiRegionView::play_midi_note_off(boost::shared_ptr<Evoral::Note> note) * event arrives, to properly display the note. */ void -MidiRegionView::add_note(const boost::shared_ptr<Evoral::Note> note) +MidiRegionView::add_note(const boost::shared_ptr<NoteType> note) { assert(note->time() >= 0); assert(midi_view()->note_mode() == Sustained || midi_view()->note_mode() == Percussive); @@ -967,7 +967,7 @@ MidiRegionView::add_note(const boost::shared_ptr<Evoral::Note> note) // finish the old note rectangle if (_active_notes[note->note()]) { CanvasNote* const old_rect = _active_notes[note->note()]; - boost::shared_ptr<Evoral::Note> old_note = old_rect->note(); + boost::shared_ptr<NoteType> old_note = old_rect->note(); cerr << "MidiModel: WARNING: Note has length 0: chan " << old_note->channel() << "note " << (int)old_note->note() << " @ " << old_note->time() << endl; /* FIXME: How large to make it? Make it a diamond? */ @@ -1338,7 +1338,7 @@ MidiRegionView::note_dropped(CanvasNoteEvent* ev, double dt, uint8_t dnote) Selection::iterator next = i; ++next; - const boost::shared_ptr<Evoral::Note> copy(new Evoral::Note(*(*i)->note().get())); + const boost::shared_ptr<NoteType> copy(new NoteType(*(*i)->note().get())); // we need to snap here again in nframes64_t in order to be sample accurate double new_note_time = (*i)->note()->time(); @@ -1530,7 +1530,7 @@ MidiRegionView::commit_resizing(CanvasNote::NoteEnd note_end, double event_x, bo // transform to region start relative current_frame += _region->start(); - const boost::shared_ptr<Evoral::Note> copy(new Evoral::Note(*(canvas_note->note().get()))); + const boost::shared_ptr<NoteType> copy(new NoteType(*(canvas_note->note().get()))); // resize beginning of note if (note_end == CanvasNote::NOTE_ON && current_frame < copy->end_time()) { @@ -1556,7 +1556,7 @@ MidiRegionView::commit_resizing(CanvasNote::NoteEnd note_end, double event_x, bo void MidiRegionView::change_note_velocity(CanvasNoteEvent* event, int8_t velocity, bool relative) { - const boost::shared_ptr<Evoral::Note> copy(new Evoral::Note(*(event->note().get()))); + const boost::shared_ptr<NoteType> copy(new NoteType(*(event->note().get()))); if (relative) { uint8_t new_velocity = copy->velocity() + velocity; @@ -1598,7 +1598,7 @@ MidiRegionView::change_channel(uint8_t channel) ++next; CanvasNoteEvent* event = *i; - const boost::shared_ptr<Evoral::Note> copy(new Evoral::Note(*(event->note().get()))); + const boost::shared_ptr<NoteType> copy(new NoteType(*(event->note().get()))); copy->set_channel(channel); diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index 6dc8e67565..16b11e176b 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -58,6 +58,8 @@ class AutomationRegionView; class MidiRegionView : public RegionView { public: + typedef Evoral::Note<ARDOUR::MidiModel::TimeType> NoteType; + MidiRegionView (ArdourCanvas::Group *, RouteTimeAxisView&, boost::shared_ptr<ARDOUR::MidiRegion>, @@ -91,7 +93,7 @@ class MidiRegionView : public RegionView GhostRegion* add_ghost (TimeAxisView&); - void add_note(const boost::shared_ptr<Evoral::Note> note); + void add_note(const boost::shared_ptr<NoteType> note); void resolve_note(uint8_t note_num, double end_time); struct ControlEvent @@ -159,7 +161,7 @@ class MidiRegionView : public RegionView void display_model(boost::shared_ptr<ARDOUR::MidiModel> model); void start_delta_command(string name = "midi edit"); - void command_add_note(const boost::shared_ptr<Evoral::Note> note, bool selected); + void command_add_note(const boost::shared_ptr<NoteType> note, bool selected); void command_remove_note(ArdourCanvas::CanvasNoteEvent* ev); void apply_command(); @@ -264,12 +266,12 @@ class MidiRegionView : public RegionView /** Play the NoteOn event of the given note immediately * and schedule the playback of the corresponding NoteOff event. */ - void play_midi_note(boost::shared_ptr<Evoral::Note> note); + void play_midi_note(boost::shared_ptr<NoteType> note); /** Play the NoteOff-Event of the given note immediately * (scheduled by @ref play_midi_note()). */ - bool play_midi_note_off(boost::shared_ptr<Evoral::Note> note); + bool play_midi_note_off(boost::shared_ptr<NoteType> note); void clear_events(); void switch_source(boost::shared_ptr<ARDOUR::Source> src); @@ -317,7 +319,7 @@ class MidiRegionView : public RegionView /** New notes (created in the current command) which should be selected * when they appear after the command is applied. */ - std::set< boost::shared_ptr<Evoral::Note> > _marked_for_selection; + std::set< boost::shared_ptr<NoteType> > _marked_for_selection; std::vector<NoteResizeData *> _resize_data; }; diff --git a/gtk2_ardour/midi_streamview.cc b/gtk2_ardour/midi_streamview.cc index f3d807af03..0d2abb04fd 100644 --- a/gtk2_ardour/midi_streamview.cc +++ b/gtk2_ardour/midi_streamview.cc @@ -605,7 +605,7 @@ MidiStreamView::update_rec_regions (boost::shared_ptr<MidiModel> data, nframes_t // FIXME: slooooooooow! - const boost::shared_ptr<Evoral::Note> note = data->note_at(i); + const boost::shared_ptr<MidiRegionView::NoteType> note = data->note_at(i); if (note->length() > 0 && note->end_time() + region->position() > start) mrv->resolve_note(note->note(), note->end_time()); diff --git a/libs/ardour/ardour/automatable.h b/libs/ardour/ardour/automatable.h index ca4624f281..98ab28d12d 100644 --- a/libs/ardour/ardour/automatable.h +++ b/libs/ardour/ardour/automatable.h @@ -114,12 +114,13 @@ public: /** Contains notes and controllers */ -class AutomatableSequence : public Automatable, public Evoral::Sequence { +template<typename T> +class AutomatableSequence : public Automatable, public Evoral::Sequence<T> { public: AutomatableSequence(Session& s, size_t size) : Evoral::ControlSet() , Automatable(s) - , Evoral::Sequence(EventTypeMap::instance()) + , Evoral::Sequence<T>(EventTypeMap::instance()) {} }; diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h index 211933c778..03d2e23cbd 100644 --- a/libs/ardour/ardour/diskstream.h +++ b/libs/ardour/ardour/diskstream.h @@ -143,7 +143,8 @@ class Diskstream : public SessionObject void remove_region_from_last_capture (boost::weak_ptr<Region> wregion); - void move_processor_automation (boost::weak_ptr<Processor>, Evoral::RangeMoveList const &); + void move_processor_automation (boost::weak_ptr<Processor>, + list< Evoral::RangeMove<nframes_t> > const &); sigc::signal<void> RecordEnableChanged; sigc::signal<void> SpeedChanged; @@ -209,7 +210,7 @@ class Diskstream : public SessionObject virtual void playlist_changed (Change); virtual void playlist_deleted (boost::weak_ptr<Playlist>); - virtual void playlist_ranges_moved (Evoral::RangeMoveList const &); + virtual void playlist_ranges_moved (list< Evoral::RangeMove<nframes_t> > const &); virtual void transport_stopped (struct tm&, time_t, bool abort) = 0; virtual void transport_looped (nframes_t transport_frame) = 0; diff --git a/libs/ardour/ardour/midi_buffer.h b/libs/ardour/ardour/midi_buffer.h index 36610c61cb..9c5bb294c3 100644 --- a/libs/ardour/ardour/midi_buffer.h +++ b/libs/ardour/ardour/midi_buffer.h @@ -32,6 +32,8 @@ namespace ARDOUR { class MidiBuffer : public Buffer { public: + typedef double TimeType; + MidiBuffer(size_t capacity); ~MidiBuffer(); @@ -41,7 +43,7 @@ public: void copy(const MidiBuffer& copy); - bool push_back(const Evoral::MIDIEvent& event); + bool push_back(const Evoral::MIDIEvent<TimeType>& event); bool push_back(const jack_midi_event_t& event); uint8_t* reserve(double time, size_t size); @@ -54,14 +56,14 @@ public: struct iterator_base { iterator_base<B,E>(B& b, size_t o) : buffer(b), offset(o) {} inline E operator*() const { - uint8_t* ev_start = buffer._data + offset + sizeof(Evoral::EventTime); + uint8_t* ev_start = buffer._data + offset + sizeof(TimeType); return E(EventTypeMap::instance().midi_event_type(*ev_start), - *(Evoral::EventTime*)(buffer._data + offset), + *(TimeType*)(buffer._data + offset), Evoral::midi_event_size(*ev_start) + 1, ev_start); } inline iterator_base<B,E>& operator++() { - uint8_t* ev_start = buffer._data + offset + sizeof(Evoral::EventTime); - offset += sizeof(Evoral::EventTime) + Evoral::midi_event_size(*ev_start) + 1; + uint8_t* ev_start = buffer._data + offset + sizeof(TimeType); + offset += sizeof(TimeType) + Evoral::midi_event_size(*ev_start) + 1; return *this; } inline bool operator!=(const iterator_base<B,E>& other) const { @@ -71,8 +73,8 @@ public: size_t offset; }; - typedef iterator_base<MidiBuffer, Evoral::MIDIEvent> iterator; - typedef iterator_base<const MidiBuffer, const Evoral::MIDIEvent> const_iterator; + typedef iterator_base< MidiBuffer, Evoral::MIDIEvent<TimeType> > iterator; + typedef iterator_base< const MidiBuffer, const Evoral::MIDIEvent<TimeType> > const_iterator; iterator begin() { return iterator(*this, 0); } iterator end() { return iterator(*this, _size); } @@ -81,8 +83,8 @@ public: const_iterator end() const { return const_iterator(*this, _size); } private: - friend class iterator_base<MidiBuffer, Evoral::MIDIEvent>; - friend class iterator_base<const MidiBuffer, const Evoral::MIDIEvent>; + friend class iterator_base< MidiBuffer, Evoral::MIDIEvent<TimeType> >; + friend class iterator_base< const MidiBuffer, const Evoral::MIDIEvent<TimeType> >; size_t _size; ///< Size in bytes of used portion of _data uint8_t* _data; ///< timestamp, event, timestamp, event, ... diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h index 852a329544..8ebbf4ce04 100644 --- a/libs/ardour/ardour/midi_diskstream.h +++ b/libs/ardour/ardour/midi_diskstream.h @@ -170,18 +170,18 @@ class MidiDiskstream : public Diskstream void engage_record_enable (); void disengage_record_enable (); - void check_note_onoffs(Evoral::MIDIEvent &event); + void check_note_onoffs(Evoral::MIDIEvent<MidiBuffer::TimeType> &event); void emit_pending_note_offs(MidiBuffer &dst, nframes_t time); - MidiRingBuffer* _playback_buf; - MidiRingBuffer* _capture_buf; - MidiPort* _source_port; - boost::shared_ptr<SMFSource> _write_source; - nframes_t _last_flush_frame; - NoteMode _note_mode; - MidiStateTracker _midistate_tracker; - volatile gint _frames_written_to_ringbuffer; - volatile gint _frames_read_from_ringbuffer; + MidiRingBuffer<MidiBuffer::TimeType>* _playback_buf; + MidiRingBuffer<MidiBuffer::TimeType>* _capture_buf; + MidiPort* _source_port; + boost::shared_ptr<SMFSource> _write_source; + nframes_t _last_flush_frame; + NoteMode _note_mode; + MidiStateTracker _midistate_tracker; + volatile gint _frames_written_to_ringbuffer; + volatile gint _frames_read_from_ringbuffer; }; }; /* namespace ARDOUR */ diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h index a1a0da7296..fb881ae127 100644 --- a/libs/ardour/ardour/midi_model.h +++ b/libs/ardour/ardour/midi_model.h @@ -47,8 +47,10 @@ class MidiSource; * Because of this MIDI controllers and automatable controllers/widgets/etc * are easily interchangeable. */ -class MidiModel : public AutomatableSequence { +class MidiModel : public AutomatableSequence<double> { public: + typedef double TimeType; + MidiModel(MidiSource* s, size_t size=0); NoteMode note_mode() const { return (percussive() ? Percussive : Sustained); } @@ -71,17 +73,17 @@ public: int set_state (const XMLNode&); XMLNode& get_state (); - void add(const boost::shared_ptr<Evoral::Note> note); - void remove(const boost::shared_ptr<Evoral::Note> note); + void add(const boost::shared_ptr< Evoral::Note<TimeType> > note); + void remove(const boost::shared_ptr< Evoral::Note<TimeType> > note); private: - XMLNode &marshal_note(const boost::shared_ptr<Evoral::Note> note); - boost::shared_ptr<Evoral::Note> unmarshal_note(XMLNode *xml_note); + XMLNode &marshal_note(const boost::shared_ptr< Evoral::Note<TimeType> > note); + boost::shared_ptr< Evoral::Note<TimeType> > unmarshal_note(XMLNode *xml_note); boost::shared_ptr<MidiModel> _model; const std::string _name; - typedef std::list< boost::shared_ptr<Evoral::Note> > NoteList; + typedef std::list< boost::shared_ptr< Evoral::Note<TimeType> > > NoteList; NoteList _added_notes; NoteList _removed_notes; diff --git a/libs/ardour/ardour/midi_playlist.h b/libs/ardour/ardour/midi_playlist.h index 697d80611b..d7fdadb2f5 100644 --- a/libs/ardour/ardour/midi_playlist.h +++ b/libs/ardour/ardour/midi_playlist.h @@ -34,7 +34,7 @@ class Session; class Region; class MidiRegion; class Source; -class MidiRingBuffer; +template<typename T> class MidiRingBuffer; class MidiPlaylist : public ARDOUR::Playlist { @@ -47,7 +47,7 @@ public: ~MidiPlaylist (); - nframes_t read (MidiRingBuffer& buf, + nframes_t read (MidiRingBuffer<double>& buf, nframes_t start, nframes_t cnt, uint32_t chan_n=0); int set_state (const XMLNode&); diff --git a/libs/ardour/ardour/midi_region.h b/libs/ardour/ardour/midi_region.h index 2cbed8f99c..781f815ec5 100644 --- a/libs/ardour/ardour/midi_region.h +++ b/libs/ardour/ardour/midi_region.h @@ -43,11 +43,13 @@ class Playlist; class Session; class MidiFilter; class MidiSource; -class MidiRingBuffer; +template<typename T> class MidiRingBuffer; class MidiRegion : public Region { public: + typedef double TimeType; + ~MidiRegion(); boost::shared_ptr<MidiSource> midi_source (uint32_t n=0) const; @@ -56,13 +58,13 @@ class MidiRegion : public Region virtual nframes64_t read (Sample*, nframes64_t pos, nframes64_t cnt, int channel) const { return 0; } virtual nframes64_t readable_length() const { return length(); } - nframes_t read_at (MidiRingBuffer& dst, + nframes_t read_at (MidiRingBuffer<TimeType>& dst, nframes_t position, nframes_t dur, uint32_t chan_n = 0, NoteMode mode = Sustained) const; - nframes_t master_read_at (MidiRingBuffer& dst, + nframes_t master_read_at (MidiRingBuffer<TimeType>& dst, nframes_t position, nframes_t dur, uint32_t chan_n = 0, @@ -106,7 +108,7 @@ class MidiRegion : public Region MidiRegion (const SourceList &, const XMLNode&); private: - nframes_t _read_at (const SourceList&, MidiRingBuffer& dst, + nframes_t _read_at (const SourceList&, MidiRingBuffer<TimeType>& dst, nframes_t position, nframes_t dur, uint32_t chan_n = 0, diff --git a/libs/ardour/ardour/midi_ring_buffer.h b/libs/ardour/ardour/midi_ring_buffer.h index 7ffdcf3b8c..228479067f 100644 --- a/libs/ardour/ardour/midi_ring_buffer.h +++ b/libs/ardour/ardour/midi_ring_buffer.h @@ -37,16 +37,17 @@ class MidiBuffer; * * [timestamp][type][size][size bytes of raw MIDI][timestamp][type][size](etc...) */ -class MidiRingBuffer : public Evoral::EventRingBuffer { +template<typename T> +class MidiRingBuffer : public Evoral::EventRingBuffer<T> { public: /** @param size Size in bytes. */ MidiRingBuffer(size_t size) - : Evoral::EventRingBuffer(size) + : Evoral::EventRingBuffer<T>(size) , _channel_mask(0x0000FFFF) {} - inline bool read_prefix(Evoral::EventTime* time, Evoral::EventType* type, uint32_t* size); + inline bool read_prefix(T* time, Evoral::EventType* type, uint32_t* size); inline bool read_contents(uint32_t size, uint8_t* buf); size_t read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t offset=0); @@ -86,14 +87,15 @@ private: /** Read the time and size of an event. This call MUST be immediately proceeded * by a call to read_contents (or the read pointer will be garbage). */ +template<typename T> inline bool -MidiRingBuffer::read_prefix(Evoral::EventTime* time, Evoral::EventType* type, uint32_t* size) +MidiRingBuffer<T>::read_prefix(T* time, Evoral::EventType* type, uint32_t* size) { - bool success = Evoral::EventRingBuffer::full_read(sizeof(Evoral::EventTime), (uint8_t*)time); + bool success = Evoral::EventRingBuffer<T>::full_read(sizeof(T), (uint8_t*)time); if (success) - success = Evoral::EventRingBuffer::full_read(sizeof(Evoral::EventType), (uint8_t*)type); + success = Evoral::EventRingBuffer<T>::full_read(sizeof(Evoral::EventType), (uint8_t*)type); if (success) - success = Evoral::EventRingBuffer::full_read(sizeof(uint32_t), (uint8_t*)size); + success = Evoral::EventRingBuffer<T>::full_read(sizeof(uint32_t), (uint8_t*)size); return success; } @@ -102,10 +104,11 @@ MidiRingBuffer::read_prefix(Evoral::EventTime* time, Evoral::EventType* type, ui /** Read the content of an event. This call MUST be immediately preceded * by a call to read_prefix (or the returned even will be garbage). */ +template<typename T> inline bool -MidiRingBuffer::read_contents(uint32_t size, uint8_t* buf) +MidiRingBuffer<T>::read_contents(uint32_t size, uint8_t* buf) { - return Evoral::EventRingBuffer::full_read(size, buf); + return Evoral::EventRingBuffer<T>::full_read(size, buf); } diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h index 895dcb25cc..c0b105decd 100644 --- a/libs/ardour/ardour/midi_source.h +++ b/libs/ardour/ardour/midi_source.h @@ -39,12 +39,14 @@ using std::string; namespace ARDOUR { -class MidiRingBuffer; +template<typename T> class MidiRingBuffer; /** Source for MIDI data */ class MidiSource : public Source { public: + typedef double TimeType; + MidiSource (Session& session, string name); MidiSource (Session& session, const XMLNode&); virtual ~MidiSource (); @@ -55,10 +57,10 @@ class MidiSource : public Source virtual uint32_t n_channels () const { return 1; } // FIXME: integrate this with the Readable::read interface somehow - virtual nframes_t midi_read (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const; - virtual nframes_t midi_write (MidiRingBuffer& src, nframes_t cnt); + virtual nframes_t midi_read (MidiRingBuffer<TimeType>& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const; + virtual nframes_t midi_write (MidiRingBuffer<TimeType>& src, nframes_t cnt); - virtual void append_event_unlocked(EventTimeUnit unit, const Evoral::Event& ev) = 0; + virtual void append_event_unlocked(EventTimeUnit unit, const Evoral::Event<TimeType>& ev) = 0; virtual void mark_for_remove() = 0; virtual void mark_streaming_midi_write_started (NoteMode mode, nframes_t start_time); @@ -99,8 +101,8 @@ class MidiSource : public Source //virtual int flush_header() = 0; //virtual int flush_footer() = 0; - virtual nframes_t read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const = 0; - virtual nframes_t write_unlocked (MidiRingBuffer& dst, nframes_t cnt) = 0; + virtual nframes_t read_unlocked (MidiRingBuffer<TimeType>& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const = 0; + virtual nframes_t write_unlocked (MidiRingBuffer<TimeType>& dst, nframes_t cnt) = 0; mutable Glib::Mutex _lock; string _captured_for; diff --git a/libs/ardour/ardour/midi_state_tracker.h b/libs/ardour/ardour/midi_state_tracker.h index bd8bdb650a..0bc7897b53 100644 --- a/libs/ardour/ardour/midi_state_tracker.h +++ b/libs/ardour/ardour/midi_state_tracker.h @@ -40,7 +40,7 @@ public: void resolve_notes (MidiBuffer& buffer, nframes_t time); private: - void track_note_onoffs(const Evoral::MIDIEvent& event); + void track_note_onoffs(const Evoral::MIDIEvent<MidiBuffer::TimeType>& event); std::bitset<128*16> _active_notes; }; diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h index 56f73fbe9d..09c64c2978 100644 --- a/libs/ardour/ardour/midi_track.h +++ b/libs/ardour/ardour/midi_track.h @@ -104,8 +104,8 @@ private: void set_state_part_two (); void set_state_part_three (); - MidiRingBuffer _immediate_events; - NoteMode _note_mode; + MidiRingBuffer<double> _immediate_events; + NoteMode _note_mode; }; } /* namespace ARDOUR*/ diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index cdde9855b2..d2920fb610 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -128,7 +128,7 @@ class Playlist : public SessionObject, public boost::enable_shared_from_this<Pla sigc::signal<void> Modified; sigc::signal<void> NameChanged; sigc::signal<void> LengthChanged; - sigc::signal<void, Evoral::RangeMoveList const &> RangesMoved; + sigc::signal<void, list< Evoral::RangeMove<nframes_t> > const &> RangesMoved; static string bump_name (string old_name, Session&); @@ -190,7 +190,7 @@ class Playlist : public SessionObject, public boost::enable_shared_from_this<Pla RegionList pending_bounds; bool pending_modified; bool pending_length; - Evoral::RangeMoveList pending_range_moves; + list< Evoral::RangeMove<nframes_t> > pending_range_moves; bool save_on_thaw; string last_save_reason; uint32_t in_set_state; diff --git a/libs/ardour/ardour/smf_source.h b/libs/ardour/ardour/smf_source.h index 0c0dba3d96..e92ae59c3f 100644 --- a/libs/ardour/ardour/smf_source.h +++ b/libs/ardour/ardour/smf_source.h @@ -27,14 +27,14 @@ #include <ardour/midi_source.h> #include <evoral/SMF.hpp> -namespace Evoral { class Event; } +namespace Evoral { template<typename T> class Event; } namespace ARDOUR { -class MidiRingBuffer; +template<typename T> class MidiRingBuffer; /** Standard Midi File (Type 0) Source */ -class SMFSource : public MidiSource, public Evoral::SMF { +class SMFSource : public MidiSource, public Evoral::SMF<double> { public: enum Flag { Writable = 0x1, @@ -74,7 +74,7 @@ class SMFSource : public MidiSource, public Evoral::SMF { void set_allow_remove_if_empty (bool yn); void mark_for_remove(); - void append_event_unlocked(EventTimeUnit unit, const Evoral::Event& ev); + void append_event_unlocked(EventTimeUnit unit, const Evoral::Event<double>& ev); int move_to_trash (const string trash_dir_name); @@ -100,14 +100,14 @@ class SMFSource : public MidiSource, public Evoral::SMF { int init (string idstr, bool must_exist); nframes_t read_unlocked ( - MidiRingBuffer& dst, + MidiRingBuffer<double>& dst, nframes_t start, nframes_t cn, nframes_t stamp_offset, nframes_t negative_stamp_offset) const; nframes_t write_unlocked ( - MidiRingBuffer& src, + MidiRingBuffer<double>& src, nframes_t cnt); bool find (std::string path, bool must_exist, bool& is_new); diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index 54d5360aa3..d277e4c37e 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -418,12 +418,18 @@ Diskstream::remove_region_from_last_capture (boost::weak_ptr<Region> wregion) } void -Diskstream::playlist_ranges_moved (Evoral::RangeMoveList const & movements) +Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<nframes_t> > const & movements_frames) { if (Config->get_automation_follows_regions () == false) { return; } + list< Evoral::RangeMove<double> > movements; + for (list< Evoral::RangeMove<nframes_t> >::const_iterator i = movements_frames.begin(); + i != movements_frames.end(); ++i) { + movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to)); + } + /* move gain automation */ boost::shared_ptr<AutomationList> gain_alist = _io->gain_control()->alist(); XMLNode & before = gain_alist->get_state (); @@ -452,18 +458,25 @@ Diskstream::playlist_ranges_moved (Evoral::RangeMoveList const & movements) /* XXX: ewww */ Route * route = dynamic_cast<Route*> (_io); if (route) { - route->foreach_processor (sigc::bind (sigc::mem_fun (*this, &Diskstream::move_processor_automation), movements)); + route->foreach_processor (sigc::bind (sigc::mem_fun (*this, &Diskstream::move_processor_automation), movements_frames)); } } void -Diskstream::move_processor_automation (boost::weak_ptr<Processor> p, Evoral::RangeMoveList const & movements) +Diskstream::move_processor_automation (boost::weak_ptr<Processor> p, + list< Evoral::RangeMove<nframes_t> > const & movements_frames) { boost::shared_ptr<Processor> processor (p.lock ()); if (!processor) { return; } + list< Evoral::RangeMove<double> > movements; + for (list< Evoral::RangeMove<nframes_t> >::const_iterator i = movements_frames.begin(); + i != movements_frames.end(); ++i) { + movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to)); + } + set<Evoral::Parameter> const a = processor->what_can_be_automated (); for (set<Evoral::Parameter>::iterator i = a.begin (); i != a.end (); ++i) { diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc index 6b3871c814..76975d8237 100644 --- a/libs/ardour/import.cc +++ b/libs/ardour/import.cc @@ -312,7 +312,7 @@ static void write_midi_data_to_new_files (Evoral::SMFReader* source, Session::import_status& status, vector<boost::shared_ptr<Source> >& newfiles) { - Evoral::Event ev(0, 0.0, 4, NULL, true); + Evoral::Event<double> ev(0, 0.0, 4, NULL, true); status.progress = 0.0f; diff --git a/libs/ardour/meter.cc b/libs/ardour/meter.cc index 4839223f40..39d7f63221 100644 --- a/libs/ardour/meter.cc +++ b/libs/ardour/meter.cc @@ -50,7 +50,7 @@ PeakMeter::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_f // GUI needs a better MIDI meter, not much information can be // expressed through peaks alone for (MidiBuffer::iterator i = bufs.get_midi(n).begin(); i != bufs.get_midi(n).end(); ++i) { - const Evoral::MIDIEvent ev(*i, false); + const Evoral::MIDIEvent<double> ev(*i, false); if (ev.is_note_on()) { const float this_vel = log(ev.buffer()[2] / 127.0 * (M_E*M_E-M_E) + M_E) - 1.0; //printf("V %d -> %f\n", (int)((Byte)ev.buffer[2]), this_vel); diff --git a/libs/ardour/midi_buffer.cc b/libs/ardour/midi_buffer.cc index df4ee13558..f724aac100 100644 --- a/libs/ardour/midi_buffer.cc +++ b/libs/ardour/midi_buffer.cc @@ -99,7 +99,7 @@ MidiBuffer::read_from(const Buffer& src, nframes_t nframes, nframes_t offset) } for (MidiBuffer::const_iterator i = msrc.begin(); i != msrc.end(); ++i) { - const Evoral::MIDIEvent ev(*i, false); + const Evoral::MIDIEvent<TimeType> ev(*i, false); /*cout << this << " MidiBuffer::read_from event type: " << int(ev.type()) << " time: " << ev.time() << " size: " << ev.size() << " status: " << (int)*ev.buffer() << " buffer size: " << _size << endl;*/ @@ -126,16 +126,16 @@ MidiBuffer::read_from(const Buffer& src, nframes_t nframes, nframes_t offset) * @return false if operation failed (not enough room) */ bool -MidiBuffer::push_back(const Evoral::MIDIEvent& ev) +MidiBuffer::push_back(const Evoral::MIDIEvent<TimeType>& ev) { - const size_t stamp_size = sizeof(Evoral::EventTime); + const size_t stamp_size = sizeof(TimeType); if (_size + stamp_size + ev.size() >= _capacity) { cerr << "MidiBuffer::push_back failed (buffer is full)" << endl; return false; } uint8_t* const write_loc = _data + _size; - *((Evoral::EventTime*)write_loc) = ev.time(); + *((TimeType*)write_loc) = ev.time(); memcpy(write_loc + stamp_size, ev.buffer(), ev.size()); _size += stamp_size + ev.size(); @@ -155,14 +155,14 @@ MidiBuffer::push_back(const Evoral::MIDIEvent& ev) bool MidiBuffer::push_back(const jack_midi_event_t& ev) { - const size_t stamp_size = sizeof(Evoral::EventTime); + const size_t stamp_size = sizeof(TimeType); if (_size + stamp_size + ev.size >= _capacity) { cerr << "MidiBuffer::push_back failed (buffer is full)" << endl; return false; } uint8_t* const write_loc = _data + _size; - *((Evoral::EventTime*)write_loc) = ev.time; + *((TimeType*)write_loc) = ev.time; memcpy(write_loc + stamp_size, ev.buffer, ev.size); _size += stamp_size + ev.size; @@ -180,15 +180,15 @@ MidiBuffer::push_back(const jack_midi_event_t& ev) * location, or the buffer will be corrupted and very nasty things will happen. */ uint8_t* -MidiBuffer::reserve(Evoral::EventTime time, size_t size) +MidiBuffer::reserve(TimeType time, size_t size) { - const size_t stamp_size = sizeof(Evoral::EventTime); + const size_t stamp_size = sizeof(TimeType); if (_size + stamp_size + size >= _capacity) { return 0; } uint8_t* const write_loc = _data + _size; - *((Evoral::EventTime*)write_loc) = time; + *((TimeType*)write_loc) = time; _size += stamp_size + size; _silent = false; diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc index cd50fc950a..b80f6217cf 100644 --- a/libs/ardour/midi_diskstream.cc +++ b/libs/ardour/midi_diskstream.cc @@ -121,8 +121,9 @@ MidiDiskstream::init (Diskstream::Flag f) set_block_size (_session.get_block_size()); allocate_temporary_buffers (); - _playback_buf = new MidiRingBuffer (_session.midi_diskstream_buffer_size()); - _capture_buf = new MidiRingBuffer (_session.midi_diskstream_buffer_size()); + const size_t size = _session.midi_diskstream_buffer_size(); + _playback_buf = new MidiRingBuffer<MidiBuffer::TimeType> (size); + _capture_buf = new MidiRingBuffer<MidiBuffer::TimeType> (size); _n_channels = ChanCount(DataType::MIDI, 1); @@ -521,7 +522,7 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t // Pump entire port buffer into the ring buffer (FIXME: split cycles?) MidiBuffer& buf = _source_port->get_midi_buffer(nframes, offset); for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) { - const Evoral::MIDIEvent ev(*i, false); + const Evoral::MIDIEvent<MidiBuffer::TimeType> ev(*i, false); assert(ev.buffer()); _capture_buf->write(ev.time() + transport_frame, ev.type(), ev.size(), ev.buffer()); } diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc index 59776c59d6..99f87e845c 100644 --- a/libs/ardour/midi_model.cc +++ b/libs/ardour/midi_model.cc @@ -38,7 +38,7 @@ using namespace ARDOUR; using namespace PBD; MidiModel::MidiModel(MidiSource *s, size_t size) - : AutomatableSequence(s->session(), size) + : AutomatableSequence<TimeType>(s->session(), size) , _midi_source(s) { cerr << "MidiModel \"" << s->name() << "\" constructed: " << this << endl; @@ -90,7 +90,7 @@ MidiModel::DeltaCommand::DeltaCommand(boost::shared_ptr<MidiModel> m, } void -MidiModel::DeltaCommand::add(const boost::shared_ptr<Evoral::Note> note) +MidiModel::DeltaCommand::add(const boost::shared_ptr< Evoral::Note<TimeType> > note) { //cerr << "MEC: apply" << endl; _removed_notes.remove(note); @@ -98,7 +98,7 @@ MidiModel::DeltaCommand::add(const boost::shared_ptr<Evoral::Note> note) } void -MidiModel::DeltaCommand::remove(const boost::shared_ptr<Evoral::Note> note) +MidiModel::DeltaCommand::remove(const boost::shared_ptr< Evoral::Note<TimeType> > note) { //cerr << "MEC: remove" << endl; _added_notes.remove(note); @@ -156,7 +156,7 @@ MidiModel::DeltaCommand::undo() } XMLNode& -MidiModel::DeltaCommand::marshal_note(const boost::shared_ptr<Evoral::Note> note) +MidiModel::DeltaCommand::marshal_note(const boost::shared_ptr< Evoral::Note<TimeType> > note) { XMLNode *xml_note = new XMLNode("note"); ostringstream note_str(ios::ate); @@ -182,7 +182,7 @@ MidiModel::DeltaCommand::marshal_note(const boost::shared_ptr<Evoral::Note> note return *xml_note; } -boost::shared_ptr<Evoral::Note> +boost::shared_ptr< Evoral::Note<double> > MidiModel::DeltaCommand::unmarshal_note(XMLNode *xml_note) { unsigned int note; @@ -232,7 +232,8 @@ MidiModel::DeltaCommand::unmarshal_note(XMLNode *xml_note) velocity = 127; } - boost::shared_ptr<Evoral::Note> note_ptr(new Evoral::Note(channel, time, length, note, velocity)); + boost::shared_ptr< Evoral::Note<TimeType> > note_ptr(new Evoral::Note<TimeType>( + channel, time, length, note, velocity)); return note_ptr; } @@ -296,7 +297,7 @@ MidiModel::write_to(boost::shared_ptr<MidiSource> source) const bool old_percussive = percussive(); set_percussive(false); - for (Evoral::Sequence::const_iterator i = begin(); i != end(); ++i) { + for (Evoral::Sequence<TimeType>::const_iterator i = begin(); i != end(); ++i) { source->append_event_unlocked(Frames, *i); } diff --git a/libs/ardour/midi_playlist.cc b/libs/ardour/midi_playlist.cc index 7403438483..7139447a19 100644 --- a/libs/ardour/midi_playlist.cc +++ b/libs/ardour/midi_playlist.cc @@ -124,7 +124,7 @@ struct RegionSortByLayer { /** Returns the number of frames in time duration read (eg could be large when 0 events are read) */ nframes_t -MidiPlaylist::read (MidiRingBuffer& dst, nframes_t start, +MidiPlaylist::read (MidiRingBuffer<MidiBuffer::TimeType>& dst, nframes_t start, nframes_t dur, unsigned chan_n) { /* this function is never called from a realtime thread, so diff --git a/libs/ardour/midi_port.cc b/libs/ardour/midi_port.cc index c69dc7fc05..ead5f5aeac 100644 --- a/libs/ardour/midi_port.cc +++ b/libs/ardour/midi_port.cc @@ -147,7 +147,7 @@ MidiPort::flush_buffers (nframes_t nframes, nframes_t offset) void* jack_buffer = jack_port_get_buffer (_jack_port, nframes); for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) { - const Evoral::Event& ev = *i; + const Evoral::Event<double>& ev = *i; // event times should be frames, relative to cycle start assert(ev.time() >= 0); assert(ev.time() < (nframes+offset)); diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc index e29fb1e659..f0c4b2297e 100644 --- a/libs/ardour/midi_region.cc +++ b/libs/ardour/midi_region.cc @@ -117,19 +117,19 @@ MidiRegion::~MidiRegion () } nframes_t -MidiRegion::read_at (MidiRingBuffer& out, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const +MidiRegion::read_at (MidiRingBuffer<TimeType>& out, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const { return _read_at (_sources, out, position, dur, chan_n, mode); } nframes_t -MidiRegion::master_read_at (MidiRingBuffer& out, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const +MidiRegion::master_read_at (MidiRingBuffer<TimeType>& out, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const { return _read_at (_master_sources, out, position, dur, chan_n, mode); } nframes_t -MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer& dst, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const +MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer<TimeType>& dst, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const { /*cerr << "MidiRegion " << _name << "._read_at(" << position << ") - " << position << " duration: " << dur << endl;*/ diff --git a/libs/ardour/midi_ring_buffer.cc b/libs/ardour/midi_ring_buffer.cc index e09406a683..6327ab45c2 100644 --- a/libs/ardour/midi_ring_buffer.cc +++ b/libs/ardour/midi_ring_buffer.cc @@ -29,14 +29,15 @@ namespace ARDOUR { * Timestamps of events returned are relative to start (i.e. event with stamp 0 * occurred at start), with offset added. */ +template<typename T> size_t -MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t offset) +MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t offset) { - if (read_space() == 0) { + if (this->read_space() == 0) { return 0; } - Evoral::EventTime ev_time; + T ev_time; Evoral::EventType ev_type; uint32_t ev_size; @@ -44,9 +45,9 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t //cerr << "MRB read " << start << " .. " << end << " + " << offset << endl; - while (read_space() >= sizeof(Evoral::EventTime) + sizeof(Evoral::EventType) + sizeof(uint32_t)) { + while (this->read_space() >= sizeof(T) + sizeof(Evoral::EventType) + sizeof(uint32_t)) { - full_peek(sizeof(Evoral::EventTime), (uint8_t*)&ev_time); + this->full_peek(sizeof(T), (uint8_t*)&ev_time); if (ev_time > end) { //cerr << "MRB: PAST END (" << ev_time << " : " << end << ")" << endl; @@ -67,7 +68,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t if (ev_type == LoopEventType) { ev_time -= start; ev_time += offset; - Evoral::MIDIEvent loopevent(LoopEventType, ev_time); + Evoral::MIDIEvent<T> loopevent(LoopEventType, ev_time); dst.push_back(loopevent); // We can safely return, without reading the data, because @@ -76,7 +77,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t } uint8_t status; - success = full_peek(sizeof(uint8_t), &status); + success = this->full_peek(sizeof(uint8_t), &status); assert(success); // If this failed, buffer is corrupt, all hope is lost // Ignore event if it doesn't match channel filter @@ -84,7 +85,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t const uint8_t channel = status & 0x0F; if ( !(get_channel_mask() & (1L << channel)) ) { //cerr << "MRB skipping event due to channel mask" << endl; - skip(ev_size); // Advance read pointer to next event + this->skip(ev_size); // Advance read pointer to next event continue; } } @@ -103,7 +104,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t continue; } - success = Evoral::EventRingBuffer::full_read(ev_size, write_loc); + success = Evoral::EventRingBuffer<T>::full_read(ev_size, write_loc); if (success) { if (is_channel_event(status) && get_channel_mode() == ForceChannel) { @@ -121,6 +122,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t return count; } +template class MidiRingBuffer<double>; } // namespace ARDOUR diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc index 2aed2cad28..7adb0f177b 100644 --- a/libs/ardour/midi_source.cc +++ b/libs/ardour/midi_source.cc @@ -101,7 +101,7 @@ MidiSource::set_state (const XMLNode& node) } nframes_t -MidiSource::midi_read (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const +MidiSource::midi_read (MidiRingBuffer<MidiBuffer::TimeType>& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const { Glib::Mutex::Lock lm (_lock); if (_model) { @@ -115,7 +115,7 @@ MidiSource::midi_read (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nfra } nframes_t -MidiSource::midi_write (MidiRingBuffer& dst, nframes_t cnt) +MidiSource::midi_write (MidiRingBuffer<MidiBuffer::TimeType>& dst, nframes_t cnt) { Glib::Mutex::Lock lm (_lock); return write_unlocked (dst, cnt); diff --git a/libs/ardour/midi_state_tracker.cc b/libs/ardour/midi_state_tracker.cc index 3871c139df..e1508717e4 100644 --- a/libs/ardour/midi_state_tracker.cc +++ b/libs/ardour/midi_state_tracker.cc @@ -31,7 +31,7 @@ MidiStateTracker::MidiStateTracker () } void -MidiStateTracker::track_note_onoffs (const Evoral::MIDIEvent &event) +MidiStateTracker::track_note_onoffs (const Evoral::MIDIEvent<MidiBuffer::TimeType>& event) { if (event.is_note_on()) { _active_notes [event.note() + 128 * event.channel()] = true; @@ -46,7 +46,7 @@ MidiStateTracker::track (const MidiBuffer::iterator &from, const MidiBuffer::ite bool ret = false; for (MidiBuffer::iterator i = from; i != to; ++i) { - const Evoral::MIDIEvent ev(*i, false); + const Evoral::MIDIEvent<MidiBuffer::TimeType> ev(*i, false); if (ev.event_type() == LoopEventType) { ret = true; continue; @@ -68,7 +68,8 @@ MidiStateTracker::resolve_notes (MidiBuffer &dst, nframes_t time) for (int note = 0; note < 128; ++note) { if (_active_notes[channel * 128 + note]) { uint8_t buffer[3] = { MIDI_CMD_NOTE_OFF | channel, note, 0 }; - Evoral::MIDIEvent noteoff (time, MIDI_CMD_NOTE_OFF, 3, buffer, false); + Evoral::MIDIEvent<MidiBuffer::TimeType> noteoff + (time, MIDI_CMD_NOTE_OFF, 3, buffer, false); dst.push_back (noteoff); diff --git a/libs/ardour/midi_stretch.cc b/libs/ardour/midi_stretch.cc index 975ec6d714..88aa436b03 100644 --- a/libs/ardour/midi_stretch.cc +++ b/libs/ardour/midi_stretch.cc @@ -87,11 +87,12 @@ MidiStretch::run (boost::shared_ptr<Region> r) boost::shared_ptr<MidiModel> new_model = new_src->model(); new_model->start_write(); - for (Evoral::Sequence::const_iterator i = old_model->begin(); i != old_model->end(); ++i) { + for (Evoral::Sequence<MidiModel::TimeType>::const_iterator i = old_model->begin(); + i != old_model->end(); ++i) { const double new_time = i->time() * _request.time_fraction; // FIXME: double copy - Evoral::Event ev = Evoral::Event(*i, true); + Evoral::Event<MidiModel::TimeType> ev(*i, true); ev.time() = new_time; new_model->append(ev); } diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index 44ba67cb67..8f4c94078d 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -363,7 +363,7 @@ Playlist::notify_region_removed (boost::shared_ptr<Region> r) void Playlist::notify_region_moved (boost::shared_ptr<Region> r) { - Evoral::RangeMove const move (r->last_position (), r->length (), r->position ()); + Evoral::RangeMove<nframes_t> const move (r->last_position (), r->length (), r->position ()); if (holding_state ()) { @@ -371,7 +371,7 @@ Playlist::notify_region_moved (boost::shared_ptr<Region> r) } else { - Evoral::RangeMoveList m; + list< Evoral::RangeMove<nframes_t> > m; m.push_back (move); RangesMoved (m); diff --git a/libs/ardour/quantize.cc b/libs/ardour/quantize.cc index 3b5a264a7b..e4a2809277 100644 --- a/libs/ardour/quantize.cc +++ b/libs/ardour/quantize.cc @@ -69,7 +69,7 @@ Quantize::run (boost::shared_ptr<Region> r) double q_frames = _q * (m.frames_per_bar(t, session.frame_rate()) / (double)m.beats_per_bar()); - for (Evoral::Sequence::Notes::iterator i = model->notes().begin(); + for (Evoral::Sequence<MidiModel::TimeType>::Notes::iterator i = model->notes().begin(); i != model->notes().end(); ++i) { const double new_time = lrint((*i)->time() / q_frames) * q_frames; double new_dur = lrint((*i)->length() / q_frames) * q_frames; diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index 978192dc0a..f4dd5e1534 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -55,7 +55,7 @@ uint64_t SMFSource::header_position_offset; SMFSource::SMFSource (Session& s, std::string path, Flag flags) : MidiSource (s, region_name_from_path(path, false)) - , SMF () + , Evoral::SMF<double> () , _flags (Flag(flags | Writable)) // FIXME: this needs to be writable for now , _allow_remove_if_empty(true) { @@ -128,7 +128,7 @@ SMFSource::init (string pathstr, bool must_exist) /** All stamps in audio frames */ nframes_t -SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const +SMFSource::read_unlocked (MidiRingBuffer<double>& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const { //cerr << "SMF read_unlocked " << name() << " read " << start << ", count=" << cnt << ", offset=" << stamp_offset << endl; @@ -146,7 +146,7 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, n size_t scratch_size = 0; // keep track of scratch to minimize reallocs // FIXME: don't seek to start and search every read (brutal!) - SMF::seek_to_start(); + Evoral::SMF<double>::seek_to_start(); // FIXME: assumes tempo never changes after start const double frames_per_beat = _session.tempo_map().tempo_at(_timeline_position).frames_per_beat( @@ -155,7 +155,7 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, n const uint64_t start_ticks = (uint64_t)((start / frames_per_beat) * ppqn()); - while (!SMF::eof()) { + while (!Evoral::SMF<double>::eof()) { int ret = read_event(&ev_delta_t, &ev_size, &ev_buffer); if (ret == -1) { // EOF //cerr << "SMF - EOF\n"; @@ -194,11 +194,11 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, n /** All stamps in audio frames */ nframes_t -SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt) +SMFSource::write_unlocked (MidiRingBuffer<double>& src, nframes_t cnt) { _write_data_count = 0; - Evoral::EventTime time; + double time; Evoral::EventType type; uint32_t size; @@ -208,7 +208,7 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt) if (_model && ! _model->writing()) _model->start_write(); - Evoral::MIDIEvent ev(0, 0.0, 4, NULL, true); + Evoral::MIDIEvent<double> ev(0, 0.0, 4, NULL, true); while (true) { bool ret = src.peek_time(&time); @@ -251,7 +251,7 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt) make_sure_controls_have_the_right_interpolation(); } - SMF::flush(); + Evoral::SMF<double>::flush(); free(buf); const nframes_t oldlen = _length; @@ -264,7 +264,7 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt) void -SMFSource::append_event_unlocked(EventTimeUnit unit, const Evoral::Event& ev) +SMFSource::append_event_unlocked(EventTimeUnit unit, const Evoral::Event<double>& ev) { if (ev.size() == 0) { cerr << "SMFSource: Warning: skipping empty event" << endl; @@ -299,7 +299,7 @@ SMFSource::append_event_unlocked(EventTimeUnit unit, const Evoral::Event& ev) delta_time = (uint32_t)((ev.time() - last_event_time()) * ppqn()); } - SMF::append_event_unlocked(delta_time, ev); + Evoral::SMF<double>::append_event_unlocked(delta_time, ev); _write_data_count += ev.size(); } @@ -354,7 +354,7 @@ void SMFSource::mark_streaming_midi_write_started (NoteMode mode, nframes_t start_frame) { MidiSource::mark_streaming_midi_write_started (mode, start_frame); - SMF::begin_write (start_frame); + Evoral::SMF<double>::begin_write (start_frame); } void @@ -367,7 +367,7 @@ SMFSource::mark_streaming_write_completed () } _model->set_edited(false); - SMF::end_write (); + Evoral::SMF<double>::end_write (); } void @@ -632,10 +632,10 @@ SMFSource::load_model(bool lock, bool force_reload) } _model->start_write(); - SMF::seek_to_start(); + Evoral::SMF<double>::seek_to_start(); uint64_t time = 0; /* in SMF ticks */ - Evoral::Event ev; + Evoral::Event<double> ev; size_t scratch_size = 0; // keep track of scratch and minimize reallocs @@ -655,7 +655,7 @@ SMFSource::load_model(bool lock, bool force_reload) if (ret > 0) { // didn't skip (meta) event // make ev.time absolute time in frames - ev.time() = time * frames_per_beat / (Evoral::EventTime)ppqn(); + ev.time() = time * frames_per_beat / (double)ppqn(); ev.set_event_type(EventTypeMap::instance().midi_event_type(buf[0])); _model->append(ev); } @@ -704,6 +704,6 @@ SMFSource::destroy_model() void SMFSource::flush_midi() { - SMF::end_write(); + Evoral::SMF<double>::end_write(); } diff --git a/libs/evoral/evoral/ControlList.hpp b/libs/evoral/evoral/ControlList.hpp index d0e1598388..70488b60be 100644 --- a/libs/evoral/evoral/ControlList.hpp +++ b/libs/evoral/evoral/ControlList.hpp @@ -120,7 +120,7 @@ public: void erase_range (double start, double end); void erase (iterator); void erase (iterator, iterator); - void move_ranges (RangeMoveList const &); + void move_ranges (std::list< RangeMove<double> > const &); void modify (iterator, double, double); boost::shared_ptr<ControlList> cut (double, double); diff --git a/libs/evoral/evoral/Event.hpp b/libs/evoral/evoral/Event.hpp index d6da9b8a1e..5863cda20f 100644 --- a/libs/evoral/evoral/Event.hpp +++ b/libs/evoral/evoral/Event.hpp @@ -38,12 +38,12 @@ namespace Evoral { /** An event (much like a type generic jack_midi_event_t) * - * time is either a frame time (from/to Jack) or a beat time (internal - * tempo time, used in MidiModel) depending on context. + * Template parameter T is the type of the time stamp used for this event. */ +template<typename T> struct Event { #ifdef EVORAL_EVENT_ALLOC - Event(EventType type=0, EventTime t=0, uint32_t s=0, uint8_t* b=NULL, bool alloc=false); + Event(EventType type=0, T t=0, uint32_t s=0, uint8_t* b=NULL, bool alloc=false); /** Copy \a copy. * @@ -58,18 +58,18 @@ struct Event { inline const Event& operator=(const Event& copy) { _type = copy._type; _time = copy._time; - if (_owns_buffer) { - if (copy._buffer) { + if (_owns_buf) { + if (copy._buf) { if (copy._size > _size) { - _buffer = (uint8_t*)::realloc(_buffer, copy._size); + _buf = (uint8_t*)::realloc(_buf, copy._size); } - memcpy(_buffer, copy._buffer, copy._size); + memcpy(_buf, copy._buf, copy._size); } else { - free(_buffer); - _buffer = NULL; + free(_buf); + _buf = NULL; } } else { - _buffer = copy._buffer; + _buf = copy._buf; } _size = copy._size; @@ -77,26 +77,26 @@ struct Event { } inline void shallow_copy(const Event& copy) { - if (_owns_buffer) { - free(_buffer); - _buffer = false; - _owns_buffer = false; + if (_owns_buf) { + free(_buf); + _buf = false; + _owns_buf = false; } _type = copy._type; _time = copy._time; _size = copy._size; - _buffer = copy._buffer; + _buf = copy._buf; } - inline void set(uint8_t* buf, uint32_t size, EventTime t) { - if (_owns_buffer) { + inline void set(uint8_t* buf, uint32_t size, T t) { + if (_owns_buf) { if (_size < size) { - _buffer = (uint8_t*) ::realloc(_buffer, size); + _buf = (uint8_t*) ::realloc(_buf, size); } - memcpy (_buffer, buf, size); + memcpy (_buf, buf, size); } else { - _buffer = buf; + _buf = buf; } _time = t; @@ -113,11 +113,11 @@ struct Event { if (_size != other._size) return false; - if (_buffer == other._buffer) + if (_buf == other._buf) return true; for (uint32_t i=0; i < _size; ++i) - if (_buffer[i] != other._buffer[i]) + if (_buf[i] != other._buf[i]) return false; return true; @@ -125,25 +125,25 @@ struct Event { inline bool operator!=(const Event& other) const { return ! operator==(other); } - inline bool owns_buffer() const { return _owns_buffer; } + inline bool owns_buffer() const { return _owns_buf; } inline void set_buffer(uint32_t size, uint8_t* buf, bool own) { - if (_owns_buffer) { - free(_buffer); - _buffer = NULL; + if (_owns_buf) { + free(_buf); + _buf = NULL; } - _size = size; - _buffer = buf; - _owns_buffer = own; + _size = size; + _buf = buf; + _owns_buf = own; } inline void realloc(uint32_t size) { - if (_owns_buffer) { + if (_owns_buf) { if (size > _size) - _buffer = (uint8_t*) ::realloc(_buffer, size); + _buf = (uint8_t*) ::realloc(_buf, size); } else { - _buffer = (uint8_t*) ::malloc(size); - _owns_buffer = true; + _buf = (uint8_t*) ::malloc(size); + _owns_buf = true; } _size = size; @@ -153,33 +153,33 @@ struct Event { _type = 0; _time = 0; _size = 0; - _buffer = NULL; + _buf = NULL; } #else - inline void set_buffer(uint8_t* buf) { _buffer = buf; } + inline void set_buffer(uint8_t* buf) { _buf = buf; } #endif // EVORAL_EVENT_ALLOC inline EventType event_type() const { return _type; } inline void set_event_type(EventType t) { _type = t; } - inline EventTime time() const { return _time; } - inline EventTime& time() { return _time; } + inline T time() const { return _time; } + inline T& time() { return _time; } inline uint32_t size() const { return _size; } inline uint32_t& size() { return _size; } - inline const uint8_t* buffer() const { return _buffer; } - inline uint8_t*& buffer() { return _buffer; } + inline const uint8_t* buffer() const { return _buf; } + inline uint8_t*& buffer() { return _buf; } protected: - EventType _type; /**< Type of event (application relative, NOT MIDI 'type') */ - EventTime _time; /**< Sample index (or beat time) at which event is valid */ - uint32_t _size; /**< Number of uint8_ts of data in \a buffer */ - uint8_t* _buffer; /**< Raw MIDI data */ + EventType _type; /**< Type of event (application relative, NOT MIDI 'type') */ + T _time; /**< Sample index (or beat time) at which event is valid */ + uint32_t _size; /**< Number of uint8_ts of data in \a buffer */ + uint8_t* _buf; /**< Raw MIDI data */ #ifdef EVORAL_EVENT_ALLOC - bool _owns_buffer; /**< Whether buffer is locally allocated */ + bool _owns_buf; /**< Whether buffer is locally allocated */ #endif }; diff --git a/libs/evoral/evoral/EventRingBuffer.hpp b/libs/evoral/evoral/EventRingBuffer.hpp index cc7b617e26..92d366387f 100644 --- a/libs/evoral/evoral/EventRingBuffer.hpp +++ b/libs/evoral/evoral/EventRingBuffer.hpp @@ -34,7 +34,8 @@ namespace Evoral { * This packs a timestamp, size, and size bytes of data flat into the buffer. * Useful for MIDI events, OSC messages, etc. */ -class EventRingBuffer : public Evoral::RingBuffer<uint8_t>, public Evoral::EventSink { +template<typename T> +class EventRingBuffer : public Evoral::RingBuffer<uint8_t>, public Evoral::EventSink<T> { public: /** @param capacity Ringbuffer capacity in bytes. @@ -44,25 +45,27 @@ public: size_t capacity() const { return _size; } - bool peek_time(EventTime* time); + bool peek_time(T* time); - uint32_t write(EventTime time, EventType type, uint32_t size, const uint8_t* buf); - bool read (EventTime* time, EventType* type, uint32_t* size, uint8_t* buf); + uint32_t write(T time, EventType type, uint32_t size, const uint8_t* buf); + bool read (T* time, EventType* type, uint32_t* size, uint8_t* buf); }; +template<typename T> inline bool -EventRingBuffer::peek_time(EventTime* time) +EventRingBuffer<T>::peek_time(T* time) { - bool success = RingBuffer<uint8_t>::full_peek(sizeof(EventTime), (uint8_t*)time); + bool success = RingBuffer<uint8_t>::full_peek(sizeof(T), (uint8_t*)time); return success; } +template<typename T> inline bool -EventRingBuffer::read(EventTime* time, EventType* type, uint32_t* size, uint8_t* buf) +EventRingBuffer<T>::read(T* time, EventType* type, uint32_t* size, uint8_t* buf) { - bool success = RingBuffer<uint8_t>::full_read(sizeof(EventTime), (uint8_t*)time); + bool success = RingBuffer<uint8_t>::full_read(sizeof(T), (uint8_t*)time); if (success) success = RingBuffer<uint8_t>::full_read(sizeof(EventType), (uint8_t*)type); if (success) @@ -74,13 +77,14 @@ EventRingBuffer::read(EventTime* time, EventType* type, uint32_t* size, uint8_t* } +template<typename T> inline uint32_t -EventRingBuffer::write(EventTime time, EventType type, uint32_t size, const uint8_t* buf) +EventRingBuffer<T>::write(T time, EventType type, uint32_t size, const uint8_t* buf) { - if (write_space() < (sizeof(EventTime) + sizeof(EventType) + sizeof(uint32_t) + size)) { + if (write_space() < (sizeof(T) + sizeof(EventType) + sizeof(uint32_t) + size)) { return 0; } else { - RingBuffer<uint8_t>::write(sizeof(EventTime), (uint8_t*)&time); + RingBuffer<uint8_t>::write(sizeof(T), (uint8_t*)&time); RingBuffer<uint8_t>::write(sizeof(EventType), (uint8_t*)&type); RingBuffer<uint8_t>::write(sizeof(uint32_t), (uint8_t*)&size); RingBuffer<uint8_t>::write(size, buf); diff --git a/libs/evoral/evoral/EventSink.hpp b/libs/evoral/evoral/EventSink.hpp index 3e98601a9a..c3a28df754 100644 --- a/libs/evoral/evoral/EventSink.hpp +++ b/libs/evoral/evoral/EventSink.hpp @@ -26,10 +26,11 @@ namespace Evoral { /** Pure virtual base for anything you can write events to. */ +template<typename T> class EventSink { public: virtual ~EventSink() {} - virtual uint32_t write(EventTime time, EventType type, uint32_t size, const uint8_t* buf) = 0; + virtual uint32_t write(T time, EventType type, uint32_t size, const uint8_t* buf) = 0; }; diff --git a/libs/evoral/evoral/MIDIEvent.hpp b/libs/evoral/evoral/MIDIEvent.hpp index 59cbb12492..9237254142 100644 --- a/libs/evoral/evoral/MIDIEvent.hpp +++ b/libs/evoral/evoral/MIDIEvent.hpp @@ -19,10 +19,11 @@ #ifndef EVORAL_MIDI_EVENT_HPP #define EVORAL_MIDI_EVENT_HPP +#include <boost/shared_ptr.hpp> #include "evoral/Event.hpp" #include "evoral/midi_events.h" #ifdef EVORAL_MIDI_XML - #include <pbd/xml++.h> +class XMLNode; #endif namespace Evoral { @@ -33,13 +34,14 @@ namespace Evoral { * but the application must make sure the event actually contains * valid MIDI data for these functions to make sense. */ -struct MIDIEvent : public Event { - MIDIEvent(EventType type=0, EventTime t=0, uint32_t s=0, uint8_t* b=NULL, bool alloc=false) - : Event(type, t, s, b, alloc) +template<typename T> +struct MIDIEvent : public Event<T> { + MIDIEvent(EventType type=0, T t=0, uint32_t s=0, uint8_t* b=NULL, bool alloc=false) + : Event<T>(type, t, s, b, alloc) {} - MIDIEvent(const Event& copy, bool alloc) - : Event(copy, alloc) + MIDIEvent(const Event<T>& copy, bool alloc) + : Event<T>(copy, alloc) {} #ifdef EVORAL_MIDI_XML @@ -52,12 +54,12 @@ struct MIDIEvent : public Event { boost::shared_ptr<XMLNode> to_xml() const; #endif - inline uint8_t type() const { return (_buffer[0] & 0xF0); } - inline void set_type(uint8_t type) { _buffer[0] = (0x0F & _buffer[0]) - | (0xF0 & type); } - inline uint8_t channel() const { return (_buffer[0] & 0x0F); } - inline void set_channel(uint8_t channel) { _buffer[0] = (0xF0 & _buffer[0]) - | (0x0F & channel); } + inline uint8_t type() const { return (this->_buf[0] & 0xF0); } + inline void set_type(uint8_t type) { this->_buf[0] = (0x0F & this->_buf[0]) + | (0xF0 & type); } + inline uint8_t channel() const { return (this->_buf[0] & 0x0F); } + inline void set_channel(uint8_t channel) { this->_buf[0] = (0xF0 & this->_buf[0]) + | (0x0F & channel); } inline bool is_note_on() const { return (type() == MIDI_CMD_NOTE_ON); } inline bool is_note_off() const { return (type() == MIDI_CMD_NOTE_OFF); } inline bool is_cc() const { return (type() == MIDI_CMD_CONTROL); } @@ -66,24 +68,24 @@ struct MIDIEvent : public Event { inline bool is_note() const { return (is_note_on() || is_note_off()); } inline bool is_aftertouch() const { return (type() == MIDI_CMD_NOTE_PRESSURE); } inline bool is_channel_pressure() const { return (type() == MIDI_CMD_CHANNEL_PRESSURE); } - inline uint8_t note() const { return (_buffer[1]); } - inline uint8_t velocity() const { return (_buffer[2]); } - inline uint8_t cc_number() const { return (_buffer[1]); } - inline void set_cc_number(uint8_t number) { _buffer[1] = number; } - inline uint8_t cc_value() const { return (_buffer[2]); } - inline void set_cc_value(uint8_t value) { _buffer[2] = value; } - inline uint8_t pitch_bender_lsb() const { return (_buffer[1]); } - inline uint8_t pitch_bender_msb() const { return (_buffer[2]); } - inline uint16_t pitch_bender_value() const { return ( ((0x7F & _buffer[2]) << 7) - | (0x7F & _buffer[1]) ); } - inline uint8_t pgm_number() const { return (_buffer[1]); } - inline void set_pgm_number(uint8_t number){ _buffer[1] = number; } - inline uint8_t aftertouch() const { return (_buffer[1]); } - inline uint8_t channel_pressure() const { return (_buffer[1]); } + inline uint8_t note() const { return (this->_buf[1]); } + inline uint8_t velocity() const { return (this->_buf[2]); } + inline uint8_t cc_number() const { return (this->_buf[1]); } + inline void set_cc_number(uint8_t number) { this->_buf[1] = number; } + inline uint8_t cc_value() const { return (this->_buf[2]); } + inline void set_cc_value(uint8_t value) { this->_buf[2] = value; } + inline uint8_t pitch_bender_lsb() const { return (this->_buf[1]); } + inline uint8_t pitch_bender_msb() const { return (this->_buf[2]); } + inline uint16_t pitch_bender_value() const { return ( ((0x7F & this->_buf[2]) << 7) + | (0x7F & this->_buf[1]) ); } + inline uint8_t pgm_number() const { return (this->_buf[1]); } + inline void set_pgm_number(uint8_t number){ this->_buf[1] = number; } + inline uint8_t aftertouch() const { return (this->_buf[1]); } + inline uint8_t channel_pressure() const { return (this->_buf[1]); } inline bool is_channel_event() const { return (0x80 <= type()) && (type() <= 0xE0); } - inline bool is_smf_meta_event() const { return _buffer[0] == 0xFF; } - inline bool is_sysex() const { return _buffer[0] == 0xF0 - || _buffer[0] == 0xF7; } + inline bool is_smf_meta_event() const { return this->_buf[0] == 0xFF; } + inline bool is_sysex() const { return this->_buf[0] == 0xF0 + || this->_buf[0] == 0xF7; } }; } // namespace Evoral diff --git a/libs/evoral/evoral/Note.hpp b/libs/evoral/evoral/Note.hpp index 7e98255d7c..51d68fe45c 100644 --- a/libs/evoral/evoral/Note.hpp +++ b/libs/evoral/evoral/Note.hpp @@ -29,15 +29,16 @@ namespace Evoral { * * Currently a note is defined as (on event, length, off event). */ +template<typename T> class Note { public: - Note(uint8_t chan=0, EventTime time=0, EventLength len=0, uint8_t note=0, uint8_t vel=0x40); - Note(const Note& copy); + Note(uint8_t chan=0, T time=0, EventLength len=0, uint8_t note=0, uint8_t vel=0x40); + Note(const Note<T>& copy); ~Note(); - const Note& operator=(const Note& copy); + const Note<T>& operator=(const Note<T>& copy); - inline bool operator==(const Note& other) { + inline bool operator==(const Note<T>& other) { return time() == other.time() && note() == other.note() && length() == other.length() && @@ -45,8 +46,8 @@ public: channel() == other.channel(); } - inline EventTime time() const { return _on_event.time(); } - inline EventTime end_time() const { return _off_event.time(); } + inline T time() const { return _on_event.time(); } + inline T end_time() const { return _off_event.time(); } inline uint8_t note() const { return _on_event.note(); } inline uint8_t velocity() const { return _on_event.velocity(); } inline EventLength length() const { return _off_event.time() - _on_event.time(); } @@ -55,21 +56,21 @@ public: return _on_event.channel(); } - inline void set_time(EventTime t) { _off_event.time() = t + length(); _on_event.time() = t; } + inline void set_time(T t) { _off_event.time() = t + length(); _on_event.time() = t; } inline void set_note(uint8_t n) { _on_event.buffer()[1] = n; _off_event.buffer()[1] = n; } inline void set_velocity(uint8_t n) { _on_event.buffer()[2] = n; } inline void set_length(EventLength l) { _off_event.time() = _on_event.time() + l; } inline void set_channel(uint8_t c) { _on_event.set_channel(c); _off_event.set_channel(c); } - inline Event& on_event() { return _on_event; } - inline const Event& on_event() const { return _on_event; } - inline Event& off_event() { return _off_event; } - inline const Event& off_event() const { return _off_event; } + inline Event<T>& on_event() { return _on_event; } + inline const Event<T>& on_event() const { return _on_event; } + inline Event<T>& off_event() { return _off_event; } + inline const Event<T>& off_event() const { return _off_event; } private: // Event buffers are self-contained - MIDIEvent _on_event; - MIDIEvent _off_event; + MIDIEvent<T> _on_event; + MIDIEvent<T> _off_event; }; diff --git a/libs/evoral/evoral/SMF.hpp b/libs/evoral/evoral/SMF.hpp index 7257368213..2587781d7a 100644 --- a/libs/evoral/evoral/SMF.hpp +++ b/libs/evoral/evoral/SMF.hpp @@ -24,12 +24,13 @@ namespace Evoral { -class Event; -class EventRingBuffer; +template<typename T> class Event; +template<typename T> class EventRingBuffer; /** Standard Midi File (Type 0) */ +template<typename T> class SMF { public: SMF(); @@ -37,14 +38,14 @@ public: void seek_to_start() const; - uint16_t ppqn() const { return _ppqn; } + uint16_t ppqn() const { return _ppqn; } bool is_empty() const { return _empty; } - bool eof() const { return feof(_fd); } + bool eof() const { return feof(_fd); } - EventTime last_event_time() const { return _last_ev_time; } + T last_event_time() const { return _last_ev_time; } void begin_write(FrameTime start_time); - void append_event_unlocked(uint32_t delta_t, const Evoral::Event& ev); + void append_event_unlocked(uint32_t delta_t, const Event<T>& ev); void end_write(); void flush(); @@ -70,11 +71,11 @@ protected: private: static const uint16_t _ppqn = 19200; - FILE* _fd; - EventTime _last_ev_time; ///< last frame time written, relative to source start - uint32_t _track_size; - uint32_t _header_size; ///< size of SMF header, including MTrk chunk header - bool _empty; ///< true iff file contains(non-empty) events + FILE* _fd; + T _last_ev_time; ///< last frame time written, relative to source start + uint32_t _track_size; + uint32_t _header_size; ///< size of SMF header, including MTrk chunk header + bool _empty; ///< true iff file contains(non-empty) events }; }; /* namespace Evoral */ diff --git a/libs/evoral/evoral/Sequence.hpp b/libs/evoral/evoral/Sequence.hpp index 450051b246..b0d0d51e10 100644 --- a/libs/evoral/evoral/Sequence.hpp +++ b/libs/evoral/evoral/Sequence.hpp @@ -35,9 +35,9 @@ namespace Evoral { class TypeMap; -class EventSink; -class Note; -class Event; +template<typename T> class EventSink; +template<typename T> class Note; +template<typename T> class Event; /** An iterator over (the x axis of) a 2-d double coordinate space. */ @@ -58,6 +58,7 @@ public: /** This is a higher level view of events, with separate representations for * notes (instead of just unassociated note on/off events) and controller data. * Controller data is represented as a list of time-stamped float values. */ +template<typename T> class Sequence : virtual public ControlSet { public: Sequence(const TypeMap& type_map, size_t size=0); @@ -79,49 +80,49 @@ public: bool writing() const { return _writing; } void end_write(bool delete_stuck=false); - size_t read(EventSink& dst, - timestamp_t start, - timedur_t length, - timestamp_t stamp_offset) const; + size_t read(EventSink<T>& dst, + timestamp_t start, + timedur_t length, + timestamp_t stamp_offset) const; /** Resizes vector if necessary (NOT realtime safe) */ - void append(const Event& ev); + void append(const Event<T>& ev); - inline const boost::shared_ptr<const Note> note_at(unsigned i) const { return _notes[i]; } - inline const boost::shared_ptr<Note> note_at(unsigned i) { return _notes[i]; } + inline const boost::shared_ptr< const Note<T> > note_at(unsigned i) const { return _notes[i]; } + inline const boost::shared_ptr< Note<T> > note_at(unsigned i) { return _notes[i]; } inline size_t n_notes() const { return _notes.size(); } inline bool empty() const { return _notes.size() == 0 && ControlSet::empty(); } - inline static bool note_time_comparator(const boost::shared_ptr<const Note>& a, - const boost::shared_ptr<const Note>& b) { + inline static bool note_time_comparator(const boost::shared_ptr< const Note<T> >& a, + const boost::shared_ptr< const Note<T> >& b) { return a->time() < b->time(); } struct LaterNoteEndComparator { - typedef const Note* value_type; - inline bool operator()(const boost::shared_ptr<const Note> a, - const boost::shared_ptr<const Note> b) const { + typedef const Note<T>* value_type; + inline bool operator()(const boost::shared_ptr< const Note<T> > a, + const boost::shared_ptr< const Note<T> > b) const { return a->end_time() > b->end_time(); } }; - typedef std::vector< boost::shared_ptr<Note> > Notes; + typedef std::vector< boost::shared_ptr< Note<T> > > Notes; inline Notes& notes() { return _notes; } inline const Notes& notes() const { return _notes; } /** Read iterator */ class const_iterator { public: - const_iterator(const Sequence& seq, EventTime t); + const_iterator(const Sequence<T>& seq, T t); ~const_iterator(); inline bool valid() const { return !_is_end && _event; } inline bool locked() const { return _locked; } - const Event& operator*() const { return *_event; } - const boost::shared_ptr<Event> operator->() const { return _event; } - const boost::shared_ptr<Event> get_event_pointer() { return _event; } + const Event<T>& operator*() const { return *_event; } + const boost::shared_ptr< Event<T> > operator->() const { return _event; } + const boost::shared_ptr< Event<T> > get_event_pointer() { return _event; } const const_iterator& operator++(); // prefix only bool operator==(const const_iterator& other) const; @@ -130,13 +131,13 @@ public: const_iterator& operator=(const const_iterator& other); private: - friend class Sequence; + friend class Sequence<T>; - const Sequence* _seq; - boost::shared_ptr<Event> _event; + const Sequence<T>* _seq; + boost::shared_ptr< Event<T> > _event; - typedef std::priority_queue< boost::shared_ptr<Note>, - std::deque< boost::shared_ptr<Note> >, + typedef std::priority_queue< boost::shared_ptr< Note<T> >, + std::deque< boost::shared_ptr< Note<T> > >, LaterNoteEndComparator > ActiveNotes; @@ -144,21 +145,21 @@ public: typedef std::vector<ControlIterator> ControlIterators; - bool _is_end; - bool _locked; - Notes::const_iterator _note_iter; - ControlIterators _control_iters; - ControlIterators::iterator _control_iter; + bool _is_end; + bool _locked; + typename Notes::const_iterator _note_iter; + ControlIterators _control_iters; + ControlIterators::iterator _control_iter; }; - const_iterator begin(EventTime t=0) const { return const_iterator(*this, t); } - const const_iterator& end() const { return _end_iter; } + const_iterator begin(T t=0) const { return const_iterator(*this, t); } + const const_iterator& end() const { return _end_iter; } - void read_seek(EventTime t) { _read_iter = begin(t); } - EventTime read_time() const { return _read_iter.valid() ? _read_iter->time() : 0.0; } + void read_seek(T t) { _read_iter = begin(t); } + T read_time() const { return _read_iter.valid() ? _read_iter->time() : 0.0; } - bool control_to_midi_event(boost::shared_ptr<Event>& ev, - const ControlIterator& iter) const; + bool control_to_midi_event(boost::shared_ptr< Event<T> >& ev, + const ControlIterator& iter) const; bool edited() const { return _edited; } void set_edited(bool yn) { _edited = yn; } @@ -167,8 +168,8 @@ public: bool is_sorted() const; #endif - void add_note_unlocked(const boost::shared_ptr<Note> note); - void remove_note_unlocked(const boost::shared_ptr<const Note> note); + void add_note_unlocked(const boost::shared_ptr< Note<T> > note); + void remove_note_unlocked(const boost::shared_ptr< const Note<T> > note); uint8_t lowest_note() const { return _lowest_note; } uint8_t highest_note() const { return _highest_note; } @@ -180,9 +181,9 @@ protected: private: friend class const_iterator; - void append_note_on_unlocked(uint8_t chan, EventTime time, uint8_t note, uint8_t velocity); - void append_note_off_unlocked(uint8_t chan, EventTime time, uint8_t note); - void append_control_unlocked(const Parameter& param, EventTime time, double value); + void append_note_on_unlocked(uint8_t chan, T time, uint8_t note, uint8_t velocity); + void append_note_off_unlocked(uint8_t chan, T time, uint8_t note); + void append_control_unlocked(const Parameter& param, T time, double value); mutable Glib::RWLock _lock; @@ -205,7 +206,7 @@ private: uint8_t _highest_note; typedef std::priority_queue< - boost::shared_ptr<Note>, std::deque< boost::shared_ptr<Note> >, + boost::shared_ptr< Note<T> >, std::deque< boost::shared_ptr< Note<T> > >, LaterNoteEndComparator> ActiveNotes; }; diff --git a/libs/evoral/evoral/types.hpp b/libs/evoral/evoral/types.hpp index 4bca6f1288..f602c7b56f 100644 --- a/libs/evoral/evoral/types.hpp +++ b/libs/evoral/evoral/types.hpp @@ -34,24 +34,20 @@ typedef double timestamp_t; typedef timestamp_t timedur_t; /** Time stamp of an event */ -typedef double EventTime; - -/** Time stamp of an event */ typedef double EventLength; /** Type of an event (opaque, mapped by application) */ typedef uint32_t EventType; /** Type to describe the movement of a time range */ +template<typename T> struct RangeMove { - RangeMove (EventTime f, FrameTime l, EventTime t) : from (f), length (l), to (t) {} - EventTime from; ///< start of the range + RangeMove (T f, FrameTime l, T t) : from (f), length (l), to (t) {} + T from; ///< start of the range FrameTime length; ///< length of the range - EventTime to; ///< new start of the range + T to; ///< new start of the range }; -typedef std::list<RangeMove> RangeMoveList; - } // namespace Evoral #endif // EVORAL_TYPES_HPP diff --git a/libs/evoral/src/ControlList.cpp b/libs/evoral/src/ControlList.cpp index 90ef106ce5..db6d6a9562 100644 --- a/libs/evoral/src/ControlList.cpp +++ b/libs/evoral/src/ControlList.cpp @@ -1285,8 +1285,10 @@ ControlList::paste (ControlList& alist, double pos, float times) /** Move automation around according to a list of region movements */ void -ControlList::move_ranges (RangeMoveList const & movements) +ControlList::move_ranges (const list< RangeMove<double> >& movements) { + typedef list< RangeMove<double> > RangeMoveList; + { Glib::Mutex::Lock lm (_lock); @@ -1304,8 +1306,8 @@ ControlList::move_ranges (RangeMoveList const & movements) /* copy the events into the new list */ for (RangeMoveList::const_iterator i = movements.begin (); i != movements.end (); ++i) { iterator j = old_events.begin (); - EventTime const limit = i->from + i->length; - EventTime const dx = i->to - i->from; + const double limit = i->from + i->length; + const double dx = i->to - i->from; while (j != old_events.end () && (*j)->when <= limit) { if ((*j)->when >= i->from) { ControlEvent* ev = new ControlEvent (**j); diff --git a/libs/evoral/src/Event.cpp b/libs/evoral/src/Event.cpp index 5ac38d6357..1f1460655f 100644 --- a/libs/evoral/src/Event.cpp +++ b/libs/evoral/src/Event.cpp @@ -22,47 +22,52 @@ namespace Evoral { #ifdef EVORAL_EVENT_ALLOC -Event::Event(uint32_t tid, EventTime t, uint32_t s, uint8_t* b, bool owns_buffer) +template<typename T> +Event<T>::Event(uint32_t tid, T t, uint32_t s, uint8_t* b, bool owns_buf) : _type(tid) , _time(t) , _size(s) - , _buffer(b) - , _owns_buffer(owns_buffer) + , _buf(b) + , _owns_buf(owns_buf) { - if (owns_buffer) { - _buffer = (uint8_t*)malloc(_size); + if (owns_buf) { + _buf = (uint8_t*)malloc(_size); if (b) { - memcpy(_buffer, b, _size); + memcpy(_buf, b, _size); } else { - memset(_buffer, 0, _size); + memset(_buf, 0, _size); } } } -Event::Event(const Event& copy, bool owns_buffer) +template<typename T> +Event<T>::Event(const Event& copy, bool owns_buf) : _type(copy._type) , _time(copy._time) , _size(copy._size) - , _buffer(copy._buffer) - , _owns_buffer(owns_buffer) + , _buf(copy._buf) + , _owns_buf(owns_buf) { - if (owns_buffer) { - _buffer = (uint8_t*)malloc(_size); - if (copy._buffer) { - memcpy(_buffer, copy._buffer, _size); + if (owns_buf) { + _buf = (uint8_t*)malloc(_size); + if (copy._buf) { + memcpy(_buf, copy._buf, _size); } else { - memset(_buffer, 0, _size); + memset(_buf, 0, _size); } } } -Event::~Event() { - if (_owns_buffer) { - free(_buffer); +template<typename T> +Event<T>::~Event() { + if (_owns_buf) { + free(_buf); } } #endif // EVORAL_EVENT_ALLOC -} // namespace MIDI +template class Event<double>; + +} // namespace Evoral diff --git a/libs/evoral/src/MIDIEvent.cpp b/libs/evoral/src/MIDIEvent.cpp index 0ae45c749d..aa87847afc 100644 --- a/libs/evoral/src/MIDIEvent.cpp +++ b/libs/evoral/src/MIDIEvent.cpp @@ -16,27 +16,34 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <string> #include "evoral/MIDIEvent.hpp" +#ifdef EVORAL_MIDI_XML + #include <pbd/xml++.h> +#endif + +using namespace std; namespace Evoral { #ifdef EVORAL_MIDI_XML -MIDIEvent::MIDIEvent(const XMLNode& event) - : Event() +template<typename T> +MIDIEvent<T>::MIDIEvent(const XMLNode& event) + : Event<T>() { string name = event.name(); if (name == "ControlChange") { - _buffer = (uint8_t*) ::malloc(3); - _owns_buffer = true; + this->_buf = (uint8_t*) ::malloc(3); + this->_owns_buf = true; set_type(MIDI_CMD_CONTROL); set_cc_number(atoi(event.property("Control")->value().c_str())); set_cc_value (atoi(event.property("Value")->value().c_str())); } else if (name == "ProgramChange") { - _buffer = (uint8_t*) ::malloc(2); - _owns_buffer = true; + this->_buf = (uint8_t*) ::malloc(2); + this->_owns_buf = true; set_type(MIDI_CMD_PGM_CHANGE); set_pgm_number(atoi(event.property("Number")->value().c_str())); @@ -44,8 +51,9 @@ MIDIEvent::MIDIEvent(const XMLNode& event) } +template<typename T> boost::shared_ptr<XMLNode> -MIDIEvent::to_xml() const +MIDIEvent<T>::to_xml() const { XMLNode *result = 0; @@ -73,5 +81,7 @@ MIDIEvent::to_xml() const #endif // EVORAL_MIDI_XML -} // namespace MIDI +template class MIDIEvent<double>; + +} // namespace Evoral diff --git a/libs/evoral/src/Note.cpp b/libs/evoral/src/Note.cpp index 02d65b5291..7ba6bd5d6b 100644 --- a/libs/evoral/src/Note.cpp +++ b/libs/evoral/src/Note.cpp @@ -21,7 +21,8 @@ namespace Evoral { -Note::Note(uint8_t chan, EventTime t, EventLength l, uint8_t n, uint8_t v) +template<typename T> +Note<T>::Note(uint8_t chan, T t, EventLength l, uint8_t n, uint8_t v) // FIXME: types? : _on_event(0xDE, t, 3, NULL, true) , _off_event(0xAD, t + l, 3, NULL, true) @@ -45,7 +46,8 @@ Note::Note(uint8_t chan, EventTime t, EventLength l, uint8_t n, uint8_t v) } -Note::Note(const Note& copy) +template<typename T> +Note<T>::Note(const Note<T>& copy) : _on_event(copy._on_event, true) , _off_event(copy._off_event, true) { @@ -71,13 +73,15 @@ Note::Note(const Note& copy) } -Note::~Note() +template<typename T> +Note<T>::~Note() { } -const Note& -Note::operator=(const Note& copy) +template<typename T> +const Note<T>& +Note<T>::operator=(const Note<T>& copy) { _on_event = copy._on_event; _off_event = copy._off_event; @@ -93,4 +97,6 @@ Note::operator=(const Note& copy) return *this; } +template class Note<double>; + } // namespace Evoral diff --git a/libs/evoral/src/SMF.cpp b/libs/evoral/src/SMF.cpp index cfcc782112..a362c602a7 100644 --- a/libs/evoral/src/SMF.cpp +++ b/libs/evoral/src/SMF.cpp @@ -32,7 +32,8 @@ using namespace std; namespace Evoral { -SMF::SMF() +template<typename T> +SMF<T>::SMF() : _fd(0) , _last_ev_time(0) , _track_size(4) // 4 bytes for the ever-present EOT event @@ -41,7 +42,8 @@ SMF::SMF() { } -SMF::~SMF() +template<typename T> +SMF<T>::~SMF() { } @@ -53,8 +55,9 @@ SMF::~SMF() * -1 if the file can not be opened for reading, * -2 if the file can not be opened for writing */ +template<typename T> int -SMF::open(const std::string& path) +SMF<T>::open(const std::string& path) { //cerr << "Opening SMF file " << path() << " writeable: " << writable() << endl; _fd = fopen(path.c_str(), "r+"); @@ -87,8 +90,9 @@ SMF::open(const std::string& path) return (_fd == 0) ? -1 : 0; } +template<typename T> void -SMF::close() +SMF<T>::close() { if (_fd) { flush_header(); @@ -98,14 +102,16 @@ SMF::close() } } +template<typename T> void -SMF::seek_to_start() const +SMF<T>::seek_to_start() const { fseek(_fd, _header_size, SEEK_SET); } +template<typename T> void -SMF::seek_to_footer_position() +SMF<T>::seek_to_footer_position() { uint8_t buffer[4]; @@ -126,14 +132,16 @@ SMF::seek_to_footer_position() } } +template<typename T> void -SMF::flush() +SMF<T>::flush() { fflush(_fd); } +template<typename T> int -SMF::flush_header() +SMF<T>::flush_header() { // FIXME: write timeline position somehow? @@ -161,8 +169,9 @@ SMF::flush_header() return 0; } +template<typename T> int -SMF::flush_footer() +SMF<T>::flush_footer() { //cerr << path() << " SMF Flushing footer\n"; seek_to_footer_position(); @@ -172,8 +181,9 @@ SMF::flush_footer() return 0; } +template<typename T> void -SMF::write_footer() +SMF<T>::write_footer() { write_var_len(0); char eot[3] = { 0xFF, 0x2F, 0x00 }; // end-of-track meta-event @@ -196,8 +206,9 @@ SMF::write_footer() * Returns event length (including status byte) on success, 0 if event was * skipped (eg a meta event), or -1 on EOF (or end of track). */ +template<typename T> int -SMF::read_event(uint32_t* delta_t, uint32_t* size, uint8_t** buf) const +SMF<T>::read_event(uint32_t* delta_t, uint32_t* size, uint8_t** buf) const { if (feof(_fd)) { return -1; @@ -263,8 +274,9 @@ SMF::read_event(uint32_t* delta_t, uint32_t* size, uint8_t** buf) const return (int)*size; } +template<typename T> void -SMF::append_event_unlocked(uint32_t delta_t, const Evoral::Event& ev) +SMF<T>::append_event_unlocked(uint32_t delta_t, const Event<T>& ev) { if (ev.size() == 0) return; @@ -279,22 +291,25 @@ SMF::append_event_unlocked(uint32_t delta_t, const Evoral::Event& ev) _empty = false; } +template<typename T> void -SMF::begin_write(FrameTime start_frame) +SMF<T>::begin_write(FrameTime start_frame) { _last_ev_time = 0; fseek(_fd, _header_size, SEEK_SET); } +template<typename T> void -SMF::end_write() +SMF<T>::end_write() { flush_header(); flush_footer(); } +template<typename T> void -SMF::write_chunk_header(const char id[4], uint32_t length) +SMF<T>::write_chunk_header(const char id[4], uint32_t length) { const uint32_t length_be = GUINT32_TO_BE(length); @@ -302,8 +317,9 @@ SMF::write_chunk_header(const char id[4], uint32_t length) fwrite(&length_be, 4, 1, _fd); } +template<typename T> void -SMF::write_chunk(const char id[4], uint32_t length, void* data) +SMF<T>::write_chunk(const char id[4], uint32_t length, void* data) { write_chunk_header(id, length); @@ -311,8 +327,9 @@ SMF::write_chunk(const char id[4], uint32_t length, void* data) } /** Returns the size (in bytes) of the value written. */ +template<typename T> size_t -SMF::write_var_len(uint32_t value) +SMF<T>::write_var_len(uint32_t value) { size_t ret = 0; @@ -336,4 +353,6 @@ SMF::write_var_len(uint32_t value) return ret; } +template class SMF<double>; + } // namespace Evoral diff --git a/libs/evoral/src/Sequence.cpp b/libs/evoral/src/Sequence.cpp index 7781ea8907..2fc7bfb39a 100644 --- a/libs/evoral/src/Sequence.cpp +++ b/libs/evoral/src/Sequence.cpp @@ -35,21 +35,25 @@ using namespace std; namespace Evoral { -void Sequence::write_lock() { +template<typename T> +void Sequence<T>::write_lock() { _lock.writer_lock(); _control_lock.lock(); } -void Sequence::write_unlock() { +template<typename T> +void Sequence<T>::write_unlock() { _lock.writer_unlock(); _control_lock.unlock(); } -void Sequence::read_lock() const { +template<typename T> +void Sequence<T>::read_lock() const { _lock.reader_lock(); } -void Sequence::read_unlock() const { +template<typename T> +void Sequence<T>::read_unlock() const { _lock.reader_unlock(); } @@ -64,7 +68,8 @@ static ostream& errorout = cerr; // Read iterator (const_iterator) -Sequence::const_iterator::const_iterator(const Sequence& seq, EventTime t) +template<typename T> +Sequence<T>::const_iterator::const_iterator(const Sequence<T>& seq, T t) : _seq(&seq) , _is_end( (t == DBL_MAX) || seq.empty() ) , _locked( !_is_end ) @@ -79,7 +84,8 @@ Sequence::const_iterator::const_iterator(const Sequence& seq, EventTime t) // find first note which begins after t _note_iter = seq.notes().end(); - for (Sequence::Notes::const_iterator i = seq.notes().begin(); i != seq.notes().end(); ++i) { + for (typename Sequence<T>::Notes::const_iterator i = seq.notes().begin(); + i != seq.notes().end(); ++i) { if ((*i)->time() >= t) { _note_iter = i; break; @@ -130,7 +136,7 @@ Sequence::const_iterator::const_iterator(const Sequence& seq, EventTime t) && (!earliest_control.list || (*_note_iter)->on_event().time() < earliest_control.x)) { debugout << "Reading note on event @ " << (*_note_iter)->on_event().time() << endl; - _event = boost::shared_ptr<Event>(new Event((*_note_iter)->on_event(), true)); + _event = boost::shared_ptr< Event<T> >(new Event<T>((*_note_iter)->on_event(), true)); _active_notes.push(*_note_iter); ++_note_iter; _control_iter = _control_iters.end(); @@ -152,22 +158,24 @@ Sequence::const_iterator::const_iterator(const Sequence& seq, EventTime t) } } else { debugout << "New Iterator = " << _event->event_type(); - debugout << " : " << hex << (int)((MIDIEvent*)_event.get())->type(); + debugout << " : " << hex << (int)((MIDIEvent<T>*)_event.get())->type(); debugout << " @ " << _event->time() << endl; } //assert(_is_end || (_event->buffer() && _event->buffer()[0] != '\0')); } -Sequence::const_iterator::~const_iterator() +template<typename T> +Sequence<T>::const_iterator::~const_iterator() { if (_locked) { _seq->read_unlock(); } } -const -Sequence::const_iterator& Sequence::const_iterator::operator++() +template<typename T> +const typename Sequence<T>::const_iterator& +Sequence<T>::const_iterator::operator++() { if (_is_end) { throw std::logic_error("Attempt to iterate past end of Sequence"); @@ -176,7 +184,7 @@ Sequence::const_iterator& Sequence::const_iterator::operator++() debugout << "Iterator ++" << endl; assert(_event->buffer() && _event->size() > 0); - const MIDIEvent& ev = *((MIDIEvent*)_event.get()); + const MIDIEvent<T>& ev = *((MIDIEvent<T>*)_event.get()); //debugout << "const_iterator::operator++: " << _event->to_string() << endl; @@ -214,10 +222,10 @@ Sequence::const_iterator& Sequence::const_iterator::operator++() } } - enum Type {NIL, NOTE_ON, NOTE_OFF, CONTROL}; + enum Type { NIL, NOTE_ON, NOTE_OFF, CONTROL }; Type type = NIL; - EventTime t = 0; + T t = 0; // Next earliest note on if (_note_iter != _seq->notes().end()) { @@ -262,8 +270,9 @@ Sequence::const_iterator& Sequence::const_iterator::operator++() return *this; } +template<typename T> bool -Sequence::const_iterator::operator==(const const_iterator& other) const +Sequence<T>::const_iterator::operator==(const const_iterator& other) const { if (_is_end || other._is_end) { return (_is_end == other._is_end); @@ -272,8 +281,9 @@ Sequence::const_iterator::operator==(const const_iterator& other) const } } -Sequence::const_iterator& -Sequence::const_iterator::operator=(const const_iterator& other) +template<typename T> +typename Sequence<T>::const_iterator& +Sequence<T>::const_iterator::operator=(const const_iterator& other) { if (_locked && _seq != other._seq) { _seq->read_unlock(); @@ -292,7 +302,7 @@ Sequence::const_iterator::operator=(const const_iterator& other) if (_event) { *_event = *other._event.get(); } else { - _event = boost::shared_ptr<Event>(new Event(*other._event, true)); + _event = boost::shared_ptr< Event<T> >(new Event<T>(*other._event, true)); } } else { if (_event) { @@ -305,7 +315,8 @@ Sequence::const_iterator::operator=(const const_iterator& other) // Sequence -Sequence::Sequence(const TypeMap& type_map, size_t size) +template<typename T> +Sequence<T>::Sequence(const TypeMap& type_map, size_t size) : _read_iter(*this, DBL_MAX) , _edited(false) , _type_map(type_map) @@ -326,8 +337,9 @@ Sequence::Sequence(const TypeMap& type_map, size_t size) * adding \a offset to each event's timestamp. * \return number of events written to \a dst */ +template<typename T> size_t -Sequence::read(EventSink& dst, timestamp_t start, timedur_t nframes, timestamp_t offset) const +Sequence<T>::read(EventSink<T>& dst, timestamp_t start, timedur_t nframes, timestamp_t offset) const { debugout << this << " read @ " << start << " * " << nframes << " + " << offset << endl; debugout << this << " # notes: " << n_notes() << endl; @@ -370,13 +382,14 @@ Sequence::read(EventSink& dst, timestamp_t start, timedur_t nframes, timestamp_t * The event_type of \a ev should be set to the expected output type. * \return true on success */ +template<typename T> bool -Sequence::control_to_midi_event(boost::shared_ptr<Event>& ev, const ControlIterator& iter) const +Sequence<T>::control_to_midi_event(boost::shared_ptr< Event<T> >& ev, const ControlIterator& iter) const { assert(iter.list.get()); const uint32_t event_type = iter.list->parameter().type(); if (!ev) { - ev = boost::shared_ptr<Event>(new Event(event_type, 0, 3, NULL, true)); + ev = boost::shared_ptr< Event<T> >(new Event<T>(event_type, 0, 3, NULL, true)); } uint8_t midi_type = _type_map.parameter_midi_type(iter.list->parameter()); @@ -438,8 +451,9 @@ Sequence::control_to_midi_event(boost::shared_ptr<Event>& ev, const ControlItera /** Clear all events from the model. */ +template<typename T> void -Sequence::clear() +Sequence<T>::clear() { _lock.writer_lock(); _notes.clear(); @@ -457,8 +471,9 @@ Sequence::clear() * stored; note off events are discarded entirely and all contained notes will * have length 0. */ +template<typename T> void -Sequence::start_write() +Sequence<T>::start_write() { debugout << this << " START WRITE, PERCUSSIVE = " << _percussive << endl; write_lock(); @@ -476,8 +491,9 @@ Sequence::start_write() * that were never resolved with a corresonding note off will be deleted. * Otherwise they will remain as notes with length 0. */ +template<typename T> void -Sequence::end_write(bool delete_stuck) +Sequence<T>::end_write(bool delete_stuck) { write_lock(); assert(_writing); @@ -485,7 +501,7 @@ Sequence::end_write(bool delete_stuck) debugout << this << " END WRITE: " << _notes.size() << " NOTES\n"; if (!_percussive && delete_stuck) { - for (Notes::iterator n = _notes.begin(); n != _notes.end() ;) { + for (typename Notes::iterator n = _notes.begin(); n != _notes.end() ;) { if ((*n)->length() == 0) { errorout << "WARNING: Stuck note lost: " << (*n)->note() << endl; n = _notes.erase(n); @@ -499,7 +515,7 @@ Sequence::end_write(bool delete_stuck) for (int i = 0; i < 16; ++i) { if (!_write_notes[i].empty()) { - errorout << "WARNING: Sequence::end_write: Channel " << i << " has " + errorout << "WARNING: Sequence<T>::end_write: Channel " << i << " has " << _write_notes[i].size() << " stuck notes" << endl; } _write_notes[i].clear(); @@ -519,13 +535,14 @@ Sequence::end_write(bool delete_stuck) * the start of this model (t=0) and MUST be monotonically increasing * and MUST be >= the latest event currently in the model. */ +template<typename T> void -Sequence::append(const Event& event) +Sequence<T>::append(const Event<T>& event) { write_lock(); _edited = true; - const MIDIEvent& ev = (const MIDIEvent&)event; + const MIDIEvent<T>& ev = (const MIDIEvent<T>&)event; assert(_notes.empty() || ev.time() >= _notes.back()->time()); assert(_writing); @@ -565,8 +582,9 @@ Sequence::append(const Event& event) write_unlock(); } +template<typename T> void -Sequence::append_note_on_unlocked(uint8_t chan, EventTime time, uint8_t note_num, uint8_t velocity) +Sequence<T>::append_note_on_unlocked(uint8_t chan, T time, uint8_t note_num, uint8_t velocity) { debugout << this << " c" << (int)chan << " note " << (int)note_num << " off @ " << time << endl; assert(note_num <= 127); @@ -579,7 +597,7 @@ Sequence::append_note_on_unlocked(uint8_t chan, EventTime time, uint8_t note_num if (note_num > _highest_note) _highest_note = note_num; - boost::shared_ptr<Note> new_note(new Note(chan, time, 0, note_num, velocity)); + boost::shared_ptr< Note<T> > new_note(new Note<T>(chan, time, 0, note_num, velocity)); _notes.push_back(new_note); if (!_percussive) { debugout << "Sustained: Appending active note on " << (unsigned)(uint8_t)note_num << endl; @@ -589,8 +607,9 @@ Sequence::append_note_on_unlocked(uint8_t chan, EventTime time, uint8_t note_num } } +template<typename T> void -Sequence::append_note_off_unlocked(uint8_t chan, EventTime time, uint8_t note_num) +Sequence<T>::append_note_off_unlocked(uint8_t chan, T time, uint8_t note_num) { debugout << this << " c" << (int)chan << " note " << (int)note_num << " off @ " << time << endl; assert(note_num <= 127); @@ -612,7 +631,7 @@ Sequence::append_note_off_unlocked(uint8_t chan, EventTime time, uint8_t note_nu for (WriteNotes::iterator n = _write_notes[chan].begin(); n != _write_notes[chan].end(); ++n) { - Note& note = *_notes[*n].get(); + Note<T>& note = *_notes[*n].get(); if (note.note() == note_num) { assert(time >= note.time()); note.set_length(time - note.time()); @@ -629,8 +648,9 @@ Sequence::append_note_off_unlocked(uint8_t chan, EventTime time, uint8_t note_nu } } +template<typename T> void -Sequence::append_control_unlocked(const Parameter& param, EventTime time, double value) +Sequence<T>::append_control_unlocked(const Parameter& param, T time, double value) { debugout << this << " " << _type_map.to_symbol(param) << " @ " << time << " \t= \t" << value << " # controls: " << _controls.size() << endl; @@ -638,25 +658,26 @@ Sequence::append_control_unlocked(const Parameter& param, EventTime time, double c->list()->rt_add(time, value); } - +template<typename T> void -Sequence::add_note_unlocked(const boost::shared_ptr<Note> note) +Sequence<T>::add_note_unlocked(const boost::shared_ptr< Note<T> > note) { debugout << this << " add note " << (int)note->note() << " @ " << note->time() << endl; _edited = true; - Notes::iterator i = upper_bound(_notes.begin(), _notes.end(), note, + typename Notes::iterator i = upper_bound(_notes.begin(), _notes.end(), note, note_time_comparator); _notes.insert(i, note); } +template<typename T> void -Sequence::remove_note_unlocked(const boost::shared_ptr<const Note> note) +Sequence<T>::remove_note_unlocked(const boost::shared_ptr< const Note<T> > note) { _edited = true; debugout << this << " remove note " << (int)note->note() << " @ " << note->time() << endl; - for (Notes::iterator n = _notes.begin(); n != _notes.end(); ++n) { - Note& _n = *(*n); - const Note& _note = *note; + for (typename Notes::iterator n = _notes.begin(); n != _notes.end(); ++n) { + Note<T>& _n = *(*n); + const Note<T>& _note = *note; // TODO: There is still the issue, that after restarting ardour // persisted undo does not work, because of rounding errors in the // event times after saving/restoring to/from MIDI files @@ -675,10 +696,11 @@ Sequence::remove_note_unlocked(const boost::shared_ptr<const Note> note) /** Slow! for debugging only. */ #ifndef NDEBUG +template<typename T> bool -Sequence::is_sorted() const { +Sequence<T>::is_sorted() const { bool t = 0; - for (Notes::const_iterator n = _notes.begin(); n != _notes.end(); ++n) + for (typename Notes::const_iterator n = _notes.begin(); n != _notes.end(); ++n) if ((*n)->time() < t) return false; else @@ -688,5 +710,7 @@ Sequence::is_sorted() const { } #endif +template class Sequence<double>; + } // namespace Evoral diff --git a/libs/midi++2/jack_midiport.cc b/libs/midi++2/jack_midiport.cc index 5ebb55c325..0f707a4b21 100644 --- a/libs/midi++2/jack_midiport.cc +++ b/libs/midi++2/jack_midiport.cc @@ -97,7 +97,7 @@ JACK_MidiPort::write(byte * msg, size_t msglen, timestamp_t timestamp) if (!is_process_thread()) { Glib::Mutex::Lock lm (non_process_thread_fifo_lock); - RingBuffer<Evoral::Event>::rw_vector vec; + RingBuffer< Evoral::Event<double> >::rw_vector vec; non_process_thread_fifo.get_write_vector (&vec); @@ -161,7 +161,7 @@ JACK_MidiPort::write(byte * msg, size_t msglen, timestamp_t timestamp) void JACK_MidiPort::flush (void* jack_port_buffer) { - RingBuffer<Evoral::Event>::rw_vector vec; + RingBuffer< Evoral::Event<double> >::rw_vector vec; size_t written; non_process_thread_fifo.get_read_vector (&vec); @@ -171,7 +171,7 @@ JACK_MidiPort::flush (void* jack_port_buffer) } if (vec.len[0]) { - Evoral::Event* evp = vec.buf[0]; + Evoral::Event<double>* evp = vec.buf[0]; for (size_t n = 0; n < vec.len[0]; ++n, ++evp) { jack_midi_event_write (jack_port_buffer, @@ -180,7 +180,7 @@ JACK_MidiPort::flush (void* jack_port_buffer) } if (vec.len[1]) { - Evoral::Event* evp = vec.buf[1]; + Evoral::Event<double>* evp = vec.buf[1]; for (size_t n = 0; n < vec.len[1]; ++n, ++evp) { jack_midi_event_write (jack_port_buffer, diff --git a/libs/midi++2/midi++/jack.h b/libs/midi++2/midi++/jack.h index 9e779b2198..01f96671be 100644 --- a/libs/midi++2/midi++/jack.h +++ b/libs/midi++2/midi++/jack.h @@ -82,9 +82,8 @@ private: void flush (void* jack_port_buffer); static pthread_t _process_thread; - - RingBuffer<Evoral::Event> non_process_thread_fifo; + RingBuffer< Evoral::Event<double> > non_process_thread_fifo; Glib::Mutex non_process_thread_fifo_lock; }; diff --git a/libs/midi++2/midi++/midnam_patch.h b/libs/midi++2/midi++/midnam_patch.h index d810d96c7a..65e624e5ce 100644 --- a/libs/midi++2/midi++/midnam_patch.h +++ b/libs/midi++2/midi++/midnam_patch.h @@ -84,7 +84,7 @@ public: class PatchBank; -typedef std::list<boost::shared_ptr<Evoral::MIDIEvent> > PatchMidiCommands; +typedef std::list< boost::shared_ptr< Evoral::MIDIEvent<double> > > PatchMidiCommands; class Patch : public PBD::Stateful { |