allow alt-drag on stereo panner to move just one side of the stereo field. this wiggles a bit, possibly because of rounding, and that probably needs to be addressed

git-svn-id: svn://localhost/ardour2/branches/3.0@12500 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis
2012-05-31 13:58:59 +00:00
parent 78c0811ed7
commit 0b958b7f15
5 changed files with 86 additions and 21 deletions

View File

@@ -476,35 +476,67 @@ StereoPanner::on_motion_notify_event (GdkEventMotion* ev)
if (dragging_left) {
delta = -delta;
}
if (dragging_left || dragging_right) {
/* maintain position as invariant as we change the width */
if (Keyboard::modifier_state_contains (ev->state, Keyboard::SecondaryModifier)) {
/* change width and position in a way that keeps the
* other side in the same place
*/
/* create a detent close to the center */
_panner->freeze ();
double pv = position_control->get_value();
if (!detented && fabs (current_width) < 0.02) {
detented = true;
/* snap to zero */
width_control->set_value (0);
}
if (detented) {
accumulated_delta += delta;
/* have we pulled far enough to escape ? */
if (fabs (accumulated_delta) >= 0.025) {
width_control->set_value (current_width + accumulated_delta);
detented = false;
accumulated_delta = false;
if (dragging_left) {
position_control->set_value (pv - delta);
} else {
position_control->set_value (pv + delta);
}
if (delta > 0.0) {
/* delta is positive, so we're about to
increase the width. But we need to increase it
by twice the required value so that the
other side remains in place when we set
the position as well.
*/
width_control->set_value (current_width + (delta * 2.0));
} else {
width_control->set_value (current_width + delta);
}
_panner->thaw ();
} else {
/* width needs to change by 2 * delta because both L & R move */
width_control->set_value (current_width + delta * 2);
/* maintain position as invariant as we change the width */
/* create a detent close to the center */
if (!detented && fabs (current_width) < 0.02) {
detented = true;
/* snap to zero */
width_control->set_value (0);
}
if (detented) {
accumulated_delta += delta;
/* have we pulled far enough to escape ? */
if (fabs (accumulated_delta) >= 0.025) {
width_control->set_value (current_width + accumulated_delta);
detented = false;
accumulated_delta = false;
}
} else {
/* width needs to change by 2 * delta because both L & R move */
width_control->set_value (current_width + (delta * 2.0));
}
}
} else if (dragging_position) {

View File

@@ -151,6 +151,9 @@ public:
return fabs (a.azi - b.azi) < 1.0;
}
virtual void freeze ();
virtual void thaw ();
protected:
boost::shared_ptr<Pannable> _pannable;
@@ -158,6 +161,8 @@ protected:
virtual void distribute_one_automated (AudioBuffer&, BufferSet& obufs,
framepos_t start, framepos_t end, pframes_t nframes,
pan_t** buffers, uint32_t which) = 0;
int32_t _frozen;
};
} // namespace

View File

@@ -118,3 +118,17 @@ Panner::set_state (XMLNode const &, int)
{
return 0;
}
void
Panner::freeze ()
{
_frozen++;
}
void
Panner::thaw ()
{
if (_frozen > 0.0) {
_frozen--;
}
}

View File

@@ -123,9 +123,22 @@ Panner2in2out::set_width (double p)
}
}
void
Panner2in2out::thaw ()
{
Panner::thaw ();
if (_frozen == 0) {
update ();
}
}
void
Panner2in2out::update ()
{
if (_frozen) {
return;
}
/* it would be very nice to split this out into a virtual function
that can be accessed from BaseStereoPanner and used in do_distribute_automated().

View File

@@ -67,6 +67,7 @@ class Panner2in2out : public Panner
void update ();
void reset ();
void thaw ();
protected:
float left[2];