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) {
|
if (_line) {
|
||||||
_line->track_entered();
|
_line->track_entered();
|
||||||
}
|
}
|
||||||
|
_editor.enable_automation_bindings ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -979,6 +980,8 @@ AutomationTimeAxisView::exited ()
|
|||||||
if (_line) {
|
if (_line) {
|
||||||
_line->track_exited();
|
_line->track_exited();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_editor.enable_automation_bindings ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -303,6 +303,32 @@ EditingContext::set_selected_midi_region_view (MidiRegionView& mrv)
|
|||||||
get_selection().set (&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
|
void
|
||||||
EditingContext::register_common_actions (Bindings* common_bindings, std::string const & prefix)
|
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* m = Bindings::get_bindings (X_("MIDI"));
|
||||||
Bindings* b = Bindings::get_bindings (X_("Editing"));
|
Bindings* b = Bindings::get_bindings (X_("Editing"));
|
||||||
|
Bindings* a = Bindings::get_bindings (X_("Automation"));
|
||||||
|
|
||||||
if (need_shared_actions) {
|
if (need_shared_actions) {
|
||||||
register_midi_actions (m, string());
|
register_midi_actions (m, string());
|
||||||
register_common_actions (b, string());
|
register_common_actions (b, string());
|
||||||
|
register_automation_actions (a, string());
|
||||||
need_shared_actions = false;
|
need_shared_actions = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3279,8 +3307,13 @@ EditingContext::load_shared_bindings ()
|
|||||||
register_common_actions (shared_bindings, _name);
|
register_common_actions (shared_bindings, _name);
|
||||||
shared_bindings->associate ();
|
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 */
|
/* Attach bindings to the canvas for this editing context */
|
||||||
|
|
||||||
|
bindings.push_back (automation_bindings);
|
||||||
bindings.push_back (midi_bindings);
|
bindings.push_back (midi_bindings);
|
||||||
bindings.push_back (shared_bindings);
|
bindings.push_back (shared_bindings);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -421,6 +421,7 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
|
|||||||
static bool need_shared_actions;
|
static bool need_shared_actions;
|
||||||
void register_midi_actions (Gtkmm2ext::Bindings*, std::string const &);
|
void register_midi_actions (Gtkmm2ext::Bindings*, std::string const &);
|
||||||
void register_common_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;
|
ArdourCanvas::Rectangle* rubberband_rect;
|
||||||
|
|
||||||
@@ -497,12 +498,16 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
|
|||||||
void center_screen (samplepos_t);
|
void center_screen (samplepos_t);
|
||||||
void reset_x_origin_to_follow_playhead ();
|
void reset_x_origin_to_follow_playhead ();
|
||||||
|
|
||||||
|
void enable_automation_bindings ();
|
||||||
|
void disable_automation_bindings ();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string _name;
|
std::string _name;
|
||||||
bool within_track_canvas;
|
bool within_track_canvas;
|
||||||
|
|
||||||
Glib::RefPtr<Gtk::ActionGroup> _midi_actions;
|
Glib::RefPtr<Gtk::ActionGroup> _midi_actions;
|
||||||
Glib::RefPtr<Gtk::ActionGroup> _common_actions;
|
Glib::RefPtr<Gtk::ActionGroup> _common_actions;
|
||||||
|
Glib::RefPtr<Gtk::ActionGroup> _automation_actions;
|
||||||
Glib::RefPtr<Gtk::ActionGroup> editor_actions;
|
Glib::RefPtr<Gtk::ActionGroup> editor_actions;
|
||||||
Glib::RefPtr<Gtk::ActionGroup> snap_actions;
|
Glib::RefPtr<Gtk::ActionGroup> snap_actions;
|
||||||
Glib::RefPtr<Gtk::ActionGroup> length_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);
|
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:
|
protected:
|
||||||
void _commit_tempo_map_edit (Temporal::TempoMap::WritableSharedPtr&, bool with_update = false);
|
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:
|
private:
|
||||||
friend class DragManager;
|
friend class DragManager;
|
||||||
|
|||||||
@@ -39,6 +39,8 @@
|
|||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
#include "ardour/types.h"
|
#include "ardour/types.h"
|
||||||
|
|
||||||
|
#include "temporal/bbt_time.h"
|
||||||
|
|
||||||
#include "canvas/canvas.h"
|
#include "canvas/canvas.h"
|
||||||
#include "canvas/pixbuf.h"
|
#include "canvas/pixbuf.h"
|
||||||
|
|
||||||
@@ -46,6 +48,7 @@
|
|||||||
|
|
||||||
#include "actions.h"
|
#include "actions.h"
|
||||||
#include "ardour_ui.h"
|
#include "ardour_ui.h"
|
||||||
|
#include "control_point.h"
|
||||||
#include "editing.h"
|
#include "editing.h"
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
#include "gui_thread.h"
|
#include "gui_thread.h"
|
||||||
@@ -1333,3 +1336,128 @@ Editor::register_region_actions ()
|
|||||||
sensitize_all_region_actions (false);
|
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' ] :
|
for b in [ 'ardour' ] :
|
||||||
obj = bld(
|
obj = bld(
|
||||||
target = b + '.keys',
|
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
|
rule = a_rule
|
||||||
)
|
)
|
||||||
obj.install_path = bld.env['CONFDIR']
|
obj.install_path = bld.env['CONFDIR']
|
||||||
|
|||||||
Reference in New Issue
Block a user