mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-15 19:16:40 +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 (BtnMacro, "Mixer", "show-editor");
|
||||
BindAction (BtnLink, "Window", "show-mixer");
|
||||
|
||||
BindMethod (BtnOpen, button_open);
|
||||
BindAction (BtnLock, "Editor", "lock");
|
||||
|
||||
BindMethod (BtnLink, button_link);
|
||||
BindMethod (BtnLock, button_lock);
|
||||
|
||||
// user-specific
|
||||
for (FP8Controls::UserButtonMap::const_iterator i = _ctrls.user_buttons ().begin ();
|
||||
|
|
@ -178,6 +178,37 @@ FaderPort8::button_open ()
|
|||
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
|
||||
FaderPort8::button_automation (ARDOUR::AutoState as)
|
||||
|
|
@ -348,6 +379,66 @@ FaderPort8::button_action (const std::string& group, const std::string& 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
|
||||
*/
|
||||
|
|
@ -540,22 +631,10 @@ FaderPort8::button_parameter ()
|
|||
switch (_ctrls.fader_mode()) {
|
||||
case ModeTrack:
|
||||
case ModePan:
|
||||
{
|
||||
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());
|
||||
}
|
||||
ac->set_value (ac->normal(), PBD::Controllable::UseGroup);
|
||||
}
|
||||
}
|
||||
if (_link_enabled || _link_locked) {
|
||||
handle_encoder_link (0);
|
||||
} else {
|
||||
handle_encoder_pan (0);
|
||||
}
|
||||
break;
|
||||
case ModePlugins:
|
||||
|
|
@ -573,23 +652,11 @@ FaderPort8::encoder_parameter (bool neg, int steps)
|
|||
switch (_ctrls.fader_mode()) {
|
||||
case ModeTrack:
|
||||
case ModePan:
|
||||
{
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
if (steps != 0) {
|
||||
if (_link_enabled || _link_locked) {
|
||||
handle_encoder_link (neg ? -steps : steps);
|
||||
} else {
|
||||
handle_encoder_pan (neg ? -steps : steps);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -218,3 +218,19 @@ FaderPort8::notify_plugin_active_changed ()
|
|||
_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_pressed (0)
|
||||
, gui (0)
|
||||
, _link_enabled (false)
|
||||
, _link_locked (false)
|
||||
, _clock_mode (1)
|
||||
, _scribble_mode (2)
|
||||
, _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
|
||||
*/
|
||||
|
|
@ -1617,6 +1691,7 @@ FaderPort8::notify_fader_mode_changed ()
|
|||
case ModeSend:
|
||||
_plugin_off = 0;
|
||||
_parameter_off = 0;
|
||||
stop_link ();
|
||||
// force unset rec-arm button, see also FaderPort8::button_arm
|
||||
_ctrls.button (FP8Controls::BtnArm).set_active (false);
|
||||
ARMButtonChange (false);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#define ABSTRACT_UI_EXPORTS
|
||||
#include "pbd/abstract_ui.h"
|
||||
#include "pbd/properties.h"
|
||||
#include "pbd/controllable.h"
|
||||
|
||||
#include "ardour/types.h"
|
||||
#include "ardour/async_midi_port.h"
|
||||
|
|
@ -271,6 +272,8 @@ private:
|
|||
void button_metronom ();
|
||||
void button_bypass ();
|
||||
void button_open ();
|
||||
void button_link ();
|
||||
void button_lock ();
|
||||
void button_varispeed (bool);
|
||||
#ifdef FP8_MUTESOLO_UNDO
|
||||
void button_solo_clear ();
|
||||
|
|
@ -293,6 +296,22 @@ private:
|
|||
std::vector <boost::weak_ptr<ARDOUR::AutomationControl> > _solo_state;
|
||||
#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 */
|
||||
uint32_t _clock_mode;
|
||||
uint32_t _scribble_mode;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue