Add support for Region Fx Automation
This commit is contained in:
parent
e5506d281a
commit
b2d4280e0f
|
@ -33,10 +33,12 @@
|
||||||
#include "ardour/audioregion.h"
|
#include "ardour/audioregion.h"
|
||||||
#include "ardour/session_event.h"
|
#include "ardour/session_event.h"
|
||||||
#include "ardour/dB.h"
|
#include "ardour/dB.h"
|
||||||
|
#include "ardour/region_fx_plugin.h"
|
||||||
|
|
||||||
#include "audio_region_editor.h"
|
#include "audio_region_editor.h"
|
||||||
#include "audio_region_view.h"
|
#include "audio_region_view.h"
|
||||||
#include "gui_thread.h"
|
#include "gui_thread.h"
|
||||||
|
#include "public_editor.h"
|
||||||
|
|
||||||
#include "pbd/i18n.h"
|
#include "pbd/i18n.h"
|
||||||
|
|
||||||
|
@ -52,11 +54,13 @@ _peak_amplitude_thread (void* arg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioRegionEditor::AudioRegionEditor (Session* s, std::shared_ptr<AudioRegion> r)
|
AudioRegionEditor::AudioRegionEditor (Session* s, AudioRegionView* arv)
|
||||||
: RegionEditor (s, r)
|
: RegionEditor (s, arv)
|
||||||
, _audio_region (r)
|
, _arv (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)
|
, gain_adjustment(accurate_coefficient_to_dB(fabsf (_audio_region->scale_amplitude())), -40.0, +40.0, 0.1, 1.0, 0)
|
||||||
, _polarity_toggle (_("Invert"))
|
, _polarity_toggle (_("Invert"))
|
||||||
|
, _show_on_touch (_("Show on Touch"))
|
||||||
, _peak_channel (false)
|
, _peak_channel (false)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -87,14 +91,27 @@ AudioRegionEditor::AudioRegionEditor (Session* s, std::shared_ptr<AudioRegion> r
|
||||||
|
|
||||||
_polarity_label.set_name ("AudioRegionEditorLabel");
|
_polarity_label.set_name ("AudioRegionEditorLabel");
|
||||||
_polarity_label.set_text (_("Polarity:"));
|
_polarity_label.set_text (_("Polarity:"));
|
||||||
|
_polarity_label.set_alignment (1, 0.5);
|
||||||
_table.attach (_polarity_label, 0, 1, _table_row, _table_row + 1, Gtk::FILL, Gtk::FILL);
|
_table.attach (_polarity_label, 0, 1, _table_row, _table_row + 1, Gtk::FILL, Gtk::FILL);
|
||||||
_table.attach (_polarity_toggle, 1, 2, _table_row, _table_row + 1, Gtk::FILL, Gtk::FILL);
|
_table.attach (_polarity_toggle, 1, 2, _table_row, _table_row + 1, Gtk::FILL, Gtk::FILL);
|
||||||
++_table_row;
|
++_table_row;
|
||||||
|
|
||||||
|
_region_line_label.set_name ("AudioRegionEditorLabel");
|
||||||
|
_region_line_label.set_text (_("Region Line:"));
|
||||||
|
_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 ();
|
gain_changed ();
|
||||||
|
refill_region_line ();
|
||||||
|
|
||||||
gain_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &AudioRegionEditor::gain_adjustment_changed));
|
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));
|
_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)));
|
||||||
|
|
||||||
_peak_amplitude.property_editable() = false;
|
_peak_amplitude.property_editable() = false;
|
||||||
_peak_amplitude.set_text (_("Calculating..."));
|
_peak_amplitude.set_text (_("Calculating..."));
|
||||||
|
@ -105,6 +122,7 @@ AudioRegionEditor::AudioRegionEditor (Session* s, std::shared_ptr<AudioRegion> r
|
||||||
snprintf (name, 64, "peak amplitude-%p", this);
|
snprintf (name, 64, "peak amplitude-%p", this);
|
||||||
pthread_create_and_store (name, &_peak_amplitude_thread_handle, _peak_amplitude_thread, this);
|
pthread_create_and_store (name, &_peak_amplitude_thread_handle, _peak_amplitude_thread, this);
|
||||||
signal_peak_thread ();
|
signal_peak_thread ();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioRegionEditor::~AudioRegionEditor ()
|
AudioRegionEditor::~AudioRegionEditor ()
|
||||||
|
@ -128,6 +146,14 @@ AudioRegionEditor::region_changed (const PBD::PropertyChange& what_changed)
|
||||||
signal_peak_thread ();
|
signal_peak_thread ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioRegionEditor::region_fx_changed ()
|
||||||
|
{
|
||||||
|
RegionEditor::region_fx_changed ();
|
||||||
|
refill_region_line ();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioRegionEditor::gain_changed ()
|
AudioRegionEditor::gain_changed ()
|
||||||
{
|
{
|
||||||
|
@ -189,3 +215,118 @@ AudioRegionEditor::peak_amplitude_found (double p)
|
||||||
_peak_amplitude.set_text (s.str ());
|
_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 ()
|
||||||
|
{
|
||||||
|
using namespace Gtk::Menu_Helpers;
|
||||||
|
|
||||||
|
_region_line.clear_items ();
|
||||||
|
|
||||||
|
MenuList& rm_items (_region_line.items ());
|
||||||
|
|
||||||
|
int nth = 0;
|
||||||
|
PBD::ID rfx_id (0);
|
||||||
|
uint32_t param_id = 0;
|
||||||
|
string active_text = _("Gain Envelope");
|
||||||
|
|
||||||
|
_arv->get_region_fx_line (rfx_id, param_id);
|
||||||
|
_arv->set_ignore_line_change (true);
|
||||||
|
|
||||||
|
Gtk::RadioMenuItem::Group grp;
|
||||||
|
AudioRegionView* arv = _arv;
|
||||||
|
|
||||||
|
rm_items.push_back (RadioMenuElem (grp, _("Gain Envelope")));
|
||||||
|
Gtk::CheckMenuItem* cmi = static_cast<Gtk::CheckMenuItem*> (&rm_items.back ());
|
||||||
|
cmi->set_active (rfx_id == 0 || param_id == UINT32_MAX);
|
||||||
|
cmi->signal_activate ().connect ([cmi, arv] () { if (cmi->get_active ()) {arv->set_region_gain_line (); }});
|
||||||
|
|
||||||
|
_audio_region->foreach_plugin ([&rm_items, arv, &nth, &grp, &active_text, rfx_id, param_id](std::weak_ptr<RegionFxPlugin> wfx)
|
||||||
|
{
|
||||||
|
std::shared_ptr<RegionFxPlugin> fx (wfx.lock ());
|
||||||
|
if (!fx) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::shared_ptr<Plugin> plugin = fx->plugin ();
|
||||||
|
|
||||||
|
Gtk::Menu* acm = manage (new Gtk::Menu);
|
||||||
|
MenuList& acm_items (acm->items ());
|
||||||
|
|
||||||
|
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);
|
||||||
|
std::string label = plugin->describe_parameter (param);
|
||||||
|
if (label == X_("latency") || label == X_("hidden")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::shared_ptr<ARDOUR::AutomationControl> c (std::dynamic_pointer_cast<ARDOUR::AutomationControl> (fx->control (param)));
|
||||||
|
if (c && c->flags () & (Controllable::HiddenControl | Controllable::NotAutomatable)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bool active = fx->id () == rfx_id && param_id == i;
|
||||||
|
|
||||||
|
acm_items.push_back (RadioMenuElem (grp, label));
|
||||||
|
Gtk::CheckMenuItem* cmi = static_cast<Gtk::CheckMenuItem*> (&acm_items.back ());
|
||||||
|
cmi->set_active (active);
|
||||||
|
cmi->signal_activate ().connect ([cmi, arv, nth, i] () { if (cmi->get_active ()) {arv->set_region_fx_line (nth, i); }});
|
||||||
|
if (active) {
|
||||||
|
active_text = fx->name () + ": " + label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!acm_items.empty ()) {
|
||||||
|
rm_items.push_back (MenuElem (fx->name (), *acm));
|
||||||
|
} else {
|
||||||
|
delete acm;
|
||||||
|
}
|
||||||
|
++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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioRegionEditor::on_unmap ()
|
||||||
|
{
|
||||||
|
_show_on_touch.set_active (false);
|
||||||
|
ArdourDialog::on_unmap ();
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include <gtkmm/separator.h>
|
#include <gtkmm/separator.h>
|
||||||
#include <gtkmm/spinbutton.h>
|
#include <gtkmm/spinbutton.h>
|
||||||
|
|
||||||
|
#include "widgets/ardour_dropdown.h"
|
||||||
|
|
||||||
#include "pbd/signals.h"
|
#include "pbd/signals.h"
|
||||||
#include "pbd/crossthread.h"
|
#include "pbd/crossthread.h"
|
||||||
|
@ -55,18 +56,25 @@ class AudioRegionView;
|
||||||
class AudioRegionEditor : public RegionEditor
|
class AudioRegionEditor : public RegionEditor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AudioRegionEditor (ARDOUR::Session*, std::shared_ptr<ARDOUR::AudioRegion>);
|
AudioRegionEditor (ARDOUR::Session*, AudioRegionView*);
|
||||||
~AudioRegionEditor ();
|
~AudioRegionEditor ();
|
||||||
|
|
||||||
void peak_amplitude_thread ();
|
void peak_amplitude_thread ();
|
||||||
|
void on_unmap ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void region_changed (PBD::PropertyChange const &);
|
void region_changed (PBD::PropertyChange const &);
|
||||||
|
void region_fx_changed ();
|
||||||
|
|
||||||
void gain_changed ();
|
void gain_changed ();
|
||||||
void gain_adjustment_changed ();
|
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;
|
std::shared_ptr<ARDOUR::AudioRegion> _audio_region;
|
||||||
|
|
||||||
Gtk::Label gain_label;
|
Gtk::Label gain_label;
|
||||||
|
@ -79,6 +87,12 @@ private:
|
||||||
Gtk::Label _peak_amplitude_label;
|
Gtk::Label _peak_amplitude_label;
|
||||||
Gtk::Entry _peak_amplitude;
|
Gtk::Entry _peak_amplitude;
|
||||||
|
|
||||||
|
Gtk::Label _region_line_label;
|
||||||
|
ArdourWidgets::ArdourDropdown _region_line;
|
||||||
|
|
||||||
|
Gtk::CheckButton _show_on_touch;
|
||||||
|
PBD::ScopedConnection _ctrl_touched_connection;
|
||||||
|
|
||||||
void signal_peak_thread ();
|
void signal_peak_thread ();
|
||||||
pthread_t _peak_amplitude_thread_handle;
|
pthread_t _peak_amplitude_thread_handle;
|
||||||
void peak_amplitude_found (double);
|
void peak_amplitude_found (double);
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "ardour/audioregion.h"
|
#include "ardour/audioregion.h"
|
||||||
#include "ardour/audiosource.h"
|
#include "ardour/audiosource.h"
|
||||||
#include "ardour/profile.h"
|
#include "ardour/profile.h"
|
||||||
|
#include "ardour/region_fx_plugin.h"
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
|
|
||||||
#include "pbd/memento_command.h"
|
#include "pbd/memento_command.h"
|
||||||
|
@ -112,8 +113,7 @@ static Cairo::RefPtr<Cairo::Pattern> create_pending_peak_pattern() {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioRegionView::AudioRegionView (ArdourCanvas::Container *parent, RouteTimeAxisView &tv, std::shared_ptr<AudioRegion> r, double spu,
|
AudioRegionView::AudioRegionView (ArdourCanvas::Container *parent, RouteTimeAxisView &tv, std::shared_ptr<AudioRegion> r, double spu, uint32_t basic_color)
|
||||||
uint32_t basic_color)
|
|
||||||
: RegionView (parent, tv, r, spu, basic_color)
|
: RegionView (parent, tv, r, spu, basic_color)
|
||||||
, fade_in_handle(0)
|
, fade_in_handle(0)
|
||||||
, fade_out_handle(0)
|
, fade_out_handle(0)
|
||||||
|
@ -129,6 +129,9 @@ AudioRegionView::AudioRegionView (ArdourCanvas::Container *parent, RouteTimeAxis
|
||||||
, _amplitude_above_axis(1.0)
|
, _amplitude_above_axis(1.0)
|
||||||
, trim_fade_in_drag_active(false)
|
, trim_fade_in_drag_active(false)
|
||||||
, trim_fade_out_drag_active(false)
|
, trim_fade_out_drag_active(false)
|
||||||
|
, _rfx_id (0)
|
||||||
|
, _rdx_param (UINT32_MAX)
|
||||||
|
, _ignore_line_change (false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,6 +152,9 @@ AudioRegionView::AudioRegionView (ArdourCanvas::Container *parent, RouteTimeAxis
|
||||||
, _amplitude_above_axis(1.0)
|
, _amplitude_above_axis(1.0)
|
||||||
, trim_fade_in_drag_active(false)
|
, trim_fade_in_drag_active(false)
|
||||||
, trim_fade_out_drag_active(false)
|
, trim_fade_out_drag_active(false)
|
||||||
|
, _rfx_id (0)
|
||||||
|
, _rdx_param (UINT32_MAX)
|
||||||
|
, _ignore_line_change (false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +174,9 @@ AudioRegionView::AudioRegionView (const AudioRegionView& other, std::shared_ptr<
|
||||||
, _amplitude_above_axis (other._amplitude_above_axis)
|
, _amplitude_above_axis (other._amplitude_above_axis)
|
||||||
, trim_fade_in_drag_active(false)
|
, trim_fade_in_drag_active(false)
|
||||||
, trim_fade_out_drag_active(false)
|
, trim_fade_out_drag_active(false)
|
||||||
|
, _rfx_id (0)
|
||||||
|
, _rdx_param (UINT32_MAX)
|
||||||
|
, _ignore_line_change (false)
|
||||||
{
|
{
|
||||||
init (true);
|
init (true);
|
||||||
}
|
}
|
||||||
|
@ -232,12 +241,7 @@ AudioRegionView::init (bool wfd)
|
||||||
set_fade_visibility (false);
|
set_fade_visibility (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const string line_name = _region->name() + ":gain";
|
set_region_gain_line ();
|
||||||
|
|
||||||
gain_line.reset (new AudioRegionGainLine (line_name, *this, *group, audio_region()->envelope()));
|
|
||||||
|
|
||||||
update_envelope_visibility ();
|
|
||||||
gain_line->reset ();
|
|
||||||
|
|
||||||
/* streamview will call set_height() */
|
/* streamview will call set_height() */
|
||||||
//set_height (trackview.current_height()); // XXX not correct for Layered mode, but set_height() will fix later.
|
//set_height (trackview.current_height()); // XXX not correct for Layered mode, but set_height() will fix later.
|
||||||
|
@ -278,7 +282,7 @@ AudioRegionView::init (bool wfd)
|
||||||
setup_waveform_visibility ();
|
setup_waveform_visibility ();
|
||||||
|
|
||||||
get_canvas_frame()->set_data ("linemerger", (LineMerger*) this);
|
get_canvas_frame()->set_data ("linemerger", (LineMerger*) this);
|
||||||
gain_line->canvas_group().raise_to_top ();
|
_fx_line->canvas_group().raise_to_top ();
|
||||||
|
|
||||||
/* XXX sync mark drag? */
|
/* XXX sync mark drag? */
|
||||||
}
|
}
|
||||||
|
@ -606,15 +610,15 @@ AudioRegionView::set_height (gdouble height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gain_line) {
|
if (_fx_line) {
|
||||||
|
|
||||||
if ((height / nchans) < NAME_HIGHLIGHT_THRESH) {
|
if ((height / nchans) < NAME_HIGHLIGHT_THRESH) {
|
||||||
gain_line->hide ();
|
_fx_line->hide ();
|
||||||
} else {
|
} else {
|
||||||
update_envelope_visibility ();
|
update_envelope_visibility ();
|
||||||
}
|
}
|
||||||
|
|
||||||
gain_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE) - 2);
|
_fx_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE) - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
reset_fade_shapes ();
|
reset_fade_shapes ();
|
||||||
|
@ -1081,8 +1085,8 @@ AudioRegionView::set_samples_per_pixel (gdouble fpp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gain_line) {
|
if (_fx_line) {
|
||||||
gain_line->reset ();
|
_fx_line->reset ();
|
||||||
}
|
}
|
||||||
|
|
||||||
reset_fade_shapes ();
|
reset_fade_shapes ();
|
||||||
|
@ -1101,12 +1105,9 @@ AudioRegionView::set_colors ()
|
||||||
{
|
{
|
||||||
RegionView::set_colors();
|
RegionView::set_colors();
|
||||||
|
|
||||||
if (gain_line) {
|
assert (_fx_line);
|
||||||
gain_line->set_line_color (audio_region()->envelope_active() ?
|
|
||||||
UIConfiguration::instance().color ("gain line") :
|
|
||||||
UIConfiguration::instance().color_mod ("gain line inactive", "gain line inactive"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
set_fx_line_colors ();
|
||||||
set_waveform_colors ();
|
set_waveform_colors ();
|
||||||
|
|
||||||
if (start_xfade_curve) {
|
if (start_xfade_curve) {
|
||||||
|
@ -1148,8 +1149,8 @@ AudioRegionView::setup_waveform_visibility ()
|
||||||
void
|
void
|
||||||
AudioRegionView::temporarily_hide_envelope ()
|
AudioRegionView::temporarily_hide_envelope ()
|
||||||
{
|
{
|
||||||
if (gain_line) {
|
if (_fx_line) {
|
||||||
gain_line->hide ();
|
_fx_line->hide ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1160,20 +1161,118 @@ AudioRegionView::unhide_envelope ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioRegionView::update_envelope_visibility ()
|
AudioRegionView::set_region_gain_line ()
|
||||||
{
|
{
|
||||||
if (!gain_line) {
|
if (_ignore_line_change) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const string line_name = _region->name() + ":gain";
|
||||||
|
_fx_line.reset (new AudioRegionGainLine (line_name, *this, *group, audio_region()->envelope()));
|
||||||
|
_fx_line->set_height ((uint32_t) rint (height() - NAME_HIGHLIGHT_SIZE) - 2);
|
||||||
|
_fx_line->reset ();
|
||||||
|
_region_fx_connection.disconnect ();
|
||||||
|
bool changed = _rfx_id != PBD::ID (0) || _rdx_param != UINT32_MAX;
|
||||||
|
_rfx_id = PBD::ID (0);
|
||||||
|
_rdx_param = UINT32_MAX;
|
||||||
|
|
||||||
|
envelope_active_changed ();
|
||||||
|
if (changed) {
|
||||||
|
region_line_changed (); /* EMIT SIGNAL */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (_ignore_line_change) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::shared_ptr<RegionFxPlugin> rfx = _region->nth_plugin (plugin_id);
|
||||||
|
if (rfx) {
|
||||||
|
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) {
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
id = _rfx_id;
|
||||||
|
param_id = _rdx_param;
|
||||||
|
return _rdx_param != UINT32_MAX && _rfx_id != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioRegionView::update_envelope_visibility ()
|
||||||
|
{
|
||||||
|
assert (_fx_line);
|
||||||
|
|
||||||
if (trackview.editor().current_mouse_mode() == Editing::MouseDraw || trackview.editor().current_mouse_mode() == Editing::MouseContent ) {
|
if (trackview.editor().current_mouse_mode() == Editing::MouseDraw || trackview.editor().current_mouse_mode() == Editing::MouseContent ) {
|
||||||
gain_line->set_visibility (AutomationLine::VisibleAspects(AutomationLine::ControlPoints|AutomationLine::Line));
|
_fx_line->set_visibility (AutomationLine::VisibleAspects(AutomationLine::ControlPoints|AutomationLine::Line));
|
||||||
gain_line->canvas_group().raise_to_top ();
|
_fx_line->canvas_group().raise_to_top ();
|
||||||
} else if (UIConfiguration::instance().get_show_region_gain() || trackview.editor().current_mouse_mode() == Editing::MouseRange ) {
|
} else if (UIConfiguration::instance().get_show_region_gain() || trackview.editor().current_mouse_mode() == Editing::MouseRange ) {
|
||||||
gain_line->set_visibility (AutomationLine::VisibleAspects(AutomationLine::Line));
|
_fx_line->set_visibility (AutomationLine::VisibleAspects(AutomationLine::Line));
|
||||||
gain_line->canvas_group().raise_to_top ();
|
_fx_line->canvas_group().raise_to_top ();
|
||||||
} else {
|
} else {
|
||||||
gain_line->set_visibility (AutomationLine::VisibleAspects(0));
|
_fx_line->set_visibility (AutomationLine::VisibleAspects(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1374,7 +1473,7 @@ AudioRegionView::peaks_ready_handler (uint32_t which)
|
||||||
void
|
void
|
||||||
AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, bool with_guard_points)
|
AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, bool with_guard_points)
|
||||||
{
|
{
|
||||||
if (!gain_line) {
|
if (!_fx_line) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1386,18 +1485,17 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, b
|
||||||
|
|
||||||
samplecnt_t const sample_within_region = (samplecnt_t) floor (mx * samples_per_pixel);
|
samplecnt_t const sample_within_region = (samplecnt_t) floor (mx * samples_per_pixel);
|
||||||
|
|
||||||
if (!gain_line->control_points_adjacent (sample_within_region, before_p, after_p)) {
|
double y = my;
|
||||||
/* no adjacent points */
|
|
||||||
return;
|
if (_fx_line->control_points_adjacent (sample_within_region, before_p, after_p)) {
|
||||||
|
/* y is in item frame */
|
||||||
|
double const bx = _fx_line->nth (before_p)->get_x();
|
||||||
|
double const ax = _fx_line->nth (after_p)->get_x();
|
||||||
|
double const click_ratio = (ax - mx) / (ax - bx);
|
||||||
|
|
||||||
|
y = ((_fx_line->nth (before_p)->get_y() * click_ratio) + (_fx_line->nth (after_p)->get_y() * (1 - click_ratio)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* y is in item frame */
|
|
||||||
double const bx = gain_line->nth (before_p)->get_x();
|
|
||||||
double const ax = gain_line->nth (after_p)->get_x();
|
|
||||||
double const click_ratio = (ax - mx) / (ax - bx);
|
|
||||||
|
|
||||||
double y = ((gain_line->nth (before_p)->get_y() * click_ratio) + (gain_line->nth (after_p)->get_y() * (1 - click_ratio)));
|
|
||||||
|
|
||||||
/* don't create points that can't be seen */
|
/* don't create points that can't be seen */
|
||||||
|
|
||||||
update_envelope_visibility ();
|
update_envelope_visibility ();
|
||||||
|
@ -1412,55 +1510,37 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, b
|
||||||
|
|
||||||
/* compute vertical fractional position */
|
/* compute vertical fractional position */
|
||||||
|
|
||||||
y = 1.0 - (y / (gain_line->height()));
|
y = 1.0 - (y / (_fx_line->height()));
|
||||||
|
|
||||||
/* map using gain line */
|
/* map using gain line */
|
||||||
|
|
||||||
gain_line->view_to_model_coord_y (y);
|
_fx_line->view_to_model_coord_y (y);
|
||||||
|
|
||||||
/* XXX STATEFUL: can't convert to stateful diff until we
|
/* XXX STATEFUL: can't convert to stateful diff until we
|
||||||
can represent automation data with it.
|
can represent automation data with it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
XMLNode &before = audio_region()->envelope()->get_state();
|
XMLNode &before = _fx_line->the_list()->get_state();
|
||||||
MementoCommand<AudioRegion>* region_memento = 0;
|
if (_fx_line->the_list()->editor_add (timepos_t (fx), y, with_guard_points)) {
|
||||||
|
XMLNode &after = _fx_line->the_list()->get_state();
|
||||||
if (!audio_region()->envelope_active()) {
|
|
||||||
XMLNode ®ion_before = audio_region()->get_state();
|
|
||||||
audio_region()->set_envelope_active(true);
|
|
||||||
XMLNode ®ion_after = audio_region()->get_state();
|
|
||||||
region_memento = new MementoCommand<AudioRegion>(*(audio_region().get()), ®ion_before, ®ion_after);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (audio_region()->envelope()->editor_add (timepos_t (fx), y, with_guard_points)) {
|
|
||||||
XMLNode &after = audio_region()->envelope()->get_state();
|
|
||||||
std::list<Selectable*> results;
|
std::list<Selectable*> results;
|
||||||
|
|
||||||
trackview.editor().begin_reversible_command (_("add gain control point"));
|
trackview.editor().begin_reversible_command (_("add gain control point"));
|
||||||
|
|
||||||
if (region_memento) {
|
_fx_line->enable_autoation ();
|
||||||
trackview.session()->add_command (region_memento);
|
|
||||||
}
|
|
||||||
|
|
||||||
trackview.session()->add_command (new MementoCommand<AutomationList>(*audio_region()->envelope().get(), &before, &after));
|
trackview.session()->add_command (new MementoCommand<AutomationList>(*_fx_line->the_list(), &before, &after));
|
||||||
|
|
||||||
gain_line->get_selectables (region ()->position () + timecnt_t (fx), region ()->position () + timecnt_t (fx), 0.0, 1.0, results);
|
_fx_line->get_selectables (region ()->position () + timecnt_t (fx), region ()->position () + timecnt_t (fx), 0.0, 1.0, results);
|
||||||
trackview.editor ().get_selection ().set (results);
|
trackview.editor ().get_selection ().set (results);
|
||||||
|
|
||||||
trackview.editor ().commit_reversible_command ();
|
trackview.editor ().commit_reversible_command ();
|
||||||
trackview.session ()->set_dirty ();
|
trackview.session ()->set_dirty ();
|
||||||
} else {
|
} else {
|
||||||
delete region_memento;
|
delete &before;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
AudioRegionView::remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent* /*ev*/)
|
|
||||||
{
|
|
||||||
ControlPoint *cp = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"));
|
|
||||||
audio_region()->envelope()->erase (cp->model());
|
|
||||||
}
|
|
||||||
|
|
||||||
GhostRegion*
|
GhostRegion*
|
||||||
AudioRegionView::add_ghost (TimeAxisView& tv)
|
AudioRegionView::add_ghost (TimeAxisView& tv)
|
||||||
{
|
{
|
||||||
|
@ -1557,10 +1637,6 @@ AudioRegionView::exited ()
|
||||||
trackview.editor().set_current_trimmable (std::shared_ptr<Trimmable>());
|
trackview.editor().set_current_trimmable (std::shared_ptr<Trimmable>());
|
||||||
trackview.editor().set_current_movable (std::shared_ptr<Movable>());
|
trackview.editor().set_current_movable (std::shared_ptr<Movable>());
|
||||||
|
|
||||||
// if (gain_line) {
|
|
||||||
// gain_line->remove_visibility (AutomationLine::ControlPoints);
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (fade_in_handle) { fade_in_handle->hide(); }
|
if (fade_in_handle) { fade_in_handle->hide(); }
|
||||||
if (fade_out_handle) { fade_out_handle->hide(); }
|
if (fade_out_handle) { fade_out_handle->hide(); }
|
||||||
if (fade_in_trim_handle) { fade_in_trim_handle->hide(); }
|
if (fade_in_trim_handle) { fade_in_trim_handle->hide(); }
|
||||||
|
@ -1572,12 +1648,8 @@ AudioRegionView::exited ()
|
||||||
void
|
void
|
||||||
AudioRegionView::envelope_active_changed ()
|
AudioRegionView::envelope_active_changed ()
|
||||||
{
|
{
|
||||||
if (gain_line) {
|
set_fx_line_colors ();
|
||||||
gain_line->set_line_color (audio_region()->envelope_active() ?
|
update_envelope_visibility ();
|
||||||
UIConfiguration::instance().color ("gain line") :
|
|
||||||
UIConfiguration::instance().color_mod ("gain line inactive", "gain line inactive"));
|
|
||||||
update_envelope_visibility ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1595,6 +1667,20 @@ AudioRegionView::color_handler ()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioRegionView::set_fx_line_colors ()
|
||||||
|
{
|
||||||
|
assert (_fx_line);
|
||||||
|
|
||||||
|
if (_rdx_param != UINT32_MAX && _rfx_id != 0) {
|
||||||
|
_fx_line->set_line_color (UIConfiguration::instance().color ("processor automation line"));
|
||||||
|
} else {
|
||||||
|
_fx_line->set_line_color (audio_region()->envelope_active()
|
||||||
|
? UIConfiguration::instance().color ("gain line")
|
||||||
|
: UIConfiguration::instance().color_mod ("gain line inactive", "gain line inactive"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioRegionView::set_waveform_colors ()
|
AudioRegionView::set_waveform_colors ()
|
||||||
{
|
{
|
||||||
|
@ -1696,7 +1782,7 @@ void
|
||||||
AudioRegionView::show_region_editor ()
|
AudioRegionView::show_region_editor ()
|
||||||
{
|
{
|
||||||
if (editor == 0) {
|
if (editor == 0) {
|
||||||
editor = new AudioRegionEditor (trackview.session(), audio_region());
|
editor = new AudioRegionEditor (trackview.session(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
editor->present ();
|
editor->present ();
|
||||||
|
@ -1858,7 +1944,7 @@ AudioRegionView::parameter_changed (string const & p)
|
||||||
MergeableLine*
|
MergeableLine*
|
||||||
AudioRegionView::make_merger ()
|
AudioRegionView::make_merger ()
|
||||||
{
|
{
|
||||||
return new MergeableLine (gain_line, std::shared_ptr<AutomationControl>(),
|
return new MergeableLine (_fx_line, std::shared_ptr<AutomationControl>(),
|
||||||
[this](timepos_t const& t) { return timepos_t (_region->position().distance (t)); },
|
[this](timepos_t const& t) { return timepos_t (_region->position().distance (t)); },
|
||||||
nullptr, nullptr);
|
nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,9 +50,9 @@ namespace ARDOUR {
|
||||||
};
|
};
|
||||||
|
|
||||||
class AudioTimeAxisView;
|
class AudioTimeAxisView;
|
||||||
class AudioRegionGainLine;
|
|
||||||
class GhostRegion;
|
class GhostRegion;
|
||||||
class AutomationTimeAxisView;
|
class AutomationTimeAxisView;
|
||||||
|
class RegionFxLine;
|
||||||
class RouteTimeAxisView;
|
class RouteTimeAxisView;
|
||||||
|
|
||||||
class AudioRegionView : public RegionView, public LineMerger
|
class AudioRegionView : public RegionView, public LineMerger
|
||||||
|
@ -91,12 +91,18 @@ public:
|
||||||
void temporarily_hide_envelope (); ///< Dangerous!
|
void temporarily_hide_envelope (); ///< Dangerous!
|
||||||
void unhide_envelope (); ///< Dangerous!
|
void unhide_envelope (); ///< Dangerous!
|
||||||
|
|
||||||
|
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 ();
|
void update_envelope_visibility ();
|
||||||
|
|
||||||
void add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event, bool with_guard_points);
|
sigc::signal<void> region_line_changed;
|
||||||
void remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event);
|
|
||||||
|
|
||||||
std::shared_ptr<AudioRegionGainLine> get_gain_line() const { return gain_line; }
|
void add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event, bool with_guard_points);
|
||||||
|
|
||||||
|
std::shared_ptr<RegionFxLine> fx_line() const { return _fx_line; }
|
||||||
|
|
||||||
void region_changed (const PBD::PropertyChange&);
|
void region_changed (const PBD::PropertyChange&);
|
||||||
void envelope_active_changed ();
|
void envelope_active_changed ();
|
||||||
|
@ -184,7 +190,7 @@ protected:
|
||||||
ArdourCanvas::Rectangle* end_xfade_rect;
|
ArdourCanvas::Rectangle* end_xfade_rect;
|
||||||
bool _end_xfade_visible;
|
bool _end_xfade_visible;
|
||||||
|
|
||||||
std::shared_ptr<AudioRegionGainLine> gain_line;
|
std::shared_ptr<RegionFxLine> _fx_line;
|
||||||
|
|
||||||
double _amplitude_above_axis;
|
double _amplitude_above_axis;
|
||||||
|
|
||||||
|
@ -206,6 +212,7 @@ protected:
|
||||||
|
|
||||||
void set_colors ();
|
void set_colors ();
|
||||||
void set_waveform_colors ();
|
void set_waveform_colors ();
|
||||||
|
void set_fx_line_colors ();
|
||||||
void reset_width_dependent_items (double pixel_width);
|
void reset_width_dependent_items (double pixel_width);
|
||||||
|
|
||||||
void color_handler ();
|
void color_handler ();
|
||||||
|
@ -234,6 +241,14 @@ private:
|
||||||
|
|
||||||
bool trim_fade_in_drag_active;
|
bool trim_fade_in_drag_active;
|
||||||
bool trim_fade_out_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;
|
||||||
|
|
||||||
|
PBD::ScopedConnection _region_fx_connection;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __gtk_ardour_audio_region_view_h__ */
|
#endif /* __gtk_ardour_audio_region_view_h__ */
|
||||||
|
|
|
@ -470,8 +470,8 @@ AudioStreamView::set_selected_points (PointSelection& points)
|
||||||
{
|
{
|
||||||
for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
|
for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
|
||||||
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
|
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
|
||||||
if (arv && arv->get_gain_line ()) {
|
if (arv && arv->fx_line ()) {
|
||||||
arv->get_gain_line ()->set_selected_points (points);
|
arv->fx_line ()->set_selected_points (points);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ using namespace Temporal;
|
||||||
AutomationLine::AutomationLine (const string& name,
|
AutomationLine::AutomationLine (const string& name,
|
||||||
TimeAxisView& tv,
|
TimeAxisView& tv,
|
||||||
ArdourCanvas::Item& parent,
|
ArdourCanvas::Item& parent,
|
||||||
std::shared_ptr<AutomationList> al,
|
std::shared_ptr<AutomationList> al,
|
||||||
const ParameterDescriptor& desc)
|
const ParameterDescriptor& desc)
|
||||||
: trackview (tv)
|
: trackview (tv)
|
||||||
, _name (name)
|
, _name (name)
|
||||||
|
|
|
@ -68,7 +68,7 @@ public:
|
||||||
AutomationLine (const std::string& name,
|
AutomationLine (const std::string& name,
|
||||||
TimeAxisView& tv,
|
TimeAxisView& tv,
|
||||||
ArdourCanvas::Item& parent,
|
ArdourCanvas::Item& parent,
|
||||||
std::shared_ptr<ARDOUR::AutomationList> al,
|
std::shared_ptr<ARDOUR::AutomationList> al,
|
||||||
const ARDOUR::ParameterDescriptor& desc);
|
const ARDOUR::ParameterDescriptor& desc);
|
||||||
|
|
||||||
|
|
||||||
|
@ -248,6 +248,7 @@ private:
|
||||||
const ARDOUR::ParameterDescriptor _desc;
|
const ARDOUR::ParameterDescriptor _desc;
|
||||||
|
|
||||||
friend class AudioRegionGainLine;
|
friend class AudioRegionGainLine;
|
||||||
|
friend class RegionFxLine;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __ardour_automation_line_h__ */
|
#endif /* __ardour_automation_line_h__ */
|
||||||
|
|
|
@ -707,11 +707,11 @@ bool
|
||||||
Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
|
Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
|
||||||
{
|
{
|
||||||
ItemType type;
|
ItemType type;
|
||||||
AudioRegionGainLine* gl;
|
RegionFxLine* rfl;
|
||||||
if ((gl = dynamic_cast<AudioRegionGainLine*> (al)) != 0) {
|
if ((rfl = dynamic_cast<RegionFxLine*> (al)) != 0) {
|
||||||
type = GainLineItem;
|
type = GainLineItem;
|
||||||
if (event->type == GDK_BUTTON_PRESS) {
|
if (event->type == GDK_BUTTON_PRESS) {
|
||||||
clicked_regionview = &gl->region_view ();
|
clicked_regionview = &rfl->region_view ();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
type = AutomationLineItem;
|
type = AutomationLineItem;
|
||||||
|
|
|
@ -5039,7 +5039,7 @@ LineDrag::finished (GdkEvent* event, bool movement_occurred)
|
||||||
AudioRegionView* arv;
|
AudioRegionView* arv;
|
||||||
|
|
||||||
if ((arv = dynamic_cast<AudioRegionView*> (_editor->clicked_regionview)) != 0) {
|
if ((arv = dynamic_cast<AudioRegionView*> (_editor->clicked_regionview)) != 0) {
|
||||||
arv->add_gain_point_event (&arv->get_gain_line ()->grab_item (), event, false);
|
arv->add_gain_point_event (&arv->fx_line ()->grab_item (), event, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6367,7 +6367,7 @@ AutomationRangeDrag::AutomationRangeDrag (Editor* editor, list<RegionView*> cons
|
||||||
|
|
||||||
for (list<RegionView*>::const_iterator i = v.begin (); i != v.end (); ++i) {
|
for (list<RegionView*>::const_iterator i = v.begin (); i != v.end (); ++i) {
|
||||||
if (AudioRegionView* audio_view = dynamic_cast<AudioRegionView*> (*i)) {
|
if (AudioRegionView* audio_view = dynamic_cast<AudioRegionView*> (*i)) {
|
||||||
lines.push_back (audio_view->get_gain_line ());
|
lines.push_back (audio_view->fx_line ());
|
||||||
} else if (AutomationRegionView* automation_view = dynamic_cast<AutomationRegionView*> (*i)) {
|
} else if (AutomationRegionView* automation_view = dynamic_cast<AutomationRegionView*> (*i)) {
|
||||||
lines.push_back (automation_view->line ());
|
lines.push_back (automation_view->line ());
|
||||||
_integral = true;
|
_integral = true;
|
||||||
|
@ -6394,8 +6394,8 @@ AutomationRangeDrag::setup (list<std::shared_ptr<AutomationLine>> const& lines)
|
||||||
|
|
||||||
/* need a special detection for automation lanes (not region gain line) */
|
/* need a special detection for automation lanes (not region gain line) */
|
||||||
// TODO: if we implement automation regions, this check can probably be removed
|
// TODO: if we implement automation regions, this check can probably be removed
|
||||||
AudioRegionGainLine* argl = dynamic_cast<AudioRegionGainLine*> ((*i).get ());
|
RegionFxLine* fxl = dynamic_cast<RegionFxLine*> ((*i).get ());
|
||||||
if (!argl) {
|
if (!fxl) {
|
||||||
/* in automation lanes, the EFFECTIVE range should be considered 0->max_position (even if there is no line) */
|
/* in automation lanes, the EFFECTIVE range should be considered 0->max_position (even if there is no line) */
|
||||||
r.first = Temporal::timepos_t ((*i)->the_list ()->time_domain ());
|
r.first = Temporal::timepos_t ((*i)->the_list ()->time_domain ());
|
||||||
r.second = Temporal::timepos_t::max ((*i)->the_list ()->time_domain ());
|
r.second = Temporal::timepos_t::max ((*i)->the_list ()->time_domain ());
|
||||||
|
|
|
@ -2340,7 +2340,7 @@ Editor::can_remove_control_point (ArdourCanvas::Item* item)
|
||||||
}
|
}
|
||||||
|
|
||||||
AutomationLine& line = control_point->line ();
|
AutomationLine& line = control_point->line ();
|
||||||
if (dynamic_cast<AudioRegionGainLine*> (&line)) {
|
if (dynamic_cast<RegionFxLine*> (&line)) {
|
||||||
/* we shouldn't remove the first or last gain point in region gain lines */
|
/* we shouldn't remove the first or last gain point in region gain lines */
|
||||||
if (line.is_last_point(*control_point) || line.is_first_point(*control_point)) {
|
if (line.is_last_point(*control_point) || line.is_first_point(*control_point)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -4833,7 +4833,7 @@ Editor::cut_copy_points (Editing::CutCopyOp op, timepos_t const & earliest_time)
|
||||||
|
|
||||||
bool erase = true;
|
bool erase = true;
|
||||||
|
|
||||||
if (dynamic_cast<AudioRegionGainLine*> (&line)) {
|
if (dynamic_cast<RegionFxLine*> (&line)) {
|
||||||
/* removing of first and last gain point in region gain lines is prohibited*/
|
/* removing of first and last gain point in region gain lines is prohibited*/
|
||||||
if (line.is_last_point (*(*sel_point)) || line.is_first_point (*(*sel_point))) {
|
if (line.is_last_point (*(*sel_point)) || line.is_first_point (*(*sel_point))) {
|
||||||
erase = false;
|
erase = false;
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
|
|
||||||
#include "ardour_http.h"
|
#include "ardour_http.h"
|
||||||
#include "ardour_ui.h"
|
#include "ardour_ui.h"
|
||||||
|
#include "audio_region_view.h"
|
||||||
#include "public_editor.h"
|
#include "public_editor.h"
|
||||||
#include "region_selection.h"
|
#include "region_selection.h"
|
||||||
#include "luadialog.h"
|
#include "luadialog.h"
|
||||||
|
@ -826,10 +827,16 @@ LuaInstance::register_classes (lua_State* L, bool sandbox)
|
||||||
.endClass ()
|
.endClass ()
|
||||||
|
|
||||||
.deriveClass <RegionView, TimeAxisViewItem> ("RegionView")
|
.deriveClass <RegionView, TimeAxisViewItem> ("RegionView")
|
||||||
|
.addCast<AudioRegionView> ("to_audioregionview")
|
||||||
.addFunction ("show_region_editor", &RegionView::show_region_editor)
|
.addFunction ("show_region_editor", &RegionView::show_region_editor)
|
||||||
.addFunction ("hide_region_editor", &RegionView::hide_region_editor)
|
.addFunction ("hide_region_editor", &RegionView::hide_region_editor)
|
||||||
.endClass ()
|
.endClass ()
|
||||||
|
|
||||||
|
.deriveClass <AudioRegionView, RegionView> ("RegionView")
|
||||||
|
.addFunction ("set_region_gain_line", &AudioRegionView::set_region_gain_line)
|
||||||
|
.addFunction ("set_region_fx_line", (bool (AudioRegionView::*)(uint32_t, uint32_t))&AudioRegionView::set_region_fx_line)
|
||||||
|
.endClass ()
|
||||||
|
|
||||||
.deriveClass <RouteUI, Selectable> ("RouteUI")
|
.deriveClass <RouteUI, Selectable> ("RouteUI")
|
||||||
.endClass ()
|
.endClass ()
|
||||||
|
|
||||||
|
|
|
@ -62,11 +62,11 @@ using namespace PBD;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Gtkmm2ext;
|
using namespace Gtkmm2ext;
|
||||||
|
|
||||||
RegionEditor::RegionEditor (Session* s, std::shared_ptr<Region> r)
|
RegionEditor::RegionEditor (Session* s, RegionView* rv)
|
||||||
: ArdourDialog (_("Region"))
|
: ArdourDialog (_("Region"))
|
||||||
, _table (9, 3)
|
, _table (9, 3)
|
||||||
, _table_row (0)
|
, _table_row (0)
|
||||||
, _region (r)
|
, _region (rv->region ())
|
||||||
, name_label (_("Name:"))
|
, name_label (_("Name:"))
|
||||||
, audition_button (_("Audition"))
|
, audition_button (_("Audition"))
|
||||||
, _clock_group (new ClockGroup)
|
, _clock_group (new ClockGroup)
|
||||||
|
@ -77,12 +77,12 @@ RegionEditor::RegionEditor (Session* s, std::shared_ptr<Region> r)
|
||||||
, sync_offset_absolute_clock (X_("regionsyncoffsetabsolute"), true, "", true, false)
|
, sync_offset_absolute_clock (X_("regionsyncoffsetabsolute"), true, "", true, false)
|
||||||
/* XXX cannot file start yet */
|
/* XXX cannot file start yet */
|
||||||
, start_clock (X_("regionstart"), true, "", false, false)
|
, start_clock (X_("regionstart"), true, "", false, false)
|
||||||
, _region_fx_box (r)
|
, _region_fx_box (_region)
|
||||||
, _sources (1)
|
, _sources (1)
|
||||||
{
|
{
|
||||||
set_session (s);
|
set_session (s);
|
||||||
|
|
||||||
switch (r->time_domain()) {
|
switch (_region->time_domain()) {
|
||||||
case Temporal::AudioTime:
|
case Temporal::AudioTime:
|
||||||
/* XXX check length of region and choose samples or minsec */
|
/* XXX check length of region and choose samples or minsec */
|
||||||
_clock_group->set_clock_mode (AudioClock::MinSec);
|
_clock_group->set_clock_mode (AudioClock::MinSec);
|
||||||
|
|
|
@ -55,12 +55,13 @@ namespace ARDOUR {
|
||||||
class RegionFxPlugin;
|
class RegionFxPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RegionView;
|
||||||
class ClockGroup;
|
class ClockGroup;
|
||||||
|
|
||||||
class RegionEditor : public ArdourDialog
|
class RegionEditor : public ArdourDialog
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RegionEditor (ARDOUR::Session*, std::shared_ptr<ARDOUR::Region>);
|
RegionEditor (ARDOUR::Session*, RegionView*);
|
||||||
virtual ~RegionEditor ();
|
virtual ~RegionEditor ();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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 "ardour/automation_control.h"
|
||||||
|
|
||||||
|
#include "audio_region_view.h"
|
||||||
|
#include "gui_thread.h"
|
||||||
|
#include "region_fx_line.h"
|
||||||
|
|
||||||
|
#include "pbd/i18n.h"
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
Temporal::timepos_t
|
||||||
|
RegionFxLine::get_origin() const
|
||||||
|
{
|
||||||
|
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 ();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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 __ardour_gtk_region_fx_line_h__
|
||||||
|
#define __ardour_gtk_region_fx_line_h__
|
||||||
|
|
||||||
|
#include "automation_line.h"
|
||||||
|
|
||||||
|
class RegionView;
|
||||||
|
|
||||||
|
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; }
|
||||||
|
|
||||||
|
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
|
|
@ -35,67 +35,52 @@
|
||||||
|
|
||||||
#include "time_axis_view.h"
|
#include "time_axis_view.h"
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
#include "gui_thread.h"
|
|
||||||
|
|
||||||
#include "pbd/i18n.h"
|
#include "pbd/i18n.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
using namespace PBD;
|
|
||||||
|
|
||||||
AudioRegionGainLine::AudioRegionGainLine (const string & name, AudioRegionView& r, ArdourCanvas::Container& parent, std::shared_ptr<AutomationList> l)
|
AudioRegionGainLine::AudioRegionGainLine (const string & name, AudioRegionView& r, ArdourCanvas::Container& parent, std::shared_ptr<AutomationList> l)
|
||||||
: AutomationLine (name, r.get_time_axis_view(), parent, l, l->parameter())
|
: RegionFxLine (name, r, parent, l, l->parameter ())
|
||||||
, rv (r)
|
, arv (r)
|
||||||
{
|
{
|
||||||
// If this isn't true something is horribly wrong, and we'll get catastrophic gain values
|
|
||||||
assert(l->parameter().type() == EnvelopeAutomation);
|
|
||||||
|
|
||||||
r.region()->PropertyChanged.connect (_region_changed_connection, invalidator (*this), boost::bind (&AudioRegionGainLine::region_changed, this, _1), gui_context());
|
|
||||||
|
|
||||||
group->raise_to_top ();
|
|
||||||
group->set_y_position (2);
|
|
||||||
terminal_points_can_slide = false;
|
terminal_points_can_slide = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
timepos_t
|
|
||||||
AudioRegionGainLine::get_origin() const
|
|
||||||
{
|
|
||||||
return rv.region()->position();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioRegionGainLine::start_drag_single (ControlPoint* cp, double x, float fraction)
|
AudioRegionGainLine::start_drag_single (ControlPoint* cp, double x, float fraction)
|
||||||
{
|
{
|
||||||
AutomationLine::start_drag_single (cp, x, fraction);
|
RegionFxLine::start_drag_single (cp, x, fraction);
|
||||||
|
|
||||||
// XXX Stateful need to capture automation curve data
|
// XXX Stateful need to capture automation curve data
|
||||||
|
|
||||||
if (!rv.audio_region()->envelope_active()) {
|
if (!arv.audio_region()->envelope_active()) {
|
||||||
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(rv.audio_region().get()), &rv.audio_region()->get_state(), 0));
|
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(arv.audio_region().get()), &arv.audio_region()->get_state(), 0));
|
||||||
rv.audio_region()->set_envelope_active(false);
|
arv.audio_region()->set_envelope_active(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioRegionGainLine::start_drag_line (uint32_t i1, uint32_t i2, float fraction)
|
AudioRegionGainLine::start_drag_line (uint32_t i1, uint32_t i2, float fraction)
|
||||||
{
|
{
|
||||||
AutomationLine::start_drag_line (i1, i2, fraction);
|
RegionFxLine::start_drag_line (i1, i2, fraction);
|
||||||
|
|
||||||
if (!rv.audio_region()->envelope_active()) {
|
if (!arv.audio_region()->envelope_active()) {
|
||||||
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(rv.audio_region().get()), &rv.audio_region()->get_state(), 0));
|
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(arv.audio_region().get()), &arv.audio_region()->get_state(), 0));
|
||||||
rv.audio_region()->set_envelope_active(false);
|
arv.audio_region()->set_envelope_active(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioRegionGainLine::start_drag_multiple (list<ControlPoint*> cp, float fraction, XMLNode* state)
|
AudioRegionGainLine::start_drag_multiple (list<ControlPoint*> cp, float fraction, XMLNode* state)
|
||||||
{
|
{
|
||||||
AutomationLine::start_drag_multiple (cp, fraction, state);
|
RegionFxLine::start_drag_multiple (cp, fraction, state);
|
||||||
|
|
||||||
if (!rv.audio_region()->envelope_active()) {
|
if (!arv.audio_region()->envelope_active()) {
|
||||||
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(rv.audio_region().get()), &rv.audio_region()->get_state(), 0));
|
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(arv.audio_region().get()), &arv.audio_region()->get_state(), 0));
|
||||||
rv.audio_region()->set_envelope_active(false);
|
arv.audio_region()->set_envelope_active(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,10 +91,10 @@ AudioRegionGainLine::remove_point (ControlPoint& cp)
|
||||||
trackview.editor().begin_reversible_command (_("remove control point"));
|
trackview.editor().begin_reversible_command (_("remove control point"));
|
||||||
XMLNode &before = alist->get_state();
|
XMLNode &before = alist->get_state();
|
||||||
|
|
||||||
if (!rv.audio_region()->envelope_active()) {
|
if (!arv.audio_region()->envelope_active()) {
|
||||||
rv.audio_region()->clear_changes ();
|
arv.audio_region()->clear_changes ();
|
||||||
rv.audio_region()->set_envelope_active(true);
|
arv.audio_region()->set_envelope_active(true);
|
||||||
trackview.session()->add_command(new StatefulDiffCommand (rv.audio_region()));
|
trackview.session()->add_command(new PBD::StatefulDiffCommand (arv.audio_region()));
|
||||||
}
|
}
|
||||||
|
|
||||||
trackview.editor ().get_selection ().clear_points ();
|
trackview.editor ().get_selection ().clear_points ();
|
||||||
|
@ -123,35 +108,27 @@ AudioRegionGainLine::remove_point (ControlPoint& cp)
|
||||||
void
|
void
|
||||||
AudioRegionGainLine::end_drag (bool with_push, uint32_t final_index)
|
AudioRegionGainLine::end_drag (bool with_push, uint32_t final_index)
|
||||||
{
|
{
|
||||||
if (!rv.audio_region()->envelope_active()) {
|
if (!arv.audio_region()->envelope_active()) {
|
||||||
rv.audio_region()->set_envelope_active(true);
|
arv.audio_region()->set_envelope_active(true);
|
||||||
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(rv.audio_region().get()), 0, &rv.audio_region()->get_state()));
|
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(arv.audio_region().get()), 0, &arv.audio_region()->get_state()));
|
||||||
}
|
}
|
||||||
|
|
||||||
AutomationLine::end_drag (with_push, final_index);
|
RegionFxLine::end_drag (with_push, final_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioRegionGainLine::end_draw_merge ()
|
AudioRegionGainLine::end_draw_merge ()
|
||||||
{
|
{
|
||||||
if (!rv.audio_region()->envelope_active()) {
|
enable_autoation ();
|
||||||
XMLNode& before = rv.audio_region()->get_state();
|
RegionFxLine::end_draw_merge ();
|
||||||
rv.audio_region()->set_envelope_active(true);
|
|
||||||
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(rv.audio_region().get()), &before, &rv.audio_region()->get_state()));
|
|
||||||
}
|
|
||||||
|
|
||||||
AutomationLine::end_draw_merge ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioRegionGainLine::region_changed (const PropertyChange& what_changed)
|
AudioRegionGainLine::enable_autoation ()
|
||||||
{
|
{
|
||||||
PropertyChange interesting_stuff;
|
if (!arv.audio_region()->envelope_active()) {
|
||||||
|
XMLNode& before = arv.audio_region()->get_state();
|
||||||
interesting_stuff.add (ARDOUR::Properties::start);
|
arv.audio_region()->set_envelope_active(true);
|
||||||
interesting_stuff.add (ARDOUR::Properties::length);
|
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(arv.audio_region().get()), &before, &arv.audio_region()->get_state()));
|
||||||
|
|
||||||
if (what_changed.contains (interesting_stuff)) {
|
|
||||||
reset ();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,7 @@
|
||||||
|
|
||||||
#include "ardour/ardour.h"
|
#include "ardour/ardour.h"
|
||||||
|
|
||||||
|
#include "region_fx_line.h"
|
||||||
#include "automation_line.h"
|
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
class Session;
|
class Session;
|
||||||
|
@ -37,26 +36,21 @@ namespace ARDOUR {
|
||||||
class TimeAxisView;
|
class TimeAxisView;
|
||||||
class AudioRegionView;
|
class AudioRegionView;
|
||||||
|
|
||||||
class AudioRegionGainLine : public AutomationLine
|
class AudioRegionGainLine : public RegionFxLine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AudioRegionGainLine (const std::string & name, AudioRegionView&, ArdourCanvas::Container& parent, std::shared_ptr<ARDOUR::AutomationList>);
|
AudioRegionGainLine (const std::string & name, AudioRegionView&, ArdourCanvas::Container& parent, std::shared_ptr<ARDOUR::AutomationList>);
|
||||||
|
|
||||||
Temporal::timepos_t get_origin() const;
|
|
||||||
|
|
||||||
void start_drag_single (ControlPoint*, double, float);
|
void start_drag_single (ControlPoint*, double, float);
|
||||||
void start_drag_line (uint32_t, uint32_t, float);
|
void start_drag_line (uint32_t, uint32_t, float);
|
||||||
void start_drag_multiple (std::list<ControlPoint*>, float, XMLNode*);
|
void start_drag_multiple (std::list<ControlPoint*>, float, XMLNode*);
|
||||||
void end_drag (bool with_push, uint32_t final_index);
|
void end_drag (bool with_push, uint32_t final_index);
|
||||||
void end_draw_merge ();
|
void end_draw_merge ();
|
||||||
|
void enable_autoation ();
|
||||||
void remove_point (ControlPoint&);
|
void remove_point (ControlPoint&);
|
||||||
AudioRegionView& region_view () { return rv; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PBD::ScopedConnection _region_changed_connection;
|
AudioRegionView& arv;
|
||||||
void region_changed (const PBD::PropertyChange& what_changed);
|
|
||||||
AudioRegionView& rv;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __ardour_gtk_region_gain_line_h__ */
|
#endif /* __ardour_gtk_region_gain_line_h__ */
|
||||||
|
|
|
@ -750,7 +750,7 @@ void
|
||||||
RegionView::show_region_editor ()
|
RegionView::show_region_editor ()
|
||||||
{
|
{
|
||||||
if (!editor) {
|
if (!editor) {
|
||||||
editor = new RegionEditor (trackview.session(), region());
|
editor = new RegionEditor (trackview.session(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
editor->present ();
|
editor->present ();
|
||||||
|
|
|
@ -1176,11 +1176,11 @@ Selection::get_state () const
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioRegionGainLine* argl = dynamic_cast<AudioRegionGainLine*> (&(*i)->line());
|
RegionFxLine* fxl = dynamic_cast<RegionFxLine*> (&(*i)->line());
|
||||||
if (argl) {
|
if (fxl) {
|
||||||
XMLNode* r = node->add_child (X_("ControlPoint"));
|
XMLNode* r = node->add_child (X_("ControlPoint"));
|
||||||
r->set_property (X_("type"), "region");
|
r->set_property (X_("type"), "region");
|
||||||
r->set_property (X_("region-id"), argl->region_view ().region ()->id ());
|
r->set_property (X_("region-id"), fxl->region_view ().region ()->id ());
|
||||||
r->set_property (X_("view-index"), (*i)->view_index());
|
r->set_property (X_("view-index"), (*i)->view_index());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1324,35 +1324,6 @@ Selection::set_state (XMLNode const & node, int)
|
||||||
if (!cps.empty()) {
|
if (!cps.empty()) {
|
||||||
add (cps);
|
add (cps);
|
||||||
}
|
}
|
||||||
} else if (prop_type->value () == "region") {
|
|
||||||
|
|
||||||
PBD::ID region_id;
|
|
||||||
uint32_t view_index;
|
|
||||||
if (!(*i)->get_property (X_("region-id"), region_id) ||
|
|
||||||
!(*i)->get_property (X_("view-index"), view_index)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
RegionSelection rs;
|
|
||||||
editor->get_regionviews_by_id (region_id, rs);
|
|
||||||
|
|
||||||
if (!rs.empty ()) {
|
|
||||||
vector <ControlPoint *> cps;
|
|
||||||
for (RegionSelection::iterator rsi = rs.begin(); rsi != rs.end(); ++rsi) {
|
|
||||||
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*rsi);
|
|
||||||
if (arv) {
|
|
||||||
std::shared_ptr<AudioRegionGainLine> gl = arv->get_gain_line ();
|
|
||||||
ControlPoint* cp = gl->nth(view_index);
|
|
||||||
if (cp) {
|
|
||||||
cps.push_back (cp);
|
|
||||||
cp->show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!cps.empty()) {
|
|
||||||
add (cps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if ((*i)->name() == X_("TimelineRange")) {
|
} else if ((*i)->name() == X_("TimelineRange")) {
|
||||||
|
|
|
@ -622,7 +622,7 @@ StreamView::get_selectables (timepos_t const & start, timepos_t const & end, dou
|
||||||
|| (!within && (*i)->region()->coverage (start, end) != Temporal::OverlapNone)) {
|
|| (!within && (*i)->region()->coverage (start, end) != Temporal::OverlapNone)) {
|
||||||
if (_trackview.editor().internal_editing()) {
|
if (_trackview.editor().internal_editing()) {
|
||||||
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
|
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
|
||||||
if (arv && arv->get_gain_line ()) {
|
if (arv && arv->fx_line ()) {
|
||||||
/* Note: AutomationLine::get_selectables() uses trackview.current_height (),
|
/* Note: AutomationLine::get_selectables() uses trackview.current_height (),
|
||||||
* disregarding Stacked layer display height
|
* disregarding Stacked layer display height
|
||||||
*/
|
*/
|
||||||
|
@ -630,7 +630,7 @@ StreamView::get_selectables (timepos_t const & start, timepos_t const & end, dou
|
||||||
double const y = (*i)->get_canvas_group ()->position().y;
|
double const y = (*i)->get_canvas_group ()->position().y;
|
||||||
double t = 1.0 - std::min (1.0, std::max (0., (top - _trackview.y_position () - y) / c));
|
double t = 1.0 - std::min (1.0, std::max (0., (top - _trackview.y_position () - y) / c));
|
||||||
double b = 1.0 - std::min (1.0, std::max (0., (bottom - _trackview.y_position () - y) / c));
|
double b = 1.0 - std::min (1.0, std::max (0., (bottom - _trackview.y_position () - y) / c));
|
||||||
arv->get_gain_line()->get_selectables (start, end, b, t, results);
|
arv->fx_line()->get_selectables (start, end, b, t, results);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
results.push_back (*i);
|
results.push_back (*i);
|
||||||
|
|
|
@ -241,6 +241,7 @@ gtk2_ardour_sources = [
|
||||||
'recorder_group_tabs.cc',
|
'recorder_group_tabs.cc',
|
||||||
'recorder_ui.cc',
|
'recorder_ui.cc',
|
||||||
'region_editor.cc',
|
'region_editor.cc',
|
||||||
|
'region_fx_line.cc',
|
||||||
'region_gain_line.cc',
|
'region_gain_line.cc',
|
||||||
'region_layering_order_editor.cc',
|
'region_layering_order_editor.cc',
|
||||||
'region_list_base.cc',
|
'region_list_base.cc',
|
||||||
|
|
Loading…
Reference in New Issue