* first prototype for track based channel selection works
authorHans Baier <hansfbaier@googlemail.com>
Sat, 19 Apr 2008 02:11:11 +0000 (02:11 +0000)
committerHans Baier <hansfbaier@googlemail.com>
Sat, 19 Apr 2008 02:11:11 +0000 (02:11 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@3267 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/midi_time_axis.cc
gtk2_ardour/midi_time_axis.h
libs/ardour/ardour/midi_diskstream.h
libs/ardour/ardour/midi_ring_buffer.h
libs/ardour/ardour/region.h
libs/ardour/ardour/smf_source.h
libs/ardour/smf_source.cc

index 7169302315b566ebdbd9f3c3b56d332ac096a786..89ca218ea23446d9f5d637ba41924460ffcb3b80 100644 (file)
@@ -78,6 +78,7 @@
 using namespace ARDOUR;
 using namespace PBD;
 using namespace Gtk;
+using namespace sigc;
 using namespace Editing;
 
 
@@ -99,6 +100,18 @@ MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session& sess, boost::shar
        mute_button->set_active (false);
        solo_button->set_active (false);
        
+       // add channel selection button
+       _channel_selection_button.add(*manage(new Label("c")));
+       controls_table.property_n_rows() = 3;
+       controls_table.attach(_channel_selection_button, 1, 2, 2, 3);
+       _channel_selection_button.show_all();
+       
+       // add channel selector
+       controls_vbox.pack_end(_channel_selector);
+       _channel_selector.selection_changed.connect(
+               mem_fun(*midi_track()->midi_diskstream(), &MidiDiskstream::set_channel_mask));
+       _channel_selector.show_all();
+       
        if (is_midi_track()) {
                controls_ebox.set_name ("MidiTimeAxisViewControlsBaseUnselected");
                _note_mode = midi_track()->note_mode();
index a91bd01d216909078a72a920369b05332c4762d0..14aa4627e7e60045971beb82f107d9844560ddfd 100644 (file)
@@ -39,6 +39,7 @@
 #include "route_time_axis.h"
 #include "canvas.h"
 #include "midi_streamview.h"
+#include "midi_channel_selector.h"
 
 namespace ARDOUR {
        class Session;
@@ -93,6 +94,8 @@ class MidiTimeAxisView : public RouteTimeAxisView
        ARDOUR::NoteMode    _note_mode;
        Gtk::RadioMenuItem* _note_mode_item;
        Gtk::RadioMenuItem* _percussion_mode_item;
+       Gtk::ToggleButton _channel_selection_button;
+       MidiMultipleChannelSelector _channel_selector;
 };
 
 #endif /* __ardour_midi_time_axis_h__ */
index d08f00b72fc2562b7669b7599dce31505996982e..40df9cfc26371d3e2dfe68c3d19324df608aba51 100644 (file)
@@ -89,6 +89,18 @@ class MidiDiskstream : public Diskstream
        int set_destructive (bool yn); // doom!
        
        void set_note_mode (NoteMode m);
+       
+       void set_channel_mask(uint16_t channel_mask) { 
+               _playback_buf->set_channel_mask(channel_mask); 
+               _capture_buf->set_channel_mask(channel_mask); 
+       }
+       
+       uint16_t get_channel_mask() { 
+               uint16_t playback_mask = _playback_buf->get_channel_mask();
+               uint16_t capture_mask  = _capture_buf->get_channel_mask();
+               assert(playback_mask == capture_mask);
+               return playback_mask;
+       }
 
   protected:
        friend class Session;
index 136d587550f2f447774229e8ae2a8acbd863d7f8..7f0e9f3b375578972c90ef4715a4438728d9af76 100644 (file)
@@ -227,7 +227,7 @@ public:
        /** @param size Size in bytes.
         */
        MidiRingBuffer(size_t size)
-               : MidiRingBufferBase<Byte>(size)
+               : MidiRingBufferBase<Byte>(size), _channel_mask(0xFFFF)
        {}
 
        size_t write(double time, size_t size, const Byte* buf);
@@ -237,6 +237,20 @@ public:
        bool   read_contents(size_t size, Byte* buf);
 
        size_t read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t offset=0);
+       
+       void      set_channel_mask(uint16_t channel_mask) { _channel_mask = channel_mask; }
+       uint16_t  get_channel_mask() { return _channel_mask; }
+       
+protected:
+       inline bool is_channel_event(Byte event_type_byte) {
+               // mask out channel information
+               event_type_byte &= 0xF0;
+               // midi channel events range from 0x80 to 0xE0
+               return (0x80 <= event_type_byte) && (event_type_byte <= 0xE0);
+       }
+       
+private:
+       uint16_t _channel_mask;
 };
 
 
@@ -284,6 +298,14 @@ MidiRingBuffer::write(double time, size_t size, const Byte* buf)
                        buf[0], buf[1], buf[2], time);
 
        assert(size > 0);
+       
+       // filter events for channels
+       if(is_channel_event(buf[0])) {
+               Byte channel_nr = buf[0] & 0x0F;
+               if( !(_channel_mask & (1L << channel_nr)) )  {
+                       return 0;
+               }
+       }
 
        if (write_space() < (sizeof(double) + sizeof(size_t) + size)) {
                return 0;
@@ -293,6 +315,7 @@ MidiRingBuffer::write(double time, size_t size, const Byte* buf)
                MidiRingBufferBase<Byte>::write(size, buf);
                return size;
        }
+
 }
 
 
@@ -311,7 +334,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
 
        size_t count = 0;
 
-       //printf("MRB - read %u .. %u + %u\n", start, end, offset);
+       printf("MRB - read %u .. %u + %u\n", start, end, offset);
 
        while (read_space() > sizeof(double) + sizeof(size_t)) {
        
@@ -319,15 +342,33 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
        
                if (ev.time() > end)
                        break;
-
+               
                bool success = MidiRingBufferBase<Byte>::full_read(sizeof(double), (Byte*)&ev.time());
                if (success)
                        success = MidiRingBufferBase<Byte>::full_read(sizeof(size_t), (Byte*)&ev.size());
-               
+
                if (!success) {
                        std::cerr << "MRB: READ ERROR (time/size)" << std::endl;
                        continue;
                }
+               
+               Byte first_event_byte;
+               if(success)
+                       success = full_peek(sizeof(Byte), &first_event_byte);
+                               
+               // could this ever happen???
+               if (!success) {
+                       std::cerr << "MRB: PEEK ERROR (first event byte)" << std::endl;
+                       continue;
+               }
+               
+               // filter events for channels
+               if(is_channel_event(first_event_byte)) {
+                       Byte channel_nr = first_event_byte & 0x0F;
+                       if( !(_channel_mask & (1L << channel_nr)) )  {
+                               return 0;
+                       }
+               }
 
                if (ev.time() >= start) {
                        ev.time() -= start;
@@ -336,7 +377,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
                
                        if (success) {
                                ++count;
-                               //printf("MRB - read event at time %lf\n", ev.time);
+                               printf("MRB - read event at time %lf\n", ev.time());
                        } else {
                                std::cerr << "MRB: READ ERROR (data)" << std::endl;
                        }
index fb1220e99649cca58ec38d7833059cda3f53f9ee..00315846b2e51e390f4faf14769775499af4b013 100644 (file)
@@ -98,6 +98,16 @@ class Region : public Automatable, public boost::enable_shared_from_this<Region>
 
        const DataType& data_type() const { return _type; }
 
+       /**
+        * Thats how the region parameters play together:
+        * <PRE>
+        * |------------------------------------------------------------------- track
+        *                    |..........[------------------].....| region
+        * |-----------------------------| _position
+        *                               |------------------| _length
+        *                    |----------| _start
+        * </PRE>
+        */
        nframes_t position () const { return _position; }
        nframes_t start ()    const { return _start; }
        nframes_t length()    const { return _length; }
index 7c729b10f302e219f6ec4f12fb522dadcae9cb23..dd8fd6192660850ff31518e6f88cf88d313b4840 100644 (file)
@@ -121,7 +121,6 @@ class SMFSource : public MidiSource {
 
        static const uint16_t _ppqn = 19200;
 
-       uint16_t       _channel;
        Glib::ustring  _path;
        Flag           _flags;
        string         _take_id;
index 257108c818ab91ec5100705be49e6e273969103d..432addd93ae85d0e523bedfb84358908d9730919 100644 (file)
@@ -53,7 +53,6 @@ uint64_t                              SMFSource::header_position_offset;
 
 SMFSource::SMFSource (Session& s, std::string path, Flag flags)
        : MidiSource (s, region_name_from_path(path, false))
-       , _channel(0)
        , _flags (Flag(flags | Writable)) // FIXME: this needs to be writable for now
        , _allow_remove_if_empty(true)
        , _fd (0)
@@ -78,7 +77,6 @@ SMFSource::SMFSource (Session& s, std::string path, Flag flags)
 
 SMFSource::SMFSource (Session& s, const XMLNode& node)
        : MidiSource (s, node)
-       , _channel(0)
        , _flags (Flag (Writable|CanRename))
        , _allow_remove_if_empty(true)
        , _fd (0)