mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-11 17:16:38 +01:00
more movement of code and members from Editor => EditingContext
This commit is contained in:
parent
e9d63a707a
commit
4398fe931b
7 changed files with 347 additions and 399 deletions
|
|
@ -33,6 +33,8 @@ class CueEditor : public EditingContext
|
||||||
void get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const;
|
void get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const;
|
||||||
StripableTimeAxisView* get_stripable_time_axis_by_id (const PBD::ID& id) const;
|
StripableTimeAxisView* get_stripable_time_axis_by_id (const PBD::ID& id) const;
|
||||||
TrackViewList axis_views_from_routes (std::shared_ptr<ARDOUR::RouteList>) const;
|
TrackViewList axis_views_from_routes (std::shared_ptr<ARDOUR::RouteList>) const;
|
||||||
|
AxisView* axis_view_by_stripable (std::shared_ptr<ARDOUR::Stripable>) const { return nullptr; }
|
||||||
|
AxisView* axis_view_by_control (std::shared_ptr<ARDOUR::AutomationControl>) const { return nullptr; }
|
||||||
|
|
||||||
ARDOUR::Location* find_location_from_marker (ArdourMarker*, bool&) const;
|
ARDOUR::Location* find_location_from_marker (ArdourMarker*, bool&) const;
|
||||||
ArdourMarker* find_marker_from_location_id (PBD::ID const&, bool) const;
|
ArdourMarker* find_marker_from_location_id (PBD::ID const&, bool) const;
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ using namespace Glib;
|
||||||
using namespace Gtk;
|
using namespace Gtk;
|
||||||
using namespace Gtkmm2ext;
|
using namespace Gtkmm2ext;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
|
using namespace Temporal;
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
sigc::signal<void> EditingContext::DropDownKeys;
|
sigc::signal<void> EditingContext::DropDownKeys;
|
||||||
|
|
@ -90,6 +91,8 @@ EditingContext::EditingContext ()
|
||||||
, _selection_memento (new SelectionMemento())
|
, _selection_memento (new SelectionMemento())
|
||||||
, _cursors (nullptr)
|
, _cursors (nullptr)
|
||||||
, _verbose_cursor (nullptr)
|
, _verbose_cursor (nullptr)
|
||||||
|
, samples_per_pixel (2048)
|
||||||
|
, zoom_focus (ZoomFocusPlayhead)
|
||||||
{
|
{
|
||||||
grid_type_strings = I18N (_grid_type_strings);
|
grid_type_strings = I18N (_grid_type_strings);
|
||||||
|
|
||||||
|
|
@ -1172,3 +1175,283 @@ EditingContext::commit_reversible_command ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
EditingContext::time_to_pixel (timepos_t const & pos) const
|
||||||
|
{
|
||||||
|
return sample_to_pixel (pos.samples());
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
EditingContext::time_to_pixel_unrounded (timepos_t const & pos) const
|
||||||
|
{
|
||||||
|
return sample_to_pixel_unrounded (pos.samples());
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
EditingContext::duration_to_pixels (timecnt_t const & dur) const
|
||||||
|
{
|
||||||
|
return sample_to_pixel (dur.samples());
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
EditingContext::duration_to_pixels_unrounded (timecnt_t const & dur) const
|
||||||
|
{
|
||||||
|
return sample_to_pixel_unrounded (dur.samples());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Snap a position to the grid, if appropriate, taking into account current
|
||||||
|
* grid settings and also the state of any snap modifier keys that may be pressed.
|
||||||
|
* @param start Position to snap.
|
||||||
|
* @param event Event to get current key modifier information from, or 0.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
EditingContext::snap_to_with_modifier (timepos_t& start, GdkEvent const * event, Temporal::RoundMode direction, SnapPref pref, bool ensure_snap)
|
||||||
|
{
|
||||||
|
if (!_session || !event) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ArdourKeyboard::indicates_snap (event->button.state)) {
|
||||||
|
if (_snap_mode == SnapOff) {
|
||||||
|
snap_to_internal (start, direction, pref, ensure_snap);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (_snap_mode != SnapOff) {
|
||||||
|
snap_to_internal (start, direction, pref);
|
||||||
|
} else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) {
|
||||||
|
/* SnapOff, but we pressed the snap_delta modifier */
|
||||||
|
snap_to_internal (start, direction, pref, ensure_snap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EditingContext::snap_to (timepos_t& start, Temporal::RoundMode direction, SnapPref pref, bool ensure_snap)
|
||||||
|
{
|
||||||
|
if (!_session || (_snap_mode == SnapOff && !ensure_snap)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
snap_to_internal (start, direction, pref, ensure_snap);
|
||||||
|
}
|
||||||
|
|
||||||
|
timepos_t
|
||||||
|
EditingContext::snap_to_bbt (timepos_t const & presnap, Temporal::RoundMode direction, SnapPref gpref)
|
||||||
|
{
|
||||||
|
return _snap_to_bbt (presnap, direction, gpref, _grid_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
timepos_t
|
||||||
|
EditingContext::_snap_to_bbt (timepos_t const & presnap, Temporal::RoundMode direction, SnapPref gpref, GridType grid_type)
|
||||||
|
{
|
||||||
|
timepos_t ret(presnap);
|
||||||
|
TempoMap::SharedPtr tmap (TempoMap::use());
|
||||||
|
|
||||||
|
/* Snap to bar always uses bars, and ignores visual grid, so it may
|
||||||
|
* sometimes snap to bars that are not visually distinguishable.
|
||||||
|
*
|
||||||
|
* XXX this should probably work totally different: we should get the
|
||||||
|
* nearby grid and walk towards the next bar point.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (grid_type == GridTypeBar) {
|
||||||
|
TempoMetric m (tmap->metric_at (presnap));
|
||||||
|
BBT_Argument bbt (m.bbt_at (presnap));
|
||||||
|
switch (direction) {
|
||||||
|
case RoundDownAlways:
|
||||||
|
bbt = BBT_Argument (bbt.reference(), bbt.round_down_to_bar ());
|
||||||
|
break;
|
||||||
|
case RoundUpAlways:
|
||||||
|
bbt = BBT_Argument (bbt.reference(), bbt.round_up_to_bar ());
|
||||||
|
break;
|
||||||
|
case RoundNearest:
|
||||||
|
bbt = BBT_Argument (bbt.reference(), m.round_to_bar (bbt));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return timepos_t (tmap->quarters_at (bbt));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gpref != SnapToGrid_Unscaled) { // use the visual grid lines which are limited by the zoom scale that the user selected
|
||||||
|
|
||||||
|
/* Determine the most obvious divisor of a beat to use
|
||||||
|
* for the snap, based on the grid setting.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int divisor;
|
||||||
|
switch (_grid_type) {
|
||||||
|
case GridTypeBeatDiv3:
|
||||||
|
case GridTypeBeatDiv6:
|
||||||
|
case GridTypeBeatDiv12:
|
||||||
|
case GridTypeBeatDiv24:
|
||||||
|
divisor = 3;
|
||||||
|
break;
|
||||||
|
case GridTypeBeatDiv5:
|
||||||
|
case GridTypeBeatDiv10:
|
||||||
|
case GridTypeBeatDiv20:
|
||||||
|
divisor = 5;
|
||||||
|
break;
|
||||||
|
case GridTypeBeatDiv7:
|
||||||
|
case GridTypeBeatDiv14:
|
||||||
|
case GridTypeBeatDiv28:
|
||||||
|
divisor = 7;
|
||||||
|
break;
|
||||||
|
case GridTypeBeat:
|
||||||
|
divisor = 1;
|
||||||
|
break;
|
||||||
|
case GridTypeNone:
|
||||||
|
return ret;
|
||||||
|
default:
|
||||||
|
divisor = 2;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* bbt_ruler_scale reflects the level of detail we will show
|
||||||
|
* for the visual grid. Adjust the "natural" divisor to reflect
|
||||||
|
* this level of detail, and snap to that.
|
||||||
|
*
|
||||||
|
* So, for example, if the grid is Div3, we use 3 divisions per
|
||||||
|
* beat, but if the visual grid is using bbt_show_sixteenths (a
|
||||||
|
* fairly high level of detail), we will snap to (2 * 3)
|
||||||
|
* divisions per beat. Etc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
BBTRulerScale scale = bbt_ruler_scale;
|
||||||
|
switch (scale) {
|
||||||
|
case bbt_show_many:
|
||||||
|
case bbt_show_64:
|
||||||
|
case bbt_show_16:
|
||||||
|
case bbt_show_4:
|
||||||
|
case bbt_show_1:
|
||||||
|
/* Round to Bar */
|
||||||
|
ret = timepos_t (tmap->quarters_at (presnap).round_to_subdivision (-1, direction));
|
||||||
|
break;
|
||||||
|
case bbt_show_quarters:
|
||||||
|
/* Round to Beat */
|
||||||
|
ret = timepos_t (tmap->quarters_at (presnap).round_to_subdivision (1, direction));
|
||||||
|
break;
|
||||||
|
case bbt_show_eighths:
|
||||||
|
ret = timepos_t (tmap->quarters_at (presnap).round_to_subdivision (1 * divisor, direction));
|
||||||
|
break;
|
||||||
|
case bbt_show_sixteenths:
|
||||||
|
ret = timepos_t (tmap->quarters_at (presnap).round_to_subdivision (2 * divisor, direction));
|
||||||
|
break;
|
||||||
|
case bbt_show_thirtyseconds:
|
||||||
|
ret = timepos_t (tmap->quarters_at (presnap).round_to_subdivision (4 * divisor, direction));
|
||||||
|
break;
|
||||||
|
case bbt_show_sixtyfourths:
|
||||||
|
ret = timepos_t (tmap->quarters_at (presnap).round_to_subdivision (8 * divisor, direction));
|
||||||
|
break;
|
||||||
|
case bbt_show_onetwentyeighths:
|
||||||
|
ret = timepos_t (tmap->quarters_at (presnap).round_to_subdivision (16 * divisor, direction));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Just use the grid as specified, without paying attention to
|
||||||
|
* zoom level
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = timepos_t (tmap->quarters_at (presnap).round_to_subdivision (get_grid_beat_divisions(_grid_type), direction));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_best_snap (timepos_t const & presnap, timepos_t &test, timepos_t &dist, timepos_t &best)
|
||||||
|
{
|
||||||
|
timepos_t diff = timepos_t (presnap.distance (test).abs ());
|
||||||
|
if (diff < dist) {
|
||||||
|
dist = diff;
|
||||||
|
best = test;
|
||||||
|
}
|
||||||
|
|
||||||
|
test = timepos_t::max (test.time_domain()); // reset this so it doesn't get accidentally reused
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EditingContext::snap_to_internal (timepos_t& start, Temporal::RoundMode direction, SnapPref pref, bool ensure_snap)
|
||||||
|
{
|
||||||
|
UIConfiguration const& uic (UIConfiguration::instance ());
|
||||||
|
const timepos_t presnap = start;
|
||||||
|
|
||||||
|
|
||||||
|
timepos_t test = timepos_t::max (start.time_domain()); // for each snap, we'll use this value
|
||||||
|
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
|
||||||
|
|
||||||
|
/* check Grid */
|
||||||
|
if ( (_grid_type != GridTypeNone) && (uic.get_snap_target () != SnapTargetOther) ) {
|
||||||
|
timepos_t pre (presnap);
|
||||||
|
timepos_t post (snap_to_grid (pre, direction, pref));
|
||||||
|
check_best_snap (presnap, post, dist, best);
|
||||||
|
if (uic.get_snap_target () == SnapTargetGrid) {
|
||||||
|
goto check_distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check snap-to-marker */
|
||||||
|
if ((pref == SnapToAny_Visual) && uic.get_snap_to_marks ()) {
|
||||||
|
test = snap_to_marker (presnap, direction);
|
||||||
|
check_best_snap (presnap, test, dist, best);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check snap-to-playhead */
|
||||||
|
if ((pref == SnapToAny_Visual) && uic.get_snap_to_playhead () && !_session->transport_rolling ()) {
|
||||||
|
test = timepos_t (_session->audible_sample());
|
||||||
|
check_best_snap (presnap, test, dist, best);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check snap-to-region-{start/end/sync} */
|
||||||
|
if ((pref == SnapToAny_Visual) && (uic.get_snap_to_region_start () || uic.get_snap_to_region_end () || uic.get_snap_to_region_sync ())) {
|
||||||
|
|
||||||
|
if (!region_boundary_cache.empty ()) {
|
||||||
|
|
||||||
|
vector<timepos_t>::iterator prev = region_boundary_cache.begin ();
|
||||||
|
vector<timepos_t>::iterator next = std::upper_bound (region_boundary_cache.begin (), region_boundary_cache.end (), presnap);
|
||||||
|
if (next != region_boundary_cache.begin ()) {
|
||||||
|
prev = next;
|
||||||
|
prev--;
|
||||||
|
}
|
||||||
|
if (next == region_boundary_cache.end ()) {
|
||||||
|
next--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((direction == Temporal::RoundUpMaybe || direction == Temporal::RoundUpAlways)) {
|
||||||
|
test = *next;
|
||||||
|
} else if ((direction == Temporal::RoundDownMaybe || direction == Temporal::RoundDownAlways)) {
|
||||||
|
test = *prev;
|
||||||
|
} else if (direction == 0) {
|
||||||
|
if ((*prev).distance (presnap) < presnap.distance (*next)) {
|
||||||
|
test = *prev;
|
||||||
|
} else {
|
||||||
|
test = *next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
check_best_snap (presnap, test, dist, best);
|
||||||
|
}
|
||||||
|
|
||||||
|
check_distance:
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -142,14 +142,44 @@ public:
|
||||||
|
|
||||||
virtual void set_selected_midi_region_view (MidiRegionView&);
|
virtual void set_selected_midi_region_view (MidiRegionView&);
|
||||||
|
|
||||||
virtual samplepos_t pixel_to_sample_from_event (double pixel) const = 0;
|
|
||||||
virtual samplepos_t pixel_to_sample (double pixel) const = 0;
|
/* NOTE: these functions assume that the "pixel" coordinate is
|
||||||
virtual double sample_to_pixel (samplepos_t sample) const = 0;
|
in canvas coordinates. These coordinates already take into
|
||||||
virtual double sample_to_pixel_unrounded (samplepos_t sample) const = 0;
|
account any scrolling offsets.
|
||||||
virtual double time_to_pixel (Temporal::timepos_t const & pos) const = 0;
|
*/
|
||||||
virtual double time_to_pixel_unrounded (Temporal::timepos_t const & pos) const = 0;
|
|
||||||
virtual double duration_to_pixels (Temporal::timecnt_t const & pos) const = 0;
|
samplepos_t pixel_to_sample_from_event (double pixel) const {
|
||||||
virtual double duration_to_pixels_unrounded (Temporal::timecnt_t const & pos) const = 0;
|
|
||||||
|
/* pixel can be less than zero when motion events
|
||||||
|
are processed. since we've already run the world->canvas
|
||||||
|
affine, that means that the location *really* is "off
|
||||||
|
to the right" and thus really is "before the start".
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (pixel >= 0) {
|
||||||
|
return pixel * samples_per_pixel;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
samplepos_t pixel_to_sample (double pixel) const {
|
||||||
|
return pixel * samples_per_pixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
double sample_to_pixel (samplepos_t sample) const {
|
||||||
|
return round (sample / (double) samples_per_pixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
double sample_to_pixel_unrounded (samplepos_t sample) const {
|
||||||
|
return sample / (double) samples_per_pixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
double time_to_pixel (Temporal::timepos_t const & pos) const;
|
||||||
|
double time_to_pixel_unrounded (Temporal::timepos_t const & pos) const;
|
||||||
|
double duration_to_pixels (Temporal::timecnt_t const & pos) const;
|
||||||
|
double duration_to_pixels_unrounded (Temporal::timecnt_t const & pos) const;
|
||||||
|
|
||||||
/** computes the timeline sample (sample) of an event whose coordinates
|
/** computes the timeline sample (sample) of an event whose coordinates
|
||||||
* are in canvas units (pixels, scroll offset included).
|
* are in canvas units (pixels, scroll offset included).
|
||||||
*/
|
*/
|
||||||
|
|
@ -190,17 +220,17 @@ public:
|
||||||
virtual void snap_to (Temporal::timepos_t & first,
|
virtual void snap_to (Temporal::timepos_t & first,
|
||||||
Temporal::RoundMode direction = Temporal::RoundNearest,
|
Temporal::RoundMode direction = Temporal::RoundNearest,
|
||||||
ARDOUR::SnapPref pref = ARDOUR::SnapToAny_Visual,
|
ARDOUR::SnapPref pref = ARDOUR::SnapToAny_Visual,
|
||||||
bool ensure_snap = false) = 0;
|
bool ensure_snap = false);
|
||||||
|
|
||||||
virtual void snap_to_with_modifier (Temporal::timepos_t & first,
|
virtual void snap_to_with_modifier (Temporal::timepos_t & first,
|
||||||
GdkEvent const* ev,
|
GdkEvent const* ev,
|
||||||
Temporal::RoundMode direction = Temporal::RoundNearest,
|
Temporal::RoundMode direction = Temporal::RoundNearest,
|
||||||
ARDOUR::SnapPref gpref = ARDOUR::SnapToAny_Visual,
|
ARDOUR::SnapPref gpref = ARDOUR::SnapToAny_Visual,
|
||||||
bool ensure_snap = false) = 0;
|
bool ensure_snap = false);
|
||||||
|
|
||||||
virtual Temporal::timepos_t snap_to_bbt (Temporal::timepos_t const & start,
|
virtual Temporal::timepos_t snap_to_bbt (Temporal::timepos_t const & start,
|
||||||
Temporal::RoundMode direction,
|
Temporal::RoundMode direction,
|
||||||
ARDOUR::SnapPref gpref) = 0;
|
ARDOUR::SnapPref gpref);
|
||||||
|
|
||||||
virtual double get_y_origin () const = 0;
|
virtual double get_y_origin () const = 0;
|
||||||
virtual void reset_x_origin (samplepos_t) = 0;
|
virtual void reset_x_origin (samplepos_t) = 0;
|
||||||
|
|
@ -342,7 +372,21 @@ public:
|
||||||
MouseCursors* _cursors;
|
MouseCursors* _cursors;
|
||||||
|
|
||||||
VerboseCursor* _verbose_cursor;
|
VerboseCursor* _verbose_cursor;
|
||||||
|
|
||||||
|
samplecnt_t samples_per_pixel;
|
||||||
|
Editing::ZoomFocus zoom_focus;
|
||||||
|
|
||||||
|
Temporal::timepos_t _snap_to_bbt (Temporal::timepos_t const & start,
|
||||||
|
Temporal::RoundMode direction,
|
||||||
|
ARDOUR::SnapPref gpref,
|
||||||
|
Editing::GridType grid_type);
|
||||||
|
|
||||||
|
void snap_to_internal (Temporal::timepos_t& first,
|
||||||
|
Temporal::RoundMode direction = Temporal::RoundNearest,
|
||||||
|
ARDOUR::SnapPref gpref = ARDOUR::SnapToAny_Visual,
|
||||||
|
bool ensure_snap = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* __ardour_midi_editing_context_h__ */
|
#endif /* __ardour_midi_editing_context_h__ */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -234,8 +234,6 @@ Editor::Editor ()
|
||||||
, constructed (false)
|
, constructed (false)
|
||||||
, _properties_box (0)
|
, _properties_box (0)
|
||||||
, no_save_visual (false)
|
, no_save_visual (false)
|
||||||
, samples_per_pixel (2048)
|
|
||||||
, zoom_focus (ZoomFocusPlayhead)
|
|
||||||
, mouse_mode (MouseObject)
|
, mouse_mode (MouseObject)
|
||||||
, marker_click_behavior (MarkerClickSelectOnly)
|
, marker_click_behavior (MarkerClickSelectOnly)
|
||||||
, _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
|
, _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
|
||||||
|
|
@ -2545,55 +2543,6 @@ Editor::set_snapped_cursor_position (timepos_t const & pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Snap a position to the grid, if appropriate, taking into account current
|
|
||||||
* grid settings and also the state of any snap modifier keys that may be pressed.
|
|
||||||
* @param start Position to snap.
|
|
||||||
* @param event Event to get current key modifier information from, or 0.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
Editor::snap_to_with_modifier (timepos_t& start, GdkEvent const * event, Temporal::RoundMode direction, SnapPref pref, bool ensure_snap)
|
|
||||||
{
|
|
||||||
if (!_session || !event) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ArdourKeyboard::indicates_snap (event->button.state)) {
|
|
||||||
if (_snap_mode == SnapOff) {
|
|
||||||
snap_to_internal (start, direction, pref, ensure_snap);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (_snap_mode != SnapOff) {
|
|
||||||
snap_to_internal (start, direction, pref);
|
|
||||||
} else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) {
|
|
||||||
/* SnapOff, but we pressed the snap_delta modifier */
|
|
||||||
snap_to_internal (start, direction, pref, ensure_snap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Editor::snap_to (timepos_t& start, Temporal::RoundMode direction, SnapPref pref, bool ensure_snap)
|
|
||||||
{
|
|
||||||
if (!_session || (_snap_mode == SnapOff && !ensure_snap)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
snap_to_internal (start, direction, pref, ensure_snap);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
check_best_snap (timepos_t const & presnap, timepos_t &test, timepos_t &dist, timepos_t &best)
|
|
||||||
{
|
|
||||||
timepos_t diff = timepos_t (presnap.distance (test).abs ());
|
|
||||||
if (diff < dist) {
|
|
||||||
dist = diff;
|
|
||||||
best = test;
|
|
||||||
}
|
|
||||||
|
|
||||||
test = timepos_t::max (test.time_domain()); // reset this so it doesn't get accidentally reused
|
|
||||||
}
|
|
||||||
|
|
||||||
timepos_t
|
timepos_t
|
||||||
Editor::snap_to_timecode (timepos_t const & presnap, Temporal::RoundMode direction, SnapPref gpref)
|
Editor::snap_to_timecode (timepos_t const & presnap, Temporal::RoundMode direction, SnapPref gpref)
|
||||||
{
|
{
|
||||||
|
|
@ -2744,117 +2693,6 @@ Editor::snap_to_cd_frames (timepos_t const & presnap, Temporal::RoundMode direct
|
||||||
return timepos_t (presnap_sample);
|
return timepos_t (presnap_sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
timepos_t
|
|
||||||
Editor::snap_to_bbt (timepos_t const & presnap, Temporal::RoundMode direction, SnapPref gpref)
|
|
||||||
{
|
|
||||||
return _snap_to_bbt (presnap, direction, gpref, _grid_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
timepos_t
|
|
||||||
Editor::_snap_to_bbt (timepos_t const & presnap, Temporal::RoundMode direction, SnapPref gpref, GridType grid_type)
|
|
||||||
{
|
|
||||||
timepos_t ret(presnap);
|
|
||||||
TempoMap::SharedPtr tmap (TempoMap::use());
|
|
||||||
|
|
||||||
/* Snap to bar always uses bars, and ignores visual grid, so it may
|
|
||||||
* sometimes snap to bars that are not visually distinguishable.
|
|
||||||
*
|
|
||||||
* XXX this should probably work totally different: we should get the
|
|
||||||
* nearby grid and walk towards the next bar point.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (grid_type == GridTypeBar) {
|
|
||||||
return timepos_t (tmap->quarters_at (presnap).round_to_subdivision (get_grid_beat_divisions(_grid_type), direction));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gpref != SnapToGrid_Unscaled) { // use the visual grid lines which are limited by the zoom scale that the user selected
|
|
||||||
|
|
||||||
/* Determine the most obvious divisor of a beat to use
|
|
||||||
* for the snap, based on the grid setting.
|
|
||||||
*/
|
|
||||||
|
|
||||||
float divisor;
|
|
||||||
switch (_grid_type) {
|
|
||||||
case GridTypeBeatDiv3:
|
|
||||||
case GridTypeBeatDiv6:
|
|
||||||
case GridTypeBeatDiv12:
|
|
||||||
case GridTypeBeatDiv24:
|
|
||||||
divisor = 3;
|
|
||||||
break;
|
|
||||||
case GridTypeBeatDiv5:
|
|
||||||
case GridTypeBeatDiv10:
|
|
||||||
case GridTypeBeatDiv20:
|
|
||||||
divisor = 2.5;
|
|
||||||
break;
|
|
||||||
case GridTypeBeatDiv7:
|
|
||||||
case GridTypeBeatDiv14:
|
|
||||||
case GridTypeBeatDiv28:
|
|
||||||
/* Septuplets suffer from drifting until libtemporal handles fractional ticks
|
|
||||||
* or if ticks_per_beat (ppqn) is raised to a point where the result
|
|
||||||
*/
|
|
||||||
divisor = 3.5;
|
|
||||||
break;
|
|
||||||
case GridTypeBeat:
|
|
||||||
divisor = 1;
|
|
||||||
break;
|
|
||||||
case GridTypeNone:
|
|
||||||
return ret;
|
|
||||||
default:
|
|
||||||
divisor = 2;
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* bbt_ruler_scale reflects the level of detail we will show
|
|
||||||
* for the visual grid. Adjust the "natural" divisor to reflect
|
|
||||||
* this level of detail, and snap to that.
|
|
||||||
*
|
|
||||||
* So, for example, if the grid is Div3, we use 3 divisions per
|
|
||||||
* beat, but if the visual grid is using bbt_show_sixteenths (a
|
|
||||||
* fairly high level of detail), we will snap to (2 * 3)
|
|
||||||
* divisions per beat. Etc.
|
|
||||||
*/
|
|
||||||
|
|
||||||
BBTRulerScale scale = bbt_ruler_scale;
|
|
||||||
switch (scale) {
|
|
||||||
case bbt_show_many:
|
|
||||||
case bbt_show_64:
|
|
||||||
case bbt_show_16:
|
|
||||||
case bbt_show_4:
|
|
||||||
case bbt_show_1:
|
|
||||||
/* Round to Bar */
|
|
||||||
ret = timepos_t (tmap->quarters_at (presnap).round_to_subdivision (-1, direction));
|
|
||||||
break;
|
|
||||||
case bbt_show_quarters:
|
|
||||||
/* Round to Beat */
|
|
||||||
ret = timepos_t (tmap->quarters_at (presnap).round_to_subdivision (1, direction));
|
|
||||||
break;
|
|
||||||
case bbt_show_eighths:
|
|
||||||
ret = timepos_t (tmap->quarters_at (presnap).round_to_subdivision (1 * divisor, direction));
|
|
||||||
break;
|
|
||||||
case bbt_show_sixteenths:
|
|
||||||
ret = timepos_t (tmap->quarters_at (presnap).round_to_subdivision (2 * divisor, direction));
|
|
||||||
break;
|
|
||||||
case bbt_show_thirtyseconds:
|
|
||||||
ret = timepos_t (tmap->quarters_at (presnap).round_to_subdivision (4 * divisor, direction));
|
|
||||||
break;
|
|
||||||
case bbt_show_sixtyfourths:
|
|
||||||
ret = timepos_t (tmap->quarters_at (presnap).round_to_subdivision (8 * divisor, direction));
|
|
||||||
break;
|
|
||||||
case bbt_show_onetwentyeighths:
|
|
||||||
ret = timepos_t (tmap->quarters_at (presnap).round_to_subdivision (16 * divisor, direction));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Just use the grid as specified, without paying attention to
|
|
||||||
* zoom level
|
|
||||||
*/
|
|
||||||
|
|
||||||
ret = timepos_t (tmap->quarters_at (presnap).round_to_subdivision (get_grid_beat_divisions(_grid_type), direction));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
timepos_t
|
timepos_t
|
||||||
Editor::snap_to_grid (timepos_t const & presnap, Temporal::RoundMode direction, SnapPref gpref)
|
Editor::snap_to_grid (timepos_t const & presnap, Temporal::RoundMode direction, SnapPref gpref)
|
||||||
{
|
{
|
||||||
|
|
@ -2916,90 +2754,6 @@ Editor::snap_to_marker (timepos_t const & presnap, Temporal::RoundMode direction
|
||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Editor::snap_to_internal (timepos_t& start, Temporal::RoundMode direction, SnapPref pref, bool ensure_snap)
|
|
||||||
{
|
|
||||||
UIConfiguration const& uic (UIConfiguration::instance ());
|
|
||||||
const timepos_t presnap = start;
|
|
||||||
|
|
||||||
|
|
||||||
timepos_t test = timepos_t::max (start.time_domain()); // for each snap, we'll use this value
|
|
||||||
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
|
|
||||||
|
|
||||||
/* check Grid */
|
|
||||||
if ( (_grid_type != GridTypeNone) && (uic.get_snap_target () != SnapTargetOther) ) {
|
|
||||||
timepos_t pre (presnap);
|
|
||||||
timepos_t post (snap_to_grid (pre, direction, pref));
|
|
||||||
check_best_snap (presnap, post, dist, best);
|
|
||||||
if (uic.get_snap_target () == SnapTargetGrid) {
|
|
||||||
goto check_distance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check snap-to-marker */
|
|
||||||
if ((pref == SnapToAny_Visual) && uic.get_snap_to_marks ()) {
|
|
||||||
test = snap_to_marker (presnap, direction);
|
|
||||||
check_best_snap (presnap, test, dist, best);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check snap-to-playhead */
|
|
||||||
if ((pref == SnapToAny_Visual) && uic.get_snap_to_playhead () && !_session->transport_rolling ()) {
|
|
||||||
test = timepos_t (_session->audible_sample());
|
|
||||||
check_best_snap (presnap, test, dist, best);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check snap-to-region-{start/end/sync} */
|
|
||||||
if ((pref == SnapToAny_Visual) && (uic.get_snap_to_region_start () || uic.get_snap_to_region_end () || uic.get_snap_to_region_sync ())) {
|
|
||||||
|
|
||||||
if (!region_boundary_cache.empty ()) {
|
|
||||||
|
|
||||||
set<timepos_t>::iterator prev = region_boundary_cache.begin ();
|
|
||||||
set<timepos_t>::iterator next = std::upper_bound (region_boundary_cache.begin (), region_boundary_cache.end (), presnap);
|
|
||||||
if (next != region_boundary_cache.begin ()) {
|
|
||||||
prev = next;
|
|
||||||
prev--;
|
|
||||||
}
|
|
||||||
if (next == region_boundary_cache.end ()) {
|
|
||||||
next--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((direction == Temporal::RoundUpMaybe || direction == Temporal::RoundUpAlways)) {
|
|
||||||
test = *next;
|
|
||||||
} else if ((direction == Temporal::RoundDownMaybe || direction == Temporal::RoundDownAlways)) {
|
|
||||||
test = *prev;
|
|
||||||
} else if (direction == 0) {
|
|
||||||
if ((*prev).distance (presnap) < presnap.distance (*next)) {
|
|
||||||
test = *prev;
|
|
||||||
} else {
|
|
||||||
test = *next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
check_best_snap (presnap, test, dist, best);
|
|
||||||
}
|
|
||||||
|
|
||||||
check_distance:
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Editor::setup_toolbar ()
|
Editor::setup_toolbar ()
|
||||||
|
|
@ -6657,30 +6411,6 @@ Editor::use_own_window (bool and_fill_it)
|
||||||
return win;
|
return win;
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
|
||||||
Editor::time_to_pixel (timepos_t const & pos) const
|
|
||||||
{
|
|
||||||
return sample_to_pixel (pos.samples());
|
|
||||||
}
|
|
||||||
|
|
||||||
double
|
|
||||||
Editor::time_to_pixel_unrounded (timepos_t const & pos) const
|
|
||||||
{
|
|
||||||
return sample_to_pixel_unrounded (pos.samples());
|
|
||||||
}
|
|
||||||
|
|
||||||
double
|
|
||||||
Editor::duration_to_pixels (timecnt_t const & dur) const
|
|
||||||
{
|
|
||||||
return sample_to_pixel (dur.samples());
|
|
||||||
}
|
|
||||||
|
|
||||||
double
|
|
||||||
Editor::duration_to_pixels_unrounded (timecnt_t const & dur) const
|
|
||||||
{
|
|
||||||
return sample_to_pixel_unrounded (dur.samples());
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Editor::start_track_drag (TimeAxisView& tav, int y, Gtk::Widget& w, bool can_change_cursor)
|
Editor::start_track_drag (TimeAxisView& tav, int y, Gtk::Widget& w, bool can_change_cursor)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -219,44 +219,6 @@ public:
|
||||||
void separate_regions_using_location (ARDOUR::Location&);
|
void separate_regions_using_location (ARDOUR::Location&);
|
||||||
void transition_to_rolling (bool forward);
|
void transition_to_rolling (bool forward);
|
||||||
|
|
||||||
/* NOTE: these functions assume that the "pixel" coordinate is
|
|
||||||
in canvas coordinates. These coordinates already take into
|
|
||||||
account any scrolling offsets.
|
|
||||||
*/
|
|
||||||
|
|
||||||
samplepos_t pixel_to_sample_from_event (double pixel) const {
|
|
||||||
|
|
||||||
/* pixel can be less than zero when motion events
|
|
||||||
are processed. since we've already run the world->canvas
|
|
||||||
affine, that means that the location *really* is "off
|
|
||||||
to the right" and thus really is "before the start".
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (pixel >= 0) {
|
|
||||||
return pixel * samples_per_pixel;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
samplepos_t pixel_to_sample (double pixel) const {
|
|
||||||
return pixel * samples_per_pixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
double sample_to_pixel (samplepos_t sample) const {
|
|
||||||
return round (sample / (double) samples_per_pixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
double sample_to_pixel_unrounded (samplepos_t sample) const {
|
|
||||||
return sample / (double) samples_per_pixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
double time_to_pixel (Temporal::timepos_t const & pos) const;
|
|
||||||
double time_to_pixel_unrounded (Temporal::timepos_t const & pos) const;
|
|
||||||
|
|
||||||
double duration_to_pixels (Temporal::timecnt_t const & pos) const;
|
|
||||||
double duration_to_pixels_unrounded (Temporal::timecnt_t const & pos) const;
|
|
||||||
|
|
||||||
/* selection */
|
/* selection */
|
||||||
|
|
||||||
Selection& get_selection() const { return *selection; }
|
Selection& get_selection() const { return *selection; }
|
||||||
|
|
@ -471,21 +433,6 @@ public:
|
||||||
|
|
||||||
TrackViewList axis_views_from_routes (std::shared_ptr<ARDOUR::RouteList>) const;
|
TrackViewList axis_views_from_routes (std::shared_ptr<ARDOUR::RouteList>) const;
|
||||||
|
|
||||||
void snap_to (Temporal::timepos_t & first,
|
|
||||||
Temporal::RoundMode direction = Temporal::RoundNearest,
|
|
||||||
ARDOUR::SnapPref pref = ARDOUR::SnapToAny_Visual,
|
|
||||||
bool ensure_snap = false);
|
|
||||||
|
|
||||||
void snap_to_with_modifier (Temporal::timepos_t & first,
|
|
||||||
GdkEvent const* ev,
|
|
||||||
Temporal::RoundMode direction = Temporal::RoundNearest,
|
|
||||||
ARDOUR::SnapPref gpref = ARDOUR::SnapToAny_Visual,
|
|
||||||
bool ensure_snap = false);
|
|
||||||
|
|
||||||
Temporal::timepos_t snap_to_bbt (Temporal::timepos_t const & start,
|
|
||||||
Temporal::RoundMode direction,
|
|
||||||
ARDOUR::SnapPref gpref);
|
|
||||||
|
|
||||||
void set_snapped_cursor_position (Temporal::timepos_t const & pos);
|
void set_snapped_cursor_position (Temporal::timepos_t const & pos);
|
||||||
|
|
||||||
void begin_selection_op_history ();
|
void begin_selection_op_history ();
|
||||||
|
|
@ -621,9 +568,6 @@ private:
|
||||||
void start_visual_state_op (uint32_t n);
|
void start_visual_state_op (uint32_t n);
|
||||||
void cancel_visual_state_op (uint32_t n);
|
void cancel_visual_state_op (uint32_t n);
|
||||||
|
|
||||||
samplecnt_t samples_per_pixel;
|
|
||||||
Editing::ZoomFocus zoom_focus;
|
|
||||||
|
|
||||||
void set_samples_per_pixel (samplecnt_t);
|
void set_samples_per_pixel (samplecnt_t);
|
||||||
void on_samples_per_pixel_changed ();
|
void on_samples_per_pixel_changed ();
|
||||||
|
|
||||||
|
|
@ -2333,16 +2277,6 @@ private:
|
||||||
Temporal::RoundMode direction,
|
Temporal::RoundMode direction,
|
||||||
ARDOUR::SnapPref gpref);
|
ARDOUR::SnapPref gpref);
|
||||||
|
|
||||||
Temporal::timepos_t _snap_to_bbt (Temporal::timepos_t const & start,
|
|
||||||
Temporal::RoundMode direction,
|
|
||||||
ARDOUR::SnapPref gpref,
|
|
||||||
Editing::GridType grid_type);
|
|
||||||
|
|
||||||
void snap_to_internal (Temporal::timepos_t& first,
|
|
||||||
Temporal::RoundMode direction = Temporal::RoundNearest,
|
|
||||||
ARDOUR::SnapPref gpref = ARDOUR::SnapToAny_Visual,
|
|
||||||
bool ensure_snap = false);
|
|
||||||
|
|
||||||
void timecode_snap_to_internal (Temporal::timepos_t & first,
|
void timecode_snap_to_internal (Temporal::timepos_t & first,
|
||||||
Temporal::RoundMode direction = Temporal::RoundNearest,
|
Temporal::RoundMode direction = Temporal::RoundNearest,
|
||||||
bool for_mark = false);
|
bool for_mark = false);
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
#include "automation_line.h"
|
#include "automation_line.h"
|
||||||
#include "control_point.h"
|
#include "control_point.h"
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
|
#include "midi_cue_editor.h"
|
||||||
#include "region_view.h"
|
#include "region_view.h"
|
||||||
#include "ui_config.h"
|
#include "ui_config.h"
|
||||||
|
|
||||||
|
|
@ -51,43 +52,6 @@ using namespace ArdourCanvas;
|
||||||
using std::max;
|
using std::max;
|
||||||
using std::min;
|
using std::min;
|
||||||
|
|
||||||
MidiClipEditor::MidiClipEditor ()
|
|
||||||
{
|
|
||||||
set_background_color (UIConfiguration::instance ().color (X_("neutral:backgroundest")));
|
|
||||||
|
|
||||||
const double scale = UIConfiguration::instance ().get_ui_scale ();
|
|
||||||
const double width = 600. * scale;
|
|
||||||
const double height = 210. * scale;
|
|
||||||
|
|
||||||
frame = new ArdourCanvas::Rectangle (this);
|
|
||||||
|
|
||||||
ArdourCanvas::Rect r (0, 0, width, height);
|
|
||||||
frame->set (r);
|
|
||||||
frame->set_outline_all ();
|
|
||||||
|
|
||||||
frame->Event.connect (sigc::mem_fun (*this, &MidiClipEditor::event_handler));
|
|
||||||
}
|
|
||||||
|
|
||||||
MidiClipEditor::~MidiClipEditor ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
MidiClipEditor::event_handler (GdkEvent* ev)
|
|
||||||
{
|
|
||||||
switch (ev->type) {
|
|
||||||
case GDK_BUTTON_PRESS:
|
|
||||||
break;
|
|
||||||
case GDK_ENTER_NOTIFY:
|
|
||||||
break;
|
|
||||||
case GDK_LEAVE_NOTIFY:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
MidiClipEditorBox::MidiClipEditorBox ()
|
MidiClipEditorBox::MidiClipEditorBox ()
|
||||||
{
|
{
|
||||||
|
|
@ -95,11 +59,11 @@ MidiClipEditorBox::MidiClipEditorBox ()
|
||||||
_header_label.set_alignment (0.0, 0.5);
|
_header_label.set_alignment (0.0, 0.5);
|
||||||
pack_start (_header_label, false, false, 6);
|
pack_start (_header_label, false, false, 6);
|
||||||
|
|
||||||
editor = manage (new MidiClipEditor ());
|
editor = manage (new MidiCueEditor ());
|
||||||
editor->set_size_request (600, 120);
|
editor->viewport().set_size_request (600, 120);
|
||||||
|
|
||||||
pack_start (*editor, true, true);
|
pack_start (editor->viewport(), true, true);
|
||||||
editor->show ();
|
editor->viewport().show ();
|
||||||
}
|
}
|
||||||
|
|
||||||
MidiClipEditorBox::~MidiClipEditorBox ()
|
MidiClipEditorBox::~MidiClipEditorBox ()
|
||||||
|
|
|
||||||
|
|
@ -50,16 +50,7 @@ namespace ArdourCanvas
|
||||||
class Polygon;
|
class Polygon;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MidiClipEditor : public ArdourCanvas::GtkCanvas
|
class MidiCueEditor;
|
||||||
{
|
|
||||||
public:
|
|
||||||
MidiClipEditor ();
|
|
||||||
~MidiClipEditor ();
|
|
||||||
|
|
||||||
private:
|
|
||||||
ArdourCanvas::Rectangle* frame;
|
|
||||||
bool event_handler (GdkEvent* ev);
|
|
||||||
};
|
|
||||||
|
|
||||||
class MidiClipEditorBox : public ClipEditorBox
|
class MidiClipEditorBox : public ClipEditorBox
|
||||||
{
|
{
|
||||||
|
|
@ -76,7 +67,7 @@ private:
|
||||||
Gtk::Label _header_label;
|
Gtk::Label _header_label;
|
||||||
Gtk::Table table;
|
Gtk::Table table;
|
||||||
|
|
||||||
MidiClipEditor* editor;
|
MidiCueEditor* editor;
|
||||||
|
|
||||||
PBD::ScopedConnection state_connection;
|
PBD::ScopedConnection state_connection;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue