Compare commits

...

78 Commits

Author SHA1 Message Date
Paul Davis 9b61abd390 the state of things in pianorule, committed for travel purposes 2024-02-27 12:21:27 -07:00
Paul Davis d191330235 basics of autoscroll for pianoroll (mostly shared with Editor)
More work to do moving/testing pianoroll autoscroll variant back into EditingContext
and sharing it with Editor.
2024-02-23 11:25:07 -07:00
Paul Davis d6dcb1c575 change coordinate system used for rubberband drags in piano roll 2024-02-22 10:37:09 -07:00
Paul Davis a5b6e1676a redesign drag API to provide a bounding item, not just "trackview only"
This allows rubberband drags on both the main editor and the separate piano roll to wokr
correctly.
2024-02-21 22:19:24 -07:00
Paul Davis 8661bfb090 fix event deliver for MidiCueView
events need a non-container item to be delivered
2024-02-21 22:19:24 -07:00
Paul Davis f76d81d44f move various action registry stuff into EditingContext 2024-02-21 22:19:24 -07:00
Paul Davis 0b7461c465 add -D actions to gtkmm2ext 2024-02-21 22:19:24 -07:00
Paul Davis 8d8e8a5509 get those MIDI tool selector menus built 2024-02-21 22:19:24 -07:00
Paul Davis 69ab632e95 some state mgmt for EditingContexts 2024-02-21 22:19:24 -07:00
Paul Davis c3c34a0e0e cue editor/piano roll: starting to get mode buttons working and keybindings too 2024-02-21 22:19:24 -07:00
Paul Davis 3d71e6136b stacktraces to help track down missing actions 2024-02-21 22:19:24 -07:00
Paul Davis 7d28d89635 cleanup canvas piano roll header so that it can exist with no current MidiView 2024-02-21 22:19:24 -07:00
Paul Davis f08ada678a working and accessible canvas cursor setting 2024-02-21 22:19:24 -07:00
Paul Davis 784aa8ccc6 note range for midi * views API cleanup 2024-02-21 22:19:24 -07:00
Paul Davis a17eac860b expose ::set_note_range() as public in MidiView 2024-02-21 22:19:24 -07:00
Paul Davis 46c341175d fix drawing translation issue 2024-02-21 22:19:24 -07:00
Paul Davis 9f76533f76 basically functioning piano roll for midi cue editor 2024-02-21 22:19:24 -07:00
Paul Davis 7329508fd1 tentative beginnings for a canvas piano roll header 2024-02-21 22:19:24 -07:00
Paul Davis a8194729f1 fix up event handling so that MIDI note drag works in cue editor 2024-02-21 22:19:24 -07:00
Paul Davis bc00c320c4 prefer lambdas to stupid stub static functions 2024-02-21 22:19:24 -07:00
Paul Davis 807c098a7a and we have h-scrolling in the cue editor 2024-02-21 22:19:24 -07:00
Paul Davis e6b6152f5a the continuing co-evolution of Editor,EditingContext & MidiCueEditor 2024-02-21 22:19:24 -07:00
Paul Davis e2e660b4cd tempo bar and BBT ruler in MIDI cue editor 2024-02-21 22:19:24 -07:00
Paul Davis 4f7ff877a9 use SMF tempo map if available in MidiCueEditor 2024-02-21 22:19:24 -07:00
Paul Davis b8217f12f2 use new SMF::tempo_map() method when importing tempo map from SMF 2024-02-21 22:19:24 -07:00
Paul Davis 7dac2a216d factor out code to extract a TempoMap from an SMF 2024-02-21 22:19:24 -07:00
Paul Davis 5509db3b24 steps toward rulers for the MIDI cue editor 2024-02-21 22:19:24 -07:00
Paul Davis 7836418ebf do something to make MIDI bindings accessible in any EditingContext 2024-02-21 22:19:24 -07:00
Paul Davis 23a672b45d move a bunch of MIDI editing into EditingContext 2024-02-21 22:19:24 -07:00
Paul Davis 89f780b78c virtualize event handling methods for EditingContext 2024-02-21 22:19:24 -07:00
Paul Davis b77974b7c0 share code between MidiRegioNView and MidiView 2024-02-21 22:19:24 -07:00
Paul Davis 86ee139689 progrss with rubber band selection and event handling in MIDI cue editor 2024-02-21 22:19:24 -07:00
Paul Davis e061c775f0 lock in some major steps for the midi cue/pianoroll editor 2024-02-21 22:19:24 -07:00
Paul Davis 97cf69a408 more work on fixing pianorule recomposition of objects 2024-02-21 22:19:24 -07:00
Paul Davis bee5edd945 fixes to get redraws when note range changes 2024-02-21 22:19:24 -07:00
Paul Davis a86a5e6de3 fix some region-view level selection issues 2024-02-21 22:19:24 -07:00
Paul Davis dbbc89835b get standalone MidiView to display notes
This also removes an unused TriggerBoxWidget from each regular
MixerStrip.
2024-02-21 22:19:23 -07:00
Paul Davis 96a35e67a5 Fix behavior of midi region when height changes
MidiView cares about the previous height, so call that first, before
RegionView::set_height() sets the member that controls height()
2024-02-21 22:19:23 -07:00
Paul Davis e33ade0116 no more slice.h 2024-02-21 22:19:23 -07:00
Paul Davis 3be39c50e1 revert scope change for a local variable 2024-02-21 22:19:23 -07:00
Paul Davis 705b9d0ab3 fix group used as parent for a Midi(Region)View
this fixed the nesting of the _note_group and thus notes are drawn
in the correct place.
2024-02-21 22:19:23 -07:00
Paul Davis 032f314de5 remove debug output 2024-02-21 22:19:23 -07:00
Paul Davis c97bf1a4b7 Revert "separate out all bounds/position info from Region into "Slice""
This reverts commit f3da2cfd8b.
2024-02-21 22:19:23 -07:00
Paul Davis efcdf21444 Revert "add set_* methods to Slice; remove property additions"
This reverts commit 81eee23baa.
2024-02-21 22:19:23 -07:00
Paul Davis 0715b0b2d3 remove current slice usage/members 2024-02-21 22:19:23 -07:00
Paul Davis 617749b200 convert debug output from printf to type-safe iostreams 2024-02-21 22:19:23 -07:00
Paul Davis 4416fa698f get region-create drags working and no crashes (nut also no note) for note-drags 2024-02-21 22:19:23 -07:00
Paul Davis 15e3c235ac initial refactoring of MidiRegionView IS-A MidiView 2024-02-21 22:19:23 -07:00
Paul Davis 62966c82bc add missing files 2024-02-21 22:19:23 -07:00
Paul Davis ee1e074ca7 fix a rebase error 2024-02-21 22:19:23 -07:00
Paul Davis 19b13053d7 first working visual evidence of MIDI display/editing on cue page 2024-02-21 22:19:23 -07:00
Paul Davis dd4bdbb81f NO-OP: comment fix 2024-02-21 22:19:23 -07:00
Paul Davis 5c5340a20d NO-OP (whitespace) 2024-02-21 22:19:23 -07:00
Paul Davis 3532180fcc all streamviews are now ViewBackgrounds
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.
2024-02-21 22:19:23 -07:00
Paul Davis 4d4fba51f6 start using the now-compilable MidiView
Nothing yet derives from this, but MIDI display items and drags
do use it.
2024-02-21 22:19:23 -07:00
Paul Davis 2830cda07e remove method decls no longer based in PublicEditor.h 2024-02-21 22:19:23 -07:00
Paul Davis 534bc9c012 add set_* methods to Slice; remove property additions
Derived classes (currently only Region) just register the Slice properties
_start and _length.
2024-02-21 22:19:23 -07:00
Paul Davis f75dde7fbc constification of EditingContext/{Public}Editor time+snap methods 2024-02-21 22:19:23 -07:00
Paul Davis 0f7cc13c07 move 2 relative time methods from RegionView to EditingContext 2024-02-21 22:19:23 -07:00
Paul Davis 91f496e533 separate out all bounds/position info from Region into "Slice"
The idea here is to be able to describe region size, start and position
independently of an actual Region object.
2024-02-21 22:19:23 -07:00
Paul Davis 44974c08ea make Stateful a virtual base class of StatefulDestructible
This permits dual inheritance from Stateful.
2024-02-21 22:19:23 -07:00
Paul Davis cfb4ed5884 removed unused MidiRegionView argument from SysEx (visual) constructor 2024-02-21 22:19:23 -07:00
Paul Davis 2cdb30d397 no-compilable steps towards MidiView 2024-02-21 22:19:23 -07:00
Paul Davis 946fe23e60 further steps towards MidiRegionView outside the Editor 2024-02-21 22:19:23 -07:00
Paul Davis 1f903e402a manually merge in new actions for note tupling 2024-02-21 22:19:23 -07:00
Paul Davis 088e71fceb finish basic distribution of EditingContext methods
This compiles but is not expected to work yet
2024-02-21 22:19:23 -07:00
Paul Davis d0170e3d9f more movement of code and members from Editor => EditingContext 2024-02-21 22:19:23 -07:00
Paul Davis 797050a56f skeleton for MIDI cue editor 2024-02-21 22:19:23 -07:00
Paul Davis 7ffcc1aaf9 adjust relationship between VerboseCursor and Editor to use EditingContext 2024-02-21 22:19:23 -07:00
Paul Davis 4effe31b77 add preprocessor guard clauses 2024-02-21 22:19:23 -07:00
Paul Davis 60f7878dc6 add stub for cue editor 2024-02-21 22:19:23 -07:00
Paul Davis f037bb622d more reorganization of implementations between Editor & EditingContext & PublicEditor 2024-02-21 22:19:23 -07:00
Paul Davis ae8587d7e5 finish inheritance work between EditingContext & Editor
this completes the initial phase of defining what an EditingContext must offer,
though the may expand or shrink as we being work on editing outside the Editor
2024-02-21 22:19:23 -07:00
Paul Davis 256edf9b7e clean up minor mess after manual rebasing 2024-02-21 22:19:22 -07:00
Paul Davis 67f31a0e82 editing refactoring, the drag part 2024-02-21 22:19:22 -07:00
Paul Davis 2eec8ec62a steps to an ecology of editing 2024-02-21 22:19:22 -07:00
Paul Davis cf88db7fe2 PublicEditor IS-A MidiEditingContext 2024-02-21 22:19:22 -07:00
Paul Davis 054e6bca89 skeleton work for a MidiEditingContext, incomplete 2024-02-21 22:19:22 -07:00
109 changed files with 13997 additions and 9287 deletions

View File

@ -157,22 +157,22 @@ This mode provides many different operations on both regions and control points,
@gmark|Common/jump-backward-to-mark| q|to previous mark
@sess|Common/Quit| <@PRIMARY@>q|quit
@gmark|Common/jump-forward-to-mark| w|to next mark
@mmode|MouseMode/set-mouse-mode-content| e|content mode
@mmode|Editor/set-mouse-mode-content| e|content mode
@sess|Main/QuickExport| <@PRIMARY@>e|quick export session
@rop|Region/export-region| <@PRIMARY@><@SECONDARY@>e|export selected region(s)
@sess|Main/ExportAudio| <@SECONDARY@>e|export session
@sess|Main/StemExport| <@SECONDARY@><@TERTIARY@>e|stem export selected tracks
@select|Editor/select-all-after-edit-cursor| <@PRIMARY@><@TERTIARY@>e|select all after EP
@vis|Editor/show-editor-mixer| <@TERTIARY@>e|toggle editor window mixer
@mmode|MouseMode/set-mouse-mode-range| r|range mode
@mmode|Editor/set-mouse-mode-range| r|range mode
@wvis|Common/show-recorder| <@SECONDARY@>r|show recorder page
@edit|Editor/redo| <@PRIMARY@>r|redo
@edit|Editor/select-from-regions| <@PRIMARY@><@TERTIARY@>r|set Range to selected regions
@edit|Editor/add-range-marker-from-selection| <@SECONDARY@><@TERTIARY@>r|Add single Range marker from selection
@trans|Transport/Record| <@TERTIARY@>r|engage record
@mmode|MouseMode/set-mouse-mode-timefx| t|timefx mode
@mmode|Editor/set-mouse-mode-timefx| t|timefx mode
@gselect|Common/select-all-visible-lanes| <@PRIMARY@>t|select all visible lanes
@mmode|MouseMode/set-mouse-mode-grid| y|grid mode
@mmode|Editor/set-mouse-mode-grid| y|grid mode
@edit|Editor/alternate-redo| <@PRIMARY@>y|redo
@select|Editor/select-all-between-cursors| <@PRIMARY@>u|select all regions enclosed by Range
@select|Editor/select-all-within-cursors| u|select all regions touched by Range
@ -200,7 +200,7 @@ This mode provides many different operations on both regions and control points,
@sess|Main/SnapshotStay| <@PRIMARY@><@TERTIARY@>s|snapshot session
@edtrk|Editor/track-solo-toggle| <@SECONDARY@>s|toggle track solo status
@edit|Editor/ToggleSummary| <@TERTIARY@>s|toggle summary
@mmode|MouseMode/set-mouse-mode-draw| d|note-draw mode
@mmode|Editor/set-mouse-mode-draw| d|note-draw mode
@edit|Editor/duplicate| <@PRIMARY@>d|duplicate (once)
@edit|Editor/multi-duplicate| <@SECONDARY@>d|duplicate (multi)
@select|Editor/select-all-in-punch-range| <@TERTIARY@>d|select all in punch range
@ -210,7 +210,7 @@ This mode provides many different operations on both regions and control points,
@rop|Region/show-rhythm-ferret| <@SECONDARY@>f|show rhythm ferret window
@wvis|Common/ToggleMaximalEditor| <@PRIMARY@><@SECONDARY@>f|maximise editor space
@wvis|Common/ToggleMaximalMixer| <@PRIMARY@><@TERTIARY@>f|maximise mixer space
@mmode|MouseMode/set-mouse-mode-object| g|object mode
@mmode|Editor/set-mouse-mode-object| g|object mode
@edit|Editor/group-selected-regions| <@PRIMARY@>g|group selected regions
@edit|Editor/ungroup-selected-regions| <@PRIMARY@><@TERTIARY@>g|ungroup selected regions
@edit|Region/play-selected-regions| h|play selected region(s)
@ -231,7 +231,7 @@ This mode provides many different operations on both regions and control points,
@aep|Region/align-regions-sync-relative| x|align sync points (relative)
@edit|Editor/editor-cut| <@PRIMARY@>x|cut
@edit|Editor/cut-paste-section| <@PRIMARY@><@TERTIARY@>x|cut \& paste section
@mmode|MouseMode/set-mouse-mode-cut| c|cut mode
@mmode|Editor/set-mouse-mode-cut| c|cut mode
@edit|Editor/editor-copy| <@PRIMARY@>c|copy
@wvis|Common/show-trigger| <@SECONDARY@>c|show cues page
@edit|Editor/editor-crop| <@PRIMARY@><@SECONDARY@>c|crop range
@ -391,7 +391,7 @@ This mode provides many different operations on both regions and control points,
@eep|Editor/cycle-edit-mode| 1|cycle edit mode {slide, lock, ripple}
@eep|Editor/cycle-edit-point| 2|next EP w/o marker {playhead, mouse}
@eep|Editor/cycle-edit-point-with-marker| <@PRIMARY@>2|next EP w/marker {playhead, mouse, marker}
@mmode|MouseMode/set-mouse-mode-object-range| 3|Smart Mode (provide some Range tools in Object mode)
@mmode|Editor/set-mouse-mode-object-range| 3|Smart Mode (provide some Range tools in Object mode)
@gmode|Transport/ToggleFollowEdits| <@PRIMARY@>3|toggle playhead follows edits
@grid|Editor/cycle-snap-mode| 4|cycle to next snap mode {On/Off}
@grid|Editor/prev-grid-choice| 5|use prev grid unit

View File

@ -274,7 +274,7 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey
Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_hierarchy (&focus);
if (focus_bindings) {
DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing widget (%3) bindings %1 @ %2 for this event\n", focus_bindings->name(), focus_bindings, gtk_widget_get_name (focus)));
DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\t(nomod) using widget (%3) bindings %1 @ %2 for this event\n", focus_bindings->name(), focus_bindings, gtk_widget_get_name (focus)));
if (focus_bindings->activate (k, Bindings::Press)) {
return true;
}
@ -290,7 +290,7 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey
*/
if (top_level_bindings) {
DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing top level bindings %1 @ %2 for this event\n", top_level_bindings->name(), top_level_bindings));
DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\t(nomod) using top level bindings %1 @ %2 for this event\n", top_level_bindings->name(), top_level_bindings));
}
if (top_level_bindings && top_level_bindings->activate (k, Bindings::Press)) {

View File

@ -213,7 +213,7 @@ protected:
void transients_changed();
AutomationLine::VisibleAspects automation_line_visibility () const;
void _redisplay (bool) {}
void redisplay (bool) {}
private:
void setup_fade_handle_positions ();

View File

@ -70,6 +70,11 @@ AudioStreamView::AudioStreamView (AudioTimeAxisView& tv)
color_handler ();
}
AudioStreamView::~AudioStreamView ()
{
undisplay_track ();
}
int
AudioStreamView::set_amplitude_above_axis (gdouble app)
{

View File

@ -55,6 +55,7 @@ class AudioStreamView : public StreamView
{
public:
AudioStreamView (AudioTimeAxisView&);
~AudioStreamView ();
int set_amplitude_above_axis (gdouble app);
gdouble get_amplitude_above_axis () { return _amplitude_above_axis; }

View File

@ -148,6 +148,8 @@ AudioTimeAxisView::set_route (std::shared_ptr<Route> rt)
AudioTimeAxisView::~AudioTimeAxisView ()
{
delete _view;
_view = nullptr;
}
void

View File

@ -184,7 +184,7 @@ AutomationRegionView::add_automation_event (timepos_t const & w, double y, bool
/* snap time */
when = snap_region_time_to_region_time (_region->source_position().distance (when), false);
when = view->editor().snap_relative_time_to_relative_time (_region->position(), _region->source_position().distance (when), false);
/* map using line */

View File

@ -87,7 +87,7 @@ protected:
void mouse_mode_changed ();
void entered();
void exited();
void _redisplay (bool) {}
void redisplay (bool) {}
private:
Evoral::Parameter _parameter;

View File

@ -52,7 +52,7 @@ public:
void redisplay_track ();
inline double contents_height() const {
double contents_height() const {
return (_trackview.current_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 2);
}

216
gtk2_ardour/cue_editor.cc Normal file
View File

@ -0,0 +1,216 @@
#include "cue_editor.h"
CueEditor::CueEditor (std::string const & name)
: EditingContext (name)
{
}
CueEditor::~CueEditor ()
{
}
void
CueEditor::set_snapped_cursor_position (Temporal::timepos_t const & pos)
{
}
std::vector<MidiRegionView*>
CueEditor::filter_to_unique_midi_region_views (RegionSelection const & ms) const
{
std::vector<MidiRegionView*> mrv;
return mrv;
}
void
CueEditor::select_all_within (Temporal::timepos_t const &, Temporal::timepos_t const &, double, double, TrackViewList const &, Selection::Operation, bool)
{
}
void
CueEditor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
{
}
StripableTimeAxisView*
CueEditor::get_stripable_time_axis_by_id (const PBD::ID& id) const
{
return nullptr;
}
TrackViewList
CueEditor::axis_views_from_routes (std::shared_ptr<ARDOUR::RouteList>) const
{
TrackViewList tvl;
return tvl;
}
ARDOUR::Location*
CueEditor::find_location_from_marker (ArdourMarker*, bool&) const
{
return nullptr;
}
ArdourMarker*
CueEditor::find_marker_from_location_id (PBD::ID const&, bool) const
{
return nullptr;
}
TempoMarker*
CueEditor::find_marker_for_tempo (Temporal::TempoPoint const &)
{
return nullptr;
}
MeterMarker*
CueEditor::find_marker_for_meter (Temporal::MeterPoint const &)
{
return nullptr;
}
void
CueEditor::maybe_autoscroll (bool, bool, bool from_headers)
{
}
void
CueEditor::stop_canvas_autoscroll ()
{
}
bool
CueEditor::autoscroll_active() const
{
return false;
}
void
CueEditor::redisplay_grid (bool immediate_redraw)
{
}
Temporal::timecnt_t
CueEditor::get_nudge_distance (Temporal::timepos_t const & pos, Temporal::timecnt_t& next) const
{
return Temporal::timecnt_t (Temporal::AudioTime);
}
void
CueEditor::instant_save()
{
}
EditingContext::EnterContext*
CueEditor::get_enter_context(ItemType type)
{
return nullptr;
}
void
CueEditor::begin_selection_op_history ()
{
}
void
CueEditor::begin_reversible_selection_op (std::string cmd_name)
{
}
void
CueEditor::commit_reversible_selection_op ()
{
}
void
CueEditor::abort_reversible_selection_op ()
{
}
void
CueEditor::undo_selection_op ()
{
}
void
CueEditor::redo_selection_op ()
{
}
double
CueEditor::get_y_origin () const
{
return 0.;
}
void
CueEditor::set_zoom_focus (Editing::ZoomFocus)
{
}
Editing::ZoomFocus
CueEditor::get_zoom_focus () const
{
return Editing::ZoomFocusPlayhead;
}
void
CueEditor::set_samples_per_pixel (samplecnt_t n)
{
samples_per_pixel = n;
ZoomChanged(); /* EMIT SIGNAL */
}
samplecnt_t
CueEditor::get_current_zoom () const
{
return samples_per_pixel;
}
void
CueEditor::reposition_and_zoom (samplepos_t, double)
{
}
void
CueEditor::set_mouse_mode (Editing::MouseMode, bool force)
{
}
void
CueEditor::step_mouse_mode (bool next)
{
}
void
CueEditor::reset_x_origin_to_follow_playhead ()
{
}
Gdk::Cursor*
CueEditor::get_canvas_cursor () const
{
return nullptr;
}
Editing::MouseMode
CueEditor::current_mouse_mode () const
{
return Editing::MouseContent;
}
std::shared_ptr<Temporal::TempoMap const>
CueEditor::start_local_tempo_map (std::shared_ptr<Temporal::TempoMap> map)
{
std::shared_ptr<Temporal::TempoMap const> tmp = Temporal::TempoMap::use();
Temporal::TempoMap::set (map);
return tmp;
}
void
CueEditor::end_local_tempo_map (std::shared_ptr<Temporal::TempoMap const> map)
{
Temporal::TempoMap::set (map);
}

102
gtk2_ardour/cue_editor.h Normal file
View File

@ -0,0 +1,102 @@
/*
* 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.
*/
#ifndef __gtk_ardour_cue_editor_h__
#define __gtk_ardour_cue_editor_h__
#include "editing.h"
#include "editing_context.h"
class CueEditor : public EditingContext
{
public:
CueEditor (std::string const & name);
~CueEditor ();
void select_all_within (Temporal::timepos_t const &, Temporal::timepos_t const &, double, double, TrackViewList const &, Selection::Operation, bool);
void get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const;
StripableTimeAxisView* get_stripable_time_axis_by_id (const PBD::ID& id) 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;
ArdourMarker* find_marker_from_location_id (PBD::ID const&, bool) const;
TempoMarker* find_marker_for_tempo (Temporal::TempoPoint const &);
MeterMarker* find_marker_for_meter (Temporal::MeterPoint const &);
void maybe_autoscroll (bool, bool, bool from_headers);
void stop_canvas_autoscroll ();
bool autoscroll_active() const;
void redisplay_grid (bool immediate_redraw);
Temporal::timecnt_t get_nudge_distance (Temporal::timepos_t const & pos, Temporal::timecnt_t& next) const;
void instant_save();
/** Get the topmost enter context for the given item type.
*
* This is used to change the cursor associated with a given enter context,
* which may not be on the top of the stack.
*/
EnterContext* get_enter_context(ItemType type);
void begin_selection_op_history ();
void begin_reversible_selection_op (std::string cmd_name);
void commit_reversible_selection_op ();
void abort_reversible_selection_op ();
void undo_selection_op ();
void redo_selection_op ();
double get_y_origin () const;
void set_zoom_focus (Editing::ZoomFocus);
Editing::ZoomFocus get_zoom_focus () const;
samplecnt_t get_current_zoom () const;
void set_samples_per_pixel (samplecnt_t);
void reposition_and_zoom (samplepos_t, double);
void set_mouse_mode (Editing::MouseMode, bool force = false);
/** Step the mouse mode onto the next or previous one.
* @param next true to move to the next, otherwise move to the previous
*/
void step_mouse_mode (bool next);
/** @return The current mouse mode (gain, object, range, timefx etc.)
* (defined in editing_syms.h)
*/
Editing::MouseMode current_mouse_mode () const;
/** cue editors are *always* used for internal editing */
bool internal_editing() const { return true; }
Gdk::Cursor* get_canvas_cursor () const;
MouseCursors const* cursors () const {
return _cursors;
}
void set_snapped_cursor_position (Temporal::timepos_t const & pos);
std::vector<MidiRegionView*> filter_to_unique_midi_region_views (RegionSelection const & ms) const;
std::shared_ptr<Temporal::TempoMap const> start_local_tempo_map (std::shared_ptr<Temporal::TempoMap>);
void end_local_tempo_map (std::shared_ptr<Temporal::TempoMap const>);
protected:
void reset_x_origin_to_follow_playhead ();
};
#endif /* __gtk_ardour_cue_editor_h__ */

View File

@ -18,44 +18,45 @@
#include <pbd/error.h>
#include "editor.h"
#include "editing_context.h"
#include "cursor_context.h"
CursorContext::CursorContext(Editor& editor, Gdk::Cursor* cursor)
: _editor(editor)
, _index(editor.push_canvas_cursor(cursor))
{}
CursorContext::CursorContext(EditingContext& ec, Gdk::Cursor* cursor)
: editing_context(ec)
, _index (editing_context.push_canvas_cursor(cursor))
{
}
CursorContext::~CursorContext()
{
if (_index == _editor._cursor_stack.size() - 1) {
_editor.pop_canvas_cursor();
if (_index == editing_context._cursor_stack.size() - 1) {
editing_context.pop_canvas_cursor();
} else {
_editor._cursor_stack[_index] = NULL;
editing_context._cursor_stack[_index] = NULL;
}
}
CursorContext::Handle
CursorContext::create(Editor& editor, Gdk::Cursor* cursor)
CursorContext::create(EditingContext& ec, Gdk::Cursor* cursor)
{
return CursorContext::Handle(new CursorContext(editor, cursor));
return CursorContext::Handle(new CursorContext(ec, cursor));
}
void
CursorContext::change(Gdk::Cursor* cursor)
{
_editor._cursor_stack[_index] = cursor;
if (_index == _editor._cursor_stack.size() - 1) {
_editor.set_canvas_cursor(cursor);
editing_context._cursor_stack[_index] = cursor;
if (_index == editing_context._cursor_stack.size() - 1) {
editing_context.set_canvas_cursor(cursor);
}
}
void
CursorContext::set(Handle* handle, Editor& editor, Gdk::Cursor* cursor)
CursorContext::set(Handle* handle, EditingContext& ec, Gdk::Cursor* cursor)
{
if (*handle) {
(*handle)->change(cursor);
} else {
*handle = CursorContext::create(editor, cursor);
*handle = CursorContext::create(ec, cursor);
}
}

View File

@ -23,7 +23,7 @@
#include <gdkmm/cursor.h>
class Editor;
class EditingContext;
/**
A scoped handle for changing the editor mouse cursor.
@ -53,7 +53,7 @@ public:
* When the returned handle goes out of scope, the cursor will be reset to
* the previous value.
*/
static Handle create(Editor& editor, Gdk::Cursor* cursor);
static Handle create(EditingContext&, Gdk::Cursor* cursor);
/** Change the editor cursor of an existing cursor context. */
void change(Gdk::Cursor* cursor);
@ -63,13 +63,13 @@ public:
* If the handle points to an existing context, it will first be reset
* before the new context is created.
*/
static void set(Handle* handle, Editor& editor, Gdk::Cursor* cursor);
static void set(Handle* handle, EditingContext&, Gdk::Cursor* cursor);
private:
Editor& _editor;
EditingContext& editing_context;
size_t _index;
CursorContext(Editor& editor, Gdk::Cursor* cursor);
CursorContext(EditingContext&, Gdk::Cursor* cursor);
};
#endif /* __ardour_gtk_cursor_context_h__ */

View File

@ -24,8 +24,10 @@
#include "gtkmm2ext/utils.h"
#include "ardour/midi_region.h"
#include "edit_note_dialog.h"
#include "midi_region_view.h"
#include "midi_view.h"
#include "note_base.h"
#include "pbd/i18n.h"
@ -41,7 +43,7 @@ using namespace Gtkmm2ext;
* @param n Notes to edit.
*/
EditNoteDialog::EditNoteDialog (MidiRegionView* rv, set<NoteBase*> n)
EditNoteDialog::EditNoteDialog (MidiView* rv, set<NoteBase*> n)
: ArdourDialog (_("Note"))
, _region_view (rv)
, _events (n)
@ -94,12 +96,11 @@ EditNoteDialog::EditNoteDialog (MidiRegionView* rv, set<NoteBase*> n)
table->attach (_time_all, 2, 3, r, r + 1);
++r;
_time_clock.set_session (_region_view->get_time_axis_view().session ());
// XXXX _time_clock.set_session (_region_view->get_time_axis_view().session ());
_time_clock.set_mode (AudioClock::BBT);
/* Calculate absolute position of the event on time timeline */
std::shared_ptr<ARDOUR::Region> region (_region_view->region ());
timepos_t const pos = region->source_position() + timecnt_t ((*_events.begin())->note()->time ());
timepos_t const pos = _region_view->midi_region()->source_position() + timecnt_t ((*_events.begin())->note()->time ());
_time_clock.set (pos, true);
@ -109,7 +110,7 @@ EditNoteDialog::EditNoteDialog (MidiRegionView* rv, set<NoteBase*> n)
table->attach (_length_all, 2, 3, r, r + 1);
++r;
_length_clock.set_session (_region_view->get_time_axis_view().session ());
// XXXX _length_clock.set_session (_region_view->get_time_axis_view().session ());
_length_clock.set_mode (AudioClock::BBT);
_length_clock.set_duration (timecnt_t ((*_events.begin())->note()->length()), true);
@ -201,10 +202,8 @@ EditNoteDialog::done (int r)
}
}
std::shared_ptr<ARDOUR::Region> region (_region_view->region ());
/* convert current clock time into an offset from the start of the source */
timecnt_t const time_clock_source_relative = region->source_position ().distance (_time_clock.last_when ());
timecnt_t const time_clock_source_relative = _region_view->midi_region()->source_position ().distance (_time_clock.last_when ());
/* convert that into a position in Beats - this will be the new note time (as an offset inside the source) */
Beats const new_note_time_source_relative_beats = time_clock_source_relative.beats ();

View File

@ -22,18 +22,18 @@
#include "ardour_dialog.h"
#include "audio_clock.h"
class MidiRegionView;
class MidiView;
class NoteBase;
class EditNoteDialog : public ArdourDialog
{
public:
EditNoteDialog (MidiRegionView* rv, std::set<NoteBase*> n);
EditNoteDialog (MidiView* rv, std::set<NoteBase*> n);
void done (int);
private:
MidiRegionView* _region_view;
MidiView* _region_view;
std::set<NoteBase*> _events;
Gtk::SpinButton _channel;
Gtk::CheckButton _channel_all;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,614 @@
/*
* Copyright (C) 2005-2007 Doug McLain <doug@nostar.net>
* Copyright (C) 2005-2018 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2005 Karsten Wiese <fzuuzf@googlemail.com>
* Copyright (C) 2006-2009 Sampo Savolainen <v2@iki.fi>
* Copyright (C) 2006-2015 David Robillard <d@drobilla.net>
* Copyright (C) 2006-2017 Tim Mayberry <mojofunk@gmail.com>
* Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2008-2011 Sakari Bergen <sakari.bergen@beatwaves.net>
* Copyright (C) 2008 Hans Baier <hansfbaier@googlemail.com>
* Copyright (C) 2013-2015 Colin Fletcher <colin.m.fletcher@googlemail.com>
* Copyright (C) 2013-2019 Robin Gareus <robin@gareus.org>
* Copyright (C) 2014-2017 Nick Mainsbridge <mainsbridge@gmail.com>
* Copyright (C) 2014-2019 Ben Loftis <ben@harrisonconsoles.com>
* Copyright (C) 2015-2019 Damien Zammit <damien@zamaudio.com>
* Copyright (C) 2015 André Nusser <andre.nusser@googlemail.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.
*/
#ifndef __ardour_midi_editing_context_h__
#define __ardour_midi_editing_context_h__
#include <queue>
#include "pbd/signals.h"
#include "temporal/timeline.h"
#include "ardour/midi_operator.h"
#include "ardour/session_handle.h"
#include "ardour/types.h"
#include "widgets/ardour_button.h"
#include "widgets/ardour_dropdown.h"
#include "widgets/ardour_spacer.h"
#include "axis_provider.h"
#include "editing.h"
#include "editor_items.h"
#include "selection.h"
using ARDOUR::samplepos_t;
using ARDOUR::samplecnt_t;
namespace Temporal {
class TempoMap;
}
class XMLNode;
class CursorContext;
class DragManager;
class EditorCursor;
class EditNoteDialog;
class MidiRegionView;
class MidiView;
class MouseCursors;
class VerboseCursor;
class TrackViewList;
class Selection;
class SelectionMemento;
class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
{
public:
/** Context for mouse entry (stored in a stack). */
struct EnterContext {
ItemType item_type;
std::shared_ptr<CursorContext> cursor_ctx;
};
EditingContext (std::string const &);
~EditingContext ();
std::string editor_name() const { return _name; }
void set_session (ARDOUR::Session*);
Temporal::TimeDomain time_domain () const;
struct TempoMapScope {
TempoMapScope (EditingContext& context, std::shared_ptr<Temporal::TempoMap> map)
: ec (context)
{
old_map = ec.start_local_tempo_map (map);
}
~TempoMapScope () {
ec.end_local_tempo_map (old_map);
}
EditingContext& ec;
std::shared_ptr<Temporal::TempoMap const> old_map;
};
DragManager* drags () const {
return _drags;
}
bool drag_active () const;
bool preview_video_drag_active () const;
virtual ArdourCanvas::Duple upper_left() const { return ArdourCanvas::Duple (0, 0); }
virtual void select_all_within (Temporal::timepos_t const &, Temporal::timepos_t const &, double, double, TrackViewList const &, Selection::Operation, bool) = 0;
virtual void get_per_region_note_selection (std::list<std::pair<PBD::ID, std::set<std::shared_ptr<Evoral::Note<Temporal::Beats> > > > >&) const = 0;
virtual void get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const = 0;
virtual StripableTimeAxisView* get_stripable_time_axis_by_id (const PBD::ID& id) const = 0;
virtual TrackViewList axis_views_from_routes (std::shared_ptr<ARDOUR::RouteList>) const = 0;
virtual ARDOUR::Location* find_location_from_marker (ArdourMarker*, bool&) const = 0;
virtual ArdourMarker* find_marker_from_location_id (PBD::ID const&, bool) const = 0;
virtual TempoMarker* find_marker_for_tempo (Temporal::TempoPoint const &) = 0;
virtual MeterMarker* find_marker_for_meter (Temporal::MeterPoint const &) = 0;
EditorCursor* playhead_cursor () const { return _playhead_cursor; }
EditorCursor* snapped_cursor () const { return _snapped_cursor; }
virtual void maybe_autoscroll (bool, bool, bool from_headers) = 0;
virtual void stop_canvas_autoscroll () = 0;
virtual bool autoscroll_active() const = 0;
virtual void redisplay_grid (bool immediate_redraw) = 0;
virtual Temporal::timecnt_t get_nudge_distance (Temporal::timepos_t const & pos, Temporal::timecnt_t& next) const = 0;
Temporal::timecnt_t relative_distance (Temporal::timepos_t const & origin, Temporal::timecnt_t const & duration, Temporal::TimeDomain domain);
Temporal::timecnt_t snap_relative_time_to_relative_time (Temporal::timepos_t const & origin, Temporal::timecnt_t const & x, bool ensure_snap) const;
/** Set whether the editor should follow the playhead.
* @param yn true to follow playhead, otherwise false.
* @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
*/
void set_follow_playhead (bool yn, bool catch_up = true);
/** Toggle whether the editor is following the playhead */
void toggle_follow_playhead ();
/** @return true if the editor is following the playhead */
bool follow_playhead () const { return _follow_playhead; }
virtual void instant_save() = 0;
/** Get the topmost enter context for the given item type.
*
* This is used to change the cursor associated with a given enter context,
* which may not be on the top of the stack.
*/
virtual EnterContext* get_enter_context(ItemType type) = 0;
virtual void begin_selection_op_history () = 0;
virtual void begin_reversible_selection_op (std::string cmd_name) = 0;
virtual void commit_reversible_selection_op () = 0;
virtual void abort_reversible_selection_op () = 0;
virtual void undo_selection_op () = 0;
virtual void redo_selection_op () = 0;
virtual void begin_reversible_command (std::string cmd_name);
virtual void begin_reversible_command (GQuark);
virtual void abort_reversible_command ();
virtual void commit_reversible_command ();
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.
*/
samplepos_t pixel_to_sample_from_event (double pixel) const {
/* pixel can be less than zero when motion events are
processed. Since the pixel value is in canvas units (since
it comes from an event delivered to the canvas), we've
already run the window->canvas transform, 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 position for an event whose coordinates
* are in canvas units (pixels, scroll offset included). The time
* domain used by the return value will match ::default_time_domain()
* at the time of calling.
*/
Temporal::timepos_t canvas_event_time (GdkEvent const*, double* px = 0, double* py = 0) const;
/** computes the timeline sample (sample) of an event whose coordinates
* are in canvas units (pixels, scroll offset included).
*/
samplepos_t canvas_event_sample (GdkEvent const * event, double* pcx = nullptr, double* pcy = nullptr) const;
virtual bool canvas_note_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
virtual Temporal::Beats get_grid_type_as_beats (bool& success, Temporal::timepos_t const & position) const = 0;
virtual Temporal::Beats get_draw_length_as_beats (bool& success, Temporal::timepos_t const & position) const = 0;
virtual int32_t get_grid_beat_divisions (Editing::GridType gt) const = 0;
virtual int32_t get_grid_music_divisions (Editing::GridType gt, uint32_t event_state) const = 0;
Editing::GridType grid_type () const;
bool grid_type_is_musical (Editing::GridType) const;
bool grid_musical () const;
void cycle_snap_mode ();
void next_grid_choice ();
void prev_grid_choice ();
void set_grid_to (Editing::GridType);
void set_snap_mode (Editing::SnapMode);
void set_draw_length_to (Editing::GridType);
void set_draw_velocity_to (int);
void set_draw_channel_to (int);
Editing::GridType draw_length () const;
int draw_velocity () const;
int draw_channel () const;
Editing::SnapMode snap_mode () const;
virtual void snap_to (Temporal::timepos_t & first,
Temporal::RoundMode direction = Temporal::RoundNearest,
ARDOUR::SnapPref pref = ARDOUR::SnapToAny_Visual,
bool ensure_snap = false) const;
virtual 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) const;
virtual Temporal::timepos_t snap_to_bbt (Temporal::timepos_t const & start,
Temporal::RoundMode direction,
ARDOUR::SnapPref gpref) const;
virtual double get_y_origin () const = 0;
void reset_x_origin (samplepos_t);
void reset_y_origin (double);
void reset_zoom (samplecnt_t);
void set_samples_per_pixel (samplecnt_t);
virtual void on_samples_per_pixel_changed () {}
virtual void set_zoom_focus (Editing::ZoomFocus) = 0;
virtual Editing::ZoomFocus get_zoom_focus () const = 0;
virtual void reposition_and_zoom (samplepos_t, double) = 0;
sigc::signal<void> ZoomChanged;
virtual Selection& get_selection() const { return *selection; }
virtual Selection& get_cut_buffer () const { return *cut_buffer; }
/** Set the mouse mode (gain, object, range, timefx etc.)
* @param m Mouse mode (defined in editing_syms.h)
* @param force Perform the effects of the change even if no change is required
* (ie even if the current mouse mode is equal to @p m)
*/
virtual void set_mouse_mode (Editing::MouseMode, bool force = false);
/** Step the mouse mode onto the next or previous one.
* @param next true to move to the next, otherwise move to the previous
*/
virtual void step_mouse_mode (bool next) = 0;
/** @return The current mouse mode (gain, object, range, timefx etc.)
* (defined in editing_syms.h)
*/
Editing::MouseMode current_mouse_mode () const { return mouse_mode; }
/** @return Whether the current mouse mode is an "internal" editing mode. */
virtual bool internal_editing() const = 0;
virtual Gdk::Cursor* get_canvas_cursor () const;
static MouseCursors const* cursors () {
return _cursors;
}
virtual VerboseCursor* verbose_cursor () const {
return _verbose_cursor;
}
virtual void set_snapped_cursor_position (Temporal::timepos_t const & pos) = 0;
static sigc::signal<void> DropDownKeys;
PBD::Signal0<void> SnapChanged;
PBD::Signal0<void> MouseModeChanged;
/* MIDI actions, proxied to selected MidiRegionView(s) */
ARDOUR::Quantize* get_quantize_op ();
void apply_midi_note_edit_op (ARDOUR::MidiOperator& op, const RegionSelection& rs);
PBD::Command* apply_midi_note_edit_op_to_region (ARDOUR::MidiOperator& op, MidiView& mrv);
void midi_action (void (MidiView::*method)());
std::vector<MidiView*> filter_to_unique_midi_region_views (RegionSelection const & ms) const;
void quantize_region ();
void transform_region ();
void legatize_region (bool shrink_only);
void transpose_region ();
static void register_midi_actions (Gtkmm2ext::Bindings*);
ArdourCanvas::Rectangle* rubberband_rect;
virtual ArdourCanvas::Container* get_trackview_group () const = 0;
virtual ArdourCanvas::Container* get_noscroll_group() const = 0;
virtual ArdourCanvas::ScrollGroup* get_hscroll_group () const = 0;
virtual ArdourCanvas::ScrollGroup* get_cursor_scroll_group () const = 0;
virtual bool canvas_playhead_cursor_event (GdkEvent* event, ArdourCanvas::Item*) { return false; }
bool typed_event (ArdourCanvas::Item*, GdkEvent*, ItemType);
void set_horizontal_position (double);
double horizontal_position () const;
virtual samplecnt_t current_page_samples() const = 0;
virtual ArdourCanvas::GtkCanvasViewport* get_canvas_viewport() const = 0;
virtual ArdourCanvas::GtkCanvas* get_canvas() const = 0;
virtual size_t push_canvas_cursor (Gdk::Cursor*);
virtual void pop_canvas_cursor ();
virtual void mouse_mode_toggled (Editing::MouseMode) = 0;
bool on_velocity_scroll_event (GdkEventScroll*);
protected:
std::string _name;
static Glib::RefPtr<Gtk::ActionGroup> _midi_actions;
/* Cursor stuff. Do not use directly, use via CursorContext. */
friend class CursorContext;
std::vector<Gdk::Cursor*> _cursor_stack;
virtual void set_canvas_cursor (Gdk::Cursor*);
Editing::GridType pre_internal_grid_type;
Editing::SnapMode pre_internal_snap_mode;
Editing::GridType internal_grid_type;
Editing::SnapMode internal_snap_mode;
static std::vector<std::string> grid_type_strings;
Glib::RefPtr<Gtk::RadioAction> grid_type_action (Editing::GridType);
Glib::RefPtr<Gtk::RadioAction> snap_mode_action (Editing::SnapMode);
Glib::RefPtr<Gtk::RadioAction> draw_length_action (Editing::GridType);
Glib::RefPtr<Gtk::RadioAction> draw_velocity_action (int);
Glib::RefPtr<Gtk::RadioAction> draw_channel_action (int);
Editing::GridType _grid_type;
Editing::SnapMode _snap_mode;
Editing::GridType _draw_length;
int _draw_velocity;
int _draw_channel;
ArdourWidgets::ArdourDropdown grid_type_selector;
void build_grid_type_menu ();
ArdourWidgets::ArdourDropdown draw_length_selector;
ArdourWidgets::ArdourDropdown draw_velocity_selector;
ArdourWidgets::ArdourDropdown draw_channel_selector;
void build_draw_midi_menus ();
void grid_type_selection_done (Editing::GridType);
void snap_mode_selection_done (Editing::SnapMode);
void snap_mode_chosen (Editing::SnapMode);
void grid_type_chosen (Editing::GridType);
void draw_length_selection_done (Editing::GridType);
void draw_length_chosen (Editing::GridType);
static void _draw_length_chosen (Editing::GridType);
void draw_velocity_selection_done (int);
void draw_velocity_chosen (int);
static void _draw_velocity_chosen (int);
void draw_channel_selection_done (int);
void draw_channel_chosen (int);
static void _draw_channel_chosen (int);
DragManager* _drags;
ArdourWidgets::ArdourButton snap_mode_button;
bool snap_mode_button_clicked (GdkEventButton*);
virtual void mark_region_boundary_cache_dirty () {}
virtual void update_tempo_based_rulers () {};
virtual void show_rulers_for_grid () {};
samplepos_t _leftmost_sample;
/* playhead and edit cursor */
EditorCursor* _playhead_cursor;
EditorCursor* _snapped_cursor;
bool _follow_playhead;
virtual void reset_x_origin_to_follow_playhead () = 0;
/* selection process */
Selection* selection;
Selection* cut_buffer;
SelectionMemento* _selection_memento;
std::list<XMLNode*> before; /* used in *_reversible_command */
static MouseCursors* _cursors;
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) const;
virtual Temporal::timepos_t snap_to_grid (Temporal::timepos_t const & start,
Temporal::RoundMode direction,
ARDOUR::SnapPref gpref) const = 0;
virtual void snap_to_internal (Temporal::timepos_t& first,
Temporal::RoundMode direction = Temporal::RoundNearest,
ARDOUR::SnapPref gpref = ARDOUR::SnapToAny_Visual,
bool ensure_snap = false) const = 0;
void check_best_snap (Temporal::timepos_t const & presnap, Temporal::timepos_t &test, Temporal::timepos_t &dist, Temporal::timepos_t &best) const;
virtual double visible_canvas_width() const = 0;
enum BBTRulerScale {
bbt_show_many,
bbt_show_64,
bbt_show_16,
bbt_show_4,
bbt_show_1,
bbt_show_quarters,
bbt_show_eighths,
bbt_show_sixteenths,
bbt_show_thirtyseconds,
bbt_show_sixtyfourths,
bbt_show_onetwentyeighths
};
BBTRulerScale bbt_ruler_scale;
uint32_t bbt_bars;
uint32_t bbt_bar_helper_on;
uint32_t count_bars (Temporal::Beats const & start, Temporal::Beats const & end) const;
void compute_bbt_ruler_scale (samplepos_t lower, samplepos_t upper);
double _visible_canvas_width;
double _visible_canvas_height; ///< height of the visible area of the track canvas
QuantizeDialog* quantize_dialog;
friend class TempoMapScope;
virtual std::shared_ptr<Temporal::TempoMap const> start_local_tempo_map (std::shared_ptr<Temporal::TempoMap>);
virtual void end_local_tempo_map (std::shared_ptr<Temporal::TempoMap const>) { /* no-op by default */ }
virtual bool button_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType) = 0;
virtual bool button_press_handler_1 (ArdourCanvas::Item*, GdkEvent*, ItemType) = 0;
virtual bool button_press_handler_2 (ArdourCanvas::Item*, GdkEvent*, ItemType) = 0;
virtual bool button_release_handler (ArdourCanvas::Item*, GdkEvent*, ItemType) = 0;
virtual bool button_press_dispatch (GdkEventButton*) = 0;
virtual bool button_release_dispatch (GdkEventButton*) = 0;
virtual bool motion_handler (ArdourCanvas::Item*, GdkEvent*, bool from_autoscroll = false) = 0;
virtual bool enter_handler (ArdourCanvas::Item*, GdkEvent*, ItemType) = 0;
virtual bool leave_handler (ArdourCanvas::Item*, GdkEvent*, ItemType) = 0;
virtual bool key_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType) = 0;
virtual bool key_release_handler (ArdourCanvas::Item*, GdkEvent*, ItemType) = 0;
void popup_note_context_menu (ArdourCanvas::Item*, GdkEvent*);
Gtk::Menu _note_context_menu;
static Gtkmm2ext::Bindings* button_bindings;
XMLNode* button_settings () const;
virtual RegionSelection region_selection() = 0;
void edit_notes (MidiView*);
void note_edit_done (int, EditNoteDialog*);
void quantize_regions (const RegionSelection& rs);
void legatize_regions (const RegionSelection& rs, bool shrink_only);
void transform_regions (const RegionSelection& rs);
void transpose_regions (const RegionSelection& rs);
static EditingContext* current_editing_context();
static void push_editing_context (EditingContext*);
static void pop_editing_context ();
/** the adjustment that controls the overall editing vertical scroll position */
friend class EditorSummary;
Gtk::Adjustment vertical_adjustment;
Gtk::Adjustment horizontal_adjustment;
ArdourWidgets::ArdourButton mouse_select_button;
ArdourWidgets::ArdourButton mouse_timefx_button;
ArdourWidgets::ArdourButton mouse_grid_button;
ArdourWidgets::ArdourButton mouse_cut_button;
ArdourWidgets::ArdourButton mouse_move_button;
ArdourWidgets::ArdourButton mouse_draw_button;
ArdourWidgets::ArdourButton mouse_content_button;
Glib::RefPtr<Gtk::ActionGroup> editor_actions;
virtual void register_actions() = 0;
void register_grid_actions ();
Glib::RefPtr<Gtk::Action> get_mouse_mode_action (Editing::MouseMode m) const;
void register_mouse_mode_actions ();
void bind_mouse_mode_buttons ();
virtual void add_mouse_mode_actions (Glib::RefPtr<Gtk::ActionGroup>) {}
Gtk::HBox snap_box;
Gtk::HBox grid_box;
Gtk::HBox draw_box;
ArdourWidgets::ArdourVSpacer _grid_box_spacer;
ArdourWidgets::ArdourVSpacer _draw_box_spacer;
void pack_draw_box ();
void pack_snap_box ();
Gtkmm2ext::Bindings* bindings;
Editing::MouseMode mouse_mode;
void set_common_editing_state (XMLNode const & node);
void get_common_editing_state (XMLNode& node) const;
struct VisualChange {
enum Type {
TimeOrigin = 0x1,
ZoomLevel = 0x2,
YOrigin = 0x4,
VideoTimeline = 0x8
};
Type pending;
samplepos_t time_origin;
samplecnt_t samples_per_pixel;
double y_origin;
int idle_handler_id;
/** true if we are currently in the idle handler */
bool being_handled;
VisualChange() : pending ((VisualChange::Type) 0), time_origin (0), samples_per_pixel (0), idle_handler_id (-1), being_handled (false) {}
void add (Type t) {
pending = Type (pending | t);
}
};
VisualChange pending_visual_change;
bool visual_change_queued;
static int _idle_visual_changer (void* arg);
int idle_visual_changer ();
void ensure_visual_change_idle_handler ();
virtual void visual_changer (const VisualChange&) = 0;
sigc::connection autoscroll_connection;
bool autoscroll_horizontal_allowed;
bool autoscroll_vertical_allowed;
uint32_t autoscroll_cnt;
ArdourCanvas::Rect autoscroll_boundary;
private:
static std::queue<EditingContext*> ec_stack;
};
#endif /* __ardour_midi_editing_context_h__ */

File diff suppressed because it is too large Load Diff

View File

@ -52,7 +52,6 @@
#include "gtkmm2ext/dndtreeview.h"
#include "pbd/controllable.h"
#include "pbd/stateful.h"
#include "pbd/signals.h"
#include "ardour/import_status.h"
@ -135,6 +134,7 @@ class EditorSummary;
class GUIObjectState;
class ArdourMarker;
class MidiRegionView;
class MidiView;
class MidiExportDialog;
class MixerStrip;
class MouseCursors;
@ -173,8 +173,6 @@ public:
bool pending_locate_request() const { return _pending_locate_request; }
Temporal::TimeDomain default_time_domain() const;
samplepos_t leftmost_sample() const { return _leftmost_sample; }
samplecnt_t current_page_samples() const {
@ -186,41 +184,17 @@ public:
}
double trackviews_height () const;
void cycle_snap_mode ();
void next_grid_choice ();
void prev_grid_choice ();
void set_grid_to (Editing::GridType);
void set_snap_mode (Editing::SnapMode);
void set_draw_length_to (Editing::GridType);
void set_draw_velocity_to (int);
void set_draw_channel_to (int);
Editing::SnapMode snap_mode () const;
Editing::GridType grid_type () const;
bool grid_type_is_musical (Editing::GridType) const;
bool grid_musical () const;
bool on_velocity_scroll_event (GdkEventScroll*);
Editing::GridType draw_length () const;
int draw_velocity () const;
int draw_channel () const;
void undo (uint32_t n = 1);
void redo (uint32_t n = 1);
XMLNode& get_state () const;
int set_state (const XMLNode&, int version);
void set_mouse_mode (Editing::MouseMode, bool force = false);
void step_mouse_mode (bool next);
Editing::MouseMode current_mouse_mode () const { return mouse_mode; }
Editing::MidiEditMode current_midi_edit_mode () const;
void remove_midi_note (ArdourCanvas::Item*, GdkEvent*);
bool internal_editing() const;
void remove_midi_note (ArdourCanvas::Item*, GdkEvent*);
void foreach_time_axis_view (sigc::slot<void,TimeAxisView&>);
void add_to_idle_resize (TimeAxisView*, int32_t);
@ -246,44 +220,6 @@ public:
void separate_regions_using_location (ARDOUR::Location&);
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& get_selection() const { return *selection; }
@ -293,7 +229,6 @@ public:
void get_regionviews_at_or_after (Temporal::timepos_t const &, RegionSelection&);
void set_selection (std::list<Selectable*>, Selection::Operation);
void set_selected_midi_region_view (MidiRegionView&);
std::shared_ptr<ARDOUR::Route> current_mixer_stripable () const;
@ -346,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);
@ -381,14 +315,14 @@ public:
/* nudge is initiated by transport controls owned by ARDOUR_UI */
Temporal::timecnt_t get_nudge_distance (Temporal::timepos_t const & pos, Temporal::timecnt_t& next);
Temporal::timecnt_t get_nudge_distance (Temporal::timepos_t const & pos, Temporal::timecnt_t& next) const;
Temporal::timecnt_t get_paste_offset (Temporal::timepos_t const & pos, unsigned paste_count, Temporal::timecnt_t const & duration);
Temporal::Beats get_grid_type_as_beats (bool& success, Temporal::timepos_t const & position);
Temporal::Beats get_draw_length_as_beats (bool& success, Temporal::timepos_t const & position);
Temporal::Beats get_grid_type_as_beats (bool& success, Temporal::timepos_t const & position) const;
Temporal::Beats get_draw_length_as_beats (bool& success, Temporal::timepos_t const & position) const;
int32_t get_grid_beat_divisions (Editing::GridType gt);
int32_t get_grid_music_divisions (Editing::GridType gt, uint32_t event_state);
int32_t get_grid_beat_divisions (Editing::GridType gt) const;
int32_t get_grid_music_divisions (Editing::GridType gt, uint32_t event_state) const;
void nudge_forward (bool next, bool force_playhead);
void nudge_backward (bool next, bool force_playhead);
@ -406,9 +340,6 @@ public:
void toggle_stationary_playhead ();
bool stationary_playhead() const { return _stationary_playhead; }
void set_follow_playhead (bool yn, bool catch_up = true);
void toggle_follow_playhead ();
bool follow_playhead() const { return _follow_playhead; }
bool dragging_playhead () const { return _dragging_playhead; }
void toggle_zero_line_visibility ();
@ -453,12 +384,10 @@ public:
void restore_editing_space();
double get_y_origin () const;
void reset_x_origin (samplepos_t);
void reset_x_origin_to_follow_playhead ();
void reset_y_origin (double);
void reset_zoom (samplecnt_t);
void reposition_and_zoom (samplepos_t, double);
void reset_x_origin_to_follow_playhead ();
Temporal::timepos_t get_preferred_edit_position (Editing::EditIgnoreOption = Editing::EDIT_IGNORE_NONE,
bool use_context_click = false,
bool from_outside_canvas = false);
@ -501,21 +430,6 @@ public:
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 begin_selection_op_history ();
@ -524,49 +438,22 @@ public:
void abort_reversible_selection_op ();
void undo_selection_op ();
void redo_selection_op ();
void begin_reversible_command (std::string cmd_name);
void begin_reversible_command (GQuark);
void abort_reversible_command ();
void commit_reversible_command ();
MixerStrip* get_current_mixer_strip () const {
return current_mixer_strip;
}
DragManager* drags () const {
return _drags;
}
bool drag_active () const;
bool preview_video_drag_active () const;
void maybe_autoscroll (bool, bool, bool);
bool autoscroll_active() const;
Gdk::Cursor* get_canvas_cursor () const;
void set_current_trimmable (std::shared_ptr<ARDOUR::Trimmable>);
void set_current_movable (std::shared_ptr<ARDOUR::Movable>);
MouseCursors const* cursors () const {
return _cursors;
}
VerboseCursor* verbose_cursor () const {
return _verbose_cursor;
}
double clamp_verbose_cursor_x (double);
double clamp_verbose_cursor_y (double);
void get_pointer_position (double &, double &) const;
/** Context for mouse entry (stored in a stack). */
struct EnterContext {
ItemType item_type;
std::shared_ptr<CursorContext> cursor_ctx;
};
/** Get the topmost enter context for the given item type.
*
* This is used to change the cursor associated with a given enter context,
@ -589,7 +476,8 @@ public:
ArdourCanvas::ScrollGroup* get_cursor_scroll_group () const { return cursor_scroll_group; }
ArdourCanvas::Container* get_drag_motion_group () const { return _drag_motion_group; }
ArdourCanvas::GtkCanvasViewport* get_track_canvas () const;
ArdourCanvas::GtkCanvasViewport* get_canvas_viewport () const;
ArdourCanvas::GtkCanvas* get_canvas () const;
void override_visible_track_count ();
@ -642,11 +530,12 @@ protected:
void suspend_route_redisplay ();
void resume_route_redisplay ();
RegionSelection region_selection();
private:
void color_handler ();
bool constructed;
bool constructed;
// to keep track of the playhead position for control_scroll
boost::optional<samplepos_t> _control_scroll_target;
@ -678,18 +567,9 @@ private:
void start_visual_state_op (uint32_t n);
void cancel_visual_state_op (uint32_t n);
samplepos_t _leftmost_sample;
samplecnt_t samples_per_pixel;
Editing::ZoomFocus zoom_focus;
void set_samples_per_pixel (samplecnt_t);
void on_samples_per_pixel_changed ();
Editing::MouseMode mouse_mode;
Editing::GridType pre_internal_grid_type;
Editing::SnapMode pre_internal_snap_mode;
Editing::GridType internal_grid_type;
Editing::SnapMode internal_snap_mode;
Editing::MouseMode effective_mouse_mode () const;
Editing::MarkerClickBehavior marker_click_behavior;
@ -772,6 +652,8 @@ private:
void reparent_location_markers (LocationMarkers*, ArdourCanvas::Item*);
ArdourCanvas::Duple upper_left() const;
LocationMarkers* find_location_markers (ARDOUR::Location*) const;
ARDOUR::Location* find_location_from_marker (ArdourMarker*, bool& is_start) const;
ArdourMarker* find_marker_from_location_id (PBD::ID const&, bool) const;
@ -885,9 +767,6 @@ private:
void popup_control_point_context_menu (ArdourCanvas::Item*, GdkEvent*);
Gtk::Menu _control_point_context_menu;
void popup_note_context_menu (ArdourCanvas::Item*, GdkEvent*);
Gtk::Menu _note_context_menu;
void initial_display ();
void add_stripables (ARDOUR::StripableList&);
void add_routes (ARDOUR::RouteList&);
@ -897,13 +776,6 @@ private:
Gtk::HBox global_hpacker;
Gtk::VBox global_vpacker;
/* Cursor stuff. Do not use directly, use via CursorContext. */
friend class CursorContext;
std::vector<Gdk::Cursor*> _cursor_stack;
void set_canvas_cursor (Gdk::Cursor*);
size_t push_canvas_cursor (Gdk::Cursor*);
void pop_canvas_cursor ();
Gdk::Cursor* which_track_cursor () const;
Gdk::Cursor* which_mode_cursor () const;
Gdk::Cursor* which_trim_cursor (bool left_side) const;
@ -920,9 +792,6 @@ private:
bool within_track_canvas;
friend class VerboseCursor;
VerboseCursor* _verbose_cursor;
RegionPeakCursor* _region_peak_cursor;
void parameter_changed (std::string);
@ -1045,27 +914,6 @@ private:
samplecnt_t _samples_ruler_interval;
void set_samples_ruler_scale (samplepos_t, samplepos_t);
enum BBTRulerScale {
bbt_show_many,
bbt_show_64,
bbt_show_16,
bbt_show_4,
bbt_show_1,
bbt_show_quarters,
bbt_show_eighths,
bbt_show_sixteenths,
bbt_show_thirtyseconds,
bbt_show_sixtyfourths,
bbt_show_onetwentyeighths
};
BBTRulerScale bbt_ruler_scale;
uint32_t bbt_bars;
uint32_t bbt_bar_helper_on;
uint32_t count_bars (Temporal::Beats const & start, Temporal::Beats const & end) const;
void compute_bbt_ruler_scale (samplepos_t lower, samplepos_t upper);
ArdourCanvas::Ruler* timecode_ruler;
ArdourCanvas::Ruler* bbt_ruler;
ArdourCanvas::Ruler* samples_ruler;
@ -1123,9 +971,6 @@ private:
int get_videotl_bar_height () const { return videotl_bar_height; }
void toggle_region_video_lock ();
EditorCursor* playhead_cursor () const { return _playhead_cursor; }
EditorCursor* snapped_cursor () const { return _snapped_cursor; }
samplepos_t playhead_cursor_sample () const;
Temporal::timepos_t get_region_boundary (Temporal::timepos_t const & pos, int32_t dir, bool with_selection, bool only_onscreen);
@ -1167,10 +1012,6 @@ private:
Gtk::Table edit_packer;
/** the adjustment that controls the overall editor vertical scroll position */
Gtk::Adjustment vertical_adjustment;
Gtk::Adjustment horizontal_adjustment;
Gtk::Adjustment unused_adjustment; // yes, really; Gtk::Layout constructor requires refs
Gtk::Layout controls_layout;
bool control_layout_scroll (GdkEventScroll* ev);
@ -1189,8 +1030,6 @@ private:
sigc::connection _scroll_connection;
int _scroll_callbacks;
double _visible_canvas_width;
double _visible_canvas_height; ///< height of the visible area of the track canvas
double _full_canvas_height; ///< full height of the canvas
bool track_canvas_map_handler (GdkEventAny*);
@ -1219,41 +1058,10 @@ private:
sigc::connection control_scroll_connection;
void tie_vertical_scrolling ();
void set_horizontal_position (double);
double horizontal_position () const;
struct VisualChange {
enum Type {
TimeOrigin = 0x1,
ZoomLevel = 0x2,
YOrigin = 0x4,
VideoTimeline = 0x8
};
Type pending;
samplepos_t time_origin;
samplecnt_t samples_per_pixel;
double y_origin;
int idle_handler_id;
/** true if we are currently in the idle handler */
bool being_handled;
VisualChange() : pending ((VisualChange::Type) 0), time_origin (0), samples_per_pixel (0), idle_handler_id (-1), being_handled (false) {}
void add (Type t) {
pending = Type (pending | t);
}
};
VisualChange pending_visual_change;
bool visual_change_queued;
void pre_render ();
static int _idle_visual_changer (void* arg);
int idle_visual_changer ();
void visual_changer (const VisualChange&);
void ensure_visual_change_idle_handler ();
/* track views */
TrackViewList track_views;
@ -1297,12 +1105,10 @@ private:
std::weak_ptr<ARDOUR::Trimmable> _trimmable;
std::weak_ptr<ARDOUR::Movable> _movable;
bool typed_event (ArdourCanvas::Item*, GdkEvent*, ItemType);
bool button_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
bool button_press_handler_1 (ArdourCanvas::Item*, GdkEvent*, ItemType);
bool button_press_handler_2 (ArdourCanvas::Item*, GdkEvent*, ItemType);
bool button_release_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
bool button_double_click_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
bool button_press_dispatch (GdkEventButton*);
bool button_release_dispatch (GdkEventButton*);
bool motion_handler (ArdourCanvas::Item*, GdkEvent*, bool from_autoscroll = false);
@ -1311,14 +1117,10 @@ private:
bool key_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
bool key_release_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
Gtkmm2ext::Bindings* button_bindings;
XMLNode* button_settings () const;
/* KEYMAP HANDLING */
void register_actions ();
void register_region_actions ();
void register_midi_actions (Gtkmm2ext::Bindings*);
void load_bindings ();
@ -1393,19 +1195,9 @@ private:
void normalize_region ();
void adjust_region_gain (bool up);
void reset_region_gain ();
ARDOUR::Quantize* get_quantize_op ();
void apply_midi_note_edit_op (ARDOUR::MidiOperator& op, const RegionSelection& rs);
void set_tempo_curve_range (double& max, double& min) const;
void quantize_region ();
void quantize_regions (const RegionSelection& rs);
void legatize_region (bool shrink_only);
void legatize_regions (const RegionSelection& rs, bool shrink_only);
void deinterlace_midi_regions (const RegionSelection& rs);
void deinterlace_selected_midi_regions ();
void transform_region ();
void transform_regions (const RegionSelection& rs);
void transpose_region ();
void transpose_regions (const RegionSelection& rs);
void set_tempo_curve_range (double& max, double& min) const;
void insert_patch_change (bool from_context);
void fork_selected_regions ();
void fork_regions_from_unselected ();
@ -1660,17 +1452,8 @@ private:
void move_range_selection_start_or_end_to_region_boundary (bool, bool);
Editing::GridType _grid_type;
Editing::SnapMode _snap_mode;
Editing::GridType _draw_length;
int _draw_velocity;
int _draw_channel;
bool ignore_gui_changes;
DragManager* _drags;
void escape ();
void lock ();
void unlock ();
@ -1788,6 +1571,7 @@ private:
void mid_tempo_change (MidTempoChanges);
Editing::EditPoint edit_point() const { return _edit_point; }
bool canvas_playhead_cursor_event (GdkEvent* event, ArdourCanvas::Item*);
protected:
void _commit_tempo_map_edit (Temporal::TempoMap::WritableSharedPtr&, bool with_update = false);
@ -1802,7 +1586,6 @@ private:
/* non-public event handlers */
bool canvas_section_box_event (GdkEvent* event);
bool canvas_playhead_cursor_event (GdkEvent* event, ArdourCanvas::Item*);
bool track_canvas_scroll (GdkEventScroll* event);
bool track_canvas_button_press_event (GdkEventButton* event);
@ -1828,8 +1611,6 @@ private:
/* display control */
/// true if the editor should follow the playhead, otherwise false
bool _follow_playhead;
/// true if we scroll the tracks rather than the playhead
bool _stationary_playhead;
/// true if we are in fullscreen mode
@ -1857,7 +1638,6 @@ private:
void edit_meter_marker (MeterMarker&);
void edit_bbt_marker (BBTMarker&);
void edit_control_point (ArdourCanvas::Item*);
void edit_notes (MidiRegionView*);
void edit_region (RegionView*);
void edit_current_meter ();
@ -1966,25 +1746,17 @@ private:
Gtk::Table toolbar_selection_clock_table;
Gtk::Label toolbar_selection_cursor_label;
ArdourWidgets::ArdourButton mouse_select_button;
ArdourWidgets::ArdourButton mouse_draw_button;
ArdourWidgets::ArdourButton mouse_move_button;
ArdourWidgets::ArdourButton mouse_timefx_button;
ArdourWidgets::ArdourButton mouse_grid_button;
ArdourWidgets::ArdourButton mouse_content_button;
ArdourWidgets::ArdourButton mouse_cut_button;
ArdourWidgets::ArdourButton smart_mode_button;
Glib::RefPtr<Gtk::ToggleAction> smart_mode_action;
void add_mouse_mode_actions (Glib::RefPtr<Gtk::ActionGroup>);
void mouse_mode_toggled (Editing::MouseMode m);
void mouse_mode_object_range_toggled ();
bool ignore_mouse_mode_toggle;
bool mouse_select_button_release (GdkEventButton*);
Glib::RefPtr<Gtk::Action> get_mouse_mode_action (Editing::MouseMode m) const;
Gtk::VBox automation_box;
Gtk::Button automation_mode_button;
@ -2001,13 +1773,6 @@ private:
void set_edit_mode (ARDOUR::EditMode);
void cycle_edit_mode ();
ArdourWidgets::ArdourDropdown grid_type_selector;
void build_grid_type_menu ();
ArdourWidgets::ArdourDropdown draw_length_selector;
ArdourWidgets::ArdourDropdown draw_velocity_selector;
ArdourWidgets::ArdourDropdown draw_channel_selector;
void build_draw_midi_menus ();
Gtk::CheckButton stretch_marker_cb;
@ -2015,45 +1780,11 @@ private:
return stretch_marker_cb.get_active ();
}
ArdourWidgets::ArdourButton snap_mode_button;
bool snap_mode_button_clicked (GdkEventButton*);
Gtk::HBox snap_box;
Gtk::HBox grid_box;
Gtk::HBox draw_box;
ArdourWidgets::ArdourVSpacer _grid_box_spacer;
ArdourWidgets::ArdourVSpacer _draw_box_spacer;
Gtk::HBox ebox_hpacker;
Gtk::VBox ebox_vpacker;
Gtk::HBox _box;
std::vector<std::string> grid_type_strings;
std::vector<std::string> snap_mode_strings;
void grid_type_selection_done (Editing::GridType);
void snap_mode_selection_done (Editing::SnapMode);
void snap_mode_chosen (Editing::SnapMode);
void grid_type_chosen (Editing::GridType);
void draw_length_selection_done (Editing::GridType);
void draw_length_chosen (Editing::GridType);
void draw_velocity_selection_done (int);
void draw_velocity_chosen (int);
void draw_channel_selection_done (int);
void draw_channel_chosen (int);
Glib::RefPtr<Gtk::RadioAction> grid_type_action (Editing::GridType);
Glib::RefPtr<Gtk::RadioAction> snap_mode_action (Editing::SnapMode);
Glib::RefPtr<Gtk::RadioAction> draw_length_action (Editing::GridType);
Glib::RefPtr<Gtk::RadioAction> draw_velocity_action (int);
Glib::RefPtr<Gtk::RadioAction> draw_channel_action (int);
//zoom focus menu stuff
ArdourWidgets::ArdourDropdown zoom_focus_selector;
void zoom_focus_selection_done (Editing::ZoomFocus);
@ -2082,12 +1813,6 @@ private:
void setup_midi_toolbar ();
/* selection process */
Selection* selection;
Selection* cut_buffer;
SelectionMemento* _selection_memento;
void time_selection_changed ();
void track_selection_changed ();
void update_time_selection_display ();
@ -2120,11 +1845,6 @@ private:
SectionBox* _section_box;
/* playhead and edit cursor */
EditorCursor* _playhead_cursor;
EditorCursor* _snapped_cursor;
/* transport range select process */
ArdourCanvas::Rectangle* cd_marker_bar_drag_rect;
@ -2150,8 +1870,6 @@ private:
void select_all_within (Temporal::timepos_t const &, Temporal::timepos_t const &, double, double, TrackViewList const &, Selection::Operation, bool);
ArdourCanvas::Rectangle* rubberband_rect;
EditorRouteGroups* _route_groups;
EditorRoutes* _routes;
EditorRegions* _regions;
@ -2168,13 +1886,6 @@ private:
/* autoscrolling */
sigc::connection autoscroll_connection;
bool autoscroll_horizontal_allowed;
bool autoscroll_vertical_allowed;
uint32_t autoscroll_cnt;
Gtk::Widget* autoscroll_widget;
ArdourCanvas::Rect autoscroll_boundary;
bool autoscroll_canvas ();
void start_canvas_autoscroll (bool allow_horiz, bool allow_vert, const ArdourCanvas::Rect& boundary);
void stop_canvas_autoscroll ();
@ -2246,7 +1957,6 @@ private:
uint32_t selection_op_history_it;
std::list<XMLNode*> selection_op_history; /* used in *_reversible_selection_op */
std::list<XMLNode*> before; /* used in *_reversible_command */
void update_title ();
void update_title_s (const std::string & snapshot_name);
@ -2270,18 +1980,6 @@ private:
void duplicate_range (bool with_dialog);
void duplicate_regions (float times);
/** computes the timeline sample (sample) of an event whose coordinates
* are in canvas units (pixels, scroll offset included).
*/
samplepos_t canvas_event_sample (GdkEvent const*, double* px = 0, double* py = 0) const;
/** computes the timeline position for an event whose coordinates
* are in canvas units (pixels, scroll offset included). The time
* domain used by the return value will match ::default_time_domain()
* at the time of calling.
*/
Temporal::timepos_t canvas_event_time (GdkEvent const*, double* px = 0, double* py = 0) const;
/** computes the timeline sample (sample) of an event whose coordinates
* are in window units (pixels, no scroll offset).
*/
@ -2332,8 +2030,6 @@ private:
void apply_filter (ARDOUR::Filter&, std::string cmd, ProgressReporter* progress = 0);
PBD::Command* apply_midi_note_edit_op_to_region (ARDOUR::MidiOperator& op, MidiRegionView& mrv);
/* plugin setup */
int plugin_setup (std::shared_ptr<ARDOUR::Route>, std::shared_ptr<ARDOUR::PluginInsert>, ARDOUR::Route::PluginSetupOptions);
@ -2420,36 +2116,29 @@ private:
Temporal::timepos_t snap_to_minsec (Temporal::timepos_t const & start,
Temporal::RoundMode direction,
ARDOUR::SnapPref gpref);
ARDOUR::SnapPref gpref) const;
Temporal::timepos_t snap_to_cd_frames (Temporal::timepos_t const & start,
Temporal::RoundMode direction,
ARDOUR::SnapPref gpref);
ARDOUR::SnapPref gpref) const;
Temporal::timepos_t snap_to_timecode (Temporal::timepos_t const & start,
Temporal::RoundMode direction,
ARDOUR::SnapPref gpref);
ARDOUR::SnapPref gpref) const;
Temporal::timepos_t snap_to_grid (Temporal::timepos_t const & start,
Temporal::RoundMode direction,
ARDOUR::SnapPref gpref);
ARDOUR::SnapPref gpref) const;
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,
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,
Temporal::RoundMode direction = Temporal::RoundNearest,
bool for_mark = false);
bool for_mark = false) const;
Temporal::timepos_t snap_to_marker (Temporal::timepos_t const & presnap,
Temporal::RoundMode direction = Temporal::RoundNearest);
Temporal::RoundMode direction = Temporal::RoundNearest) const;
double visible_canvas_width() const { return _visible_canvas_width; }
RhythmFerret* rhythm_ferret;
@ -2518,8 +2207,6 @@ private:
Gtk::MenuItem& action_menu_item (std::string const &);
void action_pre_activated (Glib::RefPtr<Gtk::Action> const &);
MouseCursors* _cursors;
void follow_mixer_selection ();
bool _following_mixer_selection;
@ -2529,7 +2216,6 @@ private:
bool _show_touched_automation;
int time_fx (ARDOUR::RegionList&, Temporal::ratio_t ratio, bool pitching, bool fixed_end);
void note_edit_done (int, EditNoteDialog*);
void toggle_sound_midi_notes ();
/** Flag for a bit of a hack wrt control point selection; see set_selected_control_point_from_click */
@ -2551,13 +2237,8 @@ private:
void update_bring_in_message (Gtk::Label* label, uint32_t n, uint32_t total, std::string name);
void bring_all_sources_into_session ();
QuantizeDialog* quantize_dialog;
MainMenuDisabler* _main_menu_disabler;
/* MIDI actions, proxied to selected MidiRegionView(s) */
void midi_action (void (MidiRegionView::*method)());
std::vector<MidiRegionView*> filter_to_unique_midi_region_views (RegionSelection const & ms) const;
/* private helper functions to help with registering region actions */
Glib::RefPtr<Gtk::Action> register_region_action (Glib::RefPtr<Gtk::ActionGroup> group, Editing::RegionActionTarget, char const* name, char const* label, sigc::slot<void> slot);

View File

@ -118,7 +118,7 @@ Editor::register_actions ()
{
RefPtr<Action> act;
editor_actions = ActionManager::create_action_group (bindings, X_("Editor"));
editor_actions = ActionManager::create_action_group (bindings, editor_name());
editor_menu_actions = ActionManager::create_action_group (bindings, X_("EditorMenu"));
/* non-operative menu items for menu bar */
@ -575,49 +575,8 @@ Editor::register_actions ()
act->set_sensitive (false);
}
Glib::RefPtr<ActionGroup> mouse_mode_actions = ActionManager::create_action_group (bindings, X_("MouseMode"));
RadioAction::Group mouse_mode_group;
act = ActionManager::register_toggle_action (mouse_mode_actions, "set-mouse-mode-object-range", _("Smart Mode"), sigc::mem_fun (*this, &Editor::mouse_mode_object_range_toggled));
smart_mode_action = Glib::RefPtr<ToggleAction>::cast_static (act);
smart_mode_button.set_related_action (smart_mode_action);
smart_mode_button.set_text (_("Smart"));
smart_mode_button.set_name ("mouse mode button");
act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-object", _("Grab (Object Tool)"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
mouse_move_button.set_related_action (act);
mouse_move_button.set_icon (ArdourWidgets::ArdourIcon::ToolGrab);
mouse_move_button.set_name ("mouse mode button");
act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-range", _("Range Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
mouse_select_button.set_related_action (act);
mouse_select_button.set_icon (ArdourWidgets::ArdourIcon::ToolRange);
mouse_select_button.set_name ("mouse mode button");
act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-draw", _("Note Drawing Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseDraw));
mouse_draw_button.set_related_action (act);
mouse_draw_button.set_icon (ArdourWidgets::ArdourIcon::ToolDraw);
mouse_draw_button.set_name ("mouse mode button");
act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-timefx", _("Time FX Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
mouse_timefx_button.set_related_action (act);
mouse_timefx_button.set_icon (ArdourWidgets::ArdourIcon::ToolStretch);
mouse_timefx_button.set_name ("mouse mode button");
act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-grid", _("Grid Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGrid));
mouse_grid_button.set_related_action (act);
mouse_grid_button.set_icon (ArdourWidgets::ArdourIcon::ToolGrid);
mouse_grid_button.set_name ("mouse mode button");
act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-content", _("Internal Edit (Content Tool)"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseContent));
mouse_content_button.set_related_action (act);
mouse_content_button.set_icon (ArdourWidgets::ArdourIcon::ToolContent);
mouse_content_button.set_name ("mouse mode button");
act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-cut", _("Cut Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseCut));
mouse_cut_button.set_related_action (act);
mouse_cut_button.set_icon (ArdourWidgets::ArdourIcon::ToolCut);
mouse_cut_button.set_name ("mouse mode button");
register_mouse_mode_actions ();
bind_mouse_mode_buttons ();
ActionManager::register_action (editor_actions, "step-mouse-mode", _("Step Mouse Mode"), sigc::bind (sigc::mem_fun(*this, &Editor::step_mouse_mode), true));
@ -638,48 +597,7 @@ Editor::register_actions ()
ActionManager::register_action (editor_actions, "set-ripple-all", _("All"), sigc::bind (sigc::mem_fun (*this, &Editor::set_ripple_mode), RippleAll));
ActionManager::register_action (editor_actions, "set-ripple-interview", S_("Interview"), sigc::bind (sigc::mem_fun (*this, &Editor::set_ripple_mode), RippleInterview));
ActionManager::register_action (editor_actions, X_("GridChoice"), _("Snap & Grid"));
RadioAction::Group snap_mode_group;
/* deprecated */ ActionManager::register_radio_action (editor_actions, snap_mode_group, X_("snap-off"), _("No Grid"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_chosen), Editing::SnapOff)));
/* deprecated */ ActionManager::register_radio_action (editor_actions, snap_mode_group, X_("snap-normal"), _("Grid"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_chosen), Editing::SnapNormal))); //deprecated
/* deprecated */ ActionManager::register_radio_action (editor_actions, snap_mode_group, X_("snap-magnetic"), _("Magnetic"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_chosen), Editing::SnapMagnetic)));
snap_mode_button.set_text (_("Snap"));
snap_mode_button.set_name ("mouse mode button");
snap_mode_button.signal_button_press_event().connect (sigc::mem_fun (*this, &Editor::snap_mode_button_clicked), false);
ActionManager::register_action (editor_actions, X_("cycle-snap-mode"), _("Toggle Snap"), sigc::mem_fun (*this, &Editor::cycle_snap_mode));
ActionManager::register_action (editor_actions, X_("next-grid-choice"), _("Next Quantize Grid Choice"), sigc::mem_fun (*this, &Editor::next_grid_choice));
ActionManager::register_action (editor_actions, X_("prev-grid-choice"), _("Previous Quantize Grid Choice"), sigc::mem_fun (*this, &Editor::prev_grid_choice));
Glib::RefPtr<ActionGroup> snap_actions = ActionManager::create_action_group (bindings, X_("Snap"));
RadioAction::Group grid_choice_group;
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-thirtyseconds"), grid_type_strings[(int)GridTypeBeatDiv32].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv32)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-twentyeighths"), grid_type_strings[(int)GridTypeBeatDiv28].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv28)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-twentyfourths"), grid_type_strings[(int)GridTypeBeatDiv24].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv24)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-twentieths"), grid_type_strings[(int)GridTypeBeatDiv20].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv20)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-asixteenthbeat"), grid_type_strings[(int)GridTypeBeatDiv16].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv16)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-fourteenths"), grid_type_strings[(int)GridTypeBeatDiv14].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv14)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-twelfths"), grid_type_strings[(int)GridTypeBeatDiv12].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv12)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-tenths"), grid_type_strings[(int)GridTypeBeatDiv10].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv10)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-eighths"), grid_type_strings[(int)GridTypeBeatDiv8].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv8)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-sevenths"), grid_type_strings[(int)GridTypeBeatDiv7].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv7)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-sixths"), grid_type_strings[(int)GridTypeBeatDiv6].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv6)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-fifths"), grid_type_strings[(int)GridTypeBeatDiv5].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv5)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-quarters"), grid_type_strings[(int)GridTypeBeatDiv4].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv4)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-thirds"), grid_type_strings[(int)GridTypeBeatDiv3].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv3)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-halves"), grid_type_strings[(int)GridTypeBeatDiv2].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv2)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-timecode"), grid_type_strings[(int)GridTypeTimecode].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeTimecode)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-minsec"), grid_type_strings[(int)GridTypeMinSec].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeMinSec)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-cdframe"), grid_type_strings[(int)GridTypeCDFrame].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeCDFrame)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-beat"), grid_type_strings[(int)GridTypeBeat].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeat)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-bar"), grid_type_strings[(int)GridTypeBar].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBar)));
ActionManager::register_radio_action (snap_actions, grid_choice_group, X_("grid-type-none"), grid_type_strings[(int)GridTypeNone].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeNone)));
register_grid_actions ();
ActionManager::register_toggle_action (editor_actions, X_("show-marker-lines"), _("Show Marker Lines"), sigc::mem_fun (*this, &Editor::toggle_marker_lines));
@ -789,134 +707,6 @@ Editor::register_actions ()
reg_sens (editor_actions, "quantize", _("Quantize"), sigc::mem_fun (*this, &Editor::quantize_region));
}
void
Editor::register_midi_actions (Bindings* midi_bindings)
{
_midi_actions = ActionManager::create_action_group (midi_bindings, X_("Notes"));
/* two versions to allow same action for Delete and Backspace */
ActionManager::register_action (_midi_actions, X_("clear-selection"), _("Clear Note Selection"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::clear_note_selection));
ActionManager::register_action (_midi_actions, X_("invert-selection"), _("Invert Note Selection"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::invert_selection));
ActionManager::register_action (_midi_actions, X_("extend-selection"), _("Extend Note Selection"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::extend_selection));
ActionManager::register_action (_midi_actions, X_("duplicate-selection"), _("Duplicate Note Selection"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::duplicate_selection));
/* Lengthen */
ActionManager::register_action (_midi_actions, X_("move-starts-earlier-fine"), _("Move Note Start Earlier (fine)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::move_note_starts_earlier_fine));
ActionManager::register_action (_midi_actions, X_("move-starts-earlier"), _("Move Note Start Earlier"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::move_note_starts_earlier));
ActionManager::register_action (_midi_actions, X_("move-ends-later-fine"), _("Move Note Ends Later (fine)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::move_note_ends_later_fine));
ActionManager::register_action (_midi_actions, X_("move-ends-later"), _("Move Note Ends Later"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::move_note_ends_later));
/* Shorten */
ActionManager::register_action (_midi_actions, X_("move-starts-later-fine"), _("Move Note Start Later (fine)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::move_note_starts_later_fine));
ActionManager::register_action (_midi_actions, X_("move-starts-later"), _("Move Note Start Later"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::move_note_starts_later));
ActionManager::register_action (_midi_actions, X_("move-ends-earlier-fine"), _("Move Note Ends Earlier (fine)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::move_note_ends_earlier_fine));
ActionManager::register_action (_midi_actions, X_("move-ends-earlier"), _("Move Note Ends Earlier"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::move_note_ends_earlier));
/* Alt versions allow bindings for both Tab and ISO_Left_Tab, if desired */
ActionManager::register_action (_midi_actions, X_("select-next"), _("Select Next"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::select_next_note));
ActionManager::register_action (_midi_actions, X_("alt-select-next"), _("Select Next (alternate)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::select_next_note));
ActionManager::register_action (_midi_actions, X_("select-previous"), _("Select Previous"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::select_previous_note));
ActionManager::register_action (_midi_actions, X_("alt-select-previous"), _("Select Previous (alternate)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::select_previous_note));
ActionManager::register_action (_midi_actions, X_("add-select-next"), _("Add Next to Selection"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::add_select_next_note));
ActionManager::register_action (_midi_actions, X_("alt-add-select-next"), _("Add Next to Selection (alternate)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::add_select_next_note));
ActionManager::register_action (_midi_actions, X_("add-select-previous"), _("Add Previous to Selection"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::add_select_previous_note));
ActionManager::register_action (_midi_actions, X_("alt-add-select-previous"), _("Add Previous to Selection (alternate)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::add_select_previous_note));
ActionManager::register_action (_midi_actions, X_("increase-velocity"), _("Increase Velocity"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::increase_note_velocity));
ActionManager::register_action (_midi_actions, X_("increase-velocity-fine"), _("Increase Velocity (fine)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::increase_note_velocity_fine));
ActionManager::register_action (_midi_actions, X_("increase-velocity-smush"), _("Increase Velocity (allow mush)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::increase_note_velocity_smush));
ActionManager::register_action (_midi_actions, X_("increase-velocity-together"), _("Increase Velocity (non-relative)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::increase_note_velocity_together));
ActionManager::register_action (_midi_actions, X_("increase-velocity-fine-smush"), _("Increase Velocity (fine, allow mush)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::increase_note_velocity_fine_smush));
ActionManager::register_action (_midi_actions, X_("increase-velocity-fine-together"), _("Increase Velocity (fine, non-relative)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::increase_note_velocity_fine_together));
ActionManager::register_action (_midi_actions, X_("increase-velocity-smush-together"), _("Increase Velocity (maintain ratios, allow mush)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::increase_note_velocity_smush_together));
ActionManager::register_action (_midi_actions, X_("increase-velocity-fine-smush-together"), _("Increase Velocity (fine, allow mush, non-relative)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::increase_note_velocity_fine_smush_together));
ActionManager::register_action (_midi_actions, X_("decrease-velocity"), _("Decrease Velocity"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::decrease_note_velocity));
ActionManager::register_action (_midi_actions, X_("decrease-velocity-fine"), _("Decrease Velocity (fine)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::decrease_note_velocity_fine));
ActionManager::register_action (_midi_actions, X_("decrease-velocity-smush"), _("Decrease Velocity (allow mush)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::decrease_note_velocity_smush));
ActionManager::register_action (_midi_actions, X_("decrease-velocity-together"), _("Decrease Velocity (non-relative)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::decrease_note_velocity_together));
ActionManager::register_action (_midi_actions, X_("decrease-velocity-fine-smush"), _("Decrease Velocity (fine, allow mush)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::decrease_note_velocity_fine_smush));
ActionManager::register_action (_midi_actions, X_("decrease-velocity-fine-together"), _("Decrease Velocity (fine, non-relative)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::decrease_note_velocity_fine_together));
ActionManager::register_action (_midi_actions, X_("decrease-velocity-smush-together"), _("Decrease Velocity (maintain ratios, allow mush)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::decrease_note_velocity_smush_together));
ActionManager::register_action (_midi_actions, X_("decrease-velocity-fine-smush-together"), _("Decrease Velocity (fine, allow mush, non-relative)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::decrease_note_velocity_fine_smush_together));
ActionManager::register_action (_midi_actions, X_("transpose-up-octave"), _("Transpose Up (octave)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::transpose_up_octave));
ActionManager::register_action (_midi_actions, X_("transpose-up-octave-smush"), _("Transpose Up (octave, allow mush)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::transpose_up_octave_smush));
ActionManager::register_action (_midi_actions, X_("transpose-up-semitone"), _("Transpose Up (semitone)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::transpose_up_tone));
ActionManager::register_action (_midi_actions, X_("transpose-up-semitone-smush"), _("Transpose Up (semitone, allow mush)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::transpose_up_octave_smush));
ActionManager::register_action (_midi_actions, X_("transpose-down-octave"), _("Transpose Down (octave)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::transpose_down_octave));
ActionManager::register_action (_midi_actions, X_("transpose-down-octave-smush"), _("Transpose Down (octave, allow mush)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::transpose_down_octave_smush));
ActionManager::register_action (_midi_actions, X_("transpose-down-semitone"), _("Transpose Down (semitone)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::transpose_down_tone));
ActionManager::register_action (_midi_actions, X_("transpose-down-semitone-smush"), _("Transpose Down (semitone, allow mush)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::transpose_down_octave_smush));
ActionManager::register_action (_midi_actions, X_("nudge-later"), _("Nudge Notes Later (grid)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::nudge_notes_later));
ActionManager::register_action (_midi_actions, X_("nudge-later-fine"), _("Nudge Notes Later (1/4 grid)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::nudge_notes_later_fine));
ActionManager::register_action (_midi_actions, X_("nudge-earlier"), _("Nudge Notes Earlier (grid)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::nudge_notes_earlier));
ActionManager::register_action (_midi_actions, X_("nudge-earlier-fine"), _("Nudge Notes Earlier (1/4 grid)"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::nudge_notes_earlier_fine));
ActionManager::register_action (_midi_actions, X_("edit-channels"), _("Edit Note Channels"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::channel_edit));
ActionManager::register_action (_midi_actions, X_("edit-velocities"), _("Edit Note Velocities"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::velocity_edit));
ActionManager::register_action (_midi_actions, X_("quantize-selected-notes"), _("Quantize Selected Notes"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::quantize_selected_notes));
ActionManager::register_action (_midi_actions, X_("split-notes-grid"), _("Split Selected Notes on grid boundaries"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::split_notes_grid));
ActionManager::register_action (_midi_actions, X_("split-notes-more"), _("Split Selected Notes into more pieces"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::split_notes_more));
ActionManager::register_action (_midi_actions, X_("split-notes-less"), _("Split Selected Notes into less pieces"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::split_notes_less));
ActionManager::register_action (_midi_actions, X_("join-notes"), _("Join Selected Notes"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::join_notes));
Glib::RefPtr<ActionGroup> length_actions = ActionManager::create_action_group (midi_bindings, X_("DrawLength"));
RadioAction::Group draw_length_group;
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-thirtyseconds"), grid_type_strings[(int)GridTypeBeatDiv32].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBeatDiv32)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-twentyeighths"), grid_type_strings[(int)GridTypeBeatDiv28].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBeatDiv28)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-twentyfourths"), grid_type_strings[(int)GridTypeBeatDiv24].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBeatDiv24)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-twentieths"), grid_type_strings[(int)GridTypeBeatDiv20].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBeatDiv20)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-asixteenthbeat"), grid_type_strings[(int)GridTypeBeatDiv16].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBeatDiv16)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-fourteenths"), grid_type_strings[(int)GridTypeBeatDiv14].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBeatDiv14)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-twelfths"), grid_type_strings[(int)GridTypeBeatDiv12].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBeatDiv12)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-tenths"), grid_type_strings[(int)GridTypeBeatDiv10].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBeatDiv10)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-eighths"), grid_type_strings[(int)GridTypeBeatDiv8].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBeatDiv8)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-sevenths"), grid_type_strings[(int)GridTypeBeatDiv7].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBeatDiv7)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-sixths"), grid_type_strings[(int)GridTypeBeatDiv6].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBeatDiv6)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-fifths"), grid_type_strings[(int)GridTypeBeatDiv5].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBeatDiv5)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-quarters"), grid_type_strings[(int)GridTypeBeatDiv4].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBeatDiv4)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-thirds"), grid_type_strings[(int)GridTypeBeatDiv3].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBeatDiv3)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-halves"), grid_type_strings[(int)GridTypeBeatDiv2].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBeatDiv2)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-beat"), grid_type_strings[(int)GridTypeBeat].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBeat)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-bar"), grid_type_strings[(int)GridTypeBar].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBar)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-auto"), _("Auto"), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), DRAW_LEN_AUTO)));
Glib::RefPtr<ActionGroup> velocity_actions = ActionManager::create_action_group (midi_bindings, _("Draw Velocity"));
RadioAction::Group draw_velocity_group;
ActionManager::register_radio_action (velocity_actions, draw_velocity_group, X_("draw-velocity-auto"), _("Auto"), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_velocity_chosen), DRAW_VEL_AUTO)));
for (int i = 1; i <= 127; i++) {
char buf[64];
sprintf(buf, X_("draw-velocity-%d"), i);
char vel[64];
sprintf(vel, _("Velocity %d"), i);
ActionManager::register_radio_action (velocity_actions, draw_velocity_group, buf, vel, (sigc::bind (sigc::mem_fun(*this, &Editor::draw_velocity_chosen), i)));
}
Glib::RefPtr<ActionGroup> channel_actions = ActionManager::create_action_group (midi_bindings, _("Draw Channel"));
RadioAction::Group draw_channel_group;
ActionManager::register_radio_action (channel_actions, draw_channel_group, X_("draw-channel-auto"), _("Auto"), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_channel_chosen), DRAW_CHAN_AUTO)));
for (int i = 0; i <= 15; i++) {
char buf[64];
sprintf(buf, X_("draw-channel-%d"), i+1);
char ch[64];
sprintf(ch, X_("Channel %d"), i+1);
ActionManager::register_radio_action (channel_actions, draw_channel_group, buf, ch, (sigc::bind (sigc::mem_fun(*this, &Editor::draw_channel_chosen), i)));
}
ActionManager::set_sensitive (_midi_actions, false);
}
static void _lua_print (std::string s) {
#ifndef NDEBUG
std::cout << "LuaInstance: " << s << "\n";
@ -984,7 +774,7 @@ Editor::trigger_script_by_name (const std::string script_name, const std::string
void
Editor::load_bindings ()
{
bindings = Bindings::get_bindings (X_("Editor"));
bindings = Bindings::get_bindings (editor_name());
global_hpacker.set_data ("ardour-bindings", bindings);
/* This set of bindings may expand in the future to include things
@ -1172,438 +962,6 @@ Editor::edit_current_tempo ()
edit_tempo_section (Temporal::TempoMap::use()->metric_at (ARDOUR_UI::instance()->primary_clock->last_when()).get_editable_tempo());
}
RefPtr<RadioAction>
Editor::draw_velocity_action (int v)
{
char buf[64];
const char* action = 0;
RefPtr<Action> act;
if (v==DRAW_VEL_AUTO) {
action = "draw-velocity-auto";
} else if (v>=1 && v<=127) {
sprintf(buf, X_("draw-velocity-%d"), v); //we don't allow drawing a velocity 0; some synths use that as note-off
action = buf;
}
act = ActionManager::get_action (_("Draw Velocity"), action);
if (act) {
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
return ract;
} else {
error << string_compose (_("programming error: %1"), "Editor::draw_velocity_action could not find action to match velocity.") << endmsg;
return RefPtr<RadioAction>();
}
}
RefPtr<RadioAction>
Editor::draw_channel_action (int c)
{
char buf[64];
const char* action = 0;
RefPtr<Action> act;
if (c==DRAW_CHAN_AUTO) {
action = "draw-channel-auto";
} else if (c>=0 && c<=15) {
sprintf(buf, X_("draw-channel-%d"), c+1);
action = buf;
}
act = ActionManager::get_action (_("Draw Channel"), action);
if (act) {
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
return ract;
} else {
error << string_compose (_("programming error: %1"), "Editor::draw_channel_action could not find action to match channel.") << endmsg;
return RefPtr<RadioAction>();
}
}
RefPtr<RadioAction>
Editor::draw_length_action (GridType type)
{
const char* action = 0;
RefPtr<Action> act;
switch (type) {
case Editing::GridTypeBeatDiv32:
action = "draw-length-thirtyseconds";
break;
case Editing::GridTypeBeatDiv28:
action = "draw-length-twentyeighths";
break;
case Editing::GridTypeBeatDiv24:
action = "draw-length-twentyfourths";
break;
case Editing::GridTypeBeatDiv20:
action = "draw-length-twentieths";
break;
case Editing::GridTypeBeatDiv16:
action = "draw-length-asixteenthbeat";
break;
case Editing::GridTypeBeatDiv14:
action = "draw-length-fourteenths";
break;
case Editing::GridTypeBeatDiv12:
action = "draw-length-twelfths";
break;
case Editing::GridTypeBeatDiv10:
action = "draw-length-tenths";
break;
case Editing::GridTypeBeatDiv8:
action = "draw-length-eighths";
break;
case Editing::GridTypeBeatDiv7:
action = "draw-length-sevenths";
break;
case Editing::GridTypeBeatDiv6:
action = "draw-length-sixths";
break;
case Editing::GridTypeBeatDiv5:
action = "draw-length-fifths";
break;
case Editing::GridTypeBeatDiv4:
action = "draw-length-quarters";
break;
case Editing::GridTypeBeatDiv3:
action = "draw-length-thirds";
break;
case Editing::GridTypeBeatDiv2:
action = "draw-length-halves";
break;
case Editing::GridTypeBeat:
action = "draw-length-beat";
break;
case Editing::GridTypeBar:
action = "draw-length-bar";
break;
case Editing::GridTypeNone:
action = "draw-length-auto";
break;
case Editing::GridTypeTimecode:
case Editing::GridTypeCDFrame:
case Editing::GridTypeMinSec:
default:
fatal << string_compose (_("programming error: %1: %2"), "Editor: impossible grid length type", (int) type) << endmsg;
abort(); /*NOTREACHED*/
}
act = ActionManager::get_action (X_("DrawLength"), action);
if (act) {
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
return ract;
} else {
error << string_compose (_("programming error: %1"), "Editor::draw_length_chosen could not find action to match type.") << endmsg;
return RefPtr<RadioAction>();
}
}
RefPtr<RadioAction>
Editor::grid_type_action (GridType type)
{
const char* action = 0;
RefPtr<Action> act;
switch (type) {
case Editing::GridTypeBeatDiv32:
action = "grid-type-thirtyseconds";
break;
case Editing::GridTypeBeatDiv28:
action = "grid-type-twentyeighths";
break;
case Editing::GridTypeBeatDiv24:
action = "grid-type-twentyfourths";
break;
case Editing::GridTypeBeatDiv20:
action = "grid-type-twentieths";
break;
case Editing::GridTypeBeatDiv16:
action = "grid-type-asixteenthbeat";
break;
case Editing::GridTypeBeatDiv14:
action = "grid-type-fourteenths";
break;
case Editing::GridTypeBeatDiv12:
action = "grid-type-twelfths";
break;
case Editing::GridTypeBeatDiv10:
action = "grid-type-tenths";
break;
case Editing::GridTypeBeatDiv8:
action = "grid-type-eighths";
break;
case Editing::GridTypeBeatDiv7:
action = "grid-type-sevenths";
break;
case Editing::GridTypeBeatDiv6:
action = "grid-type-sixths";
break;
case Editing::GridTypeBeatDiv5:
action = "grid-type-fifths";
break;
case Editing::GridTypeBeatDiv4:
action = "grid-type-quarters";
break;
case Editing::GridTypeBeatDiv3:
action = "grid-type-thirds";
break;
case Editing::GridTypeBeatDiv2:
action = "grid-type-halves";
break;
case Editing::GridTypeBeat:
action = "grid-type-beat";
break;
case Editing::GridTypeBar:
action = "grid-type-bar";
break;
case Editing::GridTypeNone:
action = "grid-type-none";
break;
case Editing::GridTypeTimecode:
action = "grid-type-timecode";
break;
case Editing::GridTypeCDFrame:
action = "grid-type-cdframe";
break;
case Editing::GridTypeMinSec:
action = "grid-type-minsec";
break;
default:
fatal << string_compose (_("programming error: %1: %2"), "Editor: impossible snap-to type", (int) type) << endmsg;
abort(); /*NOTREACHED*/
}
act = ActionManager::get_action (X_("Snap"), action);
if (act) {
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
return ract;
} else {
error << string_compose (_("programming error: %1"), "Editor::grid_type_chosen could not find action to match type.") << endmsg;
return RefPtr<RadioAction>();
}
}
void
Editor::next_grid_choice ()
{
switch (_grid_type) {
case Editing::GridTypeBeatDiv32:
set_grid_to (Editing::GridTypeNone);
break;
case Editing::GridTypeBeatDiv16:
set_grid_to (Editing::GridTypeBeatDiv32);
break;
case Editing::GridTypeBeatDiv8:
set_grid_to (Editing::GridTypeBeatDiv16);
break;
case Editing::GridTypeBeatDiv4:
set_grid_to (Editing::GridTypeBeatDiv8);
break;
case Editing::GridTypeBeatDiv2:
set_grid_to (Editing::GridTypeBeatDiv4);
break;
case Editing::GridTypeBeat:
set_grid_to (Editing::GridTypeBeatDiv2);
break;
case Editing::GridTypeBar:
set_grid_to (Editing::GridTypeBeat);
break;
case Editing::GridTypeNone:
set_grid_to (Editing::GridTypeBar);
break;
case Editing::GridTypeBeatDiv3:
case Editing::GridTypeBeatDiv6:
case Editing::GridTypeBeatDiv12:
case Editing::GridTypeBeatDiv24:
case Editing::GridTypeBeatDiv5:
case Editing::GridTypeBeatDiv10:
case Editing::GridTypeBeatDiv20:
case Editing::GridTypeBeatDiv7:
case Editing::GridTypeBeatDiv14:
case Editing::GridTypeBeatDiv28:
case Editing::GridTypeTimecode:
case Editing::GridTypeMinSec:
case Editing::GridTypeCDFrame:
break; //do nothing
}
}
void
Editor::prev_grid_choice ()
{
switch (_grid_type) {
case Editing::GridTypeBeatDiv32:
set_grid_to (Editing::GridTypeBeatDiv16);
break;
case Editing::GridTypeBeatDiv16:
set_grid_to (Editing::GridTypeBeatDiv8);
break;
case Editing::GridTypeBeatDiv8:
set_grid_to (Editing::GridTypeBeatDiv4);
break;
case Editing::GridTypeBeatDiv4:
set_grid_to (Editing::GridTypeBeatDiv2);
break;
case Editing::GridTypeBeatDiv2:
set_grid_to (Editing::GridTypeBeat);
break;
case Editing::GridTypeBeat:
set_grid_to (Editing::GridTypeBar);
break;
case Editing::GridTypeBar:
set_grid_to (Editing::GridTypeNone);
break;
case Editing::GridTypeNone:
set_grid_to (Editing::GridTypeBeatDiv32);
break;
case Editing::GridTypeBeatDiv3:
case Editing::GridTypeBeatDiv6:
case Editing::GridTypeBeatDiv12:
case Editing::GridTypeBeatDiv24:
case Editing::GridTypeBeatDiv5:
case Editing::GridTypeBeatDiv10:
case Editing::GridTypeBeatDiv20:
case Editing::GridTypeBeatDiv7:
case Editing::GridTypeBeatDiv14:
case Editing::GridTypeBeatDiv28:
case Editing::GridTypeTimecode:
case Editing::GridTypeMinSec:
case Editing::GridTypeCDFrame:
break; //do nothing
}
}
void
Editor::grid_type_chosen (GridType type)
{
/* this is driven by a toggle on a radio group, and so is invoked twice,
once for the item that became inactive and once for the one that became
active.
*/
RefPtr<RadioAction> ract = grid_type_action (type);
if (ract && ract->get_active()) {
set_grid_to (type);
}
}
void
Editor::draw_length_chosen (GridType type)
{
/* this is driven by a toggle on a radio group, and so is invoked twice,
once for the item that became inactive and once for the one that became
active.
*/
RefPtr<RadioAction> ract = draw_length_action (type);
if (ract && ract->get_active()) {
set_draw_length_to (type);
}
}
void
Editor::draw_velocity_chosen (int v)
{
/* this is driven by a toggle on a radio group, and so is invoked twice,
once for the item that became inactive and once for the one that became
active.
*/
RefPtr<RadioAction> ract = draw_velocity_action (v);
if (ract && ract->get_active()) {
set_draw_velocity_to (v);
}
}
void
Editor::draw_channel_chosen (int c)
{
/* this is driven by a toggle on a radio group, and so is invoked twice,
once for the item that became inactive and once for the one that became
active.
*/
RefPtr<RadioAction> ract = draw_channel_action (c);
if (ract && ract->get_active()) {
set_draw_channel_to (c);
}
}
RefPtr<RadioAction>
Editor::snap_mode_action (SnapMode mode)
{
const char* action = 0;
RefPtr<Action> act;
switch (mode) {
case Editing::SnapOff:
action = X_("snap-off");
break;
case Editing::SnapNormal:
action = X_("snap-normal");
break;
case Editing::SnapMagnetic:
action = X_("snap-magnetic");
break;
default:
fatal << string_compose (_("programming error: %1: %2"), "Editor: impossible snap mode type", (int) mode) << endmsg;
abort(); /*NOTREACHED*/
}
act = ActionManager::get_action (X_("Editor"), action);
if (act) {
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
return ract;
} else {
error << string_compose (_("programming error: %1: %2"), "Editor::snap_mode_chosen could not find action to match mode.", action) << endmsg;
return RefPtr<RadioAction> ();
}
}
void
Editor::cycle_snap_mode ()
{
switch (_snap_mode) {
case SnapOff:
case SnapNormal:
set_snap_mode (SnapMagnetic);
break;
case SnapMagnetic:
set_snap_mode (SnapOff);
break;
}
}
void
Editor::snap_mode_chosen (SnapMode mode)
{
/* this is driven by a toggle on a radio group, and so is invoked twice,
once for the item that became inactive and once for the one that became
active.
*/
if (mode == SnapNormal) {
mode = SnapMagnetic;
}
RefPtr<RadioAction> ract = snap_mode_action (mode);
if (ract && ract->get_active()) {
set_snap_mode (mode);
}
}
RefPtr<RadioAction>
Editor::edit_point_action (EditPoint ep)
{
@ -2034,3 +1392,15 @@ Editor::register_region_actions ()
/* desensitize them all by default. region selection will change this */
sensitize_all_region_actions (false);
}
void
Editor::add_mouse_mode_actions (Glib::RefPtr<ActionGroup> mouse_mode_actions)
{
RefPtr<Action> act;
act = ActionManager::register_toggle_action (mouse_mode_actions, "set-mouse-mode-object-range", _("Smart Mode"), sigc::mem_fun (*this, &Editor::mouse_mode_object_range_toggled));
smart_mode_action = Glib::RefPtr<ToggleAction>::cast_static (act);
smart_mode_button.set_related_action (smart_mode_action);
smart_mode_button.set_text (_("Smart"));
smart_mode_button.set_name ("mouse mode button");
}

View File

@ -279,49 +279,13 @@ Editor::import_smf_tempo_map (Evoral::SMF const & smf, timepos_t const & pos)
return;
}
const size_t num_tempos = smf.num_tempos ();
bool provided;
TempoMap::WritableSharedPtr new_map (smf.tempo_map (provided));
if (num_tempos == 0) {
if (!provided) {
return;
}
/* cannot create an empty TempoMap, so create one with "default" single
values for tempo and meter, then overwrite them.
*/
TempoMap::WritableSharedPtr new_map (new TempoMap (Tempo (120, 4), Meter (4, 4)));
Meter last_meter (4, 4);
bool have_initial_meter = false;
for (size_t n = 0; n < num_tempos; ++n) {
Evoral::SMF::Tempo* t = smf.nth_tempo (n);
assert (t);
Tempo tempo (t->tempo(), 32.0 / (double) t->notes_per_note);
Meter meter (t->numerator, t->denominator);
Temporal::BBT_Argument bbt; /* 1|1|0 which is correct for the no-meter case */
if (have_initial_meter) {
bbt = new_map->bbt_at (timepos_t (Temporal::Beats (int_div_round (t->time_pulses, (size_t) smf.ppqn()), 0)));
new_map->set_tempo (tempo, bbt);
if (!(meter == last_meter)) {
new_map->set_meter (meter, bbt);
}
} else {
new_map->set_meter (meter, bbt);
new_map->set_tempo (tempo, bbt);
have_initial_meter = true;
}
last_meter = meter;
}
TempoMap::WritableSharedPtr wmap = TempoMap::write_copy ();
TempoMapCutBuffer* tmcb;
// XMLNode& tm_before (wmap->get_state());

View File

@ -89,6 +89,8 @@ Editor::initialize_canvas ()
*/
no_scroll_group = new ArdourCanvas::Container (_track_canvas->root());
_verbose_cursor = new VerboseCursor (*this);
ArdourCanvas::ScrollGroup* hsg;
ArdourCanvas::ScrollGroup* hg;
ArdourCanvas::ScrollGroup* cg;
@ -107,7 +109,6 @@ Editor::initialize_canvas ()
CANVAS_DEBUG_NAME (cursor_scroll_group, "canvas cursor scroll");
_track_canvas->add_scroller (*cg);
_verbose_cursor = new VerboseCursor (this);
_region_peak_cursor = new RegionPeakCursor (get_noscroll_group ());
/*a group to hold global rects like punch/loop indicators */
@ -255,7 +256,7 @@ Editor::initialize_canvas ()
range_marker_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_bar_event), range_marker_bar, RangeMarkerBarItem, "range marker bar"));
transport_marker_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_bar_event), transport_marker_bar, TransportMarkerBarItem, "transport marker bar"));
_playhead_cursor = new EditorCursor (*this, &Editor::canvas_playhead_cursor_event, X_("playhead"));
_playhead_cursor = new EditorCursor (*this, &EditingContext::canvas_playhead_cursor_event, X_("playhead"));
_playhead_cursor->set_sensitive (UIConfiguration::instance().get_sensitize_playhead());
_snapped_cursor = new EditorCursor (*this, X_("snapped"));
@ -630,18 +631,6 @@ Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool from_headers)
}
}
bool
Editor::drag_active () const
{
return _drags->active();
}
bool
Editor::preview_video_drag_active () const
{
return _drags->preview_video ();
}
bool
Editor::autoscroll_active () const
{
@ -924,7 +913,7 @@ Editor::stop_canvas_autoscroll ()
autoscroll_cnt = 0;
}
Editor::EnterContext*
EditingContext::EnterContext*
Editor::get_enter_context(ItemType type)
{
for (ssize_t i = _enter_stack.size() - 1; i >= 0; --i) {
@ -1045,14 +1034,6 @@ Editor::tie_vertical_scrolling ()
}
}
void
Editor::set_horizontal_position (double p)
{
horizontal_adjustment.set_value (p);
_leftmost_sample = (samplepos_t) floor (p * samples_per_pixel);
}
void
Editor::color_handler()
{
@ -1133,10 +1114,16 @@ Editor::color_handler()
*/
}
double
Editor::horizontal_position () const
ArdourCanvas::GtkCanvasViewport*
Editor::get_canvas_viewport() const
{
return sample_to_pixel (_leftmost_sample);
return _track_canvas_viewport;
}
ArdourCanvas::GtkCanvas*
Editor::get_canvas() const
{
return _track_canvas_viewport->canvas();
}
bool
@ -1170,66 +1157,6 @@ Editor::clamp_verbose_cursor_y (double y)
return y;
}
ArdourCanvas::GtkCanvasViewport*
Editor::get_track_canvas() const
{
return _track_canvas_viewport;
}
Gdk::Cursor*
Editor::get_canvas_cursor () const
{
/* The top of the cursor stack is always the currently visible cursor. */
return _cursor_stack.back();
}
void
Editor::set_canvas_cursor (Gdk::Cursor* cursor)
{
Glib::RefPtr<Gdk::Window> win = _track_canvas->get_window();
if (win && !_cursors->is_invalid (cursor)) {
/* glibmm 2.4 doesn't allow null cursor pointer because it uses
a Gdk::Cursor& as the argument to Gdk::Window::set_cursor().
But a null pointer just means "use parent window cursor",
and so should be allowed. Gtkmm 3.x has fixed this API.
For now, drop down and use C API
*/
gdk_window_set_cursor (win->gobj(), cursor ? cursor->gobj() : 0);
}
}
size_t
Editor::push_canvas_cursor (Gdk::Cursor* cursor)
{
if (!_cursors->is_invalid (cursor)) {
_cursor_stack.push_back (cursor);
set_canvas_cursor (cursor);
}
return _cursor_stack.size() - 1;
}
void
Editor::pop_canvas_cursor ()
{
while (true) {
if (_cursor_stack.size() <= 1) {
PBD::error << "attempt to pop default cursor" << endmsg;
return;
}
_cursor_stack.pop_back();
if (_cursor_stack.back()) {
/* Popped to an existing cursor, we're done. Otherwise, the
context that created this cursor has been destroyed, so we need
to skip to the next down the stack. */
set_canvas_cursor (_cursor_stack.back());
return;
}
}
}
Gdk::Cursor*
Editor::which_trim_cursor (bool left) const
{

View File

@ -202,50 +202,6 @@ Editor::track_canvas_motion_notify_event (GdkEventMotion */*event*/)
return false;
}
bool
Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
{
if (!session () || session()->loading () || session()->deletion_in_progress ()) {
return false;
}
gint ret = FALSE;
switch (event->type) {
case GDK_BUTTON_PRESS:
case GDK_2BUTTON_PRESS:
case GDK_3BUTTON_PRESS:
ret = button_press_handler (item, event, type);
break;
case GDK_BUTTON_RELEASE:
ret = button_release_handler (item, event, type);
break;
case GDK_MOTION_NOTIFY:
ret = motion_handler (item, event);
break;
case GDK_ENTER_NOTIFY:
ret = enter_handler (item, event, type);
break;
case GDK_LEAVE_NOTIFY:
ret = leave_handler (item, event, type);
break;
case GDK_KEY_PRESS:
ret = key_press_handler (item, event, type);
break;
case GDK_KEY_RELEASE:
ret = key_release_handler (item, event, type);
break;
default:
break;
}
return ret;
}
bool
Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
{
@ -1210,7 +1166,7 @@ Editor::canvas_section_box_event (GdkEvent *event)
case GDK_BUTTON_PRESS:
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)
&& event->button.button == 1) {
_drags->set (new CursorDrag (this, *_playhead_cursor, false), event);
_drags->set (new CursorDrag (*this, *_playhead_cursor, false), event);
}
/*fallthrough*/
case GDK_2BUTTON_PRESS:
@ -1477,7 +1433,7 @@ Editor::drop_regions (const Glib::RefPtr<Gdk::DragContext>& /*context*/,
if ((std::dynamic_pointer_cast<AudioRegion> (region_copy) != 0 && dynamic_cast<AudioTimeAxisView*> (rtav) != 0) ||
(std::dynamic_pointer_cast<MidiRegion> (region_copy) != 0 && dynamic_cast<MidiTimeAxisView*> (rtav) != 0)) {
_drags->set (new RegionInsertDrag (this, region_copy, rtav, timepos_t (pos), drag_time_domain (region_copy.get())), &event);
_drags->set (new RegionInsertDrag (*this, region_copy, rtav, timepos_t (pos), drag_time_domain (region_copy.get())), &event);
_drags->end_grab (&event);
}
}

View File

@ -29,13 +29,13 @@
#include "canvas/scroll_group.h"
#include "editor_cursors.h"
#include "editor.h"
#include "editing_context.h"
using namespace ARDOUR;
using namespace PBD;
using namespace Gtk;
EditorCursor::EditorCursor (Editor& ed, bool (Editor::*callback)(GdkEvent*,ArdourCanvas::Item*), std::string const & name)
EditorCursor::EditorCursor (EditingContext& ed, bool (EditingContext::*callback)(GdkEvent*,ArdourCanvas::Item*), std::string const & name)
: _editor (ed)
, _track_canvas_item (new ArdourCanvas::Arrow (_editor.get_cursor_scroll_group()))
{
@ -57,7 +57,7 @@ EditorCursor::EditorCursor (Editor& ed, bool (Editor::*callback)(GdkEvent*,Ardou
_current_sample = 1; /* force redraw at 0 */
}
EditorCursor::EditorCursor (Editor& ed, std::string const & name)
EditorCursor::EditorCursor (EditingContext& ed, std::string const & name)
: _editor (ed)
, _track_canvas_item (new ArdourCanvas::Arrow (_editor.get_hscroll_group()))
{

View File

@ -29,13 +29,13 @@
#include "canvas/line.h"
#include "canvas/types.h"
class Editor;
class EditingContext;
class EditorCursor
{
public:
EditorCursor (Editor&, bool (Editor::*)(GdkEvent*,ArdourCanvas::Item*), std::string const &);
EditorCursor (Editor&, std::string const &);
EditorCursor (EditingContext&, bool (EditingContext::*)(GdkEvent*,ArdourCanvas::Item*), std::string const &);
EditorCursor (EditingContext&, std::string const &);
~EditorCursor ();
void set_position (samplepos_t);
@ -57,7 +57,7 @@ public:
PBD::Signal1<void, samplepos_t> PositionChanged;
private:
Editor& _editor;
EditingContext& _editor;
ArdourCanvas::Arrow* _track_canvas_item;
samplepos_t _current_sample;
};

File diff suppressed because it is too large Load Diff

View File

@ -66,6 +66,7 @@ namespace PBD {
}
class PatchChange;
class EditingContext;
class Editor;
class EditorCursor;
class TimeAxisView;
@ -76,6 +77,7 @@ class TimeAxisView;
class RouteTimeAxisView;
class RegionSelection;
class MidiRegionView;
class MidiView;
class MeterMarker;
class ArdourMarker;
class TempoMarker;
@ -91,7 +93,7 @@ class DragManager
{
public:
DragManager (Editor* e);
DragManager (EditingContext* e);
~DragManager ();
bool motion_handler (GdkEvent *, bool);
@ -138,7 +140,7 @@ public:
bool preview_video () const;
private:
Editor* _editor;
EditingContext* _editing_context;
std::list<Drag*> _drags;
bool _ending; ///< true if end_grab or abort is in progress, otherwise false
double _current_pointer_x; ///< canvas-coordinate space x of the current pointer
@ -151,13 +153,17 @@ private:
class Drag
{
public:
Drag (Editor *, ArdourCanvas::Item *, Temporal::TimeDomain td, bool trackview_only = true, bool hide_snapped_cursor = true);
Drag (EditingContext&, ArdourCanvas::Item *, Temporal::TimeDomain td, ArdourCanvas::Item const * bounding_item, bool hide_snapped_cursor = true);
virtual ~Drag ();
void set_manager (DragManager* m) {
_drags = m;
}
void set_bounding_item (ArdourCanvas::Item const * i) {
_bounding_item = i;
}
/** @return the canvas item being dragged */
ArdourCanvas::Item* item () const {
return _item;
@ -313,9 +319,10 @@ protected:
void show_verbose_cursor_text (std::string const &);
void show_view_preview (Temporal::timepos_t const &);
Editor* _editor; ///< our editor
EditingContext& editing_context;
DragManager* _drags;
ArdourCanvas::Item* _item; ///< our item
ArdourCanvas::Item const * _bounding_item; ///< our coordinate reference (normally null)
/** Offset from the mouse's position for the drag to the start of the thing that is being dragged */
Temporal::timecnt_t _pointer_offset;
Temporal::timecnt_t _video_offset;
@ -326,14 +333,13 @@ protected:
ARDOUR::timepos_t _earliest_time_limit; ///< time we cannot drag before (defaults to 0, indicating no such limit)
private:
bool _trackview_only; ///< true if pointer y value should always be relative to the top of the trackview group
bool _hide_snapped_cursor; ///< set true of ::motion does not call `set_snapped_cursor_position`
bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
bool _starting_point_passed; ///< true if we called move () with first_move flag, otherwise false
bool _initially_vertical; ///< true if after move threshold is passed we appear to be moving vertically; undefined before that
bool _was_double_click; ///< true if drag initiated by a double click event
double _grab_x; ///< trackview x of the grab start position
double _grab_y; ///< y of the grab start position, possibly adjusted if _trackview_only is true
double _grab_y; ///< y of the grab start position, possibly adjusted if _bounding_itme is non-null
double _last_pointer_x; ///< trackview x of the pointer last time a motion occurred
double _last_pointer_y; ///< trackview y of the pointer last time a motion occurred
Temporal::timepos_t _raw_grab_time; ///< unsnapped time that the mouse was at when start_grab was called, or 0
@ -352,6 +358,19 @@ private:
Gtkmm2ext::Bindings::DragsBlockBindings binding_blocker;
};
/** EditorDrag:
*
* a base class for Drags that will need access to the full Editor, not just an
* Editing Context.
*/
class EditorDrag : public Drag
{
public:
EditorDrag (Editor&, ArdourCanvas::Item *, Temporal::TimeDomain td, ArdourCanvas::Item const * bounding_item, bool hide_snapped_cursor = true);
protected:
Editor& _editor;
};
class RegionDrag;
/** Container for details about a region being dragged */
@ -379,10 +398,10 @@ public:
};
/** Abstract base class for drags that involve region(s) */
class RegionDrag : public Drag, public sigc::trackable
class RegionDrag : public EditorDrag, public sigc::trackable
{
public:
RegionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, Temporal::TimeDomain, bool hide_snapped_cursor = true);
RegionDrag (Editor&, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, Temporal::TimeDomain, bool hide_snapped_cursor = true);
virtual ~RegionDrag () {}
protected:
@ -417,7 +436,7 @@ class RegionSlipContentsDrag : public RegionDrag
{
public:
RegionSlipContentsDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, Temporal::TimeDomain td);
RegionSlipContentsDrag (Editor&, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, Temporal::TimeDomain td);
virtual ~RegionSlipContentsDrag () {}
virtual void start_grab (GdkEvent *, Gdk::Cursor *);
@ -430,7 +449,7 @@ public:
class RegionBrushDrag : public RegionDrag
{
public:
RegionBrushDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, Temporal::TimeDomain td);
RegionBrushDrag (Editor&, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, Temporal::TimeDomain td);
virtual ~RegionBrushDrag () {}
virtual void start_grab (GdkEvent *, Gdk::Cursor *);
@ -447,7 +466,7 @@ class RegionMotionDrag : public RegionDrag
{
public:
RegionMotionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, Temporal::TimeDomain td);
RegionMotionDrag (Editor&, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, Temporal::TimeDomain td);
virtual ~RegionMotionDrag () {}
virtual void start_grab (GdkEvent *, Gdk::Cursor *);
@ -486,7 +505,7 @@ private:
class RegionMoveDrag : public RegionMotionDrag
{
public:
RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool, Temporal::TimeDomain);
RegionMoveDrag (Editor&, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool, Temporal::TimeDomain);
virtual ~RegionMoveDrag () {}
void motion (GdkEvent *, bool);
@ -546,7 +565,7 @@ private:
class RegionInsertDrag : public RegionMotionDrag
{
public:
RegionInsertDrag (Editor *, std::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, Temporal::timepos_t const &, Temporal::TimeDomain);
RegionInsertDrag (Editor&, std::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, Temporal::timepos_t const &, Temporal::TimeDomain);
void finished (GdkEvent *, bool);
void aborted (bool);
@ -557,25 +576,23 @@ public:
};
/** "Drag" to cut a region (action only on button release) */
class RegionCutDrag : public Drag
class RegionCutDrag : public EditorDrag
{
public:
RegionCutDrag (Editor*, ArdourCanvas::Item*, samplepos_t);
RegionCutDrag (Editor&, ArdourCanvas::Item*, samplepos_t);
~RegionCutDrag ();
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent*, bool);
void finished (GdkEvent*, bool);
void aborted (bool);
private:
};
/** Drags to create regions */
class RegionCreateDrag : public Drag
class RegionCreateDrag : public EditorDrag
{
public:
RegionCreateDrag (Editor *, ArdourCanvas::Item *, TimeAxisView *);
RegionCreateDrag (Editor&, ArdourCanvas::Item *, TimeAxisView *);
void motion (GdkEvent *, bool);
void finished (GdkEvent *, bool);
@ -590,7 +607,7 @@ private:
class NoteResizeDrag : public Drag
{
public:
NoteResizeDrag (Editor *, ArdourCanvas::Item *);
NoteResizeDrag (EditingContext&, ArdourCanvas::Item *);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -602,18 +619,18 @@ public:
}
private:
MidiRegionView* region;
bool relative;
bool at_front;
bool _was_selected;
double _snap_delta;
MidiView* region;
bool relative;
bool at_front;
bool _was_selected;
double _snap_delta;
};
/** Drags to move MIDI notes */
class NoteDrag : public Drag
{
public:
NoteDrag (Editor*, ArdourCanvas::Item*);
NoteDrag (EditingContext&, ArdourCanvas::Item*);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -631,7 +648,7 @@ private:
Temporal::timecnt_t total_dx (GdkEvent * event) const; // total movement in quarter notes
int8_t total_dy () const;
MidiRegionView* _region;
MidiView* _region;
NoteBase* _primary;
Temporal::timecnt_t _cumulative_dx;
double _cumulative_dy;
@ -644,7 +661,7 @@ private:
class NoteCreateDrag : public Drag
{
public:
NoteCreateDrag (Editor *, ArdourCanvas::Item *, MidiRegionView *);
NoteCreateDrag (EditingContext&, ArdourCanvas::Item *, MidiView *);
~NoteCreateDrag ();
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
@ -673,7 +690,7 @@ private:
return std::make_pair (Temporal::timecnt_t (0, Temporal::AudioTime), 0);
}
MidiRegionView* _region_view;
MidiView* _midi_view;
ArdourCanvas::Rectangle* _drag_rect;
Temporal::timepos_t _note[2];
};
@ -681,7 +698,7 @@ private:
class HitCreateDrag : public Drag
{
public:
HitCreateDrag (Editor *, ArdourCanvas::Item *, MidiRegionView *);
HitCreateDrag (EditingContext&, ArdourCanvas::Item *, MidiView *);
~HitCreateDrag ();
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
@ -705,7 +722,7 @@ private:
return std::make_pair (Temporal::timecnt_t::zero (Temporal::AudioTime), 0);
}
MidiRegionView* _region_view;
MidiView* _midi_view;
Temporal::timepos_t _last_pos;
double _y;
@ -715,7 +732,7 @@ private:
class PatchChangeDrag : public Drag
{
public:
PatchChangeDrag (Editor *, PatchChange *, MidiRegionView *);
PatchChangeDrag (EditingContext&, PatchChange *, MidiView *);
void motion (GdkEvent *, bool);
void finished (GdkEvent *, bool);
@ -732,7 +749,7 @@ public:
void setup_pointer_offset ();
private:
MidiRegionView* _region_view;
MidiView* _region_view;
PatchChange* _patch_change;
double _cumulative_dx;
};
@ -748,10 +765,10 @@ public:
};
/** Drag of video offset */
class VideoTimeLineDrag : public Drag
class VideoTimeLineDrag : public EditorDrag
{
public:
VideoTimeLineDrag (Editor *e, ArdourCanvas::Item *i);
VideoTimeLineDrag (Editor&e, ArdourCanvas::Item *i);
void motion (GdkEvent *, bool);
void finished (GdkEvent *, bool);
@ -785,7 +802,7 @@ public:
EndTrim
};
TrimDrag (Editor *, ArdourCanvas::Item *, RegionView*, std::list<RegionView*> const &, Temporal::TimeDomain td, bool preserve_fade_anchor = false);
TrimDrag (Editor&, ArdourCanvas::Item *, RegionView*, std::list<RegionView*> const &, Temporal::TimeDomain td, bool preserve_fade_anchor = false);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -813,10 +830,10 @@ private:
};
/** Meter marker drag */
class MeterMarkerDrag : public Drag
class MeterMarkerDrag : public EditorDrag
{
public:
MeterMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
MeterMarkerDrag (Editor&, ArdourCanvas::Item *, bool);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -845,10 +862,10 @@ private:
};
/** Tempo curve drag */
class TempoCurveDrag : public Drag
class TempoCurveDrag : public EditorDrag
{
public:
TempoCurveDrag (Editor*, ArdourCanvas::Item*);
TempoCurveDrag (Editor&, ArdourCanvas::Item*);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -863,10 +880,10 @@ private:
};
/** Tempo marker drag */
class TempoMarkerDrag : public Drag
class TempoMarkerDrag : public EditorDrag
{
public:
TempoMarkerDrag (Editor *, ArdourCanvas::Item *);
TempoMarkerDrag (Editor&, ArdourCanvas::Item *);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -895,10 +912,10 @@ private:
};
/** Tempo marker drag */
class BBTMarkerDrag : public Drag
class BBTMarkerDrag : public EditorDrag
{
public:
BBTMarkerDrag (Editor *, ArdourCanvas::Item *);
BBTMarkerDrag (Editor&, ArdourCanvas::Item *);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -923,10 +940,10 @@ private:
XMLNode* _before_state;
};
class MappingEndDrag : public Drag
class MappingEndDrag : public EditorDrag
{
public:
MappingEndDrag (Editor *, ArdourCanvas::Item *, Temporal::TempoMap::WritableSharedPtr&, Temporal::TempoPoint&, Temporal::TempoPoint& after, XMLNode& before_state);
MappingEndDrag (Editor&, ArdourCanvas::Item *, Temporal::TempoMap::WritableSharedPtr&, Temporal::TempoPoint&, Temporal::TempoPoint& after, XMLNode& before_state);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -957,10 +974,10 @@ private:
bool _drag_valid;
};
class MappingTwistDrag : public Drag
class MappingTwistDrag : public EditorDrag
{
public:
MappingTwistDrag (Editor *, ArdourCanvas::Item *, Temporal::TempoMap::WritableSharedPtr&,
MappingTwistDrag (Editor&, ArdourCanvas::Item *, Temporal::TempoMap::WritableSharedPtr&,
Temporal::TempoPoint& prev,
Temporal::TempoPoint& focus,
Temporal::TempoPoint& next,
@ -1004,10 +1021,10 @@ private:
/** tempo curve twist drag */
class TempoTwistDrag : public Drag
class TempoTwistDrag : public EditorDrag
{
public:
TempoTwistDrag (Editor *, ArdourCanvas::Item *);
TempoTwistDrag (Editor&, ArdourCanvas::Item *);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -1034,10 +1051,10 @@ private:
};
/** tempo curve twist drag */
class TempoEndDrag : public Drag
class TempoEndDrag : public EditorDrag
{
public:
TempoEndDrag (Editor *, ArdourCanvas::Item *);
TempoEndDrag (Editor&, ArdourCanvas::Item *);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -1065,10 +1082,10 @@ private:
};
/** Drag of the playhead cursor */
class CursorDrag : public Drag
class CursorDrag : public EditorDrag
{
public:
CursorDrag (Editor *, EditorCursor&, bool);
CursorDrag (Editor&, EditorCursor&, bool);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -1101,7 +1118,7 @@ private:
class FadeInDrag : public RegionDrag
{
public:
FadeInDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, Temporal::TimeDomain);
FadeInDrag (Editor&, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, Temporal::TimeDomain);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -1123,7 +1140,7 @@ public:
class FadeOutDrag : public RegionDrag
{
public:
FadeOutDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, Temporal::TimeDomain td);
FadeOutDrag (Editor&, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, Temporal::TimeDomain td);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -1142,10 +1159,10 @@ public:
};
/** Marker drag */
class MarkerDrag : public Drag
class MarkerDrag : public EditorDrag
{
public:
MarkerDrag (Editor *, ArdourCanvas::Item *);
MarkerDrag (Editor&, ArdourCanvas::Item *);
~MarkerDrag ();
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
@ -1184,10 +1201,10 @@ private:
};
/** Control point drag */
class ControlPointDrag : public Drag
class ControlPointDrag : public EditorDrag
{
public:
ControlPointDrag (Editor *, ArdourCanvas::Item *);
ControlPointDrag (Editor&, ArdourCanvas::Item *);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -1215,10 +1232,10 @@ private:
};
/** Gain or automation line drag */
class LineDrag : public Drag
class LineDrag : public EditorDrag
{
public:
LineDrag (Editor *e, ArdourCanvas::Item *i);
LineDrag (Editor&e, ArdourCanvas::Item *i);
~LineDrag ();
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
@ -1245,7 +1262,7 @@ private:
class FeatureLineDrag : public Drag
{
public:
FeatureLineDrag (Editor *e, ArdourCanvas::Item *i);
FeatureLineDrag (Editor&e, ArdourCanvas::Item *i);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -1268,7 +1285,7 @@ private:
class RubberbandSelectDrag : public Drag
{
public:
RubberbandSelectDrag (Editor *, ArdourCanvas::Item *);
RubberbandSelectDrag (EditingContext&, ArdourCanvas::Item *);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -1301,43 +1318,45 @@ public:
class EditorRubberbandSelectDrag : public RubberbandSelectDrag
{
public:
EditorRubberbandSelectDrag (Editor *, ArdourCanvas::Item *);
EditorRubberbandSelectDrag (Editor&, ArdourCanvas::Item *);
void select_things (int, Temporal::timepos_t const &, Temporal::timepos_t const &, double, double, bool);
void deselect_things ();
private:
Editor& editor;
};
/** A RubberbandSelectDrag for selecting MIDI notes */
class MidiRubberbandSelectDrag : public RubberbandSelectDrag
{
public:
MidiRubberbandSelectDrag (Editor *, MidiRegionView *);
MidiRubberbandSelectDrag (EditingContext&, MidiView *);
void select_things (int, Temporal::timepos_t const &, Temporal::timepos_t const &, double, double, bool);
void deselect_things ();
private:
MidiRegionView* _region_view;
MidiView* _midi_view;
};
/** A RubberbandSelectDrag for selecting MIDI notes but with no horizontal component */
class MidiVerticalSelectDrag : public RubberbandSelectDrag
{
public:
MidiVerticalSelectDrag (Editor *, MidiRegionView *);
MidiVerticalSelectDrag (EditingContext&, MidiView *);
void select_things (int, Temporal::timepos_t const &, Temporal::timepos_t const &, double, double, bool);
void deselect_things ();
private:
MidiRegionView* _region_view;
MidiView* _midi_view;
};
/** Region drag in time-FX mode */
class TimeFXDrag : public RegionDrag
{
public:
TimeFXDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, Temporal::TimeDomain td);
TimeFXDrag (Editor&, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, Temporal::TimeDomain td);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -1348,7 +1367,7 @@ private:
};
/** Drag in range select mode */
class SelectionDrag : public Drag
class SelectionDrag : public EditorDrag
{
public:
enum Operation {
@ -1359,7 +1378,7 @@ public:
SelectionExtend
};
SelectionDrag (Editor *, ArdourCanvas::Item *, Operation);
SelectionDrag (Editor&, ArdourCanvas::Item *, Operation);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -1378,10 +1397,10 @@ private:
};
/** Drag time-selection markers */
class SelectionMarkerDrag : public Drag
class SelectionMarkerDrag : public EditorDrag
{
public:
SelectionMarkerDrag (Editor*, ArdourCanvas::Item*);
SelectionMarkerDrag (Editor&, ArdourCanvas::Item*);
void start_grab (GdkEvent*, Gdk::Cursor* c = 0);
void motion (GdkEvent*, bool);
@ -1395,7 +1414,7 @@ private:
};
/** Range marker drag */
class RangeMarkerBarDrag : public Drag
class RangeMarkerBarDrag : public EditorDrag
{
public:
enum Operation {
@ -1405,7 +1424,7 @@ public:
CreateCDMarker
};
RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation);
RangeMarkerBarDrag (Editor&, ArdourCanvas::Item *, Operation);
~RangeMarkerBarDrag ();
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
@ -1430,10 +1449,10 @@ private:
};
/** Drag of rectangle to set zoom */
class MouseZoomDrag : public Drag
class MouseZoomDrag : public EditorDrag
{
public:
MouseZoomDrag (Editor *, ArdourCanvas::Item *);
MouseZoomDrag (Editor&, ArdourCanvas::Item *);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -1454,8 +1473,8 @@ private:
class AutomationRangeDrag : public Drag
{
public:
AutomationRangeDrag (Editor *, AutomationTimeAxisView *, float initial_value, std::list<ARDOUR::TimelineRange> const &);
AutomationRangeDrag (Editor *, std::list<RegionView*> const &, std::list<ARDOUR::TimelineRange> const &, double y_origin, double y_height);
AutomationRangeDrag (EditingContext&, AutomationTimeAxisView *, float initial_value, std::list<ARDOUR::TimelineRange> const &);
AutomationRangeDrag (EditingContext&, std::list<RegionView*> const &, std::list<ARDOUR::TimelineRange> const &, double y_origin, double y_height);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -1494,7 +1513,7 @@ private:
class CrossfadeEdgeDrag : public Drag
{
public:
CrossfadeEdgeDrag (Editor*, AudioRegionView*, ArdourCanvas::Item*, bool start);
CrossfadeEdgeDrag (Editor&, AudioRegionView*, ArdourCanvas::Item*, bool start);
void start_grab (GdkEvent*, Gdk::Cursor* c = 0);
void motion (GdkEvent*, bool);
@ -1517,7 +1536,7 @@ private:
class RegionMarkerDrag : public Drag
{
public:
RegionMarkerDrag (Editor*, RegionView*, ArdourCanvas::Item*);
RegionMarkerDrag (Editor&, RegionView*, ArdourCanvas::Item*);
~RegionMarkerDrag ();
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
@ -1546,7 +1565,7 @@ class RegionMarkerDrag : public Drag
class LollipopDrag : public Drag
{
public:
LollipopDrag (Editor*, ArdourCanvas::Item*);
LollipopDrag (EditingContext&, ArdourCanvas::Item*);
~LollipopDrag ();
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
@ -1577,7 +1596,7 @@ template<typename OrderedPointList, typename OrderedPoint>
class FreehandLineDrag : public Drag
{
public:
FreehandLineDrag (Editor*, ArdourCanvas::Item*, ArdourCanvas::Rectangle&, Temporal::TimeDomain);
FreehandLineDrag (EditingContext&, ArdourCanvas::Item*, ArdourCanvas::Rectangle&, Temporal::TimeDomain);
~FreehandLineDrag ();
void motion (GdkEvent*, bool);
@ -1606,7 +1625,7 @@ class FreehandLineDrag : public Drag
class AutomationDrawDrag : public FreehandLineDrag<Evoral::ControlList::OrderedPoints, Evoral::ControlList::OrderedPoint>
{
public:
AutomationDrawDrag (Editor*, ArdourCanvas::Item*, ArdourCanvas::Rectangle&, Temporal::TimeDomain);
AutomationDrawDrag (EditingContext&, ArdourCanvas::Item*, ArdourCanvas::Rectangle&, Temporal::TimeDomain);
~AutomationDrawDrag ();
void finished (GdkEvent*, bool);
@ -1616,7 +1635,7 @@ class AutomationDrawDrag : public FreehandLineDrag<Evoral::ControlList::OrderedP
class VelocityLineDrag : public FreehandLineDrag<Evoral::ControlList::OrderedPoints, Evoral::ControlList::OrderedPoint>
{
public:
VelocityLineDrag (Editor*, ArdourCanvas::Rectangle&, Temporal::TimeDomain);
VelocityLineDrag (EditingContext&, ArdourCanvas::Rectangle&, Temporal::TimeDomain);
~VelocityLineDrag ();
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);

View File

@ -1521,7 +1521,7 @@ Editor::marker_menu_set_from_playhead ()
timepos_t pos (_session->audible_sample());
if (default_time_domain() == Temporal::BeatTime) {
if (time_domain() == Temporal::BeatTime) {
pos = timepos_t (pos.beats());
}

View File

@ -65,6 +65,7 @@
#include "audio_time_axis.h"
#include "audio_region_view.h"
#include "midi_region_view.h"
#include "midi_view.h"
#include "marker.h"
#include "streamview.h"
#include "region_gain_line.h"
@ -170,47 +171,6 @@ Editor::window_event_sample (GdkEvent const * event, double* pcx, double* pcy) c
return pixel_to_sample (d.x);
}
timepos_t
Editor::canvas_event_time (GdkEvent const * event, double* pcx, double* pcy) const
{
timepos_t pos (canvas_event_sample (event, pcx, pcy));
if (default_time_domain() == Temporal::AudioTime) {
return pos;
}
return timepos_t (pos.beats());
}
samplepos_t
Editor::canvas_event_sample (GdkEvent const * event, double* pcx, double* pcy) const
{
double x;
double y;
/* event coordinates are already in canvas units */
if (!gdk_event_get_coords (event, &x, &y)) {
cerr << "!NO c COORDS for event type " << event->type << endl;
return 0;
}
if (pcx) {
*pcx = x;
}
if (pcy) {
*pcy = y;
}
/* note that pixel_to_sample_from_event() never returns less than zero, so even if the pixel
position is negative (as can be the case with motion events in particular),
the sample location is always positive.
*/
return pixel_to_sample_from_event (x);
}
void
Editor::set_current_trimmable (std::shared_ptr<Trimmable> t)
{
@ -237,68 +197,6 @@ Editor::mouse_mode_object_range_toggled()
set_mouse_mode (mouse_mode, true); /* updates set-mouse-mode-range */
}
bool
Editor::snap_mode_button_clicked (GdkEventButton* ev)
{
if (ev->button != 3) {
cycle_snap_mode();
return true;
}
RCOptionEditor* rc_option_editor = ARDOUR_UI::instance()->get_rc_option_editor();
if (rc_option_editor) {
ARDOUR_UI::instance()->show_tabbable (rc_option_editor);
rc_option_editor->set_current_page (_("Editor/Snap"));
}
return true;
}
Glib::RefPtr<Action>
Editor::get_mouse_mode_action(MouseMode m) const
{
switch (m) {
case MouseRange:
return ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-range"));
case MouseObject:
return ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object"));
case MouseCut:
return ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-cut"));
case MouseDraw:
return ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-draw"));
case MouseTimeFX:
return ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-timefx"));
case MouseGrid:
return ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-grid"));
case MouseContent:
return ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-content"));
}
return Glib::RefPtr<Action>();
}
void
Editor::set_mouse_mode (MouseMode m, bool force)
{
if (_drags->active ()) {
return;
}
if (!force && m == mouse_mode) {
return;
}
Glib::RefPtr<Action> act = get_mouse_mode_action(m);
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
/* go there and back to ensure that the toggled handler is called to set up mouse_mode */
tact->set_active (false);
tact->set_active (true);
/* NOTE: this will result in a call to mouse_mode_toggled which does the heavy lifting */
}
void
Editor::mouse_mode_toggled (MouseMode m)
{
@ -760,7 +658,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
switch (item_type) {
case PlayheadCursorItem:
_drags->set (new CursorDrag (this, *_playhead_cursor, true), event);
_drags->set (new CursorDrag (*this, *_playhead_cursor, true), event);
return true;
case MarkerItem:
@ -769,43 +667,37 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
} else {
ArdourMarker* marker = static_cast<ArdourMarker*> (item->get_data ("marker"));
if (marker->type() == ArdourMarker::RegionCue) {
_drags->set (new RegionMarkerDrag (this, marker->region_view(), item), event);
_drags->set (new RegionMarkerDrag (*this, marker->region_view(), item), event);
} else {
_drags->set (new MarkerDrag (this, item), event);
_drags->set (new MarkerDrag (*this, item), event);
}
}
return true;
case TempoMarkerItem:
if (ArdourKeyboard::indicates_constraint (event->button.state)) {
_drags->set (new TempoEndDrag (this, item), event);
_drags->set (new TempoEndDrag (*this, item), event);
} else {
_drags->set (new TempoMarkerDrag (this, item), event);
_drags->set (new TempoMarkerDrag (*this, item), event);
}
return true;
case BBTMarkerItem:
_drags->set (new BBTMarkerDrag (this, item), event);
_drags->set (new BBTMarkerDrag (*this, item), event);
return true;
case SelectionMarkerItem:
_drags->set (new SelectionMarkerDrag (this, item), event);
_drags->set (new SelectionMarkerDrag (*this, item), event);
return true;
case MeterMarkerItem:
_drags->set (
new MeterMarkerDrag (
this,
item,
ArdourKeyboard::indicates_copy (event->button.state)
),
event
);
new MeterMarkerDrag (*this, item, ArdourKeyboard::indicates_copy (event->button.state)), event);
return true;
case VideoBarItem:
_drags->set (new VideoTimeLineDrag (this, item), event);
_drags->set (new VideoTimeLineDrag (*this, item), event);
return true;
break;
@ -813,9 +705,9 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case TempoCurveItem:
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)
&& !ArdourKeyboard::indicates_constraint (event->button.state)) {
_drags->set (new CursorDrag (this, *_playhead_cursor, false), event);
_drags->set (new CursorDrag (*this, *_playhead_cursor, false), event);
} else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
_drags->set (new TempoCurveDrag (this, item), event);
_drags->set (new TempoCurveDrag (*this, item), event);
return true;
}
return true;
@ -823,14 +715,14 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case MeterBarItem:
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)
&& !ArdourKeyboard::indicates_constraint (event->button.state)) {
_drags->set (new CursorDrag (this, *_playhead_cursor, false), event);
_drags->set (new CursorDrag (*this, *_playhead_cursor, false), event);
}
return true;
case BBTRulerItem:
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)
&& !ArdourKeyboard::indicates_constraint (event->button.state)) {
_drags->set (new CursorDrag (this, *_playhead_cursor, false), event);
_drags->set (new CursorDrag (*this, *_playhead_cursor, false), event);
}
return true;
@ -841,33 +733,33 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case SectionMarkerBarItem:
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)
&& !ArdourKeyboard::indicates_constraint (event->button.state)) {
_drags->set (new CursorDrag (this, *_playhead_cursor, false), event);
_drags->set (new CursorDrag (*this, *_playhead_cursor, false), event);
}
return true;
case RangeMarkerBarItem:
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::TertiaryModifier)) {
_drags->set (new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateSkipMarker), event);
_drags->set (new RangeMarkerBarDrag (*this, item, RangeMarkerBarDrag::CreateSkipMarker), event);
} else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
_drags->set (new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateRangeMarker), event);
_drags->set (new RangeMarkerBarDrag (*this, item, RangeMarkerBarDrag::CreateRangeMarker), event);
} else {
_drags->set (new CursorDrag (this, *_playhead_cursor, false), event);
_drags->set (new CursorDrag (*this, *_playhead_cursor, false), event);
}
return true;
break;
case CdMarkerBarItem:
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
_drags->set (new CursorDrag (this, *_playhead_cursor, false), event);
_drags->set (new CursorDrag (*this, *_playhead_cursor, false), event);
} else {
_drags->set (new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateCDMarker), event);
_drags->set (new RangeMarkerBarDrag (*this, item, RangeMarkerBarDrag::CreateCDMarker), event);
}
return true;
break;
case CueMarkerBarItem:
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
_drags->set (new CursorDrag (this, *_playhead_cursor, false), event);
_drags->set (new CursorDrag (*this, *_playhead_cursor, false), event);
} else {
/* no range dragging on this ruler/bar */
}
@ -876,15 +768,15 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case TransportMarkerBarItem:
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
_drags->set (new CursorDrag (this, *_playhead_cursor, false), event);
_drags->set (new CursorDrag (*this, *_playhead_cursor, false), event);
} else {
_drags->set (new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateTransportMarker), event);
_drags->set (new RangeMarkerBarDrag (*this, item, RangeMarkerBarDrag::CreateTransportMarker), event);
}
return true;
break;
case VelocityItem:
_drags->set (new LollipopDrag (this, item), event);
_drags->set (new LollipopDrag (*this, item), event);
return true;
break;
@ -892,7 +784,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
{
VelocityGhostRegion* grv = static_cast<VelocityGhostRegion*> (item->get_data ("ghostregionview"));
if (grv) {
_drags->set (new VelocityLineDrag (this, grv->base_item(), Temporal::BeatTime), event);
_drags->set (new VelocityLineDrag (*this, grv->base_item(), Temporal::BeatTime), event);
}
}
return true;
@ -910,9 +802,9 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
* over a region.
*/
if (item_type == StartSelectionTrimItem) {
_drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionStartTrim), event);
_drags->set (new SelectionDrag (*this, item, SelectionDrag::SelectionStartTrim), event);
} else if (item_type == EndSelectionTrimItem) {
_drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionEndTrim), event);
_drags->set (new SelectionDrag (*this, item, SelectionDrag::SelectionEndTrim), event);
}
}
@ -936,11 +828,11 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case MouseRange:
switch (item_type) {
case StartSelectionTrimItem:
_drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionStartTrim), event);
_drags->set (new SelectionDrag (*this, item, SelectionDrag::SelectionStartTrim), event);
break;
case EndSelectionTrimItem:
_drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionEndTrim), event);
_drags->set (new SelectionDrag (*this, item, SelectionDrag::SelectionEndTrim), event);
break;
case SelectionItem:
@ -949,34 +841,34 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
return true;
} else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::SecondaryModifier)) {
/* grab selection for moving */
_drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionMove), event);
_drags->set (new SelectionDrag (*this, item, SelectionDrag::SelectionMove), event);
} else {
/* this was debated, but decided the more common action was to make a new selection */
_drags->set (new SelectionDrag (this, item, SelectionDrag::CreateSelection), event);
_drags->set (new SelectionDrag (*this, item, SelectionDrag::CreateSelection), event);
}
break;
case StreamItem:
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::RangeSelectModifier) && !selection->time.empty()) {
_drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionExtend), event);
_drags->set (new SelectionDrag (*this, item, SelectionDrag::SelectionExtend), event);
} else {
_drags->set (new SelectionDrag (this, item, SelectionDrag::CreateSelection), event);
_drags->set (new SelectionDrag (*this, item, SelectionDrag::CreateSelection), event);
}
return true;
break;
case RegionViewNameHighlight:
if (!clicked_regionview->region()->locked()) {
_drags->set (new TrimDrag (this, item, clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region())), event);
_drags->set (new TrimDrag (*this, item, clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region())), event);
return true;
}
break;
default:
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::RangeSelectModifier) && !selection->time.empty()) {
_drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionExtend), event);
_drags->set (new SelectionDrag (*this, item, SelectionDrag::SelectionExtend), event);
} else {
_drags->set (new SelectionDrag (this, item, SelectionDrag::CreateSelection), event);
_drags->set (new SelectionDrag (*this, item, SelectionDrag::CreateSelection), event);
}
}
return true;
@ -994,7 +886,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case RegionViewName:
case StreamItem:
case AutomationTrackItem:
_drags->set (new RegionCutDrag (this, item, canvas_event_sample (event)), event, get_canvas_cursor());
_drags->set (new RegionCutDrag (*this, item, canvas_event_sample (event)), event, get_canvas_cursor());
return true;
break;
default:
@ -1008,44 +900,44 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
/* Existing note: allow trimming/motion */
if ((note = reinterpret_cast<NoteBase*> (item->get_data ("notebase")))) {
if (note->big_enough_to_trim() && note->mouse_near_ends()) {
_drags->set (new NoteResizeDrag (this, item), event, get_canvas_cursor());
_drags->set (new NoteResizeDrag (*this, item), event, get_canvas_cursor());
} else {
_drags->set (new NoteDrag (this, item), event);
_drags->set (new NoteDrag (*this, item), event);
}
}
return true;
case GainLineItem:
_drags->set (new LineDrag (this, item), event);
_drags->set (new LineDrag (*this, item), event);
return true;
break;
case ControlPointItem:
_drags->set (new ControlPointDrag (this, item), event);
_drags->set (new ControlPointDrag (*this, item), event);
return true;
break;
case AutomationLineItem:
_drags->set (new LineDrag (this, item), event);
_drags->set (new LineDrag (*this, item), event);
return true;
break;
case StreamItem:
/* in the past, we created a new midi region here, but perhaps that is best left to the Draw mode */
/* .. now we allow for rubberband selection (region gain) */
_drags->set (new EditorRubberbandSelectDrag (this, item), event);
_drags->set (new EditorRubberbandSelectDrag (*this, get_trackview_group()), event);
return true;
break;
case AutomationTrackItem:
/* rubberband drag to select automation points */
_drags->set (new EditorRubberbandSelectDrag (this, item), event);
_drags->set (new EditorRubberbandSelectDrag (*this, get_trackview_group()), event);
return true;
break;
case RegionItem:
/* rubberband drag to select region gain points */
_drags->set (new EditorRubberbandSelectDrag (this, item), event);
_drags->set (new EditorRubberbandSelectDrag (*this, get_trackview_group()), event);
return true;
break;
@ -1058,7 +950,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) &&
event->type == GDK_BUTTON_PRESS) {
_drags->set (new EditorRubberbandSelectDrag (this, item), event);
_drags->set (new EditorRubberbandSelectDrag (*this, get_trackview_group()), event);
} else if (event->type == GDK_BUTTON_PRESS) {
@ -1067,7 +959,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
{
RegionView* rv = reinterpret_cast<RegionView*> (item->get_data("regionview"));
assert (rv);
_drags->set (new FadeInDrag (this, item, rv, selection->regions, drag_time_domain (rv->region())), event, _cursors->fade_in);
_drags->set (new FadeInDrag (*this, item, rv, selection->regions, drag_time_domain (rv->region())), event, _cursors->fade_in);
return true;
}
@ -1075,7 +967,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
{
RegionView* rv = reinterpret_cast<RegionView*> (item->get_data("regionview"));
assert (rv);
_drags->set (new FadeOutDrag (this, item, rv, selection->regions, drag_time_domain (rv->region())), event, _cursors->fade_out);
_drags->set (new FadeOutDrag (*this, item, rv, selection->regions, drag_time_domain (rv->region())), event, _cursors->fade_out);
return true;
}
@ -1085,7 +977,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
* For not this is not fully implemented */
#if 0
if (!clicked_regionview->region()->locked()) {
_drags->set (new TrimDrag (this, item, clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region()), true), event);
_drags->set (new TrimDrag (*this, item, clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region()), true), event);
return true;
}
#endif
@ -1098,7 +990,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
return true;
}
_drags->set (new FeatureLineDrag (this, item), event);
_drags->set (new FeatureLineDrag (*this, item), event);
return true;
break;
}
@ -1119,7 +1011,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::slip_contents_modifier ())) {
if (!clicked_regionview->region()->locked() && (Config->get_edit_mode() != Lock)) {
_drags->add (new RegionSlipContentsDrag (this, item, clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region())));
_drags->add (new RegionSlipContentsDrag (*this, item, clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region())));
}
} else if (ArdourKeyboard::indicates_copy (event->button.state)) {
add_region_drag (item, event, clicked_regionview, true);
@ -1138,7 +1030,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case LeftFrameHandle:
case RightFrameHandle:
if (!clicked_regionview->region()->locked()) {
_drags->set (new TrimDrag (this, item, clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region()), false), event);
_drags->set (new TrimDrag (*this, item, clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region()), false), event);
return true;
}
break;
@ -1146,7 +1038,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case FadeInTrimHandleItem:
case FadeOutTrimHandleItem:
if (!clicked_regionview->region()->locked()) {
_drags->set (new TrimDrag (this, item, clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region()), true), event);
_drags->set (new TrimDrag (*this, item, clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region()), true), event);
return true;
}
break;
@ -1155,24 +1047,24 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
{
/* rename happens on edit clicks */
if (clicked_regionview->get_name_highlight()) {
_drags->set (new TrimDrag (this, clicked_regionview->get_name_highlight(), clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region())), event);
_drags->set (new TrimDrag (*this, clicked_regionview->get_name_highlight(), clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region())), event);
return true;
}
break;
}
case ControlPointItem:
_drags->set (new ControlPointDrag (this, item), event);
_drags->set (new ControlPointDrag (*this, item), event);
return true;
break;
case AutomationLineItem:
_drags->set (new LineDrag (this, item), event);
_drags->set (new LineDrag (*this, item), event);
return true;
break;
case StreamItem:
_drags->set (new EditorRubberbandSelectDrag (this, item), event);
_drags->set (new EditorRubberbandSelectDrag (*this, item), event);
return true;
case AutomationTrackItem:
@ -1187,20 +1079,20 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
std::shared_ptr<Playlist> pl = p->track()->playlist ();
if (pl->n_regions() == 0) {
/* Parent has no regions; create one so that we have somewhere to put automation */
_drags->set (new RegionCreateDrag (this, item, parent), event);
_drags->set (new RegionCreateDrag (*this, item, parent), event);
} else {
/* See if there's a region before the click that we can extend, and extend it if so */
timepos_t const t (canvas_event_sample (event));
std::shared_ptr<Region> prev = pl->find_next_region (t, End, -1);
if (!prev) {
_drags->set (new RegionCreateDrag (this, item, parent), event);
_drags->set (new RegionCreateDrag (*this, item, parent), event);
} else {
prev->set_length (prev->position ().distance (t));
}
}
} else {
/* rubberband drag to select automation points */
_drags->set (new EditorRubberbandSelectDrag (this, item), event);
_drags->set (new EditorRubberbandSelectDrag (*this, item), event);
}
break;
}
@ -1230,11 +1122,11 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case MouseDraw:
switch (item_type) {
case GainLineItem:
_drags->set (new LineDrag (this, item), event);
_drags->set (new LineDrag (*this, item), event);
return true;
case ControlPointItem:
_drags->set (new ControlPointDrag (this, item), event);
_drags->set (new ControlPointDrag (*this, item), event);
return true;
break;
@ -1255,14 +1147,14 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
/* if there's no line yet, AutomationRangeDrag will need to be told what the initial value of this control is */
float init_value = atv->control()->get_value();
_drags->set (new AutomationRangeDrag (this, atv, init_value, selection->time), event, _cursors->up_down);
_drags->set (new AutomationRangeDrag (*this, atv, init_value, selection->time), event, _cursors->up_down);
return true;
}
if (dynamic_cast<AutomationRegionView*>(clicked_regionview)) {
/* MIDI CC or similar -- TODO handle multiple? */
list<RegionView*> rvl;
rvl.push_back (clicked_regionview);
_drags->set (new AutomationRangeDrag (this, rvl, selection->time,
_drags->set (new AutomationRangeDrag (*this, rvl, selection->time,
clicked_regionview->get_time_axis_view().y_position(),
clicked_regionview->get_time_axis_view().current_height()),
event, _cursors->up_down);
@ -1277,7 +1169,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
list<RegionView*> rvl;
rvl.push_back (clicked_regionview);
// TODO: handle layer_display() == Stacked
_drags->set (new AutomationRangeDrag (this, rvl, selection->time,
_drags->set (new AutomationRangeDrag (*this, rvl, selection->time,
clicked_regionview->get_time_axis_view().y_position(),
clicked_regionview->get_time_axis_view().current_height()),
event, _cursors->up_down);
@ -1319,7 +1211,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
double yy = event->button.y - _trackview_group->canvas_origin().y;
y_pos += floor ((yy - y_pos) / height) * height;
}
_drags->set (new AutomationRangeDrag (this, rvl, selection->time, y_pos, height),
_drags->set (new AutomationRangeDrag (*this, rvl, selection->time, y_pos, height),
event, _cursors->up_down);
}
return true;
@ -1332,7 +1224,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
{
AutomationTimeAxisView* atv = static_cast<AutomationTimeAxisView*> (item->get_data ("trackview"));
if (atv) {
_drags->set (new AutomationDrawDrag (this, nullptr, atv->base_item(), Temporal::AudioTime), event);
_drags->set (new AutomationDrawDrag (*this, nullptr, atv->base_item(), Temporal::AudioTime), event);
}
}
break;
@ -1341,10 +1233,10 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
if ((note = reinterpret_cast<NoteBase*>(item->get_data ("notebase")))) {
if (note->big_enough_to_trim() && note->mouse_near_ends()) {
/* Note is big and pointer is near the end, trim */
_drags->set (new NoteResizeDrag (this, item), event, get_canvas_cursor());
_drags->set (new NoteResizeDrag (*this, item), event, get_canvas_cursor());
} else {
/* Drag note */
_drags->set (new NoteDrag (this, item), event);
_drags->set (new NoteDrag (*this, item), event);
}
return true;
}
@ -1352,14 +1244,14 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case StreamItem:
if (dynamic_cast<MidiTimeAxisView*> (clicked_axisview)) {
_drags->set (new RegionCreateDrag (this, item, clicked_axisview), event);
_drags->set (new RegionCreateDrag (*this, item, clicked_axisview), event);
}
return true;
case RegionItem: {
RegionView* rv;
if ((rv = dynamic_cast<RegionView*> (clicked_regionview))) {
ArdourCanvas::Rectangle* r = dynamic_cast<ArdourCanvas::Rectangle*> (rv->get_canvas_frame());
_drags->set (new AutomationDrawDrag (this, rv->get_canvas_group(), *r, Temporal::AudioTime), event);
_drags->set (new AutomationDrawDrag (*this, rv->get_canvas_group(), *r, Temporal::AudioTime), event);
}
}
break;
@ -1375,13 +1267,13 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
/* resize-drag notes */
if ((note = reinterpret_cast<NoteBase*>(item->get_data ("notebase")))) {
if (note->big_enough_to_trim()) {
_drags->set (new NoteResizeDrag (this, item), event, get_canvas_cursor());
_drags->set (new NoteResizeDrag (*this, item), event, get_canvas_cursor());
}
}
return true;
} else if (clicked_regionview) {
/* do time-FX */
_drags->set (new TimeFXDrag (this, item, clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region())), event);
_drags->set (new TimeFXDrag (*this, item, clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region())), event);
return true;
}
break;
@ -1413,7 +1305,7 @@ Editor::button_press_handler_2 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
return true;
break;
case ControlPointItem:
_drags->set (new ControlPointDrag (this, item), event);
_drags->set (new ControlPointDrag (*this, item), event);
return true;
break;
@ -1423,18 +1315,18 @@ Editor::button_press_handler_2 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
switch (item_type) {
case RegionViewNameHighlight:
_drags->set (new TrimDrag (this, item, clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region())), event);
_drags->set (new TrimDrag (*this, item, clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region())), event);
return true;
break;
case LeftFrameHandle:
case RightFrameHandle:
_drags->set (new TrimDrag (this, item, clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region())), event);
_drags->set (new TrimDrag (*this, item, clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region())), event);
return true;
break;
case RegionViewName:
_drags->set (new TrimDrag (this, clicked_regionview->get_name_highlight(), clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region())), event);
_drags->set (new TrimDrag (*this, clicked_regionview->get_name_highlight(), clicked_regionview, selection->regions.by_layer(), drag_time_domain (clicked_regionview->region())), event);
return true;
break;
@ -2402,28 +2294,6 @@ Editor::edit_control_point (ArdourCanvas::Item* item)
}
}
void
Editor::edit_notes (MidiRegionView* mrv)
{
MidiRegionView::Selection const & s = mrv->selection();
if (s.empty ()) {
return;
}
EditNoteDialog* d = new EditNoteDialog (mrv, s);
d->show_all ();
d->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &Editor::note_edit_done), d));
}
void
Editor::note_edit_done (int r, EditNoteDialog* d)
{
d->done (r);
delete d;
}
void
Editor::edit_region (RegionView* rv)
{
@ -2676,7 +2546,7 @@ Editor::add_region_drag (ArdourCanvas::Item* item, GdkEvent*, RegionView* region
assert (!_drags->active ());
_drags->add (new RegionMoveDrag (this, item, region_view, selection->regions.by_layer(), copy, drag_time_domain (region_view->region())));
_drags->add (new RegionMoveDrag (*this, item, region_view, selection->regions.by_layer(), copy, drag_time_domain (region_view->region())));
}
void
@ -2695,7 +2565,7 @@ Editor::add_region_brush_drag (ArdourCanvas::Item* item, GdkEvent*, RegionView*
}
std::list<RegionView*> empty;
_drags->add (new RegionBrushDrag (this, item, region_view, empty, drag_time_domain (region_view->region())));
_drags->add (new RegionBrushDrag (*this, item, region_view, empty, drag_time_domain (region_view->region())));
}
/** Start a grab where a time range is selected, track(s) are selected, and the
@ -2759,7 +2629,7 @@ Editor::start_selection_grab (ArdourCanvas::Item* /*item*/, GdkEvent* event)
commit_reversible_command ();
_drags->set (new RegionMoveDrag (this, latest_regionviews.front()->get_canvas_group(), latest_regionviews.front(), latest_regionviews, false, drag_time_domain (latest_regionviews.front()->region())), event);
_drags->set (new RegionMoveDrag (*this, latest_regionviews.front()->get_canvas_group(), latest_regionviews.front(), latest_regionviews, false, drag_time_domain (latest_regionviews.front()->region())), event);
}
void
@ -3014,18 +2884,18 @@ Editor::choose_mapping_drag (ArdourCanvas::Item* item, GdkEvent* event)
if (at_end) {
_session->current_reversible_command()->set_name (_("tempo mapping: end-stretch"));
_drags->set (new MappingEndDrag (this, item, map, tempo, *focus, *before_state), event);
_drags->set (new MappingEndDrag (*this, item, map, tempo, *focus, *before_state), event);
return;
}
if (before && focus && after) {
_session->current_reversible_command()->set_name (_("tempo mapping: mid-twist"));
_drags->set (new MappingTwistDrag (this, item, map, *before, *focus, *after, *before_state, ramped), event);
_drags->set (new MappingTwistDrag (*this, item, map, *before, *focus, *after, *before_state, ramped), event);
} else if (ramped && focus && after) {
/* special case 4: user is manipulating a beat line after the INITIAL tempo marker, so there is no prior marker*/
_session->current_reversible_command()->set_name (_("tempo mapping: mid-twist"));
before = focus; /* this is unused in MappingTwistDrag, when ramped is true, but let's not pass in garbage */
_drags->set (new MappingTwistDrag (this, item, map, *before, *focus, *after, *before_state, ramped), event);
_drags->set (new MappingTwistDrag (*this, item, map, *before, *focus, *after, *before_state, ramped), event);
} else {
abort_tempo_mapping (); /* NOTREACHED */
}

View File

@ -111,7 +111,6 @@
#include "note.h"
#include "paste_context.h"
#include "patch_change_dialog.h"
#include "quantize_dialog.h"
#include "region_gain_line.h"
#include "route_time_axis.h"
#include "selection.h"
@ -6038,54 +6037,6 @@ Editor::strip_region_silence ()
}
}
PBD::Command*
Editor::apply_midi_note_edit_op_to_region (MidiOperator& op, MidiRegionView& mrv)
{
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);
}
void
Editor::apply_midi_note_edit_op (MidiOperator& op, const RegionSelection& rs)
{
if (rs.empty()) {
return;
}
bool in_command = false;
vector<MidiRegionView*> views = filter_to_unique_midi_region_views (rs);
for (vector<MidiRegionView*>::iterator mrv = views.begin(); mrv != views.end(); ++mrv) {
Command* cmd = apply_midi_note_edit_op_to_region (op, **mrv);
if (cmd) {
if (!in_command) {
begin_reversible_command (op.name ());
in_command = true;
}
(*cmd)();
_session->add_command (cmd);
}
}
if (in_command) {
commit_reversible_command ();
_session->set_dirty ();
}
}
#include "ardour/midi_source.h" // MidiSource::name()
void
@ -6215,165 +6166,6 @@ Editor::fork_selected_regions ()
}
}
void
Editor::quantize_region ()
{
if (_session) {
quantize_regions(get_regions_from_selection_and_entered ());
}
}
void
Editor::quantize_regions (const RegionSelection& rs)
{
if (rs.n_midi_regions() == 0) {
return;
}
Quantize* quant = get_quantize_op ();
if (!quant) {
return;
}
if (!quant->empty()) {
apply_midi_note_edit_op (*quant, rs);
}
delete quant;
}
Quantize*
Editor::get_quantize_op ()
{
if (!quantize_dialog) {
quantize_dialog = new QuantizeDialog (*this);
}
quantize_dialog->present ();
int r = quantize_dialog->run ();
quantize_dialog->hide ();
if (r != Gtk::RESPONSE_OK) {
return nullptr;
}
return new Quantize (quantize_dialog->snap_start(),
quantize_dialog->snap_end(),
quantize_dialog->start_grid_size(),
quantize_dialog->end_grid_size(),
quantize_dialog->strength(),
quantize_dialog->swing(),
quantize_dialog->threshold());
}
void
Editor::legatize_region (bool shrink_only)
{
if (_session) {
legatize_regions(get_regions_from_selection_and_entered (), shrink_only);
}
}
void
Editor::deinterlace_midi_regions (const RegionSelection& rs)
{
begin_reversible_command (_("de-interlace midi"));
RegionSelection rcopy = rs;
if (_session) {
for (RegionSelection::iterator i = rcopy.begin (); i != rcopy.end(); i++) {
MidiRegionView* const mrv = dynamic_cast<MidiRegionView*> (*i);
if (mrv) {
XMLNode& before (mrv->region()->playlist()->get_state());
/* pass the regions to deinterlace_midi_region*/
_session->deinterlace_midi_region(mrv->midi_region());
XMLNode& after (mrv->region()->playlist()->get_state());
_session->add_command (new MementoCommand<Playlist>(*(mrv->region()->playlist()), &before, &after));
}
}
}
/* Remove the original region(s) safely, without rippling, as part of this command */
remove_regions(rs, false /*can_ripple*/, true /*as_part_of_other_command*/);
commit_reversible_command ();
}
void
Editor::deinterlace_selected_midi_regions ()
{
if (_session) {
RegionSelection rs = get_regions_from_selection_and_entered ();
deinterlace_midi_regions(rs);
}
}
void
Editor::legatize_regions (const RegionSelection& rs, bool shrink_only)
{
if (rs.n_midi_regions() == 0) {
return;
}
Legatize legatize(shrink_only);
apply_midi_note_edit_op (legatize, rs);
}
void
Editor::transform_region ()
{
if (_session) {
transform_regions(get_regions_from_selection_and_entered ());
}
}
void
Editor::transform_regions (const RegionSelection& rs)
{
if (rs.n_midi_regions() == 0) {
return;
}
TransformDialog td;
td.present();
const int r = td.run();
td.hide();
if (r == Gtk::RESPONSE_OK) {
Transform transform(td.get());
apply_midi_note_edit_op(transform, rs);
}
}
void
Editor::transpose_region ()
{
if (_session) {
transpose_regions(get_regions_from_selection_and_entered ());
}
}
void
Editor::transpose_regions (const RegionSelection& rs)
{
if (rs.n_midi_regions() == 0) {
return;
}
TransposeDialog d;
int const r = d.run ();
if (r == RESPONSE_ACCEPT) {
Transpose transpose(d.semitones ());
apply_midi_note_edit_op (transpose, rs);
}
}
void
Editor::insert_patch_change (bool from_context)
@ -6496,6 +6288,43 @@ Editor::apply_filter (Filter& filter, string command, ProgressReporter* progress
}
}
void
Editor::deinterlace_midi_regions (const RegionSelection& rs)
{
begin_reversible_command (_("de-interlace midi"));
RegionSelection rcopy = rs;
if (_session) {
for (RegionSelection::iterator i = rcopy.begin (); i != rcopy.end(); i++) {
MidiRegionView* const mrv = dynamic_cast<MidiRegionView*> (*i);
if (mrv) {
XMLNode& before (mrv->region()->playlist()->get_state());
/* pass the regions to deinterlace_midi_region*/
_session->deinterlace_midi_region(mrv->midi_region());
XMLNode& after (mrv->region()->playlist()->get_state());
_session->add_command (new MementoCommand<Playlist>(*(mrv->region()->playlist()), &before, &after));
}
}
}
/* Remove the original region(s) safely, without rippling, as part of this command */
remove_regions(rs, false /*can_ripple*/, true /*as_part_of_other_command*/);
commit_reversible_command ();
}
void
Editor::deinterlace_selected_midi_regions ()
{
if (_session) {
RegionSelection rs = region_selection ();
deinterlace_midi_regions(rs);
}
}
void
Editor::external_edit_region ()
{
@ -9245,69 +9074,6 @@ Editor::launch_playlist_selector ()
}
}
vector<MidiRegionView*>
Editor::filter_to_unique_midi_region_views (RegionSelection const & ms) const
{
typedef std::pair<std::shared_ptr<MidiSource>,timepos_t> MapEntry;
std::set<MapEntry> single_region_set;
vector<MidiRegionView*> views;
/* build a list of regions that are unique with respect to their source
* and start position. Note: this is non-exhaustive... if someone has a
* non-forked copy of a MIDI region and then suitably modifies it, this
* will still put both regions into the list of things to be acted
* upon.
*
* Solution: user should not select both regions, or should fork one of them.
*/
for (MidiRegionSelection::const_iterator i = ms.begin(); i != ms.end(); ++i) {
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (*i);
if (!mrv) {
continue;
}
MapEntry entry = make_pair (mrv->midi_region()->midi_source(), mrv->region()->start());
if (single_region_set.insert (entry).second) {
views.push_back (mrv);
}
}
return views;
}
void
Editor::midi_action (void (MidiRegionView::*method)())
{
MidiRegionSelection ms = selection->midi_regions();
if (ms.empty()) {
return;
}
if (ms.size() > 1) {
vector<MidiRegionView*> views = filter_to_unique_midi_region_views (ms);
for (vector<MidiRegionView*>::iterator mrv = views.begin(); mrv != views.end(); ++mrv) {
((*mrv)->*method) ();
}
} else {
MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(ms.front());
if (mrv) {
(mrv->*method)();
}
}
}
void
Editor::add_region_marker ()
{

View File

@ -1103,111 +1103,6 @@ Editor::metric_get_timecode (std::vector<ArdourCanvas::Ruler::Mark>& marks, int6
}
}
uint32_t
Editor::count_bars (Beats const & start, Beats const & end) const
{
TempoMapPoints bar_grid;
TempoMap::SharedPtr tmap (TempoMap::use());
bar_grid.reserve (4096);
superclock_t s (tmap->superclock_at (start));
superclock_t e (tmap->superclock_at (end));
tmap->get_grid (bar_grid, s, e, 1);
return bar_grid.size();
}
void
Editor::compute_bbt_ruler_scale (samplepos_t lower, samplepos_t upper)
{
if (_session == 0) {
return;
}
Temporal::BBT_Time lower_beat, upper_beat; // the beats at each end of the ruler
Temporal::TempoMap::SharedPtr tmap (Temporal::TempoMap::use());
Beats floor_lower_beat = std::max (Beats(), tmap->quarters_at_sample (lower)).round_down_to_beat ();
if (floor_lower_beat < Temporal::Beats()) {
floor_lower_beat = Temporal::Beats();
}
const samplepos_t beat_before_lower_pos = tmap->sample_at (floor_lower_beat);
const samplepos_t beat_after_upper_pos = tmap->sample_at ((std::max (Beats(), tmap->quarters_at_sample (upper)).round_down_to_beat()) + Beats (1, 0));
lower_beat = Temporal::TempoMap::use()->bbt_at (timepos_t (beat_before_lower_pos));
upper_beat = Temporal::TempoMap::use()->bbt_at (timepos_t (beat_after_upper_pos));
uint32_t beats = 0;
bbt_bar_helper_on = false;
bbt_bars = 0;
bbt_ruler_scale = bbt_show_many;
const Beats ceil_upper_beat = std::max (Beats(), tmap->quarters_at_sample (upper)).round_up_to_beat() + Beats (1, 0);
if (ceil_upper_beat == floor_lower_beat) {
return;
}
bbt_bars = count_bars (floor_lower_beat, ceil_upper_beat);
double ruler_line_granularity = UIConfiguration::instance().get_ruler_granularity (); //in pixels
ruler_line_granularity = _visible_canvas_width / (ruler_line_granularity*5); //fudge factor '5' probably related to (4+1 beats)/measure, I think
beats = (ceil_upper_beat - floor_lower_beat).get_beats();
double beat_density = ((beats + 1) * ((double) (upper - lower) / (double) (1 + beat_after_upper_pos - beat_before_lower_pos))) / (float)ruler_line_granularity;
/* Only show the bar helper if there aren't many bars on the screen */
if ((bbt_bars < 2) || (beats < 5)) {
bbt_bar_helper_on = true;
}
if (beat_density > 2048) {
bbt_ruler_scale = bbt_show_many;
} else if (beat_density > 1024) {
bbt_ruler_scale = bbt_show_64;
} else if (beat_density > 256) {
bbt_ruler_scale = bbt_show_16;
} else if (beat_density > 64) {
bbt_ruler_scale = bbt_show_4;
} else if (beat_density > 16) {
bbt_ruler_scale = bbt_show_1;
} else if (beat_density > 4) {
bbt_ruler_scale = bbt_show_quarters;
} else if (beat_density > 2) {
bbt_ruler_scale = bbt_show_eighths;
} else if (beat_density > 1) {
bbt_ruler_scale = bbt_show_sixteenths;
} else if (beat_density > 0.5) {
bbt_ruler_scale = bbt_show_thirtyseconds;
} else if (beat_density > 0.25) {
bbt_ruler_scale = bbt_show_sixtyfourths;
} else {
bbt_ruler_scale = bbt_show_onetwentyeighths;
}
/* Now that we know how fine a grid (Ruler) is allowable on this screen, limit it to the coarseness selected by the user */
/* note: GridType and RulerScale are not the same enums, so it's not a simple mathematical operation */
int suggested_scale = (int) bbt_ruler_scale;
int divs = get_grid_music_divisions(_grid_type, 0);
if (_grid_type == GridTypeBar) {
suggested_scale = std::min(suggested_scale, (int) bbt_show_1);
} else if (_grid_type == GridTypeBeat) {
suggested_scale = std::min(suggested_scale, (int) bbt_show_quarters);
} else if ( divs < 4 ) {
suggested_scale = std::min(suggested_scale, (int) bbt_show_eighths);
} else if ( divs < 8 ) {
suggested_scale = std::min(suggested_scale, (int) bbt_show_sixteenths);
} else if ( divs < 16 ) {
suggested_scale = std::min(suggested_scale, (int) bbt_show_thirtyseconds);
} else if ( divs < 32 ) {
suggested_scale = std::min(suggested_scale, (int) bbt_show_sixtyfourths);
} else {
suggested_scale = std::min(suggested_scale, (int) bbt_show_onetwentyeighths);
}
bbt_ruler_scale = (Editor::BBTRulerScale) suggested_scale;
}
static void
edit_last_mark_label (std::vector<ArdourCanvas::Ruler::Mark>& marks, const std::string& newlabel)
{

View File

@ -1005,20 +1005,6 @@ out:
return commit;
}
void
Editor::set_selected_midi_region_view (MidiRegionView& mrv)
{
/* clear note selection in all currently selected MidiRegionViews */
if (get_selection().regions.contains (&mrv) && get_selection().regions.size() == 1) {
/* Nothing to do */
return;
}
midi_action (&MidiRegionView::clear_note_selection);
get_selection().set (&mrv);
}
void
Editor::set_selection (std::list<Selectable*> s, Selection::Operation op)
{
@ -2490,3 +2476,9 @@ Editor::move_selected_tracks (bool up)
ensure_time_axis_view_is_visible (*scroll_to, false);
}
}
RegionSelection
Editor::region_selection()
{
return get_regions_from_selection_and_entered ();
}

View File

@ -449,8 +449,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

@ -29,7 +29,7 @@
using namespace ARDOUR;
using namespace ArdourCanvas;
Hit::Hit (MidiRegionView& region, Item* parent, double size, const std::shared_ptr<NoteType> note, bool with_events)
Hit::Hit (MidiView& region, Item* parent, double size, const std::shared_ptr<NoteType> note, bool with_events)
: NoteBase (region, with_events, note)
{
_polygon = new ArdourCanvas::Polygon (parent);

View File

@ -32,7 +32,7 @@ class Hit : public NoteBase
public:
typedef Evoral::Note<Temporal::Beats> NoteType;
Hit (MidiRegionView& region,
Hit (MidiView& region,
ArdourCanvas::Item* parent,
double size,
const std::shared_ptr<NoteType> note = std::shared_ptr<NoteType>(),

View File

@ -21,7 +21,7 @@
#include "ardour/session.h"
#include "automation_line.h"
#include "editor.h"
#include "editing_context.h"
#include "mergeable_line.h"
#include "route_time_axis.h"
#include "selectable.h"
@ -32,7 +32,7 @@
using namespace ARDOUR;
void
MergeableLine::merge_drawn_line (Editor& e, Session& s, Evoral::ControlList::OrderedPoints& points, bool thin)
MergeableLine::merge_drawn_line (EditingContext& e, Session& s, Evoral::ControlList::OrderedPoints& points, bool thin)
{
if (points.empty()) {
return;

View File

@ -28,7 +28,7 @@
class AutomationLine;
class RouteTimeAxisView;
class Editor;
class EditingContext;
namespace ARDOUR {
class Session;
@ -50,7 +50,7 @@ class MergeableLine
virtual ~MergeableLine() {}
void merge_drawn_line (Editor& e, ARDOUR::Session& s, Evoral::ControlList::OrderedPoints& points, bool thin);
void merge_drawn_line (EditingContext& e, ARDOUR::Session& s, Evoral::ControlList::OrderedPoints& points, bool thin);
private:
std::shared_ptr<AutomationLine> _line;

View File

@ -38,6 +38,7 @@
#include "automation_line.h"
#include "control_point.h"
#include "editor.h"
#include "midi_cue_editor.h"
#include "region_view.h"
#include "ui_config.h"
@ -51,43 +52,6 @@ using namespace ArdourCanvas;
using std::max;
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 ()
{
@ -95,39 +59,38 @@ MidiClipEditorBox::MidiClipEditorBox ()
_header_label.set_alignment (0.0, 0.5);
pack_start (_header_label, false, false, 6);
editor = manage (new MidiClipEditor ());
editor->set_size_request (600, 120);
editor = new MidiCueEditor ();
editor->viewport().set_size_request (600, 120);
pack_start (*editor, true, true);
editor->show ();
pack_start (editor->viewport(), true, true);
editor->viewport().show ();
}
MidiClipEditorBox::~MidiClipEditorBox ()
{
delete editor;
}
void
MidiClipEditorBox::set_session (Session* s)
{
SessionHandlePtr::set_session (s);
editor->set_session (s);
}
void
MidiClipEditorBox::set_region (std::shared_ptr<Region> r, TriggerReference /*notused*/)
{
delete _midi_view;
_midi_view = nullptr;
if (!r) {
set_session (nullptr);
return;
}
set_session (&r->session ());
state_connection.disconnect ();
_region = r;
PBD::PropertyChange interesting_stuff;
region_changed (interesting_stuff);
_region->PropertyChanged.connect (state_connection, invalidator (*this), boost::bind (&MidiClipEditorBox::region_changed, this, _1), gui_context ());
editor->set_region (r);
}
void
MidiClipEditorBox::region_changed (const PBD::PropertyChange& what_changed)
{
}

View File

@ -50,16 +50,7 @@ namespace ArdourCanvas
class Polygon;
}
class MidiClipEditor : public ArdourCanvas::GtkCanvas
{
public:
MidiClipEditor ();
~MidiClipEditor ();
private:
ArdourCanvas::Rectangle* frame;
bool event_handler (GdkEvent* ev);
};
class MidiCueEditor;
class MidiClipEditorBox : public ClipEditorBox
{
@ -76,7 +67,7 @@ private:
Gtk::Label _header_label;
Gtk::Table table;
MidiClipEditor* editor;
MidiCueEditor* editor;
PBD::ScopedConnection state_connection;

View File

@ -0,0 +1,95 @@
/*
* Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
* Copyright (C) 2007 Doug McLain <doug@nostar.net>
* Copyright (C) 2008-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2016-2017 Robin Gareus <robin@gareus.org>
*
* 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 "midi_cue_background.h"
#include "midi_view.h"
CueMidiBackground::CueMidiBackground (ArdourCanvas::Item* parent)
: MidiViewBackground (parent)
, view (nullptr)
, _width (0.)
, _height (0.)
{
}
CueMidiBackground::~CueMidiBackground ()
{
}
void
CueMidiBackground::set_size (double w, double h)
{
_width = w;
_height = h;
update_contents_height ();
HeightChanged (); /* EMIT SIGNAL */
}
double
CueMidiBackground::contents_height() const
{
return _height;
}
double
CueMidiBackground::height() const
{
return _height;
}
double
CueMidiBackground::width() const
{
return _width;
}
uint8_t
CueMidiBackground::get_preferred_midi_channel () const
{
return 0;
}
void
CueMidiBackground::set_note_highlight (bool yn)
{
}
void
CueMidiBackground::record_layer_check (std::shared_ptr<ARDOUR::Region>, samplepos_t)
{
}
void
CueMidiBackground::set_view (MidiView* mv)
{
view = mv;
}
void
CueMidiBackground::apply_note_range_to_children ()
{
if (view) {
view->apply_note_range (lowest_note(), highest_note());
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
* Copyright (C) 2007 Doug McLain <doug@nostar.net>
* Copyright (C) 2008-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2016-2017 Robin Gareus <robin@gareus.org>
*
* 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.
*/
#ifndef __gtk2_ardour_midi_cue_background_h__
#define __gtk2_ardour_midi_cue_background_h__
#include <cstdint>
#include <gtkmm/adjustment.h>
#include "ardour/types.h"
#include "midi_view_background.h"
class MidiView;
class CueMidiBackground : public MidiViewBackground
{
public:
CueMidiBackground (ArdourCanvas::Item* parent);
~CueMidiBackground ();
double height() const;
double width() const;
double contents_height() const;
uint8_t get_preferred_midi_channel () const;
void set_note_highlight (bool);
void record_layer_check (std::shared_ptr<ARDOUR::Region>, samplepos_t);
void set_size (double w, double h);
void set_view (MidiView*);
protected:
MidiView* view;
double _width;
double _height;
void apply_note_range_to_children();
};
#endif /* __gtk2_ardour_midi_cue_background_h__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,194 @@
/*
* 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.
*/
#ifndef __gtk_ardour_midi_cue_editor_h__
#define __gtk_ardour_midi_cue_editor_h__
#include <gtkmm/adjustment.h>
#include "canvas/ruler.h"
#include "cue_editor.h"
namespace Gtk {
class Widget;
}
namespace ArdourCanvas {
class Box;
class Canvas;
class Container;
class GtkCanvasViewport;
class PianoRollHeader;
class ScrollGroup;
class Widget;
}
namespace ArdourWidgets {
class ArdourButton;
}
class MidiCueView;
class CueMidiBackground;
class MidiCueEditor : public CueEditor
{
public:
MidiCueEditor ();
~MidiCueEditor ();
ArdourCanvas::Container* get_trackview_group () const { return data_group; }
ArdourCanvas::Container* get_noscroll_group() const { return no_scroll_group; }
Gtk::Widget& viewport();
Gtk::Widget& toolbox ();
double visible_canvas_width() const { return _visible_canvas_width; }
samplecnt_t current_page_samples() const;
void get_per_region_note_selection (std::list<std::pair<PBD::ID, std::set<std::shared_ptr<Evoral::Note<Temporal::Beats> > > > >&) const {}
Temporal::Beats get_grid_type_as_beats (bool& success, Temporal::timepos_t const & position) const { return Temporal::Beats (1, 0); }
Temporal::Beats get_draw_length_as_beats (bool& success, Temporal::timepos_t const & position) const { return Temporal::Beats (1, 0); }
bool canvas_note_event (GdkEvent* event, ArdourCanvas::Item*);
int32_t get_grid_beat_divisions (Editing::GridType gt) const { return 1; }
int32_t get_grid_music_divisions (Editing::GridType gt, uint32_t event_state) const { return 1; }
void set_region (std::shared_ptr<ARDOUR::MidiTrack>, std::shared_ptr<ARDOUR::MidiRegion>);
ArdourCanvas::ScrollGroup* get_hscroll_group () const { return h_scroll_group; }
ArdourCanvas::ScrollGroup* get_cursor_scroll_group () const { return cursor_scroll_group; }
void set_samples_per_pixel (samplecnt_t);
void set_mouse_mode (Editing::MouseMode, bool force = false);
void step_mouse_mode (bool next);
Editing::MouseMode current_mouse_mode () const;
bool internal_editing() const;
double timebar_height;
size_t n_timebars;
ArdourCanvas::GtkCanvasViewport* get_canvas_viewport() const;
ArdourCanvas::GtkCanvas* get_canvas() const;
int set_state (const XMLNode&, int version);
XMLNode& get_state () const;
void maybe_autoscroll (bool, bool, bool);
bool autoscroll_active() const;
protected:
void register_actions ();
Temporal::timepos_t snap_to_grid (Temporal::timepos_t const & start,
Temporal::RoundMode direction,
ARDOUR::SnapPref gpref) const;
void snap_to_internal (Temporal::timepos_t& first,
Temporal::RoundMode direction = Temporal::RoundNearest,
ARDOUR::SnapPref gpref = ARDOUR::SnapToAny_Visual,
bool ensure_snap = false) const;
bool button_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
bool button_press_handler_1 (ArdourCanvas::Item*, GdkEvent*, ItemType);
bool button_press_handler_2 (ArdourCanvas::Item*, GdkEvent*, ItemType);
bool button_release_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
bool button_press_dispatch (GdkEventButton*);
bool button_release_dispatch (GdkEventButton*);
bool motion_handler (ArdourCanvas::Item*, GdkEvent*, bool from_autoscroll = false);
bool enter_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
bool leave_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
bool key_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
bool key_release_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
void mouse_mode_toggled (Editing::MouseMode);
private:
ArdourCanvas::GtkCanvasViewport* _canvas_viewport;
ArdourCanvas::GtkCanvas* _canvas;
/* The group containing all other groups that are scrolled vertically
and horizontally.
*/
ArdourCanvas::ScrollGroup* hv_scroll_group;
/* The group containing all other groups that are scrolled horizontally ONLY
*/
ArdourCanvas::ScrollGroup* h_scroll_group;
ArdourCanvas::ScrollGroup* v_scroll_group;
/* Scroll group for cursors, scrolled horizontally, above everything else
*/
ArdourCanvas::ScrollGroup* cursor_scroll_group;
ArdourCanvas::Container* global_rect_group;
ArdourCanvas::Container* no_scroll_group;
ArdourCanvas::Container* data_group;
ArdourCanvas::Container* time_line_group;
ArdourCanvas::Ruler* bbt_ruler;
ArdourCanvas::Rectangle* tempo_bar;
ArdourCanvas::Rectangle* meter_bar;
ArdourCanvas::PianoRollHeader* prh;
ArdourCanvas::Rectangle* transport_loop_range_rect;
Gtk::VBox _toolbox;
CueMidiBackground* bg;
MidiCueView* view;
void build_canvas ();
void canvas_allocate (Gtk::Allocation);
RegionSelection region_selection();
bool canvas_enter_leave (GdkEventCrossing* ev);
void metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>&, samplepos_t, samplepos_t, gint);
class BBTMetric : public ArdourCanvas::Ruler::Metric
{
public:
BBTMetric (MidiCueEditor& ec) : context (&ec) {}
void get_marks (std::vector<ArdourCanvas::Ruler::Mark>& marks, int64_t lower, int64_t upper, int maxchars) const {
context->metric_get_bbt (marks, lower, upper, maxchars);
}
private:
MidiCueEditor* context;
};
BBTMetric bbt_metric;
bool canvas_pre_event (GdkEvent*);
void setup_toolbar ();
/* autoscrolling */
bool autoscroll_canvas ();
void start_canvas_autoscroll (bool allow_horiz, bool allow_vert, const ArdourCanvas::Rect& boundary);
void stop_canvas_autoscroll ();
void visual_changer (const VisualChange&);
};
#endif /* __gtk_ardour_midi_cue_editor_h__ */

View File

@ -0,0 +1,120 @@
/*
* Copyright (C) 2024 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 "ardour/midi_region.h"
#include "ardour/midi_source.h"
#include "gtkmm2ext/utils.h"
#include "canvas/debug.h"
#include "editing_context.h"
#include "editor_drag.h"
#include "keyboard.h"
#include "midi_cue_view.h"
#include "pbd/i18n.h"
using namespace Gtkmm2ext;
MidiCueView::MidiCueView (std::shared_ptr<ARDOUR::MidiTrack> mt,
ArdourCanvas::Item& parent,
EditingContext& ec,
MidiViewBackground& bg,
uint32_t basic_color)
: MidiView (mt, parent, ec, bg, basic_color)
{
CANVAS_DEBUG_NAME (_note_group, X_("note group for MIDI cue"));
/* Containers don't get canvas events, so we need an invisible rect
* that will. It will be resized as needed sothat it always covers the
* entire canvas/view.
*/
event_rect = new ArdourCanvas::Rectangle (&parent);
event_rect->set (ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, 10.));
event_rect->Event.connect (sigc::mem_fun (*this, &MidiCueView::canvas_event));
event_rect->set_fill (false);
event_rect->set_outline (false);
_note_group->raise_to_top ();
}
void
MidiCueView::set_height (double h)
{
event_rect->set (ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, h));
}
ArdourCanvas::Item*
MidiCueView::drag_group () const
{
return event_rect;
}
bool
MidiCueView::canvas_event (GdkEvent* ev)
{
return MidiView::canvas_group_event (ev);
}
bool
MidiCueView::scroll (GdkEventScroll* ev)
{
if (_editing_context.drags()->active()) {
return false;
}
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier) ||
Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier)) {
switch (ev->direction) {
case GDK_SCROLL_UP:
_editing_context.reset_zoom (_editing_context.get_current_zoom() / 2);
return true;
case GDK_SCROLL_DOWN:
_editing_context.reset_zoom (_editing_context.get_current_zoom() * 2);
return true;
default:
return false;
}
}
return MidiView::scroll (ev);
}
void
MidiCueView::set_samples_per_pixel (double spp)
{
std::shared_ptr<Temporal::TempoMap> map;
Temporal::timecnt_t duration;
if (_midi_region) {
duration = Temporal::timecnt_t (_midi_region->midi_source()->length().beats());
map.reset (new Temporal::TempoMap (Temporal::Tempo (120, 4), Temporal::Meter (4, 4)));
} else {
duration = Temporal::timecnt_t (Temporal::Beats (4, 0));
map.reset (new Temporal::TempoMap (Temporal::Tempo (120, 4), Temporal::Meter (4, 4)));
}
EditingContext::TempoMapScope tms (_editing_context, map);
std::cerr << "for duration of " << duration << " pixels " << _editing_context.duration_to_pixels (duration) << std::endl;
reset_width_dependent_items (_editing_context.duration_to_pixels (duration));
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2006-2015 David Robillard <d@drobilla.net>
* Copyright (C) 2008-2012 Hans Baier <hansfbaier@googlemail.com>
* Copyright (C) 2008-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2015-2016 Tim Mayberry <mojofunk@gmail.com>
* Copyright (C) 2015-2017 Nick Mainsbridge <mainsbridge@gmail.com>
* Copyright (C) 2015-2017 Robin Gareus <robin@gareus.org>
*
* 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.
*/
#ifndef __gtk_ardour_midi_cue_view_h__
#define __gtk_ardour_midi_cue_view_h__
#include "midi_view.h"
class MidiCueView : public MidiView
{
public:
MidiCueView (std::shared_ptr<ARDOUR::MidiTrack> mt,
ArdourCanvas::Item& parent,
EditingContext& ec,
MidiViewBackground& bg,
uint32_t basic_color);
bool canvas_event (GdkEvent*);
void set_samples_per_pixel (double);
void set_height (double);
ArdourCanvas::Item* drag_group() const;
protected:
bool scroll (GdkEventScroll* ev);
std::shared_ptr<Temporal::TempoMap const> tempo_map;
ArdourCanvas::Rectangle* event_rect;
};
#endif /* __gtk_ardour_midi_cue_view_h__ */

File diff suppressed because it is too large Load Diff

View File

@ -37,6 +37,7 @@
#include "editing.h"
#include "region_view.h"
#include "midi_time_axis.h"
#include "midi_view.h"
#include "time_axis_view_item.h"
#include "automation_line.h"
#include "enums.h"
@ -68,20 +69,23 @@ class PatchChange;
class ItemCounts;
class CursorContext;
class VelocityGhostRegion;
class EditingContext;
class MidiRegionView : public RegionView
class MidiRegionView : public RegionView, public MidiView
{
public:
typedef Evoral::Note<Temporal::Beats> NoteType;
typedef Evoral::Sequence<Temporal::Beats>::Notes Notes;
MidiRegionView (ArdourCanvas::Container* parent,
EditingContext&,
RouteTimeAxisView& tv,
std::shared_ptr<ARDOUR::MidiRegion> r,
double samples_per_pixel,
uint32_t basic_color);
MidiRegionView (ArdourCanvas::Container* parent,
EditingContext&,
RouteTimeAxisView& tv,
std::shared_ptr<ARDOUR::MidiRegion> r,
double samples_per_pixel,
@ -96,6 +100,7 @@ public:
~MidiRegionView ();
void init (bool wfd);
bool display_is_enabled() const;
void set_selected (bool yn);
@ -107,301 +112,34 @@ public:
inline MidiStreamView* midi_stream_view() const
{ return midi_view()->midi_view(); }
void step_add_note (uint8_t channel, uint8_t number, uint8_t velocity,
Temporal::Beats pos, Temporal::Beats len);
void step_sustain (Temporal::Beats beats);
void set_height (double);
void apply_note_range(uint8_t lowest, uint8_t highest, bool force=false);
inline ARDOUR::ColorMode color_mode() const { return midi_view()->color_mode(); }
uint32_t get_fill_color() const;
void color_handler ();
void show_step_edit_cursor (Temporal::Beats pos);
void move_step_edit_cursor (Temporal::Beats pos);
void hide_step_edit_cursor ();
void set_step_edit_cursor_width (Temporal::Beats beats);
std::string get_modifier_name() const;
GhostRegion* add_ghost (TimeAxisView&);
NoteBase* add_note(const std::shared_ptr<NoteType> note, bool visible);
void cut_copy_clear (Editing::CutCopyOp);
bool paste (Temporal::timepos_t const & pos, const ::Selection& selection, PasteContext& ctx);
void paste_internal (Temporal::timepos_t const & pos, unsigned paste_count, float times, const MidiCutBuffer&);
void add_canvas_patch_change (ARDOUR::MidiModel::PatchChangePtr patch);
void remove_canvas_patch_change (PatchChange* pc);
/** Look up the given time and channel in the 'automation' and set keys accordingly.
* @param time the time of the patch change event
* @param channel the MIDI channel of the event
* @param key a reference to an instance of MIDI::Name::PatchPrimaryKey whose fields will
* will be set according to the result of the lookup
*/
void get_patch_key_at (Temporal::Beats time, uint8_t channel, MIDI::Name::PatchPrimaryKey& key) const;
/** Convert a given PatchChange into a PatchPrimaryKey
*/
MIDI::Name::PatchPrimaryKey patch_change_to_patch_key (ARDOUR::MidiModel::PatchChangePtr);
/** Change old_patch to new_patch.
* @param old_patch the canvas patch change which is to be altered
* @param new_patch new patch
*/
void change_patch_change (PatchChange& old_patch, const MIDI::Name::PatchPrimaryKey& new_patch);
void change_patch_change (ARDOUR::MidiModel::PatchChangePtr, Evoral::PatchChange<Temporal::Beats> const &);
void add_patch_change (Temporal::timecnt_t const &, Evoral::PatchChange<Temporal::Beats> const &);
void move_patch_change (PatchChange &, Temporal::Beats);
void delete_patch_change (PatchChange *);
void edit_patch_change (PatchChange *);
void delete_sysex (SysEx*);
/** Change a patch to the next or previous bank/program.
*
* @param patch The patch-change instance (canvas item)
* @param bank If true, step bank, otherwise, step program.
* @param delta Amount to adjust number.
*/
void step_patch (PatchChange& patch, bool bank, int delta);
/** Displays all patch change events in the region as flags on the canvas.
*/
void display_patch_changes();
/** Displays all system exclusive events in the region as flags on the canvas.
*/
void display_sysexes();
void begin_write();
void end_write();
void extend_active_notes();
void begin_drag_edit (std::string const & why);
void end_drag_edit ();
void display_model(std::shared_ptr<ARDOUR::MidiModel> model);
std::shared_ptr<ARDOUR::MidiModel> model() const { return _model; }
/* note_diff commands should start here; this initiates an undo record */
void start_note_diff_command (std::string name = "midi edit");
void note_diff_add_change (NoteBase* ev, ARDOUR::MidiModel::NoteDiffCommand::Property, uint8_t val);
void note_diff_add_change (NoteBase* ev, ARDOUR::MidiModel::NoteDiffCommand::Property, Temporal::Beats val);
void note_diff_add_note (const std::shared_ptr<NoteType> note, bool selected, bool show_velocity = false);
void note_diff_remove_note (NoteBase* ev);
/* note_diff commands should be completed with one of these calls; they may (or may not) commit the undo record */
void apply_note_diff (bool as_subcommand = false, bool was_copy = false);
void abort_note_diff();
void note_entered(NoteBase* ev);
void note_left(NoteBase* ev);
void patch_entered (PatchChange *);
void patch_left (PatchChange *);
void sysex_entered (SysEx* p);
void sysex_left (SysEx* p);
void note_mouse_position (float xfraction, float yfraction, bool can_set_cursor=true);
void unique_select(NoteBase* ev);
void note_selected(NoteBase* ev, bool add, bool extend=false);
void note_deselected(NoteBase* ev);
void delete_selection();
void delete_note (std::shared_ptr<NoteType>);
size_t selection_size() { return _selection.size(); }
void select_all_notes ();
void select_range(Temporal::timepos_t const & start, Temporal::timepos_t const & end);
void invert_selection ();
void extend_selection ();
void duplicate_selection ();
Temporal::Beats earliest_in_selection ();
void move_selection(Temporal::timecnt_t const & dx, double dy, double cumulative_dy);
void note_dropped (NoteBase* ev, Temporal::timecnt_t const & d_qn, int8_t d_note, bool copy);
NoteBase* copy_selection (NoteBase* primary);
void move_copies(Temporal::timecnt_t const & dx_qn, double dy, double cumulative_dy);
void select_notes (std::list<Evoral::event_id_t>, bool allow_audition);
void select_matching_notes (uint8_t notenum, uint16_t channel_mask, bool add, bool extend);
void toggle_matching_notes (uint8_t notenum, uint16_t channel_mask);
/** Test if a note is within this region's range
*
* @param note the note to test
* @param visible will be set to true if the note is within the visible note range, false otherwise.
* @return true iff the note is within the (time) extent of the region.
*/
bool note_in_region_range(const std::shared_ptr<NoteType> note, bool& visible) const;
/* Test if a note is withing this region's time range. Return true if so */
bool note_in_region_time_range(const std::shared_ptr<NoteType> note) const;
/** Get the region position in pixels relative to session. */
double get_position_pixels();
/** Get the region end position in pixels relative to session. */
double get_end_position_pixels();
/** Begin resizing of some notes.
* Called by CanvasMidiNote when resizing starts.
* @param at_front which end of the note (true == note on, false == note off)
*/
void begin_resizing(bool at_front);
void update_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative, double snap_delta, bool with_snap);
void finish_resizing (NoteBase* primary, bool at_front, double delat_x, bool relative, double snap_delta, bool with_snap);
void abort_resizing ();
/** Change the channel of the selection.
* @param channel - the channel number of the new channel, zero-based
*/
void change_channel(uint8_t channel);
enum MouseState {
None,
Pressed,
SelectTouchDragging,
SelectRectDragging,
SelectVerticalDragging,
AddDragging
};
MouseState mouse_state() const { return _mouse_state; }
struct NoteResizeData {
::Note *note;
ArdourCanvas::Rectangle *resize_rect;
};
/** Snap a region relative pixel coordinate to pixel units.
* @param x a pixel coordinate relative to region start
* @param ensure_snap do not use magnetic snap (required for snap delta calculation)
* @return the snapped pixel coordinate relative to region start
*/
double snap_to_pixel(double x, bool ensure_snap = false);
/** Snap a region relative pixel coordinate to time units.
* @param x a pixel coordinate relative to region start
* @param ensure_snap ignore SnapOff and magnetic snap.
* Required for inverting snap logic with modifier keys and snap delta calculation.
* @return the snapped timecnt_t coordinate relative to region start
*/
Temporal::timecnt_t snap_pixel_to_time (double x, bool ensure_snap = false);
void goto_previous_note (bool add_to_selection);
void goto_next_note (bool add_to_selection);
void change_note_lengths (bool, bool, Temporal::Beats beats, bool start, bool end);
void change_velocities (bool up, bool fine, bool allow_smush, bool all_together);
void set_velocity (NoteBase* primary, int velocity);
bool set_velocity_for_notes (std::vector<NoteBase*>& notes, int velocity);
bool set_velocities_for_notes (std::vector<NoteBase*>& notes, std::vector<int>& velocities);
void transpose (bool up, bool fine, bool allow_smush);
void nudge_notes (bool forward, bool fine);
void channel_edit ();
void velocity_edit ();
void show_list_editor ();
typedef std::set<NoteBase*> Selection;
Selection const & selection () const {
return _selection;
}
void selection_as_notelist (Notes& selected, bool allow_all_if_none_selected = false);
void set_channel_selector_scoped_note(NoteBase* note){ _channel_selection_scoped_note = note; }
NoteBase* channel_selector_scoped_note(){ return _channel_selection_scoped_note; }
void trim_front_starting ();
void trim_front_ending ();
/** Add a note to the model, and the view, at a canvas (click) coordinate.
* \param t time in samples relative to the position of the region
* \param y vertical position in pixels
* \param length duration of the note in beats
* \param state the keyboard modifier mask for the canvas event (click).
* \param shift_snap true alters snap behavior to round down always (false if the gui has already done that).
*/
void create_note_at (Temporal::timepos_t const & t, double y, Temporal::Beats length, uint32_t state, bool shift_snap);
/** An external request to clear the note selection, remove MRV from editor
* selection.
*/
void clear_selection ();
ARDOUR::InstrumentInfo& instrument_info() const;
void note_deleted (NoteBase*);
void clear_note_selection ();
double height() const;
void redisplay (bool);
void show_verbose_cursor_for_new_note_value(std::shared_ptr<NoteType> current_note, uint8_t new_note) const;
ArdourCanvas::Item* drag_group() const;
void select_self (bool add);
void unselect_self ();
void select_self_uniquely ();
void begin_drag_edit (std::string const & why);
void set_visibility_note_range (MidiViewBackground::VisibleNoteRange, bool);
protected:
void region_resized (const PBD::PropertyChange&);
void set_flags (XMLNode *);
void store_flags ();
void reset_width_dependent_items (double pixel_width);
void parameter_changed (std::string const & p);
void _redisplay (bool view_only);
protected:
friend class Editor;
void invert_note_selection ();
void extend_note_selection ();
void move_note_starts_earlier_fine () { change_note_lengths (true, false, Temporal::Beats(), true, false); }
void move_note_starts_earlier () { change_note_lengths (false, false, Temporal::Beats(), true, false); }
void move_note_ends_later_fine () { change_note_lengths (true, false, Temporal::Beats(), false, true); }
void move_note_ends_later () { change_note_lengths (false, false, Temporal::Beats(), false, true); }
void move_note_starts_later_fine () { change_note_lengths (true, true, Temporal::Beats(), true, false); }
void move_note_starts_later () { change_note_lengths (false, true, Temporal::Beats(), true, false); }
void move_note_ends_earlier_fine () { change_note_lengths (true, true, Temporal::Beats(), false, true); }
void move_note_ends_earlier () { change_note_lengths (false, true, Temporal::Beats(), false, true); }
void select_next_note () { goto_next_note (false); }
void select_previous_note () { goto_previous_note (false); }
void add_select_next_note () { goto_next_note (true); }
void add_select_previous_note () { goto_previous_note (true); }
void increase_note_velocity () { change_velocities (true, false, false, false); }
void increase_note_velocity_fine () { change_velocities (true, true, false, false); }
void increase_note_velocity_smush () { change_velocities (true, false, true, false); }
void increase_note_velocity_together () { change_velocities (true, false, false, true); }
void increase_note_velocity_fine_smush () { change_velocities (true, true, true, false); }
void increase_note_velocity_fine_together () { change_velocities (true, true, false, true); }
void increase_note_velocity_smush_together () { change_velocities (true, false, true, true); }
void increase_note_velocity_fine_smush_together () { change_velocities (true, true, true, true); }
void decrease_note_velocity () { change_velocities (false, false, false, false); }
void decrease_note_velocity_fine () { change_velocities (false, true, false, false); }
void decrease_note_velocity_smush () { change_velocities (false, false, true, false); }
void decrease_note_velocity_together () { change_velocities (false, false, false, true); }
void decrease_note_velocity_fine_smush () { change_velocities (false, true, true, false); }
void decrease_note_velocity_fine_together () { change_velocities (false, true, false, true); }
void decrease_note_velocity_smush_together () { change_velocities (false, false, true, true); }
void decrease_note_velocity_fine_smush_together () { change_velocities (false, true, true, true); }
void transpose_up_octave () { transpose (true, false, false); }
void transpose_up_octave_smush () { transpose (true, false, true); }
void transpose_up_tone () { transpose (true, true, false); }
void transpose_up_tone_smush () { transpose (true, true, true); }
void transpose_down_octave () { transpose (false, false, false); }
void transpose_down_octave_smush () { transpose (false, false, true); }
void transpose_down_tone () { transpose (false, true, false); }
void transpose_down_tone_smush () { transpose (false, true, true); }
void nudge_notes_later () { nudge_notes (true, false); }
void nudge_notes_later_fine () { nudge_notes (true, true); }
void nudge_notes_earlier () { nudge_notes (false, false); }
void nudge_notes_earlier_fine () { nudge_notes (false, true); }
void quantize_selected_notes ();
uint32_t get_fill_color() const;
void color_handler ();
void region_resized (const PBD::PropertyChange&);
bool canvas_group_event (GdkEvent*);
private:
@ -414,214 +152,27 @@ public:
friend class EditNoteDialog;
/** Play the NoteOn event of the given note immediately
* and schedule the playback of the corresponding NoteOff event.
*/
void play_midi_note (std::shared_ptr<NoteType> note);
void start_playing_midi_note (std::shared_ptr<NoteType> note);
void start_playing_midi_chord (std::vector<std::shared_ptr<NoteType> > notes);
/** Clear the note selection of just this midi region
*/
void clear_selection_internal ();
void clear_events ();
bool canvas_group_event(GdkEvent* ev);
bool note_canvas_event(GdkEvent* ev);
void midi_channel_mode_changed ();
PBD::ScopedConnection _channel_mode_changed_connection;
void instrument_settings_changed ();
PBD::ScopedConnection _instrument_changed_connection;
void change_note_channel (NoteBase *, int8_t, bool relative=false);
void change_note_velocity(NoteBase* ev, int8_t vel, bool relative=false);
uint8_t change_note_note(NoteBase* ev, int8_t note, bool relative=false);
void change_note_time(NoteBase* ev, ARDOUR::MidiModel::TimeType, bool relative=false);
void change_note_length (NoteBase *, ARDOUR::MidiModel::TimeType);
void trim_note(NoteBase* ev, ARDOUR::MidiModel::TimeType start_delta,
ARDOUR::MidiModel::TimeType end_delta);
void update_drag_selection (Temporal::timepos_t const & start, Temporal::timepos_t const & end, double y0, double y1, bool extend);
void update_vertical_drag_selection (double last_y, double y, bool extend);
void add_to_selection (NoteBase*);
void remove_from_selection (NoteBase*);
std::string get_note_name (std::shared_ptr<NoteType> note, uint8_t note_value) const;
void show_verbose_cursor (std::string const &, double, double) const;
void show_verbose_cursor (std::shared_ptr<NoteType>) const;
uint8_t get_velocity_for_add (ARDOUR::MidiModel::TimeType time) const;
uint8_t get_channel_for_add (ARDOUR::MidiModel::TimeType time) const;
uint8_t _current_range_min;
uint8_t _current_range_max;
typedef boost::unordered_map<std::shared_ptr<NoteType>, NoteBase*> Events;
typedef boost::unordered_map<ARDOUR::MidiModel::PatchChangePtr, std::shared_ptr<PatchChange> > PatchChanges;
typedef boost::unordered_map<ARDOUR::MidiModel::constSysExPtr, std::shared_ptr<SysEx> > SysExes;
typedef std::vector<NoteBase*> CopyDragEvents;
std::shared_ptr<ARDOUR::MidiModel> _model;
Events _events;
CopyDragEvents _copy_drag_events;
PatchChanges _patch_changes;
SysExes _sys_exes;
Note** _active_notes;
ArdourCanvas::Container* _note_group;
ARDOUR::MidiModel::NoteDiffCommand* _note_diff_command;
NoteBase* _ghost_note;
double _last_ghost_x;
double _last_ghost_y;
ArdourCanvas::Rectangle* _step_edit_cursor;
Temporal::Beats _step_edit_cursor_width;
Temporal::Beats _step_edit_cursor_position;
NoteBase* _channel_selection_scoped_note;
MouseState _mouse_state;
int _pressed_button;
/** Currently selected NoteBase objects */
Selection _selection;
MidiCutBuffer* selection_as_cut_buffer () const;
/** New notes (created in the current command) which should be selected
* when they appear after the command is applied. */
std::set< std::shared_ptr<NoteType> > _marked_for_selection;
/** Notes that should be selected when the model is redisplayed. */
std::set<Evoral::event_id_t> _pending_note_selection;
/** New notes (created in the current command) which should have visible velocity
* when they appear after the command is applied. */
std::set< std::shared_ptr<NoteType> > _marked_for_velocity;
std::vector<NoteResizeData *> _resize_data;
/** connection used to connect to model's ContentChanged signal */
PBD::ScopedConnection content_connection;
NoteBase* find_canvas_note (std::shared_ptr<NoteType>);
NoteBase* find_canvas_note (Evoral::event_id_t id);
Events::iterator _optimization_iterator;
std::shared_ptr<PatchChange> find_canvas_patch_change (ARDOUR::MidiModel::PatchChangePtr p);
std::shared_ptr<SysEx> find_canvas_sys_ex (ARDOUR::MidiModel::SysExPtr s);
friend class VelocityGhostRegion;
void sync_velocity_drag (double factor);
void update_note (NoteBase*, bool update_ghost_regions = true);
void update_sustained (Note *, bool update_ghost_regions = true);
void update_hit (Hit *, bool update_ghost_regions = true);
void create_ghost_note (double, double, uint32_t state);
void update_ghost_note (double, double, uint32_t state);
MidiListEditor* _list_editor;
bool _no_sound_notes;
void snap_changed ();
PBD::ScopedConnection snap_changed_connection;
void clear_ghost_events() {}
void ghosts_model_changed() {}
void ghosts_view_changed();
void ghost_remove_note (NoteBase*) {}
void ghost_add_note (NoteBase*) {}
void ghost_sync_selection (NoteBase*);
bool motion (GdkEventMotion*);
bool scroll (GdkEventScroll*);
bool key_press (GdkEventKey*);
bool key_release (GdkEventKey*);
bool button_press (GdkEventButton*);
bool button_release (GdkEventButton*);
bool enter_notify (GdkEventCrossing*);
bool leave_notify (GdkEventCrossing*);
void drop_down_keys ();
void maybe_select_by_position (GdkEventButton* ev, double x, double y);
void get_events (Events& e, Evoral::Sequence<Temporal::Beats>::NoteOperator op, uint8_t val, int chan_mask = 0);
void display_patch_changes_on_channel (uint8_t, bool);
void connect_to_diskstream ();
void data_recorded (std::weak_ptr<ARDOUR::MidiSource>);
/** Get grid type as beats, or default to 1 if not snapped to beats. */
Temporal::Beats get_grid_beats(Temporal::timepos_t const & pos) const;
Temporal::Beats get_draw_length_beats(Temporal::timepos_t const & pos) const;
void remove_ghost_note ();
void mouse_mode_changed ();
void enter_internal (uint32_t state);
void leave_internal ();
void hide_verbose_cursor ();
void mouse_mode_changed ();
samplecnt_t _last_display_zoom;
double contents_height() const { return (_height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 2); }
double _last_event_x;
double _last_event_y;
bool _entered;
NoteBase* _entered_note;
bool _select_all_notes_after_add;
bool _mouse_changed_selection;
Gtkmm2ext::Color _patch_change_outline;
Gtkmm2ext::Color _patch_change_fill;
PBD::ScopedConnection _mouse_mode_connection;
std::shared_ptr<CursorContext> _press_cursor_ctx;
ARDOUR::ChannelMode get_channel_mode() const;
uint16_t get_selected_channels () const;
inline double contents_height() const { return (_height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 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(); }
double note_to_y (uint8_t note) const;
uint8_t y_to_note (double y) const;
void update_patch_changes ();
void update_sysexes ();
void view_changed ();
void model_changed ();
void sync_ghost_selection (NoteBase*);
struct SplitInfo {
Temporal::Beats time;
Temporal::Beats base_len;
int note;
int channel;
int velocity;
int off_velocity;
SplitInfo (Temporal::Beats const & t, Temporal::Beats const & l, int n, int c, int v, int ov)
: time (t)
, base_len (l)
, note (n)
, channel (c)
, velocity (v)
, off_velocity (ov) {}
};
std::vector<SplitInfo> split_info;
uint32_t split_tuple;
bool note_splitting;
void start_note_splitting ();
void end_note_splitting ();
void split_notes_grid ();
void split_notes_more ();
void split_notes_less ();
void join_notes ();
void join_notes_on_channel (int channel);
void add_split_notes ();
void connect_to_diskstream ();
};

View File

@ -29,8 +29,8 @@
#include <gtkmm2ext/gtk_ui.h>
#include "canvas/line_set.h"
#include "canvas/rectangle.h"
#include "canvas/line_set.h"
#include "ardour/midi_region.h"
#include "ardour/midi_source.h"
@ -64,14 +64,7 @@ using namespace Editing;
MidiStreamView::MidiStreamView (MidiTimeAxisView& tv)
: StreamView (tv)
, note_range_adjustment(0.0f, 0.0f, 0.0f)
, _range_dirty(false)
, _range_sum_cache(-1.0)
, _lowest_note(UIConfiguration::instance().get_default_lower_midi_note())
, _highest_note(UIConfiguration::instance().get_default_upper_midi_note())
, _data_note_min(60)
, _data_note_max(71)
, _note_lines (0)
, MidiViewBackground (_canvas_group)
, _updates_suspended (false)
{
/* use a dedicated group for MIDI regions (on top of the grid and lines) */
@ -82,39 +75,27 @@ MidiStreamView::MidiStreamView (MidiTimeAxisView& tv)
/* put the note lines in the timeaxisview's group, so it
can be put below ghost regions from MIDI underlays
*/
_note_lines = new ArdourCanvas::LineSet (_canvas_group, ArdourCanvas::LineSet::Horizontal);
_note_lines->Event.connect(
sigc::bind(sigc::mem_fun(_trackview.editor(),
&PublicEditor::canvas_stream_view_event),
_note_lines, &_trackview));
_note_lines->lower_to_bottom();
color_handler ();
UIConfiguration::instance().ColorsChanged.connect(sigc::mem_fun(*this, &MidiStreamView::color_handler));
UIConfiguration::instance().ParameterChanged.connect(sigc::mem_fun(*this, &MidiStreamView::parameter_changed));
note_range_adjustment.set_page_size(_highest_note - _lowest_note);
note_range_adjustment.set_value(_lowest_note);
note_range_adjustment.signal_value_changed().connect(
sigc::mem_fun(*this, &MidiStreamView::note_range_adjustment_changed));
}
MidiStreamView::~MidiStreamView ()
{
undisplay_track ();
}
void
MidiStreamView::parameter_changed (string const & param)
{
if (param == X_("max-note-height")) {
apply_note_range (_lowest_note, _highest_note, true);
} else {
StreamView::parameter_changed (param);
}
StreamView::parameter_changed (param);
}
RegionView*
@ -129,12 +110,12 @@ MidiStreamView::create_region_view (std::shared_ptr<Region> r, bool /*wfd*/, boo
RegionView* region_view = NULL;
if (recording) {
region_view = new MidiRegionView (
_region_group, _trackview, region,
_samples_per_pixel, region_color, recording,
_region_group, _trackview.editor(), _trackview, region,
_samples_per_pixel, MidiViewBackground::region_color(), recording,
TimeAxisViewItem::Visibility(TimeAxisViewItem::ShowFrame));
} else {
region_view = new MidiRegionView (_region_group, _trackview, region,
_samples_per_pixel, region_color);
region_view = new MidiRegionView (_region_group, _trackview.editor(), _trackview, region,
_samples_per_pixel, MidiViewBackground::region_color());
}
region_view->init (false);
@ -179,7 +160,7 @@ MidiStreamView::add_region_view_internal (std::shared_ptr<Region> r, bool wait_f
/* fit note range if we are importing */
if (_trackview.session()->operation_in_progress (Operations::insert_file)) {
/* this will call display_region() */
set_note_range (ContentsRange);
set_note_visibility_range_style (ContentsRange);
}
}
@ -232,6 +213,13 @@ MidiStreamView::display_track (std::shared_ptr<Track> tr)
NoteRangeChanged(); /* EMIT SIGNAL*/
}
void
MidiStreamView::update_contents_height ()
{
StreamView::update_contents_height();
MidiViewBackground::update_contents_height ();
}
void
MidiStreamView::update_contents_metrics(std::shared_ptr<Region> r)
{
@ -243,21 +231,6 @@ MidiStreamView::update_contents_metrics(std::shared_ptr<Region> r)
}
}
bool
MidiStreamView::update_data_note_range(uint8_t min, uint8_t max)
{
bool dirty = false;
if (min < _data_note_min) {
_data_note_min = min;
dirty = true;
}
if (max > _data_note_max) {
_data_note_max = max;
dirty = true;
}
return dirty;
}
void
MidiStreamView::set_layer_display (LayerDisplay d)
{
@ -314,140 +287,7 @@ MidiStreamView::redisplay_track ()
}
void
MidiStreamView::update_contents_height ()
{
StreamView::update_contents_height();
_note_lines->set_extent (ArdourCanvas::COORD_MAX);
apply_note_range (lowest_note(), highest_note(), true);
}
void
MidiStreamView::draw_note_lines()
{
if (!_note_lines || _updates_suspended) {
return;
}
double y;
double prev_y = 0.;
Gtkmm2ext::Color black = UIConfiguration::instance().color_mod ("piano roll black", "piano roll black");
Gtkmm2ext::Color white = UIConfiguration::instance().color_mod ("piano roll white", "piano roll white");
Gtkmm2ext::Color outline = UIConfiguration::instance().color ("piano roll black outline");
Gtkmm2ext::Color color;
ArdourCanvas::LineSet::ResetRAII lr (*_note_lines);
if (child_height() < 140 || note_height() < 3) {
/* track is too small for note lines, or there are too many */
return;
}
/* do this is order of highest ... lowest since that matches the
* coordinate system in which y=0 is at the top
*/
for (int i = highest_note() + 1; i >= lowest_note(); --i) {
y = floor (note_to_y (i));
/* add a thicker line/bar which covers the entire vertical height of this note. */
switch (i % 12) {
case 1:
case 3:
case 6:
case 8:
case 10:
color = black;
break;
case 4:
case 11:
/* this is the line actually corresponding to the division between B & C and E & F */
_note_lines->add_coord (y, 1.0, outline);
/* fallthrough */
default:
color = white;
break;
}
double h = y - prev_y;
double middle = y + (h/2.0);
if (!fmod (h, 2.) && !fmod (middle, 1.)) {
middle += 0.5;
}
if (middle >= 0 && h > 1.0) {
_note_lines->add_coord (middle, h, color);
}
prev_y = y;
}
}
void
MidiStreamView::set_note_range(VisibleNoteRange r)
{
if (r == FullRange) {
_lowest_note = 0;
_highest_note = 127;
} else {
_lowest_note = _data_note_min;
_highest_note = _data_note_max;
}
apply_note_range(_lowest_note, _highest_note, true);
}
void
MidiStreamView::apply_note_range(uint8_t lowest, uint8_t highest, bool to_region_views)
{
_highest_note = highest;
_lowest_note = lowest;
float uiscale = UIConfiguration::instance().get_ui_scale();
uiscale = expf (uiscale) / expf (1.f);
const int mnh = UIConfiguration::instance().get_max_note_height();
int const max_note_height = std::max<int> (mnh, mnh * uiscale);
int const range = _highest_note - _lowest_note;
int const available_note_range = floor (child_height() / max_note_height);
int additional_notes = available_note_range - range;
/* distribute additional notes to higher and lower ranges, clamp at 0 and 127 */
for (int i = 0; i < additional_notes; i++){
if (i % 2 && _highest_note < 127){
_highest_note++;
}
else if (i % 2) {
_lowest_note--;
}
else if (_lowest_note > 0){
_lowest_note--;
}
else {
_highest_note++;
}
}
note_range_adjustment.set_page_size (_highest_note - _lowest_note);
note_range_adjustment.set_value (_lowest_note);
draw_note_lines();
if (to_region_views) {
apply_note_range_to_regions ();
}
NoteRangeChanged(); /* EMIT SIGNAL*/
}
void
MidiStreamView::apply_note_range_to_regions ()
MidiStreamView::apply_note_range_to_children ()
{
if (!_updates_suspended) {
for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
@ -456,13 +296,6 @@ MidiStreamView::apply_note_range_to_regions ()
}
}
void
MidiStreamView::update_note_range(uint8_t note_num)
{
_data_note_min = min(_data_note_min, note_num);
_data_note_max = max(_data_note_max, note_num);
}
void
MidiStreamView::setup_rec_box ()
{
@ -559,8 +392,9 @@ MidiStreamView::setup_rec_box ()
void
MidiStreamView::color_handler ()
{
MidiViewBackground::color_handler ();
_region_group->set_render_with_alpha (UIConfiguration::instance().modifier ("region alpha").a());
draw_note_lines ();
if (_trackview.is_midi_track()) {
canvas_rect->set_fill_color (UIConfiguration::instance().color_mod ("midi track base", "midi track base"));
@ -573,34 +407,6 @@ MidiStreamView::color_handler ()
}
}
void
MidiStreamView::note_range_adjustment_changed()
{
double sum = note_range_adjustment.get_value() + note_range_adjustment.get_page_size();
int lowest = (int) floor(note_range_adjustment.get_value());
int highest;
if (sum == _range_sum_cache) {
//cerr << "cached" << endl;
highest = (int) floor(sum);
} else {
//cerr << "recalc" << endl;
highest = lowest + (int) floor(note_range_adjustment.get_page_size());
_range_sum_cache = sum;
}
if (lowest == _lowest_note && highest == _highest_note) {
return;
}
//cerr << "note range adjustment changed: " << lowest << " " << highest << endl;
//cerr << " val=" << v_zoom_adjustment.get_value() << " page=" << v_zoom_adjustment.get_page_size() << " sum=" << v_zoom_adjustment.get_value() + v_zoom_adjustment.get_page_size() << endl;
_lowest_note = lowest;
_highest_note = highest;
apply_note_range(lowest, highest, true);
}
void
MidiStreamView::update_rec_box ()
{
@ -618,21 +424,6 @@ MidiStreamView::update_rec_box ()
mrv->extend_active_notes ();
}
uint8_t
MidiStreamView::y_to_note (double y) const
{
int const n = ((contents_height() - y) / contents_height() * (double)contents_note_range())
+ lowest_note();
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, highest_note());
}
/** Suspend updates to the regions' note ranges and our
* note lines until resume_updates() is called.
@ -652,7 +443,7 @@ MidiStreamView::resume_updates ()
_updates_suspended = false;
draw_note_lines ();
apply_note_range_to_regions ();
apply_note_range_to_children ();
_canvas_group->redraw ();
}
@ -710,3 +501,27 @@ MidiStreamView::get_regions_with_selected_data (RegionSelection& rs)
}
}
}
void
MidiStreamView::set_note_highlight (bool yn)
{
dynamic_cast<MidiTimeAxisView*> (&_trackview)->set_note_highlight (yn);
}
uint8_t
MidiStreamView::get_preferred_midi_channel () const
{
return dynamic_cast<MidiTimeAxisView*> (&_trackview)->get_preferred_midi_channel();
}
void
MidiStreamView::record_layer_check (std::shared_ptr<ARDOUR::Region> r, samplepos_t t)
{
check_record_layers (r, t);
}
double
MidiStreamView::y_position () const
{
return _trackview.y_position();
}

View File

@ -28,6 +28,7 @@
#include "ardour/location.h"
#include "enums.h"
#include "midi_view_background.h"
#include "streamview.h"
#include "time_axis_view_item.h"
#include "route_time_axis.h"
@ -57,7 +58,7 @@ class RegionSelection;
class CrossfadeView;
class Selection;
class MidiStreamView : public StreamView
class MidiStreamView : public StreamView, public MidiViewBackground
{
public:
MidiStreamView (MidiTimeAxisView&);
@ -66,65 +67,38 @@ public:
void get_inverted_selectables (Selection&, std::list<Selectable* >& results);
void get_regions_with_selected_data (RegionSelection&);
enum VisibleNoteRange {
FullRange,
ContentsRange
};
Gtk::Adjustment note_range_adjustment;
void set_note_range(VisibleNoteRange r);
inline uint8_t lowest_note() const { return _lowest_note; }
inline uint8_t highest_note() const { return _highest_note; }
void update_note_range(uint8_t note_num);
void set_layer_display (LayerDisplay);
//bool can_change_layer_display() const { return false; } // revert this change for now. Although stacked view is weirdly implemented wrt the "scroomer", it is still necessary to be able to manage layered regions.
void redisplay_track ();
inline double contents_height() const {
double contents_height() const {
return (child_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 2);
}
inline double note_to_y(uint8_t note) const {
return contents_height() - (note + 1 - lowest_note()) * note_height() + 1;
}
uint8_t y_to_note(double y) const;
inline double note_height() const {
return contents_height() / (double)contents_note_range();
}
inline uint8_t contents_note_range() const {
return highest_note() - lowest_note() + 1;
}
sigc::signal<void> NoteRangeChanged;
double y_position () const;
RegionView* create_region_view (std::shared_ptr<ARDOUR::Region>, bool, bool);
bool paste (Temporal::timepos_t const & pos, const Selection& selection, PasteContext& ctx);
void apply_note_range(uint8_t lowest, uint8_t highest, bool to_region_views);
void suspend_updates ();
void resume_updates ();
ArdourCanvas::Container* region_canvas () const { return _region_group; }
void parameter_changed (std::string const &);
uint8_t get_preferred_midi_channel () const;
void record_layer_check (std::shared_ptr<ARDOUR::Region>, samplepos_t);
void set_note_highlight (bool);
protected:
void setup_rec_box ();
void update_rec_box ();
bool updates_suspended() const { return _updates_suspended; }
ArdourCanvas::Container* _region_group;
private:
RegionView* add_region_view_internal (
std::shared_ptr<ARDOUR::Region>,
bool wait_for_waves,
@ -132,27 +106,13 @@ private:
void display_region(MidiRegionView* region_view, bool load_model);
void display_track (std::shared_ptr<ARDOUR::Track> tr);
void update_contents_height ();
void draw_note_lines();
bool update_data_note_range(uint8_t min, uint8_t max);
void update_contents_metrics(std::shared_ptr<ARDOUR::Region> r);
void update_contents_metrics (std::shared_ptr<ARDOUR::Region> r);
void color_handler ();
void apply_note_range_to_children ();
void note_range_adjustment_changed();
void apply_note_range_to_regions ();
bool _range_dirty;
double _range_sum_cache;
uint8_t _lowest_note; ///< currently visible
uint8_t _highest_note; ///< currently visible
uint8_t _data_note_min; ///< in data
uint8_t _data_note_max; ///< in data
ArdourCanvas::LineSet* _note_lines;
/** true if updates to the note lines and regions are currently suspended */
bool _updates_suspended;
bool _updates_suspended;
};
#endif /* __ardour_midi_streamview_h__ */

View File

@ -122,18 +122,18 @@ MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session* sess, ArdourCanva
, RouteTimeAxisView (ed, sess, canvas)
, _ignore_signals(false)
, _asked_all_automation(false)
, _piano_roll_header(0)
, _piano_roll_header(nullptr)
, _note_mode(Sustained)
, _note_mode_item(0)
, _percussion_mode_item(0)
, _percussion_mode_item(nullptr)
, _color_mode(MeterColors)
, _meter_color_mode_item(0)
, _channel_color_mode_item(0)
, _meter_color_mode_item(nullptr)
, _channel_color_mode_item(nullptr)
, _track_color_mode_item(0)
, _channel_selector (0)
, _step_edit_item (0)
, controller_menu (0)
, _step_editor (0)
, _channel_selector (nullptr)
, _step_edit_item (nullptr)
, controller_menu (nullptr)
, _step_editor (nullptr)
, velocity_menu_item (nullptr)
{
_midnam_model_selector.disable_scrolling();
@ -164,7 +164,9 @@ MidiTimeAxisView::parameter_changed (string const & param)
void
MidiTimeAxisView::set_note_highlight (uint8_t note)
{
_piano_roll_header->set_note_highlight (note);
if (_piano_roll_header) {
_piano_roll_header->set_note_highlight (note);
}
}
void
@ -358,13 +360,20 @@ MidiTimeAxisView::first_idle ()
MidiTimeAxisView::~MidiTimeAxisView ()
{
delete _view;
_view = nullptr;
delete _channel_selector;
_channel_selector = nullptr;
delete _piano_roll_header;
_piano_roll_header = 0;
_piano_roll_header = nullptr;
delete controller_menu;
controller_menu = nullptr;
delete _step_editor;
_step_editor = nullptr;
}
void
@ -737,12 +746,12 @@ MidiTimeAxisView::append_extra_display_menu_items ()
range_items.push_back (
MenuElem (_("Show Full Range"),
sigc::bind (sigc::mem_fun(*this, &MidiTimeAxisView::set_note_range),
sigc::bind (sigc::mem_fun(*this, &MidiTimeAxisView::set_visibility_note_range),
MidiStreamView::FullRange, true)));
range_items.push_back (
MenuElem (_("Fit Contents"),
sigc::bind (sigc::mem_fun(*this, &MidiTimeAxisView::set_note_range),
sigc::bind (sigc::mem_fun(*this, &MidiTimeAxisView::set_visibility_note_range),
MidiStreamView::ContentsRange, true)));
items.push_back (MenuElem (_("Note Range"), *range_menu));
@ -1317,14 +1326,14 @@ MidiTimeAxisView::set_color_mode (ColorMode mode, bool force, bool redisplay, bo
}
void
MidiTimeAxisView::set_note_range (MidiStreamView::VisibleNoteRange range, bool apply_to_selection)
MidiTimeAxisView::set_visibility_note_range (MidiStreamView::VisibleNoteRange range, bool apply_to_selection)
{
if (apply_to_selection) {
_editor.get_selection().tracks.foreach_midi_time_axis (
boost::bind (&MidiTimeAxisView::set_note_range, _1, range, false));
boost::bind (&MidiTimeAxisView::set_visibility_note_range, _1, range, false));
} else {
if (!_ignore_signals) {
midi_view()->set_note_range(range);
midi_view()->set_note_visibility_range_style (range);
}
}
}

View File

@ -113,7 +113,7 @@ public:
void get_per_region_note_selection (std::list<std::pair<PBD::ID, std::set<std::shared_ptr<Evoral::Note<Temporal::Beats> > > > >&);
void use_midnam_info ();
void set_note_range (MidiStreamView::VisibleNoteRange range, bool apply_to_selection = false);
void set_visibility_note_range (MidiStreamView::VisibleNoteRange range, bool apply_to_selection = false);
protected:
void start_step_editing ();

4687
gtk2_ardour/midi_view.cc Normal file

File diff suppressed because it is too large Load Diff

638
gtk2_ardour/midi_view.h Normal file
View File

@ -0,0 +1,638 @@
/*
* Copyright (C) 2006-2015 David Robillard <d@drobilla.net>
* Copyright (C) 2008-2012 Hans Baier <hansfbaier@googlemail.com>
* Copyright (C) 2008-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2015-2016 Tim Mayberry <mojofunk@gmail.com>
* Copyright (C) 2015-2017 Nick Mainsbridge <mainsbridge@gmail.com>
* Copyright (C) 2015-2017 Robin Gareus <robin@gareus.org>
*
* 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.
*/
#ifndef __gtk_ardour_midi_view_h__
#define __gtk_ardour_midi_view_h__
#include <string>
#include <vector>
#include <stdint.h>
#include <boost/unordered_map.hpp>
#include <sigc++/signal.h>
#include "pbd/signals.h"
#include "ardour/midi_model.h"
#include "ardour/types.h"
#include "editing.h"
#include "region_view.h"
#include "midi_view_background.h"
#include "time_axis_view_item.h"
#include "automation_line.h"
#include "enums.h"
namespace ARDOUR {
class MidiRegion;
class MidiModel;
class MidiTrack;
class Filter;
};
namespace MIDI {
namespace Name {
struct PatchPrimaryKey;
};
};
class SysEx;
class Note;
class Hit;
class MidiTimeAxisView;
class NoteBase;
class GhostRegion;
class AutomationTimeAxisView;
class AutomationRegionView;
class MidiCutBuffer;
class MidiListEditor;
class EditNoteDialog;
class PatchChange;
class ItemCounts;
class CursorContext;
class VelocityGhostRegion;
class EditingContext;
class PasteContext;
class MidiView : public virtual sigc::trackable
{
public:
typedef Evoral::Note<Temporal::Beats> NoteType;
typedef Evoral::Sequence<Temporal::Beats>::Notes Notes;
MidiView (std::shared_ptr<ARDOUR::MidiTrack> mt,
ArdourCanvas::Item& parent,
EditingContext& ec,
MidiViewBackground& bg,
uint32_t basic_color);
MidiView (MidiView const & other);
virtual ~MidiView ();
void init (bool wfd);
virtual void set_samples_per_pixel (double) {};
virtual bool display_is_enabled() const { return true; }
virtual ArdourCanvas::Item* drag_group() const = 0;
void step_add_note (uint8_t channel, uint8_t number, uint8_t velocity,
Temporal::Beats pos, Temporal::Beats len);
void step_sustain (Temporal::Beats beats);
virtual void set_height (double);
void apply_note_range(uint8_t lowest, uint8_t highest, bool force=false);
// inline ARDOUR::ColorMode color_mode() const { return _background->color_mode(); }
virtual uint32_t get_fill_color() const;
void color_handler ();
void show_step_edit_cursor (Temporal::Beats pos);
void move_step_edit_cursor (Temporal::Beats pos);
void hide_step_edit_cursor ();
void set_step_edit_cursor_width (Temporal::Beats beats);
virtual GhostRegion* add_ghost (TimeAxisView&) { return nullptr; }
virtual std::string get_modifier_name() const;
void set_region (std::shared_ptr<ARDOUR::MidiRegion>);
void set_model (std::shared_ptr<ARDOUR::MidiModel>);
NoteBase* add_note(const std::shared_ptr<NoteType> note, bool visible);
void cut_copy_clear (Editing::CutCopyOp);
bool paste (Temporal::timepos_t const & pos, const ::Selection& selection, PasteContext& ctx);
void paste_internal (Temporal::timepos_t const & pos, unsigned paste_count, float times, const MidiCutBuffer&);
void add_canvas_patch_change (ARDOUR::MidiModel::PatchChangePtr patch);
void remove_canvas_patch_change (PatchChange* pc);
/** Look up the given time and channel in the 'automation' and set keys accordingly.
* @param time the time of the patch change event
* @param channel the MIDI channel of the event
* @param key a reference to an instance of MIDI::Name::PatchPrimaryKey whose fields will
* will be set according to the result of the lookup
*/
void get_patch_key_at (Temporal::Beats time, uint8_t channel, MIDI::Name::PatchPrimaryKey& key) const;
/** Convert a given PatchChange into a PatchPrimaryKey
*/
MIDI::Name::PatchPrimaryKey patch_change_to_patch_key (ARDOUR::MidiModel::PatchChangePtr);
/** Change old_patch to new_patch.
* @param old_patch the canvas patch change which is to be altered
* @param new_patch new patch
*/
void change_patch_change (PatchChange& old_patch, const MIDI::Name::PatchPrimaryKey& new_patch);
void change_patch_change (ARDOUR::MidiModel::PatchChangePtr, Evoral::PatchChange<Temporal::Beats> const &);
void add_patch_change (Temporal::timecnt_t const &, Evoral::PatchChange<Temporal::Beats> const &);
void move_patch_change (PatchChange &, Temporal::Beats);
void delete_patch_change (PatchChange *);
void edit_patch_change (PatchChange *);
void delete_sysex (SysEx*);
/** Change a patch to the next or previous bank/program.
*
* @param patch The patch-change instance (canvas item)
* @param bank If true, step bank, otherwise, step program.
* @param delta Amount to adjust number.
*/
void step_patch (PatchChange& patch, bool bank, int delta);
/** Displays all patch change events in the region as flags on the canvas.
*/
void display_patch_changes();
/** Displays all system exclusive events in the region as flags on the canvas.
*/
void display_sysexes();
void begin_write();
void end_write();
void extend_active_notes();
virtual void begin_drag_edit (std::string const & why);
void end_drag_edit ();
void display_model(std::shared_ptr<ARDOUR::MidiModel> model);
std::shared_ptr<ARDOUR::MidiModel> model() const { return _model; }
/* note_diff commands should start here; this initiates an undo record */
void start_note_diff_command (std::string name = "midi edit");
void note_diff_add_change (NoteBase* ev, ARDOUR::MidiModel::NoteDiffCommand::Property, uint8_t val);
void note_diff_add_change (NoteBase* ev, ARDOUR::MidiModel::NoteDiffCommand::Property, Temporal::Beats val);
void note_diff_add_note (const std::shared_ptr<NoteType> note, bool selected, bool show_velocity = false);
void note_diff_remove_note (NoteBase* ev);
/* note_diff commands should be completed with one of these calls; they may (or may not) commit the undo record */
void apply_note_diff (bool as_subcommand = false, bool was_copy = false);
void abort_note_diff();
void note_entered(NoteBase* ev);
void note_left(NoteBase* ev);
void patch_entered (PatchChange *);
void patch_left (PatchChange *);
void sysex_entered (SysEx* p);
void sysex_left (SysEx* p);
void note_mouse_position (float xfraction, float yfraction, bool can_set_cursor=true);
void unique_select(NoteBase* ev);
void note_selected(NoteBase* ev, bool add, bool extend=false);
void note_deselected(NoteBase* ev);
void delete_selection();
void delete_note (std::shared_ptr<NoteType>);
size_t selection_size() { return _selection.size(); }
void select_all_notes ();
void select_range(Temporal::timepos_t const & start, Temporal::timepos_t const & end);
void invert_selection ();
void extend_selection ();
void duplicate_selection ();
Temporal::Beats earliest_in_selection ();
void move_selection(Temporal::timecnt_t const & dx, double dy, double cumulative_dy);
void note_dropped (NoteBase* ev, Temporal::timecnt_t const & d_qn, int8_t d_note, bool copy);
NoteBase* copy_selection (NoteBase* primary);
void move_copies(Temporal::timecnt_t const & dx_qn, double dy, double cumulative_dy);
void select_notes (std::list<Evoral::event_id_t>, bool allow_audition);
void select_matching_notes (uint8_t notenum, uint16_t channel_mask, bool add, bool extend);
void toggle_matching_notes (uint8_t notenum, uint16_t channel_mask);
/** Test if a note is within this region's range
*
* @param note the note to test
* @param visible will be set to true if the note is within the visible note range, false otherwise.
* @return true iff the note is within the (time) extent of the region.
*/
bool note_in_region_range(const std::shared_ptr<NoteType> note, bool& visible) const;
/* Test if a note is withing this region's time range. Return true if so */
bool note_in_region_time_range(const std::shared_ptr<NoteType> note) const;
/** Get the region position in pixels relative to session. */
double get_position_pixels();
/** Get the region end position in pixels relative to session. */
double get_end_position_pixels();
/** Begin resizing of some notes.
* Called by CanvasMidiNote when resizing starts.
* @param at_front which end of the note (true == note on, false == note off)
*/
void begin_resizing(bool at_front);
void update_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative, double snap_delta, bool with_snap);
void finish_resizing (NoteBase* primary, bool at_front, double delat_x, bool relative, double snap_delta, bool with_snap);
void abort_resizing ();
/** Change the channel of the selection.
* @param channel - the channel number of the new channel, zero-based
*/
void change_channel(uint8_t channel);
enum MouseState {
None,
Pressed,
SelectTouchDragging,
SelectRectDragging,
SelectVerticalDragging,
AddDragging
};
MouseState mouse_state() const { return _mouse_state; }
struct NoteResizeData {
::Note *note;
ArdourCanvas::Rectangle *resize_rect;
};
/** Snap a region relative pixel coordinate to pixel units.
* @param x a pixel coordinate relative to region start
* @param ensure_snap do not use magnetic snap (required for snap delta calculation)
* @return the snapped pixel coordinate relative to region start
*/
double snap_to_pixel(double x, bool ensure_snap = false);
/** Snap a region relative pixel coordinate to time units.
* @param x a pixel coordinate relative to region start
* @param ensure_snap ignore SnapOff and magnetic snap.
* Required for inverting snap logic with modifier keys and snap delta calculation.
* @return the snapped timecnt_t coordinate relative to region start
*/
Temporal::timecnt_t snap_pixel_to_time (double x, bool ensure_snap = false);
void goto_previous_note (bool add_to_selection);
void goto_next_note (bool add_to_selection);
void change_note_lengths (bool, bool, Temporal::Beats beats, bool start, bool end);
void change_velocities (bool up, bool fine, bool allow_smush, bool all_together);
void set_velocity (NoteBase* primary, int velocity);
bool set_velocity_for_notes (std::vector<NoteBase*>& notes, int velocity);
bool set_velocities_for_notes (std::vector<NoteBase*>& notes, std::vector<int>& velocities);
void transpose (bool up, bool fine, bool allow_smush);
void nudge_notes (bool forward, bool fine);
void channel_edit ();
void velocity_edit ();
void show_list_editor ();
void set_note_range (uint8_t low, uint8_t high);
virtual void set_visibility_note_range (MidiViewBackground::VisibleNoteRange, bool);
typedef std::set<NoteBase*> Selection;
Selection const & selection () const {
return _selection;
}
void selection_as_notelist (Notes& selected, bool allow_all_if_none_selected = false);
void set_channel_selector_scoped_note(NoteBase* note){ _channel_selection_scoped_note = note; }
NoteBase* channel_selector_scoped_note(){ return _channel_selection_scoped_note; }
void trim_front_starting ();
void trim_front_ending ();
/** Add a note to the model, and the view, at a canvas (click) coordinate.
* \param t time in samples relative to the position of the region
* \param y vertical position in pixels
* \param length duration of the note in beats
* \param state the keyboard modifier mask for the canvas event (click).
* \param shift_snap true alters snap behavior to round down always (false if the gui has already done that).
*/
void create_note_at (Temporal::timepos_t const & t, double y, Temporal::Beats length, uint32_t state, bool shift_snap);
/** An external request to clear the note selection, remove MRV from editor
* selection.
*/
void clear_selection ();
void note_deleted (NoteBase*);
void clear_note_selection ();
void show_verbose_cursor_for_new_note_value(std::shared_ptr<NoteType> current_note, uint8_t new_note) const;
std::shared_ptr<ARDOUR::MidiTrack> midi_track() const { return _midi_track; }
std::shared_ptr<ARDOUR::MidiRegion> midi_region() const { return _midi_region; }
EditingContext& editing_context() const { return _editing_context; }
MidiViewBackground& midi_context() const { return _midi_context; }
virtual void select_self (bool add) {}
virtual void unselect_self () {}
void select_self () { select_self (false); }
virtual void select_self_uniquely () {}
protected:
void init ();
virtual void region_resized (const PBD::PropertyChange&);
void set_flags (XMLNode *);
void store_flags ();
virtual void reset_width_dependent_items (double pixel_width);
void redisplay (bool view_only);
protected:
friend class EditingContext;
friend class Editor; // grr, C++ does not allow inheritance of friendship
void invert_note_selection ();
void extend_note_selection ();
void move_note_starts_earlier_fine () { change_note_lengths (true, false, Temporal::Beats(), true, false); }
void move_note_starts_earlier () { change_note_lengths (false, false, Temporal::Beats(), true, false); }
void move_note_ends_later_fine () { change_note_lengths (true, false, Temporal::Beats(), false, true); }
void move_note_ends_later () { change_note_lengths (false, false, Temporal::Beats(), false, true); }
void move_note_starts_later_fine () { change_note_lengths (true, true, Temporal::Beats(), true, false); }
void move_note_starts_later () { change_note_lengths (false, true, Temporal::Beats(), true, false); }
void move_note_ends_earlier_fine () { change_note_lengths (true, true, Temporal::Beats(), false, true); }
void move_note_ends_earlier () { change_note_lengths (false, true, Temporal::Beats(), false, true); }
void select_next_note () { goto_next_note (false); }
void select_previous_note () { goto_previous_note (false); }
void add_select_next_note () { goto_next_note (true); }
void add_select_previous_note () { goto_previous_note (true); }
void increase_note_velocity () { change_velocities (true, false, false, false); }
void increase_note_velocity_fine () { change_velocities (true, true, false, false); }
void increase_note_velocity_smush () { change_velocities (true, false, true, false); }
void increase_note_velocity_together () { change_velocities (true, false, false, true); }
void increase_note_velocity_fine_smush () { change_velocities (true, true, true, false); }
void increase_note_velocity_fine_together () { change_velocities (true, true, false, true); }
void increase_note_velocity_smush_together () { change_velocities (true, false, true, true); }
void increase_note_velocity_fine_smush_together () { change_velocities (true, true, true, true); }
void decrease_note_velocity () { change_velocities (false, false, false, false); }
void decrease_note_velocity_fine () { change_velocities (false, true, false, false); }
void decrease_note_velocity_smush () { change_velocities (false, false, true, false); }
void decrease_note_velocity_together () { change_velocities (false, false, false, true); }
void decrease_note_velocity_fine_smush () { change_velocities (false, true, true, false); }
void decrease_note_velocity_fine_together () { change_velocities (false, true, false, true); }
void decrease_note_velocity_smush_together () { change_velocities (false, false, true, true); }
void decrease_note_velocity_fine_smush_together () { change_velocities (false, true, true, true); }
void transpose_up_octave () { transpose (true, false, false); }
void transpose_up_octave_smush () { transpose (true, false, true); }
void transpose_up_tone () { transpose (true, true, false); }
void transpose_up_tone_smush () { transpose (true, true, true); }
void transpose_down_octave () { transpose (false, false, false); }
void transpose_down_octave_smush () { transpose (false, false, true); }
void transpose_down_tone () { transpose (false, true, false); }
void transpose_down_tone_smush () { transpose (false, true, true); }
void nudge_notes_later () { nudge_notes (true, false); }
void nudge_notes_later_fine () { nudge_notes (true, true); }
void nudge_notes_earlier () { nudge_notes (false, false); }
void nudge_notes_earlier_fine () { nudge_notes (false, true); }
void quantize_selected_notes ();
protected:
friend class MidiRubberbandSelectDrag;
friend class MidiVerticalSelectDrag;
friend class NoteDrag;
friend class NoteCreateDrag;
friend class HitCreateDrag;
friend class MidiGhostRegion;
friend class EditNoteDialog;
/** Play the NoteOn event of the given note immediately
* and schedule the playback of the corresponding NoteOff event.
*/
void play_midi_note (std::shared_ptr<NoteType> note);
void start_playing_midi_note (std::shared_ptr<NoteType> note);
void start_playing_midi_chord (std::vector<std::shared_ptr<NoteType> > notes);
/** Clear the note selection of just this midi region
*/
void clear_selection_internal ();
void clear_events ();
virtual void clear_ghost_events() {}
virtual void ghosts_model_changed() {}
virtual void ghosts_view_changed() {}
virtual void ghost_remove_note (NoteBase*) {}
virtual void ghost_add_note (NoteBase*) {}
virtual void ghost_sync_selection (NoteBase*) {}
virtual bool canvas_group_event(GdkEvent* ev);
bool note_canvas_event(GdkEvent* ev);
PBD::ScopedConnectionList connections_requiring_model;
void midi_channel_mode_changed ();
void instrument_settings_changed ();
void change_note_channel (NoteBase *, int8_t, bool relative=false);
void change_note_velocity(NoteBase* ev, int8_t vel, bool relative=false);
uint8_t change_note_note(NoteBase* ev, int8_t note, bool relative=false);
void change_note_time(NoteBase* ev, ARDOUR::MidiModel::TimeType, bool relative=false);
void change_note_length (NoteBase *, ARDOUR::MidiModel::TimeType);
void trim_note(NoteBase* ev, ARDOUR::MidiModel::TimeType start_delta,
ARDOUR::MidiModel::TimeType end_delta);
void update_drag_selection (Temporal::timepos_t const & start, Temporal::timepos_t const & end, double y0, double y1, bool extend);
void update_vertical_drag_selection (double last_y, double y, bool extend);
void add_to_selection (NoteBase*);
void remove_from_selection (NoteBase*);
std::string get_note_name (std::shared_ptr<NoteType> note, uint8_t note_value) const;
void show_verbose_cursor (std::string const &, double, double) const;
void show_verbose_cursor (std::shared_ptr<NoteType>) const;
uint8_t get_velocity_for_add (ARDOUR::MidiModel::TimeType time) const;
uint8_t get_channel_for_add (ARDOUR::MidiModel::TimeType time) const;
typedef boost::unordered_map<std::shared_ptr<NoteType>, NoteBase*> Events;
typedef boost::unordered_map<ARDOUR::MidiModel::PatchChangePtr, std::shared_ptr<PatchChange> > PatchChanges;
typedef boost::unordered_map<ARDOUR::MidiModel::constSysExPtr, std::shared_ptr<SysEx> > SysExes;
typedef std::vector<NoteBase*> CopyDragEvents;
std::shared_ptr<ARDOUR::MidiTrack> _midi_track;
EditingContext& _editing_context;
MidiViewBackground& _midi_context;
std::shared_ptr<ARDOUR::MidiModel> _model;
std::shared_ptr<ARDOUR::MidiRegion> _midi_region;
Events _events;
CopyDragEvents _copy_drag_events;
PatchChanges _patch_changes;
SysExes _sys_exes;
Note** _active_notes;
ArdourCanvas::Container* _note_group;
ARDOUR::MidiModel::NoteDiffCommand* _note_diff_command;
NoteBase* _ghost_note;
double _last_ghost_x;
double _last_ghost_y;
ArdourCanvas::Rectangle* _step_edit_cursor;
Temporal::Beats _step_edit_cursor_width;
Temporal::Beats _step_edit_cursor_position;
NoteBase* _channel_selection_scoped_note;
MouseState _mouse_state;
int _pressed_button;
/** Currently selected NoteBase objects */
Selection _selection;
MidiCutBuffer* selection_as_cut_buffer () const;
/** New notes (created in the current command) which should be selected
* when they appear after the command is applied. */
std::set< std::shared_ptr<NoteType> > _marked_for_selection;
/** Notes that should be selected when the model is redisplayed. */
std::set<Evoral::event_id_t> _pending_note_selection;
/** New notes (created in the current command) which should have visible velocity
* when they appear after the command is applied. */
std::set< std::shared_ptr<NoteType> > _marked_for_velocity;
std::vector<NoteResizeData *> _resize_data;
/** connection used to connect to model's ContentChanged signal */
NoteBase* find_canvas_note (std::shared_ptr<NoteType>);
NoteBase* find_canvas_note (Evoral::event_id_t id);
Events::iterator _optimization_iterator;
std::shared_ptr<PatchChange> find_canvas_patch_change (ARDOUR::MidiModel::PatchChangePtr p);
std::shared_ptr<SysEx> find_canvas_sys_ex (ARDOUR::MidiModel::SysExPtr s);
friend class VelocityGhostRegion;
void sync_velocity_drag (double factor);
void update_note (NoteBase*, bool update_ghost_regions = true);
void update_sustained (Note *, bool update_ghost_regions = true);
void update_hit (Hit *, bool update_ghost_regions = true);
void create_ghost_note (double, double, uint32_t state);
void update_ghost_note (double, double, uint32_t state);
MidiListEditor* _list_editor;
bool _no_sound_notes;
void snap_changed ();
virtual bool motion (GdkEventMotion*);
virtual bool scroll (GdkEventScroll*);
virtual bool key_press (GdkEventKey*);
virtual bool key_release (GdkEventKey*);
virtual bool button_press (GdkEventButton*);
virtual bool button_release (GdkEventButton*);
virtual bool enter_notify (GdkEventCrossing*);
virtual bool leave_notify (GdkEventCrossing*);
void drop_down_keys ();
void maybe_select_by_position (GdkEventButton* ev, double x, double y);
void get_events (Events& e, Evoral::Sequence<Temporal::Beats>::NoteOperator op, uint8_t val, int chan_mask = 0);
void display_patch_changes_on_channel (uint8_t, bool);
void data_recorded (std::weak_ptr<ARDOUR::MidiSource>);
/** Get grid type as beats, or default to 1 if not snapped to beats. */
Temporal::Beats get_grid_beats(Temporal::timepos_t const & pos) const;
Temporal::Beats get_draw_length_beats(Temporal::timepos_t const & pos) const;
void remove_ghost_note ();
virtual void mouse_mode_changed ();
virtual void enter_internal (uint32_t state);
virtual void leave_internal ();
void hide_verbose_cursor ();
samplecnt_t _last_display_zoom;
double _last_event_x;
double _last_event_y;
bool _entered;
NoteBase* _entered_note;
bool _select_all_notes_after_add;
bool _mouse_changed_selection;
Gtkmm2ext::Color _patch_change_outline;
Gtkmm2ext::Color _patch_change_fill;
std::shared_ptr<CursorContext> _press_cursor_ctx;
ARDOUR::ChannelMode get_channel_mode() const;
uint16_t get_selected_channels () const;
virtual double height() const;
virtual double contents_height() const { return height() - 2; }
inline double note_height() const { return contents_height() / _midi_context.contents_note_range(); }
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 ();
void view_changed ();
void model_changed ();
void sync_ghost_selection (NoteBase*);
struct SplitInfo {
Temporal::Beats time;
Temporal::Beats base_len;
int note;
int channel;
int velocity;
int off_velocity;
SplitInfo (Temporal::Beats const & t, Temporal::Beats const & l, int n, int c, int v, int ov)
: time (t)
, base_len (l)
, note (n)
, channel (c)
, velocity (v)
, off_velocity (ov) {}
};
std::vector<SplitInfo> split_info;
uint32_t split_tuple;
bool note_splitting;
void start_note_splitting ();
void end_note_splitting ();
void split_notes_grid ();
void split_notes_more ();
void split_notes_less ();
void join_notes ();
void join_notes_on_channel (int channel);
void add_split_notes ();
};
#endif /* __gtk_ardour_midi_view_h__ */

View File

@ -0,0 +1,307 @@
/*
* Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
* Copyright (C) 2007 Doug McLain <doug@nostar.net>
* Copyright (C) 2008-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2014-2019 Robin Gareus <robin@gareus.org>
* Copyright (C) 2015 Tim Mayberry <mojofunk@gmail.com>
* Copyright (C) 2016 Nick Mainsbridge <mainsbridge@gmail.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/line_set.h"
#include "midi_view_background.h"
#include "ui_config.h"
#include "pbd/i18n.h"
using namespace std;
MidiViewBackground::MidiViewBackground (ArdourCanvas::Item* parent)
: note_range_adjustment (0.0f, 0.0f, 0.0f)
, _range_dirty (false)
, _range_sum_cache (-1.0)
, _lowest_note (UIConfiguration::instance().get_default_lower_midi_note())
, _highest_note (UIConfiguration::instance().get_default_upper_midi_note())
, _data_note_min (60)
, _data_note_max (71)
, _note_lines (new ArdourCanvas::LineSet (parent, ArdourCanvas::LineSet::Horizontal))
, _note_mode (ARDOUR::Sustained)
, _color_mode (ARDOUR::MeterColors)
{
_note_lines->lower_to_bottom();
// color_handler ();
UIConfiguration::instance().ColorsChanged.connect(sigc::mem_fun(*this, &MidiViewBackground::color_handler));
UIConfiguration::instance().ParameterChanged.connect(sigc::mem_fun(*this, &MidiViewBackground::parameter_changed));
note_range_adjustment.set_page_size(_highest_note - _lowest_note);
note_range_adjustment.set_value(_lowest_note);
note_range_adjustment.set_lower(0);
note_range_adjustment.set_upper(127);
note_range_adjustment.signal_value_changed().connect(sigc::mem_fun(*this, &MidiViewBackground::note_range_adjustment_changed));
}
MidiViewBackground::~MidiViewBackground()
{
}
void
MidiViewBackground::parameter_changed (std::string const & param)
{
if (param == X_("max-note-height")) {
apply_note_range (_lowest_note, _highest_note, true);
}
}
void
MidiViewBackground::color_handler ()
{
draw_note_lines ();
}
void
MidiViewBackground::note_range_adjustment_changed()
{
double sum = note_range_adjustment.get_value() + note_range_adjustment.get_page_size();
int lowest = (int) floor(note_range_adjustment.get_value());
int highest;
if (sum == _range_sum_cache) {
//cerr << "cached" << endl;
highest = (int) floor(sum);
} else {
//cerr << "recalc" << endl;
highest = lowest + (int) floor(note_range_adjustment.get_page_size());
_range_sum_cache = sum;
}
if (lowest == _lowest_note && highest == _highest_note) {
return;
}
//cerr << "note range adjustment changed: " << lowest << " " << highest << endl;
//cerr << " val=" << v_zoom_adjustment.get_value() << " page=" << v_zoom_adjustment.get_page_size() << " sum=" << v_zoom_adjustment.get_value() + v_zoom_adjustment.get_page_size() << endl;
apply_note_range (lowest, highest, true);
}
uint8_t
MidiViewBackground::y_to_note (double y) const
{
int const n = ((contents_height() - y) / contents_height() * (double)contents_note_range())
+ lowest_note();
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, highest_note());
}
void
MidiViewBackground::update_contents_height ()
{
ViewBackground::update_contents_height ();
draw_note_lines ();
apply_note_range (lowest_note(), highest_note(), true);
}
void
MidiViewBackground::draw_note_lines()
{
if (updates_suspended()) {
return;
}
double y;
double prev_y = 0.;
Gtkmm2ext::Color black = UIConfiguration::instance().color_mod ("piano roll black", "piano roll black");
Gtkmm2ext::Color white = UIConfiguration::instance().color_mod ("piano roll white", "piano roll white");
Gtkmm2ext::Color outline = UIConfiguration::instance().color ("piano roll black outline");
Gtkmm2ext::Color color;
ArdourCanvas::LineSet::ResetRAII lr (*_note_lines);
if (contents_height() < 10 || note_height() < 3) {
/* context is too small for note lines, or there are too many */
return;
}
/* do this is order of highest ... lowest since that matches the
* coordinate system in which y=0 is at the top
*/
for (int i = highest_note() + 1; i >= lowest_note(); --i) {
y = floor (note_to_y (i));
/* add a thicker line/bar which covers the entire vertical height of this note. */
switch (i % 12) {
case 1:
case 3:
case 6:
case 8:
case 10:
color = black;
break;
case 4:
case 11:
/* this is the line actually corresponding to the division between B & C and E & F */
_note_lines->add_coord (y, 1.0, outline);
/* fallthrough */
default:
color = white;
break;
}
double h = y - prev_y;
double middle = y + (h/2.0);
if (!fmod (h, 2.) && !fmod (middle, 1.)) {
middle += 0.5;
}
if (middle >= 0 && h > 1.0) {
_note_lines->add_coord (middle, h, color);
}
prev_y = y;
}
_note_lines->set_extent (ArdourCanvas::COORD_MAX);
}
void
MidiViewBackground::set_note_visibility_range_style (VisibleNoteRange r)
{
_visibility_note_range = r;
if (_visibility_note_range == FullRange) {
apply_note_range (0, 127, true);
} else {
apply_note_range (_data_note_min, _data_note_max, true);
}
}
void
MidiViewBackground::maybe_extend_note_range (uint8_t note_num)
{
_data_note_min = min (_data_note_min, note_num);
_data_note_max = max (_data_note_max, note_num);
bool changed = false;
if (_visibility_note_range == FullRange) {
return;
}
if (_lowest_note > _data_note_min) {
changed = true;
}
if (_highest_note < _data_note_max) {
changed = true;
}
if (changed) {
apply_note_range (_data_note_min, _data_note_max, true);
}
}
void
MidiViewBackground::apply_note_range (uint8_t lowest, uint8_t highest, bool to_children)
{
bool changed = false;
if (_highest_note != highest) {
_highest_note = highest;
changed = true;
}
if (_lowest_note != lowest) {
changed = true;
_lowest_note = lowest;
}
if (!changed) {
return;
}
float uiscale = UIConfiguration::instance().get_ui_scale();
uiscale = expf (uiscale) / expf (1.f);
const int mnh = UIConfiguration::instance().get_max_note_height();
int const max_note_height = std::max<int> (mnh, mnh * uiscale);
int const range = _highest_note - _lowest_note;
int const available_note_range = floor (contents_height() / max_note_height);
int additional_notes = available_note_range - range;
/* distribute additional notes to higher and lower ranges, clamp at 0 and 127 */
for (int i = 0; i < additional_notes; i++){
if (i % 2 && _highest_note < 127){
_highest_note++;
}
else if (i % 2) {
_lowest_note--;
}
else if (_lowest_note > 0){
_lowest_note--;
}
else {
_highest_note++;
}
}
note_range_adjustment.set_page_size (_highest_note - _lowest_note);
note_range_adjustment.set_value (_lowest_note);
draw_note_lines();
if (to_children) {
apply_note_range_to_children ();
}
NoteRangeChanged(); /* EMIT SIGNAL*/
}
bool
MidiViewBackground::update_data_note_range (uint8_t min, uint8_t max)
{
bool dirty = false;
if (min < _data_note_min) {
_data_note_min = min;
dirty = true;
}
if (max > _data_note_max) {
_data_note_max = max;
dirty = true;
}
return dirty;
}

View File

@ -0,0 +1,131 @@
/*
* Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
* Copyright (C) 2007 Doug McLain <doug@nostar.net>
* Copyright (C) 2008-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2016-2017 Robin Gareus <robin@gareus.org>
*
* 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.
*/
#ifndef __gtk2_ardour_midi_view_background_h__
#define __gtk2_ardour_midi_view_background_h__
#include <cstdint>
#include <gtkmm/adjustment.h>
#include "pbd/signals.h"
#include "ardour/types.h"
#include "gtkmm2ext/colors.h"
#include "view_background.h"
namespace ArdourCanvas {
class Item;
class LineSet;
}
/** A class that provides various context for a MidiVieww:
= note ranges
* color information
* etc.
*/
class MidiViewBackground : public virtual ViewBackground
{
public:
MidiViewBackground (ArdourCanvas::Item* parent);
~MidiViewBackground ();
Gtk::Adjustment note_range_adjustment;
enum VisibleNoteRange {
FullRange,
ContentsRange
};
ARDOUR::NoteMode note_mode() const { return _note_mode; }
void set_note_mode (ARDOUR::NoteMode nm);
ARDOUR::ColorMode color_mode() const { return _color_mode; }
void set_color_mode (ARDOUR::ColorMode);
Gtkmm2ext::Color region_color() const { return _region_color; }
void set_note_visibility_range_style (VisibleNoteRange r);
VisibleNoteRange visibility_range_style() const { return _visibility_note_range; }
inline uint8_t lowest_note() const { return _lowest_note; }
inline uint8_t highest_note() const { return _highest_note; }
void maybe_extend_note_range (uint8_t note_num);
double note_to_y (uint8_t note) const {
return contents_height() - (note + 1 - lowest_note()) * note_height() + 1;
}
uint8_t y_to_note(double y) const;
uint8_t contents_note_range() const {
return highest_note() - lowest_note() + 1;
}
double note_height() const {
return contents_height() / (double)contents_note_range();
}
sigc::signal<void> NoteRangeChanged;
void apply_note_range (uint8_t lowest, uint8_t highest, bool to_children);
/** @return y position, or -1 if hidden */
virtual double y_position () const { return 0.; }
virtual uint8_t get_preferred_midi_channel () const = 0;
virtual void set_note_highlight (bool) = 0;
virtual void record_layer_check (std::shared_ptr<ARDOUR::Region>, samplepos_t) = 0;
virtual void set_size (double w, double h) {}
PBD::Signal0<void> HeightChanged;
protected:
bool _range_dirty;
double _range_sum_cache;
uint8_t _lowest_note; ///< currently visible
uint8_t _highest_note; ///< currently visible
uint8_t _data_note_min; ///< in data
uint8_t _data_note_max; ///< in data
ArdourCanvas::LineSet* _note_lines;
ARDOUR::NoteMode _note_mode;
Gtkmm2ext::Color _region_color;
ARDOUR::ColorMode _color_mode;
VisibleNoteRange _visibility_note_range;
void color_handler ();
void parameter_changed (std::string const &);
void note_range_adjustment_changed();
void draw_note_lines();
bool update_data_note_range (uint8_t min, uint8_t max);
void update_contents_height ();
virtual void apply_note_range_to_children () = 0;
virtual bool updates_suspended() const { return false; }
void sync_data_and_visual_range ();
};
#endif /* __gtk2_ardour_midi_view_background_h__ */

View File

@ -609,7 +609,7 @@ MiniTimeline::render (Cairo::RefPtr<Cairo::Context> const& ctx, cairo_rectangle_
timepos_t rounded = timepos_t (tmap->quarters_at (tmap->round_to_bar (tmap->bbt_at (timepos_t(when)))));
when = tmap->sample_at(rounded);
}
double xpos = width * .5 + (when - phead) * _px_per_sample;
// TODO round to nearest display TC in +/- 1px

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)
@ -328,7 +326,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);
@ -409,7 +406,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"));
@ -565,8 +561,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
@ -1689,8 +1683,6 @@ MixerStrip::revert_to_default_display ()
}
reset_strip_style ();
set_trigger_display (_route->triggerbox());
}
void
@ -2146,9 +2138,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

@ -29,8 +29,7 @@ using namespace ARDOUR;
using ArdourCanvas::Coord;
using ArdourCanvas::Duple;
Note::Note (
MidiRegionView& region, ArdourCanvas::Item* parent, const std::shared_ptr<NoteType> note, bool with_events)
Note::Note (MidiView& region, ArdourCanvas::Item* parent, const std::shared_ptr<NoteType> note, bool with_events)
: NoteBase (region, with_events, note)
, _visual_note (new ArdourCanvas::Note (parent))
{

View File

@ -33,7 +33,7 @@ class Note : public NoteBase
public:
typedef Evoral::Note<Temporal::Beats> NoteType;
Note (MidiRegionView& region,
Note (MidiView& region,
ArdourCanvas::Item* parent,
const std::shared_ptr<NoteType> note = std::shared_ptr<NoteType>(),
bool with_events = true);

View File

@ -28,10 +28,10 @@
#include "canvas/text.h"
#include "note_base.h"
#include "public_editor.h"
#include "editing_context.h"
#include "editing_syms.h"
#include "keyboard.h"
#include "midi_region_view.h"
#include "midi_view.h"
using namespace std;
using namespace Gtkmm2ext;
@ -61,7 +61,7 @@ NoteBase::set_colors ()
color_modifier = UIConfiguration::instance().modifier ("midi note");
}
NoteBase::NoteBase(MidiRegionView& region, bool with_events, const std::shared_ptr<NoteType> note)
NoteBase::NoteBase(MidiView& region, bool with_events, const std::shared_ptr<NoteType> note)
: _region(region)
, _item (0)
, _text(0)
@ -183,7 +183,7 @@ NoteBase::set_selected(bool selected)
uint32_t
NoteBase::base_color ()
{
return base_color (_note->velocity(), _region.color_mode(), _region.midi_stream_view()->get_region_color(), _note->channel(), selected());
return base_color (_note->velocity(), _region.midi_context().color_mode(), _region.midi_context().region_color(), _note->channel(), selected());
}
uint32_t
@ -288,7 +288,7 @@ NoteBase::set_mouse_fractions (GdkEvent* ev)
bool
NoteBase::event_handler (GdkEvent* ev)
{
PublicEditor& editor = _region.get_time_axis_view().editor();
EditingContext& editor = _region.editing_context();
if (!editor.internal_editing()) {
return false;
}

View File

@ -33,7 +33,7 @@
#include "ui_config.h"
class Editor;
class MidiRegionView;
class MidiView;
namespace Evoral {
template<typename T> class Note;
@ -67,7 +67,7 @@ class NoteBase : public sigc::trackable
public:
typedef Evoral::Note<Temporal::Beats> NoteType;
NoteBase (MidiRegionView& region, bool, const std::shared_ptr<NoteType> note = std::shared_ptr<NoteType>());
NoteBase (MidiView& region, bool, const std::shared_ptr<NoteType> note = std::shared_ptr<NoteType>());
virtual ~NoteBase ();
void set_item (ArdourCanvas::Item *);
@ -115,7 +115,7 @@ class NoteBase : public sigc::trackable
float mouse_y_fraction() const { return _mouse_y_fraction; }
const std::shared_ptr<NoteType> note() const { return _note; }
MidiRegionView& region_view() const { return _region; }
MidiView& region_view() const { return _region; }
static void set_colors ();
@ -139,7 +139,7 @@ class NoteBase : public sigc::trackable
protected:
enum State { None, Pressed, Dragging };
MidiRegionView& _region;
MidiView& _region;
ArdourCanvas::Item* _item;
ArdourCanvas::Text* _text;
State _state;

View File

@ -34,7 +34,7 @@
#include "editor.h"
#include "editor_drag.h"
#include "midi_region_view.h"
#include "midi_view.h"
#include "patch_change.h"
#include "ui_config.h"
@ -44,8 +44,8 @@ using Gtkmm2ext::Keyboard;
/** @param x x position in pixels.
*/
PatchChange::PatchChange (MidiRegionView& region,
ArdourCanvas::Container* parent,
PatchChange::PatchChange (MidiView& region,
ArdourCanvas::Item* parent,
double height,
double x,
double y,
@ -153,15 +153,15 @@ bool
PatchChange::event_handler (GdkEvent* ev)
{
/* XXX: icky dcast */
Editor* e = dynamic_cast<Editor*> (&_region.get_time_axis_view ().editor ());
EditingContext& e = _region.editing_context();
if (!e->internal_editing ()) {
if (!e.internal_editing ()) {
return false;
}
switch (ev->type) {
case GDK_BUTTON_PRESS:
if (e->current_mouse_mode () == Editing::MouseContent) {
if (e.current_mouse_mode () == Editing::MouseContent) {
if (Gtkmm2ext::Keyboard::is_delete_event (&ev->button)) {
_region.delete_patch_change (this);
return true;
@ -171,7 +171,7 @@ PatchChange::event_handler (GdkEvent* ev)
return true;
} else if (ev->button.button == 1) {
e->drags ()->set (new PatchChangeDrag (e, this, &_region), ev);
e.drags ()->set (new PatchChangeDrag (e, this, &_region), ev);
return true;
}
}

View File

@ -34,8 +34,8 @@ namespace MIDI {
class PatchChange
{
public:
PatchChange (MidiRegionView& region,
ArdourCanvas::Container* parent,
PatchChange (MidiView& region,
ArdourCanvas::Item* parent,
double height,
double x,
double y,
@ -65,7 +65,7 @@ public:
private:
bool event_handler (GdkEvent*);
MidiRegionView& _region;
MidiView& _region;
ARDOUR::InstrumentInfo& _info;
ARDOUR::MidiModel::PatchChangePtr _patch;
Gtk::Menu _popup;

View File

@ -652,7 +652,7 @@ PianoRollHeader::on_button_press_event (GdkEventButton* ev)
if (ev->type == GDK_2BUTTON_PRESS) {
MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*>(&_view.trackview());
if (mtv) {
mtv->set_note_range (MidiStreamView::ContentsRange, false);
mtv->set_visibility_note_range (MidiStreamView::ContentsRange, false);
}
return true;
}

View File

@ -0,0 +1,8 @@
<Bindings name="Pianoroll">
<Press>
<Binding key="d" action="MIDICueEditor/set-mouse-mode-draw" group="pianoroll"/>
<Binding key="e" action="MIDICueEditor/set-mouse-mode-content" group="pianoroll"/>
<Binding key="equal" action="MIDICueEditor/zoom-in" group="pianoroll"/>
<Binding key="minus" action="MIDICueEditor/zoom-in" group="pianoroll"/>
</Press>
</Bindings>

982
gtk2_ardour/prh.cc Normal file
View File

@ -0,0 +1,982 @@
/*
* Copyright (C) 2008-2014 David Robillard <d@drobilla.net>
* Copyright (C) 2009-2011 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2009-2013 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2014-2017 Robin Gareus <robin@gareus.org>
*
* 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 <iostream>
#include "evoral/midi_events.h"
#include "canvas/canvas.h"
#include "ardour/midi_track.h"
#include "gtkmm2ext/colors.h"
#include "gtkmm2ext/keyboard.h"
#include "gtkmm2ext/rgb_macros.h"
#include "midi++/midnam_patch.h"
#include "editing.h"
#include "gui_thread.h"
#include "midi_view.h"
#include "midi_view_background.h"
#include "prh.h"
#include "editing_context.h"
#include "ui_config.h"
#include "pbd/i18n.h"
using namespace std;
using namespace Gtkmm2ext;
namespace ArdourCanvas {
PianoRollHeader::PianoRollHeader (Item* parent, MidiViewBackground& bg)
: Rectangle (parent)
, _midi_context (bg)
, _adj (_midi_context.note_range_adjustment)
, _view (nullptr)
, _font_descript ("Sans Bold")
, _font_descript_big_c ("Sans")
, _font_descript_midnam ("Sans")
, _highlighted_note (NO_MIDI_NOTE)
, _clicked_note (NO_MIDI_NOTE)
, _dragging (false)
, _scroomer_size (63.f)
, _scroomer_drag (false)
, _old_y (0.0)
, _fract (0.0)
, _scroomer_state (NONE)
, _scroomer_button_state (NONE)
, _saved_top_val (0.0)
, _saved_bottom_val (127.0)
, _mini_map_display (false)
, entered (false)
, have_note_names (false)
{
Glib::RefPtr<Pango::Context> context = _canvas->get_pango_context();
_layout = Pango::Layout::create (context);
_big_c_layout = Pango::Layout::create (context);
_font_descript_big_c.set_absolute_size (10.0 * Pango::SCALE);
_big_c_layout->set_font_description(_font_descript_big_c);
_midnam_layout = Pango::Layout::create (context);
for (int i = 0; i < 128; ++i) {
_active_notes[i] = false;
}
resize ();
bg.HeightChanged.connect (height_connection, MISSING_INVALIDATOR, boost::bind (&PianoRollHeader::resize, this), gui_context());
/* draw vertical lines on both sides of the rectangle */
set_fill (false);
set_fill (true);
set_outline_color (0x000000ff); /* XXX theme me */
set_outline_what (Rectangle::What (Rectangle::LEFT|Rectangle::RIGHT));
Event.connect (sigc::mem_fun (*this, &PianoRollHeader::event_handler));
}
void
PianoRollHeader::resize ()
{
double w, h;
size_request (w, h);
set (Rect (0., 0., w, h));
}
void
PianoRollHeader::set_view (MidiView& v)
{
_view = &v;
_view->midi_context().NoteRangeChanged.connect (sigc::mem_fun (*this, &PianoRollHeader::note_range_changed));
}
void
PianoRollHeader::size_request (double& w, double& h) const
{
h = _midi_context.contents_height();
if (show_scroomer()) {
_scroomer_size = 60.f * UIConfiguration::instance().get_ui_scale();
} else {
_scroomer_size = 20.f * UIConfiguration::instance().get_ui_scale();
}
w = _scroomer_size + 20.;
}
bool
PianoRollHeader::event_handler (GdkEvent* ev)
{
/* Remember that ev uses canvas coordinates, not item */
switch (ev->type) {
case GDK_BUTTON_PRESS:
case GDK_2BUTTON_PRESS:
case GDK_3BUTTON_PRESS:
return button_press_handler (&ev->button);
case GDK_BUTTON_RELEASE:
return button_release_handler (&ev->button);
case GDK_ENTER_NOTIFY:
return enter_handler (&ev->crossing);
case GDK_LEAVE_NOTIFY:
return leave_handler (&ev->crossing);
case GDK_SCROLL:
return scroll_handler (&ev->scroll);
case GDK_MOTION_NOTIFY:
return motion_handler (&ev->motion);
default:
break;
}
return false;
}
inline void
create_path (Cairo::RefPtr<Cairo::Context> cr, double x[], double y[], int start, int stop)
{
cr->move_to (x[start], y[start]);
for (int i = start + 1; i <= stop; ++i) {
cr->line_to (x[i], y[i]);
}
}
inline void
render_rect(Cairo::RefPtr<Cairo::Context> cr, int note, double x[], double y[], Gtkmm2ext::Color& bg)
{
set_source_rgba (cr, bg);
create_path (cr, x, y, 0, 4);
cr->fill ();
}
void
PianoRollHeader::render_scroomer (Cairo::RefPtr<Cairo::Context> cr) const
{
double scroomer_top = max (1.0, (1.0 - ((_adj.get_value()+_adj.get_page_size()) / 127.0)) * get().height () );
double scroomer_bottom = (1.0 - (_adj.get_value () / 127.0)) * get().height ();
Gtkmm2ext::Color c = UIConfiguration::instance().color_mod (X_("scroomer"), X_("scroomer alpha"));
Gtkmm2ext::Color save_color (c);
if (entered) {
c = HSV (c).lighter (0.25).color();
}
set_source_rgba (cr, c);
cr->move_to (1.f, scroomer_top);
cr->line_to (_scroomer_size - 1.f, scroomer_top);
cr->line_to (_scroomer_size - 1.f, scroomer_bottom);
cr->line_to (1.f, scroomer_bottom);
cr->line_to (1.f, scroomer_top);
cr->fill();
if (entered) {
cr->save ();
c = HSV (save_color).lighter (0.9).color();
set_source_rgba (cr, c);
cr->set_line_width (4.);
cr->move_to (1.f, scroomer_top + 2.);
cr->line_to (_scroomer_size - 1.f, scroomer_top + 2.);
cr->stroke ();
cr->line_to (_scroomer_size - 1.f, scroomer_bottom - 2.);
cr->line_to (2.f, scroomer_bottom - 2.);
cr->stroke ();
cr->restore ();
}
}
bool
PianoRollHeader::scroll_handler (GdkEventScroll* ev)
{
if (!_view) {
return false;
}
int note_range = _adj.get_page_size ();
int note_lower = _adj.get_value ();
if(ev->state == GDK_SHIFT_MASK){
switch (ev->direction) {
case GDK_SCROLL_UP: //ZOOM IN
_view->apply_note_range (min(note_lower + 1, 127), max(note_lower + note_range - 1,0), true);
break;
case GDK_SCROLL_DOWN: //ZOOM OUT
_view->apply_note_range (max(note_lower - 1,0), min(note_lower + note_range + 1, 127), true);
break;
default:
return false;
}
}else{
switch (ev->direction) {
case GDK_SCROLL_UP:
_adj.set_value (min (note_lower + 1, 127 - note_range));
break;
case GDK_SCROLL_DOWN:
_adj.set_value (note_lower - 1.0);
break;
default:
return false;
}
}
Duple evd (canvas_to_item (Duple (ev->x, ev->y)));
set_note_highlight (_view->midi_context().y_to_note (evd.y));
_adj.value_changed ();
redraw ();
return true;
}
void
PianoRollHeader::get_path (int note, double x[], double y[]) const
{
double y_pos = floor(_midi_context.note_to_y(note));
double note_height;
double width = get().width() - 1.0f;
if (note == 0) {
note_height = floor(_midi_context.contents_height()) - y_pos;
} else {
note_height = _midi_context.note_height() <= 3 ? _midi_context.note_height() : _midi_context.note_height() - 1.f;
}
x[0] = _scroomer_size;
y[0] = y_pos + note_height;
x[1] = _scroomer_size;
y[1] = y_pos;
x[2] = width;
y[2] = y_pos;
x[3] = width;
y[3] = y_pos + note_height;
x[4] = x[0];
y[4] = y[0];
}
void
PianoRollHeader::render (ArdourCanvas::Rect const & area, Cairo::RefPtr<Cairo::Context> cr) const
{
int lowest, highest;
Gtkmm2ext::Color bg;
double x[9];
double y[9];
int oct_rel;
Rectangle::render (area, cr);
/* Setup a cairo translation so that all drawing can be done using item
* coordinate
*/
Duple origin (item_to_window (Duple (0., 0.)));
cr->save ();
cr->translate (origin.x, origin.y);
Rect self (get());
double y1 = max (self.y0, 0.);
double y2 = min (self.y1, (ArdourCanvas::Coord) floor(_midi_context.contents_height()));
double av_note_height = _midi_context.note_height();
int bc_height, bc_width;
//Reduce the frequency of Pango layout resizing
//if (int(_old_av_note_height) != int(av_note_height)) {
//Set Pango layout keyboard c's size
_font_descript.set_absolute_size (av_note_height * 0.7 * Pango::SCALE);
_layout->set_font_description(_font_descript);
//change mode of midnam display
if (av_note_height >= 8.0) {
_mini_map_display = false;
} else {
_mini_map_display = true;
}
//Set Pango layout midnam size
_font_descript_midnam.set_absolute_size (max(8.0 * 0.7 * Pango::SCALE, (int)av_note_height * 0.7 * Pango::SCALE));
_midnam_layout->set_font_description(_font_descript_midnam);
lowest = max(_midi_context.lowest_note(), _midi_context.y_to_note(y2));
highest = min(_midi_context.highest_note(), _midi_context.y_to_note(y1));
if (lowest > 127) {
lowest = 0;
}
/* fill the entire rect with the color for non-highlighted white notes.
* then we won't have to draw the background for those notes,
* and would only have to draw the background for the one highlighted white note*/
//cr->rectangle(rect.x, rect.y, rect.width, rect.height);
//r->set_source_rgb(1, 0,0);
//cr->fill();
cr->set_line_width (1.0f);
Gtkmm2ext::Color white = UIConfiguration::instance().color (X_("piano key white"));
Gtkmm2ext::Color white_highlight = UIConfiguration::instance().color (X_("piano key highlight"));
Gtkmm2ext::Color black = UIConfiguration::instance().color (X_("piano key black"));
Gtkmm2ext::Color black_highlight = UIConfiguration::instance().color (X_("piano key highlight"));
Gtkmm2ext::Color textc = UIConfiguration::instance().color (X_("gtk_foreground"));
// Render the MIDNAM text or its equivalent. First, set up a clip
// region so that the text doesn't spill, regardless of its length.
cr->save();
cr->rectangle (0,0,_scroomer_size, get().height () );
cr->clip();
if (show_scroomer()) {
/* Draw the actual text */
for (int i = lowest; i <= highest; ++i) {
int size_x, size_y;
double y = floor(_midi_context.note_to_y(i)) - 0.5f;
NoteName const & note (note_names[i]);
_midnam_layout->set_text (note.name);
set_source_rgba (cr, textc);
cr->move_to (2.f, y);
if (!_mini_map_display) {
_midnam_layout->show_in_cairo_context (cr);
} else {
/* Too small for text, just show a thing rect where the
text would have been.
*/
if (!note.from_midnam) {
set_source_rgba(cr, textc);
}
pango_layout_get_pixel_size (_midnam_layout->gobj (), &size_x, &size_y);
cr->rectangle (2.f, y + (av_note_height * 0.5), size_x, av_note_height * 0.2);
cr->fill ();
}
}
/* Add a gradient over the text, to act as a sort of "visual
elision". This avoids using text elision with "..." which takes up too
much space.
*/
Gtkmm2ext::Color bg = UIConfiguration::instance().color (X_("gtk_background"));
double r,g,b,a;
Gtkmm2ext::color_to_rgba(bg,r,g,b,a);
double fade_width = 30.;
auto gradient_ptr = Cairo::LinearGradient::create (_scroomer_size - fade_width, 0, _scroomer_size, 0);
gradient_ptr->add_color_stop_rgba (0,r,g,b,0);
gradient_ptr->add_color_stop_rgba (1,r,g,b,1);
cr->set_source (gradient_ptr);
cr->rectangle (_scroomer_size - fade_width, 0, _scroomer_size, get().height () );
cr->fill();
}
/* Now draw the semi-transparent scroomer over the top */
render_scroomer (cr);
/* Done with clip region */
cr->restore();
/* Now draw black/white rects for each note, following standard piano
layout, but without a setback/offset for the black keys
*/
for (int i = lowest; i <= highest; ++i) {
oct_rel = i % 12;
switch (oct_rel) {
case 1:
case 3:
case 6:
case 8:
case 10:
/* black note */
if (i == _highlighted_note) {
bg = black_highlight;
} else {
bg = black;
}
/* draw black separators */
cr->set_source_rgb (0.0f, 0.0f, 0.0f);
get_path (i, x, y);
create_path (cr, x, y, 0, 1);
cr->stroke();
get_path (i, x, y);
create_path (cr, x, y, 0, 1);
cr->stroke();
get_path (i, x, y);
render_rect (cr, i, x, y, bg);
break;
}
switch(oct_rel) {
case 0:
case 2:
case 4:
case 5:
case 7:
case 9:
case 11:
if (i == _highlighted_note) {
bg = white_highlight;
} else {
bg = white;
}
get_path (i, x, y);
render_rect (cr, i, x, y, bg);
break;
default:
break;
}
}
/* render the C<N> of the key, when key is too small to contain text we
place the C<N> on the midnam scroomer area.
we render an additional 5 notes below the lowest note displayed
so that the top of the C is shown to maintain visual context
*/
for (int i = lowest - 5; i <= highest; ++i) {
double y = floor(_midi_context.note_to_y(i)) - 0.5f;
double note_height = i == 0? av_note_height : floor(_midi_context.note_to_y(i - 1)) - y;
oct_rel = i % 12;
if (oct_rel == 0 || (oct_rel == 7 && _adj.get_page_size() <=10)) {
std::stringstream s;
int cn = i / 12 - 1;
if (oct_rel == 0){
s << 'C' << cn;
} else {
s << 'G' << cn;
}
if (av_note_height > 12.0){
set_source_rgba(cr, black);
_layout->set_text (s.str());
cr->move_to(_scroomer_size, ceil(y+1.));
_layout->show_in_cairo_context (cr);
}else{
set_source_rgba(cr, textc);
_big_c_layout->set_text (s.str());
pango_layout_get_pixel_size (_big_c_layout->gobj(), &bc_width, &bc_height);
cr->move_to(_scroomer_size - 18, y - bc_height + av_note_height);
_big_c_layout->show_in_cairo_context (cr);
cr->move_to(_scroomer_size - 18, y + note_height);
cr->line_to(_scroomer_size, y + note_height);
cr->stroke();
}
}
}
/* Done with translation for item->window */
cr->restore ();
}
void
PianoRollHeader::instrument_info_change ()
{
have_note_names = false;
for (int i = 0; i < 128; ++i) {
note_names[i] = get_note_name (i);
if (note_names[i].from_midnam) {
have_note_names = true;
}
}
queue_resize ();
/* need this to get editor to potentially sync all
track header widths if our piano roll header changes
width.
*/
if (_view) {
_view->midi_track()->gui_changed ("visible_tracks", (void *) 0); /* EMIT SIGNAL */
}
}
PianoRollHeader::NoteName
PianoRollHeader::get_note_name (int note)
{
using namespace MIDI::Name;
std::string name;
std::string note_n;
NoteName rtn;
#if 0
MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*>(&_view.trackview());
if (mtv) {
string chn = mtv->gui_property (X_("midnam-channel"));
if (!chn.empty()) {
int midnam_channel;
sscanf (chn.c_str(), "%*s %d", &midnam_channel);
midnam_channel--;
name = mtv->route()->instrument_info ().get_note_name (
0, //bank
0, //program
midnam_channel, //channel
note); //note
}
}
int oct_rel = note % 12;
switch (oct_rel) {
case 0:
note_n = "C";
break;
case 1:
note_n = "C♯";
break;
case 2:
note_n = "D";
break;
case 3:
note_n = "D♯";
break;
case 4:
note_n = "E";
break;
case 5:
note_n = "F";
break;
case 6:
note_n = "F♯";
break;
case 7:
note_n = "G";
break;
case 8:
note_n = "G♯";
break;
case 9:
note_n = "A";
break;
case 10:
note_n = "A♯";
break;
case 11:
note_n = "B";
break;
default:
break;
}
#endif
std::string new_string = std::string(3 - std::to_string(note).length(), '0') + std::to_string(note);
rtn.name = name.empty()? new_string + " " + note_n : name;
rtn.from_midnam = !name.empty();
return rtn;
}
bool
PianoRollHeader::motion_handler (GdkEventMotion* ev)
{
if (!_view) {
return false;
}
Duple evd (canvas_to_item (Duple (ev->x, ev->y)));
if (!_scroomer_drag && ev->x < _scroomer_size){
Gdk::Cursor m_Cursor;
double scroomer_top = max(1.0, (1.0 - ((_adj.get_value()+_adj.get_page_size()) / 127.0)) * get().height());
double scroomer_bottom = (1.0 - (_adj.get_value () / 127.0)) * get().height();
if (evd.y > scroomer_top - 5 && evd.y < scroomer_top + 5){
m_Cursor = Gdk::Cursor (Gdk::TOP_SIDE);
_view->editing_context().push_canvas_cursor (&m_Cursor);
_scroomer_state = TOP;
} else if (evd.y > scroomer_bottom - 5 && evd.y < scroomer_bottom + 5){
m_Cursor = Gdk::Cursor (Gdk::BOTTOM_SIDE);
_view->editing_context().push_canvas_cursor (&m_Cursor);
_scroomer_state = BOTTOM;
} else {
_scroomer_state = MOVE;
_view->editing_context().pop_canvas_cursor ();
}
}
if (_scroomer_drag){
double pixel2val = 127.0 / get().height();
double delta = _old_y - evd.y;
double val_at_pointer = (delta * pixel2val);
double real_val_at_pointer = 127.0 - (evd.y * pixel2val);
double note_range = _adj.get_page_size ();
switch (_scroomer_button_state){
case MOVE:
_fract += val_at_pointer;
_fract = (_fract + note_range > 127.0)? 127.0 - note_range : _fract;
_fract = max(0.0, _fract);
_adj.set_value (min(_fract, 127.0 - note_range));
break;
case TOP:
real_val_at_pointer = real_val_at_pointer <= _saved_top_val? _adj.get_value() + _adj.get_page_size() : real_val_at_pointer;
real_val_at_pointer = min(127.0, real_val_at_pointer);
if (_midi_context.note_height() >= UIConfiguration::instance().get_max_note_height()){
_saved_top_val = min(_adj.get_value() + _adj.get_page_size (), 127.0);
} else {
_saved_top_val = 0.0;
}
//if we are at largest note size & the user is moving down don't do anything
//FIXME we are using a heuristic of 18.5 for max note size, but this changes when track size is small to 19.5?
_midi_context.apply_note_range (_adj.get_value (), real_val_at_pointer, true);
break;
case BOTTOM:
real_val_at_pointer = max(0.0, real_val_at_pointer);
real_val_at_pointer = real_val_at_pointer >= _saved_bottom_val? _adj.get_value() : real_val_at_pointer;
if (_midi_context.note_height() >= UIConfiguration::instance().get_max_note_height()){
_saved_bottom_val = _adj.get_value();
} else {
_saved_bottom_val = 127.0;
}
_midi_context.apply_note_range (real_val_at_pointer, _adj.get_value () + _adj.get_page_size (), true);
break;
default:
break;
}
} else {
int note = _midi_context.y_to_note(evd.y);
set_note_highlight (note);
if (_dragging) {
if ( false /*editor().current_mouse_mode() == Editing::MouseRange*/ ) { //ToDo: fix this. this mode is buggy, and of questionable utility anyway
/* select note range */
if (Keyboard::no_modifiers_active (ev->state)) {
AddNoteSelection (note); // EMIT SIGNAL
}
} else {
/* play notes */
/* redraw already taken care of above in set_note_highlight */
if (_clicked_note != NO_MIDI_NOTE && _clicked_note != note) {
_active_notes[_clicked_note] = false;
send_note_off(_clicked_note);
_clicked_note = note;
if (!_active_notes[note]) {
_active_notes[note] = true;
send_note_on(note);
}
}
}
}
}
redraw ();
_old_y = evd.y;
//win->process_updates(false);
return true;
}
bool
PianoRollHeader::button_press_handler (GdkEventButton* ev)
{
if (!_view) {
return false;
}
/* Convert canvas-coordinates to item coordinates */
Duple evd (canvas_to_item (Duple (ev->x, ev->y)));
_scroomer_button_state = _scroomer_state;
if (ev->button == 1 && ev->x <= _scroomer_size){
if (ev->type == GDK_2BUTTON_PRESS) {
_view->set_visibility_note_range (MidiStreamView::ContentsRange, false);
return true;
}
_scroomer_drag = true;
_old_y = evd.y;
_fract = _adj.get_value();
_fract_top = _adj.get_value() + _adj.get_page_size();
return true;
} else {
int note = _midi_context.y_to_note(evd.y);
bool tertiary = Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier);
bool primary = Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier);
if (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS) {
if (primary) {
_adj.set_value (0.0);
_adj.set_page_size (127.0);
_adj.value_changed ();
redraw ();
return false;
}
return false;
} else if (ev->button == 2 && Keyboard::no_modifiers_active (ev->state)) {
SetNoteSelection (note); // EMIT SIGNAL
return true;
} else if (tertiary && (ev->button == 1 || ev->button == 2)) {
ExtendNoteSelection (note); // EMIT SIGNAL
return true;
} else if (primary && (ev->button == 1 || ev->button == 2)) {
ToggleNoteSelection (note); // EMIT SIGNAL
return true;
} else if (ev->button == 1 && note >= 0 && note < 128) {
grab ();
_dragging = true;
if (!_active_notes[note]) {
_active_notes[note] = true;
_clicked_note = note;
send_note_on(note);
invalidate_note_range(note, note);
} else {
reset_clicked_note(note);
}
}
}
return true;
}
bool
PianoRollHeader::button_release_handler (GdkEventButton* ev)
{
Duple evd (canvas_to_item (Duple (ev->x, ev->y)));
_scroomer_drag = false;
int note = _midi_context.y_to_note(evd.y);
if (false /*editor().current_mouse_mode() == Editing::MouseRange*/) { //Todo: this mode is buggy, and of questionable utility anyway
if (Keyboard::no_modifiers_active (ev->state)) {
AddNoteSelection (note); // EMIT SIGNAL
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
ToggleNoteSelection (note); // EMIT SIGNAL
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::RangeSelectModifier)) {
ExtendNoteSelection (note); // EMIT SIGNAL
}
} else {
if (_dragging) {
ungrab ();
if (note == _clicked_note) {
reset_clicked_note (note);
}
}
}
_dragging = false;
return true;
}
void
PianoRollHeader::set_note_highlight (uint8_t note)
{
if (_highlighted_note == note) {
return;
}
if (_highlighted_note != NO_MIDI_NOTE) {
if (note > _highlighted_note) {
invalidate_note_range (_highlighted_note, note);
} else {
invalidate_note_range (note, _highlighted_note);
}
}
_highlighted_note = note;
if (_highlighted_note != NO_MIDI_NOTE) {
invalidate_note_range (_highlighted_note, _highlighted_note);
}
}
bool
PianoRollHeader::enter_handler (GdkEventCrossing* ev)
{
Duple evd (canvas_to_item (Duple (ev->x, ev->y)));
set_note_highlight (_midi_context.y_to_note (evd.y));
entered = true;
redraw ();
return true;
}
bool
PianoRollHeader::leave_handler (GdkEventCrossing*)
{
if (!_scroomer_drag){
if (_view) {
_view->editing_context().pop_canvas_cursor ();
}
}
invalidate_note_range(_highlighted_note, _highlighted_note);
if (_clicked_note != NO_MIDI_NOTE) {
reset_clicked_note (_clicked_note, _clicked_note != _highlighted_note);
}
_highlighted_note = NO_MIDI_NOTE;
entered = false;
redraw ();
return true;
}
void
PianoRollHeader::note_range_changed ()
{
redraw ();
}
void
PianoRollHeader::invalidate_note_range (int lowest, int highest)
{
lowest = max((int) _midi_context.lowest_note(), lowest - 1);
highest = min((int) _midi_context.highest_note(), highest + 2);
double y = _midi_context.note_to_y (highest);
double height = _midi_context.note_to_y (lowest - 1) - y;
dynamic_cast<ArdourCanvas::GtkCanvas*>(_canvas)->queue_draw_area (0., floor (y), get().width(), floor (height));
}
bool
PianoRollHeader::show_scroomer () const
{
if (!_view) {
return false;
}
Editing::NoteNameDisplay nnd = UIConfiguration::instance().get_note_name_display();
if (nnd == Editing::Never) {
return false;
}
switch (_view->editing_context().current_mouse_mode()) {
case Editing::MouseDraw:
case Editing::MouseContent:
if (nnd == Editing::WithMIDNAM) {
return have_note_names;
} else {
return true;
}
default:
break;
}
return false;
}
void
PianoRollHeader::send_note_on (uint8_t note)
{
if (!_view) {
return;
}
std::shared_ptr<ARDOUR::MidiTrack> track = _view->midi_track ();
//cerr << "note on: " << (int) note << endl;
if (track) {
_event[0] = (MIDI_CMD_NOTE_ON | _midi_context.get_preferred_midi_channel ());
_event[1] = note;
_event[2] = 100;
track->write_user_immediate_event (Evoral::MIDI_EVENT, 3, _event);
}
}
void
PianoRollHeader::send_note_off (uint8_t note)
{
if (!_view) {
return;
}
std::shared_ptr<ARDOUR::MidiTrack> track = _view->midi_track ();
if (track) {
_event[0] = (MIDI_CMD_NOTE_OFF | _midi_context.get_preferred_midi_channel ());
_event[1] = note;
_event[2] = 100;
track->write_user_immediate_event (Evoral::MIDI_EVENT, 3, _event);
}
}
void
PianoRollHeader::reset_clicked_note (uint8_t note, bool invalidate)
{
_active_notes[note] = false;
_clicked_note = NO_MIDI_NOTE;
send_note_off (note);
if (invalidate) {
invalidate_note_range (note, note);
}
}
void
PianoRollHeader::set_min_page_size(double page_size)
{
_min_page_size = page_size;
};
}

135
gtk2_ardour/prh.h Normal file
View File

@ -0,0 +1,135 @@
/*
* Copyright (C) 2008-2009 David Robillard <d@drobilla.net>
* Copyright (C) 2010-2012 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.
*/
#ifndef __ardour_canvas_piano_roll_header_h__
#define __ardour_canvas_piano_roll_header_h__
#include <pangomm/layout.h>
#include <glibmm/refptr.h>
#include "ardour/types.h"
#include "canvas/rectangle.h"
namespace ARDOUR {
class MidiTrack;
}
class MidiView;
class MidiViewBackground;
class EditingContext;
namespace ArdourCanvas {
class PianoRollHeader : public ArdourCanvas::Rectangle {
public:
PianoRollHeader (ArdourCanvas::Item* parent, MidiViewBackground&);
void size_request (double& w, double& h) const;
void render (ArdourCanvas::Rect const & area, Cairo::RefPtr<Cairo::Context>) const;
void instrument_info_change ();
void note_range_changed();
void set_note_highlight (uint8_t note);
sigc::signal<void,uint8_t> SetNoteSelection;
sigc::signal<void,uint8_t> AddNoteSelection;
sigc::signal<void,uint8_t> ToggleNoteSelection;
sigc::signal<void,uint8_t> ExtendNoteSelection;
void set_view (MidiView&);
private:
MidiViewBackground& _midi_context;
Gtk::Adjustment& _adj;
MidiView* _view;
uint8_t _event[3];
mutable Glib::RefPtr<Pango::Layout> _layout;
mutable Glib::RefPtr<Pango::Layout> _big_c_layout;
mutable Glib::RefPtr<Pango::Layout> _midnam_layout;
mutable Pango::FontDescription _font_descript;
Pango::FontDescription _font_descript_big_c;
mutable Pango::FontDescription _font_descript_midnam;
bool _active_notes[128];
uint8_t _highlighted_note;
uint8_t _clicked_note;
double _grab_y;
bool _dragging;
mutable double _scroomer_size;
bool _scroomer_drag;
double _old_y;
double _fract;
double _fract_top;
double _min_page_size;
enum scr_pos {TOP, BOTTOM, MOVE, NONE};
scr_pos _scroomer_state;
scr_pos _scroomer_button_state;
double _saved_top_val;
double _saved_bottom_val;
mutable bool _mini_map_display;
bool entered;
// void on_size_request(Gtk::Requisition*);
struct NoteName {
std::string name;
bool from_midnam;
};
NoteName note_names[128];
bool have_note_names;
PBD::ScopedConnection height_connection;
void set_min_page_size (double page_size);
void render_scroomer (Cairo::RefPtr<Cairo::Context>) const;
NoteName get_note_name (int note);
bool event_handler (GdkEvent*);
bool motion_handler (GdkEventMotion*);
bool button_press_handler (GdkEventButton*);
bool button_release_handler (GdkEventButton*);
bool scroll_handler (GdkEventScroll*);
bool enter_handler (GdkEventCrossing*);
bool leave_handler (GdkEventCrossing*);
enum ItemType {
BLACK_SEPARATOR,
BLACK_MIDDLE_SEPARATOR,
BLACK,
WHITE_SEPARATOR,
WHITE_RECT,
WHITE_CF,
WHITE_EB,
WHITE_DGA
};
void invalidate_note_range (int lowest, int highest);
void get_path (int note, double x[], double y[]) const;
void send_note_on (uint8_t note);
void send_note_off (uint8_t note);
void reset_clicked_note (uint8_t, bool invalidate = true);
bool show_scroomer () const;
void resize ();
};
}
#endif /* __ardour_piano_roll_header_h__ */

View File

@ -29,12 +29,11 @@ const int PublicEditor::container_border_width = 12;
const int PublicEditor::vertical_spacing = 6;
const int PublicEditor::horizontal_spacing = 6;
sigc::signal<void> PublicEditor::DropDownKeys;
ARDOUR::DataType PublicEditor::pbdid_dragged_dt = ARDOUR::DataType::NIL;
PublicEditor::PublicEditor (Gtk::Widget& content)
: Tabbable (content, _("Editor"), X_("editor"))
, EditingContext (X_("Editor"))
{
_suspend_route_redisplay_counter.store (0);
}

View File

@ -60,8 +60,8 @@
#include "widgets/tabbable.h"
#include "axis_provider.h"
#include "editing.h"
#include "editing_context.h"
#include "selection.h"
namespace Temporal {
@ -96,6 +96,7 @@ class MeterMarker;
class MixerStrip;
class MouseCursors;
class RegionView;
class MidiView;
class RouteTimeAxisView;
class Selection;
class SimpleExport;
@ -123,7 +124,7 @@ using ARDOUR::samplecnt_t;
* of PublicEditor need not be recompiled if private methods or member variables
* change.
*/
class PublicEditor : public ArdourWidgets::Tabbable, public ARDOUR::SessionHandlePtr, public AxisViewProvider
class PublicEditor : public ArdourWidgets::Tabbable, public EditingContext
{
public:
PublicEditor (Gtk::Widget& content);
@ -137,37 +138,12 @@ public:
virtual void setup_tooltips() = 0;
/* returns the time domain to be used when there's no other overriding
* reason to choose one.
*/
virtual Temporal::TimeDomain default_time_domain() const = 0;
/** Attach this editor to a Session.
* @param s Session to connect to.
*/
virtual void set_session (ARDOUR::Session* s) = 0;
/** Set the snap type.
* @param t Snap type (defined in editing_syms.h)
*/
virtual void set_grid_to (Editing::GridType t) = 0;
virtual Editing::GridType grid_type () const = 0;
virtual Editing::SnapMode snap_mode () const = 0;
/** Set the snap mode.
* @param m Snap mode (defined in editing_syms.h)
*/
virtual void set_snap_mode (Editing::SnapMode m) = 0;
/**
* Snap a value according to the current snap setting.
* ensure_snap overrides SnapOff and magnetic snap
*/
virtual void snap_to (Temporal::timepos_t & first,
Temporal::RoundMode direction = Temporal::RoundNearest,
ARDOUR::SnapPref gpref = ARDOUR::SnapToAny_Visual,
bool ensure_snap = false) = 0;
virtual samplepos_t playhead_cursor_sample () const = 0;
/** Undo some transactions.
* @param n Number of transactions to undo.
@ -180,26 +156,6 @@ public:
*/
virtual void redo (uint32_t n = 1) = 0;
/** Set the mouse mode (gain, object, range, timefx etc.)
* @param m Mouse mode (defined in editing_syms.h)
* @param force Perform the effects of the change even if no change is required
* (ie even if the current mouse mode is equal to @p m)
*/
virtual void set_mouse_mode (Editing::MouseMode m, bool force = false) = 0;
/** Step the mouse mode onto the next or previous one.
* @param next true to move to the next, otherwise move to the previous
*/
virtual void step_mouse_mode (bool next) = 0;
/** @return The current mouse mode (gain, object, range, timefx etc.)
* (defined in editing_syms.h)
*/
virtual Editing::MouseMode current_mouse_mode () const = 0;
/** @return Whether the current mouse mode is an "internal" editing mode. */
virtual bool internal_editing() const = 0;
/** Possibly start the audition of a region.
*
* If \p r is 0, or not an AudioRegion any current audition is cancelled.
@ -219,28 +175,13 @@ public:
virtual void reverse_region () = 0;
virtual void normalize_region () = 0;
virtual void quantize_region () = 0;
virtual void legatize_region (bool shrink_only) = 0;
virtual void transform_region () = 0;
virtual void transpose_region () = 0;
virtual void pitch_shift_region () = 0;
virtual void transition_to_rolling (bool fwd) = 0;
virtual samplepos_t pixel_to_sample (double pixel) const = 0;
virtual samplepos_t playhead_cursor_sample () const = 0;
virtual double sample_to_pixel (samplepos_t sample) const = 0;
virtual double sample_to_pixel_unrounded (samplepos_t sample) const = 0;
virtual double time_to_pixel (Temporal::timepos_t const &) const = 0;
virtual double time_to_pixel_unrounded (Temporal::timepos_t const &) const = 0;
virtual double duration_to_pixels (Temporal::timecnt_t const &) const = 0;
virtual double duration_to_pixels_unrounded (Temporal::timecnt_t const &) const = 0;
virtual Selection& get_selection () const = 0;
virtual bool get_selection_extents (Temporal::timepos_t &start, Temporal::timepos_t &end) const = 0;
virtual Selection& get_cut_buffer () const = 0;
virtual void set_selection (std::list<Selectable*>, Selection::Operation) = 0;
virtual void set_selected_midi_region_view (MidiRegionView&) = 0;
virtual std::shared_ptr<ARDOUR::Route> current_mixer_stripable () const = 0;
@ -317,10 +258,6 @@ public:
virtual void loudness_assistant (bool) = 0;
virtual void register_actions () = 0;
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 clear_playlist (std::shared_ptr<ARDOUR::Playlist>) = 0;
virtual void clear_grouped_playlists (RouteUI*) = 0;
@ -351,18 +288,6 @@ public:
virtual void toggle_cue_behavior () = 0;
/** Set whether the editor should follow the playhead.
* @param yn true to follow playhead, otherwise false.
* @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
*/
virtual void set_follow_playhead (bool yn, bool catch_up = true) = 0;
/** Toggle whether the editor is following the playhead */
virtual void toggle_follow_playhead () = 0;
/** @return true if the editor is following the playhead */
virtual bool follow_playhead () const = 0;
/** @return true if the playhead is currently being dragged, otherwise false */
virtual bool dragging_playhead () const = 0;
virtual samplepos_t leftmost_sample() const = 0;
@ -379,9 +304,6 @@ public:
virtual void cleanup_regions () = 0;
virtual void prepare_for_cleanup () = 0;
virtual void finish_cleanup () = 0;
virtual void reset_x_origin (samplepos_t sample) = 0;
virtual double get_y_origin () const = 0;
virtual void reset_y_origin (double pos) = 0;
virtual void set_visible_track_count (int32_t) = 0;
virtual void fit_selection () = 0;
virtual void remove_last_capture () = 0;
@ -394,20 +316,8 @@ public:
virtual void mouse_add_new_marker (Temporal::timepos_t where, ARDOUR::Location::Flags extra_flags = ARDOUR::Location::Flags (0), int32_t cue_id = 0) = 0;
virtual void foreach_time_axis_view (sigc::slot<void,TimeAxisView&>) = 0;
virtual void add_to_idle_resize (TimeAxisView*, int32_t) = 0;
virtual Temporal::timecnt_t get_nudge_distance (Temporal::timepos_t const & pos, Temporal::timecnt_t& next) = 0;
virtual Temporal::timecnt_t get_paste_offset (Temporal::timepos_t const & pos, unsigned paste_count, Temporal::timecnt_t const & duration) = 0;
virtual Temporal::Beats get_grid_type_as_beats (bool& success, Temporal::timepos_t const & position) = 0;
virtual Temporal::Beats get_draw_length_as_beats (bool& success, Temporal::timepos_t const & position) = 0;
virtual int draw_velocity () const = 0;
virtual int draw_channel () const = 0;
virtual int32_t get_grid_beat_divisions (Editing::GridType gt) = 0;
virtual int32_t get_grid_music_divisions (Editing::GridType gt, uint32_t event_state) = 0;
virtual void edit_notes (MidiRegionView*) = 0;
virtual void queue_visual_videotimeline_update () = 0;
virtual void set_close_video_sensitive (bool) = 0;
virtual void toggle_ruler_video (bool) = 0;
@ -423,22 +333,17 @@ public:
virtual bool track_selection_change_without_scroll () const = 0;
virtual bool show_touched_automation () const = 0;
virtual StripableTimeAxisView* get_stripable_time_axis_by_id (const PBD::ID& id) const = 0;
virtual TimeAxisView* time_axis_view_from_stripable (std::shared_ptr<ARDOUR::Stripable> s) const = 0;
virtual void get_equivalent_regions (RegionView* rv, std::vector<RegionView*>&, PBD::PropertyID) const = 0;
virtual RegionView* regionview_from_region (std::shared_ptr<ARDOUR::Region>) const = 0;
virtual RouteTimeAxisView* rtav_from_route (std::shared_ptr<ARDOUR::Route>) const = 0;
sigc::signal<void> ZoomChanged;
sigc::signal<void> Realized;
sigc::signal<void,samplepos_t> UpdateAllTransportClocks;
virtual bool pending_locate_request() const = 0;
static sigc::signal<void> DropDownKeys;
struct RegionAction {
Glib::RefPtr<Gtk::Action> action;
Editing::RegionActionTarget target;
@ -452,10 +357,8 @@ public:
std::map<std::string,RegionAction> region_action_map;
Glib::RefPtr<Gtk::ActionGroup> editor_actions;
Glib::RefPtr<Gtk::ActionGroup> editor_menu_actions;
Glib::RefPtr<Gtk::ActionGroup> _region_actions;
Glib::RefPtr<Gtk::ActionGroup> _midi_actions;
virtual bool canvas_scroll_event (GdkEventScroll* event, bool from_canvas) = 0;
virtual bool canvas_control_point_event (GdkEvent* event, ArdourCanvas::Item*, ControlPoint*) = 0;
@ -487,8 +390,6 @@ public:
virtual bool canvas_bbt_marker_event (GdkEvent* event, ArdourCanvas::Item*, BBTMarker*) = 0;
virtual bool canvas_automation_track_event(GdkEvent* event, ArdourCanvas::Item*, AutomationTimeAxisView*) = 0;
virtual bool canvas_note_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
static const int window_border_width;
static const int container_border_width;
static const int vertical_spacing;
@ -500,31 +401,15 @@ public:
virtual ArdourCanvas::ScrollGroup* get_cursor_scroll_group () const = 0;
virtual ArdourCanvas::Container* get_drag_motion_group () const = 0;
virtual ArdourCanvas::GtkCanvasViewport* get_track_canvas() const = 0;
virtual void set_current_trimmable (std::shared_ptr<ARDOUR::Trimmable>) = 0;
virtual void set_current_movable (std::shared_ptr<ARDOUR::Movable>) = 0;
virtual void center_screen (samplepos_t) = 0;
virtual TrackViewList axis_views_from_routes (std::shared_ptr<ARDOUR::RouteList>) const = 0;
virtual TrackViewList const & get_track_views () const = 0;
virtual MixerStrip* get_current_mixer_strip () const = 0;
virtual DragManager* drags () const = 0;
virtual bool drag_active () const = 0;
virtual bool preview_video_drag_active () const = 0;
virtual void maybe_autoscroll (bool, bool, bool from_headers) = 0;
virtual void stop_canvas_autoscroll () = 0;
virtual bool autoscroll_active() const = 0;
virtual void begin_reversible_selection_op (std::string cmd_name) = 0;
virtual void commit_reversible_selection_op () = 0;
virtual void begin_reversible_command (std::string cmd_name) = 0;
virtual void begin_reversible_command (GQuark) = 0;
virtual void abort_reversible_command () = 0;
virtual void commit_reversible_command () = 0;
virtual Temporal::TempoMap::WritableSharedPtr begin_tempo_map_edit () = 0;
virtual void abort_tempo_map_edit () = 0;
@ -539,37 +424,15 @@ public:
virtual void access_action (const std::string&, const std::string&) = 0;
virtual void set_toggleaction (const std::string&, const std::string&, bool) = 0;
virtual MouseCursors const* cursors () const = 0;
virtual VerboseCursor* verbose_cursor () const = 0;
virtual EditorCursor* playhead_cursor () const = 0;
virtual EditorCursor* snapped_cursor () const = 0;
virtual bool get_smart_mode () const = 0;
virtual void get_pointer_position (double &, double &) const = 0;
virtual std::pair <Temporal::timepos_t, Temporal::timepos_t> session_gui_extents (bool use_extra = true) const = 0;
virtual ARDOUR::Location* find_location_from_marker (ArdourMarker*, bool&) const = 0;
virtual ArdourMarker* find_marker_from_location_id (PBD::ID const&, bool) const = 0;
virtual TempoMarker* find_marker_for_tempo (Temporal::TempoPoint const &) = 0;
virtual MeterMarker* find_marker_for_meter (Temporal::MeterPoint const &) = 0;
virtual 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) = 0;
virtual Temporal::timepos_t snap_to_bbt (Temporal::timepos_t const & pos, Temporal::RoundMode, ARDOUR::SnapPref) = 0;
virtual void set_snapped_cursor_position (Temporal::timepos_t const & pos) = 0;
virtual void get_regions_at (RegionSelection &, Temporal::timepos_t const & where, TrackViewList const &) const = 0;
virtual void get_regions_after (RegionSelection&, Temporal::timepos_t const & where, const TrackViewList& ts) const = 0;
virtual RegionSelection get_regions_from_selection_and_mouse (Temporal::timepos_t const &) = 0;
virtual void get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const = 0;
virtual void get_per_region_note_selection (std::list<std::pair<PBD::ID, std::set<std::shared_ptr<Evoral::Note<Temporal::Beats> > > > >&) const = 0;
virtual void build_region_boundary_cache () = 0;
virtual void mark_region_boundary_cache_dirty () = 0;
@ -583,9 +446,6 @@ public:
virtual void queue_redisplay_track_views () = 0;
virtual ARDOUR::Quantize* get_quantize_op () = 0;
virtual void apply_midi_note_edit_op (ARDOUR::MidiOperator& op, const RegionSelection& rs) = 0;
virtual void set_tempo_curve_range (double& max, double& min) const = 0;
/// Singleton instance, set up by Editor::Editor()
@ -595,11 +455,6 @@ public:
friend bool ARDOUR_UI_UTILS::relay_key_press (GdkEventKey*, Gtk::Window*);
friend bool ARDOUR_UI_UTILS::forward_key_press (GdkEventKey*);
PBD::Signal0<void> SnapChanged;
PBD::Signal0<void> MouseModeChanged;
Gtkmm2ext::Bindings* bindings;
protected:
friend class DisplaySuspender;
virtual void suspend_route_redisplay () = 0;

View File

@ -26,7 +26,7 @@
#include "pbd/convert.h"
#include "quantize_dialog.h"
#include "public_editor.h"
#include "editing_context.h"
#include "pbd/i18n.h"
#include "pbd/integer_division.h"
@ -71,7 +71,7 @@ static const int _grid_beats[] = {
std::vector<std::string> QuantizeDialog::grid_strings;
QuantizeDialog::QuantizeDialog (PublicEditor& e)
QuantizeDialog::QuantizeDialog (EditingContext& e)
: ArdourDialog (_("Quantize"), false, false)
, editor (e)
, strength_adjustment (100.0, 0.0, 100.0, 1.0, 10.0)

View File

@ -38,12 +38,12 @@ namespace ARDOUR {
class MidiModel;
};
class PublicEditor;
class EditingContext;
class QuantizeDialog : public ArdourDialog
{
public:
QuantizeDialog (PublicEditor&);
QuantizeDialog (EditingContext&);
~QuantizeDialog ();
Temporal::Beats start_grid_size() const;
@ -55,7 +55,7 @@ public:
float swing () const;
private:
PublicEditor& editor;
EditingContext& editor;
Gtk::ComboBoxText start_grid_combo;
Gtk::ComboBoxText end_grid_combo;

View File

@ -1139,40 +1139,6 @@ RegionView::move_contents (timecnt_t const & distance)
region_changed (PropertyChange (ARDOUR::Properties::start));
}
/** Snap a time offset within our region using the current snap settings.
* @param x Time offset from this region's position.
* @param ensure_snap whether to ignore snap_mode (in the case of SnapOff) and magnetic snap.
* Used when inverting snap mode logic with key modifiers, or snap distance calculation.
* @return Snapped time offset from this region's position.
*/
timecnt_t
RegionView::snap_region_time_to_region_time (timecnt_t const & x, bool ensure_snap) const
{
PublicEditor& editor = trackview.editor();
/* x is region relative, convert it to global absolute time */
timepos_t const session_pos = _region->position() + x;
/* try a snap in either direction */
timepos_t snapped = session_pos;
editor.snap_to (snapped, Temporal::RoundNearest, SnapToAny_Visual, ensure_snap);
/* if we went off the beginning of the region, snap forwards */
if (snapped < _region->position ()) {
snapped = session_pos;
editor.snap_to (snapped, Temporal::RoundUpAlways, SnapToAny_Visual, ensure_snap);
}
/* back to region relative */
return _region->region_relative_position (snapped);
}
timecnt_t
RegionView::region_relative_distance (timecnt_t const & duration, Temporal::TimeDomain domain)
{
return Temporal::TempoMap::use()->convert_duration (duration, _region->position(), domain);
}
void
RegionView::update_visibility ()
{

View File

@ -101,12 +101,13 @@ public:
virtual void exited () {}
bool display_enabled() const;
void redisplay (bool view_only = true) {
_redisplay (view_only);
virtual void redisplay (bool) = 0;
void redisplay () {
redisplay (true);
}
virtual void tempo_map_changed () {
_redisplay (true);
redisplay (true);
}
struct DisplaySuspender {
@ -249,7 +250,6 @@ private:
typedef std::list<ViewCueMarker*> ViewCueMarkers;
ViewCueMarkers _cue_markers;
bool _cue_markers_visible;
virtual void _redisplay (bool) = 0;
private:
friend struct DisplaySuspender;

View File

@ -341,9 +341,6 @@ RouteTimeAxisView::~RouteTimeAxisView ()
delete automation_action_menu;
delete _view;
_view = 0;
_automation_tracks.clear ();
delete route_group_menu;

View File

@ -63,7 +63,7 @@ struct TimelineRangeComparator {
}
};
Selection::Selection (const PublicEditor* e, bool mls)
Selection::Selection (const EditingContext* e, bool mls)
: editor (e)
, next_time_id (0)
, manage_libardour_selection (mls)
@ -1693,8 +1693,8 @@ Selection::midi_regions ()
{
MidiRegionSelection ms;
for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(*i);
for (auto & r : regions) {
MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(r);
if (mrv) {
ms.add (mrv);
}

View File

@ -48,7 +48,7 @@
class TimeAxisView;
class RegionView;
class Selectable;
class PublicEditor;
class EditingContext;
class MidiRegionView;
class AutomationLine;
class ControlPoint;
@ -102,7 +102,7 @@ public:
*/
MidiRegionSelection midi_regions();
Selection (PublicEditor const * e, bool manage_libardour_selection);
Selection (EditingContext const * e, bool manage_libardour_selection);
// Selection& operator= (const Selection& other);
@ -250,7 +250,7 @@ public:
void core_selection_changed (PBD::PropertyChange const & pc);
private:
PublicEditor const * editor;
EditingContext const * editor;
uint32_t next_time_id;
bool manage_libardour_selection;

View File

@ -49,6 +49,7 @@
#include "trigger_ui.h"
#include "utils.h"
#include "audio_clip_editor.h"
#include "audio_region_properties_box.h"
#include "audio_trigger_properties_box.h"
#include "audio_region_operations_box.h"
@ -56,7 +57,7 @@
#include "midi_trigger_properties_box.h"
#include "midi_region_properties_box.h"
#include "midi_region_operations_box.h"
#include "midi_clip_editor.h"
#include "midi_cue_editor.h"
#include "slot_properties_box.h"
@ -743,20 +744,24 @@ SlotPropertyWindow::SlotPropertyWindow (TriggerReference tref)
_trim_box = manage(new AudioClipEditorBox ());
_trig_box->set_trigger (tref);
_trim_box->set_region(trigger->region(), tref);
_ops_box->set_session(&trigger->region()->session());
table->attach(*_trig_box, col, col+1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); col++;
table->attach(*_ops_box, col, col+1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); col++;
table->attach(*_trim_box, col, col+1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); col++;
} else {
_trig_box = manage(new MidiTriggerPropertiesBox ());
_ops_box = manage(new MidiRegionOperationsBox ());
_trim_box = manage(new MidiClipEditorBox ());
_trig_box->set_trigger (tref);
_midi_editor = new MidiCueEditor;
std::cerr << "here\n";
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++;
}
_trim_box->set_region(trigger->region(), tref);
_ops_box->set_session(&trigger->region()->session());
table->attach(*_trig_box, col, col+1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); col++;
table->attach(*_trim_box, col, col+1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); col++;
table->attach(*_ops_box, col, col+1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); col++;
}
add (*table);

View File

@ -52,6 +52,7 @@ namespace ArdourWidgets {
class TriggerPropertiesBox;
class RegionPropertiesBox;
class RegionOperationsBox;
class MidiCueEditor;
class ClipEditorBox;
class SlotPropertyTable : public TriggerUI, public Gtk::Table
@ -185,5 +186,6 @@ class SlotPropertyWindow : public Gtk::Window
TriggerPropertiesBox *_trig_box;
RegionOperationsBox *_ops_box;
ClipEditorBox *_trim_box;
MidiCueEditor* _midi_editor;
};
#endif /* __multi_region_properties_box_h__ */

View File

@ -284,8 +284,8 @@ StepEditor::step_add_note (uint8_t channel, uint8_t pitch, uint8_t velocity, Tem
/* make sure its visible on the vertical axis */
if (pitch < msv->lowest_note() || pitch > msv->highest_note()) {
msv->update_note_range (pitch);
msv->set_note_range (MidiStreamView::ContentsRange);
msv->maybe_extend_note_range (pitch);
msv->set_note_visibility_range_style (MidiStreamView::ContentsRange);
}
/* make sure its visible on the horizontal axis */

View File

@ -95,8 +95,6 @@ StreamView::StreamView (RouteTimeAxisView& tv, ArdourCanvas::Container* canvas_g
StreamView::~StreamView ()
{
undisplay_track ();
delete canvas_rect;
}

View File

@ -31,7 +31,9 @@
#include "pbd/signals.h"
#include "ardour/location.h"
#include "enums.h"
#include "view_background.h"
namespace Gdk {
class Color;
@ -64,7 +66,7 @@ class RegionSelection;
class CrossfadeView;
class Selection;
class StreamView : public sigc::trackable, public PBD::ScopedConnectionList
class StreamView : public sigc::trackable, public PBD::ScopedConnectionList, public virtual ViewBackground
{
public:
virtual ~StreamView ();

View File

@ -24,7 +24,6 @@
using namespace std;
SysEx::SysEx (
MidiRegionView& region,
ArdourCanvas::Container* parent,
string& text,
double height,

View File

@ -30,7 +30,6 @@ class SysEx
{
public:
SysEx (
MidiRegionView& region,
ArdourCanvas::Container* parent,
std::string& text,
double height,

View File

@ -618,7 +618,7 @@ TimeAxisViewItem::get_canvas_frame()
}
ArdourCanvas::Item*
TimeAxisViewItem::get_canvas_group()
TimeAxisViewItem::get_canvas_group() const
{
return group;
}

View File

@ -85,7 +85,7 @@ public:
virtual uint32_t get_fill_color () const;
ArdourCanvas::Item* get_canvas_frame();
ArdourCanvas::Item* get_canvas_group();
ArdourCanvas::Item* get_canvas_group() const;
ArdourCanvas::Item* get_name_highlight();
virtual void set_samples_per_pixel (double);

View File

@ -313,7 +313,11 @@ TimeInfoBox::selection_changed ()
case Editing::MouseRange:
if (selection.time.empty()) {
Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action ("MouseMode", "set-mouse-mode-object-range");
/* XXX we really ought to be calling
::get_mouse_mode_action() here but there is no actual
mouse emode enum for smart mode (object-range).
*/
Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (PublicEditor::instance().editor_name(), "set-mouse-mode-object-range");
if (tact->get_active() && !selection.regions.empty()) {
/* show selected regions */

View File

@ -39,14 +39,15 @@
#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"
#include "editor.h"
#include "gui_thread.h"
#include "public_editor.h"
#include "midi_cue_editor.h"
#include "timers.h"
#include "trigger_page.h"
#include "trigger_strip.h"
#include "triggerbox_ui.h"
@ -134,6 +135,8 @@ TriggerPage::TriggerPage ()
_pane_upper.add (_strip_group_box);
_pane_upper.add (_sidebar_vbox);
_midi_editor = new MidiCueEditor;
/* Bottom -- Properties of selected Slot/Region */
Gtk::Table* table = manage (new Gtk::Table);
table->set_homogeneous (false);
@ -142,16 +145,11 @@ TriggerPage::TriggerPage ()
int col = 0;
table->attach (_slot_prop_box, col, col + 1, 0, 1, Gtk::FILL, Gtk::SHRINK | Gtk::FILL);
col = 1;
++col;
table->attach (_audio_trig_box, col, col + 1, 0, 1, Gtk::FILL, Gtk::SHRINK | Gtk::FILL);
++col;
#ifdef MIDI_PROPERTIES_BOX_IMPLEMENTED
col = 2;
table->attach (_midi_trig_box, col, col + 1, 0, 1, Gtk::FILL, Gtk::SHRINK);
table->attach (_midi_editor->toolbox(), col, col + 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL);
++col;
#endif
_parameter_box.pack_start (*table);
@ -226,6 +224,8 @@ TriggerPage::get_state () const
node->set_property (X_("triggerpage-hpane-pos"), _pane_upper.get_divider ());
node->set_property (X_("triggerpage-sidebar-page"), _sidebar_notebook.get_current_page ());
node->add_child_nocopy (_midi_editor->get_state());
return *node;
}
@ -236,6 +236,12 @@ TriggerPage::set_state (const XMLNode& node, int version)
if (node.get_property (X_("triggerpage-sidebar-page"), sidebar_page)) {
_sidebar_notebook.set_current_page (sidebar_page);
}
XMLNode* mn = node.child (X_("MIDICueEditor"));
if (mn) {
_midi_editor->set_state (*mn, version);
}
return Tabbable::set_state (node, version);
}
@ -281,7 +287,7 @@ TriggerPage::set_session (Session* s)
_audio_trig_box.set_session (s);
_midi_trig_box.set_session (s);
_midi_editor->set_session (s);
update_title ();
start_updating ();
@ -386,6 +392,7 @@ TriggerPage::selection_changed ()
_audio_trig_box.hide ();
_midi_trig_box.hide ();
_midi_editor->viewport().hide ();
_parameter_box.hide ();
@ -404,6 +411,13 @@ TriggerPage::selection_changed ()
} else {
_midi_trig_box.set_trigger (ref);
_midi_trig_box.show ();
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

@ -34,7 +34,6 @@
#include "audio_trigger_properties_box.h"
#include "cuebox_ui.h"
#include "fitted_canvas_widget.h"
#include "midi_clip_editor.h"
#include "midi_region_operations_box.h"
#include "midi_region_properties_box.h"
#include "midi_trigger_properties_box.h"
@ -47,6 +46,7 @@
#include "trigger_master.h"
class TriggerStrip;
class MidiCueEditor;
class TriggerPage : public ArdourWidgets::Tabbable, public ARDOUR::SessionHandlePtr, public PBD::ScopedConnectionList, public AxisViewProvider
{
@ -133,11 +133,10 @@ private:
#if REGION_PROPERTIES_BOX_TODO
AudioRegionOperationsBox _audio_ops_box;
AudioClipEditorBox _audio_trim_box;
MidiRegionOperationsBox _midi_ops_box;
MidiClipEditorBox _midi_trim_box;
#endif
MidiCueEditor* _midi_editor;
RouteProcessorSelection _selection;
std::list<TriggerStrip*> _strips;
sigc::connection _fast_screen_update_connection;

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

@ -30,7 +30,7 @@
#include "canvas/tracking_text.h"
#include "audio_clock.h"
#include "editor.h"
#include "editing_context.h"
#include "editor_drag.h"
#include "main_clock.h"
#include "verbose_cursor.h"
@ -43,10 +43,10 @@ using namespace std;
using namespace ARDOUR;
using namespace Temporal;
VerboseCursor::VerboseCursor (Editor* editor)
VerboseCursor::VerboseCursor (EditingContext& editor)
: _editor (editor)
{
_canvas_item = new ArdourCanvas::TrackingText (_editor->get_noscroll_group());
_canvas_item = new ArdourCanvas::TrackingText (_editor.get_noscroll_group());
CANVAS_DEBUG_NAME (_canvas_item, "verbose canvas cursor");
_canvas_item->set_font_description (Pango::FontDescription (UIConfiguration::instance().get_LargerBoldFont()));
color_handler ();
@ -103,7 +103,7 @@ VerboseCursor::set_time (samplepos_t sample)
Timecode::Time timecode;
Temporal::BBT_Time bbt;
if (_editor->_session == 0) {
if (_editor.session() == 0) {
return;
}
@ -118,16 +118,16 @@ VerboseCursor::set_time (samplepos_t sample)
break;
case AudioClock::Timecode:
_editor->_session->timecode_time (sample, timecode);
_editor.session()->timecode_time (sample, timecode);
snprintf (buf, sizeof (buf), "%s", Timecode::timecode_format_time (timecode).c_str());
break;
case AudioClock::MinSec:
AudioClock::print_minsec (sample, buf, sizeof (buf), _editor->_session->sample_rate());
AudioClock::print_minsec (sample, buf, sizeof (buf), _editor.session()->sample_rate());
break;
case AudioClock::Seconds:
snprintf (buf, sizeof(buf), "%.1f", sample / (float)_editor->_session->sample_rate());
snprintf (buf, sizeof(buf), "%.1f", sample / (float)_editor.session()->sample_rate());
break;
default:
@ -147,7 +147,7 @@ VerboseCursor::set_duration (samplepos_t start, samplepos_t end)
Temporal::BBT_Time ebbt;
Meter const & meter_at_start (TempoMap::use()->metric_at (timepos_t (start)).meter());
if (_editor->_session == 0) {
if (_editor.session() == 0) {
return;
}
@ -191,16 +191,16 @@ VerboseCursor::set_duration (samplepos_t start, samplepos_t end)
}
case AudioClock::Timecode:
_editor->_session->timecode_duration (end - start, timecode);
_editor.session()->timecode_duration (end - start, timecode);
snprintf (buf, sizeof (buf), "%s", Timecode::timecode_format_time (timecode).c_str());
break;
case AudioClock::MinSec:
AudioClock::print_minsec (end - start, buf, sizeof (buf), _editor->_session->sample_rate());
AudioClock::print_minsec (end - start, buf, sizeof (buf), _editor.session()->sample_rate());
break;
case AudioClock::Seconds:
snprintf (buf, sizeof(buf), "%.1f", (end - start) / (float)_editor->_session->sample_rate());
snprintf (buf, sizeof(buf), "%.1f", (end - start) / (float)_editor.session()->sample_rate());
break;
default:

View File

@ -23,7 +23,7 @@
#include "ardour/types.h"
#include "canvas/canvas.h"
class Editor;
class EditingContext;
namespace ArdourCanvas {
class TrackingText;
@ -32,7 +32,7 @@ namespace ArdourCanvas {
class VerboseCursor
{
public:
VerboseCursor (Editor *);
VerboseCursor (EditingContext&);
ArdourCanvas::Item* canvas_item () const;
bool visible () const;
@ -46,7 +46,7 @@ public:
void hide ();
private:
Editor* _editor;
EditingContext& _editor;
ArdourCanvas::TrackingText* _canvas_item;
void color_handler ();

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
* Copyright (C) 2007 Doug McLain <doug@nostar.net>
* Copyright (C) 2008-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2014-2019 Robin Gareus <robin@gareus.org>
* Copyright (C) 2015 Tim Mayberry <mojofunk@gmail.com>
* Copyright (C) 2016 Nick Mainsbridge <mainsbridge@gmail.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/line_set.h"
#include "view_background.h"
#include "ui_config.h"
using namespace std;
ViewBackground::ViewBackground ()
{
UIConfiguration::instance().ColorsChanged.connect(sigc::mem_fun(*this, &ViewBackground::color_handler));
UIConfiguration::instance().ParameterChanged.connect(sigc::mem_fun(*this, &ViewBackground::parameter_changed));
}
ViewBackground::~ViewBackground()
{
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
* Copyright (C) 2007 Doug McLain <doug@nostar.net>
* Copyright (C) 2008-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2016-2017 Robin Gareus <robin@gareus.org>
*
* 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.
*/
#ifndef __gtk2_ardour_view_background_h__
#define __gtk2_ardour_view_background_h__
#include <cstdint>
#include "gtkmm2ext/colors.h"
namespace ArdourCanvas {
class Item;
}
/** A class that provides limited context for a View
*/
class ViewBackground
{
public:
ViewBackground ();
virtual ~ViewBackground ();
virtual double height() const { return 0.; }
virtual double contents_height() const { return 0.; }
/** @return y position, or -1 if hidden */
virtual double y_position () const { return 0.; }
protected:
virtual void update_contents_height () {}
virtual void color_handler () {}
virtual void parameter_changed (std::string const &) {}
};
#endif /* __gtk2_ardour_view_background_h__ */

View File

@ -65,6 +65,7 @@ gtk2_ardour_sources = [
'control_point_dialog.cc',
'control_slave_ui.cc',
'cuebox_ui.cc',
'cue_editor.cc',
'cursor_context.cc',
'curvetest.cc',
'debug.cc',
@ -73,6 +74,7 @@ gtk2_ardour_sources = [
'duplicate_routes_dialog.cc',
'edit_note_dialog.cc',
'editing.cc',
'editing_context.cc',
'editor.cc',
'editor_actions.cc',
'editor_audio_import.cc',
@ -157,7 +159,9 @@ gtk2_ardour_sources = [
'midi_automation_line.cc',
'midi_channel_dialog.cc',
'midi_channel_selector.cc',
'midi_clip_editor.cc',
'midi_cue_background.cc',
'midi_cue_editor.cc',
'midi_cue_view.cc',
'midi_cut_buffer.cc',
'midi_export_dialog.cc',
'midi_list_editor.cc',
@ -170,6 +174,8 @@ gtk2_ardour_sources = [
'midi_time_axis.cc',
'midi_tracer.cc',
'midi_velocity_dialog.cc',
'midi_view.cc',
'midi_view_background.cc',
'mini_timeline.cc',
'missing_file_dialog.cc',
'missing_filesource_dialog.cc',
@ -228,7 +234,8 @@ gtk2_ardour_sources = [
'port_matrix_grid.cc',
'port_matrix_labels.cc',
'port_matrix_row_labels.cc',
'processor_box.cc',
'prh.cc',
'processor_box.cc',
'processor_selection.cc',
'patch_change_dialog.cc',
'progress_reporter.cc',
@ -333,6 +340,7 @@ gtk2_ardour_sources = [
'vca_time_axis.cc',
'video_timeline.cc',
'video_monitor.cc',
'view_background.cc',
'transcode_ffmpeg.cc',
'transcode_video_dialog.cc',
'velocity_ghost_region.cc',

View File

@ -26,6 +26,8 @@
#include "temporal/beats.h"
#include "evoral/Sequence.h"
#include "ardour/libardour_visibility.h"
namespace PBD {
class Command;
}

View File

@ -1262,6 +1262,8 @@ MidiModel::sync_to_source (const Source::WriterLock& source_lock)
{
ReadLock lock(read_lock());
std::cerr << "SYNC " << _midi_source.name() << " from model\n";
/* Invalidate and store active notes, which will be picked up by the iterator
on the next roll if time progresses linearly. */
_midi_source.invalidate(source_lock);

View File

@ -419,9 +419,9 @@ SMFSource::append_event_beats (const WriterLock& lock,
}
#if 0
printf("SMFSource: %s - append_event_beats ID = %d time = %lf, size = %u, data = ",
name().c_str(), ev.id(), ev.time(), ev.size());
for (size_t i = 0; i < ev.size(); ++i) printf("%X ", ev.buffer()[i]); printf("\n");
std::cerr << "SMFSource " << name() << " - append_event_beats ID = " << ev.id() << " time = " << ev.time() << " size " << ev.size() << " data: ";
for (size_t i = 0; i < ev.size(); ++i) std::cerr << "0x" << std::hex << (int) ev.buffer()[i];
std::cerr << std::dec << std::endl;
#endif
Temporal::Beats time = ev.time();

Some files were not shown because too many files have changed in this diff Show More