mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 23:35:03 +01:00
make MIDI thru work even when not rolling; add GUI control over MIDI thru (midi track context menu); add "default channel" concept for MIDI tracks so that piano roll header events can send stuff on the right channel; add GUI control over this channel setting
git-svn-id: svn://localhost/ardour2/branches/3.0@5687 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
756fc18394
commit
9867035f29
5 changed files with 102 additions and 8 deletions
|
|
@ -108,6 +108,9 @@ MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session& sess,
|
||||||
, _meter_color_mode_item(0)
|
, _meter_color_mode_item(0)
|
||||||
, _channel_color_mode_item(0)
|
, _channel_color_mode_item(0)
|
||||||
, _track_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");
|
subplugin_menu.set_name ("ArdourContextMenu");
|
||||||
|
|
||||||
|
|
@ -301,8 +304,57 @@ MidiTimeAxisView::append_extra_display_menu_items ()
|
||||||
MidiStreamView::ContentsRange)));
|
MidiStreamView::ContentsRange)));
|
||||||
|
|
||||||
items.push_back (MenuElem (_("Note range"), *range_menu));
|
items.push_back (MenuElem (_("Note range"), *range_menu));
|
||||||
|
|
||||||
items.push_back (MenuElem (_("Note mode"), *build_note_mode_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
|
void
|
||||||
|
|
|
||||||
|
|
@ -129,12 +129,17 @@ class MidiTimeAxisView : public RouteTimeAxisView
|
||||||
Gtk::ComboBoxText _custom_device_mode_selector;
|
Gtk::ComboBoxText _custom_device_mode_selector;
|
||||||
|
|
||||||
Gtk::CheckMenuItem* _step_edit_item;
|
Gtk::CheckMenuItem* _step_edit_item;
|
||||||
|
Gtk::CheckMenuItem* _midi_thru_item;
|
||||||
|
Gtk::Menu* default_channel_menu;
|
||||||
|
|
||||||
nframes64_t step_edit_insert_position;
|
nframes64_t step_edit_insert_position;
|
||||||
Evoral::MusicalTime step_edit_beat_pos;
|
Evoral::MusicalTime step_edit_beat_pos;
|
||||||
boost::shared_ptr<ARDOUR::Region> step_edit_region;
|
boost::shared_ptr<ARDOUR::Region> step_edit_region;
|
||||||
MidiRegionView* step_edit_region_view;
|
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__ */
|
#endif /* __ardour_midi_time_axis_h__ */
|
||||||
|
|
|
||||||
|
|
@ -651,7 +651,7 @@ PianoRollHeader::send_note_on(uint8_t note)
|
||||||
//cerr << "note on: " << (int) note << endl;
|
//cerr << "note on: " << (int) note << endl;
|
||||||
|
|
||||||
if (track) {
|
if (track) {
|
||||||
_event[0] = MIDI_CMD_NOTE_ON;
|
_event[0] = (MIDI_CMD_NOTE_ON | track->default_channel());
|
||||||
_event[1] = note;
|
_event[1] = note;
|
||||||
_event[2] = 100;
|
_event[2] = 100;
|
||||||
|
|
||||||
|
|
@ -665,7 +665,7 @@ PianoRollHeader::send_note_off(uint8_t note)
|
||||||
boost::shared_ptr<ARDOUR::MidiTrack> track = _view.trackview().midi_track();
|
boost::shared_ptr<ARDOUR::MidiTrack> track = _view.trackview().midi_track();
|
||||||
|
|
||||||
if (track) {
|
if (track) {
|
||||||
_event[0] = MIDI_CMD_NOTE_OFF;
|
_event[0] = (MIDI_CMD_NOTE_OFF | track->default_channel());
|
||||||
_event[1] = note;
|
_event[1] = note;
|
||||||
_event[2] = 100;
|
_event[2] = 100;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,12 @@ public:
|
||||||
bool step_editing() const { return _step_editing; }
|
bool step_editing() const { return _step_editing; }
|
||||||
void set_step_editing (bool yn);
|
void set_step_editing (bool yn);
|
||||||
MidiRingBuffer<nframes_t>& step_edit_ring_buffer() { return _step_edit_ring_buffer; }
|
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:
|
protected:
|
||||||
XMLNode& state (bool full);
|
XMLNode& state (bool full);
|
||||||
|
|
@ -105,6 +111,9 @@ private:
|
||||||
MidiRingBuffer<nframes_t> _step_edit_ring_buffer;
|
MidiRingBuffer<nframes_t> _step_edit_ring_buffer;
|
||||||
NoteMode _note_mode;
|
NoteMode _note_mode;
|
||||||
bool _step_editing;
|
bool _step_editing;
|
||||||
|
uint8_t _default_channel;
|
||||||
|
bool _midi_thru;
|
||||||
|
|
||||||
|
|
||||||
int no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
|
int no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
|
||||||
bool state_changing, bool can_record, bool rec_monitors_input);
|
bool state_changing, bool can_record, bool rec_monitors_input);
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,8 @@ MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mo
|
||||||
, _step_edit_ring_buffer(64) // FIXME: size?
|
, _step_edit_ring_buffer(64) // FIXME: size?
|
||||||
, _note_mode(Sustained)
|
, _note_mode(Sustained)
|
||||||
, _step_editing (false)
|
, _step_editing (false)
|
||||||
|
, _default_channel (0)
|
||||||
|
, _midi_thru (true)
|
||||||
{
|
{
|
||||||
use_new_diskstream ();
|
use_new_diskstream ();
|
||||||
|
|
||||||
|
|
@ -70,6 +72,8 @@ MidiTrack::MidiTrack (Session& sess, const XMLNode& node)
|
||||||
, _step_edit_ring_buffer(64) // FIXME: size?
|
, _step_edit_ring_buffer(64) // FIXME: size?
|
||||||
, _note_mode(Sustained)
|
, _note_mode(Sustained)
|
||||||
, _step_editing (false)
|
, _step_editing (false)
|
||||||
|
, _default_channel (0)
|
||||||
|
, _midi_thru (true)
|
||||||
{
|
{
|
||||||
_set_state(node, false);
|
_set_state(node, false);
|
||||||
}
|
}
|
||||||
|
|
@ -175,6 +179,14 @@ MidiTrack::_set_state (const XMLNode& node, bool call_base)
|
||||||
_note_mode = Sustained;
|
_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) {
|
if ((prop = node.property ("diskstream-id")) == 0) {
|
||||||
|
|
||||||
/* some old sessions use the diskstream name rather than the ID */
|
/* 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 ("step-editing", (_step_editing ? "yes" : "no"));
|
||||||
root.add_property ("note-mode", enum_2_string (_note_mode));
|
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;
|
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);
|
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
|
// Feed the data through the MidiStateTracker
|
||||||
bool did_loop;
|
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));
|
MidiBuffer& buf (bufs.get_midi (0));
|
||||||
_immediate_events.read (buf, 0, 0, nframes - 1); // all stamps = 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
|
int
|
||||||
MidiTrack::export_stuff (BufferSet& /*bufs*/, nframes_t /*nframes*/, sframes_t /*end_frame*/)
|
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;
|
_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;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue