Use a timeout to reset faders' in_use flags when in BCF mode (ie with faders that don't support touch).
git-svn-id: svn://localhost/ardour2/branches/3.0@9469 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
f01dc1bfd5
commit
91d512174e
|
@ -111,7 +111,6 @@ Control::Control( int id, int ordinal, std::string name, Group & group )
|
||||||
, _name( name )
|
, _name( name )
|
||||||
, _group( group )
|
, _group( group )
|
||||||
, _in_use( false )
|
, _in_use( false )
|
||||||
, _in_use_timeout( 250 )
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,15 +177,22 @@ Button & Strip::fader_touch()
|
||||||
return *_fader_touch;
|
return *_fader_touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Control::in_use() const
|
/** @return true if the control is in use, or false otherwise.
|
||||||
|
Buttons are `in use' when they are held down.
|
||||||
|
Faders with touch support are `in use' when they are being touched.
|
||||||
|
Pots, or faders without touch support, are `in use' from the first move
|
||||||
|
event until a timeout after the last move event.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
Control::in_use () const
|
||||||
{
|
{
|
||||||
return _in_use;
|
return _in_use;
|
||||||
}
|
}
|
||||||
|
|
||||||
Control & Control::in_use( bool rhs )
|
void
|
||||||
|
Control::set_in_use (bool in_use)
|
||||||
{
|
{
|
||||||
_in_use = rhs;
|
_in_use = in_use;
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ostream & Mackie::operator << ( ostream & os, const Mackie::Control & control )
|
ostream & Mackie::operator << ( ostream & os, const Mackie::Control & control )
|
||||||
|
|
|
@ -214,29 +214,23 @@ public:
|
||||||
/// Return true if this control is the one and only Jog Wheel
|
/// Return true if this control is the one and only Jog Wheel
|
||||||
virtual bool is_jog() const { return false; }
|
virtual bool is_jog() const { return false; }
|
||||||
|
|
||||||
/**
|
bool in_use () const;
|
||||||
Return true if the control is in use, or false otherwise. For buttons
|
void set_in_use (bool);
|
||||||
this returns true if the button is currently being held down. For
|
|
||||||
faders, the touch button has not been released. For pots, this returns
|
|
||||||
true from the first move event until a timeout after the last move event.
|
|
||||||
*/
|
|
||||||
virtual bool in_use() const;
|
|
||||||
virtual Control & in_use( bool );
|
|
||||||
|
|
||||||
/// The timeout value for this control. Normally defaulted to 250ms, but
|
|
||||||
/// certain controls (ie jog wheel) may want to override it.
|
|
||||||
virtual unsigned int in_use_timeout() { return _in_use_timeout; }
|
|
||||||
|
|
||||||
/// Keep track of the timeout so it can be updated with more incoming events
|
/// Keep track of the timeout so it can be updated with more incoming events
|
||||||
sigc::connection in_use_connection;
|
sigc::connection in_use_connection;
|
||||||
|
|
||||||
|
/** If we are doing an in_use timeout for a fader without touch, this
|
||||||
|
* is its touch button control; otherwise 0.
|
||||||
|
*/
|
||||||
|
Control* in_use_touch_control;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _id;
|
int _id;
|
||||||
int _ordinal;
|
int _ordinal;
|
||||||
std::string _name;
|
std::string _name;
|
||||||
Group & _group;
|
Group & _group;
|
||||||
bool _in_use;
|
bool _in_use;
|
||||||
unsigned int _in_use_timeout;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream & operator << ( std::ostream & os, const Control & control );
|
std::ostream & operator << ( std::ostream & os, const Control & control );
|
||||||
|
|
|
@ -397,7 +397,7 @@ MackieControlProtocol::set_active (bool yn)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MackieControlProtocol::handle_strip_button (Control & control, ButtonState bs, boost::shared_ptr<Route> route)
|
MackieControlProtocol::handle_strip_button (SurfacePort & port, Control & control, ButtonState bs, boost::shared_ptr<Route> route)
|
||||||
{
|
{
|
||||||
bool state = false;
|
bool state = false;
|
||||||
|
|
||||||
|
@ -433,7 +433,14 @@ MackieControlProtocol::handle_strip_button (Control & control, ButtonState bs, b
|
||||||
if (control.name() == "fader_touch")
|
if (control.name() == "fader_touch")
|
||||||
{
|
{
|
||||||
state = bs == press;
|
state = bs == press;
|
||||||
control.strip().gain().in_use (state);
|
control.strip().gain().set_in_use (state);
|
||||||
|
|
||||||
|
if (ARDOUR::Config->get_mackie_emulation() == "bcf" && state) {
|
||||||
|
/* BCF faders don't support touch, so add a timeout to reset
|
||||||
|
their `in_use' state.
|
||||||
|
*/
|
||||||
|
port.add_in_use_timeout (control.strip().gain(), &control.strip().fader_touch());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
|
@ -803,6 +810,11 @@ MackieControlProtocol::handle_control_event (SurfacePort & port, Control & contr
|
||||||
{
|
{
|
||||||
route->gain_control()->set_value (state.pos);
|
route->gain_control()->set_value (state.pos);
|
||||||
|
|
||||||
|
if (ARDOUR::Config->get_mackie_emulation() == "bcf") {
|
||||||
|
/* reset the timeout while we're still moving the fader */
|
||||||
|
port.add_in_use_timeout (control, control.in_use_touch_control);
|
||||||
|
}
|
||||||
|
|
||||||
// must echo bytes back to slider now, because
|
// must echo bytes back to slider now, because
|
||||||
// the notifier only works if the fader is not being
|
// the notifier only works if the fader is not being
|
||||||
// touched. Which it is if we're getting input.
|
// touched. Which it is if we're getting input.
|
||||||
|
@ -814,7 +826,7 @@ MackieControlProtocol::handle_control_event (SurfacePort & port, Control & contr
|
||||||
if (control.group().is_strip()) {
|
if (control.group().is_strip()) {
|
||||||
// strips
|
// strips
|
||||||
if (route != 0) {
|
if (route != 0) {
|
||||||
handle_strip_button (control, state.button_state, route);
|
handle_strip_button (port, control, state.button_state, route);
|
||||||
} else {
|
} else {
|
||||||
// no route so always switch the light off
|
// no route so always switch the light off
|
||||||
// because no signals will be emitted by a non-route
|
// because no signals will be emitted by a non-route
|
||||||
|
@ -823,7 +835,7 @@ MackieControlProtocol::handle_control_event (SurfacePort & port, Control & contr
|
||||||
} else if (control.group().is_master()) {
|
} else if (control.group().is_master()) {
|
||||||
// master fader touch
|
// master fader touch
|
||||||
if (route != 0) {
|
if (route != 0) {
|
||||||
handle_strip_button (control, state.button_state, route);
|
handle_strip_button (port, control, state.button_state, route);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// handle all non-strip buttons
|
// handle all non-strip buttons
|
||||||
|
|
|
@ -270,7 +270,7 @@ class MackieControlProtocol
|
||||||
Handle a button press for the control and return whether
|
Handle a button press for the control and return whether
|
||||||
the corresponding light should be on or off.
|
the corresponding light should be on or off.
|
||||||
*/
|
*/
|
||||||
bool handle_strip_button(Mackie::Control &, Mackie::ButtonState, boost::shared_ptr<ARDOUR::Route>);
|
bool handle_strip_button (Mackie::SurfacePort &, Mackie::Control &, Mackie::ButtonState, boost::shared_ptr<ARDOUR::Route>);
|
||||||
|
|
||||||
void add_port (MIDI::Port &, MIDI::Port &, int number);
|
void add_port (MIDI::Port &, MIDI::Port &, int number);
|
||||||
|
|
||||||
|
|
|
@ -374,17 +374,6 @@ Control & MackiePort::lookup_control( MIDI::byte * bytes, size_t count )
|
||||||
return *control;
|
return *control;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MackiePort::handle_control_timeout_event ( Control * control )
|
|
||||||
{
|
|
||||||
// empty control_state
|
|
||||||
ControlState control_state;
|
|
||||||
control->in_use( false );
|
|
||||||
control_event( *this, *control, control_state );
|
|
||||||
|
|
||||||
// only call this method once from the timer
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// converts midi messages into control_event signals
|
// converts midi messages into control_event signals
|
||||||
// it might be worth combining this with lookup_control
|
// it might be worth combining this with lookup_control
|
||||||
// because they have similar logic flows.
|
// because they have similar logic flows.
|
||||||
|
@ -407,7 +396,7 @@ void MackiePort::handle_midi_any (MIDI::Parser &, MIDI::byte * raw_bytes, size_t
|
||||||
}
|
}
|
||||||
|
|
||||||
Control & control = lookup_control( raw_bytes, count );
|
Control & control = lookup_control( raw_bytes, count );
|
||||||
control.in_use( true );
|
control.set_in_use (true);
|
||||||
|
|
||||||
// This handles incoming bytes. Outgoing bytes
|
// This handles incoming bytes. Outgoing bytes
|
||||||
// are sent by the signal handlers.
|
// are sent by the signal handlers.
|
||||||
|
@ -429,7 +418,7 @@ void MackiePort::handle_midi_any (MIDI::Parser &, MIDI::byte * raw_bytes, size_t
|
||||||
case Control::type_button:
|
case Control::type_button:
|
||||||
{
|
{
|
||||||
ControlState control_state( raw_bytes[2] == 0x7f ? press : release );
|
ControlState control_state( raw_bytes[2] == 0x7f ? press : release );
|
||||||
control.in_use( control_state.button_state == press );
|
control.set_in_use (control_state.button_state == press);
|
||||||
control_event( *this, control, control_state );
|
control_event( *this, control, control_state );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -452,26 +441,12 @@ void MackiePort::handle_midi_any (MIDI::Parser &, MIDI::byte * raw_bytes, size_t
|
||||||
}
|
}
|
||||||
state.delta = float( state.ticks ) / float( 0x3f );
|
state.delta = float( state.ticks ) / float( 0x3f );
|
||||||
|
|
||||||
/*
|
/* Pots only emit events when they move, not when they
|
||||||
Pots only emit events when they move, not when they
|
|
||||||
stop moving. So to get a stop event, we need to use a timeout.
|
stop moving. So to get a stop event, we need to use a timeout.
|
||||||
*/
|
*/
|
||||||
// this is set to false ...
|
|
||||||
control.in_use( true );
|
|
||||||
|
|
||||||
// ... by this timeout
|
control.set_in_use (true);
|
||||||
|
add_in_use_timeout (control, &control);
|
||||||
// first disconnect any previous timeouts
|
|
||||||
control.in_use_connection.disconnect();
|
|
||||||
|
|
||||||
// now connect a new timeout to call handle_control_timeout_event
|
|
||||||
// XXX should this use the GUI event loop (default) or the
|
|
||||||
// MIDI UI event loop ?
|
|
||||||
|
|
||||||
sigc::slot<bool> timeout_slot = sigc::bind
|
|
||||||
(sigc::mem_fun( *this, &MackiePort::handle_control_timeout_event), &control);
|
|
||||||
|
|
||||||
control.in_use_connection = Glib::signal_timeout().connect (timeout_slot , control.in_use_timeout());
|
|
||||||
|
|
||||||
// emit the control event
|
// emit the control event
|
||||||
control_event( *this, control, state );
|
control_event( *this, control, state );
|
||||||
|
@ -489,3 +464,4 @@ void MackiePort::handle_midi_any (MIDI::Parser &, MIDI::byte * raw_bytes, size_t
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("finished MackiePort::handle_midi_any %1\n", bytes));
|
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("finished MackiePort::handle_midi_any %1\n", bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,10 +107,6 @@ protected:
|
||||||
*/
|
*/
|
||||||
void probe_emulation( const MidiByteArray & bytes );
|
void probe_emulation( const MidiByteArray & bytes );
|
||||||
|
|
||||||
/// Handle timeout events set for controls that don't emit
|
|
||||||
/// an off event
|
|
||||||
bool handle_control_timeout_event ( Control * );
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MackieControlProtocol & _mcp;
|
MackieControlProtocol & _mcp;
|
||||||
port_type_t _port_type;
|
port_type_t _port_type;
|
||||||
|
|
|
@ -178,3 +178,43 @@ ostream & Mackie::operator << ( ostream & os, const SurfacePort & port )
|
||||||
os << " }";
|
os << " }";
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Handle timeouts to reset in_use for controls that can't
|
||||||
|
* do this by themselves (e.g. pots, and faders without touch support).
|
||||||
|
* @param in_use_control the control whose in_use flag to reset.
|
||||||
|
* @param touch_control a touch control to emit an event for, or 0.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
SurfacePort::control_in_use_timeout (Control* in_use_control, Control* touch_control)
|
||||||
|
{
|
||||||
|
in_use_control->set_in_use (false);
|
||||||
|
|
||||||
|
if (touch_control) {
|
||||||
|
// empty control_state
|
||||||
|
ControlState control_state;
|
||||||
|
control_event (*this, *touch_control, control_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// only call this method once from the timer
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add a timeout so that a control's in_use flag will be reset some time in the future.
|
||||||
|
* @param in_use_control the control whose in_use flag to reset.
|
||||||
|
* @param touch_control a touch control to emit an event for, or 0.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
SurfacePort::add_in_use_timeout (Control& in_use_control, Control* touch_control)
|
||||||
|
{
|
||||||
|
in_use_control.in_use_connection.disconnect ();
|
||||||
|
|
||||||
|
/* XXX should this use the GUI event loop (default) or the MIDI UI event loop? */
|
||||||
|
|
||||||
|
/* timeout after 250ms */
|
||||||
|
in_use_control.in_use_connection = Glib::signal_timeout().connect (
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &SurfacePort::control_in_use_timeout), &in_use_control, touch_control),
|
||||||
|
250
|
||||||
|
);
|
||||||
|
|
||||||
|
in_use_control.in_use_touch_control = touch_control;
|
||||||
|
}
|
||||||
|
|
|
@ -87,11 +87,15 @@ public:
|
||||||
virtual bool active() const { return _active; }
|
virtual bool active() const { return _active; }
|
||||||
virtual void active( bool yn ) { _active = yn; }
|
virtual void active( bool yn ) { _active = yn; }
|
||||||
|
|
||||||
|
void add_in_use_timeout (Control &, Control *);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Only for use by DummyPort
|
/// Only for use by DummyPort
|
||||||
SurfacePort();
|
SurfacePort();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool control_in_use_timeout (Control *, Control *);
|
||||||
|
|
||||||
MIDI::Port * _input_port;
|
MIDI::Port * _input_port;
|
||||||
MIDI::Port * _output_port;
|
MIDI::Port * _output_port;
|
||||||
int _number;
|
int _number;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user