basic implementation of Live-style kbd-driven automation editing
This commit is contained in:
9
gtk2_ardour/automation.bindings
Normal file
9
gtk2_ardour/automation.bindings
Normal file
@@ -0,0 +1,9 @@
|
||||
<Bindings name="Automation">
|
||||
<Press>
|
||||
<Binding key="Return" action="Automation/create-point"/>
|
||||
<Binding key="Right" action="Automation/move-points-later"/>
|
||||
<Binding key="Left" action="Automation/move-points-earlier"/>
|
||||
<Binding key="Up" action="Automation/raise-points"/>
|
||||
<Binding key="Down" action="Automation/lower-points"/>
|
||||
</Press>
|
||||
</Bindings>
|
||||
@@ -971,6 +971,7 @@ AutomationTimeAxisView::entered()
|
||||
if (_line) {
|
||||
_line->track_entered();
|
||||
}
|
||||
_editor.enable_automation_bindings ();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -979,6 +980,8 @@ AutomationTimeAxisView::exited ()
|
||||
if (_line) {
|
||||
_line->track_exited();
|
||||
}
|
||||
|
||||
_editor.enable_automation_bindings ();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -303,6 +303,32 @@ EditingContext::set_selected_midi_region_view (MidiRegionView& mrv)
|
||||
get_selection().set (&mrv);
|
||||
}
|
||||
|
||||
void
|
||||
EditingContext::register_automation_actions (Bindings* automation_bindings, std::string const & prefix)
|
||||
{
|
||||
_automation_actions = ActionManager::create_action_group (automation_bindings, prefix + X_("Automation"));
|
||||
|
||||
reg_sens (_automation_actions, "create-point", _("Create Automation Point"), sigc::mem_fun (*this, &EditingContext::automation_create_point_at_edit_point));
|
||||
reg_sens (_automation_actions, "move-points-later", _("Create Automation P (at Playhead)"), sigc::mem_fun (*this, &EditingContext::automation_move_points_later));
|
||||
reg_sens (_automation_actions, "move-points-earlier", _("Create Automation Point (at Playhead)"), sigc::mem_fun (*this, &EditingContext::automation_move_points_earlier));
|
||||
reg_sens (_automation_actions, "raise-points", _("Create Automation Point (at Playhead)"), sigc::mem_fun (*this, &EditingContext::automation_raise_points));
|
||||
reg_sens (_automation_actions, "lower-points", _("Create Automation Point (at Playhead)"), sigc::mem_fun (*this, &EditingContext::automation_lower_points));
|
||||
|
||||
ActionManager::set_sensitive (_automation_actions, false);
|
||||
}
|
||||
|
||||
void
|
||||
EditingContext::enable_automation_bindings ()
|
||||
{
|
||||
ActionManager::set_sensitive (_automation_actions, true);
|
||||
}
|
||||
|
||||
void
|
||||
EditingContext::disable_automation_bindings ()
|
||||
{
|
||||
ActionManager::set_sensitive (_automation_actions, false);
|
||||
}
|
||||
|
||||
void
|
||||
EditingContext::register_common_actions (Bindings* common_bindings, std::string const & prefix)
|
||||
{
|
||||
@@ -3254,10 +3280,12 @@ EditingContext::load_shared_bindings ()
|
||||
{
|
||||
Bindings* m = Bindings::get_bindings (X_("MIDI"));
|
||||
Bindings* b = Bindings::get_bindings (X_("Editing"));
|
||||
Bindings* a = Bindings::get_bindings (X_("Automation"));
|
||||
|
||||
if (need_shared_actions) {
|
||||
register_midi_actions (m, string());
|
||||
register_common_actions (b, string());
|
||||
register_automation_actions (a, string());
|
||||
need_shared_actions = false;
|
||||
}
|
||||
|
||||
@@ -3279,8 +3307,13 @@ EditingContext::load_shared_bindings ()
|
||||
register_common_actions (shared_bindings, _name);
|
||||
shared_bindings->associate ();
|
||||
|
||||
Bindings* automation_bindings = new Bindings (_name, *a);
|
||||
register_automation_actions (automation_bindings, _name);
|
||||
automation_bindings->associate ();
|
||||
|
||||
/* Attach bindings to the canvas for this editing context */
|
||||
|
||||
bindings.push_back (automation_bindings);
|
||||
bindings.push_back (midi_bindings);
|
||||
bindings.push_back (shared_bindings);
|
||||
}
|
||||
|
||||
@@ -421,6 +421,7 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
|
||||
static bool need_shared_actions;
|
||||
void register_midi_actions (Gtkmm2ext::Bindings*, std::string const &);
|
||||
void register_common_actions (Gtkmm2ext::Bindings*, std::string const &);
|
||||
void register_automation_actions (Gtkmm2ext::Bindings*, std::string const &);
|
||||
|
||||
ArdourCanvas::Rectangle* rubberband_rect;
|
||||
|
||||
@@ -497,12 +498,16 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
|
||||
void center_screen (samplepos_t);
|
||||
void reset_x_origin_to_follow_playhead ();
|
||||
|
||||
void enable_automation_bindings ();
|
||||
void disable_automation_bindings ();
|
||||
|
||||
protected:
|
||||
std::string _name;
|
||||
bool within_track_canvas;
|
||||
|
||||
Glib::RefPtr<Gtk::ActionGroup> _midi_actions;
|
||||
Glib::RefPtr<Gtk::ActionGroup> _common_actions;
|
||||
Glib::RefPtr<Gtk::ActionGroup> _automation_actions;
|
||||
Glib::RefPtr<Gtk::ActionGroup> editor_actions;
|
||||
Glib::RefPtr<Gtk::ActionGroup> snap_actions;
|
||||
Glib::RefPtr<Gtk::ActionGroup> length_actions;
|
||||
@@ -818,4 +823,9 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
|
||||
|
||||
void center_screen_internal (samplepos_t, float);
|
||||
|
||||
virtual void automation_create_point_at_edit_point() {}
|
||||
virtual void automation_raise_points () {}
|
||||
virtual void automation_lower_points () {};
|
||||
virtual void automation_move_points_later () {};
|
||||
virtual void automation_move_points_earlier () {};
|
||||
};
|
||||
|
||||
@@ -1603,6 +1603,11 @@ private:
|
||||
|
||||
protected:
|
||||
void _commit_tempo_map_edit (Temporal::TempoMap::WritableSharedPtr&, bool with_update = false);
|
||||
void automation_create_point_at_edit_point();
|
||||
void automation_raise_points ();
|
||||
void automation_lower_points ();
|
||||
void automation_move_points_later ();
|
||||
void automation_move_points_earlier ();
|
||||
|
||||
private:
|
||||
friend class DragManager;
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
#include "ardour/session.h"
|
||||
#include "ardour/types.h"
|
||||
|
||||
#include "temporal/bbt_time.h"
|
||||
|
||||
#include "canvas/canvas.h"
|
||||
#include "canvas/pixbuf.h"
|
||||
|
||||
@@ -46,6 +48,7 @@
|
||||
|
||||
#include "actions.h"
|
||||
#include "ardour_ui.h"
|
||||
#include "control_point.h"
|
||||
#include "editing.h"
|
||||
#include "editor.h"
|
||||
#include "gui_thread.h"
|
||||
@@ -1333,3 +1336,128 @@ Editor::register_region_actions ()
|
||||
sensitize_all_region_actions (false);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::automation_create_point_at_edit_point ()
|
||||
{
|
||||
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (entered_track);
|
||||
if (!atv) {
|
||||
return;
|
||||
}
|
||||
|
||||
timepos_t where (get_preferred_edit_position());;
|
||||
GdkEvent event;
|
||||
|
||||
event.type = GDK_KEY_PRESS;
|
||||
event.button.button = 1;
|
||||
event.button.state = 0;
|
||||
|
||||
atv->line()->add (atv->control(), &event, where, atv->line()->the_list()->eval (where), false);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::automation_lower_points ()
|
||||
{
|
||||
PointSelection& points (selection->points);
|
||||
|
||||
if (points.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (entered_track);
|
||||
|
||||
if (!atv) {
|
||||
return;
|
||||
}
|
||||
|
||||
begin_reversible_command (_("automation event lower"));
|
||||
add_command (new MementoCommand<AutomationList> (atv->line()->memento_command_binder(), &atv->line()->the_list()->get_state(), 0));
|
||||
atv->line()->the_list()->freeze ();
|
||||
for (auto & p : points) {
|
||||
atv->line()->the_list()->modify (p->model(), (*p->model())->when, max (0.0, (*p->model())->value - 0.1));
|
||||
}
|
||||
atv->line()->the_list()->thaw ();
|
||||
add_command (new MementoCommand<AutomationList>(atv->line()->memento_command_binder (), 0, &atv->line()->the_list()->get_state()));
|
||||
commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
Editor::automation_raise_points ()
|
||||
{
|
||||
PointSelection& points (selection->points);
|
||||
|
||||
if (points.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (entered_track);
|
||||
|
||||
if (!atv) {
|
||||
return;
|
||||
}
|
||||
|
||||
begin_reversible_command (_("automation event raise"));
|
||||
add_command (new MementoCommand<AutomationList> (atv->line()->memento_command_binder(), &atv->line()->the_list()->get_state(), 0));
|
||||
atv->line()->the_list()->freeze ();
|
||||
for (auto & p : points) {
|
||||
atv->line()->the_list()->modify (p->model(), (*p->model())->when, min (1.0, (*p->model())->value + 0.1));
|
||||
}
|
||||
atv->line()->the_list()->thaw ();
|
||||
add_command (new MementoCommand<AutomationList>(atv->line()->memento_command_binder (), 0, &atv->line()->the_list()->get_state()));
|
||||
commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
Editor::automation_move_points_later ()
|
||||
{
|
||||
PointSelection& points (selection->points);
|
||||
|
||||
if (points.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (entered_track);
|
||||
|
||||
if (!atv) {
|
||||
return;
|
||||
}
|
||||
|
||||
begin_reversible_command (_("automation points move later"));
|
||||
add_command (new MementoCommand<AutomationList> (atv->line()->memento_command_binder(), &atv->line()->the_list()->get_state(), 0));
|
||||
atv->line()->the_list()->freeze ();
|
||||
for (auto & p : points) {
|
||||
timepos_t model_time ((*p->model())->when);
|
||||
model_time += Temporal::BBT_Offset (0, 1, 0);
|
||||
atv->line()->the_list()->modify (p->model(), model_time, (*p->model())->value);
|
||||
}
|
||||
atv->line()->the_list()->thaw ();
|
||||
add_command (new MementoCommand<AutomationList>(atv->line()->memento_command_binder (), 0, &atv->line()->the_list()->get_state()));
|
||||
commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
Editor::automation_move_points_earlier ()
|
||||
{
|
||||
PointSelection& points (selection->points);
|
||||
|
||||
if (points.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (entered_track);
|
||||
|
||||
if (!atv) {
|
||||
return;
|
||||
}
|
||||
|
||||
begin_reversible_command (_("automation points move earlier"));
|
||||
add_command (new MementoCommand<AutomationList> (atv->line()->memento_command_binder(), &atv->line()->the_list()->get_state(), 0));
|
||||
atv->line()->the_list()->freeze ();
|
||||
for (auto & p : points) {
|
||||
timepos_t model_time ((*p->model())->when);
|
||||
model_time = model_time.earlier (Temporal::BBT_Offset (0, 1, 0));
|
||||
atv->line()->the_list()->modify (p->model(), model_time, (*p->model())->value);
|
||||
}
|
||||
atv->line()->the_list()->thaw ();
|
||||
add_command (new MementoCommand<AutomationList>(atv->line()->memento_command_binder (), 0, &atv->line()->the_list()->get_state()));
|
||||
commit_reversible_command ();
|
||||
}
|
||||
|
||||
@@ -945,7 +945,7 @@ def build(bld):
|
||||
for b in [ 'ardour' ] :
|
||||
obj = bld(
|
||||
target = b + '.keys',
|
||||
source = [ b + '.keys.in', 'mixer.bindings', 'processor_box.bindings', 'step_editing.bindings', 'monitor.bindings', 'trigger.bindings', 'regionfx_box.bindings' ],
|
||||
source = [ b + '.keys.in', 'mixer.bindings', 'processor_box.bindings', 'step_editing.bindings', 'monitor.bindings', 'trigger.bindings', 'regionfx_box.bindings', 'automation.bindings' ],
|
||||
rule = a_rule
|
||||
)
|
||||
obj.install_path = bld.env['CONFDIR']
|
||||
|
||||
Reference in New Issue
Block a user