13
0

get standalone MidiView to display notes

This also removes an unused TriggerBoxWidget from each regular
MixerStrip.
This commit is contained in:
Paul Davis 2024-01-11 18:00:07 -07:00
parent a8895e50c7
commit 182a24751b
18 changed files with 91 additions and 87 deletions

View File

@ -146,6 +146,8 @@ public:
virtual void set_selected_midi_region_view (MidiRegionView&);
samplecnt_t get_current_zoom () const { return samples_per_pixel; }
/* NOTE: these functions assume that the "pixel" coordinate is
in canvas coordinates. These coordinates already take into
account any scrolling offsets.
@ -244,7 +246,6 @@ public:
virtual void set_zoom_focus (Editing::ZoomFocus) = 0;
virtual Editing::ZoomFocus get_zoom_focus () const = 0;
virtual samplecnt_t get_current_zoom () const = 0;
virtual void reset_zoom (samplecnt_t) = 0;
virtual void reposition_and_zoom (samplepos_t, double) = 0;

View File

@ -281,7 +281,6 @@ public:
void set_zoom_focus (Editing::ZoomFocus);
Editing::ZoomFocus get_zoom_focus () const { return zoom_focus; }
samplecnt_t get_current_zoom () const { return samples_per_pixel; }
void cycle_zoom_focus ();
void temporal_zoom_step (bool zoom_out);
void temporal_zoom_step_scale (bool zoom_out, double scale);

View File

@ -452,8 +452,8 @@ MidiGhostRegion::model_changed ()
std::shared_ptr<NoteType> note = i->first;
GhostEvent* cne = i->second;
const bool visible = (note->note() >= parent_mrv._current_range_min) &&
(note->note() <= parent_mrv._current_range_max);
const bool visible = (note->note() >= parent_mrv.midi_context().lowest_note()) &&
(note->note() <= parent_mrv.midi_context().highest_note());
if (visible) {
if (cne->is_hit) {

View File

@ -50,6 +50,12 @@ CueMidiBackground::contents_height() const
return _height;
}
double
CueMidiBackground::height() const
{
return _height;
}
uint8_t
CueMidiBackground::get_preferred_midi_channel () const
{

View File

@ -37,6 +37,7 @@ class CueMidiBackground : public MidiViewBackground
CueMidiBackground (ArdourCanvas::Item* parent);
~CueMidiBackground ();
double height() const;
double contents_height() const;
uint8_t get_preferred_midi_channel () const;

View File

@ -96,13 +96,7 @@ MidiCueEditor::build_canvas ()
rubberband_rect = new ArdourCanvas::Rectangle (hv_scroll_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0));
rubberband_rect->hide();
ArdourCanvas::Text* hw = new ArdourCanvas::Text (hv_scroll_group);
hw->set ("hello, world");
hw->set_fill_color (Gtkmm2ext::Color (0xff0000ff));
std::cerr << "New CMB\n";
bg = new CueMidiBackground (hv_scroll_group);
_canvas_viewport->signal_size_allocate().connect (sigc::mem_fun(*this, &MidiCueEditor::canvas_allocate));
}
@ -119,7 +113,6 @@ MidiCueEditor::snap_to_grid (timepos_t const & presnap, Temporal::RoundMode dire
return snap_to_bbt (presnap, direction, gpref);
}
void
MidiCueEditor::snap_to_internal (timepos_t& start, Temporal::RoundMode direction, SnapPref pref, bool ensure_snap) const
{
@ -198,7 +191,7 @@ MidiCueEditor::viewport()
}
void
MidiCueEditor::set_region (std::shared_ptr<ARDOUR::MidiTrack> t, std::shared_ptr<ARDOUR::Region> r)
MidiCueEditor::set_region (std::shared_ptr<ARDOUR::MidiTrack> t, std::shared_ptr<ARDOUR::MidiRegion> r)
{
// delete view;
// view = nullptr;
@ -207,5 +200,6 @@ MidiCueEditor::set_region (std::shared_ptr<ARDOUR::MidiTrack> t, std::shared_ptr
return;
}
// view = new MidiView (t, hv_scroll_group, *this, *bg, 0xff0000ff);
view = new MidiView (t, *hv_scroll_group, *this, *bg, 0xff0000ff);
view->set_region (r);
}

View File

@ -62,7 +62,7 @@ class MidiCueEditor : public CueEditor
void apply_midi_note_edit_op (ARDOUR::MidiOperator& op, const RegionSelection& rs);
PBD::Command* apply_midi_note_edit_op_to_region (ARDOUR::MidiOperator& op, MidiRegionView& mrv);
void set_region (std::shared_ptr<ARDOUR::MidiTrack>, std::shared_ptr<ARDOUR::Region>);
void set_region (std::shared_ptr<ARDOUR::MidiTrack>, std::shared_ptr<ARDOUR::MidiRegion>);
protected:
Temporal::timepos_t snap_to_grid (Temporal::timepos_t const & start,

View File

@ -207,7 +207,6 @@ MidiStreamView::display_track (std::shared_ptr<Track> tr)
{
StreamView::display_track (tr);
std::cerr << "MSV @ " << this << " dnl\n";
draw_note_lines();
NoteRangeChanged(); /* EMIT SIGNAL*/

View File

@ -120,8 +120,6 @@ MidiView::MidiView (std::shared_ptr<MidiTrack> mt,
, _step_edit_cursor (0)
, _step_edit_cursor_width (1, 0)
, _channel_selection_scoped_note (0)
, _current_range_min(0)
, _current_range_max(0)
, _mouse_state(None)
, _pressed_button(0)
, _optimization_iterator (_events.end())
@ -153,8 +151,6 @@ MidiView::MidiView (MidiView const & other)
, _step_edit_cursor (0)
, _step_edit_cursor_width (1, 0)
, _channel_selection_scoped_note (0)
, _current_range_min(0)
, _current_range_max(0)
, _mouse_state(None)
, _pressed_button(0)
, _optimization_iterator (_events.end())
@ -233,6 +229,8 @@ MidiView::set_model (std::shared_ptr<MidiModel> m)
_editing_context.MouseModeChanged.connect (connections_requiring_model, invalidator (*this),
boost::bind (&MidiView::mouse_mode_changed, this),
gui_context ());
model_changed ();
}
bool
@ -1005,6 +1003,8 @@ MidiView::redisplay (bool view_only)
void
MidiView::model_changed()
{
std::cerr << "MC!\n";
if (!display_is_enabled()) {
return;
}
@ -1045,6 +1045,22 @@ MidiView::model_changed()
NoteBase* cne;
std::cerr << "drawing " << notes.size() << " notes\n";
uint8_t low_note = std::numeric_limits<uint8_t>::max();
uint8_t hi_note = std::numeric_limits<uint8_t>::min();
for (MidiModel::Notes::iterator n = notes.begin(); n != notes.end(); ++n) {
if ((*n)->note() < low_note) {
low_note = (*n)->note();
}
if ((*n)->note() > hi_note) {
hi_note = (*n)->note();
}
}
_midi_context.apply_note_range (low_note, hi_note, true);
for (MidiModel::Notes::iterator n = notes.begin(); n != notes.end(); ++n) {
std::shared_ptr<NoteType> note (*n);
@ -1445,13 +1461,10 @@ MidiView::set_height (double ht)
void
MidiView::apply_note_range (uint8_t min, uint8_t max, bool force)
{
if (!force && _current_range_min == min && _current_range_max == max) {
if (!force && _midi_context.lowest_note() == min && _midi_context.highest_note() == max) {
return;
}
_current_range_min = min;
_current_range_max = max;
view_changed ();
}
@ -1548,7 +1561,7 @@ MidiView::note_in_region_range (const std::shared_ptr<NoteType> note, bool& visi
const bool outside = !note_in_region_time_range (note);
visible = (note->note() >= _current_range_min) && (note->note() <= _current_range_max);
visible = (note->note() >= _midi_context.lowest_note()) && (note->note() <= _midi_context.highest_note());
return !outside;
}
@ -1600,6 +1613,11 @@ MidiView::update_sustained (Note* ev, bool update_ghost_regions)
const double y0 = 1 + floor(note_to_y(note->note()));
double y1;
std::cerr << "Note: " << *note << std::endl;
std::cerr << "SSS " << session_source_start << std::endl;
std::cerr << "nh " << note_height() << std::endl;
std::cerr << "vs. " << (int) _midi_context.lowest_note() << " .. " << (int) _midi_context.highest_note() << std::endl;
if (note->length() == Temporal::Beats()) {
/* special case actual zero-length notes */
@ -1618,6 +1636,8 @@ MidiView::update_sustained (Note* ev, bool update_ghost_regions)
const samplepos_t note_end_samples = _midi_region->position().distance ((session_source_start + note_end)).samples();
std::cerr << "nes: " << note_end_samples << " Z " << _editing_context.get_current_zoom() << std::endl;
x1 = std::max(1., _editing_context.sample_to_pixel (note_end_samples));
} else {
@ -1629,6 +1649,7 @@ MidiView::update_sustained (Note* ev, bool update_ghost_regions)
y1 = y0 + std::max(1., floor(note_height()) - 1);
std::cerr << "note rect " << ArdourCanvas::Rect (x0, y0, x1, y1) << std::endl;
ev->set (ArdourCanvas::Rect (x0, y0, x1, y1));
ev->set_velocity (note->velocity()/127.0);
@ -4174,10 +4195,10 @@ MidiView::data_recorded (std::weak_ptr<MidiSource> w)
nb->item()->set_outline_color (UIConfiguration::instance().color ("recording note"));
/* fix up our note range */
if (ev.note() < _current_range_min) {
apply_note_range (ev.note(), _current_range_max, true);
} else if (ev.note() > _current_range_max) {
apply_note_range (_current_range_min, ev.note(), true);
if (ev.note() < _midi_context.lowest_note()) {
apply_note_range (ev.note(), _midi_context.highest_note(), true);
} else if (ev.note() > _midi_context.highest_note()) {
apply_note_range (_midi_context.lowest_note(), ev.note(), true);
}
} else if (ev.type() == MIDI_CMD_NOTE_OFF) {
@ -4415,28 +4436,6 @@ MidiView::get_draw_length_beats (timepos_t const & pos) const
return beats;
}
uint8_t
MidiView::y_to_note (double y) const
{
int const n = ((contents_height() - y) / contents_height() * (double)(_current_range_max - _current_range_min + 1))
+ _current_range_min;
if (n < 0) {
return 0;
} else if (n > 127) {
return 127;
}
/* min due to rounding and/or off-by-one errors */
return min ((uint8_t) n, _current_range_max);
}
double
MidiView::note_to_y(uint8_t note) const
{
return contents_height() - (note + 1 - _current_range_min) * note_height() + 1;
}
void
MidiView::quantize_selected_notes ()
{
@ -4677,3 +4676,9 @@ MidiView::drag_group () const
{
return _note_group->parent();
}
double
MidiView::height() const
{
return _midi_context.height();
}

View File

@ -483,9 +483,6 @@ class MidiView : public virtual sigc::trackable
Temporal::Beats _step_edit_cursor_position;
NoteBase* _channel_selection_scoped_note;
uint8_t _current_range_min;
uint8_t _current_range_max;
MouseState _mouse_state;
int _pressed_button;
@ -577,14 +574,13 @@ class MidiView : public virtual sigc::trackable
ARDOUR::ChannelMode get_channel_mode() const;
uint16_t get_selected_channels () const;
virtual double height() const = 0;
virtual double height() const;
virtual double contents_height() const { return height() - 2; }
inline double contents_note_range () const { return (double)(_current_range_max - _current_range_min + 1); }
inline double note_height() const { return contents_height() / contents_note_range(); }
inline double note_height() const { return contents_height() / _midi_context.contents_note_range(); }
double note_to_y (uint8_t note) const;
uint8_t y_to_note (double y) const;
double note_to_y (uint8_t note) const { return _midi_context.note_to_y (note); }
uint8_t y_to_note (double y) const { return _midi_context.y_to_note (y); }
void update_patch_changes ();
void update_sysexes ();

View File

@ -115,7 +115,6 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session* sess, bool in_mixer)
, processor_box (sess, boost::bind (&MixerStrip::plugin_selector, this), mx.selection(), this, in_mixer)
, gpm (sess, 250)
, panners (sess)
, trigger_display (-1., TriggerBox::default_triggers_per_box*16.)
, button_size_group (Gtk::SizeGroup::create (Gtk::SIZE_GROUP_HORIZONTAL))
, rec_mon_table (2, 2)
, solo_iso_table (1, 2)
@ -153,7 +152,6 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session* sess, std::shared_ptr<Route> rt,
, processor_box (sess, boost::bind (&MixerStrip::plugin_selector, this), mx.selection(), this, in_mixer)
, gpm (sess, 250)
, panners (sess)
, trigger_display (-1., 8*16.)
, button_size_group (Gtk::SizeGroup::create (Gtk::SIZE_GROUP_HORIZONTAL))
, rec_mon_table (2, 2)
, solo_iso_table (1, 2)
@ -335,7 +333,6 @@ MixerStrip::init ()
global_vpacker.pack_start (name_button, Gtk::PACK_SHRINK);
global_vpacker.pack_start (input_button_box, Gtk::PACK_SHRINK);
global_vpacker.pack_start (invert_button_box, Gtk::PACK_SHRINK);
global_vpacker.pack_start (trigger_display, Gtk::PACK_SHRINK);
global_vpacker.pack_start (_tmaster_widget, Gtk::PACK_SHRINK);
global_vpacker.pack_start (processor_box, true, true);
global_vpacker.pack_start (panners, Gtk::PACK_SHRINK);
@ -425,7 +422,6 @@ MixerStrip::init ()
_visibility.add (&output_button, X_("Output"), _("Output"), false);
_visibility.add (&_comment_button, X_("Comments"), _("Comments"), false);
_visibility.add (&control_slave_ui, X_("VCA"), _("VCA Assigns"), false);
_visibility.add (&trigger_display, X_("TriggerGrid"), _("Trigger Grid"), false);
_visibility.add (&_tmaster_widget, X_("TriggerMaster"), _("Trigger Master"), false);
parameter_changed (X_("mixer-element-visibility"));
@ -542,8 +538,6 @@ MixerStrip::set_route (std::shared_ptr<Route> rt)
RouteUI::set_route (rt);
set_trigger_display (rt->triggerbox());
control_slave_ui.set_stripable (std::dynamic_pointer_cast<Stripable> (rt));
/* ProcessorBox needs access to _route so that it can read
@ -1683,8 +1677,6 @@ MixerStrip::revert_to_default_display ()
}
reset_strip_style ();
set_trigger_display (_route->triggerbox());
}
void
@ -2140,9 +2132,3 @@ MixerStrip::hide_master_spacer (bool yn)
}
}
void
MixerStrip::set_trigger_display (std::shared_ptr<TriggerBox> tb)
{
_tmaster->set_triggerbox (tb);
trigger_display.set_triggerbox (tb.get());
}

View File

@ -192,7 +192,6 @@ private:
ProcessorBox processor_box;
GainMeter gpm;
PannerUI panners;
TriggerBoxWidget trigger_display;
Glib::RefPtr<Gtk::SizeGroup> button_size_group;

View File

@ -756,7 +756,6 @@ SlotPropertyWindow::SlotPropertyWindow (TriggerReference tref)
_trig_box->set_trigger (tref);
_midi_editor = new MidiCueEditor;
_midi_editor->set_region (std::shared_ptr<MidiTrack>(), trigger->region());
table->attach(*_trig_box, col, col+1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); col++;
table->attach(_midi_editor->viewport(), col, col+1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); col++;

View File

@ -39,6 +39,7 @@
#include "ardour/region_factory.h"
#include "ardour/profile.h"
#include "ardour/smf_source.h"
#include "ardour/stripable.h"
#include "actions.h"
#include "ardour_ui.h"
@ -410,10 +411,14 @@ TriggerPage::selection_changed ()
_midi_trig_box.set_trigger (ref);
_midi_trig_box.show ();
// _midi_trim_box.set_trigger (ref);
std::shared_ptr<MidiRegion> mr = std::dynamic_pointer_cast<MidiRegion> (trigger->region());
if (mr) {
std::shared_ptr<MidiTrack> mt = std::dynamic_pointer_cast<MidiTrack> (entry->strip().stripable());
_midi_editor->set_region (mt, mr);
_midi_editor->viewport().show ();
}
}
}
_parameter_box.show ();
}
}

View File

@ -65,7 +65,7 @@ TriggerStrip::TriggerStrip (Session* s, std::shared_ptr<ARDOUR::Route> rt)
, _pb_selection ()
, _tmaster_widget (-1, 16)
, _processor_box (s, boost::bind (&TriggerStrip::plugin_selector, this), _pb_selection, 0)
, _trigger_display (-1., TriggerBox::default_triggers_per_box * 16.)
, _trigger_display (*this, -1., TriggerBox::default_triggers_per_box * 16.)
, _panners (s)
, _level_meter (s)
{

View File

@ -65,8 +65,9 @@ using namespace ArdourCanvas;
using namespace Gtkmm2ext;
using namespace PBD;
TriggerEntry::TriggerEntry (Item* item, TriggerReference tr)
TriggerEntry::TriggerEntry (Item* item, TriggerStrip& s, TriggerReference tr)
: ArdourCanvas::Rectangle (item)
, _strip (s)
, _grabbed (false)
, _drag_active (false)
{
@ -826,9 +827,10 @@ TriggerEntry::drag_data_get (Glib::RefPtr<Gdk::DragContext> const&, Gtk::Selecti
Glib::RefPtr<Gtk::TargetList> TriggerBoxUI::_dnd_src;
TriggerBoxUI::TriggerBoxUI (ArdourCanvas::Item* parent, TriggerBox& tb)
TriggerBoxUI::TriggerBoxUI (ArdourCanvas::Item* parent, TriggerStrip& s, TriggerBox& tb)
: Rectangle (parent)
, _triggerbox (tb)
, _strip (s)
{
set_layout_sensitive (true); // why???
@ -894,7 +896,7 @@ TriggerBoxUI::build ()
if (!t) {
break;
}
TriggerEntry* te = new TriggerEntry (this, TriggerReference (_triggerbox, n));
TriggerEntry* te = new TriggerEntry (this, _strip, TriggerReference (_triggerbox, n));
_slots.push_back (te);
@ -1031,9 +1033,10 @@ TriggerBoxUI::drag_data_received (Glib::RefPtr<Gdk::DragContext> const& context,
/* ********************************************** */
TriggerBoxWidget::TriggerBoxWidget (float w, float h)
TriggerBoxWidget::TriggerBoxWidget (TriggerStrip& s, float w, float h)
: FittedCanvasWidget (w, h)
, ui (0)
, ui (nullptr)
, _strip (s)
{
set_background_color (UIConfiguration::instance ().color (X_("theme:bg")));
}
@ -1044,13 +1047,13 @@ TriggerBoxWidget::set_triggerbox (TriggerBox* tb)
if (ui) {
root ()->remove (ui);
delete ui;
ui = 0;
ui = nullptr;
}
if (!tb) {
return;
}
ui = new TriggerBoxUI (root (), *tb);
ui = new TriggerBoxUI (root (), _strip, *tb);
repeat_size_allocation ();
}

View File

@ -43,10 +43,12 @@ namespace ArdourCanvas
class Polygon;
}
class TriggerStrip;
class TriggerEntry : public ArdourCanvas::Rectangle, public TriggerUI
{
public:
TriggerEntry (ArdourCanvas::Item* item, ARDOUR::TriggerReference rf);
TriggerEntry (ArdourCanvas::Item* item, TriggerStrip&, ARDOUR::TriggerReference rf);
~TriggerEntry ();
ArdourCanvas::Rectangle* play_button;
@ -76,7 +78,10 @@ public:
bool name_button_event (GdkEvent*);
TriggerStrip& strip() const { return _strip; }
private:
TriggerStrip& _strip;
bool _grabbed;
double _poly_size;
double _poly_margin;
@ -104,11 +109,13 @@ private:
class TriggerBoxUI : public ArdourCanvas::Rectangle
{
public:
TriggerBoxUI (ArdourCanvas::Item* parent, ARDOUR::TriggerBox&);
TriggerBoxUI (ArdourCanvas::Item* parent, TriggerStrip&, ARDOUR::TriggerBox&);
~TriggerBoxUI ();
void _size_allocate (ArdourCanvas::Rect const&);
TriggerStrip& strip() const { return _strip; }
static Glib::RefPtr<Gtk::TargetList> dnd_src ()
{
return _dnd_src;
@ -119,6 +126,7 @@ private:
ARDOUR::TriggerBox& _triggerbox;
Slots _slots;
TriggerStrip& _strip;
static Glib::RefPtr<Gtk::TargetList> _dnd_src;
@ -140,12 +148,14 @@ private:
class TriggerBoxWidget : public FittedCanvasWidget
{
public:
TriggerBoxWidget (float w, float h);
TriggerBoxWidget (TriggerStrip&, float w, float h);
void set_triggerbox (ARDOUR::TriggerBox* tb);
TriggerStrip& strip() const { return _strip; }
private:
TriggerBoxUI* ui;
TriggerStrip& _strip;
};
#endif

View File

@ -40,6 +40,7 @@ class ViewBackground
ViewBackground ();
virtual ~ViewBackground ();
virtual double height() const { return 0.; }
virtual double contents_height() const { return 0.; }
/** @return y position, or -1 if hidden */