summaryrefslogtreecommitdiff
path: root/libs/surfaces/mackie/mackie_jog_wheel.cc
diff options
context:
space:
mode:
authorJohn Anderson <ardour@semiosix.com>2007-07-19 22:07:10 +0000
committerJohn Anderson <ardour@semiosix.com>2007-07-19 22:07:10 +0000
commit4c12c98e338dd88e7b05b7e47133f91c3e3bbc06 (patch)
treeb4c58bcba79696bcaf453cff5441d6caff417f85 /libs/surfaces/mackie/mackie_jog_wheel.cc
parent47add43cd028855cda2292bef9dcde607f948490 (diff)
Jog Wheel Fun:
- When ffwd/rew is pressed, wheel controls speed - Zoom button allows jog wheel to zoom - Scrub button cycles jog from scrub to shuttle to whatever it was before git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@2155 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/surfaces/mackie/mackie_jog_wheel.cc')
-rw-r--r--libs/surfaces/mackie/mackie_jog_wheel.cc218
1 files changed, 218 insertions, 0 deletions
diff --git a/libs/surfaces/mackie/mackie_jog_wheel.cc b/libs/surfaces/mackie/mackie_jog_wheel.cc
new file mode 100644
index 0000000000..481c45bffc
--- /dev/null
+++ b/libs/surfaces/mackie/mackie_jog_wheel.cc
@@ -0,0 +1,218 @@
+#include "mackie_jog_wheel.h"
+
+#include "mackie_control_protocol.h"
+#include "surface_port.h"
+#include "controls.h"
+
+#include <algorithm>
+
+using namespace Mackie;
+
+JogWheel::JogWheel( MackieControlProtocol & mcp )
+: _mcp( mcp )
+, _transport_speed( 4.0 )
+, _transport_direction( 0 )
+, _shuttle_speed( 0.0 )
+{
+}
+
+JogWheel::State JogWheel::jog_wheel_state() const
+{
+ if ( !_jog_wheel_states.empty() )
+ return _jog_wheel_states.top();
+ else
+ return scroll;
+}
+
+void JogWheel::zoom_event( SurfacePort & port, Control & control, const ControlState & state )
+{
+}
+
+void JogWheel::scrub_event( SurfacePort & port, Control & control, const ControlState & state )
+{
+}
+
+void JogWheel::speed_event( SurfacePort & port, Control & control, const ControlState & state )
+{
+}
+
+void JogWheel::scroll_event( SurfacePort & port, Control & control, const ControlState & state )
+{
+}
+
+float scaled_delta( const ControlState & state, float current_speed )
+{
+ return state.sign * ( pow( state.ticks + 1, 2 ) + current_speed ) / 100.0;
+}
+
+void JogWheel::jog_event( SurfacePort & port, Control & control, const ControlState & state )
+{
+// TODO use current snap-to setting?
+#if 0
+ long delta = state.ticks * sign * 1000;
+ nframes_t next = session->transport_frame() + delta;
+ if ( delta < 0 && session->transport_frame() < (nframes_t) abs( delta ) )
+ {
+ next = session->current_start_frame();
+ }
+ else if ( next > session->current_end_frame() )
+ {
+ next = session->current_end_frame();
+ }
+
+ // doesn't work very well
+ session->request_locate( next, session->transport_rolling() );
+#endif
+
+ switch ( jog_wheel_state() )
+ {
+ case scroll:
+ //ScrollTimeline causes crashes
+ if ( _mcp.mcu_port().emulation() == MackiePort::bcf2000 )
+ _mcp.ScrollTimeline( state.ticks * state.sign / 100.0 );
+ else
+ _mcp.ScrollTimeline( state.ticks * state.sign / 100.0 );
+ break;
+
+ case zoom:
+ // TODO do a for loop for each, to number of ticks
+ if ( state.sign > 0 )
+ for ( unsigned int i = 0; i < state.ticks; ++i ) _mcp.ZoomIn();
+ else
+ for ( unsigned int i = 0; i < state.ticks; ++i ) _mcp.ZoomOut();
+ break;
+
+ case speed:
+ {
+ // block because we initialize a variable
+ // locally, _transport_speed is an absolute value...
+ // fairly arbitrary scaling function
+ _transport_speed += scaled_delta( state, _mcp.get_session().transport_speed() );
+
+ // make sure not weirdness get so the session
+ if ( _transport_speed < 0 || isnan( _transport_speed ) )
+ {
+ _transport_speed = 0.0;
+ }
+
+ // translated current speed to a signed transport velocity
+ _mcp.get_session().request_transport_speed( transport_speed() * transport_direction() );
+ break;
+ }
+
+ case scrub:
+ {
+ add_scrub_interval( _scrub_timer.restart() );
+ // copied from tranzport driver
+ float speed = 0.0;
+
+ // This should really be part of the surface object
+ if ( _mcp.mcu_port().emulation() == MackiePort::bcf2000 )
+ // 5 clicks per second => speed == 1.0
+ speed = 50.0 / average_scrub_interval() * state.ticks;
+ else
+ // 10 clicks per second => speed == 1.0
+ speed = 100.0 / average_scrub_interval() * state.ticks;
+
+ _mcp.get_session().request_transport_speed( speed * state.sign );
+ break;
+ }
+
+ case shuttle:
+ _shuttle_speed = _mcp.get_session().transport_speed();
+ _shuttle_speed += scaled_delta( state, _mcp.get_session().transport_speed() );
+ _mcp.get_session().request_transport_speed( _shuttle_speed );
+ break;
+
+ case select:
+ cout << "JogWheel select not implemented" << endl;
+ break;
+ }
+}
+
+void JogWheel::check_scrubbing()
+{
+ // if the last elapsed is greater than the average + std deviation, then stop
+ if ( !_scrub_intervals.empty() && _scrub_timer.elapsed() > average_scrub_interval() + std_dev_scrub_interval() )
+ {
+ _mcp.get_session().request_transport_speed( 0.0 );
+ _scrub_intervals.clear();
+ }
+}
+
+void JogWheel::push( State state )
+{
+ _jog_wheel_states.push( state );
+}
+
+void JogWheel::pop()
+{
+ if ( _jog_wheel_states.size() > 0 )
+ {
+ _jog_wheel_states.pop();
+ }
+}
+
+void JogWheel::zoom_state_toggle()
+{
+ if ( jog_wheel_state() == zoom )
+ pop();
+ else
+ push( zoom );
+}
+
+JogWheel::State JogWheel::scrub_state_cycle()
+{
+ State top = jog_wheel_state();
+ if ( top == scrub )
+ {
+ // stop scrubbing and go to shuttle
+ pop();
+ push( shuttle );
+ _shuttle_speed = 0.0;
+ }
+ else if ( top == shuttle )
+ {
+ // default to scroll, or the last selected
+ pop();
+ }
+ else
+ {
+ // start with scrub
+ push( scrub );
+ }
+
+ return jog_wheel_state();
+}
+
+void JogWheel::add_scrub_interval( unsigned long elapsed )
+{
+ if ( _scrub_intervals.size() > 5 )
+ {
+ _scrub_intervals.pop_front();
+ }
+ _scrub_intervals.push_back( elapsed );
+}
+
+float JogWheel::average_scrub_interval()
+{
+ float sum = 0.0;
+ for ( std::deque<unsigned long>::iterator it = _scrub_intervals.begin(); it != _scrub_intervals.end(); ++it )
+ {
+ sum += *it;
+ }
+ return sum / _scrub_intervals.size();
+}
+
+float JogWheel::std_dev_scrub_interval()
+{
+ float average = average_scrub_interval();
+
+ // calculate standard deviation
+ float sum = 0.0;
+ for ( std::deque<unsigned long>::iterator it = _scrub_intervals.begin(); it != _scrub_intervals.end(); ++it )
+ {
+ sum += pow( *it - average, 2 );
+ }
+ return sqrt( sum / _scrub_intervals.size() -1 );
+}