change default overlapping note strategy to "relax" (i.e. do nothing); fix crash...
authorPaul Davis <paul@linuxaudiosystems.com>
Tue, 21 Jun 2011 21:29:22 +0000 (21:29 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 21 Jun 2011 21:29:22 +0000 (21:29 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@9753 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/midi_region_view.cc
libs/ardour/ardour/midi_ring_buffer.h
libs/ardour/ardour/session_configuration_vars.h
libs/ardour/midi_diskstream.cc
libs/ardour/midi_ring_buffer.cc
libs/evoral/evoral/Sequence.hpp
libs/evoral/evoral/midi_util.h
libs/evoral/src/Sequence.cpp

index 54f6a2c59a2e2428963d8f0e6e72053d8252fe92..2de95c1f73aa67e0dfe4dcb0d03e594822c43c52 100644 (file)
@@ -1844,9 +1844,7 @@ MidiRegionView::maybe_remove_deleted_note_from_selection (CanvasNoteEvent* cne)
                return;
        }
 
-       if (_selection.erase (cne) > 0) {
-               cerr << "Erased a CNE from selection\n";
-       }
+       _selection.erase (cne);
 }
 
 void
index 567f375bc3f9a6f68b0ddec5580b0edbd29cd2a4..14934456e132f8afc3836fdc8ec56b8f41d4a24c 100644 (file)
 
 #include <iostream>
 #include <algorithm>
+
+#include "evoral/EventRingBuffer.hpp"
+
 #include "ardour/types.h"
 #include "ardour/buffer.h"
-#include "evoral/EventRingBuffer.hpp"
+#include "ardour/midi_state_tracker.h"
 
 namespace ARDOUR {
 
@@ -80,8 +83,19 @@ protected:
                return (0x80 <= event_type_byte) && (event_type_byte <= 0xE0);
        }
 
+       inline bool is_note_on(uint8_t event_type_byte) {
+               // mask out channel information
+               return (event_type_byte & 0xF0) == MIDI_CMD_NOTE_ON;
+       }
+
+       inline bool is_note_off(uint8_t event_type_byte) {
+               // mask out channel information
+               return (event_type_byte & 0xF0) == MIDI_CMD_NOTE_OFF;
+       }
+
 private:
        volatile uint32_t _channel_mask; // 16 bits mode, 16 bits mask
+       MidiStateTracker _tracker;
 };
 
 
index 336e694e6a81d74177ed7ad8abd499518e4f6aec..5924adcc863531c6b04de2c5f12ece9c02e72277 100644 (file)
@@ -58,6 +58,6 @@ CONFIG_VARIABLE (bool, show_summary, "show-summary", true)
 CONFIG_VARIABLE (bool, show_group_tabs, "show-group-tabs", true)
 CONFIG_VARIABLE (bool, external_sync, "external-sync", false)
 CONFIG_VARIABLE (SyncSource, sync_source, "sync-source", JACK)
-CONFIG_VARIABLE (InsertMergePolicy, insert_merge_policy, "insert-merge-policy", InsertMergeReject)
+CONFIG_VARIABLE (InsertMergePolicy, insert_merge_policy, "insert-merge-policy", InsertMergeRelax)
 CONFIG_VARIABLE (framecnt_t, timecode_offset, "timecode-offset", 0)
 CONFIG_VARIABLE (bool, timecode_offset_negative, "timecode-offset-negative", true)
index 0539e3b62f744e5d0e4f4f4f579d2f3edf5cc70e..1c34ff9c0368ff7b757f374a433ef5aa75c5cb5b 100644 (file)
@@ -1413,8 +1413,8 @@ MidiDiskstream::get_playback (MidiBuffer& dst, framepos_t start, framepos_t end)
 
 #ifndef NDEBUG
        DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose (
-                            "%1 MDS pre-read read from %2 write to %3\n", _name,
-                            _playback_buf->get_read_ptr(), _playback_buf->get_write_ptr()));
+                            "%1 MDS pre-read read %4..%5 from %2 write to %3\n", _name,
+                            _playback_buf->get_read_ptr(), _playback_buf->get_write_ptr(), start, end));
 //        cerr << "================\n";
 //        _playback_buf->dump (cerr);
 //        cerr << "----------------\n";
index 434fa0c33ea608242b8f6106c4832f49a6e78264..902f6866f17443c2e4909999aaeb95a43515b0e7 100644 (file)
@@ -101,17 +101,28 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, framepos_t start, framepos_t end, frame
                        DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("MRB event @ %1 in range %2 .. %3\n", ev_time, start, end));
                }
 
-               /* lets see if we are going to be able to write this event into dst.
-                */
-
                assert(ev_time >= start);
 
                ev_time -= start;
                ev_time += offset;
 
-               // write the timestamp to address (write_loc - 1)
-               uint8_t* write_loc = dst.reserve(ev_time, ev_size);
-               if (write_loc == NULL) {
+               // This event marks a loop end (i.e. the next event's timestamp
+               // will be non-monotonic). Don't write it into the buffer - the
+               // significance of this event ends here.
+               
+               if (ev_type == LoopEventType) {
+                       assert (ev_size == sizeof (framepos_t));
+                       framepos_t loop_start;
+                       read_contents (ev_size, (uint8_t *) &loop_start);
+                       loop_offset = ev_time - loop_start;
+                       _tracker.resolve_notes (dst, ev_time);
+                       continue;
+               }
+
+               /* lets see if we are going to be able to write this event into dst.
+                */
+               uint8_t* write_loc = dst.reserve (ev_time, ev_size);
+               if (write_loc == 0) {
                        if (stop_on_overflow_in_dst) {
                                DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("MidiRingBuffer: overflow in destination MIDI buffer, stopped after %1 events\n", count));
                                break;
@@ -124,19 +135,7 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, framepos_t start, framepos_t end, frame
                /* we're good to go ahead and read the data now but since we
                 * have the prefix data already, just skip over that
                 */
-
                this->increment_read_ptr (prefix_size);
-
-               // This event marks a loop end (i.e. the next event's timestamp will be non-monotonic)
-               if (ev_type == LoopEventType) {
-                       assert (ev_size == sizeof (framepos_t));
-                       framepos_t loop_start;
-                       read_contents (ev_size, (uint8_t *) &loop_start);
-
-                       loop_offset = ev_time - loop_start;
-                       continue;
-               }
-
                ev_time += loop_offset;
 
                uint8_t status;
@@ -172,6 +171,13 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, framepos_t start, framepos_t end, frame
 #endif
 
                if (success) {
+
+                       if (is_note_on(write_loc[0]) ) {
+                               _tracker.add (write_loc[1], write_loc[0] & 0xf);
+                       } else if (is_note_off(write_loc[0])) {
+                               _tracker.remove (write_loc[1], write_loc[0] & 0xf);
+                       }
+                       
                        if (is_channel_event(status) && get_channel_mode() == ForceChannel) {
                                write_loc[0] = (write_loc[0] & 0xF0) | (get_channel_mask() & 0x0F);
                        }
index 2b3ba4ace06c6dc8578f3dd8abb6bf0b69869653..922b7594d4e42f21d6b6c768231d1da674dcd8a5 100644 (file)
@@ -191,6 +191,8 @@ public:
        inline       PatchChanges& patch_changes ()       { return _patch_changes; }
        inline const PatchChanges& patch_changes () const { return _patch_changes; }
 
+        void dump (std::ostream&) const;
+
 private:
        typedef std::priority_queue<NotePtr, std::deque<NotePtr>, LaterNoteEndComparator> ActiveNotes;
 public:
@@ -332,5 +334,7 @@ private:
 
 } // namespace Evoral
 
+// template<typename Time> std::ostream& operator<<(std::ostream& o, const Evoral::Sequence<Time>& s) { s.dump (o); return o; }
+
 #endif // EVORAL_SEQUENCE_HPP
 
index da7051aefa5b827de37903f9fecaa5e7bd7688a2..e1ae7f46203233382ae4cca6cb072ae983d997a3 100644 (file)
@@ -19,6 +19,8 @@
 #ifndef EVORAL_MIDI_UTIL_H
 #define EVORAL_MIDI_UTIL_H
 
+#include <iostream>
+
 #include <stdint.h>
 #include <stdbool.h>
 #include <string>
@@ -66,9 +68,11 @@ midi_event_size(uint8_t status)
                return 1;
 
        case MIDI_CMD_COMMON_SYSEX:
+               std::cerr << "event size called for sysex\n";
                return -1;
        }
 
+       std::cerr << "event size called for unknown status byte " << std::hex << (int) status << "\n";
        return -1;
 }
 
index 3c1bda9b964f0d62af7c549ca35aa0bcb5d05698..1d91690a6143b6d9de0f31328160f2c59776e461 100644 (file)
@@ -687,7 +687,7 @@ Sequence<Time>::add_note_unlocked(const NotePtr note, void* arg)
  
        _edited = true;
 
-       return true;
+       return true;
 }
 
 template<typename Time>
@@ -750,7 +750,7 @@ Sequence<Time>::remove_note_unlocked(const constNotePtr note)
         }
         
         if (!erased) {
-                cerr << "Unable to find note to erase" << endl;
+                cerr << "Unable to find note to erase matching " << *note.get() << endl;
         }
 }
 
@@ -1214,5 +1214,17 @@ Sequence<Time>::control_list_marked_dirty ()
 
 template class Sequence<Evoral::MusicalTime>;
 
+template<typename Time>
+void
+Sequence<Time>::dump (ostream& str) const
+{
+       Sequence<Time>::const_iterator i;
+       str << "+++ dump\n";
+       for (i = begin(); i != end(); ++i) {
+               str << *i << endl;
+       }
+       str << "--- dump\n";
+}
+
 } // namespace Evoral