13
0

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:
Carl Hetherington 2011-05-04 09:22:32 +00:00
parent f01dc1bfd5
commit 91d512174e
8 changed files with 87 additions and 59 deletions

View File

@ -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 )

View File

@ -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 );

View File

@ -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

View File

@ -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);

View File

@ -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));
} }

View File

@ -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;

View File

@ -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;
}

View File

@ -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;