make MIDI thru work even when not rolling; add GUI control over MIDI thru (midi track...
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 25 Sep 2009 19:00:34 +0000 (19:00 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 25 Sep 2009 19:00:34 +0000 (19:00 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@5687 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/midi_time_axis.cc
gtk2_ardour/midi_time_axis.h
gtk2_ardour/piano_roll_header.cc
libs/ardour/ardour/midi_track.h
libs/ardour/midi_track.cc

index 6103e0254479a02b9095dd10badcf4d97688a1c4..b189827782d8fd3d20e8b30244a6717737d76031 100644 (file)
@@ -108,6 +108,9 @@ MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session& sess,
        , _meter_color_mode_item(0)
        , _channel_color_mode_item(0)
        , _track_color_mode_item(0)
+       , _step_edit_item (0)
+       , _midi_thru_item (0)
+       , default_channel_menu (0)
 {
        subplugin_menu.set_name ("ArdourContextMenu");
 
@@ -301,8 +304,57 @@ MidiTimeAxisView::append_extra_display_menu_items ()
                        MidiStreamView::ContentsRange)));
 
        items.push_back (MenuElem (_("Note range"), *range_menu));
-
        items.push_back (MenuElem (_("Note mode"), *build_note_mode_menu()));
+       items.push_back (MenuElem (_("Default Channel"), *build_def_channel_menu()));
+
+       items.push_back (CheckMenuElem (_("MIDI Thru"), mem_fun(*this, &MidiTimeAxisView::toggle_midi_thru)));
+       _midi_thru_item = dynamic_cast<CheckMenuItem*>(&items.back());
+}
+
+Gtk::Menu*
+MidiTimeAxisView::build_def_channel_menu ()
+{
+       using namespace Menu_Helpers;
+       
+       if (default_channel_menu == 0) {
+               default_channel_menu = manage (new Menu ());
+       } 
+       
+       uint8_t defchn = midi_track()->default_channel();
+       MenuList& def_channel_items = default_channel_menu->items();
+       RadioMenuItem* item;
+       RadioMenuItem::Group dc_group;
+       
+       for (int i = 0; i < 16; ++i) {
+               char buf[4];
+               snprintf (buf, sizeof (buf), "%d", i+1);
+               
+               def_channel_items.push_back (RadioMenuElem (dc_group, buf,
+                                                           bind (mem_fun (*this, &MidiTimeAxisView::set_default_channel), i)));
+               item = dynamic_cast<RadioMenuItem*>(&def_channel_items.back());
+               item->set_active ((i == defchn));
+       }
+
+       return default_channel_menu;
+}
+
+void
+MidiTimeAxisView::set_default_channel (int chn)
+{
+       midi_track()->set_default_channel (chn);
+}
+
+void
+MidiTimeAxisView::toggle_midi_thru ()
+{
+       if (!_midi_thru_item) {
+               return;
+       }
+
+       bool view_yn = _midi_thru_item->get_active();
+       if (view_yn != midi_track()->midi_thru()) {
+               midi_track()->set_midi_thru (view_yn);
+       }
 }
 
 void
index fd9db05a991f7f9e063df3e9700c616fec8f5c5f..d71c156f480735a2cccabfd881b21142814ff8b6 100644 (file)
@@ -129,12 +129,17 @@ class MidiTimeAxisView : public RouteTimeAxisView
        Gtk::ComboBoxText            _custom_device_mode_selector;
 
        Gtk::CheckMenuItem*          _step_edit_item;
+       Gtk::CheckMenuItem*          _midi_thru_item;
+       Gtk::Menu*                    default_channel_menu;
 
        nframes64_t step_edit_insert_position;
        Evoral::MusicalTime step_edit_beat_pos;
        boost::shared_ptr<ARDOUR::Region> step_edit_region;
        MidiRegionView* step_edit_region_view;
 
+       Gtk::Menu* build_def_channel_menu();
+       void set_default_channel (int);
+       void toggle_midi_thru ();
 };
 
 #endif /* __ardour_midi_time_axis_h__ */
index 9a7b86396fcd1e0fdb99d500f4d9124f9e6f3cb6..c6784bf853badf639544aca56fce0ed7a5ec3c44 100644 (file)
@@ -651,7 +651,7 @@ PianoRollHeader::send_note_on(uint8_t note)
        //cerr << "note on: " << (int) note << endl;
 
        if (track) {
-               _event[0] = MIDI_CMD_NOTE_ON;
+               _event[0] = (MIDI_CMD_NOTE_ON | track->default_channel());
                _event[1] = note;
                _event[2] = 100;
 
@@ -665,7 +665,7 @@ PianoRollHeader::send_note_off(uint8_t note)
        boost::shared_ptr<ARDOUR::MidiTrack> track = _view.trackview().midi_track();
 
        if (track) {
-               _event[0] = MIDI_CMD_NOTE_OFF;
+               _event[0] = (MIDI_CMD_NOTE_OFF | track->default_channel());
                _event[1] = note;
                _event[2] = 100;
 
index a1b0d2003e8a7b05d32a3b9591775054c17adff0..f8bca2304c69926e088d342802ceaa770e495fee 100644 (file)
@@ -84,6 +84,12 @@ public:
        bool step_editing() const { return _step_editing; }
        void set_step_editing (bool yn);
        MidiRingBuffer<nframes_t>& step_edit_ring_buffer() { return _step_edit_ring_buffer; }
+
+       uint8_t default_channel() const { return _default_channel; }
+       void set_default_channel (uint8_t chn);
+
+       bool midi_thru() const { return _midi_thru; }
+       void set_midi_thru (bool yn);
        
 protected:
        XMLNode& state (bool full);
@@ -105,6 +111,9 @@ private:
        MidiRingBuffer<nframes_t> _step_edit_ring_buffer;
        NoteMode                  _note_mode;
        bool                      _step_editing;
+       uint8_t                   _default_channel;
+       bool                      _midi_thru;
+
        
        int no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, 
                     bool state_changing, bool can_record, bool rec_monitors_input);
index 4f13682a89b2f9f93cf98ac5421b9de8f1579f72..bc6ea5fe58dbf43171124622e0bc1e716949d05c 100644 (file)
@@ -55,6 +55,8 @@ MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mo
        , _step_edit_ring_buffer(64) // FIXME: size?
        , _note_mode(Sustained)
        , _step_editing (false)
+       , _default_channel (0)
+       , _midi_thru (true)
 {
        use_new_diskstream ();
 
@@ -70,6 +72,8 @@ MidiTrack::MidiTrack (Session& sess, const XMLNode& node)
        , _step_edit_ring_buffer(64) // FIXME: size?
        , _note_mode(Sustained)
        , _step_editing (false)
+       , _default_channel (0)
+       , _midi_thru (true)
 {
        _set_state(node, false);
 }
@@ -175,6 +179,14 @@ MidiTrack::_set_state (const XMLNode& node, bool call_base)
                _note_mode = Sustained;
        }
 
+       if ((prop = node.property ("midi-thru")) != 0) {
+               set_midi_thru (prop->value() == "yes");
+       }
+
+       if ((prop = node.property ("default-channel")) != 0) {
+               set_default_channel ((uint8_t) atoi (prop->value()));
+       }
+
        if ((prop = node.property ("diskstream-id")) == 0) {
                
                /* some old sessions use the diskstream name rather than the ID */
@@ -284,6 +296,9 @@ MidiTrack::state(bool full_state)
 
        root.add_property ("step-editing", (_step_editing ? "yes" : "no"));
        root.add_property ("note-mode", enum_2_string (_note_mode));
+       root.add_property ("midi-thru", (_midi_thru ? "yes" : "no"));
+       snprintf (buf, sizeof (buf), "%d", (int) _default_channel);
+       root.add_property ("default-channel", buf);
        
        return root;
 }
@@ -450,11 +465,6 @@ MidiTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
 
                write_out_of_band_data (bufs, start_frame, end_frame, nframes); 
 
-               /* send incoming data "through" output */
-               if (_input->n_ports().n_midi()) {
-                       mbuf.merge_in_place (_input->midi(0)->get_midi_buffer(nframes));
-               }
-
                // Feed the data through the MidiStateTracker
                bool did_loop;
 
@@ -535,8 +545,14 @@ MidiTrack::write_out_of_band_data (BufferSet& bufs, sframes_t /*start*/, sframes
 
        MidiBuffer& buf (bufs.get_midi (0));
        _immediate_events.read (buf, 0, 0, nframes - 1); // all stamps = 0
+
+       /* MIDI thru: send incoming data "through" output */
+       if (_midi_thru && _input->n_ports().n_midi()) {
+               buf.merge_in_place (_input->midi(0)->get_midi_buffer(nframes));
+       }
 }
 
+
 int
 MidiTrack::export_stuff (BufferSet& /*bufs*/, nframes_t /*nframes*/, sframes_t /*end_frame*/)
 {
@@ -678,3 +694,15 @@ MidiTrack::set_step_editing (bool yn)
 {
        _step_editing = yn;
 }
+
+void
+MidiTrack::set_default_channel (uint8_t chn)
+{
+       _default_channel = std::min ((unsigned int) chn, 15U);
+}
+
+void
+MidiTrack::set_midi_thru (bool yn)
+{
+       _midi_thru = yn;
+}