mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 15:25:01 +01:00
This new inheritance heirarchy lets us share (a very small piece of) code between streamviews in the Editor and the nascent piano roll object on the cue page.
204 lines
6.3 KiB
C++
204 lines
6.3 KiB
C++
/*
|
|
* Copyright (C) 2023 Paul Davis <paul@linuxaudiosystems.com>
|
|
*
|
|
* 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.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include "canvas/canvas.h"
|
|
#include "canvas/container.h"
|
|
#include "canvas/debug.h"
|
|
#include "canvas/scroll_group.h"
|
|
#include "canvas/rectangle.h"
|
|
|
|
#include "midi_cue_background.h"
|
|
#include "midi_cue_editor.h"
|
|
#include "midi_view.h"
|
|
#include "ui_config.h"
|
|
#include "verbose_cursor.h"
|
|
|
|
using namespace ARDOUR;
|
|
using namespace ArdourCanvas;
|
|
using namespace Temporal;
|
|
|
|
MidiCueEditor::MidiCueEditor()
|
|
: vertical_adjustment (0.0, 0.0, 10.0, 400.0)
|
|
, horizontal_adjustment (0.0, 0.0, 1e16)
|
|
{
|
|
build_canvas ();
|
|
|
|
_verbose_cursor = new VerboseCursor (*this);
|
|
}
|
|
|
|
MidiCueEditor::~MidiCueEditor ()
|
|
{
|
|
}
|
|
|
|
void
|
|
MidiCueEditor::build_canvas ()
|
|
{
|
|
_canvas_viewport = new ArdourCanvas::GtkCanvasViewport (horizontal_adjustment, vertical_adjustment);
|
|
|
|
_canvas = _canvas_viewport->canvas ();
|
|
_canvas->set_background_color (0xff00000a); // UIConfiguration::instance().color ("arrange base"));
|
|
dynamic_cast<ArdourCanvas::GtkCanvas*>(_canvas)->use_nsglview (UIConfiguration::instance().get_nsgl_view_mode () == NSGLHiRes);
|
|
|
|
/* scroll group for items that should not automatically scroll
|
|
* (e.g verbose cursor). It shares the canvas coordinate space.
|
|
*/
|
|
no_scroll_group = new ArdourCanvas::Container (_canvas->root());
|
|
|
|
ArdourCanvas::ScrollGroup* hsg;
|
|
ArdourCanvas::ScrollGroup* hg;
|
|
ArdourCanvas::ScrollGroup* cg;
|
|
|
|
h_scroll_group = hg = new ArdourCanvas::ScrollGroup (_canvas->root(), ArdourCanvas::ScrollGroup::ScrollsHorizontally);
|
|
CANVAS_DEBUG_NAME (h_scroll_group, "canvas h scroll");
|
|
_canvas->add_scroller (*hg);
|
|
|
|
hv_scroll_group = hsg = new ArdourCanvas::ScrollGroup (_canvas->root(),
|
|
ArdourCanvas::ScrollGroup::ScrollSensitivity (ArdourCanvas::ScrollGroup::ScrollsVertically|
|
|
ArdourCanvas::ScrollGroup::ScrollsHorizontally));
|
|
CANVAS_DEBUG_NAME (hv_scroll_group, "canvas hv scroll");
|
|
_canvas->add_scroller (*hsg);
|
|
|
|
cursor_scroll_group = cg = new ArdourCanvas::ScrollGroup (_canvas->root(), ArdourCanvas::ScrollGroup::ScrollsHorizontally);
|
|
CANVAS_DEBUG_NAME (cursor_scroll_group, "canvas cursor scroll");
|
|
_canvas->add_scroller (*cg);
|
|
|
|
/*a group to hold global rects like punch/loop indicators */
|
|
global_rect_group = new ArdourCanvas::Container (hv_scroll_group);
|
|
CANVAS_DEBUG_NAME (global_rect_group, "global rect group");
|
|
|
|
transport_loop_range_rect = new ArdourCanvas::Rectangle (global_rect_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, ArdourCanvas::COORD_MAX));
|
|
CANVAS_DEBUG_NAME (transport_loop_range_rect, "loop rect");
|
|
transport_loop_range_rect->hide();
|
|
|
|
/*a group to hold time (measure) lines */
|
|
time_line_group = new ArdourCanvas::Container (h_scroll_group);
|
|
CANVAS_DEBUG_NAME (time_line_group, "time line group");
|
|
|
|
_trackview_group = new ArdourCanvas::Container (hv_scroll_group);
|
|
CANVAS_DEBUG_NAME (_trackview_group, "Canvas TrackViews");
|
|
|
|
// used as rubberband rect
|
|
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);
|
|
}
|
|
|
|
|
|
timepos_t
|
|
MidiCueEditor::snap_to_grid (timepos_t const & presnap, Temporal::RoundMode direction, SnapPref gpref) const
|
|
{
|
|
/* BBT time only */
|
|
return snap_to_bbt (presnap, direction, gpref);
|
|
}
|
|
|
|
|
|
void
|
|
MidiCueEditor::snap_to_internal (timepos_t& start, Temporal::RoundMode direction, SnapPref pref, bool ensure_snap) const
|
|
{
|
|
UIConfiguration const& uic (UIConfiguration::instance ());
|
|
const timepos_t presnap = start;
|
|
|
|
|
|
timepos_t dist = timepos_t::max (start.time_domain()); // this records the distance of the best snap result we've found so far
|
|
timepos_t best = timepos_t::max (start.time_domain()); // this records the best snap-result we've found so far
|
|
|
|
timepos_t pre (presnap);
|
|
timepos_t post (snap_to_grid (pre, direction, pref));
|
|
|
|
check_best_snap (presnap, post, dist, best);
|
|
|
|
if (timepos_t::max (start.time_domain()) == best) {
|
|
return;
|
|
}
|
|
|
|
/* now check "magnetic" state: is the grid within reasonable on-screen distance to trigger a snap?
|
|
* this also helps to avoid snapping to somewhere the user can't see. (i.e.: I clicked on a region and it disappeared!!)
|
|
* ToDo: Perhaps this should only occur if EditPointMouse?
|
|
*/
|
|
samplecnt_t snap_threshold_s = pixel_to_sample (uic.get_snap_threshold ());
|
|
|
|
if (!ensure_snap && ::llabs (best.distance (presnap).samples()) > snap_threshold_s) {
|
|
return;
|
|
}
|
|
|
|
start = best;
|
|
}
|
|
|
|
samplecnt_t
|
|
MidiCueEditor::current_page_samples() const
|
|
{
|
|
return (samplecnt_t) _visible_canvas_width* samples_per_pixel;
|
|
}
|
|
|
|
void
|
|
MidiCueEditor::apply_midi_note_edit_op (ARDOUR::MidiOperator& op, const RegionSelection& rs)
|
|
{
|
|
}
|
|
|
|
PBD::Command*
|
|
MidiCueEditor::apply_midi_note_edit_op_to_region (ARDOUR::MidiOperator& op, MidiRegionView& mrv)
|
|
{
|
|
#if 0
|
|
Evoral::Sequence<Temporal::Beats>::Notes selected;
|
|
mrv.selection_as_notelist (selected, true);
|
|
|
|
if (selected.empty()) {
|
|
return 0;
|
|
}
|
|
|
|
vector<Evoral::Sequence<Temporal::Beats>::Notes> v;
|
|
v.push_back (selected);
|
|
|
|
timepos_t pos = mrv.midi_region()->source_position();
|
|
|
|
return op (mrv.midi_region()->model(), pos.beats(), v);
|
|
#endif
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
bool
|
|
MidiCueEditor::canvas_note_event (GdkEvent* event, ArdourCanvas::Item*)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Gtk::Widget&
|
|
MidiCueEditor::viewport()
|
|
{
|
|
return *_canvas_viewport;
|
|
}
|
|
|
|
void
|
|
MidiCueEditor::set_region (std::shared_ptr<ARDOUR::MidiTrack> t, std::shared_ptr<ARDOUR::Region> r)
|
|
{
|
|
// delete view;
|
|
// view = nullptr;
|
|
|
|
if (!t || !r) {
|
|
return;
|
|
}
|
|
|
|
// view = new MidiView (t, hv_scroll_group, *this, *bg, 0xff0000ff);
|
|
}
|