Compare commits
78 Commits
Author | SHA1 | Date |
---|---|---|
Paul Davis | 9b61abd390 | |
Paul Davis | d191330235 | |
Paul Davis | d6dcb1c575 | |
Paul Davis | a5b6e1676a | |
Paul Davis | 8661bfb090 | |
Paul Davis | f76d81d44f | |
Paul Davis | 0b7461c465 | |
Paul Davis | 8d8e8a5509 | |
Paul Davis | 69ab632e95 | |
Paul Davis | c3c34a0e0e | |
Paul Davis | 3d71e6136b | |
Paul Davis | 7d28d89635 | |
Paul Davis | f08ada678a | |
Paul Davis | 784aa8ccc6 | |
Paul Davis | a17eac860b | |
Paul Davis | 46c341175d | |
Paul Davis | 9f76533f76 | |
Paul Davis | 7329508fd1 | |
Paul Davis | a8194729f1 | |
Paul Davis | bc00c320c4 | |
Paul Davis | 807c098a7a | |
Paul Davis | e6b6152f5a | |
Paul Davis | e2e660b4cd | |
Paul Davis | 4f7ff877a9 | |
Paul Davis | b8217f12f2 | |
Paul Davis | 7dac2a216d | |
Paul Davis | 5509db3b24 | |
Paul Davis | 7836418ebf | |
Paul Davis | 23a672b45d | |
Paul Davis | 89f780b78c | |
Paul Davis | b77974b7c0 | |
Paul Davis | 86ee139689 | |
Paul Davis | e061c775f0 | |
Paul Davis | 97cf69a408 | |
Paul Davis | bee5edd945 | |
Paul Davis | a86a5e6de3 | |
Paul Davis | dbbc89835b | |
Paul Davis | 96a35e67a5 | |
Paul Davis | e33ade0116 | |
Paul Davis | 3be39c50e1 | |
Paul Davis | 705b9d0ab3 | |
Paul Davis | 032f314de5 | |
Paul Davis | c97bf1a4b7 | |
Paul Davis | efcdf21444 | |
Paul Davis | 0715b0b2d3 | |
Paul Davis | 617749b200 | |
Paul Davis | 4416fa698f | |
Paul Davis | 15e3c235ac | |
Paul Davis | 62966c82bc | |
Paul Davis | ee1e074ca7 | |
Paul Davis | 19b13053d7 | |
Paul Davis | dd4bdbb81f | |
Paul Davis | 5c5340a20d | |
Paul Davis | 3532180fcc | |
Paul Davis | 4d4fba51f6 | |
Paul Davis | 2830cda07e | |
Paul Davis | 534bc9c012 | |
Paul Davis | f75dde7fbc | |
Paul Davis | 0f7cc13c07 | |
Paul Davis | 91f496e533 | |
Paul Davis | 44974c08ea | |
Paul Davis | cfb4ed5884 | |
Paul Davis | 2cdb30d397 | |
Paul Davis | 946fe23e60 | |
Paul Davis | 1f903e402a | |
Paul Davis | 088e71fceb | |
Paul Davis | d0170e3d9f | |
Paul Davis | 797050a56f | |
Paul Davis | 7ffcc1aaf9 | |
Paul Davis | 4effe31b77 | |
Paul Davis | 60f7878dc6 | |
Paul Davis | f037bb622d | |
Paul Davis | ae8587d7e5 | |
Paul Davis | 256edf9b7e | |
Paul Davis | 67f31a0e82 | |
Paul Davis | 2eec8ec62a | |
Paul Davis | cf88db7fe2 | |
Paul Davis | 054e6bca89 |
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -70,6 +70,11 @@ AudioStreamView::AudioStreamView (AudioTimeAxisView& tv)
|
|||
color_handler ();
|
||||
}
|
||||
|
||||
AudioStreamView::~AudioStreamView ()
|
||||
{
|
||||
undisplay_track ();
|
||||
}
|
||||
|
||||
int
|
||||
AudioStreamView::set_amplitude_above_axis (gdouble app)
|
||||
{
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -148,6 +148,8 @@ AudioTimeAxisView::set_route (std::shared_ptr<Route> rt)
|
|||
|
||||
AudioTimeAxisView::~AudioTimeAxisView ()
|
||||
{
|
||||
delete _view;
|
||||
_view = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ protected:
|
|||
void mouse_mode_changed ();
|
||||
void entered();
|
||||
void exited();
|
||||
void _redisplay (bool) {}
|
||||
void redisplay (bool) {}
|
||||
|
||||
private:
|
||||
Evoral::Parameter _parameter;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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__ */
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()))
|
||||
{
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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 ()
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>(),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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__ */
|
|
@ -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));
|
||||
}
|
|
@ -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
|
@ -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 ();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -192,7 +192,6 @@ private:
|
|||
ProcessorBox processor_box;
|
||||
GainMeter gpm;
|
||||
PannerUI panners;
|
||||
TriggerBoxWidget trigger_display;
|
||||
|
||||
Glib::RefPtr<Gtk::SizeGroup> button_size_group;
|
||||
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
|
@ -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__ */
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ()
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -341,9 +341,6 @@ RouteTimeAxisView::~RouteTimeAxisView ()
|
|||
|
||||
delete automation_action_menu;
|
||||
|
||||
delete _view;
|
||||
_view = 0;
|
||||
|
||||
_automation_tracks.clear ();
|
||||
|
||||
delete route_group_menu;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -95,8 +95,6 @@ StreamView::StreamView (RouteTimeAxisView& tv, ArdourCanvas::Container* canvas_g
|
|||
|
||||
StreamView::~StreamView ()
|
||||
{
|
||||
undisplay_track ();
|
||||
|
||||
delete canvas_rect;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
using namespace std;
|
||||
|
||||
SysEx::SysEx (
|
||||
MidiRegionView& region,
|
||||
ArdourCanvas::Container* parent,
|
||||
string& text,
|
||||
double height,
|
||||
|
|
|
@ -30,7 +30,6 @@ class SysEx
|
|||
{
|
||||
public:
|
||||
SysEx (
|
||||
MidiRegionView& region,
|
||||
ArdourCanvas::Container* parent,
|
||||
std::string& text,
|
||||
double height,
|
||||
|
|
|
@ -618,7 +618,7 @@ TimeAxisViewItem::get_canvas_frame()
|
|||
}
|
||||
|
||||
ArdourCanvas::Item*
|
||||
TimeAxisViewItem::get_canvas_group()
|
||||
TimeAxisViewItem::get_canvas_group() const
|
||||
{
|
||||
return group;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
}
|
||||
|
|
@ -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__ */
|
|
@ -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',
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include "temporal/beats.h"
|
||||
#include "evoral/Sequence.h"
|
||||
|
||||
#include "ardour/libardour_visibility.h"
|
||||
|
||||
namespace PBD {
|
||||
class Command;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue