diff options
-rw-r--r-- | gtk2_ardour/canvas-note-event.cc | 1 | ||||
-rw-r--r-- | gtk2_ardour/midi_channel_selector.cc | 163 | ||||
-rw-r--r-- | gtk2_ardour/midi_channel_selector.h | 62 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.cc | 113 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.h | 9 | ||||
-rw-r--r-- | gtk2_ardour/midi_time_axis.cc | 10 | ||||
-rw-r--r-- | gtk2_ardour/midi_time_axis.h | 7 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_diskstream.h | 25 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_ring_buffer.h | 156 | ||||
-rw-r--r-- | libs/ardour/ardour/types.h | 6 | ||||
-rw-r--r-- | libs/ardour/enums.cc | 6 | ||||
-rw-r--r-- | libs/ardour/midi_buffer.cc | 5 | ||||
-rw-r--r-- | libs/ardour/midi_diskstream.cc | 27 | ||||
-rw-r--r-- | libs/ardour/midi_model.cc | 3 | ||||
-rw-r--r-- | libs/ardour/midi_track.cc | 22 | ||||
-rw-r--r-- | libs/ardour/smf_source.cc | 6 | ||||
-rw-r--r-- | libs/midi++2/jack_midiport.cc | 31 |
17 files changed, 353 insertions, 299 deletions
diff --git a/gtk2_ardour/canvas-note-event.cc b/gtk2_ardour/canvas-note-event.cc index bd402f8c08..0e758b5489 100644 --- a/gtk2_ardour/canvas-note-event.cc +++ b/gtk2_ardour/canvas-note-event.cc @@ -45,7 +45,6 @@ CanvasNoteEvent::CanvasNoteEvent(MidiRegionView& region, Item* item, CanvasNoteEvent::~CanvasNoteEvent() { - cerr << "CanvasNoteEvent::~CanvasNoteEvent() " << int(_note->note()) << " velo " << int(_note->velocity()) << endl; if (_text) { _text->hide(); delete _text; diff --git a/gtk2_ardour/midi_channel_selector.cc b/gtk2_ardour/midi_channel_selector.cc index 0018c169ab..281c6f5e2d 100644 --- a/gtk2_ardour/midi_channel_selector.cc +++ b/gtk2_ardour/midi_channel_selector.cc @@ -1,14 +1,34 @@ +/* + Copyright (C) 2008 Paul Davis + Author: Hans Baier + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <sstream> #include "midi_channel_selector.h" #include "gtkmm/separator.h" #include "i18n.h" -#include <sstream> using namespace std; using namespace Gtk; using namespace sigc; +using namespace ARDOUR; -MidiChannelSelector::MidiChannelSelector(int no_rows, int no_columns, int start_row, int start_column) : - Table(no_rows, no_columns, true), _recursion_counter(0) +MidiChannelSelector::MidiChannelSelector(int no_rows, int no_columns, int start_row, int start_column) : Table(no_rows, no_columns, true) + , _recursion_counter(0) { assert(no_rows >= 4); assert(no_rows >= start_row + 4); @@ -19,8 +39,8 @@ MidiChannelSelector::MidiChannelSelector(int no_rows, int no_columns, int start_ property_row_spacing() = 0; uint8_t channel_nr = 0; - for(int row = 0; row < 4; ++row) { - for(int column = 0; column < 4; ++column) { + for (int row = 0; row < 4; ++row) { + for (int column = 0; column < 4; ++column) { ostringstream channel; channel << int(++channel_nr); _button_labels[row][column].set_text(channel.str()); @@ -47,21 +67,21 @@ SingleMidiChannelSelector::SingleMidiChannelSelector(uint8_t active_channel) : MidiChannelSelector() { _last_active_button = 0; - ToggleButton *button = &_buttons[active_channel / 4][active_channel % 4]; + ToggleButton* button = &_buttons[active_channel / 4][active_channel % 4]; _active_channel = active_channel; button->set_active(true); _last_active_button = button; } void -SingleMidiChannelSelector::button_toggled(ToggleButton *button, uint8_t channel) +SingleMidiChannelSelector::button_toggled(ToggleButton* button, uint8_t channel) { ++_recursion_counter; - if(_recursion_counter == 1) { + if (_recursion_counter == 1) { // if the current button is active it must // be different from the first one - if(button->get_active()) { - if(_last_active_button) { + if (button->get_active()) { + if (_last_active_button) { _last_active_button->set_active(false); _active_channel = channel; _last_active_button = button; @@ -76,8 +96,9 @@ SingleMidiChannelSelector::button_toggled(ToggleButton *button, uint8_t channel) --_recursion_counter; } -MidiMultipleChannelSelector::MidiMultipleChannelSelector(uint16_t initial_selection, int8_t force_channel) - : MidiChannelSelector(4, 6, 0, 0), _mode(FILTERING_MULTIPLE_CHANNELS) +MidiMultipleChannelSelector::MidiMultipleChannelSelector(ChannelMode mode, uint16_t mask) + : MidiChannelSelector(4, 6, 0, 0) + , _channel_mode(mode) { _select_all.add(*manage(new Label(_("All")))); _select_all.signal_clicked().connect( @@ -103,58 +124,42 @@ MidiMultipleChannelSelector::MidiMultipleChannelSelector(uint16_t initial_select attach(_invert_selection, 5, 6, 2, 3); attach(_force_channel, 5, 6, 3, 4); - set_selected_channels(initial_selection); + set_selected_channels(mask); } MidiMultipleChannelSelector::~MidiMultipleChannelSelector() { - selection_changed.clear(); - force_channel_changed.clear(); + mode_changed.clear(); } -const int8_t -MidiMultipleChannelSelector::get_force_channel() const +void +MidiMultipleChannelSelector::set_channel_mode(ChannelMode mode, uint8_t mask) { - if(_mode == FORCING_SINGLE_CHANNEL) { - for(int8_t i = 0; i < 16; i++) { - const ToggleButton *button = &_buttons[i / 4][i % 4]; - if(button->get_active()) { - return i; - } + switch (mode) { + case AllChannels: + _force_channel.set_active(false); + set_selected_channels(0xFFFF); + break; + case FilterChannels: + _force_channel.set_active(false); + set_selected_channels(mask); + break; + case ForceChannel: + _force_channel.set_active(true); + for (uint16_t i = 0; i < 16; i++) { + ToggleButton* button = &_buttons[i / 4][i % 4]; + button->set_active(i == mask); } - - // this point should not be reached. - assert(false); - } - - return -1; -} - -void -MidiMultipleChannelSelector::set_force_channel(int8_t channel) -{ - if(channel < 0) { - // if forcing is already activated, deactivate - if(_mode == FORCING_SINGLE_CHANNEL) { - _force_channel.toggled(); - } - // if not, nothing to do - } else { - // otherwise simulate activating force channels by pressing the - // two buttons the user would press - _force_channel.toggled(); - _buttons[channel / 4][channel % 4].toggled(); } } - const uint16_t MidiMultipleChannelSelector::get_selected_channels() const { uint16_t selected_channels = 0; - for(uint16_t i = 0; i < 16; i++) { - const ToggleButton *button = &_buttons[i / 4][i % 4]; - if(button->get_active()) { + for (uint16_t i = 0; i < 16; i++) { + const ToggleButton* button = &_buttons[i / 4][i % 4]; + if (button->get_active()) { selected_channels |= (1L << i); } } @@ -165,9 +170,9 @@ MidiMultipleChannelSelector::get_selected_channels() const void MidiMultipleChannelSelector::set_selected_channels(uint16_t selected_channels) { - for(uint16_t i = 0; i < 16; i++) { - ToggleButton *button = &_buttons[i / 4][i % 4]; - if(selected_channels & (1L << i)) { + for (uint16_t i = 0; i < 16; i++) { + ToggleButton* button = &_buttons[i / 4][i % 4]; + if (selected_channels & (1L << i)) { button->set_active(true); } else { button->set_active(false); @@ -179,13 +184,13 @@ void MidiMultipleChannelSelector::button_toggled(ToggleButton *button, uint8_t channel) { ++_recursion_counter; - if(_recursion_counter == 1) { - if(_mode == FORCING_SINGLE_CHANNEL) { + if (_recursion_counter == 1) { + if (_channel_mode == ForceChannel) { + mode_changed.emit(_channel_mode, channel); set_selected_channels(1 << channel); + } else { + mode_changed.emit(_channel_mode, get_selected_channels()); } - - force_channel_changed.emit(get_force_channel()); - selection_changed.emit(get_selected_channels()); } --_recursion_counter; } @@ -193,67 +198,73 @@ MidiMultipleChannelSelector::button_toggled(ToggleButton *button, uint8_t channe void MidiMultipleChannelSelector::force_channels_button_toggled() { - if(_force_channel.get_active()) { - _mode = FORCING_SINGLE_CHANNEL; + if (_force_channel.get_active()) { + _channel_mode = ForceChannel; bool found_first_active = false; // leave only the first button enabled - for(int i = 0; i <= 15; i++) { - ToggleButton *button = &_buttons[i / 4][i % 4]; - if(button->get_active()) { - if(found_first_active) { + uint16_t active_channel = 0; + for (int i = 0; i <= 15; i++) { + ToggleButton* button = &_buttons[i / 4][i % 4]; + if (button->get_active()) { + if (found_first_active) { ++_recursion_counter; button->set_active(false); --_recursion_counter; } else { found_first_active = true; + active_channel = i; } } } - if(!found_first_active) { + if (!found_first_active) { _buttons[0][0].set_active(true); } _select_all.set_sensitive(false); _select_none.set_sensitive(false); _invert_selection.set_sensitive(false); - force_channel_changed.emit(get_force_channel()); - selection_changed.emit(get_selected_channels()); + mode_changed.emit(_channel_mode, active_channel); } else { - _mode = FILTERING_MULTIPLE_CHANNELS; + _channel_mode = FilterChannels; _select_all.set_sensitive(true); _select_none.set_sensitive(true); _invert_selection.set_sensitive(true); - force_channel_changed.emit(get_force_channel()); - selection_changed.emit(get_selected_channels()); + mode_changed.emit(FilterChannels, get_selected_channels()); } } void MidiMultipleChannelSelector::select_all(bool on) { + if (_channel_mode == ForceChannel) + return; + ++_recursion_counter; - for(uint16_t i = 0; i < 16; i++) { - ToggleButton *button = &_buttons[i / 4][i % 4]; + for (uint16_t i = 0; i < 16; i++) { + ToggleButton* button = &_buttons[i / 4][i % 4]; button->set_active(on); } --_recursion_counter; - selection_changed.emit(get_selected_channels()); + mode_changed.emit(_channel_mode, get_selected_channels()); } void MidiMultipleChannelSelector::invert_selection(void) { + if (_channel_mode == ForceChannel) + return; + ++_recursion_counter; - for(uint16_t i = 0; i < 16; i++) { - ToggleButton *button = &_buttons[i / 4][i % 4]; - if(button->get_active()) { + for (uint16_t i = 0; i < 16; i++) { + ToggleButton* button = &_buttons[i / 4][i % 4]; + if (button->get_active()) { button->set_active(false); } else { button->set_active(true); } } --_recursion_counter; - selection_changed.emit(get_selected_channels()); + mode_changed.emit(_channel_mode, get_selected_channels()); } diff --git a/gtk2_ardour/midi_channel_selector.h b/gtk2_ardour/midi_channel_selector.h index 9ac95036d6..1f15f3eef5 100644 --- a/gtk2_ardour/midi_channel_selector.h +++ b/gtk2_ardour/midi_channel_selector.h @@ -1,13 +1,34 @@ +/* + Copyright (C) 2008 Paul Davis + Author: Hans Baier + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __ardour_ui_midi_channel_selector_h__ #define __ardour_ui_midi_channel_selector_h__ +#include <set> #include "boost/shared_ptr.hpp" -#include "gtkmm/table.h" #include "sigc++/trackable.h" +#include "gtkmm/table.h" #include "gtkmm/button.h" #include "gtkmm/togglebutton.h" #include "gtkmm/label.h" -#include <set> +#include <ardour/types.h> + class MidiChannelSelector : public Gtk::Table { @@ -15,8 +36,10 @@ public: MidiChannelSelector(int no_rows = 4, int no_columns = 4, int start_row = 0, int start_column = 0); virtual ~MidiChannelSelector() = 0; + sigc::signal<void, ARDOUR::ChannelMode, uint16_t> mode_changed; + protected: - virtual void button_toggled(Gtk::ToggleButton *button, uint8_t button_nr) = 0; + virtual void button_toggled(Gtk::ToggleButton* button, uint8_t button_nr) = 0; Gtk::Label _button_labels[4][4]; Gtk::ToggleButton _buttons[4][4]; int _recursion_counter; @@ -32,7 +55,7 @@ public: sigc::signal<void, uint8_t> channel_selected; protected: - virtual void button_toggled(Gtk::ToggleButton *button, uint8_t button_nr); + virtual void button_toggled(Gtk::ToggleButton* button, uint8_t button_nr); Gtk::ToggleButton* _last_active_button; uint8_t _active_channel; @@ -41,40 +64,35 @@ protected: class MidiMultipleChannelSelector : public MidiChannelSelector { public: - MidiMultipleChannelSelector(uint16_t initial_selection = 0xFFFF, int8_t force_channel = -1); + MidiMultipleChannelSelector(ARDOUR::ChannelMode mode = ARDOUR::FilterChannels, + uint16_t initial_selection = 0xFFFF); + virtual ~MidiMultipleChannelSelector(); + void set_channel_mode(ARDOUR::ChannelMode mode, uint8_t mask); + /** * @return each bit in the returned word represents a midi channel, eg. * bit 0 represents channel 0 and bit 15 represents channel 15 * */ const uint16_t get_selected_channels() const; - void set_selected_channels(uint16_t selected_channels); - - sigc::signal<void, uint16_t> selection_changed; - sigc::signal<void, int8_t> force_channel_changed; + void set_selected_channels(uint16_t selected_channels); - const int8_t get_force_channel() const; - void set_force_channel(int8_t force_channel); protected: - enum Mode { - FILTERING_MULTIPLE_CHANNELS, - FORCING_SINGLE_CHANNEL - }; - - Mode _mode; + ARDOUR::ChannelMode _channel_mode; + ARDOUR::NoteMode _note_mode; - virtual void button_toggled(Gtk::ToggleButton *button, uint8_t button_nr); + virtual void button_toggled(Gtk::ToggleButton* button, uint8_t button_nr); void force_channels_button_toggled(); void select_all(bool on); void invert_selection(void); - Gtk::Button _select_all; - Gtk::Button _select_none; - Gtk::Button _invert_selection; - Gtk::ToggleButton _force_channel; + Gtk::Button _select_all; + Gtk::Button _select_none; + Gtk::Button _invert_selection; + Gtk::ToggleButton _force_channel; }; #endif /*__ardour_ui_midi_channel_selector_h__*/ diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index bc492b0e71..b83630e9fa 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -62,8 +62,8 @@ using namespace ArdourCanvas; MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, boost::shared_ptr<MidiRegion> r, double spu, Gdk::Color& basic_color) : RegionView (parent, tv, r, spu, basic_color) - , force_channel(-1) - , last_channel_selection(0xFFFF) + , _force_channel(-1) + , _last_channel_selection(0xFFFF) , _default_note_length(0.0) , _active_notes(0) , _note_group(new ArdourCanvas::Group(*parent)) @@ -79,8 +79,8 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView & MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, boost::shared_ptr<MidiRegion> r, double spu, Gdk::Color& basic_color, TimeAxisViewItem::Visibility visibility) : RegionView (parent, tv, r, spu, basic_color, visibility) - , force_channel(-1) - , last_channel_selection(0xFFFF) + , _force_channel(-1) + , _last_channel_selection(0xFFFF) , _default_note_length(0.0) , _active_notes(0) , _note_group(new ArdourCanvas::Group(*parent)) @@ -135,10 +135,8 @@ MidiRegionView::init (Gdk::Color& basic_color, bool wfd) group->signal_event().connect (mem_fun (this, &MidiRegionView::canvas_event), false); - midi_view()->signal_force_channel_changed().connect( - mem_fun(this, &MidiRegionView::midi_force_channel_changed)); - midi_view()->signal_channel_selection_changed().connect( - mem_fun(this, &MidiRegionView::midi_channel_selection_changed)); + midi_view()->signal_channel_mode_changed().connect( + mem_fun(this, &MidiRegionView::midi_channel_mode_changed)); } bool @@ -324,7 +322,7 @@ MidiRegionView::canvas_event(GdkEvent* ev) group->ungrab(ev->button.time); event_frame = trackview.editor.pixel_to_frame(event_x); - if(_pressed_button != 1) { + if (_pressed_button != 1) { return false; } @@ -458,18 +456,17 @@ MidiRegionView::redisplay_model() clear_events(); _model->read_lock(); - MidiModel::Notes notes = _model->notes(); - cerr << endl << "Model contains " << notes.size() << " Notes:" << endl; - for(MidiModel::Notes::iterator i = notes.begin(); i != notes.end(); ++i) { - cerr << "MODEL: Note time: " << (*i)->time() - << " pitch: " << int((*i)->note()) - << " duration: " << (*i)->duration() - << " end-time: " << (*i)->end_time() - << " velocity: " << int((*i)->velocity()) - //<< " Note-on: " << note.on_event(). - //<< " Note-off: " << note.off_event() + /*MidiModel::Notes notes = _model->notes(); + cerr << endl << _model->midi_source()->name() << " : redisplaying " << notes.size() << " notes:" << endl; + for (MidiModel::Notes::iterator i = notes.begin(); i != notes.end(); ++i) { + cerr << "NOTE time: " << (*i)->time() + << " pitch: " << int((*i)->note()) + << " duration: " << (*i)->duration() + << " end-time: " << (*i)->end_time() + << " velocity: " << int((*i)->velocity()) << endl; - } + }*/ + for (size_t i = 0; i < _model->n_notes(); ++i) { add_note(_model->note_at(i)); @@ -479,10 +476,10 @@ MidiRegionView::redisplay_model() control = _model->controls().begin(); control != _model->controls().end(); ++control) { - if( control->first.type() == MidiPgmChangeAutomation ) { + if ( control->first.type() == MidiPgmChangeAutomation ) { Glib::Mutex::Lock list_lock (control->second->list()->lock()); - for(AutomationList::const_iterator event = control->second->list()->begin(); + for (AutomationList::const_iterator event = control->second->list()->begin(); event != control->second->list()->end(); ++event) { boost::shared_ptr<MIDI::Event> midi_event(new MIDI::Event()); MidiControlIterator iter(control->second->list(), (*event)->when, (*event)->value); @@ -594,14 +591,14 @@ MidiRegionView::set_y_position_and_height (double y, double h) } event->hide_velocity(); - if(CanvasNote* note = dynamic_cast<CanvasNote*>(event)) { + if (CanvasNote* note = dynamic_cast<CanvasNote*>(event)) { const double y1 = midi_stream_view()->note_to_y(event->note()->note()); const double y2 = y1 + floor(midi_stream_view()->note_height()); note->property_y1() = y1; note->property_y2() = y2; } - if(CanvasHit* hit = dynamic_cast<CanvasHit*>(event)) { + if (CanvasHit* hit = dynamic_cast<CanvasHit*>(event)) { double x = trackview.editor.frame_to_pixel((nframes_t) event->note()->time() - _region->start()); const double diamond_size = midi_stream_view()->note_height() / 2.0; @@ -612,7 +609,7 @@ MidiRegionView::set_y_position_and_height (double y, double h) hit->move(x-hit->x1(), y-hit->y1()); hit->show(); } - if(event->selected()) { + if (event->selected()) { event->show_velocity(); } } @@ -732,7 +729,7 @@ MidiRegionView::add_note(const boost::shared_ptr<Note> note) assert(midi_view()->note_mode() == Sustained || midi_view()->note_mode() == Percussive); // dont display notes beyond the region bounds - if( + if ( note->time() - _region->start() >= _region->length() || note->time() < _region->start() || note->note() < midi_stream_view()->lowest_note() || @@ -805,11 +802,11 @@ MidiRegionView::add_note(const boost::shared_ptr<Note> note) event = 0; } - if(event) { - if(_marked_for_selection.find(event->note()) != _marked_for_selection.end()) { + if (event) { + if (_marked_for_selection.find(event->note()) != _marked_for_selection.end()) { note_selected(event, true); } - event->on_channel_selection_change(last_channel_selection); + event->on_channel_selection_change(_last_channel_selection); } } @@ -819,7 +816,7 @@ MidiRegionView::add_pgm_change(boost::shared_ptr<MIDI::Event> event) assert(event->time() >= 0); // dont display notes beyond the region bounds - if( + if ( event->time() - _region->start() >= _region->length() || event->time() < _region->start() ) { @@ -997,7 +994,7 @@ MidiRegionView::note_dropped(CanvasNoteEvent* ev, double dt, uint8_t dnote) new_note_time += dt; // keep notes inside region if dragged beyond left region bound - if(new_note_time < _region->start()) { + if (new_note_time < _region->start()) { new_note_time = _region->start(); } @@ -1014,7 +1011,7 @@ MidiRegionView::note_dropped(CanvasNoteEvent* ev, double dt, uint8_t dnote) clamp_0_to_127(new_pitch); //notes which are dragged beyond the standard midi range snap back to their original place - if((original_pitch != 0 && new_pitch == 0) || (original_pitch != 127 && new_pitch == 127)) { + if ((original_pitch != 0 && new_pitch == 0) || (original_pitch != 127 && new_pitch == 127)) { new_pitch = original_pitch; } @@ -1032,7 +1029,7 @@ MidiRegionView::note_dropped(CanvasNoteEvent* ev, double dt, uint8_t dnote) apply_command(); // care about notes being moved beyond the upper/lower bounds on the canvas - if(lowest_note_in_selection < midi_stream_view()->lowest_note() || + if (lowest_note_in_selection < midi_stream_view()->lowest_note() || highest_note_in_selection > midi_stream_view()->highest_note() ) { midi_stream_view()->set_note_range(MidiStreamView::ContentsRange); @@ -1088,7 +1085,7 @@ MidiRegionView::begin_resizing(CanvasNote::NoteEnd note_end) CanvasNote *note = dynamic_cast<CanvasNote *> (*i); // only insert CanvasNotes into the map - if(note) { + if (note) { NoteResizeData *resize_data = new NoteResizeData(); resize_data->canvas_note = note; @@ -1122,7 +1119,7 @@ MidiRegionView::begin_resizing(CanvasNote::NoteEnd note_end) resize_data->resize_rect = resize_rect; - if(note_end == CanvasNote::NOTE_ON) { + if (note_end == CanvasNote::NOTE_ON) { resize_data->current_x = note->x1(); } else { // NOTE_OFF resize_data->current_x = note->x2(); @@ -1142,7 +1139,7 @@ MidiRegionView::update_resizing(CanvasNote::NoteEnd note_end, double x, bool rel const double region_start = get_position_pixels(); - if(relative) { + if (relative) { (*i)->current_x = (*i)->current_x + x; } else { // x is in track relative, transform it to region relative @@ -1151,7 +1148,7 @@ MidiRegionView::update_resizing(CanvasNote::NoteEnd note_end, double x, bool rel double current_x = (*i)->current_x; - if(note_end == CanvasNote::NOTE_ON) { + if (note_end == CanvasNote::NOTE_ON) { resize_rect->property_x1() = snap_to_pixel(current_x); resize_rect->property_x2() = canvas_note->x2(); } else { @@ -1172,7 +1169,7 @@ MidiRegionView::commit_resizing(CanvasNote::NoteEnd note_end, double event_x, bo double current_x = (*i)->current_x; const double position = get_position_pixels(); - if(!relative) { + if (!relative) { // event_x is in track relative, transform it to region relative current_x = event_x - position; } @@ -1221,7 +1218,7 @@ MidiRegionView::change_velocity(uint8_t velocity, bool relative) CanvasNoteEvent *event = *i; const boost::shared_ptr<Note> copy(new Note(*(event->note().get()))); - if(relative) { + if (relative) { uint8_t new_velocity = copy->velocity() + velocity; clamp_0_to_127(new_velocity); @@ -1238,7 +1235,7 @@ MidiRegionView::change_velocity(uint8_t velocity, bool relative) } // dont keep notes selected if tweaking a single note - if(_marked_for_selection.size() == 1) { + if (_marked_for_selection.size() == 1) { _marked_for_selection.clear(); } @@ -1266,7 +1263,7 @@ MidiRegionView::change_channel(uint8_t channel) } // dont keep notes selected if tweaking a single note - if(_marked_for_selection.size() == 1) { + if (_marked_for_selection.size() == 1) { _marked_for_selection.clear(); } @@ -1308,22 +1305,24 @@ MidiRegionView::set_frame_color() } void -MidiRegionView::midi_force_channel_changed(int8_t channel) -{ - force_channel = channel; -} - -void -MidiRegionView::midi_channel_selection_changed(uint16_t selection) +MidiRegionView::midi_channel_mode_changed(ChannelMode mode, uint16_t mask) { - if(force_channel >= 0) { - selection = 0xFFFF; - } - - for(std::vector<ArdourCanvas::CanvasNoteEvent*>::iterator i = _events.begin(); - i != _events.end(); - ++i) { - (*i)->on_channel_selection_change(selection); + switch (mode) { + case AllChannels: + case FilterChannels: + _force_channel = -1; + break; + case ForceChannel: + _force_channel = mask; + mask = 0xFFFF; // Show all notes as active (below) + }; + + // Update notes for selection + for (std::vector<ArdourCanvas::CanvasNoteEvent*>::iterator i = _events.begin(); + i != _events.end(); ++i) { + (*i)->on_channel_selection_change(mask); } - last_channel_selection = selection; + + _last_channel_selection = mask; } + diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index 1a37205bef..4283483f04 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -241,16 +241,15 @@ class MidiRegionView : public RegionView bool canvas_event(GdkEvent* ev); bool note_canvas_event(GdkEvent* ev); - int8_t force_channel; - void midi_force_channel_changed(int8_t channel); - uint16_t last_channel_selection; - void midi_channel_selection_changed(uint16_t selection); + void midi_channel_mode_changed(ARDOUR::ChannelMode mode, uint16_t mask); void clear_selection_except(ArdourCanvas::CanvasNoteEvent* ev); void clear_selection() { clear_selection_except(NULL); } void update_drag_selection(double last_x, double x, double last_y, double y); - double _default_note_length; + int8_t _force_channel; + uint16_t _last_channel_selection; + double _default_note_length; boost::shared_ptr<ARDOUR::MidiModel> _model; std::vector<ArdourCanvas::CanvasNoteEvent*> _events; diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc index 95b77abaf4..f6d2993cfe 100644 --- a/gtk2_ardour/midi_time_axis.cc +++ b/gtk2_ardour/midi_time_axis.cc @@ -144,13 +144,11 @@ MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session& sess, boost::shar mem_fun(this, &MidiTimeAxisView::channel_selector_toggled)); controls_vbox.pack_end(_midi_expander, SHRINK, 0); boost::shared_ptr<MidiDiskstream> diskstream = midi_track()->midi_diskstream(); + // restore channel selector settings - _channel_selector.set_selected_channels(diskstream->get_channel_mask()); - _channel_selector.set_force_channel(diskstream->get_force_channel()); - _channel_selector.selection_changed.connect( - mem_fun(*midi_track()->midi_diskstream(), &MidiDiskstream::set_channel_mask)); - _channel_selector.force_channel_changed.connect( - mem_fun(*midi_track()->midi_diskstream(), &MidiDiskstream::set_force_channel)); + _channel_selector.set_channel_mode(diskstream->get_channel_mode(), diskstream->get_channel_mask()); + _channel_selector.mode_changed.connect( + mem_fun(*midi_track()->midi_diskstream(), &MidiDiskstream::set_channel_mode)); } diff --git a/gtk2_ardour/midi_time_axis.h b/gtk2_ardour/midi_time_axis.h index 98cc5bb0b7..cdbf6907e1 100644 --- a/gtk2_ardour/midi_time_axis.h +++ b/gtk2_ardour/midi_time_axis.h @@ -74,11 +74,8 @@ class MidiTimeAxisView : public RouteTimeAxisView void update_range(); - sigc::signal<void, uint16_t>& signal_channel_selection_changed() - { return _channel_selector.selection_changed; } - - sigc::signal<void, int8_t>& signal_force_channel_changed() - { return _channel_selector.force_channel_changed; } + sigc::signal<void, ARDOUR::ChannelMode, uint16_t>& signal_channel_mode_changed() + { return _channel_selector.mode_changed; } private: diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h index f52f66dc6d..3e8e9c4156 100644 --- a/libs/ardour/ardour/midi_diskstream.h +++ b/libs/ardour/ardour/midi_diskstream.h @@ -90,28 +90,27 @@ class MidiDiskstream : public Diskstream 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(); +#ifndef NDEBUG uint16_t capture_mask = _capture_buf->get_channel_mask(); assert(playback_mask == capture_mask); +#endif return playback_mask; } - void set_force_channel(int8_t force_channel) { - _playback_buf->set_force_channel(force_channel); - _capture_buf->set_force_channel(force_channel); + void set_channel_mode(ChannelMode mode, uint16_t mask) { + _playback_buf->set_channel_mode(mode, mask); + _capture_buf->set_channel_mode(mode, mask); } - int8_t get_force_channel() { - int8_t playback_force_channel = _playback_buf->get_force_channel(); - int8_t capture_force_channel = _capture_buf->get_force_channel(); - assert(playback_force_channel == capture_force_channel); - return playback_force_channel; + ChannelMode get_channel_mode() { + ChannelMode playback_mode = _playback_buf->get_channel_mode(); +#ifndef NDEBUG + ChannelMode capture_mode = _capture_buf->get_channel_mode(); + assert(playback_mode == capture_mode); +#endif + return playback_mode; } protected: diff --git a/libs/ardour/ardour/midi_ring_buffer.h b/libs/ardour/ardour/midi_ring_buffer.h index 680e2a7b61..ea0013fe46 100644 --- a/libs/ardour/ardour/midi_ring_buffer.h +++ b/libs/ardour/ardour/midi_ring_buffer.h @@ -75,7 +75,7 @@ public: if (w > r) { return ((r - w + _size) % _size) - 1; - } else if(w < r) { + } else if (w < r) { return (r - w) - 1; } else { return _size - 1; @@ -101,15 +101,17 @@ public: size_t read(size_t size, T* dst); bool full_read(size_t size, T* dst); + + bool skip(size_t size); void write(size_t size, const T* src); protected: - mutable gint _write_ptr; - mutable gint _read_ptr; + mutable int _write_ptr; + mutable int _read_ptr; size_t _size; ///< Size (capacity) in bytes - T* _buf; ///< size, event, size, event... + T* _buf; ///< size, event, size, event... }; @@ -130,7 +132,7 @@ MidiRingBufferBase<T>::peek(size_t size, T* dst) : _size - priv_read_ptr; memcpy(dst, &_buf[priv_read_ptr], read_size); - + return read_size; } @@ -168,7 +170,7 @@ MidiRingBufferBase<T>::read(size_t size, T* dst) : _size - priv_read_ptr; memcpy(dst, &_buf[priv_read_ptr], read_size); - + g_atomic_int_set(&_read_ptr, (priv_read_ptr + read_size) % _size); return read_size; @@ -192,6 +194,23 @@ MidiRingBufferBase<T>::full_read(size_t size, T* dst) template<typename T> +bool +MidiRingBufferBase<T>::skip(size_t size) +{ + if (read_space() < size) { + std::cerr << "WARNING: Attempt to skip past end of MIDI ring buffer" << std::endl; + return false; + } + + const size_t priv_read_ptr = g_atomic_int_get(&_read_ptr); + g_atomic_int_set(&_read_ptr, (priv_read_ptr + size) % _size); + + return true; +} + + + +template<typename T> inline void MidiRingBufferBase<T>::write(size_t size, const T* src) { @@ -199,14 +218,14 @@ MidiRingBufferBase<T>::write(size_t size, const T* src) if (priv_write_ptr + size <= _size) { memcpy(&_buf[priv_write_ptr], src, size); - g_atomic_int_set(&_write_ptr, (priv_write_ptr + size) % _size); + g_atomic_int_set(&_write_ptr, (priv_write_ptr + size) % _size); } else { const size_t this_size = _size - priv_write_ptr; assert(this_size < size); assert(priv_write_ptr + this_size <= _size); memcpy(&_buf[priv_write_ptr], src, this_size); memcpy(&_buf[0], src+this_size, size - this_size); - g_atomic_int_set(&_write_ptr, size - this_size); + g_atomic_int_set(&_write_ptr, size - this_size); } } @@ -223,11 +242,10 @@ MidiRingBufferBase<T>::write(size_t size, const T* src) */ class MidiRingBuffer : public MidiRingBufferBase<Byte> { public: - /** @param size Size in bytes. */ MidiRingBuffer(size_t size) - : MidiRingBufferBase<Byte>(size), _channel_mask(0xFFFF), _force_channel(-1) + : MidiRingBufferBase<Byte>(size), _channel_mask(0x0000FFFF) {} size_t write(double time, size_t size, const Byte* buf); @@ -238,21 +256,24 @@ public: size_t read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t offset=0); - /** - * @param channel_mask each bit in channel_mask represents a midi channel: bit 0 = channel 0, - * bit 1 = channel 1 etc. the read and write methods will only allow - * events to pass, whose channel bit is 1. + /** Set the channel filtering mode. + * @param mask If mode is FilterChannels, each bit represents a midi channel: + * bit 0 = channel 0, bit 1 = channel 1 etc. the read and write methods will only + * process events whose channel bit is 1. + * If mode is ForceChannel, mask is simply a channel number which all events will + * be forced to while reading. */ - void set_channel_mask(uint16_t channel_mask) { g_atomic_int_set(&_channel_mask, channel_mask); } - uint16_t get_channel_mask() { return g_atomic_int_get(&_channel_mask); } + void set_channel_mode(ChannelMode mode, uint16_t mask) { + g_atomic_int_set(&_channel_mask, ((uint16_t)mode << 16) | mask); + } + + ChannelMode get_channel_mode() const { + return static_cast<ChannelMode>((g_atomic_int_get(&_channel_mask) & 0xFFFF0000) >> 16); + } - /** - * @param channel if negative, forcing channels is deactivated and filtering channels - * is activated, if positive, the LSB of channel is the channel number - * of the channel all events are forced into and filtering is deactivated - */ - void set_force_channel(int8_t channel) { g_atomic_int_set(&_force_channel, channel); } - int8_t get_force_channel() { return g_atomic_int_get(&_force_channel); } + uint16_t get_channel_mask() const { + return static_cast<ChannelMode>((g_atomic_int_get(&_channel_mask) & 0x0000FFFF)); + } protected: inline bool is_channel_event(Byte event_type_byte) { @@ -263,8 +284,7 @@ protected: } private: - volatile uint16_t _channel_mask; - volatile int8_t _force_channel; + volatile uint32_t _channel_mask; // 16 bits mode, 16 bits mask }; @@ -308,17 +328,18 @@ MidiRingBuffer::read_contents(size_t size, Byte* buf) inline size_t MidiRingBuffer::write(double time, size_t size, const Byte* buf) { - //printf("MRB - write %#X %d %d with time %lf\n", - // buf[0], buf[1], buf[2], time); + /*fprintf(stderr, "MRB %p write (t = %f) ", this, time); + for (size_t i = 0; i < size; ++i) + fprintf(stderr, "%X", (char)buf[i]); + fprintf(stderr, "\n");*/ assert(size > 0); - if(is_channel_event(buf[0]) && (g_atomic_int_get(&_force_channel) < 0)) { - // filter events for channels - Byte channel_nr = buf[0] & 0x0F; - if( !(g_atomic_int_get(&_channel_mask) & (1L << channel_nr)) ) { + // Don't write event if it doesn't match channel filter + if (is_channel_event(buf[0]) && get_channel_mode() == FilterChannels) { + Byte channel = buf[0] & 0x0F; + if ( !(get_channel_mask() & (1L << channel)) ) return 0; - } } if (write_space() < (sizeof(double) + sizeof(size_t) + size)) { @@ -326,11 +347,11 @@ MidiRingBuffer::write(double time, size_t size, const Byte* buf) } else { MidiRingBufferBase<Byte>::write(sizeof(double), (Byte*)&time); MidiRingBufferBase<Byte>::write(sizeof(size_t), (Byte*)&size); - if(is_channel_event(buf[0]) && (g_atomic_int_get(&_force_channel) >= 0)) { + if (is_channel_event(buf[0]) && get_channel_mode() == ForceChannel) { assert(size == 3); Byte tmp_buf[3]; - //force event into channel - tmp_buf[0] = (buf[0] & 0xF0) | (g_atomic_int_get(&_force_channel) & 0x0F); + // Force event to channel + tmp_buf[0] = (buf[0] & 0xF0) | (get_channel_mask() & 0x0F); tmp_buf[1] = buf[1]; tmp_buf[2] = buf[2]; MidiRingBufferBase<Byte>::write(size, tmp_buf); @@ -354,22 +375,23 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t if (read_space() == 0) return 0; - MIDI::Event ev; + double ev_time; + uint32_t ev_size; 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)) { - full_peek(sizeof(double), (Byte*)&ev.time()); + full_peek(sizeof(double), (Byte*)&ev_time); - if (ev.time() > end) + if (ev_time > end) break; - bool success = MidiRingBufferBase<Byte>::full_read(sizeof(double), (Byte*)&ev.time()); + bool success = MidiRingBufferBase<Byte>::full_read(sizeof(double), (Byte*)&ev_time); if (success) { - success = MidiRingBufferBase<Byte>::full_read(sizeof(size_t), (Byte*)&ev.size()); + success = MidiRingBufferBase<Byte>::full_read(sizeof(size_t), (Byte*)&ev_size); } if (!success) { @@ -377,51 +399,47 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t 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; - } + Byte status; + success = full_peek(sizeof(Byte), &status); + assert(success); // If this failed, buffer is corrupt, all hope is lost - // filter events for channels - // filtering is only active, if forcing channels is not active - if(is_channel_event(first_event_byte) && (g_atomic_int_get(&_force_channel) < 0)) { - Byte channel_nr = first_event_byte & 0x0F; - if( !(g_atomic_int_get(&_channel_mask) & (1L << channel_nr)) ) { + // Ignore event if it doesn't match channel filter + if (is_channel_event(status) && get_channel_mode() == FilterChannels) { + const Byte channel = status & 0x0F; + if ( !(get_channel_mask() & (1L << channel)) ) { + skip(ev_size); // Advance read pointer to next event continue; } } - if (ev.time() >= start) { - ev.time() -= start; - // TODO: Right now there come MIDI Events with empty buffer - if(!ev.buffer()) { - std::cerr << "MidiRingBuffer::read WARNING: Skipping MIDI Event with NULL buffer pointer " - << " and length " << int(ev.size()) << std::endl; + if (ev_time >= start) { + + /*std::cerr << "MRB " << this << " - Reading event, time = " + << ev_time << " - " << start << " => " << ev_time - start + << ", size = " << ev_size << std::endl;*/ + + ev_time -= start; + + Byte* write_loc = dst.reserve(ev_time, ev_size); + if (write_loc == NULL) { + std::cerr << "MRB: Unable to reserve space in buffer, event skipped"; continue; } - Byte* write_loc = dst.reserve(ev.time(), ev.size()); - - success = MidiRingBufferBase<Byte>::full_read(ev.size(), write_loc); + success = MidiRingBufferBase<Byte>::full_read(ev_size, write_loc); if (success) { - if(is_channel_event(first_event_byte) && (g_atomic_int_get(&_force_channel) >= 0)) { - write_loc[0] = (write_loc[0] & 0xF0) | (g_atomic_int_get(&_force_channel) & 0x0F); + if (is_channel_event(status) && get_channel_mode() == ForceChannel) { + write_loc[0] = (write_loc[0] & 0xF0) | (get_channel_mask() & 0x0F); } ++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; } } else { - printf("MRB - SKIPPING EVENT AT TIME %f\n", ev.time()); + printf("MRB (start %u) - Skipping event at (too early) time %f\n", start, ev_time); } } diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index 9195b1075c..55655e9e26 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -135,6 +135,12 @@ namespace ARDOUR { Sustained, Percussive }; + + enum ChannelMode { + AllChannels = 0, ///< Pass through all channel information unmodified + FilterChannels, ///< Ignore events on certain channels + ForceChannel ///< Force all events to a certain channel + }; enum EventTimeUnit { Frames, diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc index d64d3a2f99..71b699396b 100644 --- a/libs/ardour/enums.cc +++ b/libs/ardour/enums.cc @@ -46,6 +46,7 @@ setup_enum_writer () MeterPoint _MeterPoint; TrackMode _TrackMode; NoteMode _NoteMode; + ChannelMode _ChannelMode; MeterFalloff _MeterFalloff; MeterHold _MeterHold; EditMode _EditMode; @@ -140,6 +141,11 @@ setup_enum_writer () REGISTER_ENUM (Sustained); REGISTER_ENUM (Percussive); REGISTER (_NoteMode); + + REGISTER_ENUM (AllChannels); + REGISTER_ENUM (FilterChannels); + REGISTER_ENUM (ForceChannel); + REGISTER (_ChannelMode); REGISTER_ENUM (MeterFalloffOff); REGISTER_ENUM (MeterFalloffSlowest); diff --git a/libs/ardour/midi_buffer.cc b/libs/ardour/midi_buffer.cc index 042f9529ad..4628de4a6a 100644 --- a/libs/ardour/midi_buffer.cc +++ b/libs/ardour/midi_buffer.cc @@ -195,7 +195,10 @@ MidiBuffer::push_back(const jack_midi_event_t& ev) Byte* MidiBuffer::reserve(double time, size_t size) { - assert(size <= MAX_EVENT_SIZE); + if (size > MAX_EVENT_SIZE) { + cerr << "WARNING: Failed to reserve " << size << " bytes for event"; + return 0; + } if (_size == _capacity) return 0; diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc index 6efa1abbae..acc8f8117a 100644 --- a/libs/ardour/midi_diskstream.cc +++ b/libs/ardour/midi_diskstream.cc @@ -1227,11 +1227,10 @@ MidiDiskstream::get_state () snprintf (buf, sizeof(buf), "0x%x", _flags); node->add_property ("flags", buf); + node->add_property("channel-mode", enum_2_string(get_channel_mode())); + snprintf (buf, sizeof(buf), "0x%x", get_channel_mask()); - node->add_property("channel_mask", buf); - - snprintf (buf, sizeof(buf), "%d", get_force_channel()); - node->add_property("force_channel", buf); + node->add_property("channel-mask", buf); node->add_property ("playlist", _playlist->name()); @@ -1310,19 +1309,21 @@ MidiDiskstream::set_state (const XMLNode& node) if ((prop = node.property ("flags")) != 0) { _flags = Flag (string_2_enum (prop->value(), _flags)); } - - if ((prop = node.property ("channel_mask")) != 0) { - unsigned int channel_mask; - sscanf (prop->value().c_str(), "0x%x", &channel_mask); - set_channel_mask(channel_mask); + + ChannelMode channel_mode = AllChannels; + if ((prop = node.property ("channel-mode")) != 0) { + channel_mode = ChannelMode (string_2_enum(prop->value(), channel_mode)); } - if ((prop = node.property ("force_channel")) != 0) { - int force_channel; - sscanf (prop->value().c_str(), "%d", &force_channel); - set_force_channel(force_channel); + unsigned int channel_mask = 0xFFFF; + if ((prop = node.property ("channel-mask")) != 0) { + sscanf (prop->value().c_str(), "0x%x", &channel_mask); + if (channel_mask & 0xFFFF) + warning << _("MidiDiskstream: XML property channel-mask out of range") << endmsg; } + set_channel_mode(channel_mode, channel_mask); + if ((prop = node.property ("channels")) != 0) { nchans = atoi (prop->value().c_str()); } diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc index 01f0ecc436..2b8755b0f9 100644 --- a/libs/ardour/midi_model.cc +++ b/libs/ardour/midi_model.cc @@ -491,9 +491,6 @@ void MidiModel::append(const MIDI::Event& ev) write_lock(); _edited = true; - cerr << "MidiModel append event type: " - << hex << "0x" << (int)ev.type() << endl; - assert(_notes.empty() || ev.time() >= _notes.back()->time()); assert(_writing); diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index ab13ad410c..d22c2171e7 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -428,9 +428,6 @@ MidiTrack::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_fram passthru (start_frame, end_frame, nframes, offset, 0, (_meter_point == MeterInput)); } - // stop all sounds - midi_panic(); - return 0; } @@ -571,10 +568,8 @@ MidiTrack::process_output_buffers (BufferSet& bufs, IO::silence(nframes, offset); } else { - MidiBuffer& output_buf = bufs.get_midi(0); - // TODO this crashes: (sends events with NULL buffer pointer) - // Is this necessary anyway here? Dont know. - //write_controller_messages(output_buf, start_frame, end_frame, nframes, offset); + // Write 'automation' controllers (e.g. CC events from a UI slider) + write_controller_messages(bufs.get_midi(0), start_frame, end_frame, nframes, offset); deliver_output(bufs, start_frame, end_frame, nframes, offset); } @@ -706,13 +701,13 @@ MidiTrack::set_note_mode (NoteMode m) void MidiTrack::midi_panic() { - for(uint8_t channel = 0; channel <= 0xF; channel++) { + for (uint8_t channel = 0; channel <= 0xF; channel++) { Byte ev[3] = { MIDI_CMD_CONTROL | channel, MIDI_CTL_SUSTAIN, 0 }; - write_immediate_event(3, ev); + write_immediate_event(3, ev); ev[1] = MIDI_CTL_ALL_NOTES_OFF; - write_immediate_event(3, ev); + write_immediate_event(3, ev); ev[1] = MIDI_CTL_RESET_CONTROLLERS; - write_immediate_event(3, ev); + write_immediate_event(3, ev); } } @@ -721,6 +716,11 @@ MidiTrack::midi_panic() bool MidiTrack::write_immediate_event(size_t size, const Byte* buf) { + printf("Write immediate event: "); + for (size_t i=0; i < size; ++i) { + printf("%X ", buf[i]); + } + printf("\n"); return (_immediate_events.write(0, size, buf) == size); } diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index 4ab7a9b973..389224eb3b 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -361,11 +361,11 @@ SMFSource::read_event(uint32_t* delta_t, uint32_t* size, Byte** buf) const if (event_size > 1) fread((*buf) + 1, 1, *size - 1, _fd); - printf("SMFSource %s read event: delta = %u, size = %u, data = ", _name.c_str(), *delta_t, *size); + /*printf("SMFSource %s read event: delta = %u, size = %u, data = ", _name.c_str(), *delta_t, *size); for (size_t i=0; i < *size; ++i) { printf("%X ", (*buf)[i]); } - printf("\n"); + printf("\n");*/ return (int)*size; } @@ -374,7 +374,7 @@ SMFSource::read_event(uint32_t* delta_t, uint32_t* size, Byte** buf) const nframes_t SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const { - cerr << "SMF read_unlocked " << name() << " read " << start << ", count=" << cnt << ", offset=" << stamp_offset << endl; + //cerr << "SMF read_unlocked " << name() << " read " << start << ", count=" << cnt << ", offset=" << stamp_offset << endl; // 64 bits ought to be enough for anybody uint64_t time = 0; // in SMF ticks, 1 tick per _ppqn diff --git a/libs/midi++2/jack_midiport.cc b/libs/midi++2/jack_midiport.cc index 311bbb98f6..0b49517212 100644 --- a/libs/midi++2/jack_midiport.cc +++ b/libs/midi++2/jack_midiport.cc @@ -95,24 +95,27 @@ JACK_MidiPort::write(byte * msg, size_t msglen, timestamp_t timestamp) } else { - assert(_currently_in_cycle); assert(_jack_output_port); assert(timestamp < _nframes_this_cycle); - if (timestamp == 0) { - timestamp = _last_write_timestamp; - } - - if (jack_midi_event_write (jack_port_get_buffer (_jack_output_port, _nframes_this_cycle), - timestamp, msg, msglen) == 0) { - ret = msglen; - _last_write_timestamp = timestamp; - + if (_currently_in_cycle) { + if (timestamp == 0) { + timestamp = _last_write_timestamp; + } + + if (jack_midi_event_write (jack_port_get_buffer (_jack_output_port, _nframes_this_cycle), + timestamp, msg, msglen) == 0) { + ret = msglen; + _last_write_timestamp = timestamp; + + } else { + ret = 0; + cerr << "write of " << msglen << " failed, port holds " + << jack_midi_get_event_count (jack_port_get_buffer (_jack_output_port, _nframes_this_cycle)) + << endl; + } } else { - ret = 0; - cerr << "write of " << msglen << " failed, port holds " - << jack_midi_get_event_count (jack_port_get_buffer (_jack_output_port, _nframes_this_cycle)) - << endl; + cerr << "write to JACK midi port failed: not currently in a process cycle." << endl; } } |