summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/midi_time_axis.cc13
-rw-r--r--gtk2_ardour/midi_time_axis.h3
-rw-r--r--libs/ardour/ardour/midi_diskstream.h12
-rw-r--r--libs/ardour/ardour/midi_ring_buffer.h51
-rw-r--r--libs/ardour/ardour/region.h10
-rw-r--r--libs/ardour/ardour/smf_source.h1
-rw-r--r--libs/ardour/smf_source.cc2
7 files changed, 84 insertions, 8 deletions
diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc
index 7169302315..89ca218ea2 100644
--- a/gtk2_ardour/midi_time_axis.cc
+++ b/gtk2_ardour/midi_time_axis.cc
@@ -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();
diff --git a/gtk2_ardour/midi_time_axis.h b/gtk2_ardour/midi_time_axis.h
index a91bd01d21..14aa4627e7 100644
--- a/gtk2_ardour/midi_time_axis.h
+++ b/gtk2_ardour/midi_time_axis.h
@@ -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__ */
diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h
index d08f00b72f..40df9cfc26 100644
--- a/libs/ardour/ardour/midi_diskstream.h
+++ b/libs/ardour/ardour/midi_diskstream.h
@@ -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;
diff --git a/libs/ardour/ardour/midi_ring_buffer.h b/libs/ardour/ardour/midi_ring_buffer.h
index 136d587550..7f0e9f3b37 100644
--- a/libs/ardour/ardour/midi_ring_buffer.h
+++ b/libs/ardour/ardour/midi_ring_buffer.h
@@ -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;
}
diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h
index fb1220e996..00315846b2 100644
--- a/libs/ardour/ardour/region.h
+++ b/libs/ardour/ardour/region.h
@@ -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; }
diff --git a/libs/ardour/ardour/smf_source.h b/libs/ardour/ardour/smf_source.h
index 7c729b10f3..dd8fd61926 100644
--- a/libs/ardour/ardour/smf_source.h
+++ b/libs/ardour/ardour/smf_source.h
@@ -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;
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index 257108c818..432addd93a 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -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)