Amend bde791df3 (Add support for Region Fx Automation)

This commit is contained in:
Robin Gareus 2024-04-16 21:55:18 +02:00
parent 76badd8c10
commit ff6fe6f852
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
11 changed files with 192 additions and 71 deletions

View File

@ -38,6 +38,7 @@
#include "audio_region_editor.h"
#include "audio_region_view.h"
#include "gui_thread.h"
#include "public_editor.h"
#include "pbd/i18n.h"
@ -59,6 +60,7 @@ AudioRegionEditor::AudioRegionEditor (Session* s, AudioRegionView* arv)
, _audio_region (arv->audio_region ())
, gain_adjustment(accurate_coefficient_to_dB(fabsf (_audio_region->scale_amplitude())), -40.0, +40.0, 0.1, 1.0, 0)
, _polarity_toggle (_("Invert"))
, _show_on_touch (_("Show on Touch"))
, _peak_channel (false)
{
@ -99,6 +101,7 @@ AudioRegionEditor::AudioRegionEditor (Session* s, AudioRegionView* arv)
_region_line_label.set_alignment (1, 0.5);
_table.attach (_region_line_label, 0, 1, _table_row, _table_row + 1, Gtk::FILL, Gtk::FILL);
_table.attach (_region_line, 1, 2, _table_row, _table_row + 1, Gtk::FILL, Gtk::FILL);
_table.attach (_show_on_touch, 2, 3, _table_row, _table_row + 1, Gtk::FILL, Gtk::FILL);
++_table_row;
gain_changed ();
@ -106,6 +109,7 @@ AudioRegionEditor::AudioRegionEditor (Session* s, AudioRegionView* arv)
gain_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &AudioRegionEditor::gain_adjustment_changed));
_polarity_toggle.signal_toggled().connect (sigc::mem_fun (*this, &AudioRegionEditor::gain_adjustment_changed));
_show_on_touch.signal_toggled().connect (sigc::mem_fun (*this, &AudioRegionEditor::show_on_touch_changed));
arv->region_line_changed.connect ((sigc::mem_fun (*this, &AudioRegionEditor::refill_region_line)));
@ -118,6 +122,7 @@ AudioRegionEditor::AudioRegionEditor (Session* s, AudioRegionView* arv)
snprintf (name, 64, "peak amplitude-%p", this);
pthread_create_and_store (name, &_peak_amplitude_thread_handle, _peak_amplitude_thread, this);
signal_peak_thread ();
}
AudioRegionEditor::~AudioRegionEditor ()
@ -210,6 +215,35 @@ AudioRegionEditor::peak_amplitude_found (double p)
_peak_amplitude.set_text (s.str ());
}
void
AudioRegionEditor::show_touched_automation (std::weak_ptr<PBD::Controllable> wac)
{
if (!_arv->set_region_fx_line (wac)) {
return;
}
switch (PublicEditor::instance ().current_mouse_mode ()) {
case Editing::MouseObject:
case Editing::MouseTimeFX:
case Editing::MouseGrid:
case Editing::MouseCut:
PublicEditor::instance ().set_mouse_mode (Editing::MouseDraw, false);
break;
default:
break;
}
}
void
AudioRegionEditor::show_on_touch_changed ()
{
if (!_show_on_touch.get_active ()) {
_ctrl_touched_connection.disconnect ();
return;
}
Controllable::ControlTouched.connect (_ctrl_touched_connection, invalidator (*this), boost::bind (&AudioRegionEditor::show_touched_automation, this, _1), gui_context ());
}
void
AudioRegionEditor::refill_region_line ()
{
@ -278,6 +312,14 @@ AudioRegionEditor::refill_region_line ()
++nth;
});
if (rm_items.size () > 1) {
_show_on_touch.set_sensitive (true);
} else {
_show_on_touch.set_active (false);
_show_on_touch.set_sensitive (false);
}
_region_line.set_text (active_text);
_arv->set_ignore_line_change (false);
}

View File

@ -70,6 +70,8 @@ private:
void gain_adjustment_changed ();
void refill_region_line ();
void show_on_touch_changed ();
void show_touched_automation (std::weak_ptr<PBD::Controllable>);
AudioRegionView* _arv;
std::shared_ptr<ARDOUR::AudioRegion> _audio_region;
@ -87,6 +89,9 @@ private:
Gtk::Label _region_line_label;
ArdourWidgets::ArdourDropdown _region_line;
Gtk::CheckButton _show_on_touch;
PBD::ScopedConnection _ctrl_touched_connection;
void signal_peak_thread ();
pthread_t _peak_amplitude_thread_handle;
void peak_amplitude_found (double);

View File

@ -1181,6 +1181,26 @@ AudioRegionView::set_region_gain_line ()
}
}
void
AudioRegionView::set_region_fx_line (std::shared_ptr<AutomationControl> ac, std::shared_ptr<RegionFxPlugin> rfx, uint32_t param_id)
{
const string line_name = _region->name () + ":" + rfx->describe_parameter (Evoral::Parameter (PluginAutomation, 0, param_id));
_fx_line.reset (new RegionFxLine (line_name, *this, *group, ac));
_fx_line->set_height ((uint32_t) rint (height() - NAME_HIGHLIGHT_SIZE) - 2);
_fx_line->reset ();
rfx->DropReferences.connect (_region_fx_connection, invalidator (*this), boost::bind (&AudioRegionView::set_region_gain_line, this), gui_context ());
bool changed = _rfx_id != rfx->id () || _rdx_param != param_id;
_rfx_id = rfx->id ();
_rdx_param = param_id;
envelope_active_changed ();
if (changed) {
region_line_changed (); /* EMIT SIGNAL */
}
}
bool
AudioRegionView::set_region_fx_line (uint32_t plugin_id, uint32_t param_id)
{
@ -1192,28 +1212,46 @@ AudioRegionView::set_region_fx_line (uint32_t plugin_id, uint32_t param_id)
std::shared_ptr<Evoral::Control> c = rfx->control (Evoral::Parameter (PluginAutomation, 0, param_id));
std::shared_ptr<AutomationControl> ac = std::dynamic_pointer_cast<AutomationControl> (c);
if (ac) {
ac->set_automation_state (Play);
const string line_name = _region->name () + ":" + rfx->describe_parameter (Evoral::Parameter (PluginAutomation, 0, param_id));
_fx_line.reset (new RegionFxLine (line_name, *this, *group, ac->alist (), ac->desc ()));
_fx_line->set_height ((uint32_t) rint (height() - NAME_HIGHLIGHT_SIZE) - 2);
_fx_line->reset ();
rfx->DropReferences.connect (_region_fx_connection, invalidator (*this), boost::bind (&AudioRegionView::set_region_gain_line, this), gui_context ());
bool changed = _rfx_id != rfx->id () || _rdx_param != param_id;
_rfx_id = rfx->id ();
_rdx_param = param_id;
envelope_active_changed ();
if (changed) {
region_line_changed (); /* EMIT SIGNAL */
}
set_region_fx_line (ac, rfx, param_id);
return true;
}
}
return false;
}
bool
AudioRegionView::set_region_fx_line (std::weak_ptr<PBD::Controllable> wac)
{
if (_ignore_line_change) {
return false;
}
std::shared_ptr<AutomationControl> ac = std::dynamic_pointer_cast<AutomationControl> (wac.lock ());
if (!ac) {
return false;
}
bool found = false;
_region->foreach_plugin ([this, ac, &found](std::weak_ptr<RegionFxPlugin> wfx)
{
std::shared_ptr<RegionFxPlugin> rfx (wfx.lock ());
if (!rfx || found) {
return;
}
std::shared_ptr<Plugin> plugin = rfx->plugin ();
for (size_t i = 0; i < plugin->parameter_count (); ++i) {
if (!plugin->parameter_is_control (i) || !plugin->parameter_is_input (i)) {
continue;
}
const Evoral::Parameter param (PluginAutomation, 0, i);
if (ac == std::dynamic_pointer_cast<ARDOUR::AutomationControl> (rfx->control (param))) {
set_region_fx_line (ac, rfx, i);
found = true;
break;
}
}
});
return found;
}
bool
AudioRegionView::get_region_fx_line (PBD::ID& id, uint32_t& param_id)
{
@ -1483,24 +1521,13 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, b
*/
XMLNode &before = _fx_line->the_list()->get_state();
MementoCommand<AudioRegion>* region_memento = 0;
if (!audio_region()->envelope_active() && _fx_line->the_list() == audio_region()->envelope()) {
XMLNode &region_before = audio_region()->get_state();
audio_region()->set_envelope_active(true);
XMLNode &region_after = audio_region()->get_state();
region_memento = new MementoCommand<AudioRegion>(*(audio_region().get()), &region_before, &region_after);
}
if (_fx_line->the_list()->editor_add (timepos_t (fx), y, with_guard_points)) {
XMLNode &after = _fx_line->the_list()->get_state();
std::list<Selectable*> results;
trackview.editor().begin_reversible_command (_("add gain control point"));
if (region_memento) {
trackview.session()->add_command (region_memento);
}
_fx_line->enable_autoation ();
trackview.session()->add_command (new MementoCommand<AutomationList>(*_fx_line->the_list(), &before, &after));
@ -1510,19 +1537,10 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, b
trackview.editor ().commit_reversible_command ();
trackview.session ()->set_dirty ();
} else {
delete region_memento;
delete &before;
}
}
#if 0 // unused
void
AudioRegionView::remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent* /*ev*/)
{
ControlPoint *cp = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"));
_fx_line->the_list()->erase (cp->model());
}
#endif
GhostRegion*
AudioRegionView::add_ghost (TimeAxisView& tv)
{

View File

@ -94,13 +94,13 @@ public:
void set_region_gain_line ();
void set_ignore_line_change (bool v) { _ignore_line_change = v; };
bool set_region_fx_line (uint32_t, uint32_t);
bool set_region_fx_line (std::weak_ptr<PBD::Controllable>);
bool get_region_fx_line (PBD::ID&, uint32_t&);
void update_envelope_visibility ();
sigc::signal<void> region_line_changed;
void add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event, bool with_guard_points);
void remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event);
std::shared_ptr<RegionFxLine> fx_line() const { return _fx_line; }
@ -242,6 +242,8 @@ private:
bool trim_fade_in_drag_active;
bool trim_fade_out_drag_active;
void set_region_fx_line (std::shared_ptr<ARDOUR::AutomationControl>, std::shared_ptr<ARDOUR::RegionFxPlugin>, uint32_t);
PBD::ID _rfx_id;
uint32_t _rdx_param;
bool _ignore_line_change;

View File

@ -87,7 +87,7 @@ using namespace Temporal;
AutomationLine::AutomationLine (const string& name,
TimeAxisView& tv,
ArdourCanvas::Item& parent,
std::shared_ptr<AutomationList> al,
std::shared_ptr<AutomationList> al,
const ParameterDescriptor& desc)
: trackview (tv)
, _name (name)

View File

@ -68,7 +68,7 @@ public:
AutomationLine (const std::string& name,
TimeAxisView& tv,
ArdourCanvas::Item& parent,
std::shared_ptr<ARDOUR::AutomationList> al,
std::shared_ptr<ARDOUR::AutomationList> al,
const ARDOUR::ParameterDescriptor& desc);
@ -249,6 +249,7 @@ private:
const ARDOUR::ParameterDescriptor _desc;
friend class AudioRegionGainLine;
friend class RegionFxLine;
};
#endif /* __ardour_automation_line_h__ */

View File

@ -834,7 +834,7 @@ LuaInstance::register_classes (lua_State* L, bool sandbox)
.deriveClass <AudioRegionView, RegionView> ("RegionView")
.addFunction ("set_region_gain_line", &AudioRegionView::set_region_gain_line)
.addFunction ("set_region_fx_line", &AudioRegionView::set_region_fx_line)
.addFunction ("set_region_fx_line", (bool (AudioRegionView::*)(uint32_t, uint32_t))&AudioRegionView::set_region_fx_line)
.endClass ()
.deriveClass <RouteUI, Selectable> ("RouteUI")

View File

@ -16,15 +16,35 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "ardour/automation_control.h"
#include "audio_region_view.h"
#include "gui_thread.h"
#include "region_fx_line.h"
#include "pbd/i18n.h"
RegionFxLine::RegionFxLine (std::string const& name, RegionView& r, ArdourCanvas::Container& parent, std::shared_ptr<ARDOUR::AutomationList> l, ARDOUR::ParameterDescriptor const& d)
using namespace ARDOUR;
RegionFxLine::RegionFxLine (std::string const& name, RegionView& r, ArdourCanvas::Container& parent, std::shared_ptr<AutomationList> l, ParameterDescriptor const& d)
: AutomationLine (name, r.get_time_axis_view(), parent, l, d)
, rv (r)
, _rv (r)
{
init ();
}
RegionFxLine::RegionFxLine (std::string const& name, RegionView& r, ArdourCanvas::Container& parent, std::shared_ptr<ARDOUR::AutomationControl> ac)
: AutomationLine (name, r.get_time_axis_view(), parent, ac->alist (), ac->desc ())
, _rv (r)
, _ac (ac)
{
init ();
}
void
RegionFxLine::init ()
{
_rv.region()->PropertyChanged.connect (_region_changed_connection, invalidator (*this), boost::bind (&RegionFxLine::region_changed, this, _1), gui_context());
group->raise_to_top ();
group->set_y_position (2);
}
@ -32,5 +52,41 @@ RegionFxLine::RegionFxLine (std::string const& name, RegionView& r, ArdourCanvas
Temporal::timepos_t
RegionFxLine::get_origin() const
{
return rv.region()->position();
return _rv.region()->position();
}
void
RegionFxLine::enable_autoation ()
{
std::shared_ptr<AutomationControl> ac = _ac.lock ();
if (ac) {
ac->set_automation_state (Play);
}
}
void
RegionFxLine::end_drag (bool with_push, uint32_t final_index)
{
enable_autoation ();
AutomationLine::end_drag (with_push, final_index);
}
void
RegionFxLine::end_draw_merge ()
{
enable_autoation ();
AutomationLine::end_draw_merge ();
}
void
RegionFxLine::region_changed (PBD::PropertyChange const& what_changed)
{
PBD::PropertyChange interesting_stuff;
interesting_stuff.add (ARDOUR::Properties::start);
interesting_stuff.add (ARDOUR::Properties::length);
if (what_changed.contains (interesting_stuff)) {
reset ();
}
}

View File

@ -27,13 +27,24 @@ class RegionFxLine : public AutomationLine
{
public:
RegionFxLine (std::string const&, RegionView&, ArdourCanvas::Container&, std::shared_ptr<ARDOUR::AutomationList>, ARDOUR::ParameterDescriptor const&);
RegionFxLine (std::string const&, RegionView&, ArdourCanvas::Container&, std::shared_ptr<ARDOUR::AutomationControl>);
Temporal::timepos_t get_origin() const;
RegionView& region_view () { return rv; }
RegionView& region_view () { return _rv; }
protected:
RegionView& rv;
void end_drag (bool with_push, uint32_t final_index);
void end_draw_merge ();
virtual void enable_autoation ();
private:
void init ();
void region_changed (PBD::PropertyChange const&);
RegionView& _rv;
std::weak_ptr<ARDOUR::AutomationControl> _ac;
PBD::ScopedConnection _region_changed_connection;
};
#endif

View File

@ -35,19 +35,16 @@
#include "time_axis_view.h"
#include "editor.h"
#include "gui_thread.h"
#include "pbd/i18n.h"
using namespace std;
using namespace ARDOUR;
using namespace PBD;
AudioRegionGainLine::AudioRegionGainLine (const string & name, AudioRegionView& r, ArdourCanvas::Container& parent, std::shared_ptr<AutomationList> l)
: RegionFxLine (name, r, parent, l, l->parameter ())
, arv (r)
{
r.region()->PropertyChanged.connect (_region_changed_connection, invalidator (*this), boost::bind (&AudioRegionGainLine::region_changed, this, _1), gui_context());
terminal_points_can_slide = false;
}
@ -97,7 +94,7 @@ AudioRegionGainLine::remove_point (ControlPoint& cp)
if (!arv.audio_region()->envelope_active()) {
arv.audio_region()->clear_changes ();
arv.audio_region()->set_envelope_active(true);
trackview.session()->add_command(new StatefulDiffCommand (arv.audio_region()));
trackview.session()->add_command(new PBD::StatefulDiffCommand (arv.audio_region()));
}
trackview.editor ().get_selection ().clear_points ();
@ -121,25 +118,17 @@ AudioRegionGainLine::end_drag (bool with_push, uint32_t final_index)
void
AudioRegionGainLine::end_draw_merge ()
{
enable_autoation ();
RegionFxLine::end_draw_merge ();
}
void
AudioRegionGainLine::enable_autoation ()
{
if (!arv.audio_region()->envelope_active()) {
XMLNode& before = arv.audio_region()->get_state();
arv.audio_region()->set_envelope_active(true);
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(arv.audio_region().get()), &before, &arv.audio_region()->get_state()));
}
RegionFxLine::end_draw_merge ();
}
void
AudioRegionGainLine::region_changed (const PropertyChange& what_changed)
{
PropertyChange interesting_stuff;
interesting_stuff.add (ARDOUR::Properties::start);
interesting_stuff.add (ARDOUR::Properties::length);
if (what_changed.contains (interesting_stuff)) {
reset ();
}
}

View File

@ -46,14 +46,11 @@ public:
void start_drag_multiple (std::list<ControlPoint*>, float, XMLNode*);
void end_drag (bool with_push, uint32_t final_index);
void end_draw_merge ();
void enable_autoation ();
void remove_point (ControlPoint&);
private:
void region_changed (const PBD::PropertyChange& what_changed);
AudioRegionView& arv;
PBD::ScopedConnection _region_changed_connection;
};
#endif /* __ardour_gtk_region_gain_line_h__ */