1 #include "mackie_jog_wheel.h"
3 #include "mackie_control_protocol.h"
4 #include "surface_port.h"
10 using namespace Mackie;
12 JogWheel::JogWheel( MackieControlProtocol & mcp )
14 , _transport_speed( 4.0 )
15 , _transport_direction( 0 )
16 , _shuttle_speed( 0.0 )
20 JogWheel::State JogWheel::jog_wheel_state() const
22 if ( !_jog_wheel_states.empty() )
23 return _jog_wheel_states.top();
28 void JogWheel::zoom_event( SurfacePort & port, Control & control, const ControlState & state )
32 void JogWheel::scrub_event( SurfacePort & port, Control & control, const ControlState & state )
36 void JogWheel::speed_event( SurfacePort & port, Control & control, const ControlState & state )
40 void JogWheel::scroll_event( SurfacePort & port, Control & control, const ControlState & state )
44 void JogWheel::jog_event( SurfacePort & port, Control & control, const ControlState & state )
46 // TODO use current snap-to setting?
47 switch ( jog_wheel_state() )
50 _mcp.ScrollTimeline( state.delta * state.sign );
55 // TODO implement something similar to ScrollTimeline which
56 // ends up in Editor::control_scroll for smoother zooming.
58 for ( unsigned int i = 0; i < state.ticks; ++i ) _mcp.ZoomIn();
60 for ( unsigned int i = 0; i < state.ticks; ++i ) _mcp.ZoomOut();
64 // locally, _transport_speed is an positive value
65 _transport_speed += _mcp.surface().scaled_delta( state, _mcp.get_session().transport_speed() );
67 // make sure no weirdness gets to the session
68 if ( _transport_speed < 0 || isnan( _transport_speed ) )
70 _transport_speed = 0.0;
73 // translate _transport_speed speed to a signed transport velocity
74 _mcp.get_session().request_transport_speed( transport_speed() * transport_direction() );
79 add_scrub_interval( _scrub_timer.restart() );
80 // x clicks per second => speed == 1.0
81 float speed = _mcp.surface().scrub_scaling_factor() / average_scrub_interval() * state.ticks;
82 _mcp.get_session().request_transport_speed( speed * state.sign );
87 _shuttle_speed = _mcp.get_session().transport_speed();
88 _shuttle_speed += _mcp.surface().scaled_delta( state, _mcp.get_session().transport_speed() );
89 _mcp.get_session().request_transport_speed( _shuttle_speed );
93 cout << "JogWheel select not implemented" << endl;
98 void JogWheel::check_scrubbing()
100 // if the last elapsed is greater than the average + std deviation, then stop
101 if ( !_scrub_intervals.empty() && _scrub_timer.elapsed() > average_scrub_interval() + std_dev_scrub_interval() )
103 _mcp.get_session().request_transport_speed( 0.0 );
104 _scrub_intervals.clear();
108 void JogWheel::push( State state )
110 _jog_wheel_states.push( state );
115 if ( _jog_wheel_states.size() > 0 )
117 _jog_wheel_states.pop();
121 void JogWheel::zoom_state_toggle()
123 if ( jog_wheel_state() == zoom )
129 JogWheel::State JogWheel::scrub_state_cycle()
131 State top = jog_wheel_state();
134 // stop scrubbing and go to shuttle
137 _shuttle_speed = 0.0;
139 else if ( top == shuttle )
141 // default to scroll, or the last selected
150 return jog_wheel_state();
153 void JogWheel::add_scrub_interval( unsigned long elapsed )
155 if ( _scrub_intervals.size() > 5 )
157 _scrub_intervals.pop_front();
159 _scrub_intervals.push_back( elapsed );
162 float JogWheel::average_scrub_interval()
165 for ( std::deque<unsigned long>::iterator it = _scrub_intervals.begin(); it != _scrub_intervals.end(); ++it )
169 return sum / _scrub_intervals.size();
172 float JogWheel::std_dev_scrub_interval()
174 float average = average_scrub_interval();
176 // calculate standard deviation
178 for ( std::deque<unsigned long>::iterator it = _scrub_intervals.begin(); it != _scrub_intervals.end(); ++it )
180 sum += pow( *it - average, 2 );
182 return sqrt( sum / _scrub_intervals.size() -1 );