mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-16 11:46:25 +01:00
FP8: Implement "Control-Link"
This commit is contained in:
parent
98a1a96f32
commit
0310f89971
4 changed files with 213 additions and 36 deletions
|
|
@ -99,10 +99,10 @@ FaderPort8::setup_actions ()
|
||||||
BindAction (BtnBypassAll, "Mixer", "ab-plugins");
|
BindAction (BtnBypassAll, "Mixer", "ab-plugins");
|
||||||
|
|
||||||
BindAction (BtnMacro, "Mixer", "show-editor");
|
BindAction (BtnMacro, "Mixer", "show-editor");
|
||||||
BindAction (BtnLink, "Window", "show-mixer");
|
|
||||||
|
|
||||||
BindMethod (BtnOpen, button_open);
|
BindMethod (BtnOpen, button_open);
|
||||||
BindAction (BtnLock, "Editor", "lock");
|
|
||||||
|
BindMethod (BtnLink, button_link);
|
||||||
|
BindMethod (BtnLock, button_lock);
|
||||||
|
|
||||||
// user-specific
|
// user-specific
|
||||||
for (FP8Controls::UserButtonMap::const_iterator i = _ctrls.user_buttons ().begin ();
|
for (FP8Controls::UserButtonMap::const_iterator i = _ctrls.user_buttons ().begin ();
|
||||||
|
|
@ -178,6 +178,37 @@ FaderPort8::button_open ()
|
||||||
AccessAction ("Common", "addExistingAudioFiles");
|
AccessAction ("Common", "addExistingAudioFiles");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void
|
||||||
|
FaderPort8::button_lock ()
|
||||||
|
{
|
||||||
|
if (!_link_enabled) {
|
||||||
|
AccessAction ("Editor", "lock");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_link_locked) {
|
||||||
|
unlock_link ();
|
||||||
|
} else if (!_link_control.expired ()) {
|
||||||
|
lock_link ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FaderPort8::button_link ()
|
||||||
|
{
|
||||||
|
switch (_ctrls.fader_mode()) {
|
||||||
|
case ModeTrack:
|
||||||
|
case ModePan:
|
||||||
|
if (_link_enabled) {
|
||||||
|
stop_link ();
|
||||||
|
} else {
|
||||||
|
start_link ();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//AccessAction ("Window", "show-mixer");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FaderPort8::button_automation (ARDOUR::AutoState as)
|
FaderPort8::button_automation (ARDOUR::AutoState as)
|
||||||
|
|
@ -348,6 +379,66 @@ FaderPort8::button_action (const std::string& group, const std::string& item)
|
||||||
AccessAction (group, item);
|
AccessAction (group, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ****************************************************************************
|
||||||
|
* Control Interaction (encoder)
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
FaderPort8::handle_encoder_pan (int steps)
|
||||||
|
{
|
||||||
|
boost::shared_ptr<Stripable> s = first_selected_stripable();
|
||||||
|
if (s) {
|
||||||
|
boost::shared_ptr<AutomationControl> ac;
|
||||||
|
if (shift_mod () || _ctrls.fader_mode() == ModePan) {
|
||||||
|
ac = s->pan_width_control ();
|
||||||
|
} else {
|
||||||
|
ac = s->pan_azimuth_control ();
|
||||||
|
}
|
||||||
|
if (ac) {
|
||||||
|
if (ac->automation_state() == Touch && !ac->touching ()) {
|
||||||
|
ac->start_touch (ac->session().transport_frame());
|
||||||
|
}
|
||||||
|
if (steps == 0) {
|
||||||
|
ac->set_value (ac->normal(), PBD::Controllable::UseGroup);
|
||||||
|
} else {
|
||||||
|
double v = ac->internal_to_interface (ac->get_value());
|
||||||
|
v = std::max (0.0, std::min (1.0, v + steps * .01));
|
||||||
|
ac->set_value (ac->interface_to_internal(v), PBD::Controllable::UseGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FaderPort8::handle_encoder_link (int steps)
|
||||||
|
{
|
||||||
|
if (_link_control.expired ()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (_link_control.lock ());
|
||||||
|
if (!ac) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double v = ac->internal_to_interface (ac->get_value());
|
||||||
|
if (ac->automation_state() == Touch && !ac->touching ()) {
|
||||||
|
ac->start_touch (ac->session().transport_frame());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (steps == 0) {
|
||||||
|
ac->set_value (ac->normal(), PBD::Controllable::UseGroup);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ac->desc().toggled) {
|
||||||
|
v = v > 0 ? 0. : 1.;
|
||||||
|
} else {
|
||||||
|
v = std::max (0.0, std::min (1.0, v + steps * .01));
|
||||||
|
}
|
||||||
|
ac->set_value (ac->interface_to_internal(v), PBD::Controllable::UseGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ****************************************************************************
|
/* ****************************************************************************
|
||||||
* Mode specific and internal callbacks
|
* Mode specific and internal callbacks
|
||||||
*/
|
*/
|
||||||
|
|
@ -540,22 +631,10 @@ FaderPort8::button_parameter ()
|
||||||
switch (_ctrls.fader_mode()) {
|
switch (_ctrls.fader_mode()) {
|
||||||
case ModeTrack:
|
case ModeTrack:
|
||||||
case ModePan:
|
case ModePan:
|
||||||
{
|
if (_link_enabled || _link_locked) {
|
||||||
boost::shared_ptr<Stripable> s = first_selected_stripable();
|
handle_encoder_link (0);
|
||||||
if (s) {
|
} else {
|
||||||
boost::shared_ptr<AutomationControl> ac;
|
handle_encoder_pan (0);
|
||||||
if (shift_mod () || _ctrls.fader_mode() == ModePan) {
|
|
||||||
ac = s->pan_width_control ();
|
|
||||||
} else {
|
|
||||||
ac = s->pan_azimuth_control ();
|
|
||||||
}
|
|
||||||
if (ac) {
|
|
||||||
if (ac->automation_state() == Touch && !ac->touching ()) {
|
|
||||||
ac->start_touch (ac->session().transport_frame());
|
|
||||||
}
|
|
||||||
ac->set_value (ac->normal(), PBD::Controllable::UseGroup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ModePlugins:
|
case ModePlugins:
|
||||||
|
|
@ -573,23 +652,11 @@ FaderPort8::encoder_parameter (bool neg, int steps)
|
||||||
switch (_ctrls.fader_mode()) {
|
switch (_ctrls.fader_mode()) {
|
||||||
case ModeTrack:
|
case ModeTrack:
|
||||||
case ModePan:
|
case ModePan:
|
||||||
{
|
if (steps != 0) {
|
||||||
boost::shared_ptr<Stripable> s = first_selected_stripable();
|
if (_link_enabled || _link_locked) {
|
||||||
if (s) {
|
handle_encoder_link (neg ? -steps : steps);
|
||||||
boost::shared_ptr<AutomationControl> ac;
|
} else {
|
||||||
if (shift_mod () || _ctrls.fader_mode() == ModePan) {
|
handle_encoder_pan (neg ? -steps : steps);
|
||||||
ac = s->pan_width_control ();
|
|
||||||
} else {
|
|
||||||
ac = s->pan_azimuth_control ();
|
|
||||||
}
|
|
||||||
if (ac) {
|
|
||||||
double v = ac->internal_to_interface (ac->get_value());
|
|
||||||
v = std::max (0.0, std::min (1.0, v + steps * (neg ? -.01 : .01)));
|
|
||||||
if (ac->automation_state() == Touch && !ac->touching ()) {
|
|
||||||
ac->start_touch (ac->session().transport_frame());
|
|
||||||
}
|
|
||||||
ac->set_value (ac->interface_to_internal(v), PBD::Controllable::UseGroup);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -218,3 +218,19 @@ FaderPort8::notify_plugin_active_changed ()
|
||||||
_ctrls.button (FP8Controls::BtnBypass).set_color (0x888888ff);
|
_ctrls.button (FP8Controls::BtnBypass).set_color (0x888888ff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FaderPort8::nofity_focus_control (boost::weak_ptr<PBD::Controllable> c)
|
||||||
|
{
|
||||||
|
assert (_link_enabled && !_link_locked);
|
||||||
|
// TODO consider subscribing to c's DropReferences
|
||||||
|
// (in case the control goes away while it has focus, update the BtnColor)
|
||||||
|
_link_control = c;
|
||||||
|
if (c.expired ()) {
|
||||||
|
_ctrls.button (FP8Controls::BtnLink).set_color (0xff8800ff);
|
||||||
|
_ctrls.button (FP8Controls::BtnLock).set_color (0xff0000ff);
|
||||||
|
} else {
|
||||||
|
_ctrls.button (FP8Controls::BtnLink).set_color (0x88ff00ff);
|
||||||
|
_ctrls.button (FP8Controls::BtnLock).set_color (0x00ff88ff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,8 @@ FaderPort8::FaderPort8 (Session& s)
|
||||||
, _shift_lock (false)
|
, _shift_lock (false)
|
||||||
, _shift_pressed (0)
|
, _shift_pressed (0)
|
||||||
, gui (0)
|
, gui (0)
|
||||||
|
, _link_enabled (false)
|
||||||
|
, _link_locked (false)
|
||||||
, _clock_mode (1)
|
, _clock_mode (1)
|
||||||
, _scribble_mode (2)
|
, _scribble_mode (2)
|
||||||
, _two_line_text (false)
|
, _two_line_text (false)
|
||||||
|
|
@ -982,6 +984,78 @@ FaderPort8::assign_stripables (bool select_only)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ****************************************************************************
|
||||||
|
* Control Link/Lock
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
FaderPort8::unlock_link (bool drop)
|
||||||
|
{
|
||||||
|
link_locked_connection.disconnect ();
|
||||||
|
|
||||||
|
if (drop) {
|
||||||
|
stop_link (); // calls back here with drop = false
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_link_locked = false;
|
||||||
|
|
||||||
|
if (_link_enabled) {
|
||||||
|
assert (_ctrls.button (FP8Controls::BtnLink).is_active ());
|
||||||
|
_link_control.reset ();
|
||||||
|
start_link (); // re-connect & update LED colors
|
||||||
|
} else {
|
||||||
|
_ctrls.button (FP8Controls::BtnLink).set_active (false);
|
||||||
|
_ctrls.button (FP8Controls::BtnLink).set_color (0x888888ff);
|
||||||
|
_ctrls.button (FP8Controls::BtnLock).set_active (false);
|
||||||
|
_ctrls.button (FP8Controls::BtnLock).set_color (0x888888ff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FaderPort8::lock_link ()
|
||||||
|
{
|
||||||
|
boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (_link_control.lock ());
|
||||||
|
if (!ac) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ac->DropReferences.connect (link_locked_connection, MISSING_INVALIDATOR, boost::bind (&FaderPort8::unlock_link, this, true), this);
|
||||||
|
|
||||||
|
// stop watching for focus events
|
||||||
|
link_connection.disconnect ();
|
||||||
|
|
||||||
|
_link_locked = true;
|
||||||
|
|
||||||
|
_ctrls.button (FP8Controls::BtnLock).set_color (0x00ff00ff);
|
||||||
|
_ctrls.button (FP8Controls::BtnLink).set_color (0x00ff00ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FaderPort8::stop_link ()
|
||||||
|
{
|
||||||
|
if (!_link_enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
link_connection.disconnect ();
|
||||||
|
_link_control.reset ();
|
||||||
|
_link_enabled = false;
|
||||||
|
unlock_link (); // also updates button colors
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FaderPort8::start_link ()
|
||||||
|
{
|
||||||
|
assert (!_link_locked);
|
||||||
|
|
||||||
|
_link_enabled = true;
|
||||||
|
_ctrls.button (FP8Controls::BtnLink).set_active (true);
|
||||||
|
_ctrls.button (FP8Controls::BtnLock).set_active (true);
|
||||||
|
nofity_focus_control (_link_control); // update BtnLink, BtnLock colors
|
||||||
|
|
||||||
|
PBD::Controllable::GUIFocusChanged.connect (link_connection, MISSING_INVALIDATOR, boost::bind (&FaderPort8::nofity_focus_control, this, _1), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ****************************************************************************
|
/* ****************************************************************************
|
||||||
* Plugin selection and parameters
|
* Plugin selection and parameters
|
||||||
*/
|
*/
|
||||||
|
|
@ -1617,6 +1691,7 @@ FaderPort8::notify_fader_mode_changed ()
|
||||||
case ModeSend:
|
case ModeSend:
|
||||||
_plugin_off = 0;
|
_plugin_off = 0;
|
||||||
_parameter_off = 0;
|
_parameter_off = 0;
|
||||||
|
stop_link ();
|
||||||
// force unset rec-arm button, see also FaderPort8::button_arm
|
// force unset rec-arm button, see also FaderPort8::button_arm
|
||||||
_ctrls.button (FP8Controls::BtnArm).set_active (false);
|
_ctrls.button (FP8Controls::BtnArm).set_active (false);
|
||||||
ARMButtonChange (false);
|
ARMButtonChange (false);
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
#define ABSTRACT_UI_EXPORTS
|
#define ABSTRACT_UI_EXPORTS
|
||||||
#include "pbd/abstract_ui.h"
|
#include "pbd/abstract_ui.h"
|
||||||
#include "pbd/properties.h"
|
#include "pbd/properties.h"
|
||||||
|
#include "pbd/controllable.h"
|
||||||
|
|
||||||
#include "ardour/types.h"
|
#include "ardour/types.h"
|
||||||
#include "ardour/async_midi_port.h"
|
#include "ardour/async_midi_port.h"
|
||||||
|
|
@ -271,6 +272,8 @@ private:
|
||||||
void button_metronom ();
|
void button_metronom ();
|
||||||
void button_bypass ();
|
void button_bypass ();
|
||||||
void button_open ();
|
void button_open ();
|
||||||
|
void button_link ();
|
||||||
|
void button_lock ();
|
||||||
void button_varispeed (bool);
|
void button_varispeed (bool);
|
||||||
#ifdef FP8_MUTESOLO_UNDO
|
#ifdef FP8_MUTESOLO_UNDO
|
||||||
void button_solo_clear ();
|
void button_solo_clear ();
|
||||||
|
|
@ -293,6 +296,22 @@ private:
|
||||||
std::vector <boost::weak_ptr<ARDOUR::AutomationControl> > _solo_state;
|
std::vector <boost::weak_ptr<ARDOUR::AutomationControl> > _solo_state;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Encoder handlers */
|
||||||
|
void handle_encoder_pan (int steps);
|
||||||
|
void handle_encoder_link (int steps);
|
||||||
|
|
||||||
|
/* Control Link */
|
||||||
|
void stop_link ();
|
||||||
|
void start_link ();
|
||||||
|
void lock_link ();
|
||||||
|
void unlock_link (bool drop = false);
|
||||||
|
void nofity_focus_control (boost::weak_ptr<PBD::Controllable>);
|
||||||
|
PBD::ScopedConnection link_connection;
|
||||||
|
PBD::ScopedConnection link_locked_connection;
|
||||||
|
boost::weak_ptr<PBD::Controllable> _link_control;
|
||||||
|
bool _link_enabled;
|
||||||
|
bool _link_locked; // can only be true if _link_enabled
|
||||||
|
|
||||||
/* user prefs */
|
/* user prefs */
|
||||||
uint32_t _clock_mode;
|
uint32_t _clock_mode;
|
||||||
uint32_t _scribble_mode;
|
uint32_t _scribble_mode;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue