summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Anderson <ardour@semiosix.com>2007-07-31 10:52:23 +0000
committerJohn Anderson <ardour@semiosix.com>2007-07-31 10:52:23 +0000
commit2def7ef1abd7a30e05aa25aebd02e7987946bf1a (patch)
treef011d8764bbcebf38a2091cd4004f4cf5ae626d5
parent0259d682595f966528904cd9b1f99c4380aa2751 (diff)
Add Control::in_use. Add a timeout-generated stop event to Pot.
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@2197 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--libs/surfaces/mackie/TODO4
-rw-r--r--libs/surfaces/mackie/controls.cc20
-rw-r--r--libs/surfaces/mackie/controls.h38
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.cc5
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol_poll.cc3
-rw-r--r--libs/surfaces/mackie/mackie_jog_wheel.cc16
-rw-r--r--libs/surfaces/mackie/mackie_jog_wheel.h2
-rw-r--r--libs/surfaces/mackie/mackie_port.cc48
-rw-r--r--libs/surfaces/mackie/mackie_port.h4
-rw-r--r--libs/surfaces/mackie/types.h2
10 files changed, 110 insertions, 32 deletions
diff --git a/libs/surfaces/mackie/TODO b/libs/surfaces/mackie/TODO
index 245929886c..7d6f945132 100644
--- a/libs/surfaces/mackie/TODO
+++ b/libs/surfaces/mackie/TODO
@@ -1,8 +1,7 @@
* if mackie wheel moves too fast, it's ignored.
-* active (pressed?) state for controls, including timeout
* update manual with jog wheel states
* alsa/sequencer ports unstable. possibly problems with use of ::poll
-* use glib::timeout for check_scrubbing
+* use glib::Timer instead of mine
* crash when mmc port set to mcu?
* remappable buttons
* how long can UI signal callbacks take to execute? What happens if they block?
@@ -19,6 +18,7 @@ Later
-----
* remove commented couts
* Perhaps MackieControlProtocol shouldn't implement MackieButtonHandler
+* Need a HostAdapter class to encapsulate ardour calls
* talk to route plugins
* check for excessiveness (ie too many events making other subsystems work too hard)
* Queueing of writes?
diff --git a/libs/surfaces/mackie/controls.cc b/libs/surfaces/mackie/controls.cc
index bac37797ab..5c2d1e6779 100644
--- a/libs/surfaces/mackie/controls.cc
+++ b/libs/surfaces/mackie/controls.cc
@@ -45,6 +45,15 @@ Strip::Strip( const std::string & name, int index )
{
}
+Control::Control( int id, int ordinal, std::string name, Group & group )
+: _id( id )
+, _ordinal( ordinal )
+, _name( name )
+, _group( group )
+, _in_use_timeout( 250 )
+{
+}
+
/**
generated with
@@ -108,6 +117,17 @@ Button & Strip::fader_touch()
return *_fader_touch;
}
+bool Control::in_use() const
+{
+ return _in_use;
+}
+
+Control & Control::in_use( bool rhs )
+{
+ _in_use = rhs;
+ return *this;
+}
+
ostream & Mackie::operator << ( ostream & os, const Mackie::Control & control )
{
os << typeid( control ).name();
diff --git a/libs/surfaces/mackie/controls.h b/libs/surfaces/mackie/controls.h
index a4e259465c..a6c45e7eef 100644
--- a/libs/surfaces/mackie/controls.h
+++ b/libs/surfaces/mackie/controls.h
@@ -18,6 +18,8 @@
#ifndef mackie_controls_h
#define mackie_controls_h
+#include <sigc++/sigc++.h>
+
#include <map>
#include <vector>
#include <string>
@@ -157,11 +159,7 @@ class Control
public:
enum type_t { type_led, type_led_ring, type_fader = 0xe0, type_button = 0x90, type_pot = 0xb0 };
- Control( int id, int ordinal, std::string name, Group & group )
- : _id( id ), _ordinal( ordinal ), _name( name ), _group( group )
- {
- }
-
+ Control( int id, int ordinal, std::string name, Group & group );
virtual ~Control() {}
virtual const Led & led() const
@@ -215,11 +213,29 @@ public:
/// Jog Wheel
virtual bool is_jog() const { return false; }
+ /**
+ Return true if the controlis in use, or false otherwise. For buttons
+ 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
+ sigc::connection in_use_connection;
+
private:
int _id;
int _ordinal;
std::string _name;
Group & _group;
+ bool _in_use;
+ unsigned int _in_use_timeout;
};
std::ostream & operator << ( std::ostream & os, const Control & control );
@@ -229,18 +245,10 @@ class Fader : public Control
public:
Fader( int id, int ordinal, std::string name, Group & group )
: Control( id, ordinal, name, group )
- , _touch( false )
{
}
- bool touch() const { return _touch; }
-
- void touch( bool yn ) { _touch = yn; }
-
virtual type_t type() const { return type_fader; }
-
-private:
- bool _touch;
};
class Led : public Control
@@ -272,12 +280,8 @@ public:
virtual type_t type() const { return type_button; };
- bool pressed() const { return _pressed; }
- Button & pressed( bool rhs ) { _pressed = rhs; return *this; }
-
private:
Led _led;
- bool _pressed;
};
class LedRing : public Led
diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc
index d0b977c57f..de532e28fa 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.cc
+++ b/libs/surfaces/mackie/mackie_control_protocol.cc
@@ -478,7 +478,7 @@ bool MackieControlProtocol::handle_strip_button( Control & control, ButtonState
if ( control.name() == "fader_touch" )
{
state = bs == press;
- control.strip().gain().touch( state );
+ control.strip().gain().in_use( state );
}
return state;
@@ -831,6 +831,7 @@ void MackieControlProtocol::handle_control_event( SurfacePort & port, Control &
switch ( control.type() )
{
case Control::type_fader:
+ // TODO this seems to be a duplicate of the above if
if ( control.group().is_strip() )
{
// find the route in the route table for the id
@@ -984,7 +985,7 @@ void MackieControlProtocol::notify_gain_changed( RouteSignal * route_signal )
try
{
Fader & fader = route_signal->strip().gain();
- if ( !fader.touch() )
+ if ( !fader.in_use() )
{
route_signal->port().write( builder.build_fader( fader, gain_to_slider_position( route_signal->route().effective_gain() ) ) );
}
diff --git a/libs/surfaces/mackie/mackie_control_protocol_poll.cc b/libs/surfaces/mackie/mackie_control_protocol_poll.cc
index a9e946cd7f..0efca85bd8 100644
--- a/libs/surfaces/mackie/mackie_control_protocol_poll.cc
+++ b/libs/surfaces/mackie/mackie_control_protocol_poll.cc
@@ -64,9 +64,6 @@ void * MackieControlProtocol::monitor_work()
}
// poll for automation data from the routes
poll_automation();
-
- // check if we need to stop scrubbing
- _jog_wheel.check_scrubbing();
}
catch ( exception & e )
{
diff --git a/libs/surfaces/mackie/mackie_jog_wheel.cc b/libs/surfaces/mackie/mackie_jog_wheel.cc
index 54ded2f84e..dbf18de931 100644
--- a/libs/surfaces/mackie/mackie_jog_wheel.cc
+++ b/libs/surfaces/mackie/mackie_jog_wheel.cc
@@ -76,10 +76,18 @@ void JogWheel::jog_event( SurfacePort & port, Control & control, const ControlSt
case scrub:
{
- add_scrub_interval( _scrub_timer.restart() );
- // x clicks per second => speed == 1.0
- float speed = _mcp.surface().scrub_scaling_factor() / average_scrub_interval() * state.ticks;
- _mcp.get_session().request_transport_speed( speed * state.sign );
+ if ( state.delta != 0.0 )
+ {
+ add_scrub_interval( _scrub_timer.restart() );
+ // x clicks per second => speed == 1.0
+ float speed = _mcp.surface().scrub_scaling_factor() / average_scrub_interval() * state.ticks;
+ _mcp.get_session().request_transport_speed( speed * state.sign );
+ }
+ else
+ {
+ // we have a stop event
+ check_scrubbing();
+ }
break;
}
diff --git a/libs/surfaces/mackie/mackie_jog_wheel.h b/libs/surfaces/mackie/mackie_jog_wheel.h
index c22b75bd1b..83a4364393 100644
--- a/libs/surfaces/mackie/mackie_jog_wheel.h
+++ b/libs/surfaces/mackie/mackie_jog_wheel.h
@@ -79,7 +79,7 @@ protected:
private:
MackieControlProtocol & _mcp;
- // transport speed for ffwd and rew, controller by jog
+ /// transport speed for ffwd and rew, controller by jog
float _transport_speed;
int _transport_direction;
diff --git a/libs/surfaces/mackie/mackie_port.cc b/libs/surfaces/mackie/mackie_port.cc
index d712270402..c78021ed91 100644
--- a/libs/surfaces/mackie/mackie_port.cc
+++ b/libs/surfaces/mackie/mackie_port.cc
@@ -23,6 +23,8 @@
#include "controls.h"
#include "surface.h"
+#include <glibmm/main.h>
+
#include <midi++/types.h>
#include <midi++/port.h>
#include <sigc++/sigc++.h>
@@ -378,6 +380,17 @@ Control & MackiePort::lookup_control( MIDI::byte * bytes, size_t count )
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
// it might be worth combining this with lookup_control
// because they have similar logic flows.
@@ -402,6 +415,7 @@ void MackiePort::handle_midi_any (MIDI::Parser & parser, MIDI::byte * raw_bytes,
}
Control & control = lookup_control( raw_bytes, count );
+ control.in_use( true );
// This handles incoming bytes. Outgoing bytes
// are sent by the signal handlers.
@@ -412,6 +426,9 @@ void MackiePort::handle_midi_any (MIDI::Parser & parser, MIDI::byte * raw_bytes,
{
// only the top-order 10 bits out of 14 are used
int midi_pos = ( ( raw_bytes[2] << 7 ) + raw_bytes[1] ) >> 4;
+
+ // in_use is set by the MackieControlProtocol::handle_strip_button
+
// relies on implicit ControlState constructor
control_event( *this, control, float(midi_pos) / float(0x3ff) );
}
@@ -419,9 +436,13 @@ void MackiePort::handle_midi_any (MIDI::Parser & parser, MIDI::byte * raw_bytes,
// button
case Control::type_button:
- // relies on implicit ControlState constructor
- control_event( *this, control, raw_bytes[2] == 0x7f ? press : release );
+ {
+ ControlState control_state( raw_bytes[2] == 0x7f ? press : release );
+ control.in_use( control_state.button_state == press );
+ control_event( *this, control, control_state );
+
break;
+ }
// pot (jog wheel, external control)
case Control::type_pot:
@@ -434,6 +455,29 @@ void MackiePort::handle_midi_any (MIDI::Parser & parser, MIDI::byte * raw_bytes,
state.ticks = ( raw_bytes[2] & 0x3f);
state.delta = float( state.ticks ) / float( 0x3f );
+ /*
+ Pots only emit events when they move, not when they
+ 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
+
+ // first disconnect any previous timeouts
+ control.in_use_connection.disconnect();
+
+ // now connect a new timeout to call handle_control_timeout_event
+ sigc::slot<bool> timeout_slot = sigc::bind(
+ 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
control_event( *this, control, state );
break;
}
diff --git a/libs/surfaces/mackie/mackie_port.h b/libs/surfaces/mackie/mackie_port.h
index 2621e6dd95..26ec1ca799 100644
--- a/libs/surfaces/mackie/mackie_port.h
+++ b/libs/surfaces/mackie/mackie_port.h
@@ -109,6 +109,10 @@ protected:
*/
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:
MackieControlProtocol & _mcp;
port_type_t _port_type;
diff --git a/libs/surfaces/mackie/types.h b/libs/surfaces/mackie/types.h
index 21b0d1989a..be5c7e8b79 100644
--- a/libs/surfaces/mackie/types.h
+++ b/libs/surfaces/mackie/types.h
@@ -64,7 +64,7 @@ enum ButtonState { neither = -1, release = 0, press = 1 };
*/
struct ControlState
{
- ControlState(): pos(0.0), delta(0.0), button_state(neither) {}
+ ControlState(): pos(0.0), sign(0), delta(0.0), ticks(0), led_state(off), button_state(neither) {}
ControlState( LedState ls ): pos(0.0), delta(0.0), led_state(ls), button_state(neither) {}